Added threads to load files in background.

Added a new file-selector (using PIDLs for Win32).
This commit is contained in:
David Capello 2008-02-04 02:37:26 +00:00
parent 2aea148245
commit 528eaab937
85 changed files with 4247 additions and 1954 deletions

View File

@ -1,3 +1,36 @@
2008-02-04 David A. Capello <dacap@users.sourceforge.net>
* src/dialogs/filesel.c: Done (navigation history added, and
file-type combo-box).
* src/core/file_system.c: Done the Allegro interface with
for_each_file.
2008-02-03 David A. Capello <dacap@users.sourceforge.net>
* src/jinete/jcombox.c (jcombobox_del_index): Fixed a memory leak.
(jcombobox_add_string): Added 'data' field for each item.
(jcombobox_get_data): Added.
* src/test/test_file_system.c: Added.
* src/core/file_system.c: All these days I was working in
this. The PIDL interface for Win32 is done.
2008-01-27 David A. Capello <dacap@users.sourceforge.net>
* src/commands/cmd_configure_screen.c (show_dialog): Added a
confirmation dialog after changing the gfx-mode.
2008-01-24 David A. Capello <dacap@users.sourceforge.net>
* src/modules/gui.c (rebuild_sprite_list): Removed.
* src/file/*.c: A lot of work to make it thread safe through the
new FileOp structure.
* src/raster/gfxobj.c: Added a mutex to be thread safe.
2008-01-23 David A. Capello <dacap@users.sourceforge.net> 2008-01-23 David A. Capello <dacap@users.sourceforge.net>
* src/widgets/editor/editor.c (show_drawing_cursor): Added the * src/widgets/editor/editor.c (show_drawing_cursor): Added the

View File

@ -1,10 +1,11 @@
High priority work High priority work
------------------ ------------------
- the user_data of hook_signal should be void*.
- search for TODO; - search for TODO;
- Problems: - rename jcombox.c to jcombobox.c
- test UNDO in 64bits plataforms (reported by Jon Rafkind); - fix a bug in the film editor when move the separator (panel) outside
the screen (to left or right)
- the user_data of hook_signal should be void*.
- ver por el nuevo load_font de Allegro. - ver por el nuevo load_font de Allegro.
- complete palette operations, and palette editor (it needs a slider - complete palette operations, and palette editor (it needs a slider
or something to move between palette changes); or something to move between palette changes);

30
data/jids/filesel.jid Normal file
View File

@ -0,0 +1,30 @@
<!-- ASE - Allegro Sprite Editor -->
<!-- Copyright (C) 2001-2005, 2007, 2008 by David A. Capello -->
<!-- Read "LEGAL.txt" for more information. -->
<window text="" name="file_selector">
<box vertical>
<box horizontal>
<box horizontal noborders>
<button text="" name="goback" bevel="2 0 2 0" />
<button text="" name="goforward" bevel="0 2 0 2" />
</box>
<button text="" name="goup" />
<combobox name="location" expansive />
</box>
<box vertical expansive name="box" />
<box horizontal>
<label text="Name:" />
<entry text="" maxsize=256 name="filename" expansive />
<combobox name="filetype" minwidth=70 />
</box>
<box horizontal>
<box horizontal expansive />
<box horizontal homogeneous>
<button text="&OK" name="ok" magnetic width="60" />
<button text="&Cancel" />
</box>
</box>
</box>
</window>

View File

@ -1,5 +1,5 @@
ASE Files (.ASE) Format description ASE Files (.ASE) Format description
Copyright (C) 2004-2005, 2007 by David A. Capello Copyright (C) 2004-2005, 2007, 2008 by David A. Capello
---------------------------------------------------------------------- ----------------------------------------------------------------------
1. References 1. References
@ -19,7 +19,6 @@ BYTE An 8-bit unsigned integer value
WORD A 16-bit unsigned integer value WORD A 16-bit unsigned integer value
DWORD A 32-bit unsigned integer value DWORD A 32-bit unsigned integer value
LONG A 32-bit signed integer value LONG A 32-bit signed integer value
DOUBLE A 64-bit floating point value
BYTE[n] "n" bytes. BYTE[n] "n" bytes.
RECT Four LONGs (in the order: x-pos, y-pos, width, heigth) RECT Four LONGs (in the order: x-pos, y-pos, width, heigth)
STRING length=WORD (how many characters to read next) STRING length=WORD (how many characters to read next)
@ -211,6 +210,7 @@ NOTE.1: The child level is used to show the relationship of this
| `- Layer2 2 | `- Layer2 2
`- Layer3 1 `- Layer3 1
NOTE.2: The layer index is a number to identify any layer in the NOTE.2: The layer index is a number to identify any layer in the
sprite, for example: sprite, for example:
@ -223,6 +223,7 @@ NOTE.2: The layer index is a number to identify any layer in the
| `- Layer2 4 | `- Layer2 4
`- Layer3 5 `- Layer3 5
NOTE.3: The raw pixel data is saved row by row from top to bottom, and NOTE.3: The raw pixel data is saved row by row from top to bottom, and
each scanline is from pixel by pixel from left to right. each scanline is from pixel by pixel from left to right.
In RGB images, each pixel have 4 bytes in the order R, G, B, A. In RGB images, each pixel have 4 bytes in the order R, G, B, A.

View File

@ -190,11 +190,15 @@ endif
TESTS = $(addsuffix $(EXE), \ TESTS = $(addsuffix $(EXE), \
$(basename \ $(basename \
$(wildcard src/test/convmatr/*.c) \ $(wildcard src/test/*.c) \
$(wildcard src/test/raster/*.c) \ $(wildcard src/test/raster/*.c) \
$(wildcard src/test/jinete/*.c))) $(wildcard src/test/jinete/*.c)))
src/test/convmatr/%$(EXE): src/test/convmatr/%.c $(COMMON_OBJS) AUTOTESTS = $(addsuffix $(EXE), \
$(basename \
$(wildcard src/test/*.c)))
src/test/%$(EXE): src/test/%.c $(COMMON_OBJS)
$(CC) $(CFLAGS) -o $@ $^ $(LFLAGS) $(LFLAGS_LAST) $(CC) $(CFLAGS) -o $@ $^ $(LFLAGS) $(LFLAGS_LAST)
src/test/raster/%$(EXE): src/test/raster/%.c $(COMMON_OBJS) src/test/raster/%$(EXE): src/test/raster/%.c $(COMMON_OBJS)
@ -204,3 +208,6 @@ src/test/jinete/%$(EXE): src/test/jinete/%.c $(COMMON_OBJS)
$(CC) $(CFLAGS) -o $@ $^ $(LFLAGS) $(LFLAGS_LAST) $(CC) $(CFLAGS) -o $@ $^ $(LFLAGS) $(LFLAGS_LAST)
test: $(TESTS) test: $(TESTS)
runtest:
@-$(foreach TEST, $(AUTOTESTS), ./$(TEST))

View File

@ -79,6 +79,7 @@ COMMON_SOURCES = \
src/core/config.c \ src/core/config.c \
src/core/core.c \ src/core/core.c \
src/core/dirs.c \ src/core/dirs.c \
src/core/file_system.c \
src/core/modules.c \ src/core/modules.c \
src/dialogs/canvasze.c \ src/dialogs/canvasze.c \
src/dialogs/colsel.c \ src/dialogs/colsel.c \
@ -148,6 +149,7 @@ COMMON_SOURCES = \
src/jinete/jsystem.c \ src/jinete/jsystem.c \
src/jinete/jtextbox.c \ src/jinete/jtextbox.c \
src/jinete/jtheme.c \ src/jinete/jtheme.c \
src/jinete/jthread.c \
src/jinete/jview.c \ src/jinete/jview.c \
src/jinete/jwidget.c \ src/jinete/jwidget.c \
src/jinete/jwindow.c \ src/jinete/jwindow.c \
@ -206,6 +208,7 @@ COMMON_SOURCES = \
src/widgets/editor/cursor.c \ src/widgets/editor/cursor.c \
src/widgets/editor/editor.c \ src/widgets/editor/editor.c \
src/widgets/editor/keys.c \ src/widgets/editor/keys.c \
src/widgets/fileview.c \
src/widgets/groupbut.c \ src/widgets/groupbut.c \
src/widgets/menuitem.c \ src/widgets/menuitem.c \
src/widgets/paledit.c \ src/widgets/paledit.c \
@ -215,6 +218,11 @@ COMMON_SOURCES = \
src/widgets/target.c \ src/widgets/target.c \
src/widgets/toolbar.c src/widgets/toolbar.c
ifdef WIN32
COMMON_SOURCES += src/core/file_system_win32.c
else
endif
ifdef USE_X86_INT_MULT ifdef USE_X86_INT_MULT
COMMON_SOURCES += src/raster/x86/int_mult.s COMMON_SOURCES += src/raster/x86/int_mult.s
endif endif

View File

@ -1,4 +1,4 @@
# Copyright (C) 2001-2005, 2007 by David A. Capello -*-Makefile-*- # Copyright (C) 2001-2005, 2007, 2008 by David A. Capello -*-Makefile-*-
ifndef CONFIGURED ifndef CONFIGURED
include makefile.cfg include makefile.cfg
@ -14,8 +14,9 @@ endif
###################################################################### ######################################################################
# Flags for MinGW # Flags for MinGW
# CFLAGS = -D_WIN32_WINNT=0x0500
CFLAGS = CFLAGS =
LFLAGS = -mwindows LFLAGS = -mwindows -lshlwapi
ifdef DEBUGMODE ifdef DEBUGMODE
LFLAGS_LAST = -lalld LFLAGS_LAST = -lalld
else else

View File

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
find data/scripts jinete src third_party \ find data/scripts src third_party \
\( -name '*.[ch]' -o \ \( -name '*.[ch]' -o \
-name '*.lua' \) -print | \ -name '*.lua' \) -print | \
sed -e "/_old/D" | \ sed -e "/_old/D" | \

View File

@ -93,23 +93,23 @@ static void show_dialog(void)
return; return;
} }
jcombobox_add_string(resolution, "320x200"); jcombobox_add_string(resolution, "320x200", NULL);
jcombobox_add_string(resolution, "320x240"); jcombobox_add_string(resolution, "320x240", NULL);
jcombobox_add_string(resolution, "640x400"); jcombobox_add_string(resolution, "640x400", NULL);
jcombobox_add_string(resolution, "640x480"); jcombobox_add_string(resolution, "640x480", NULL);
jcombobox_add_string(resolution, "800x600"); jcombobox_add_string(resolution, "800x600", NULL);
jcombobox_add_string(resolution, "1024x768"); jcombobox_add_string(resolution, "1024x768", NULL);
jcombobox_add_string(color_depth, _("8 bpp (256 colors)")); jcombobox_add_string(color_depth, _("8 bpp (256 colors)"), NULL);
jcombobox_add_string(color_depth, _("15 bpp (32K colors)")); jcombobox_add_string(color_depth, _("15 bpp (32K colors)"), NULL);
jcombobox_add_string(color_depth, _("16 bpp (64K colors)")); jcombobox_add_string(color_depth, _("16 bpp (64K colors)"), NULL);
jcombobox_add_string(color_depth, _("24 bpp (16M colors)")); jcombobox_add_string(color_depth, _("24 bpp (16M colors)"), NULL);
jcombobox_add_string(color_depth, _("32 bpp (16M colors)")); jcombobox_add_string(color_depth, _("32 bpp (16M colors)"), NULL);
jcombobox_add_string(pixel_scale, "x1 (normal)"); jcombobox_add_string(pixel_scale, _("x1 (normal)"), NULL);
jcombobox_add_string(pixel_scale, "x2 (double)"); jcombobox_add_string(pixel_scale, _("x2 (double)"), NULL);
jcombobox_add_string(pixel_scale, "x3 (big)"); jcombobox_add_string(pixel_scale, _("x3 (big)"), NULL);
jcombobox_add_string(pixel_scale, "x4 (huge)"); jcombobox_add_string(pixel_scale, _("x4 (huge)"), NULL);
usprintf(buf, "%dx%d", old_w, old_h); usprintf(buf, "%dx%d", old_w, old_h);
jcombobox_select_string(resolution, buf); jcombobox_select_string(resolution, buf);

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2007 David A. Capello * Copyright (C) 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -42,7 +42,7 @@ static void cmd_load_mask_execute(const char *argument)
{ {
/* get current sprite */ /* get current sprite */
Sprite *sprite = current_sprite; Sprite *sprite = current_sprite;
char *filename = GUI_FileSelect(_("Load .msk File"), "", "msk"); char *filename = ase_file_selector(_("Load .msk File"), "", "msk");
if (filename) { if (filename) {
Mask *mask = load_msk_file(filename); Mask *mask = load_msk_file(filename);
if (!mask) { if (!mask) {

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2007 David A. Capello * Copyright (C) 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,23 +20,98 @@
#ifndef USE_PRECOMPILED_HEADER #ifndef USE_PRECOMPILED_HEADER
#include <stdio.h>
#include "jinete/jinete.h"
#include "commands/commands.h" #include "commands/commands.h"
#include "console/console.h"
#include "core/app.h"
#include "dialogs/filesel.h" #include "dialogs/filesel.h"
#include "file/file.h" #include "file/file.h"
#include "raster/sprite.h" #include "raster/sprite.h"
#include "modules/editors.h"
#include "modules/gui.h"
#include "modules/recent.h" #include "modules/recent.h"
#include "modules/sprites.h" #include "modules/sprites.h"
#include "widgets/statebar.h"
#endif #endif
typedef struct OpenFileData
{
FileOp *fop;
Progress *progress;
} OpenFileData;
/**
* Thread to do the hard work: load the file from the disk.
*
* [loading thread]
*/
static void bg_open_file(void *fop_data)
{
FileOp *fop = (FileOp *)fop_data;
fop_operate(fop);
}
/**
* Called by the gui-monitor (a timer in the gui module that is called
* every 100 milliseconds).
*
* [main thread]
*/
static bool bg_monitor_fop(void *_data)
{
OpenFileData *data = (OpenFileData *)_data;
FileOp *fop = (FileOp *)data->fop;
if (data->progress)
progress_update(data->progress, fop_get_progress(fop));
/* is done? ...ok, now the sprite is in the main thread only... */
if (fop_is_done(fop)) {
Sprite *sprite = fop->sprite;
if (sprite) {
recent_file(fop->filename);
sprite_mount(sprite);
sprite_show(sprite);
}
else {
unrecent_file(fop->filename);
}
if (data->progress)
progress_free(data->progress);
if (fop->error) {
console_open();
console_printf(fop->error);
console_close();
}
fop_free(fop);
jfree(data);
return TRUE; /* done */
}
else
return FALSE; /* work isn't yet */
}
/**
* Command to open a file.
*
* [main thread]
*/
static void cmd_open_file_execute(const char *argument) static void cmd_open_file_execute(const char *argument)
{ {
char *filename; char *filename;
/* interactive */ /* interactive */
if (!argument) { if (!argument) {
filename = GUI_FileSelect(_("Open Sprite"), "", char exts[4096];
get_readable_extensions()); get_readable_extensions(exts, sizeof(exts));
filename = ase_file_selector(_("Open Sprite"), "", exts);
} }
/* load the file specified in the argument */ /* load the file specified in the argument */
else { else {
@ -44,18 +119,38 @@ static void cmd_open_file_execute(const char *argument)
} }
if (filename) { if (filename) {
Sprite *sprite = sprite_load(filename); FileOp *fop = fop_to_load_sprite(filename);
if (sprite) {
recent_file(filename);
sprite_mount(sprite);
sprite_show(sprite);
}
else {
unrecent_file(filename);
}
if (filename != argument) if (filename != argument)
jfree(filename); jfree(filename);
if (fop) {
if (fop->error) {
console_printf(fop->error);
fop_free(fop);
}
else {
JThread thread = jthread_new(bg_open_file, fop);
if (thread) {
OpenFileData *data = jnew(OpenFileData, 1);
data->fop = fop;
/* add the progress bar */
if (app_get_status_bar())
data->progress = progress_new(app_get_status_bar());
else
data->progress = NULL;
/* add a monitor to check the loading (FileOp) progress */
add_gui_monitor(bg_monitor_fop, data);
}
else {
console_printf(_("Error creating thread to load the sprite"));
}
}
}
/* else do nothing (the user canceled or something like that) */
} }
} }

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2007 David A. Capello * Copyright (C) 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -20,14 +20,18 @@
#ifndef USE_PRECOMPILED_HEADER #ifndef USE_PRECOMPILED_HEADER
#include <allegro.h>
#include "jinete/jbase.h" #include "jinete/jbase.h"
#include "commands/commands.h" #include "commands/commands.h"
#include "core/app.h"
#include "console/console.h" #include "console/console.h"
#include "file/file.h" #include "file/file.h"
#include "modules/recent.h" #include "modules/recent.h"
#include "modules/sprites.h" #include "modules/sprites.h"
#include "raster/sprite.h" #include "raster/sprite.h"
#include "widgets/statebar.h"
#endif #endif
@ -44,12 +48,15 @@ static void cmd_save_file_execute(const char *argument)
if (sprite_save(current_sprite) == 0) { if (sprite_save(current_sprite) == 0) {
recent_file(current_sprite->filename); recent_file(current_sprite->filename);
sprite_mark_as_saved(current_sprite); sprite_mark_as_saved(current_sprite);
if (app_get_status_bar())
status_bar_set_text(app_get_status_bar(),
1000, "File %s, saved.",
get_filename(current_sprite->filename));
} }
else { else {
/* TODO if the user cancel we shouldn't unrecent the file */
unrecent_file(current_sprite->filename); unrecent_file(current_sprite->filename);
console_printf("%s: %s",
_("Error saving sprite file"),
current_sprite->filename);
} }
} }
/* if the sprite isn't associated to a file, we must to show the /* if the sprite isn't associated to a file, we must to show the

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2007 David A. Capello * Copyright (C) 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -26,7 +26,7 @@
#include "commands/commands.h" #include "commands/commands.h"
#include "console/console.h" #include "console/console.h"
/* #include "core/app.h" */ #include "core/app.h"
#include "dialogs/filesel.h" #include "dialogs/filesel.h"
#include "file/file.h" #include "file/file.h"
#include "modules/recent.h" #include "modules/recent.h"
@ -44,14 +44,15 @@ static bool cmd_save_file_as_enabled(const char *argument)
static void cmd_save_file_as_execute(const char *argument) static void cmd_save_file_as_execute(const char *argument)
{ {
char filename[4096]; char filename[4096];
char exts[4096];
char *newfilename; char *newfilename;
int ret; int ret;
ustrcpy(filename, current_sprite->filename); ustrcpy(filename, current_sprite->filename);
get_writable_extensions(exts, sizeof(exts));
for (;;) { for (;;) {
newfilename = GUI_FileSelect(_("Save Sprite"), filename, newfilename = ase_file_selector(_("Save Sprite"), filename, exts);
get_writable_extensions());
if (!newfilename) if (!newfilename)
return; return;
ustrcpy(filename, newfilename); ustrcpy(filename, newfilename);
@ -80,17 +81,15 @@ static void cmd_save_file_as_execute(const char *argument)
} }
sprite_set_filename(current_sprite, filename); sprite_set_filename(current_sprite, filename);
rebuild_sprite_list(); app_realloc_sprite_list();
if (sprite_save(current_sprite) == 0) { if (sprite_save(current_sprite) == 0) {
recent_file(filename); recent_file(filename);
sprite_mark_as_saved(current_sprite); sprite_mark_as_saved(current_sprite);
} }
else { else {
/* TODO if the user cancel we shouldn't unrecent the file */
unrecent_file(filename); unrecent_file(filename);
console_printf("%s: %s",
_("Error saving sprite file"),
filename);
} }
} }

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2007 David A. Capello * Copyright (C) 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -50,7 +50,7 @@ static void cmd_save_mask_execute(const char *argument)
int ret; int ret;
for (;;) { for (;;) {
char *filename = GUI_FileSelect(_("Save .msk File"), filename, "msk"); char *filename = ase_file_selector(_("Save .msk File"), filename, "msk");
if (!filename) if (!filename)
return; return;

View File

@ -171,36 +171,3 @@ void user_printf(const char *format, ...)
/* else */ /* else */
allegro_message(buf); allegro_message(buf);
} }
void do_progress(int progress)
{
JWidget status_bar = app_get_status_bar();
if (status_bar) {
status_bar_do_progress(status_bar, progress);
jwidget_flush_redraw(status_bar);
jmanager_dispatch_messages(ji_get_default_manager());
gui_feedback();
}
}
void add_progress(int max)
{
JWidget status_bar = app_get_status_bar();
if (status_bar)
status_bar_add_progress(status_bar, max);
jmouse_hide();
}
void del_progress(void)
{
JWidget status_bar = app_get_status_bar();
if (status_bar)
status_bar_del_progress(status_bar);
jmouse_show();
}

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello * Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -25,8 +25,4 @@ void console_close(void);
void console_printf(const char *format, ...); void console_printf(const char *format, ...);
void user_printf(const char *format, ...); void user_printf(const char *format, ...);
void do_progress(int progress);
void add_progress(int max);
void del_progress(void);
#endif /* CONSOLE_H */ #endif /* CONSOLE_H */

View File

@ -37,6 +37,7 @@
#include "core/app.h" #include "core/app.h"
#include "core/cfg.h" #include "core/cfg.h"
#include "core/core.h" #include "core/core.h"
#include "core/file_system.h"
#include "core/modules.h" #include "core/modules.h"
#include "dialogs/options.h" #include "dialogs/options.h"
#include "dialogs/tips.h" #include "dialogs/tips.h"
@ -99,7 +100,7 @@ static Option *option_new(int type, const char *data);
static void option_free(Option *option); static void option_free(Option *option);
/* install and load all initial stuff */ /* install and load all initial stuff */
int app_init(int argc, char *argv[]) bool app_init(int argc, char *argv[])
{ {
exe_name = argv[0]; exe_name = argv[0];
@ -107,11 +108,15 @@ int app_init(int argc, char *argv[])
intl_init(); intl_init();
/* install the `core' of ASE application */ /* install the `core' of ASE application */
if (core_init() < 0) { if (!core_init()) {
user_printf(_("ASE core initialization error.\n")); user_printf(_("ASE core initialization error.\n"));
return -1; return FALSE;
} }
/* install the file-system access module */
if (!file_system_init())
return FALSE;
/* init configuration */ /* init configuration */
ase_config_init(); ase_config_init();
@ -120,16 +125,21 @@ int app_init(int argc, char *argv[])
/* search options in the arguments */ /* search options in the arguments */
if (check_args(argc, argv) < 0) if (check_args(argc, argv) < 0)
return -1; return FALSE;
/* GUI is the default mode */ /* GUI is the default mode */
if (!(ase_mode & MODE_BATCH)) if (!(ase_mode & MODE_BATCH))
ase_mode |= MODE_GUI; ase_mode |= MODE_GUI;
/* install 'raster' stuff */
if (!gfxobj_init()) {
return FALSE;
}
/* install the modules */ /* install the modules */
if (modules_init (ase_mode & MODE_GUI ? REQUIRE_INTERFACE: if (!modules_init(ase_mode & MODE_GUI ? REQUIRE_INTERFACE:
REQUIRE_SCRIPTING) < 0) REQUIRE_SCRIPTING))
return -1; return FALSE;
_ji_font_init(); _ji_font_init();
@ -145,7 +155,7 @@ int app_init(int argc, char *argv[])
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
console_printf(_("Error loading default palette from `%s'\n"), console_printf(_("Error loading default palette from `%s'\n"),
palette_filename); palette_filename);
return -1; return FALSE;
} }
destroy_bitmap(bmp); destroy_bitmap(bmp);
@ -157,7 +167,7 @@ int app_init(int argc, char *argv[])
set_current_palette(NULL, TRUE); set_current_palette(NULL, TRUE);
/* ok */ /* ok */
return 0; return TRUE;
} }
/* runs ASE main dialog */ /* runs ASE main dialog */
@ -335,7 +345,9 @@ void app_exit(void)
/* finalize modules, configuration and core */ /* finalize modules, configuration and core */
modules_exit(); modules_exit();
gfxobj_exit();
ase_config_exit(); ase_config_exit();
file_system_exit();
core_exit(); core_exit();
_ji_font_exit(); _ji_font_exit();
@ -364,15 +376,10 @@ void app_refresh_screen(void)
} }
} }
/* updates the sprites list menu. WARNING!: This routine can't be used
when a menu callback was called, because, it destroy some menus,
you should use rebuild_sprite_list() instead (src/gui/gui.c) */
void app_realloc_sprite_list(void) void app_realloc_sprite_list(void)
{ {
Sprite *sprite; Sprite *sprite;
JLink link; JLink link;
#if 1
PRINTF("Reallocating sprite list...\n");
/* insert all other sprites */ /* insert all other sprites */
JI_LIST_FOR_EACH(get_sprite_list(), link) { JI_LIST_FOR_EACH(get_sprite_list(), link) {
@ -381,115 +388,26 @@ void app_realloc_sprite_list(void)
get_filename(sprite->filename), get_filename(sprite->filename),
sprite); sprite);
} }
#else
JWidget list_menuitem = get_sprite_list_menuitem();
JWidget menuitem;
PRINTF("Reallocating sprite list...\n");
/* update the sprite-list menu */
if (list_menuitem) {
Command *cmd_select_file = command_get_by_name(CMD_SELECT_FILE);
Sprite *clipboard = get_clipboard_sprite();
JWidget submenu;
char buf[256];
int c, count = 0;
submenu = jmenuitem_get_submenu(list_menuitem);
if (submenu) {
jmenuitem_set_submenu(list_menuitem, NULL);
jwidget_free(submenu);
}
submenu = jmenu_new();
jmenuitem_set_submenu(list_menuitem, submenu);
/* for `null' */
menuitem = menuitem_new(_("Nothing"), cmd_select_file, NULL);
/* if (!current_sprite) */
/* jwidget_select(menuitem); */
jwidget_add_child(submenu, menuitem);
count++;
/* for `clipboard' */
if (clipboard)
usprintf(buf, "%d", clipboard->gfxobj.id);
menuitem = menuitem_new(_("Clipboard"), cmd_select_file,
clipboard ? buf: "0");
/* if (!clipboard) */
/* jwidget_disable(menuitem); */
/* else if (current_sprite == clipboard) */
/* jwidget_select(menuitem); */
jwidget_add_child(submenu, menuitem);
count++;
/* insert a separator */
c = 0;
JI_LIST_FOR_EACH(get_sprite_list(), link) {
if (link->data == clipboard)
continue;
c++;
}
if (c > 0) {
jwidget_add_child(submenu, ji_separator_new(NULL, JI_HORIZONTAL));
count++;
/* insert all other sprites */
JI_LIST_FOR_EACH(get_sprite_list(), link) {
sprite = link->data;
if (sprite == clipboard)
continue;
/* `count' limit -- TODO how I know the height of menu-items? */
/* if (count >= SCREEN_H/(text_height (font)+4)-2) { */
if (count >= 14) {
menuitem = menuitem_new(_("More"), NULL, NULL);
jwidget_add_child(submenu, menuitem);
submenu = jmenu_new();
jmenuitem_set_submenu(menuitem, submenu);
count = 0;
}
usprintf(buf, "%d", sprite->gfxobj.id);
menuitem = menuitem_new(get_filename(sprite->filename),
cmd_select_file, buf);
if (current_sprite == sprite)
jwidget_select(menuitem);
jwidget_add_child(submenu, menuitem);
count++;
}
}
}
#endif
} }
/* updates the recent list menu. WARNING!: This routine can't be used /* updates the recent list menu. WARNING!: This routine can't be used
when a menu callback was called, because, it destroy the menus, when a menu callback was called, because, it destroy the menus,
you should use rebuild_recent_list() instead (src/gui/gui.c). */ you should use rebuild_recent_list() instead (src/gui/gui.c). */
void app_realloc_recent_list(void) bool app_realloc_recent_list(void)
{ {
JWidget list_menuitem = get_recent_list_menuitem(); JWidget list_menuitem = get_recent_list_menuitem();
JWidget menuitem; JWidget menuitem;
PRINTF("Reallocating recent list...\n");
/* update the recent file list menu item */ /* update the recent file list menu item */
if (list_menuitem) { if (list_menuitem) {
Command *cmd_open_file = command_get_by_name(CMD_OPEN_FILE); Command *cmd_open_file;
JWidget submenu; JWidget submenu;
if (jmenuitem_has_submenu_opened(list_menuitem))
return FALSE;
cmd_open_file = command_get_by_name(CMD_OPEN_FILE);
submenu = jmenuitem_get_submenu(list_menuitem); submenu = jmenuitem_get_submenu(list_menuitem);
if (submenu) { if (submenu) {
jmenuitem_set_submenu(list_menuitem, NULL); jmenuitem_set_submenu(list_menuitem, NULL);
@ -518,6 +436,8 @@ void app_realloc_recent_list(void)
jwidget_add_child(submenu, menuitem); jwidget_add_child(submenu, menuitem);
} }
} }
return TRUE;
} }
int app_get_current_image_type(void) int app_get_current_image_type(void)

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello * Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -21,14 +21,14 @@
#include "jinete/jbase.h" #include "jinete/jbase.h"
int app_init(int argc, char *argv[]); bool app_init(int argc, char *argv[]);
void app_loop(void); void app_loop(void);
void app_exit(void); void app_exit(void);
void app_refresh_screen(void); void app_refresh_screen(void);
void app_realloc_sprite_list(void); void app_realloc_sprite_list(void);
void app_realloc_recent_list(void); bool app_realloc_recent_list(void);
int app_get_current_image_type(void); int app_get_current_image_type(void);

View File

@ -51,7 +51,7 @@ static char *log_filename = NULL;
static FILE *log_fileptr = NULL; static FILE *log_fileptr = NULL;
#endif #endif
int core_init(void) bool core_init(void)
{ {
#ifdef NEED_LOG #ifdef NEED_LOG
char buf[512]; char buf[512];
@ -71,7 +71,7 @@ int core_init(void)
dirs_free(dirs); dirs_free(dirs);
#endif #endif
return 0; return TRUE;
} }
void core_exit(void) void core_exit(void)
@ -121,5 +121,5 @@ void verbose_printf(const char *format, ...)
bool is_interactive(void) bool is_interactive(void)
{ {
return ase_mode & MODE_GUI; return ase_mode & MODE_GUI ? TRUE: FALSE;
} }

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello * Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -30,7 +30,7 @@ enum {
extern int ase_mode; extern int ase_mode;
int core_init(void); bool core_init(void);
void core_exit(void); void core_exit(void);
void verbose_printf(const char *format, ...); void verbose_printf(const char *format, ...);

946
src/core/file_system.c Normal file
View File

@ -0,0 +1,946 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007, 2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Some of the original code to handle PIDLs come from the
MiniExplorer example of the Vaca library:
http://vaca.sourceforge.net/
*/
#include "config.h"
#include <stdio.h>
#include <assert.h>
#include <allegro.h>
#if defined ALLEGRO_WINDOWS
# define USE_PIDLS
#endif
#if defined ALLEGRO_UNIX || defined ALLEGRO_DJGPP || defined ALLEGRO_MINGW32
# include <sys/stat.h>
#endif
#if defined ALLEGRO_UNIX || defined ALLEGRO_MINGW32
# include <sys/unistd.h>
#endif
#if defined USE_PIDLS
# define COBJMACROS
# include <winalleg.h>
# include <shlobj.h>
# include <shlwapi.h>
#endif
#include "jinete/jlist.h"
#include "jinete/jfilesel.h"
#include "core/file_system.h"
#include "util/hash.h"
#ifdef USE_PIDLS /* using Win32 Shell (PIDLs) */
#define IS_FOLDER(fi) \
(((fi)->attrib & SFGAO_FOLDER) == SFGAO_FOLDER)
#else /* using Allegro (for_each_file) */
#define IS_FOLDER(fi) \
(((fi)->attrib & FA_DIREC) == FA_DIREC)
#if (DEVICE_SEPARATOR != 0) && (DEVICE_SEPARATOR != '\0')
# define HAVE_DRIVES
#else
# define CASE_SENSITIVE
#endif
#ifndef FA_ALL
#define FA_ALL FA_RDONLY | FA_DIREC | FA_ARCH | FA_HIDDEN | FA_SYSTEM
#endif
#define FA_TO_SHOW FA_RDONLY | FA_DIREC | FA_ARCH | FA_SYSTEM
#endif
/* a position in the file-system */
struct FileItem
{
char *filename;
char *displayname;
FileItem *parent;
JList children;
int last_update;
#ifdef USE_PIDLS
LPITEMIDLIST pidl; /* relative to parent */
LPITEMIDLIST fullpidl; /* relative to the Desktop folder
(like a full path-name, because the
desktop is the root on Windows) */
SFGAOF attrib;
#else
char *keyname;
int attrib;
#endif
};
/* the root of the file-system */
static FileItem *rootitem = NULL;
static HashTable *hash_fileitems = NULL;
#ifdef USE_PIDLS
static LPMALLOC shl_imalloc = NULL;
static IShellFolder *shl_idesktop = NULL;
#endif
/* local auxiliary routines */
static FileItem *fileitem_new(FileItem *parent);
static void fileitem_free(FileItem *fileitem);
static void fileitem_insert_child_sorted(FileItem *fileitem, FileItem *child);
static int fileitem_cmp(FileItem *fi1, FileItem *fi2);
/* a more easy PIDLs interface (without using the SH* & IL* routines of W2K) */
#ifdef USE_PIDLS
static void update_by_pidl(FileItem *fileitem);
static LPITEMIDLIST concat_pidl(LPITEMIDLIST pidlHead, LPITEMIDLIST pidlTail);
static UINT get_pidl_size(LPITEMIDLIST pidl);
static LPITEMIDLIST get_next_pidl(LPITEMIDLIST pidl);
static LPITEMIDLIST get_last_pidl(LPITEMIDLIST pidl);
static LPITEMIDLIST clone_pidl(LPITEMIDLIST pidl);
static LPITEMIDLIST remove_last_pidl(LPITEMIDLIST pidl);
static void free_pidl(LPITEMIDLIST pidl);
static char *get_key_for_pidl(LPITEMIDLIST pidl);
static FileItem *get_fileitem_by_fullpidl(LPITEMIDLIST pidl, bool create_if_not);
static void put_fileitem(FileItem *fileitem);
#else
static FileItem *get_fileitem_by_path(const char *path, bool create_if_not);
static void for_each_child_callback(const char *filename, int attrib, int param);
static char *remove_backslash(char *filename);
static char *get_key_for_filename(const char *filename);
static void put_fileitem(FileItem *fileitem);
#endif
/**
* Initializes the file-system module to navigate the file-system.
*/
bool file_system_init(void)
{
#ifdef USE_PIDLS
/* get the IMalloc interface */
SHGetMalloc(&shl_imalloc);
/* get desktop IShellFolder interface */
SHGetDesktopFolder(&shl_idesktop);
#endif
hash_fileitems = hash_new(512);
get_root_fileitem();
return TRUE;
}
/**
* Shutdowns the file-system module.
*/
void file_system_exit(void)
{
if (rootitem)
fileitem_free(rootitem);
if (hash_fileitems)
hash_free(hash_fileitems, NULL);
#ifdef USE_PIDLS
/* relase desktop IShellFolder interface */
IShellFolder_Release(shl_idesktop);
/* release IMalloc interface */
IMalloc_Release(shl_imalloc);
shl_imalloc = NULL;
#endif
}
FileItem *get_root_fileitem(void)
{
FileItem *fileitem;
if (rootitem)
return rootitem;
fileitem = fileitem_new(NULL);
if (!fileitem)
return NULL;
rootitem = fileitem;
#ifdef USE_PIDLS
{
/* get the desktop PIDL */
LPITEMIDLIST pidl = NULL;
if (SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidl) != S_OK) {
/* TODO do something better */
assert(FALSE);
exit(1);
}
fileitem->pidl = pidl;
fileitem->fullpidl = pidl;
fileitem->attrib = SFGAO_FOLDER;
IShellFolder_GetAttributesOf(shl_idesktop, 1,
(LPCITEMIDLIST *)&pidl,
&fileitem->attrib);
update_by_pidl(fileitem);
}
#else
{
char buf[MAX_PATH];
#if defined HAVE_DRIVES
ustrcpy(buf, "C:\\");
#else
ustrcpy(buf, "/");
#endif
fileitem->filename = jstrdup(buf);
fileitem->displayname = jstrdup(buf);
fileitem->attrib = FA_DIREC;
}
#endif
/* insert the file-item in the hash-table */
put_fileitem(fileitem);
return fileitem;
}
FileItem *get_fileitem_from_path(const char *path)
{
FileItem *fileitem = NULL;
#ifdef USE_PIDLS
{
ULONG cbEaten;
WCHAR wStr[MAX_PATH];
LPITEMIDLIST fullpidl = NULL;
SFGAOF attrib = SFGAO_FOLDER;
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, path, ustrlen(path)+1, wStr, MAX_PATH);
if (IShellFolder_ParseDisplayName(shl_idesktop,
NULL, NULL,
wStr, &cbEaten,
&fullpidl,
&attrib) != S_OK) {
return NULL;
}
fileitem = get_fileitem_by_fullpidl(fullpidl, TRUE);
free_pidl(fullpidl);
}
#else
{
char buf[MAX_PATH];
ustrcpy(buf, path);
remove_backslash(buf);
fileitem = get_fileitem_by_path(buf, TRUE);
}
#endif
return fileitem;
}
bool fileitem_is_folder(FileItem *fileitem)
{
assert(fileitem != NULL);
return IS_FOLDER(fileitem);
}
bool fileitem_is_browsable(FileItem *fileitem)
{
assert(fileitem != NULL);
assert(fileitem->filename != NULL);
#ifdef USE_PIDLS
return
IS_FOLDER(fileitem) &&
(fileitem->filename[0] != ':' ||
/* My Computer = {20D04FE0-3AEA-1069-A2D8-08002B30309D} */
ustrcmp(fileitem->filename, "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}") == 0);
#else
return IS_FOLDER(fileitem);
#endif
}
const char *fileitem_get_filename(FileItem *fileitem)
{
assert(fileitem != NULL);
assert(fileitem->filename != NULL);
return fileitem->filename;
}
const char *fileitem_get_displayname(FileItem *fileitem)
{
assert(fileitem != NULL);
assert(fileitem->displayname != NULL);
return fileitem->displayname;
}
FileItem *fileitem_get_parent(FileItem *fileitem)
{
assert(fileitem != NULL);
if (fileitem == rootitem)
return NULL;
else {
assert(fileitem->parent != NULL);
return fileitem->parent;
}
}
JList fileitem_get_children(FileItem *fileitem)
{
assert(fileitem != NULL);
if (!fileitem->children && IS_FOLDER(fileitem)) {
fileitem->children = jlist_new();
#ifdef USE_PIDLS
{
IShellFolder *pFolder = NULL;
if (fileitem == rootitem)
pFolder = shl_idesktop;
else
IShellFolder_BindToObject(shl_idesktop,
fileitem->fullpidl,
NULL,
&IID_IShellFolder,
(LPVOID *)&pFolder);
if (pFolder != NULL) {
IEnumIDList *pEnum = NULL;
ULONG c, fetched;
/* get the interface to enumerate subitems */
IShellFolder_EnumObjects(pFolder, win_get_window(),
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pEnum);
if (pEnum != NULL) {
LPITEMIDLIST itempidl[256];
SFGAOF attribs[256];
/* enumerate the items in the folder */
while (IEnumIDList_Next(pEnum, 256, itempidl, &fetched) == S_OK &&
fetched > 0) {
/* request the SFGAO_FOLDER attribute to know what of the
item is a folder */
for (c=0; c<fetched; ++c)
attribs[c] = SFGAO_FOLDER;
if (IShellFolder_GetAttributesOf(pFolder, fetched,
(LPCITEMIDLIST *)itempidl, attribs) != S_OK) {
for (c=0; c<fetched; ++c)
attribs[c] = 0;
}
/* generate the FileItems */
for (c=0; c<fetched; ++c) {
FileItem *child;
LPITEMIDLIST fullpidl = concat_pidl(fileitem->fullpidl,
itempidl[c]);
child = get_fileitem_by_fullpidl(fullpidl, FALSE);
if (!child) {
child = fileitem_new(fileitem);
child->pidl = itempidl[c];
child->fullpidl = fullpidl;
child->attrib = attribs[c];
update_by_pidl(child);
put_fileitem(child);
}
else {
assert(child->parent == fileitem);
free_pidl(fullpidl);
free_pidl(itempidl[c]);
}
fileitem_insert_child_sorted(fileitem, child);
}
}
IEnumIDList_Release(pEnum);
}
if (pFolder != shl_idesktop)
IShellFolder_Release(pFolder);
}
}
#else
{
char buf[MAX_PATH], path[MAX_PATH], tmp[32];
ustrcpy(path, fileitem->filename);
put_backslash(path);
replace_filename(buf,
path,
uconvert_ascii("*.*", tmp),
sizeof(buf));
for_each_file(buf, FA_TO_SHOW,
for_each_child_callback,
(int)fileitem); /* TODO warning with 64bits */
}
#endif
}
return fileitem->children;
}
bool filename_has_extension(const char *filename, const char *list_of_extensions)
{
const char *extension = get_extension(filename);
bool ret = FALSE;
if (extension) {
char *extdup = ustrlwr(jstrdup(extension));
int extsz = ustrlen(extdup);
char *p = ustrstr(list_of_extensions, extdup);
if ((p != NULL) &&
(p[extsz] == 0 || p[extsz] == ',') &&
(p == list_of_extensions || *(p-1) == ',')) {
ret = TRUE;
}
jfree(extdup);
}
return ret;
}
bool fileitem_has_extension(FileItem *fileitem, const char *list_of_extensions)
{
return filename_has_extension(fileitem_get_filename(fileitem),
list_of_extensions);
}
static FileItem *fileitem_new(FileItem *parent)
{
FileItem *fileitem = jnew(FileItem, 1);
if (!fileitem)
return NULL;
fileitem->filename = NULL;
fileitem->displayname = NULL;
fileitem->parent = parent;
fileitem->children = NULL;
fileitem->last_update = -1;
#ifdef USE_PIDLS
fileitem->pidl = NULL;
fileitem->fullpidl = NULL;
fileitem->attrib = 0;
#else
fileitem->keyname = NULL;
fileitem->attrib = 0;
#endif
return fileitem;
}
static void fileitem_free(FileItem *fileitem)
{
assert(fileitem != NULL);
#ifdef USE_PIDLS
if (fileitem->fullpidl &&
fileitem->fullpidl != fileitem->pidl) {
free_pidl(fileitem->fullpidl);
fileitem->fullpidl = NULL;
}
if (fileitem->pidl) {
free_pidl(fileitem->pidl);
fileitem->pidl = NULL;
}
#else
if (fileitem->keyname)
jfree(fileitem->keyname);
#endif
/* this isn't neccessary (if fileitem_free is called with the
root-item at the first time)...
if (fileitem->parent)
jlist_remove(fileitem->parent->children, fileitem);
*/
if (fileitem->filename)
jfree(fileitem->filename);
if (fileitem->displayname)
jfree(fileitem->displayname);
if (fileitem->children) {
JLink link, next;
JI_LIST_FOR_EACH_SAFE(fileitem->children, link, next) {
fileitem_free(link->data);
}
jlist_free(fileitem->children);
}
jfree(fileitem);
}
static void fileitem_insert_child_sorted(FileItem *fileitem, FileItem *child)
{
JLink link;
bool inserted = FALSE;
JI_LIST_FOR_EACH(fileitem->children, link) {
if (fileitem_cmp((FileItem *)link->data, child) > 0) {
jlist_insert_before(fileitem->children, link, child);
inserted = TRUE;
break;
}
}
if (!inserted)
jlist_append(fileitem->children, child);
}
/* fileitem_cmp:
* ustricmp for filenames: makes sure that eg "foo.bar" comes before
* "foo-1.bar", and also that "foo9.bar" comes before "foo10.bar".
*/
static int fileitem_cmp(FileItem *fi1, FileItem *fi2)
{
if (IS_FOLDER(fi1)) {
if (!IS_FOLDER(fi2))
return -1;
}
else if (IS_FOLDER(fi2))
return 1;
#ifdef USE_PIDLS
{
int c1, c2;
int x1, x2;
char *t1, *t2;
const char *s1 = fi1->displayname;
const char *s2 = fi2->displayname;
for (;;) {
c1 = utolower(ugetxc(&s1));
c2 = utolower(ugetxc(&s2));
if ((c1 >= '0') && (c1 <= '9') && (c2 >= '0') && (c2 <= '9')) {
x1 = ustrtol(s1 - ucwidth(c1), &t1, 10);
x2 = ustrtol(s2 - ucwidth(c2), &t2, 10);
if (x1 != x2)
return x1 - x2;
else if (t1 - s1 != t2 - s2)
return (t2 - s2) - (t1 - s1);
s1 = t1;
s2 = t2;
}
else if (c1 != c2) {
if (!c1)
return -1;
else if (!c2)
return 1;
else if (c1 == '.')
return -1;
else if (c2 == '.')
return 1;
return c1 - c2;
}
if (!c1)
return 0;
}
}
#endif
return -1;
}
/********************************************************************/
/* PIDLS: Only for Win32 */
/********************************************************************/
#ifdef USE_PIDLS
/* updates the names of the file-item through its PIDL */
static void update_by_pidl(FileItem *fileitem)
{
STRRET strret;
TCHAR pszName[MAX_PATH];
IShellFolder *pFolder = NULL;
if (fileitem->filename) {
jfree(fileitem->filename);
fileitem->filename = NULL;
}
if (fileitem->displayname) {
jfree(fileitem->displayname);
fileitem->displayname = NULL;
}
if (fileitem == rootitem)
pFolder = shl_idesktop;
else {
assert(fileitem->parent != NULL);
IShellFolder_BindToObject(shl_idesktop,
fileitem->parent->fullpidl,
NULL,
&IID_IShellFolder,
(LPVOID *)&pFolder);
}
/****************************************/
/* get the file name */
if (pFolder &&
IShellFolder_GetDisplayNameOf(pFolder,
fileitem->pidl,
SHGDN_NORMAL | SHGDN_FORPARSING,
&strret) == S_OK) {
StrRetToBuf(&strret, fileitem->pidl, pszName, MAX_PATH);
fileitem->filename = jstrdup(pszName);
}
else if (IShellFolder_GetDisplayNameOf(shl_idesktop,
fileitem->fullpidl,
SHGDN_NORMAL | SHGDN_FORPARSING,
&strret) == S_OK) {
StrRetToBuf(&strret, fileitem->fullpidl, pszName, MAX_PATH);
fileitem->filename = jstrdup(pszName);
}
else
fileitem->filename = jstrdup("ERR");
/****************************************/
/* get the name to display */
if (pFolder &&
IShellFolder_GetDisplayNameOf(pFolder,
fileitem->pidl,
SHGDN_INFOLDER,
&strret) == S_OK) {
StrRetToBuf(&strret, fileitem->pidl, pszName, MAX_PATH);
fileitem->displayname = jstrdup(pszName);
}
else if (IShellFolder_GetDisplayNameOf(shl_idesktop,
fileitem->fullpidl,
SHGDN_INFOLDER,
&strret) == S_OK) {
StrRetToBuf(&strret, fileitem->fullpidl, pszName, MAX_PATH);
fileitem->displayname = jstrdup(pszName);
}
else
fileitem->displayname = jstrdup("ERR");
if (pFolder && pFolder != shl_idesktop) {
IShellFolder_Release(pFolder);
}
}
static LPITEMIDLIST concat_pidl(LPITEMIDLIST pidlHead, LPITEMIDLIST pidlTail)
{
LPITEMIDLIST pidlNew;
UINT cb1, cb2;
assert(pidlHead != NULL);
assert(pidlTail != NULL);
cb1 = get_pidl_size(pidlHead) - sizeof(pidlHead->mkid.cb);
cb2 = get_pidl_size(pidlTail);
pidlNew = (LPITEMIDLIST)IMalloc_Alloc(shl_imalloc, cb1 + cb2);
if (pidlNew) {
CopyMemory(pidlNew, pidlHead, cb1);
CopyMemory(((LPSTR)pidlNew) + cb1, pidlTail, cb2);
}
return pidlNew;
}
static UINT get_pidl_size(LPITEMIDLIST pidl)
{
UINT cbTotal = 0;
if (pidl) {
cbTotal += sizeof(pidl->mkid.cb); /* null terminator */
while (pidl) {
cbTotal += pidl->mkid.cb;
pidl = get_next_pidl(pidl);
}
}
return cbTotal;
}
static LPITEMIDLIST get_next_pidl(LPITEMIDLIST pidl)
{
if (pidl != NULL && pidl->mkid.cb > 0) {
pidl = (LPITEMIDLIST)(((LPBYTE)(pidl)) + pidl->mkid.cb);
if (pidl->mkid.cb > 0)
return pidl;
}
return NULL;
}
static LPITEMIDLIST get_last_pidl(LPITEMIDLIST pidl)
{
LPITEMIDLIST pidlLast = pidl;
LPITEMIDLIST pidlNew = NULL;
while (pidl) {
pidlLast = pidl;
pidl = get_next_pidl(pidl);
}
if (pidlLast) {
ULONG sz = get_pidl_size(pidlLast);
pidlNew = (LPITEMIDLIST)IMalloc_Alloc(shl_imalloc, sz);
CopyMemory(pidlNew, pidlLast, sz);
}
return pidlNew;
}
static LPITEMIDLIST clone_pidl(LPITEMIDLIST pidl)
{
ULONG sz = get_pidl_size(pidl);
LPITEMIDLIST pidlNew = (LPITEMIDLIST)IMalloc_Alloc(shl_imalloc, sz);
CopyMemory(pidlNew, pidl, sz);
return pidlNew;
}
static LPITEMIDLIST remove_last_pidl(LPITEMIDLIST pidl)
{
LPITEMIDLIST pidlFirst = pidl;
LPITEMIDLIST pidlLast = pidl;
while (pidl) {
pidlLast = pidl;
pidl = get_next_pidl(pidl);
}
if (pidlLast)
pidlLast->mkid.cb = 0;
return pidlFirst;
}
static void free_pidl(LPITEMIDLIST pidl)
{
IMalloc_Free(shl_imalloc, pidl);
}
static char *get_key_for_pidl(LPITEMIDLIST pidl)
{
char *key = jmalloc(sizeof(char) * (get_pidl_size(pidl)+1));
UINT c, i = 0;
while (pidl) {
for (c=0; c<pidl->mkid.cb; ++c) {
if (pidl->mkid.abID[c])
key[i++] = pidl->mkid.abID[c];
else
key[i++] = 1;
}
pidl = get_next_pidl(pidl);
}
key[i] = 0;
return key;
}
static FileItem *get_fileitem_by_fullpidl(LPITEMIDLIST fullpidl, bool create_if_not)
{
char *key;
FileItem *fileitem;
key = get_key_for_pidl(fullpidl);
fileitem = hash_lookup(hash_fileitems, key);
jfree(key);
if (fileitem)
return fileitem;
if (!create_if_not)
return NULL;
/* new file-item */
fileitem = fileitem_new(NULL);
fileitem->fullpidl = clone_pidl(fullpidl);
fileitem->attrib = SFGAO_FOLDER;
IShellFolder_GetAttributesOf(shl_idesktop, 1,
(LPCITEMIDLIST *)&fileitem->fullpidl,
&fileitem->attrib);
{
LPITEMIDLIST parent_fullpidl = clone_pidl(fileitem->fullpidl);
remove_last_pidl(parent_fullpidl);
fileitem->pidl = get_last_pidl(fileitem->fullpidl);
fileitem->parent = get_fileitem_by_fullpidl(parent_fullpidl, TRUE);
free_pidl(parent_fullpidl);
}
update_by_pidl(fileitem);
put_fileitem(fileitem);
return fileitem;
}
static void put_fileitem(FileItem *fileitem)
{
char *key;
assert(fileitem->filename != NULL);
key = get_key_for_pidl(fileitem->fullpidl);
hash_insert(hash_fileitems, key, fileitem);
jfree(key);
}
#else
/********************************************************************/
/* Allegro for_each_file: Portable */
/********************************************************************/
static FileItem *get_fileitem_by_path(const char *path, bool create_if_not)
{
char *key;
FileItem *fileitem;
int attrib;
key = get_key_for_filename(path);
fileitem = hash_lookup(hash_fileitems, key);
jfree(key);
if (fileitem)
return fileitem;
if (!create_if_not)
return NULL;
/* get the attributes of the file */
attrib = 0;
if (!file_exists(path, FA_ALL, &attrib)) {
if (!ji_dir_exists(path))
return NULL;
attrib = FA_DIREC;
}
/* new file-item */
fileitem = fileitem_new(NULL);
fileitem->filename = jstrdup(path);
fileitem->displayname = jstrdup(get_filename(path));
fileitem->attrib = attrib;
/* get the parent */
{
char parent_path[MAX_PATH];
replace_filename(parent_path, path, "", sizeof(parent_path));
remove_backslash(parent_path);
fileitem->parent = get_fileitem_by_path(parent_path, TRUE);
}
put_fileitem(fileitem);
return fileitem;
}
static void for_each_child_callback(const char *filename, int attrib, int param)
{
FileItem *fileitem = (FileItem *)param;
FileItem *child;
const char *filename_without_path = get_filename(filename);
if (*filename_without_path == '.' &&
(ustrcmp(filename_without_path, ".") == 0 ||
ustrcmp(filename_without_path, "..") == 0))
return;
child = get_fileitem_by_path(filename, FALSE);
if (!child) {
child = fileitem_new(fileitem);
child->filename = jstrdup(filename);
child->displayname = jstrdup(filename_without_path);
child->attrib = attrib;
put_fileitem(child);
}
else {
assert(child->parent == fileitem);
}
fileitem_insert_child_sorted(fileitem, child);
}
static char *remove_backslash(char *filename)
{
int len = ustrlen(filename);
if (len > 0 &&
(filename[len-1] == '/' ||
filename[len-1] == OTHER_PATH_SEPARATOR)) {
#ifdef HAVE_DRIVES
/* if the name is C:\ or something like that, the backslash isn't
removed */
if (len == 3 && filename[1] == DEVICE_SEPARATOR)
return filename;
#endif
filename[len-1] = 0;
}
return filename;
}
static char *get_key_for_filename(const char *filename)
{
char buf[MAX_PATH];
ustrcpy(buf, filename);
#if !defined CASE_SENSITIVE
ustrlwr(buf);
#endif
fix_filename_slashes(buf);
return jstrdup(buf);
}
static void put_fileitem(FileItem *fileitem)
{
assert(fileitem->filename != NULL);
assert(fileitem->keyname == NULL);
fileitem->keyname = get_key_for_filename(fileitem->filename);
/* insert this file-item in the hash-table */
hash_insert(hash_fileitems, fileitem->keyname, fileitem);
}
#endif

46
src/core/file_system.h Normal file
View File

@ -0,0 +1,46 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef CORE_FILE_SYSTEM_H
#define CORE_FILE_SYSTEM_H
#include "jinete/jbase.h"
struct FileItem;
typedef struct FileItem FileItem;
bool file_system_init(void);
void file_system_exit(void);
FileItem *get_root_fileitem(void);
FileItem *get_fileitem_from_path(const char *path);
bool fileitem_is_folder(FileItem *fileitem);
bool fileitem_is_browsable(FileItem *fileitem);
const char *fileitem_get_filename(FileItem *fileitem);
const char *fileitem_get_displayname(FileItem *fileitem);
FileItem *fileitem_get_parent(FileItem *fileitem);
JList fileitem_get_children(FileItem *fileitem);
bool filename_has_extension(const char *filename, const char *list_of_extensions);
bool fileitem_has_extension(FileItem *fileitem, const char *list_of_extensions);
#endif /* CORE_FILE_SYSTEM_H */

View File

@ -68,7 +68,7 @@ static Module module[] =
static int modules = sizeof(module) / sizeof(Module); static int modules = sizeof(module) / sizeof(Module);
int modules_init(int requirements) bool modules_init(int requirements)
{ {
int c; int c;
@ -76,11 +76,12 @@ int modules_init(int requirements)
if (module[c].reqs & requirements) { if (module[c].reqs & requirements) {
PRINTF("Installing module: %s\n", module[c].name); PRINTF("Installing module: %s\n", module[c].name);
if ((*module[c].init)() < 0) if ((*module[c].init)() < 0)
return -1; return FALSE;
module[c].installed = TRUE; module[c].installed = TRUE;
} }
return 0; return TRUE;
} }
void modules_exit(void) void modules_exit(void)

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello * Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -19,10 +19,12 @@
#ifndef CORE_MODULES_H #ifndef CORE_MODULES_H
#define CORE_MODULES_H #define CORE_MODULES_H
#include "jinete/jbase.h"
#define REQUIRE_INTERFACE 1 #define REQUIRE_INTERFACE 1
#define REQUIRE_SCRIPTING 2 #define REQUIRE_SCRIPTING 2
int modules_init(int requirements); bool modules_init(int requirements);
void modules_exit(void); void modules_exit(void);
#endif /* CORE_MODULES_H */ #endif /* CORE_MODULES_H */

View File

@ -240,7 +240,7 @@ static void load_command(JWidget widget)
RGB *palette; RGB *palette;
char *filename; char *filename;
filename = GUI_FileSelect(_("Load Palette"), "", "pcx,bmp,tga,lbm,col"); filename = ase_file_selector(_("Load Palette"), "", "pcx,bmp,tga,lbm,col");
if (filename) { if (filename) {
palette = palette_load(filename); palette = palette_load(filename);
if (!palette) { if (!palette) {
@ -260,7 +260,7 @@ static void save_command(JWidget widget)
int ret; int ret;
again: again:
filename = GUI_FileSelect(_("Save Palette"), "", "pcx,bmp,tga,col"); filename = ase_file_selector(_("Save Palette"), "", "pcx,bmp,tga,col");
if (filename) { if (filename) {
if (exists(filename)) { if (exists(filename)) {
ret = jalert("%s<<%s<<%s||%s", ret = jalert("%s<<%s<<%s||%s",

View File

@ -283,9 +283,9 @@ static void button_font_command(JWidget widget)
{ {
char *filename; char *filename;
filename = GUI_FileSelect(_("Open Font (TTF or Allegro bitmap format)"), filename = ase_file_selector(_("Open Font (TTF or Allegro bitmap format)"),
get_config_string ("DrawText", "Font", ""), get_config_string ("DrawText", "Font", ""),
"pcx,bmp,tga,lbm,ttf"); "pcx,bmp,tga,lbm,ttf");
if (filename) { if (filename) {
set_config_string("DrawText", "Font", filename); set_config_string("DrawText", "Font", filename);
update_button_text(); update_button_text();

View File

@ -20,20 +20,10 @@
#ifndef USE_PRECOMPILED_HEADER #ifndef USE_PRECOMPILED_HEADER
#include <assert.h>
#include <allegro.h> #include <allegro.h>
#include <allegro/internal/aintern.h> #include <allegro/internal/aintern.h>
#include <errno.h> #include <errno.h>
#if defined ALLEGRO_UNIX || defined ALLEGRO_DJGPP || defined ALLEGRO_MINGW32
# include <sys/stat.h>
#endif
#if defined ALLEGRO_UNIX || defined ALLEGRO_MINGW32
# include <sys/unistd.h>
#endif
#ifdef ALLEGRO_WINDOWS
#include <winalleg.h>
#include <shlobj.h>
#endif
#include "jinete/jinete.h" #include "jinete/jinete.h"
@ -41,6 +31,7 @@
#include "core/dirs.h" #include "core/dirs.h"
#include "modules/gfx.h" #include "modules/gfx.h"
#include "modules/gui.h" #include "modules/gui.h"
#include "widgets/fileview.h"
#endif #endif
@ -48,38 +39,50 @@
# define HAVE_DRIVES # define HAVE_DRIVES
#endif #endif
#define FA_ALL FA_RDONLY | FA_DIREC | FA_ARCH | FA_HIDDEN | FA_SYSTEM /* Variables used only to maintain the history of navigation. */
static JLink navigation_position = NULL; /* current position in the navigation history */
static JList navigation_history = NULL; /* set of FileItems navigated */
static bool navigation_locked = FALSE; /* if TRUE the navigation_history isn't
modified if the current folder
changes (used when the back/forward
buttons are pushed) */
static bool combobox_msg_proc(JWidget widget, JMessage message); static void update_location(JWidget window);
static void add_bookmark_command(JWidget widget, void *data); static void update_navigation_buttons(JWidget window);
static void del_bookmark_command(JWidget widget, void *data); static void add_in_navigation_history(FileItem *folder);
static void fill_bookmarks_combobox(JWidget combobox); static void select_filetype_from_filename(JWidget window);
static void home_command(JWidget widget);
static void fonts_command(JWidget widget); static void goback_command(JWidget widget);
static void palettes_command(JWidget widget); static void goforward_command(JWidget widget);
static void mkdir_command(JWidget widget); static void goup_command(JWidget widget);
static bool fileview_msg_proc(JWidget widget, JMessage msg);
static bool location_msg_proc(JWidget widget, JMessage msg);
static bool filetype_msg_proc(JWidget widget, JMessage msg);
/** /**
* The routine to select file in ASE. * The routine that shows the dialog to select a file in ASE.
*
* It add some extra functionalities to the default Jinete
* file-selection dialog.
*
* @see ji_file_select_ex.
*/ */
char *GUI_FileSelect(const char *message, char *ase_file_selector(const char *message,
const char *init_path, const char *init_path,
const char *exts) const char *exts)
{ {
JWidget box_left, button_home; static JWidget window = NULL;
JWidget button_fonts, button_palettes, button_mkdir; JWidget fileview, box, ok;
JWidget box_top, box_top2, combobox, add_bookmark, del_bookmark, entry_path; JWidget goback, goforward, goup;
JWidget widget_extension; JWidget filename_entry;
char buf[512], *selected_filename; JWidget filetype;
char buf[512];
char *result = NULL;
char *tok;
if (!navigation_history)
navigation_history = jlist_new();
/* 'buf' will contain the start folder path */
ustrcpy(buf, init_path); ustrcpy(buf, init_path);
/* insert the path */ /* use the current path */
if (get_filename(buf) == buf) { if (get_filename(buf) == buf) {
char path[512]; char path[512];
@ -105,297 +108,410 @@ char *GUI_FileSelect(const char *message,
ustrcat(path, buf); ustrcat(path, buf);
ustrcpy(buf, path); ustrcpy(buf, path);
} }
else {
/* remove the filename */
*get_filename(buf) = 0;
}
if (!window) {
JWidget view, location;
/**********************************************************************/ /* load the window widget */
/* prepare left side */ window = load_widget("filesel.jid", "file_selector");
if (!window)
return NULL;
box_left = jbox_new(JI_VERTICAL); box = jwidget_find_name(window, "box");
button_home = jbutton_new(NULL); goback = jwidget_find_name(window, "goback");
button_fonts = jbutton_new(NULL); goforward = jwidget_find_name(window, "goforward");
button_palettes = jbutton_new(NULL); goup = jwidget_find_name(window, "goup");
button_mkdir = jbutton_new(NULL); location = jwidget_find_name(window, "location");
filetype = jwidget_find_name(window, "filetype");
add_gfxicon_to_button(button_home, GFX_FILE_HOME, JI_CENTER | JI_MIDDLE); jwidget_focusrest(goback, FALSE);
add_gfxicon_to_button(button_fonts, GFX_FILE_FONTS, JI_CENTER | JI_MIDDLE); jwidget_focusrest(goforward, FALSE);
add_gfxicon_to_button(button_palettes, GFX_FILE_PALETTES, JI_CENTER | JI_MIDDLE); jwidget_focusrest(goup, FALSE);
add_gfxicon_to_button(button_mkdir, GFX_FILE_MKDIR, JI_CENTER | JI_MIDDLE);
/* hook signals */ add_gfxicon_to_button(goback, GFX_ARROW_LEFT, JI_CENTER | JI_MIDDLE);
jbutton_add_command(button_home, home_command); add_gfxicon_to_button(goforward, GFX_ARROW_RIGHT, JI_CENTER | JI_MIDDLE);
jbutton_add_command(button_fonts, fonts_command); add_gfxicon_to_button(goup, GFX_ARROW_UP, JI_CENTER | JI_MIDDLE);
jbutton_add_command(button_palettes, palettes_command);
jbutton_add_command(button_mkdir, mkdir_command);
jwidget_add_childs(box_left, jbutton_add_command(goback, goback_command);
button_home, button_fonts, jbutton_add_command(goforward, goforward_command);
button_palettes, button_mkdir, NULL); jbutton_add_command(goup, goup_command);
/**********************************************************************/ view = jview_new();
/* prepare top side */ fileview = fileview_new(get_fileitem_from_path(buf), exts);
box_top = jbox_new(JI_HORIZONTAL); jwidget_add_hook(fileview, -1, fileview_msg_proc, NULL);
box_top2 = jbox_new(JI_HORIZONTAL | JI_HOMOGENEOUS); jwidget_add_hook(location, -1, location_msg_proc, NULL);
combobox = jcombobox_new(); jwidget_add_hook(filetype, -1, filetype_msg_proc, NULL);
entry_path = jcombobox_get_entry_widget(combobox);
add_bookmark = jbutton_new("+");
del_bookmark = jbutton_new("-");
#ifdef HAVE_DRIVES jwidget_set_name(fileview, "fileview");
jcombobox_casesensitive(combobox, FALSE); jwidget_magnetic(fileview, TRUE);
#else
jcombobox_casesensitive(combobox, TRUE);
#endif
jwidget_noborders(box_top2); jview_attach(view, fileview);
jbutton_set_bevel(add_bookmark, 2, 0, 2, 0); jwidget_expansive(view, TRUE);
jbutton_set_bevel(del_bookmark, 0, 2, 0, 2);
jcombobox_editable(combobox, TRUE);
jcombobox_clickopen(combobox, FALSE);
jwidget_add_hook(combobox, JI_WIDGET, combobox_msg_proc, NULL); jwidget_add_child(box, view);
jbutton_add_command_data(add_bookmark, add_bookmark_command, combobox);
jbutton_add_command_data(del_bookmark, del_bookmark_command, combobox);
fill_bookmarks_combobox(combobox); jwidget_set_min_size(window, JI_SCREEN_W*9/10, JI_SCREEN_H*9/10);
jwindow_remap(window);
jwindow_center(window);
}
else {
fileview = jwidget_find_name(window, "fileview");
filetype = jwidget_find_name(window, "filetype");
jwidget_expansive(combobox, TRUE); jwidget_signal_off(fileview);
jwidget_add_childs(box_top, combobox, box_top2, NULL); fileview_set_current_folder(fileview, get_fileitem_from_path(buf));
jwidget_add_childs(box_top2, add_bookmark, del_bookmark, NULL); jwidget_signal_on(fileview);
}
/**********************************************************************/ /* current location */
/* prepare widget_extension */ navigation_position = NULL;
add_in_navigation_history(fileview_get_current_folder(fileview));
/* fill the location combo-box */
update_location(window);
update_navigation_buttons(window);
widget_extension = jwidget_new(JI_WIDGET); /* fill file-type combo-box */
jwidget_set_name(box_left, "left"); jcombobox_clear(filetype);
jwidget_set_name(box_top, "top"); ustrcpy(buf, exts);
jwidget_set_name(entry_path, "path"); for (tok = ustrtok(buf, ",");
jwidget_add_childs(widget_extension, box_left, box_top, NULL); tok != NULL;
tok = ustrtok(NULL, ",")) {
jcombobox_add_string(filetype, tok, NULL);
}
/* call the jinete file selector */ /* file name entry field */
selected_filename = ji_file_select_ex(message, buf, exts, widget_extension); filename_entry = jwidget_find_name(window, "filename");
if (selected_filename) { jwidget_set_text(filename_entry, get_filename(init_path));
char *s, *name_dup = jstrdup(selected_filename); select_filetype_from_filename(window);
/* setup the title of the window */
jwidget_set_text(window, message);
/* get the ok-button */
ok = jwidget_find_name(window, "ok");
/* update the view */
jview_update(jwidget_get_view(fileview));
/* open the window and run... the user press ok? */
jwindow_open_fg(window);
if (jwindow_get_killer(window) == ok ||
jwindow_get_killer(window) == fileview) {
char *p;
/* open the selected file */
FileItem *folder = fileview_get_current_folder(fileview);
assert(folder != NULL);
ustrcpy(buf, fileitem_get_filename(folder));
put_backslash(buf);
ustrcat(buf, jwidget_get_text(filename_entry));
/* does it not have extension? ...we should add the extension
selected in the filetype combo-box */
p = get_extension(buf);
if (!p || *p == 0) {
ustrcat(buf, ".");
ustrcat(buf, jcombobox_get_selected_string(filetype));
}
/* duplicate the buffer to return a new string */
result = jstrdup(buf);
/* save the path in the configuration file */ /* save the path in the configuration file */
s = get_filename(name_dup); {
if (s) char *name_dup = jstrdup(result);
*s = 0; char *s = get_filename(name_dup);
if (s)
set_config_string("FileSelect", "CurrentDirectory", name_dup); *s = 0;
jfree(name_dup); set_config_string("FileSelect", "CurrentDirectory", name_dup);
jfree(name_dup);
}
} }
jwidget_free(widget_extension); /* TODO why this doesn't work if I remove this? */
jwidget_free(window);
window = NULL;
return selected_filename; return result;
} }
static bool combobox_msg_proc(JWidget widget, JMessage msg) /**
* Updates the content of the combo-box that shows the current
* location in the file-system.
*/
static void update_location(JWidget window)
{ {
switch (msg->type) { char buf[MAX_PATH*2];
JWidget fileview = jwidget_find_name(window, "fileview");
JWidget location = jwidget_find_name(window, "location");
FileItem *current_folder = fileview_get_current_folder(fileview);
FileItem *fileitem = current_folder;
JList locations = jlist_new();
int c, level = 0;
JLink link;
int selected_index = -1;
case JM_SIGNAL: while (fileitem != NULL) {
if (msg->signal.num == JI_SIGNAL_COMBOBOX_SELECT) { jlist_prepend(locations, fileitem);
ji_file_select_enter_to_path(jcombobox_get_selected_string(widget)); fileitem = fileitem_get_parent(fileitem);
return TRUE;
}
break;
} }
/* clear all the items from the combo-box */
jcombobox_clear(location);
/* add item by item (from root to the specific current folder) */
level = 0;
JI_LIST_FOR_EACH(locations, link) {
fileitem = link->data;
/* indentation */
ustrcpy(buf, empty_string);
for (c=0; c<level; ++c)
ustrcat(buf, " ");
/* location name */
ustrcat(buf, fileitem_get_displayname(fileitem));
/* add the new location to the combo-box */
jcombobox_add_string(location, buf, fileitem);
if (fileitem == current_folder)
selected_index = level;
level++;
}
jwidget_signal_off(location);
jcombobox_select_index(location, selected_index);
jwidget_set_text(jcombobox_get_entry_widget(location),
fileitem_get_displayname(current_folder));
jentry_deselect_text(jcombobox_get_entry_widget(location));
jwidget_signal_on(location);
jlist_free(locations);
}
static void update_navigation_buttons(JWidget window)
{
JWidget fileview = jwidget_find_name(window, "fileview");
JWidget goback = jwidget_find_name(window, "goback");
JWidget goforward = jwidget_find_name(window, "goforward");
JWidget goup = jwidget_find_name(window, "goup");
FileItem *current_folder = fileview_get_current_folder(fileview);
/* update the state of the go back button: if the navigation-history
has two elements and the navigation-position isn't the first
one */
if (jlist_length(navigation_history) > 1 &&
(!navigation_position ||
navigation_position != jlist_first(navigation_history))) {
jwidget_enable(goback);
}
else {
jwidget_disable(goback);
}
/* update the state of the go forward button: if the
navigation-history has two elements and the navigation-position
isn't the last one */
if (jlist_length(navigation_history) > 1 &&
(!navigation_position ||
navigation_position != jlist_last(navigation_history))) {
jwidget_enable(goforward);
}
else {
jwidget_disable(goforward);
}
/* update the state of the go up button: if the current-folder isn't
the root-item */
if (current_folder != get_root_fileitem())
jwidget_enable(goup);
else
jwidget_disable(goup);
}
static void add_in_navigation_history(FileItem *folder)
{
assert(fileitem_is_folder(folder));
/* remove the history from the current position */
if (navigation_position) {
JLink next;
for (navigation_position = navigation_position->next;
navigation_position != navigation_history->end;
navigation_position = next) {
next = navigation_position->next;
jlist_delete_link(navigation_history,
navigation_position);
}
navigation_position = NULL;
}
/* if the history is empty or if the last item isn't the folder that
we are visiting... */
if (jlist_empty(navigation_history) ||
jlist_last_data(navigation_history) != folder) {
/* ...we can add the location in the history */
jlist_append(navigation_history, folder);
navigation_position = jlist_last(navigation_history);
}
}
static void select_filetype_from_filename(JWidget window)
{
JWidget entry = jwidget_find_name(window, "filename");
JWidget filetype = jwidget_find_name(window, "filetype");
const char *filename = jwidget_get_text(entry);
char *p = get_extension(filename);
char buf[MAX_PATH];
if (p && *p != 0) {
ustrcpy(buf, get_extension(filename));
ustrlwr(buf);
jcombobox_select_string(filetype, buf);
}
}
static void goback_command(JWidget widget)
{
JWidget fileview = jwidget_find_name(jwidget_get_window(widget),
"fileview");
if (jlist_length(navigation_history) > 1) {
if (!navigation_position)
navigation_position = jlist_last(navigation_history);
if (navigation_position->prev != navigation_history->end) {
navigation_position = navigation_position->prev;
navigation_locked = TRUE;
fileview_set_current_folder(fileview,
navigation_position->data);
navigation_locked = FALSE;
}
}
}
static void goforward_command(JWidget widget)
{
JWidget fileview = jwidget_find_name(jwidget_get_window(widget),
"fileview");
if (jlist_length(navigation_history) > 1) {
if (!navigation_position)
navigation_position = jlist_first(navigation_history);
if (navigation_position->next != navigation_history->end) {
navigation_position = navigation_position->next;
navigation_locked = TRUE;
fileview_set_current_folder(fileview,
navigation_position->data);
navigation_locked = FALSE;
}
}
}
static void goup_command(JWidget widget)
{
JWidget fileview = jwidget_find_name(jwidget_get_window(widget),
"fileview");
fileview_goup(fileview);
}
static bool fileview_msg_proc(JWidget widget, JMessage msg)
{
if (msg->type == JM_SIGNAL) {
switch (msg->signal.num) {
case SIGNAL_FILEVIEW_FILE_SELECTED: {
FileItem *fileitem = fileview_get_selected(widget);
if (!fileitem_is_folder(fileitem)) {
JWidget window = jwidget_get_window(widget);
JWidget entry = jwidget_find_name(window, "filename");
const char *filename = fileitem_get_filename(fileitem);
jwidget_set_text(entry, get_filename(filename));
select_filetype_from_filename(window);
}
break;
}
case SIGNAL_FILEVIEW_FILE_ACCEPT:
jwidget_close_window(widget);
break;
case SIGNAL_FILEVIEW_CURRENT_FOLDER_CHANGED: {
JWidget window = jwidget_get_window(widget);
if (!navigation_locked)
add_in_navigation_history(fileview_get_current_folder(widget));
update_location(window);
update_navigation_buttons(window);
break;
}
}
}
return FALSE; return FALSE;
} }
/** static bool location_msg_proc(JWidget widget, JMessage msg)
* Adds a new bookmark.
*/
static void add_bookmark_command(JWidget widget, void *data)
{ {
JWidget combobox = data; if (msg->type == JM_SIGNAL) {
char buf[64], path[1024]; switch (msg->signal.num) {
int count;
case JI_SIGNAL_COMBOBOX_SELECT: {
FileItem *fileitem =
jcombobox_get_data(widget,
jcombobox_get_selected_index(widget));
count = get_config_int("Bookmarks", "Count", 0); if (fileitem) {
count = MID(0, count, 256); JWidget fileview = jwidget_find_name(jwidget_get_window(widget),
"fileview");
if (count < 256) { fileview_set_current_folder(fileview, fileitem);
replace_filename(path, ji_file_select_get_current_path(), "", 1024); }
break;
jcombobox_add_string(combobox, path);
usprintf(buf, "Mark%02d", count);
set_config_string("Bookmarks", buf, path);
set_config_int("Bookmarks", "Count", count+1);
}
}
/**
* Deletes a bookmark.
*/
static void del_bookmark_command(JWidget widget, void *data)
{
JWidget combobox = data;
char buf[64], path[1024];
int index, count;
count = jcombobox_get_count(combobox);
if (count > 0) {
replace_filename(path, ji_file_select_get_current_path(), "", 1024);
index = jcombobox_get_index(combobox, path);
if (index >= 0 && index < count) {
jcombobox_del_index(combobox, index);
for (; index<count; index++) {
usprintf(buf, "Mark%02d", index);
set_config_string("Bookmarks", buf,
jcombobox_get_string(combobox, index));
} }
usprintf(buf, "Mark%02d", index);
set_config_string("Bookmarks", buf, "");
set_config_int("Bookmarks", "Count", count-1);
} }
} }
return FALSE;
} }
/** static bool filetype_msg_proc(JWidget widget, JMessage msg)
* Fills the combo-box with the existent bookmarks.
*/
static void fill_bookmarks_combobox(JWidget combobox)
{ {
const char *path; if (msg->type == JM_SIGNAL) {
char buf[256]; switch (msg->signal.num) {
int c, count;
count = get_config_int("Bookmarks", "Count", 0); case JI_SIGNAL_COMBOBOX_SELECT: {
count = MID(0, count, 256); const char *ext = jcombobox_get_selected_string(widget);
JWidget window = jwidget_get_window(widget);
JWidget entry = jwidget_find_name(window, "filename");
char buf[MAX_PATH];
char *p;
for (c=0; c<count; c++) { ustrcpy(buf, jwidget_get_text(entry));
usprintf(buf, "Mark%02d", c); p = get_extension(buf);
path = get_config_string("Bookmarks", buf, ""); if (p && *p != 0) {
if (path && *path) ustrcpy(p, ext);
jcombobox_add_string(combobox, path); jwidget_set_text(entry, buf);
} }
} break;
}
/**
* Goes to the "Home" folder.
*/
static void home_command(JWidget widget)
{
char *env;
/* in Windows we can use the "My Documents" folder */
#ifdef ALLEGRO_WINDOWS
TCHAR szPath[MAX_PATH];
if (SHGetFolderPath(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE,
NULL, 0, szPath) == S_OK) {
ji_file_select_enter_to_path(szPath);
return;
}
#endif
/* in Unix we can use the HOME enviroment variable */
env = getenv("HOME");
/* home directory? */
if ((env) && (*env)) {
ji_file_select_enter_to_path(env);
}
/* ok, maybe we are in DOS, so we can use the ASE directory */
else {
char path[1024];
get_executable_name(path, sizeof(path));
*get_filename(path) = 0;
ji_file_select_enter_to_path(path);
}
}
/**
* Goes to the "Fonts" directory.
*/
static void fonts_command(JWidget widget)
{
DIRS *dir, *dirs = filename_in_datadir("fonts/");
for (dir=dirs; dir; dir=dir->next) {
if (ji_dir_exists (dir->path)) {
ji_file_select_enter_to_path(dir->path);
break;
} }
} }
return FALSE;
dirs_free(dirs);
} }
/**
* Goes to the "Palettes" directory.
*/
static void palettes_command(JWidget widget)
{
DIRS *dir, *dirs = filename_in_datadir("palettes/");
for (dir=dirs; dir; dir=dir->next) {
if (ji_dir_exists (dir->path)) {
ji_file_select_enter_to_path(dir->path);
break;
}
}
dirs_free(dirs);
}
/**
* Shows the dialog to makes a new folder/directory.
*/
static void mkdir_command(JWidget widget)
{
JWidget window, box1, box2, label_name, entry_name, button_create, button_cancel;
window = jwindow_new(_("Make Directory"));
box1 = jbox_new(JI_VERTICAL);
box2 = jbox_new(JI_HORIZONTAL | JI_HOMOGENEOUS);
label_name = jlabel_new(_("Name:"));
entry_name = jentry_new(256, _("New Directory"));
button_create = jbutton_new(_("&OK"));
button_cancel = jbutton_new(_("&Cancel"));
jwidget_set_min_size(entry_name, JI_SCREEN_W*75/100, 0);
jwidget_add_child(box2, button_create);
jwidget_add_child(box2, button_cancel);
jwidget_add_child(box1, label_name);
jwidget_add_child(box1, entry_name);
jwidget_add_child(box1, box2);
jwidget_add_child(window, box1);
jwidget_magnetic(button_create, TRUE);
jwindow_open_fg(window);
if (jwindow_get_killer(window) == button_create) {
char buf[1024];
int res;
ustrcpy(buf, ji_file_select_get_current_path());
put_backslash(buf);
ustrcat(buf, jwidget_get_text(entry_name));
#if defined ALLEGRO_UNIX || defined ALLEGRO_DJGPP
res = mkdir(buf, 0777);
#else
res = mkdir(buf);
#endif
if (res != 0)
jalert(_("Error<<Error making the directory||&Close"));
/* fill again the file-list */
else
ji_file_select_refresh_listbox();
}
jwidget_free(window);
}

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello * Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -19,9 +19,9 @@
#ifndef DIALOGS_FILESEL_H #ifndef DIALOGS_FILESEL_H
#define DIALOGS_FILESEL_H #define DIALOGS_FILESEL_H
char *GUI_FileSelect(const char *message, char *ase_file_selector(const char *message,
const char *init_path, const char *init_path,
const char *exts); const char *exts);
#endif /* DIALOGS_FILESEL_H */ #endif /* DIALOGS_FILESEL_H */

View File

@ -268,11 +268,12 @@ bool effect_apply_step(Effect *effect)
void effect_apply(Effect *effect) void effect_apply(Effect *effect)
{ {
add_progress(effect->h); /* add_progress(effect->h); */
effect_begin(effect); effect_begin(effect);
while (effect_apply_step(effect)) while (effect_apply_step(effect))
do_progress(effect->row); ;
/* do_progress(effect->row); */
/* undo stuff */ /* undo stuff */
if (undo_is_enabled(effect->sprite->undo)) if (undo_is_enabled(effect->sprite->undo))
@ -282,7 +283,7 @@ void effect_apply(Effect *effect)
/* copy "dst" to "src" */ /* copy "dst" to "src" */
image_copy(effect->src, effect->dst, 0, 0); image_copy(effect->src, effect->dst, 0, 0);
del_progress(); /* del_progress(); */
} }
void effect_flush(Effect *effect) void effect_flush(Effect *effect)
@ -343,15 +344,15 @@ void effect_apply_to_target(Effect *effect)
undo_open(effect->sprite->undo); undo_open(effect->sprite->undo);
} }
add_progress(images); /* add_progress(images); */
for (n=n2=0; n<stock->nimage; n++) { for (n=n2=0; n<stock->nimage; n++) {
if (!stock->image[n]) if (!stock->image[n])
continue; continue;
do_progress(n2++); /* do_progress(n2++); */
effect_apply_to_image(effect, stock->image[n], x[n], y[n]); effect_apply_to_image(effect, stock->image[n], x[n], y[n]);
} }
del_progress(); /* del_progress(); */
if (images > 1) { if (images > 1) {
/* close */ /* close */

View File

@ -24,8 +24,7 @@
#include "jinete/jlist.h" #include "jinete/jlist.h"
#include "console/console.h" /* #include "file/ase_format.h" */
#include "file/ase_format.h"
#include "file/file.h" #include "file/file.h"
#include "raster/raster.h" #include "raster/raster.h"
@ -69,17 +68,14 @@ typedef struct ASE_FrameHeader
ase_uint16 duration; ase_uint16 duration;
} ASE_FrameHeader; } ASE_FrameHeader;
static Sprite *load_ASE(const char *filename); static bool load_ASE(FileOp *fop);
static int save_ASE(Sprite *sprite); static bool save_ASE(FileOp *fop);
static ASE_FrameHeader *current_frame_header = NULL; static ASE_FrameHeader *current_frame_header = NULL;
static int chunk_type; static int chunk_type;
static int chunk_start; static int chunk_start;
static Sprite *ase_file_read(const char *filename); static bool ase_file_read_header(FILE *f, ASE_Header *header);
static int ase_file_write(Sprite *sprite);
static int ase_file_read_header(FILE *f, ASE_Header *header);
static void ase_file_prepare_header(FILE *f, ASE_Header *header, Sprite *sprite); static void ase_file_prepare_header(FILE *f, ASE_Header *header, Sprite *sprite);
static void ase_file_write_header(FILE *f, ASE_Header *header); static void ase_file_write_header(FILE *f, ASE_Header *header);
@ -88,7 +84,7 @@ static void ase_file_prepare_frame_header(FILE *f, ASE_FrameHeader *frame_header
static void ase_file_write_frame_header(FILE *f, ASE_FrameHeader *frame_header); static void ase_file_write_frame_header(FILE *f, ASE_FrameHeader *frame_header);
static void ase_file_write_layers(FILE *f, Layer *layer); static void ase_file_write_layers(FILE *f, Layer *layer);
static void ase_file_write_cels(FILE *f, Sprite *sprite, Layer *layer, int frpos); static void ase_file_write_cels(FILE *f, Sprite *sprite, Layer *layer, int frame);
static void ase_file_read_padding(FILE *f, int bytes); static void ase_file_read_padding(FILE *f, int bytes);
static void ase_file_write_padding(FILE *f, int bytes); static void ase_file_write_padding(FILE *f, int bytes);
@ -102,15 +98,20 @@ static void ase_file_read_color_chunk(FILE *f, RGB *pal);
static void ase_file_write_color_chunk(FILE *f, RGB *pal); static void ase_file_write_color_chunk(FILE *f, RGB *pal);
static Layer *ase_file_read_layer_chunk(FILE *f, Sprite *sprite, Layer **previous_layer, int *current_level); static Layer *ase_file_read_layer_chunk(FILE *f, Sprite *sprite, Layer **previous_layer, int *current_level);
static void ase_file_write_layer_chunk(FILE *f, Layer *layer); static void ase_file_write_layer_chunk(FILE *f, Layer *layer);
static Cel *ase_file_read_cel_chunk(FILE *f, Sprite *sprite, int frpos, int imgtype); static Cel *ase_file_read_cel_chunk(FILE *f, Sprite *sprite, int frame, int imgtype, FileOp *fop, ASE_Header *header);
static void ase_file_write_cel_chunk(FILE *f, Cel *cel, Layer *layer, Sprite *sprite); static void ase_file_write_cel_chunk(FILE *f, Cel *cel, Layer *layer, Sprite *sprite);
static Mask *ase_file_read_mask_chunk(FILE *f); static Mask *ase_file_read_mask_chunk(FILE *f);
static void ase_file_write_mask_chunk(FILE *f, Mask *mask); static void ase_file_write_mask_chunk(FILE *f, Mask *mask);
static int fgetw(FILE *file);
static long fgetl(FILE *file);
static int fputw(int w, FILE *file);
static int fputl(long l, FILE *file);
FileFormat format_ase = FileFormat format_ase =
{ {
"ase", "ase,aseprite",
"ase", "ase,aseprite",
load_ASE, load_ASE,
save_ASE, save_ASE,
FILE_SUPPORT_RGB | FILE_SUPPORT_RGB |
@ -125,45 +126,7 @@ FileFormat format_ase =
FILE_SUPPORT_PATHS_REPOSITORY FILE_SUPPORT_PATHS_REPOSITORY
}; };
static Sprite *load_ASE(const char *filename) static bool load_ASE(FileOp *fop)
{
return ase_file_read(filename);
}
static int save_ASE(Sprite *sprite)
{
return ase_file_write(sprite);
}
static Sprite *ase_file_read(const char *filename)
{
Sprite *sprite = NULL;
FILE *f;
f = fopen(filename, "rb");
if (f) {
sprite = ase_file_read_f(f);
fclose(f);
}
return sprite;
}
static int ase_file_write(Sprite *sprite)
{
int ret = -1;
FILE *f;
f = fopen(sprite->filename, "wb");
if (f) {
ret = ase_file_write_f(f, sprite);
fclose(f);
}
return ret;
}
Sprite *ase_file_read_f(FILE *f)
{ {
Sprite *sprite = NULL; Sprite *sprite = NULL;
ASE_Header header; ASE_Header header;
@ -174,11 +137,17 @@ Sprite *ase_file_read_f(FILE *f)
int chunk_pos; int chunk_pos;
int chunk_size; int chunk_size;
int chunk_type; int chunk_type;
int c, frpos; int c, frame;
FILE *f;
if (ase_file_read_header(f, &header) != 0) { f = fopen(fop->filename, "rb");
console_printf(_("Error reading header\n")); if (!f)
return NULL; return FALSE;
if (!ase_file_read_header(f, &header)) {
fop_error(fop, _("Error reading header\n"));
fclose(f);
return FALSE;
} }
/* create the new sprite */ /* create the new sprite */
@ -186,8 +155,9 @@ Sprite *ase_file_read_f(FILE *f)
header.depth == 16 ? IMAGE_GRAYSCALE: IMAGE_INDEXED, header.depth == 16 ? IMAGE_GRAYSCALE: IMAGE_INDEXED,
header.width, header.height); header.width, header.height);
if (!sprite) { if (!sprite) {
console_printf(_("Error creating sprite with file spec\n")); fop_error(fop, _("Error creating sprite with file spec\n"));
return NULL; fclose(f);
return FALSE;
} }
/* set frames and speed */ /* set frames and speed */
@ -215,14 +185,11 @@ Sprite *ase_file_read_f(FILE *f)
last_layer = sprite->set; last_layer = sprite->set;
current_level = -1; current_level = -1;
/* progress */
add_progress(header.size);
/* read frame by frame to end-of-file */ /* read frame by frame to end-of-file */
for (frpos=0; frpos<sprite->frames; frpos++) { for (frame=0; frame<sprite->frames; frame++) {
/* start frame position */ /* start frame position */
frame_pos = ftell(f); frame_pos = ftell(f);
do_progress(frame_pos); fop_progress(fop, (float)frame_pos / (float)header.size);
/* read frame header */ /* read frame header */
ase_file_read_frame_header(f, &frame_header); ase_file_read_frame_header(f, &frame_header);
@ -231,13 +198,13 @@ Sprite *ase_file_read_f(FILE *f)
if (frame_header.magic == ASE_FILE_FRAME_MAGIC) { if (frame_header.magic == ASE_FILE_FRAME_MAGIC) {
/* use frame-duration field? */ /* use frame-duration field? */
if (frame_header.duration > 0) if (frame_header.duration > 0)
sprite_set_frlen(sprite, frame_header.duration, frpos); sprite_set_frlen(sprite, frame_header.duration, frame);
/* read chunks */ /* read chunks */
for (c=0; c<frame_header.chunks; c++) { for (c=0; c<frame_header.chunks; c++) {
/* start chunk position */ /* start chunk position */
chunk_pos = ftell(f); chunk_pos = ftell(f);
do_progress(chunk_pos); fop_progress(fop, (float)chunk_pos / (float)header.size);
/* read chunk information */ /* read chunk information */
chunk_size = fgetl(f); chunk_size = fgetl(f);
@ -247,7 +214,7 @@ Sprite *ase_file_read_f(FILE *f)
/* only for 8 bpp images */ /* only for 8 bpp images */
case ASE_FILE_CHUNK_FLI_COLOR: case ASE_FILE_CHUNK_FLI_COLOR:
/* console_printf ("Color chunk\n"); */ /* fop_error(fop, "Color chunk\n"); */
if (sprite->imgtype == IMAGE_INDEXED) { if (sprite->imgtype == IMAGE_INDEXED) {
/* TODO fix to read palette-per-frame */ /* TODO fix to read palette-per-frame */
@ -256,11 +223,11 @@ Sprite *ase_file_read_f(FILE *f)
sprite_set_palette(sprite, palette, 0); sprite_set_palette(sprite, palette, 0);
} }
else else
console_printf(_("Warning: was found a color chunk in non-8bpp file\n")); fop_error(fop, _("Warning: was found a color chunk in non-8bpp file\n"));
break; break;
case ASE_FILE_CHUNK_LAYER: { case ASE_FILE_CHUNK_LAYER: {
/* console_printf("Layer chunk\n"); */ /* fop_error(fop, "Layer chunk\n"); */
ase_file_read_layer_chunk(f, sprite, ase_file_read_layer_chunk(f, sprite,
&last_layer, &last_layer,
@ -269,32 +236,32 @@ Sprite *ase_file_read_f(FILE *f)
} }
case ASE_FILE_CHUNK_CEL: { case ASE_FILE_CHUNK_CEL: {
/* console_printf("Cel chunk\n"); */ /* fop_error(fop, "Cel chunk\n"); */
ase_file_read_cel_chunk(f, sprite, frpos, sprite->imgtype); ase_file_read_cel_chunk(f, sprite, frame, sprite->imgtype, fop, &header);
break; break;
} }
case ASE_FILE_CHUNK_MASK: { case ASE_FILE_CHUNK_MASK: {
Mask *mask; Mask *mask;
/* console_printf("Mask chunk\n"); */ /* fop_error(fop, "Mask chunk\n"); */
mask = ase_file_read_mask_chunk(f); mask = ase_file_read_mask_chunk(f);
if (mask) if (mask)
sprite_add_mask(sprite, mask); sprite_add_mask(sprite, mask);
else else
console_printf(_("Warning: error loading a mask chunk\n")); fop_error(fop, _("Warning: error loading a mask chunk\n"));
break; break;
} }
case ASE_FILE_CHUNK_PATH: case ASE_FILE_CHUNK_PATH:
/* console_printf("Path chunk\n"); */ /* fop_error(fop, "Path chunk\n"); */
break; break;
default: default:
console_printf(_("Warning: Unsupported chunk type %d (skipping)\n"), chunk_type); fop_error(fop, _("Warning: Unsupported chunk type %d (skipping)\n"), chunk_type);
break; break;
} }
@ -307,37 +274,38 @@ Sprite *ase_file_read_f(FILE *f)
fseek(f, frame_pos+frame_header.size, SEEK_SET); fseek(f, frame_pos+frame_header.size, SEEK_SET);
} }
del_progress(); fop->sprite = sprite;
fclose(f);
return sprite; return TRUE;
} }
int ase_file_write_f(FILE *f, Sprite *sprite) static bool save_ASE(FileOp *fop)
{ {
Sprite *sprite = fop->sprite;
ASE_Header header; ASE_Header header;
ASE_FrameHeader frame_header; ASE_FrameHeader frame_header;
JLink link; JLink link;
int frpos; int frame;
FILE *f;
f = fopen(fop->filename, "wb");
if (!f)
return FALSE;
/* prepare the header */ /* prepare the header */
ase_file_prepare_header(f, &header, sprite); ase_file_prepare_header(f, &header, sprite);
/* add a new progress bar */
add_progress(sprite->frames);
/* write frame */ /* write frame */
for (frpos=0; frpos<sprite->frames; frpos++) { for (frame=0; frame<sprite->frames; frame++) {
/* progress */
do_progress(frpos);
/* prepare the header */ /* prepare the header */
ase_file_prepare_frame_header(f, &frame_header); ase_file_prepare_frame_header(f, &frame_header);
/* frame duration */ /* frame duration */
frame_header.duration = sprite_get_frlen(sprite, frpos); frame_header.duration = sprite_get_frlen(sprite, frame);
/* write extra chunks in the first frame */ /* write extra chunks in the first frame */
if (frpos == 0) { if (frame == 0) {
/* color chunk */ /* color chunk */
if (sprite->imgtype == IMAGE_INDEXED) if (sprite->imgtype == IMAGE_INDEXED)
/* TODO fix this to write palette per-frame */ /* TODO fix this to write palette per-frame */
@ -353,27 +321,30 @@ int ase_file_write_f(FILE *f, Sprite *sprite)
} }
/* write cel chunks */ /* write cel chunks */
ase_file_write_cels(f, sprite, sprite->set, frpos); ase_file_write_cels(f, sprite, sprite->set, frame);
/* write the frame header */ /* write the frame header */
ase_file_write_frame_header(f, &frame_header); ase_file_write_frame_header(f, &frame_header);
}
del_progress(); /* progress */
if (sprite->frames > 1)
fop_progress(fop, (float)(frame+1) / (float)(sprite->frames));
}
/* write the header */ /* write the header */
ase_file_write_header(f, &header); ase_file_write_header(f, &header);
return 0; fclose(f);
return TRUE;
} }
static int ase_file_read_header(FILE *f, ASE_Header *header) static bool ase_file_read_header(FILE *f, ASE_Header *header)
{ {
header->pos = ftell(f); header->pos = ftell(f);
header->size = fgetl(f); header->size = fgetl(f);
header->magic = fgetw(f); header->magic = fgetw(f);
if (header->magic != ASE_FILE_MAGIC) if (header->magic != ASE_FILE_MAGIC)
return -1; return FALSE;
header->frames = fgetw(f); header->frames = fgetw(f);
header->width = fgetw(f); header->width = fgetw(f);
@ -389,7 +360,7 @@ static int ase_file_read_header(FILE *f, ASE_Header *header)
header->bgcolor[3] = fgetc(f); header->bgcolor[3] = fgetc(f);
fseek(f, header->pos+128, SEEK_SET); fseek(f, header->pos+128, SEEK_SET);
return 0; return TRUE;
} }
static void ase_file_prepare_header(FILE *f, ASE_Header *header, Sprite *sprite) static void ase_file_prepare_header(FILE *f, ASE_Header *header, Sprite *sprite)
@ -512,14 +483,14 @@ static void ase_file_write_layers(FILE *f, Layer *layer)
} }
} }
static void ase_file_write_cels(FILE *f, Sprite *sprite, Layer *layer, int frpos) static void ase_file_write_cels(FILE *f, Sprite *sprite, Layer *layer, int frame)
{ {
if (layer_is_image(layer)) { if (layer_is_image(layer)) {
Cel *cel = layer_get_cel(layer, frpos); Cel *cel = layer_get_cel(layer, frame);
if (cel) { if (cel) {
/* console_printf("New cel in frpos %d, in layer %d\n", */ /* fop_error(fop, "New cel in frame %d, in layer %d\n", */
/* frpos, sprite_layer2index(sprite, layer)); */ /* frame, sprite_layer2index(sprite, layer)); */
ase_file_write_cel_chunk(f, cel, layer, sprite); ase_file_write_cel_chunk(f, cel, layer, sprite);
} }
@ -528,7 +499,7 @@ static void ase_file_write_cels(FILE *f, Sprite *sprite, Layer *layer, int frpos
if (layer_is_set(layer)) { if (layer_is_set(layer)) {
JLink link; JLink link;
JI_LIST_FOR_EACH(layer->layers, link) JI_LIST_FOR_EACH(layer->layers, link)
ase_file_write_cels(f, sprite, link->data, frpos); ase_file_write_cels(f, sprite, link->data, frame);
} }
} }
@ -731,10 +702,10 @@ static void ase_file_write_layer_chunk(FILE *f, Layer *layer)
ase_file_write_close_chunk(f); ase_file_write_close_chunk(f);
/* console_printf("Layer name \"%s\" child level: %d\n", layer->name, child_level); */ /* fop_error(fop, "Layer name \"%s\" child level: %d\n", layer->name, child_level); */
} }
static Cel *ase_file_read_cel_chunk(FILE *f, Sprite *sprite, int frpos, int imgtype) static Cel *ase_file_read_cel_chunk(FILE *f, Sprite *sprite, int frame, int imgtype, FileOp *fop, ASE_Header *header)
{ {
Cel *cel; Cel *cel;
/* read chunk data */ /* read chunk data */
@ -749,14 +720,13 @@ static Cel *ase_file_read_cel_chunk(FILE *f, Sprite *sprite, int frpos, int imgt
layer = sprite_index2layer(sprite, layer_index); layer = sprite_index2layer(sprite, layer_index);
if (!layer) { if (!layer) {
console_printf(_("Frame %d didn't found layer with index %d\n"), fop_error(fop, _("Frame %d didn't found layer with index %d\n"),
frpos, layer_index); frame, layer_index);
return NULL; return NULL;
} }
/* console_printf("Layer found: %d -> %s\n", layer_index, layer->name); */
/* create the new frame */ /* create the new frame */
cel = cel_new(frpos, 0); cel = cel_new(frame, 0);
cel_set_position(cel, x, y); cel_set_position(cel, x, y);
cel_set_opacity(cel, opacity); cel_set_opacity(cel, opacity);
@ -789,8 +759,8 @@ static Cel *ase_file_read_cel_chunk(FILE *f, Sprite *sprite, int frpos, int imgt
a = fgetc(f); a = fgetc(f);
image->method->putpixel(image, x, y, _rgba(r, g, b, a)); image->method->putpixel(image, x, y, _rgba(r, g, b, a));
} }
fop_progress(fop, (float)ftell(f) / (float)header->size);
} }
do_progress(ftell(f));
break; break;
case IMAGE_GRAYSCALE: case IMAGE_GRAYSCALE:
@ -800,16 +770,17 @@ static Cel *ase_file_read_cel_chunk(FILE *f, Sprite *sprite, int frpos, int imgt
a = fgetc(f); a = fgetc(f);
image->method->putpixel(image, x, y, _graya(k, a)); image->method->putpixel(image, x, y, _graya(k, a));
} }
fop_progress(fop, (float)ftell(f) / (float)header->size);
} }
do_progress(ftell(f));
break; break;
case IMAGE_INDEXED: case IMAGE_INDEXED:
for (y=0; y<image->h; y++) { for (y=0; y<image->h; y++) {
for (x=0; x<image->w; x++) for (x=0; x<image->w; x++)
image->method->putpixel(image, x, y, fgetc(f)); image->method->putpixel(image, x, y, fgetc(f));
fop_progress(fop, (float)ftell(f) / (float)header->size);
} }
do_progress(ftell(f));
break; break;
} }
@ -820,8 +791,8 @@ static Cel *ase_file_read_cel_chunk(FILE *f, Sprite *sprite, int frpos, int imgt
case ASE_FILE_LINK_CEL: { case ASE_FILE_LINK_CEL: {
/* read link position */ /* read link position */
int link_frpos = fgetw(f); int link_frame = fgetw(f);
Cel *link = layer_get_cel(layer, link_frpos); Cel *link = layer_get_cel(layer, link_frame);
if (link) if (link)
cel->image = link->image; cel->image = link->image;
@ -868,9 +839,6 @@ static void ase_file_write_cel_chunk(FILE *f, Cel *cel, Layer *layer, Sprite *sp
fputw(image->w, f); fputw(image->w, f);
fputw(image->h, f); fputw(image->h, f);
/* TODO */
/* add_progress(image->h); */
/* pixel data */ /* pixel data */
switch (image->imgtype) { switch (image->imgtype) {
@ -883,7 +851,6 @@ static void ase_file_write_cel_chunk(FILE *f, Cel *cel, Layer *layer, Sprite *sp
fputc(_rgba_getb(c), f); fputc(_rgba_getb(c), f);
fputc(_rgba_geta(c), f); fputc(_rgba_geta(c), f);
} }
/* do_progress(y); */
} }
break; break;
@ -894,7 +861,6 @@ static void ase_file_write_cel_chunk(FILE *f, Cel *cel, Layer *layer, Sprite *sp
fputc(_graya_getk(c), f); fputc(_graya_getk(c), f);
fputc(_graya_geta(c), f); fputc(_graya_geta(c), f);
} }
/* do_progress(y); */
} }
break; break;
@ -902,13 +868,9 @@ static void ase_file_write_cel_chunk(FILE *f, Cel *cel, Layer *layer, Sprite *sp
for (y=0; y<image->h; y++) { for (y=0; y<image->h; y++) {
for (x=0; x<image->w; x++) for (x=0; x<image->w; x++)
fputc(image->method->getpixel(image, x, y), f); fputc(image->method->getpixel(image, x, y), f);
/* do_progress(y); */
} }
break; break;
} }
/* del_progress(); */
} }
else { else {
/* width and height */ /* width and height */
@ -993,7 +955,7 @@ static void ase_file_write_mask_chunk(FILE *f, Mask *mask)
} }
/* returns a word (16 bits) */ /* returns a word (16 bits) */
int fgetw(FILE *file) static int fgetw(FILE *file)
{ {
int b1, b2; int b1, b2;
@ -1010,7 +972,7 @@ int fgetw(FILE *file)
} }
/* returns a dword (32 bits) */ /* returns a dword (32 bits) */
long fgetl(FILE *file) static long fgetl(FILE *file)
{ {
int b1, b2, b3, b4; int b1, b2, b3, b4;
@ -1035,7 +997,7 @@ long fgetl(FILE *file)
} }
/* returns 0 in success or -1 in error */ /* returns 0 in success or -1 in error */
int fputw(int w, FILE *file) static int fputw(int w, FILE *file)
{ {
int b1, b2; int b1, b2;
@ -1051,7 +1013,7 @@ int fputw(int w, FILE *file)
} }
/* returns 0 in success or -1 in error */ /* returns 0 in success or -1 in error */
int fputl(long l, FILE *file) static int fputl(long l, FILE *file)
{ {
int b1, b2, b3, b4; int b1, b2, b3, b4;

View File

@ -25,14 +25,13 @@
#include <allegro/color.h> #include <allegro/color.h>
#include <allegro/file.h> #include <allegro/file.h>
#include "console/console.h"
#include "file/file.h" #include "file/file.h"
#include "raster/raster.h" #include "raster/raster.h"
#endif #endif
static Sprite *load_BMP(const char *filename); static bool load_BMP(FileOp *fop);
static int save_BMP(Sprite *sprite); static bool save_BMP(FileOp *fop);
FileFormat format_bmp = FileFormat format_bmp =
{ {
@ -162,7 +161,7 @@ static int read_os2_bminfoheader(PACKFILE *f, BITMAPINFOHEADER *infoheader)
/* read_bmicolors: /* read_bmicolors:
* Loads the color palette for 1,4,8 bit formats. * Loads the color palette for 1,4,8 bit formats.
*/ */
static void read_bmicolors(int ncols, PACKFILE *f,int win_flag) static void read_bmicolors(FileOp *fop, int ncols, PACKFILE *f,int win_flag)
{ {
int i, r, g, b; int i, r, g, b;
@ -170,7 +169,7 @@ static void read_bmicolors(int ncols, PACKFILE *f,int win_flag)
b = pack_getc(f) / 4; b = pack_getc(f) / 4;
g = pack_getc(f) / 4; g = pack_getc(f) / 4;
r = pack_getc(f) / 4; r = pack_getc(f) / 4;
file_sequence_set_color(i, r, g, b); fop_sequence_set_color(fop, i, r, g, b);
if (win_flag) if (win_flag)
pack_getc(f); pack_getc(f);
} }
@ -280,7 +279,7 @@ static void read_24bit_line(int length, PACKFILE *f, Image *image, int line)
/* read_image: /* read_image:
* For reading the noncompressed BMP image format. * For reading the noncompressed BMP image format.
*/ */
static void read_image(PACKFILE *f, Image *image, AL_CONST BITMAPINFOHEADER *infoheader) static void read_image(PACKFILE *f, Image *image, AL_CONST BITMAPINFOHEADER *infoheader, FileOp *fop)
{ {
int i, line; int i, line;
@ -306,8 +305,7 @@ static void read_image(PACKFILE *f, Image *image, AL_CONST BITMAPINFOHEADER *inf
break; break;
} }
if (infoheader->biHeight > 1) fop_progress(fop, (float)(i+1) / (float)(infoheader->biHeight));
do_progress(100 * i / (infoheader->biHeight-1));
} }
} }
@ -500,27 +498,23 @@ static void read_bitfields_image(PACKFILE *f, Image *image, int bpp, BITMAPINFOH
} }
} }
static Sprite *load_BMP(const char *filename) static bool load_BMP(FileOp *fop)
{ {
BITMAPFILEHEADER fileheader; BITMAPFILEHEADER fileheader;
BITMAPINFOHEADER infoheader; BITMAPINFOHEADER infoheader;
Image *image; Image *image;
Sprite *sprite;
PACKFILE *f; PACKFILE *f;
int ncol; int ncol;
unsigned long biSize; unsigned long biSize;
int type, bpp = 0; int type, bpp = 0;
f = pack_fopen(filename, F_READ); f = pack_fopen(fop->filename, F_READ);
if (!f) { if (!f)
if (!file_sequence_sprite()) return FALSE;
console_printf(_("Error opening file.\n"));
return NULL;
}
if (read_bmfileheader(f, &fileheader) != 0) { if (read_bmfileheader(f, &fileheader) != 0) {
pack_fclose(f); pack_fclose(f);
return NULL; return FALSE;
} }
biSize = pack_igetl(f); biSize = pack_igetl(f);
@ -528,28 +522,28 @@ static Sprite *load_BMP(const char *filename)
if (biSize == WININFOHEADERSIZE) { if (biSize == WININFOHEADERSIZE) {
if (read_win_bminfoheader(f, &infoheader) != 0) { if (read_win_bminfoheader(f, &infoheader) != 0) {
pack_fclose(f); pack_fclose(f);
return NULL; return FALSE;
} }
/* compute number of colors recorded */ /* compute number of colors recorded */
ncol = (fileheader.bfOffBits - 54) / 4; ncol = (fileheader.bfOffBits - 54) / 4;
if (infoheader.biCompression != BI_BITFIELDS) if (infoheader.biCompression != BI_BITFIELDS)
read_bmicolors(ncol, f, 1); read_bmicolors(fop, ncol, f, 1);
} }
else if (biSize == OS2INFOHEADERSIZE) { else if (biSize == OS2INFOHEADERSIZE) {
if (read_os2_bminfoheader(f, &infoheader) != 0) { if (read_os2_bminfoheader(f, &infoheader) != 0) {
pack_fclose(f); pack_fclose(f);
return NULL; return FALSE;
} }
/* compute number of colors recorded */ /* compute number of colors recorded */
ncol = (fileheader.bfOffBits - 26) / 3; ncol = (fileheader.bfOffBits - 26) / 3;
if (infoheader.biCompression != BI_BITFIELDS) if (infoheader.biCompression != BI_BITFIELDS)
read_bmicolors(ncol, f, 0); read_bmicolors(fop, ncol, f, 0);
} }
else { else {
pack_fclose(f); pack_fclose(f);
return NULL; return FALSE;
} }
if ((infoheader.biBitCount == 24) || (infoheader.biBitCount == 16)) if ((infoheader.biBitCount == 24) || (infoheader.biBitCount == 16))
@ -573,16 +567,16 @@ static Sprite *load_BMP(const char *filename)
else { else {
/* Unrecognised bit masks/depth */ /* Unrecognised bit masks/depth */
pack_fclose(f); pack_fclose(f);
return NULL; return FALSE;
} }
} }
image = file_sequence_image(type, image = fop_sequence_image(fop, type,
infoheader.biWidth, infoheader.biWidth,
infoheader.biHeight); infoheader.biHeight);
if (!image) { if (!image) {
pack_fclose(f); pack_fclose(f);
return NULL; return FALSE;
} }
if (type == IMAGE_RGB) if (type == IMAGE_RGB)
@ -590,12 +584,10 @@ static Sprite *load_BMP(const char *filename)
else else
image_clear(image, 0); image_clear(image, 0);
sprite = file_sequence_sprite();
switch (infoheader.biCompression) { switch (infoheader.biCompression) {
case BI_RGB: case BI_RGB:
read_image(f, image, &infoheader); read_image(f, image, &infoheader, fop);
break; break;
case BI_RLE8: case BI_RLE8:
@ -611,42 +603,41 @@ static Sprite *load_BMP(const char *filename)
break; break;
default: default:
sprite = NULL; pack_fclose(f);
return FALSE;
} }
pack_fclose(f); pack_fclose(f);
return sprite; return TRUE;
} }
static int save_BMP(Sprite *sprite) static bool save_BMP(FileOp *fop)
{ {
Image *image; Image *image = fop->seq.image;
PACKFILE *f; PACKFILE *f;
int bfSize; int bfSize;
int biSizeImage; int biSizeImage;
int bpp = (sprite->imgtype == IMAGE_RGB) ? 24 : 8; int bpp = (image->imgtype == IMAGE_RGB) ? 24 : 8;
int filler = 3 - ((sprite->w*(bpp/8)-1) & 3); int filler = 3 - ((image->w*(bpp/8)-1) & 3);
int c, i, j, r, g, b; int c, i, j, r, g, b;
if (bpp == 8) { if (bpp == 8) {
biSizeImage = (sprite->w + filler) * sprite->h; biSizeImage = (image->w + filler) * image->h;
bfSize = (54 /* header */ bfSize = (54 /* header */
+ 256*4 /* palette */ + 256*4 /* palette */
+ biSizeImage); /* image data */ + biSizeImage); /* image data */
} }
else { else {
biSizeImage = (sprite->w*3 + filler) * sprite->h; biSizeImage = (image->w*3 + filler) * image->h;
bfSize = 54 + biSizeImage; /* header + image data */ bfSize = 54 + biSizeImage; /* header + image data */
} }
f = pack_fopen(sprite->filename, F_WRITE); f = pack_fopen(fop->filename, F_WRITE);
if (!f) { if (!f) {
console_printf(_("Error creating file.\n")); fop_error(fop, _("Error creating file.\n"));
return -1; return FALSE;
} }
image = file_sequence_image_to_save();
*allegro_errno = 0; *allegro_errno = 0;
/* file_header */ /* file_header */
@ -677,7 +668,7 @@ static int save_BMP(Sprite *sprite)
/* palette */ /* palette */
for (i=0; i<256; i++) { for (i=0; i<256; i++) {
file_sequence_get_color(i, &r, &g, &b); fop_sequence_get_color(fop, i, &r, &g, &b);
pack_putc(_rgb_scale_6[b], f); pack_putc(_rgb_scale_6[b], f);
pack_putc(_rgb_scale_6[g], f); pack_putc(_rgb_scale_6[g], f);
pack_putc(_rgb_scale_6[r], f); pack_putc(_rgb_scale_6[r], f);
@ -709,16 +700,15 @@ static int save_BMP(Sprite *sprite)
for (j=0; j<filler; j++) for (j=0; j<filler; j++)
pack_putc(0, f); pack_putc(0, f);
if (image->h > 1) fop_progress(fop, (float)(image->h-i) / (float)image->h);
do_progress(100 * (image->h-1-i) / (image->h-1));
} }
pack_fclose(f); pack_fclose(f);
if (*allegro_errno) { if (*allegro_errno) {
console_printf(_("Error writing bytes.\n")); fop_error(fop, _("Error writing bytes.\n"));
return -1; return FALSE;
} }
else else
return 0; return TRUE;
} }

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,9 @@
#ifndef FILE_H #ifndef FILE_H
#define FILE_H #define FILE_H
#include "jinete/jbase.h"
#include <allegro/color.h>
#define FILE_SUPPORT_RGB (1<<0) #define FILE_SUPPORT_RGB (1<<0)
#define FILE_SUPPORT_RGBA (1<<1) #define FILE_SUPPORT_RGBA (1<<1)
#define FILE_SUPPORT_GRAY (1<<2) #define FILE_SUPPORT_GRAY (1<<2)
@ -31,8 +34,18 @@
#define FILE_SUPPORT_MASKS_REPOSITORY (1<<9) #define FILE_SUPPORT_MASKS_REPOSITORY (1<<9)
#define FILE_SUPPORT_PATHS_REPOSITORY (1<<10) #define FILE_SUPPORT_PATHS_REPOSITORY (1<<10)
typedef struct Sprite *(*FileLoad)(const char *filename); struct Image;
typedef int (*FileSave)(struct Sprite *sprite); struct Cel;
struct Layer;
struct Sprite;
struct FileFormat;
struct FileOp;
/* file operations */
typedef enum { FileOpLoad, FileOpSave } FileOpType;
typedef bool (*FileLoad)(struct FileOp *fop);
typedef bool (*FileSave)(struct FileOp *fop);
/* load or/and save a file format */ /* load or/and save a file format */
typedef struct FileFormat typedef struct FileFormat
@ -44,22 +57,62 @@ typedef struct FileFormat
int flags; int flags;
} FileFormat; } FileFormat;
/* routines to handle sequences */ /* structure to load & save files */
typedef struct FileOp
{
FileOpType type; /* operation type: 0=load, 1=save */
FileFormat *format;
struct Sprite *sprite; /* loaded sprite/sprite to be saved */
char *filename; /* file-name to load/save */
void file_sequence_set_color(int index, int r, int g, int b); /* shared fields between threads */
void file_sequence_get_color(int index, int *r, int *g, int *b); JMutex mutex; /* mutex to access to the next two fields */
struct Image *file_sequence_image(int imgtype, int w, int h); float progress; /* progress (1.0 is ready) */
struct Sprite *file_sequence_sprite(void); char *error; /* error string */
struct Image *file_sequence_image_to_save(void); bool done : 1; /* true if the operation finished */
bool stop : 1; /* force the break of the operation */
/* data for sequences */
struct {
JList filename_list; /* all file names to load/save */
RGB *palette; /* palette of the sequence */
struct Image *image; /* image to be saved/loaded */
/* for the progress bar */
float progress_offset; /* progress offset from the current frame */
float progress_fraction; /* progress fraction for one frame */
/* to load sequences */
int frame;
struct Layer *layer;
struct Cel *last_cel;
} seq;
} FileOp;
/* available extensions for each load/save operation */ /* available extensions for each load/save operation */
const char *get_readable_extensions(void); void get_readable_extensions(char *buf, int size);
const char *get_writable_extensions(void); void get_writable_extensions(char *buf, int size);
/* mainly routines to load/save images */ /* high-level routines to load/save sprites */
struct Sprite *sprite_load(const char *filename); struct Sprite *sprite_load(const char *filename);
int sprite_save(struct Sprite *sprite); int sprite_save(struct Sprite *sprite);
/* low-level routines to load/save sprites */
FileOp *fop_to_load_sprite(const char *filename);
FileOp *fop_to_save_sprite(struct Sprite *sprite);
void fop_operate(FileOp *fop);
void fop_free(FileOp *fop);
void fop_sequence_set_color(FileOp *fop, int index, int r, int g, int b);
void fop_sequence_get_color(FileOp *fop, int index, int *r, int *g, int *b);
struct Image *fop_sequence_image(FileOp *fi, int imgtype, int w, int h);
void fop_error(FileOp *fop, const char *error, ...);
void fop_progress(FileOp *fop, float progress);
float fop_get_progress(FileOp *fop);
bool fop_is_done(FileOp *fop);
bool fop_is_stop(FileOp *fop);
#endif /* FILE_H */ #endif /* FILE_H */

View File

@ -23,7 +23,6 @@
#include <allegro/color.h> #include <allegro/color.h>
#include <stdio.h> #include <stdio.h>
#include "console/console.h"
#include "file/file.h" #include "file/file.h"
#include "modules/palette.h" #include "modules/palette.h"
#include "raster/raster.h" #include "raster/raster.h"
@ -33,8 +32,8 @@
#endif #endif
static Sprite *load_FLI(const char *filename); static bool load_FLI(FileOp *fop);
static int save_FLI(Sprite *sprite); static bool save_FLI(FileOp *fop);
static int get_time_precision(Sprite *sprite); static int get_time_precision(Sprite *sprite);
@ -50,7 +49,7 @@ FileFormat format_fli =
}; };
/* loads a FLI/FLC file */ /* loads a FLI/FLC file */
static Sprite *load_FLI(const char *filename) static bool load_FLI(FileOp *fop)
{ {
#define SETPAL() \ #define SETPAL() \
do { \ do { \
@ -77,9 +76,9 @@ static Sprite *load_FLI(const char *filename)
FILE *f; FILE *f;
/* open the file to read in binary mode */ /* open the file to read in binary mode */
f = fopen(filename, "rb"); f = fopen(fop->filename, "rb");
if (!f) if (!f)
return NULL; return FALSE;
fli_read_header(f, &fli_header); fli_read_header(f, &fli_header);
fseek(f, 128, SEEK_SET); fseek(f, 128, SEEK_SET);
@ -92,11 +91,11 @@ static Sprite *load_FLI(const char *filename)
bmp = image_new(IMAGE_INDEXED, w, h); bmp = image_new(IMAGE_INDEXED, w, h);
old = image_new(IMAGE_INDEXED, w, h); old = image_new(IMAGE_INDEXED, w, h);
if ((!bmp) || (!old)) { if ((!bmp) || (!old)) {
console_printf(_("Not enough memory for temporary bitmaps.\n")); fop_error(fop, _("Not enough memory for temporary bitmaps.\n"));
if (bmp) image_free(bmp); if (bmp) image_free(bmp);
if (old) image_free(old); if (old) image_free(old);
fclose(f); fclose(f);
return NULL; return FALSE;
} }
/* create the image */ /* create the image */
@ -110,8 +109,6 @@ static Sprite *load_FLI(const char *filename)
sprite_set_speed(sprite, fli_header.speed); sprite_set_speed(sprite, fli_header.speed);
/* write frame by frame */ /* write frame by frame */
add_progress(100);
inc_frpos_out = FALSE; inc_frpos_out = FALSE;
for (frpos_in=frpos_out=0; for (frpos_in=frpos_out=0;
@ -156,15 +153,12 @@ static Sprite *load_FLI(const char *filename)
memcpy(omap, cmap, 768); memcpy(omap, cmap, 768);
/* update progress */ /* update progress */
if (sprite->frames > 1) fop_progress(fop, (float)(frpos_in+1) / (float)(sprite->frames));
do_progress(100 * (frpos_in) / (sprite->frames-1));
} }
/* update sprites frames */ /* update sprites frames */
sprite_set_frames(sprite, frpos_out+1); sprite_set_frames(sprite, frpos_out+1);
del_progress();
/* close the file */ /* close the file */
fclose(f); fclose(f);
@ -172,12 +166,14 @@ static Sprite *load_FLI(const char *filename)
image_free(bmp); image_free(bmp);
image_free(old); image_free(old);
return sprite; fop->sprite = sprite;
return TRUE;
} }
/* saves a FLC file */ /* saves a FLC file */
static int save_FLI(Sprite *sprite) static bool save_FLI(FileOp *fop)
{ {
Sprite *sprite = fop->sprite;
unsigned char cmap[768]; unsigned char cmap[768];
unsigned char omap[768]; unsigned char omap[768];
s_fli_header fli_header; s_fli_header fli_header;
@ -207,9 +203,9 @@ static int save_FLI(Sprite *sprite)
fli_header.oframe1 = fli_header.oframe2 = 0; fli_header.oframe1 = fli_header.oframe2 = 0;
/* open the file to write in binary mode */ /* open the file to write in binary mode */
f = fopen(sprite->filename, "wb"); f = fopen(fop->filename, "wb");
if (!f) if (!f)
return -1; return FALSE;
fseek(f, 128, SEEK_SET); fseek(f, 128, SEEK_SET);
@ -217,16 +213,14 @@ static int save_FLI(Sprite *sprite)
bmp = image_new(IMAGE_INDEXED, sprite->w, sprite->h); bmp = image_new(IMAGE_INDEXED, sprite->w, sprite->h);
old = image_new(IMAGE_INDEXED, sprite->w, sprite->h); old = image_new(IMAGE_INDEXED, sprite->w, sprite->h);
if ((!bmp) || (!old)) { if ((!bmp) || (!old)) {
console_printf(_("Not enough memory for temporary bitmaps.\n")); fop_error(fop, _("Not enough memory for temporary bitmaps.\n"));
if (bmp) image_free(bmp); if (bmp) image_free(bmp);
if (old) image_free(old); if (old) image_free(old);
fclose(f); fclose(f);
return -1; return FALSE;
} }
/* write frame by frame */ /* write frame by frame */
add_progress(100);
for (frpos=0; for (frpos=0;
frpos<sprite->frames; frpos<sprite->frames;
frpos++) { frpos++) {
@ -262,12 +256,9 @@ static int save_FLI(Sprite *sprite)
} }
/* update progress */ /* update progress */
if (sprite->frames > 1) fop_progress(fop, (float)(frpos+1) / (float)(sprite->frames));
do_progress(100 * (frpos) / (sprite->frames-1));
} }
del_progress();
/* write the header and close the file */ /* write the header and close the file */
fli_write_header(f, &fli_header); fli_write_header(f, &fli_header);
fclose(f); fclose(f);
@ -276,7 +267,7 @@ static int save_FLI(Sprite *sprite)
image_free(bmp); image_free(bmp);
image_free(old); image_free(old);
return 0; return TRUE;
} }
static int get_time_precision(Sprite *sprite) static int get_time_precision(Sprite *sprite)

View File

@ -86,7 +86,8 @@ static void lzw_write_pixel (int pos, int c, unsigned char *data)
*/ */
int int
gif_save_animation (const char *filename, GIF_ANIMATION *gif, gif_save_animation (const char *filename, GIF_ANIMATION *gif,
void (*progress) (int)) void (*progress) (void *, float),
void *dp)
{ {
int frame; int frame;
int i, j; int i, j;
@ -125,7 +126,7 @@ gif_save_animation (const char *filename, GIF_ANIMATION *gif,
pack_putc (0, file); pack_putc (0, file);
} }
progress(0); progress(dp, 0.0f);
for (frame = 0; frame < gif->frames_count; frame++) for (frame = 0; frame < gif->frames_count; frame++)
{ {
int w = gif->frames[frame].w; int w = gif->frames[frame].w;
@ -169,9 +170,9 @@ gif_save_animation (const char *filename, GIF_ANIMATION *gif,
pack_putc (0x00, file); /* Terminator. */ pack_putc (0x00, file); /* Terminator. */
progress(100 * frame / gif->frames_count); progress(dp, (float)frame / (float)gif->frames_count);
} }
progress(100); progress(dp, 1.0f);
pack_putc (0x3b, file); /* Trailer. */ pack_putc (0x3b, file); /* Trailer. */
@ -205,7 +206,7 @@ deinterlace (unsigned char *bmp, int w, int h)
} }
static GIF_ANIMATION * static GIF_ANIMATION *
load_object (PACKFILE * file, long size, void (*progress) (int)) load_object (PACKFILE * file, long size, void (*progress) (void *, float), void *dp)
{ {
int version; int version;
unsigned char *bmp = NULL; unsigned char *bmp = NULL;
@ -252,11 +253,11 @@ load_object (PACKFILE * file, long size, void (*progress) (int))
have_global_palette = 1; have_global_palette = 1;
} }
progress(0); progress(dp, 0.0f);
do do
{ {
i = pack_getc (file); i = pack_getc (file);
progress(100 * i / size); progress(dp, (float)i / (float)size);
switch (i) switch (i)
{ {
@ -361,7 +362,7 @@ load_object (PACKFILE * file, long size, void (*progress) (int))
case 0x3b: case 0x3b:
/* GIF Trailer. */ /* GIF Trailer. */
pack_fclose (file); pack_fclose (file);
progress(100); progress(dp, 1.0f);
return gif; return gif;
} }
} }
@ -388,7 +389,7 @@ load_object (PACKFILE * file, long size, void (*progress) (int))
* All bitmaps will have a color depth of 8. * All bitmaps will have a color depth of 8.
*/ */
GIF_ANIMATION * GIF_ANIMATION *
gif_load_animation (const char *filename, void (*progress) (int)) gif_load_animation (const char *filename, void (*progress) (void *, float), void *dp)
{ {
PACKFILE *file; PACKFILE *file;
GIF_ANIMATION *gif = NULL; GIF_ANIMATION *gif = NULL;
@ -402,7 +403,7 @@ gif_load_animation (const char *filename, void (*progress) (int))
file = pack_fopen (filename, "r"); file = pack_fopen (filename, "r");
if (file) if (file)
gif = load_object (file, size, progress); gif = load_object (file, size, progress, dp);
return gif; return gif;
} }

View File

@ -37,9 +37,11 @@ struct GIF_FRAME
GIF_ANIMATION *gif_create_animation(int frames_count); GIF_ANIMATION *gif_create_animation(int frames_count);
void gif_destroy_animation(GIF_ANIMATION *gif); void gif_destroy_animation(GIF_ANIMATION *gif);
int gif_save_animation(const char *filename, GIF_ANIMATION *gif, int gif_save_animation(const char *filename, GIF_ANIMATION *gif,
void (*progress) (int)); void (*progress) (void *, float),
void *dp);
GIF_ANIMATION *gif_load_animation(const char *filename, GIF_ANIMATION *gif_load_animation(const char *filename,
void (*progress) (int)); void (*progress) (void *, float),
void *dp);
#endif #endif

View File

@ -31,7 +31,6 @@
#include "jinete/jbase.h" #include "jinete/jbase.h"
#include "console/console.h"
#include "file/file.h" #include "file/file.h"
#include "modules/palette.h" #include "modules/palette.h"
#include "raster/raster.h" #include "raster/raster.h"
@ -43,8 +42,8 @@
#endif #endif
static Sprite *load_GIF(const char *filename); static bool load_GIF(FileOp *fop);
static int save_GIF(Sprite *sprite); static bool save_GIF(FileOp *fop);
FileFormat format_gif = FileFormat format_gif =
{ {
@ -78,7 +77,7 @@ static void render_gif_frame(GIF_FRAME *frame, Image *image,
/* load_GIF: /* load_GIF:
* Loads a GIF into a sprite. * Loads a GIF into a sprite.
*/ */
static Sprite *load_GIF(const char *filename) static bool load_GIF(FileOp *fop)
{ {
GIF_ANIMATION *gif = NULL; GIF_ANIMATION *gif = NULL;
Sprite *sprite = NULL; Sprite *sprite = NULL;
@ -90,13 +89,10 @@ static Sprite *load_GIF(const char *filename)
PALETTE opal, npal; PALETTE opal, npal;
int i, c; int i, c;
add_progress(100); gif = gif_load_animation(fop->filename, fop_progress, fop);
gif = gif_load_animation(filename, do_progress);
del_progress();
if (!gif) { if (!gif) {
console_printf(_("Error loading GIF file.\n")); fop_error(fop, _("Error loading GIF file.\n"));
return NULL; return FALSE;
} }
current_image = image_new(IMAGE_INDEXED, gif->width, gif->height); current_image = image_new(IMAGE_INDEXED, gif->width, gif->height);
@ -106,16 +102,16 @@ static Sprite *load_GIF(const char *filename)
if (current_image_old) image_free(current_image_old); if (current_image_old) image_free(current_image_old);
gif_destroy_animation(gif); gif_destroy_animation(gif);
console_printf(_("Error creating temporary image.\n")); fop_error(fop, _("Error creating temporary image.\n"));
return NULL; return FALSE;
} }
sprite = sprite_new(IMAGE_INDEXED, gif->width, gif->height); sprite = sprite_new(IMAGE_INDEXED, gif->width, gif->height);
if (!sprite) { if (!sprite) {
gif_destroy_animation(gif); gif_destroy_animation(gif);
image_free(current_image); image_free(current_image);
console_printf(_("Error creating sprite.\n")); fop_error(fop, _("Error creating sprite.\n"));
return NULL; return FALSE;
} }
sprite_set_frames(sprite, gif->frames_count); sprite_set_frames(sprite, gif->frames_count);
@ -125,8 +121,8 @@ static Sprite *load_GIF(const char *filename)
gif_destroy_animation(gif); gif_destroy_animation(gif);
image_free(current_image); image_free(current_image);
sprite_free(sprite); sprite_free(sprite);
console_printf(_("Error creating main layer.\n")); fop_error(fop, _("Error creating main layer.\n"));
return NULL; return FALSE;
} }
layer_add_layer(sprite->set, layer); layer_add_layer(sprite->set, layer);
@ -180,7 +176,7 @@ static Sprite *load_GIF(const char *filename)
if (!cel || !image) { if (!cel || !image) {
if (cel) cel_free(cel); if (cel) cel_free(cel);
if (image) image_free(image); if (image) image_free(image);
console_printf(_("Error creating cel %d.\n"), i); fop_error(fop, _("Error creating cel %d.\n"), i);
break; break;
} }
@ -260,7 +256,8 @@ static Sprite *load_GIF(const char *filename)
image_free(current_image); image_free(current_image);
image_free(current_image_old); image_free(current_image_old);
return sprite; fop->sprite = sprite;
return TRUE;
} }
/* TODO: find the colors that are used and resort the palette */ /* TODO: find the colors that are used and resort the palette */
@ -283,8 +280,9 @@ static int max_used_index(Image *image)
* TODO: transparent index is not stored. And reserve a single color * TODO: transparent index is not stored. And reserve a single color
* as transparent. * as transparent.
*/ */
static int save_GIF(Sprite *sprite) static bool save_GIF(FileOp *fop)
{ {
Sprite *sprite = fop->sprite;
GIF_ANIMATION *gif; GIF_ANIMATION *gif;
int x1, y1, x2, y2; int x1, y1, x2, y2;
int u1, v1, u2, v2; int u1, v1, u2, v2;
@ -300,16 +298,16 @@ static int save_GIF(Sprite *sprite)
if (!bmp || !old) { if (!bmp || !old) {
if (bmp) image_free(bmp); if (bmp) image_free(bmp);
if (old) image_free(old); if (old) image_free(old);
console_printf(_("Not enough memory for temporary bitmaps.\n")); fop_error(fop, _("Not enough memory for temporary bitmaps.\n"));
return -1; return FALSE;
} }
gif = gif_create_animation(sprite->frames); gif = gif_create_animation(sprite->frames);
if (!gif) { if (!gif) {
image_free(bmp); image_free(bmp);
image_free(old); image_free(old);
console_printf(_("Error creating GIF structure.\n")); fop_error(fop, _("Error creating GIF structure.\n"));
return -1; return FALSE;
} }
gif->width = sprite->w; gif->width = sprite->w;
@ -327,8 +325,6 @@ static int save_GIF(Sprite *sprite)
/* avoid compilation warnings */ /* avoid compilation warnings */
x1 = y1 = x2 = y2 = 0; x1 = y1 = x2 = y2 = 0;
add_progress(2);
add_progress(sprite->frames);
for (i = 0; i < sprite->frames; i++) { for (i = 0; i < sprite->frames; i++) {
/* frame palette */ /* frame palette */
palette_copy(npal, sprite_get_palette(sprite, i)); palette_copy(npal, sprite_get_palette(sprite, i));
@ -442,19 +438,9 @@ static int save_GIF(Sprite *sprite)
/* update the old image and color-map to the new ones to compare later */ /* update the old image and color-map to the new ones to compare later */
image_copy(old, bmp, 0, 0); image_copy(old, bmp, 0, 0);
palette_copy(opal, npal); palette_copy(opal, npal);
do_progress(i);
} }
del_progress();
do_progress(1);
add_progress(100);
ret = gif_save_animation(sprite->filename, gif, do_progress);
del_progress();
do_progress(2);
del_progress();
ret = gif_save_animation(fop->filename, gif, fop_progress, fop);
gif_destroy_animation(gif); gif_destroy_animation(gif);
return ret; return ret == 0 ? TRUE: FALSE;
} }

View File

@ -25,45 +25,42 @@
#include <allegro/color.h> #include <allegro/color.h>
#include <allegro/file.h> #include <allegro/file.h>
#include "console/console.h"
#include "file/file.h" #include "file/file.h"
#include "raster/raster.h" #include "raster/raster.h"
#endif #endif
static Sprite *load_ICO(const char *filename); /* static bool load_ICO(FileOp *fop); */
static int save_ICO(Sprite *sprite); static bool save_ICO(FileOp *fop);
FileFormat format_ico = FileFormat format_ico =
{ {
"ico", "ico",
"ico", "ico",
load_ICO, NULL, /* load_ICO, */
save_ICO, save_ICO,
/* FILE_SUPPORT_RGB | */ /* FILE_SUPPORT_RGB | */
/* FILE_SUPPORT_GRAY | */ /* FILE_SUPPORT_GRAY | */
FILE_SUPPORT_INDEXED FILE_SUPPORT_INDEXED
}; };
static Sprite *load_ICO(const char *filename) /* static bool load_ICO(FileOp *fop) */
{ /* { */
return NULL; /* TODO */ /* return NULL; /\* TODO *\/ */
} /* } */
static int save_ICO(Sprite *sprite) static bool save_ICO(FileOp *fop)
{ {
PACKFILE *f; PACKFILE *f;
int depth, bpp, bw, bitsw; int depth, bpp, bw, bitsw;
int size, offset, n, i; int size, offset, n, i;
int c, x, y, b, m, v; int c, x, y, b, m, v;
int num = sprite->frames; int num = fop->sprite->frames;
Image *bmp; Image *bmp;
errno = 0; f = pack_fopen(fop->filename, F_WRITE);
f = pack_fopen(sprite->filename, F_WRITE);
if (!f) if (!f)
return errno; return FALSE;
offset = 6 + num * 16; /* ICONDIR + ICONDIRENTRYs */ offset = 6 + num * 16; /* ICONDIR + ICONDIRENTRYs */
@ -75,16 +72,16 @@ static int save_ICO(Sprite *sprite)
for(n = 0; n < num; n++) { for(n = 0; n < num; n++) {
depth = 8;/* bitmap_color_depth(bmp[n]); */ depth = 8;/* bitmap_color_depth(bmp[n]); */
bpp = (depth == 8) ? 8 : 24; bpp = (depth == 8) ? 8 : 24;
bw = (((sprite->w * bpp / 8) + 3) / 4) * 4; bw = (((fop->sprite->w * bpp / 8) + 3) / 4) * 4;
bitsw = ((((sprite->w + 7) / 8) + 3) / 4) * 4; bitsw = ((((fop->sprite->w + 7) / 8) + 3) / 4) * 4;
size = sprite->h * (bw + bitsw) + 40; size = fop->sprite->h * (bw + bitsw) + 40;
if (bpp == 8) if (bpp == 8)
size += 256 * 4; size += 256 * 4;
/* ICONDIRENTRY */ /* ICONDIRENTRY */
pack_putc(sprite->w, f); /* width */ pack_putc(fop->sprite->w, f); /* width */
pack_putc(sprite->h, f); /* height */ pack_putc(fop->sprite->h, f); /* height */
pack_putc(0, f); /* color count */ pack_putc(0, f); /* color count */
pack_putc(0, f); /* reserved */ pack_putc(0, f); /* reserved */
pack_iputw(1, f); /* color planes */ pack_iputw(1, f); /* color planes */
@ -95,11 +92,13 @@ static int save_ICO(Sprite *sprite)
offset += size; offset += size;
} }
bmp = image_new(sprite->imgtype, sprite->w, sprite->h); bmp = image_new(fop->sprite->imgtype,
fop->sprite->w,
fop->sprite->h);
for(n = 0; n < num; n++) { for (n = 0; n < num; n++) {
image_clear(bmp, 0); image_clear(bmp, 0);
layer_render(sprite->set, bmp, 0, 0, n); layer_render(fop->sprite->set, bmp, 0, 0, n);
depth = 8; /* bitmap_color_depth(bmp); */ depth = 8; /* bitmap_color_depth(bmp); */
bpp = (depth == 8) ? 8 : 24; bpp = (depth == 8) ? 8 : 24;
@ -125,7 +124,7 @@ static int save_ICO(Sprite *sprite)
/* PALETTE */ /* PALETTE */
if (bpp == 8) { if (bpp == 8) {
RGB *pal = sprite_get_palette(sprite, n); RGB *pal = sprite_get_palette(fop->sprite, n);
pack_iputl(0, f); /* color 0 is black, so the XOR mask works */ pack_iputl(0, f); /* color 0 is black, so the XOR mask works */
@ -185,5 +184,5 @@ static int save_ICO(Sprite *sprite)
image_free(bmp); image_free(bmp);
pack_fclose(f); pack_fclose(f);
return errno; return TRUE;
} }

View File

@ -26,7 +26,6 @@
#include "jinete/jinete.h" #include "jinete/jinete.h"
#include "console/console.h"
#include "core/app.h" #include "core/app.h"
#include "core/cfg.h" #include "core/cfg.h"
#include "core/core.h" #include "core/core.h"
@ -38,10 +37,10 @@
#include "jpeglib.h" #include "jpeglib.h"
static Sprite *load_JPEG(const char *filename); static bool load_JPEG(FileOp *fop);
static int save_JPEG(Sprite *sprite); static bool save_JPEG(FileOp *fop);
static int configure_jpeg(void); static bool configure_jpeg(void); /* TODO warning: not thread safe */
FileFormat format_jpeg = FileFormat format_jpeg =
{ {
@ -54,17 +53,10 @@ FileFormat format_jpeg =
FILE_SUPPORT_SEQUENCES FILE_SUPPORT_SEQUENCES
}; };
static void progress_monitor(j_common_ptr cinfo)
{
if (cinfo->progress->pass_limit > 1)
do_progress(100 *
(cinfo->progress->pass_counter) /
(cinfo->progress->pass_limit-1));
}
struct error_mgr { struct error_mgr {
struct jpeg_error_mgr pub; struct jpeg_error_mgr head;
jmp_buf setjmp_buffer; jmp_buf setjmp_buffer;
FileOp *fop;
}; };
static void error_exit(j_common_ptr cinfo) static void error_exit(j_common_ptr cinfo)
@ -87,14 +79,13 @@ static void output_message(j_common_ptr cinfo)
PRINTF("JPEG library: \"%s\"\n", buffer); PRINTF("JPEG library: \"%s\"\n", buffer);
/* Leave the message for the application. */ /* Leave the message for the application. */
console_printf("%s\n", buffer); fop_error(((struct error_mgr *)cinfo->err)->fop, "%s\n", buffer);
} }
static Sprite *load_JPEG(const char *filename) static bool load_JPEG(FileOp *fop)
{ {
struct jpeg_decompress_struct cinfo; struct jpeg_decompress_struct cinfo;
struct error_mgr jerr; struct error_mgr jerr;
struct jpeg_progress_mgr progress;
Image *image; Image *image;
FILE *file; FILE *file;
JDIMENSION num_scanlines; JDIMENSION num_scanlines;
@ -102,24 +93,22 @@ static Sprite *load_JPEG(const char *filename)
JDIMENSION buffer_height; JDIMENSION buffer_height;
int c; int c;
file = fopen(filename, "rb"); file = fopen(fop->filename, "rb");
if (!file) { if (!file)
if (!file_sequence_sprite()) return FALSE;
console_printf(_("Error opening file.\n"));
return NULL;
}
/* initialize the JPEG decompression object with error handling */ /* initialize the JPEG decompression object with error handling */
cinfo.err = jpeg_std_error(&jerr.pub); jerr.fop = fop;
cinfo.err = jpeg_std_error(&jerr.head);
jerr.pub.error_exit = error_exit; jerr.head.error_exit = error_exit;
jerr.pub.output_message = output_message; jerr.head.output_message = output_message;
/* establish the setjmp return context for error_exit to use */ /* establish the setjmp return context for error_exit to use */
if (setjmp(jerr.setjmp_buffer)) { if (setjmp(jerr.setjmp_buffer)) {
jpeg_destroy_decompress(&cinfo); jpeg_destroy_decompress(&cinfo);
fclose(file); fclose(file);
return NULL; return FALSE;
} }
jpeg_create_decompress(&cinfo); jpeg_create_decompress(&cinfo);
@ -139,14 +128,15 @@ static Sprite *load_JPEG(const char *filename)
jpeg_start_decompress(&cinfo); jpeg_start_decompress(&cinfo);
/* create the image */ /* create the image */
image = file_sequence_image((cinfo.out_color_space == JCS_RGB ? IMAGE_RGB: image = fop_sequence_image(fop,
IMAGE_GRAYSCALE), (cinfo.out_color_space == JCS_RGB ? IMAGE_RGB:
cinfo.output_width, IMAGE_GRAYSCALE),
cinfo.output_height); cinfo.output_width,
cinfo.output_height);
if (!image) { if (!image) {
jpeg_destroy_decompress(&cinfo); jpeg_destroy_decompress(&cinfo);
fclose(file); fclose(file);
return NULL; return FALSE;
} }
/* create the buffer */ /* create the buffer */
@ -155,7 +145,7 @@ static Sprite *load_JPEG(const char *filename)
if (!buffer) { if (!buffer) {
jpeg_destroy_decompress(&cinfo); jpeg_destroy_decompress(&cinfo);
fclose(file); fclose(file);
return NULL; return FALSE;
} }
for (c=0; c<(int)buffer_height; c++) { for (c=0; c<(int)buffer_height; c++) {
@ -167,21 +157,18 @@ static Sprite *load_JPEG(const char *filename)
jfree(buffer); jfree(buffer);
jpeg_destroy_decompress(&cinfo); jpeg_destroy_decompress(&cinfo);
fclose(file); fclose(file);
return NULL; return FALSE;
} }
} }
/* generate a grayscale palette if is necessary */ /* generate a grayscale palette if is necessary */
if (image->imgtype == IMAGE_GRAYSCALE) if (image->imgtype == IMAGE_GRAYSCALE)
for (c=0; c<256; c++) for (c=0; c<256; c++)
file_sequence_set_color(c, c >> 2, c >> 2, c >> 2); fop_sequence_set_color(fop, c, c >> 2, c >> 2, c >> 2);
/* for progress bar */
progress.progress_monitor = progress_monitor;
cinfo.progress = &progress;
/* read each scan line */ /* read each scan line */
while (cinfo.output_scanline < cinfo.output_height) { while (cinfo.output_scanline < cinfo.output_height) {
/* TODO */
/* if (plugin_want_close()) */ /* if (plugin_want_close()) */
/* break; */ /* break; */
@ -219,6 +206,8 @@ static Sprite *load_JPEG(const char *filename)
*(dst_address++) = _graya(*(src_address++), 255); *(dst_address++) = _graya(*(src_address++), 255);
} }
} }
fop_progress(fop, (float)(cinfo.output_scanline+1) / (float)(cinfo.output_height));
} }
/* destroy all data */ /* destroy all data */
@ -230,26 +219,25 @@ static Sprite *load_JPEG(const char *filename)
jpeg_destroy_decompress(&cinfo); jpeg_destroy_decompress(&cinfo);
fclose(file); fclose(file);
return file_sequence_sprite(); return TRUE;
} }
static int save_JPEG(Sprite *sprite) static bool save_JPEG(FileOp *fop)
{ {
struct jpeg_compress_struct cinfo; struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr; struct error_mgr jerr;
struct jpeg_progress_mgr progress; Image *image = fop->seq.image;
FILE *file; FILE *file;
JSAMPARRAY buffer; JSAMPARRAY buffer;
JDIMENSION buffer_height; JDIMENSION buffer_height;
Image *image;
int c; int c;
int smooth; int smooth;
int quality; int quality;
J_DCT_METHOD method; J_DCT_METHOD method;
/* Configure JPEG compression only in the first frame. */ /* Configure JPEG compression only in the first frame. */
if (sprite->frame == 0 && configure_jpeg() < 0) if (fop->sprite->frame == 0 && !configure_jpeg())
return 0; return FALSE;
/* Options. */ /* Options. */
smooth = get_config_int("JPEG", "Smooth", 0); smooth = get_config_int("JPEG", "Smooth", 0);
@ -257,16 +245,15 @@ static int save_JPEG(Sprite *sprite)
method = get_config_int("JPEG", "Method", JDCT_DEFAULT); method = get_config_int("JPEG", "Method", JDCT_DEFAULT);
/* Open the file for write in it. */ /* Open the file for write in it. */
file = fopen(sprite->filename, "wb"); file = fopen(fop->filename, "wb");
if (!file) { if (!file) {
console_printf(_("Error creating file.\n")); fop_error(fop, _("Error creating file.\n"));
return -1; return FALSE;
} }
image = file_sequence_image_to_save();
/* Allocate and initialize JPEG compression object. */ /* Allocate and initialize JPEG compression object. */
cinfo.err = jpeg_std_error(&jerr); jerr.fop = fop;
cinfo.err = jpeg_std_error(&jerr.head);
jpeg_create_compress(&cinfo); jpeg_create_compress(&cinfo);
/* Specify data destination file. */ /* Specify data destination file. */
@ -297,30 +284,26 @@ static int save_JPEG(Sprite *sprite)
buffer_height = 1; buffer_height = 1;
buffer = jmalloc(sizeof(JSAMPROW) * buffer_height); buffer = jmalloc(sizeof(JSAMPROW) * buffer_height);
if (!buffer) { if (!buffer) {
console_printf(_("Not enough memory for the buffer.\n")); fop_error(fop, _("Not enough memory for the buffer.\n"));
jpeg_destroy_compress(&cinfo); jpeg_destroy_compress(&cinfo);
fclose(file); fclose(file);
return -1; return FALSE;
} }
for (c=0; c<(int)buffer_height; c++) { for (c=0; c<(int)buffer_height; c++) {
buffer[c] = jmalloc(sizeof(JSAMPLE) * buffer[c] = jmalloc(sizeof(JSAMPLE) *
cinfo.image_width * cinfo.num_components); cinfo.image_width * cinfo.num_components);
if (!buffer[c]) { if (!buffer[c]) {
console_printf(_("Not enough memory for buffer scanlines.\n")); fop_error(fop, _("Not enough memory for buffer scanlines.\n"));
for (c--; c>=0; c--) for (c--; c>=0; c--)
jfree(buffer[c]); jfree(buffer[c]);
jfree(buffer); jfree(buffer);
jpeg_destroy_compress(&cinfo); jpeg_destroy_compress(&cinfo);
fclose(file); fclose(file);
return -1; return FALSE;
} }
} }
/* For progress bar. */
progress.progress_monitor = progress_monitor;
cinfo.progress = &progress;
/* Write each scan line. */ /* Write each scan line. */
while (cinfo.next_scanline < cinfo.image_height) { while (cinfo.next_scanline < cinfo.image_height) {
/* RGB */ /* RGB */
@ -352,6 +335,8 @@ static int save_JPEG(Sprite *sprite)
} }
} }
jpeg_write_scanlines(&cinfo, buffer, buffer_height); jpeg_write_scanlines(&cinfo, buffer, buffer_height);
fop_progress(fop, (float)(cinfo.next_scanline+1) / (float)(cinfo.image_height));
} }
/* Destroy all data. */ /* Destroy all data. */
@ -369,23 +354,24 @@ static int save_JPEG(Sprite *sprite)
fclose(file); fclose(file);
/* All fine. */ /* All fine. */
return 0; return TRUE;
} }
/** /**
* Shows the JPEG configuration dialog. * Shows the JPEG configuration dialog.
*/ */
static int configure_jpeg(void) static bool configure_jpeg(void)
{ {
JWidget window, box1, box2, box3, box4, box5; JWidget window, box1, box2, box3, box4, box5;
JWidget label_quality, label_smooth, label_method; JWidget label_quality, label_smooth, label_method;
JWidget slider_quality, slider_smooth, view_method; JWidget slider_quality, slider_smooth, view_method;
JWidget list_method, button_ok, button_cancel; JWidget list_method, button_ok, button_cancel;
int ret, quality, smooth, method; int quality, smooth, method;
bool ret;
/* interactive mode */ /* interactive mode */
if (!is_interactive()) if (!is_interactive())
return 0; return TRUE;
/* configuration parameters */ /* configuration parameters */
quality = get_config_int("JPEG", "Quality", 100); quality = get_config_int("JPEG", "Quality", 100);

View File

@ -25,14 +25,13 @@
#include <allegro/color.h> #include <allegro/color.h>
#include <allegro/file.h> #include <allegro/file.h>
#include "console/console.h"
#include "file/file.h" #include "file/file.h"
#include "raster/raster.h" #include "raster/raster.h"
#endif #endif
static Sprite *load_PCX(const char *filename); static bool load_PCX(FileOp *fop);
static int save_PCX(Sprite *sprite); static bool save_PCX(FileOp *fop);
FileFormat format_pcx = FileFormat format_pcx =
{ {
@ -46,7 +45,7 @@ FileFormat format_pcx =
FILE_SUPPORT_SEQUENCES FILE_SUPPORT_SEQUENCES
}; };
static Sprite *load_PCX(const char *filename) static bool load_PCX(FileOp *fop)
{ {
Image *image; Image *image;
PACKFILE *f; PACKFILE *f;
@ -57,18 +56,18 @@ static Sprite *load_PCX(const char *filename)
int x, y; int x, y;
char ch = 0; char ch = 0;
f = pack_fopen(filename, F_READ); f = pack_fopen(fop->filename, F_READ);
if (!f) if (!f)
return NULL; return FALSE;
pack_getc(f); /* skip manufacturer ID */ pack_getc(f); /* skip manufacturer ID */
pack_getc(f); /* skip version flag */ pack_getc(f); /* skip version flag */
pack_getc(f); /* skip encoding flag */ pack_getc(f); /* skip encoding flag */
if (pack_getc(f) != 8) { /* we like 8 bit color planes */ if (pack_getc(f) != 8) { /* we like 8 bit color planes */
console_printf(_("This PCX doesn't have 8 bit color planes.\n")); fop_error(fop, _("This PCX doesn't have 8 bit color planes.\n"));
pack_fclose(f); pack_fclose(f);
return NULL; return FALSE;
} }
width = -(pack_igetw(f)); /* xmin */ width = -(pack_igetw(f)); /* xmin */
@ -82,7 +81,7 @@ static Sprite *load_PCX(const char *filename)
r = pack_getc(f) / 4; r = pack_getc(f) / 4;
g = pack_getc(f) / 4; g = pack_getc(f) / 4;
b = pack_getc(f) / 4; b = pack_getc(f) / 4;
file_sequence_set_color(c, r, g, b); fop_sequence_set_color(fop, c, r, g, b);
} }
pack_getc(f); pack_getc(f);
@ -90,7 +89,7 @@ static Sprite *load_PCX(const char *filename)
bpp = pack_getc(f) * 8; /* how many color planes? */ bpp = pack_getc(f) * 8; /* how many color planes? */
if ((bpp != 8) && (bpp != 24)) { if ((bpp != 8) && (bpp != 24)) {
pack_fclose(f); pack_fclose(f);
return NULL; return FALSE;
} }
bytes_per_line = pack_igetw(f); bytes_per_line = pack_igetw(f);
@ -98,12 +97,13 @@ static Sprite *load_PCX(const char *filename)
for (c=0; c<60; c++) /* skip some more junk */ for (c=0; c<60; c++) /* skip some more junk */
pack_getc(f); pack_getc(f);
image = file_sequence_image(bpp == 8 ? image = fop_sequence_image(fop, bpp == 8 ?
IMAGE_INDEXED: IMAGE_INDEXED:
IMAGE_RGB, width, height); IMAGE_RGB,
width, height);
if (!image) { if (!image) {
pack_fclose(f); pack_fclose(f);
return NULL; return FALSE;
} }
if (bpp == 24) if (bpp == 24)
@ -150,8 +150,7 @@ static Sprite *load_PCX(const char *filename)
} }
} }
if (height > 1) fop_progress(fop, (float)(y+1) / (float)(height));
do_progress(100 * y / (height-1));
} }
if (bpp == 8) { /* look for a 256 color palette */ if (bpp == 8) { /* look for a 256 color palette */
@ -161,7 +160,7 @@ static Sprite *load_PCX(const char *filename)
r = pack_getc(f) / 4; r = pack_getc(f) / 4;
g = pack_getc(f) / 4; g = pack_getc(f) / 4;
b = pack_getc(f) / 4; b = pack_getc(f) / 4;
file_sequence_set_color(c, r, g, b); fop_sequence_set_color(fop, c, r, g, b);
} }
break; break;
} }
@ -169,19 +168,19 @@ static Sprite *load_PCX(const char *filename)
} }
if (*allegro_errno) { if (*allegro_errno) {
console_printf(_("Error reading bytes.\n")); fop_error(fop, _("Error reading bytes.\n"));
pack_fclose(f); pack_fclose(f);
return NULL; return FALSE;
} }
pack_fclose(f); pack_fclose(f);
return file_sequence_sprite(); return TRUE;
} }
static int save_PCX(Sprite *sprite) static bool save_PCX(FileOp *fop)
{ {
Image *image = fop->seq.image;
PACKFILE *f; PACKFILE *f;
Image *image;
int c, r, g, b; int c, r, g, b;
int x, y; int x, y;
int runcount; int runcount;
@ -189,15 +188,13 @@ static int save_PCX(Sprite *sprite)
char runchar; char runchar;
char ch = 0; char ch = 0;
f = pack_fopen(sprite->filename, F_WRITE); f = pack_fopen(fop->filename, F_WRITE);
if (!f) { if (!f) {
console_printf(_("Error creating file.\n")); fop_error(fop, _("Error creating file.\n"));
return -1; return FALSE;
} }
image = file_sequence_image_to_save(); if (image->imgtype == IMAGE_RGB) {
if (sprite->imgtype == IMAGE_RGB) {
depth = 24; depth = 24;
planes = 3; planes = 3;
} }
@ -220,7 +217,7 @@ static int save_PCX(Sprite *sprite)
pack_iputw(200, f); /* VDpi */ pack_iputw(200, f); /* VDpi */
for (c=0; c<16; c++) { for (c=0; c<16; c++) {
file_sequence_get_color(c, &r, &g, &b); fop_sequence_get_color(fop, c, &r, &g, &b);
pack_putc(_rgb_scale_6[r], f); pack_putc(_rgb_scale_6[r], f);
pack_putc(_rgb_scale_6[g], f); pack_putc(_rgb_scale_6[g], f);
pack_putc(_rgb_scale_6[b], f); pack_putc(_rgb_scale_6[b], f);
@ -283,15 +280,14 @@ static int save_PCX(Sprite *sprite)
pack_putc(runchar, f); pack_putc(runchar, f);
if (image->h > 1) fop_progress(fop, (float)(y+1) / (float)(image->h));
do_progress(100 * y / (image->h-1));
} }
if (depth == 8) { /* 256 color palette */ if (depth == 8) { /* 256 color palette */
pack_putc(12, f); pack_putc(12, f);
for (c=0; c<256; c++) { for (c=0; c<256; c++) {
file_sequence_get_color(c, &r, &g, &b); fop_sequence_get_color(fop, c, &r, &g, &b);
pack_putc(_rgb_scale_6[r], f); pack_putc(_rgb_scale_6[r], f);
pack_putc(_rgb_scale_6[g], f); pack_putc(_rgb_scale_6[g], f);
pack_putc(_rgb_scale_6[b], f); pack_putc(_rgb_scale_6[b], f);
@ -301,9 +297,9 @@ static int save_PCX(Sprite *sprite)
pack_fclose(f); pack_fclose(f);
if (*allegro_errno) { if (*allegro_errno) {
console_printf(_("Error writing bytes.\n")); fop_error(fop, _("Error writing bytes.\n"));
return -1; return FALSE;
} }
else else
return 0; return TRUE;
} }

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello * Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -23,7 +23,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "console/console.h"
#include "core/app.h" #include "core/app.h"
#include "core/cfg.h" #include "core/cfg.h"
#include "core/core.h" #include "core/core.h"
@ -36,8 +35,8 @@
#endif #endif
static Sprite *load_PNG(const char *filename); static bool load_PNG(FileOp *fop);
static int save_PNG(Sprite *sprite); static bool save_PNG(FileOp *fop);
/* static int configure_png(void); */ /* static int configure_png(void); */
@ -57,10 +56,10 @@ FileFormat format_png =
static void report_png_error(png_structp png_ptr, png_const_charp error) static void report_png_error(png_structp png_ptr, png_const_charp error)
{ {
console_printf("libpng: %s\n", error); fop_error((FileOp *)png_ptr->error_ptr, "libpng: %s\n", error);
} }
static Sprite *load_PNG(const char *filename) static bool load_PNG(FileOp *fop)
{ {
png_uint_32 width, height, y; png_uint_32 width, height, y;
unsigned int sig_read = 0; unsigned int sig_read = 0;
@ -75,12 +74,9 @@ static Sprite *load_PNG(const char *filename)
int imgtype; int imgtype;
FILE *fp; FILE *fp;
fp = fopen(filename, "rb"); fp = fopen(fop->filename, "rb");
if (!fp) { if (!fp)
if (!file_sequence_sprite()) return FALSE;
console_printf(_("Error opening file.\n"));
return NULL;
}
/* Create and initialize the png_struct with the desired error handler /* Create and initialize the png_struct with the desired error handler
* functions. If you want to use the default stderr and longjump method, * functions. If you want to use the default stderr and longjump method,
@ -88,33 +84,33 @@ static Sprite *load_PNG(const char *filename)
* the compiler header file version, so that we know if the application * the compiler header file version, so that we know if the application
* was compiled with a compatible version of the library * was compiled with a compatible version of the library
*/ */
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)fop,
report_png_error, report_png_error); report_png_error, report_png_error);
if (png_ptr == NULL) { if (png_ptr == NULL) {
console_printf("png_create_read_struct\n"); fop_error(fop, "png_create_read_struct\n");
fclose(fp); fclose(fp);
return NULL; return FALSE;
} }
/* Allocate/initialize the memory for image information. */ /* Allocate/initialize the memory for image information. */
info_ptr = png_create_info_struct(png_ptr); info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) { if (info_ptr == NULL) {
console_printf("png_create_info_struct\n"); fop_error(fop, "png_create_info_struct\n");
fclose(fp); fclose(fp);
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL); png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
return NULL; return FALSE;
} }
/* Set error handling if you are using the setjmp/longjmp method (this is /* Set error handling if you are using the setjmp/longjmp method (this is
* the normal method of doing things with libpng). * the normal method of doing things with libpng).
*/ */
if (setjmp(png_jmpbuf(png_ptr))) { if (setjmp(png_jmpbuf(png_ptr))) {
console_printf("Error reading PNG file\n"); fop_error(fop, "Error reading PNG file\n");
/* Free all of the memory associated with the png_ptr and info_ptr */ /* Free all of the memory associated with the png_ptr and info_ptr */
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
fclose(fp); fclose(fp);
/* If we get here, we had a problem reading the file */ /* If we get here, we had a problem reading the file */
return NULL; return FALSE;
} }
/* Set up the input control if you are using standard C streams */ /* Set up the input control if you are using standard C streams */
@ -175,18 +171,18 @@ static Sprite *load_PNG(const char *filename)
imgtype = IMAGE_INDEXED; imgtype = IMAGE_INDEXED;
break; break;
default: default:
console_printf("Color type not supported\n)"); fop_error(fop, "Color type not supported\n)");
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
fclose(fp); fclose(fp);
return NULL; return FALSE;
} }
image = file_sequence_image(imgtype, info_ptr->width, info_ptr->height); image = fop_sequence_image(fop, imgtype, info_ptr->width, info_ptr->height);
if (!image) { if (!image) {
console_printf("file_sequence_image %dx%d\n", info_ptr->width, info_ptr->height); fop_error(fop, "file_sequence_image %dx%d\n", info_ptr->width, info_ptr->height);
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
fclose(fp); fclose(fp);
return NULL; return FALSE;
} }
/* read palette */ /* read palette */
@ -196,13 +192,13 @@ static Sprite *load_PNG(const char *filename)
int c; int c;
for (c = 0; c < num_palette; c++) { for (c = 0; c < num_palette; c++) {
file_sequence_set_color(c, fop_sequence_set_color(fop, c,
palette[c].red / 4, palette[c].red / 4,
palette[c].green / 4, palette[c].green / 4,
palette[c].blue / 4); palette[c].blue / 4);
} }
for (; c < 256; c++) { for (; c < 256; c++) {
file_sequence_set_color(c, 0, 0, 0); fop_sequence_set_color(fop, c, 0, 0, 0);
} }
} }
@ -277,7 +273,9 @@ static Sprite *load_PNG(const char *filename)
} }
} }
do_progress(100 * y / height); fop_progress(fop,
(float)((float)pass + (float)(y+1) / (float)(height))
/ (float)number_passes);
} }
} }
png_free(png_ptr, row_pointer); png_free(png_ptr, row_pointer);
@ -287,27 +285,25 @@ static Sprite *load_PNG(const char *filename)
/* close the file */ /* close the file */
fclose(fp); fclose(fp);
return TRUE;
/* return the sprite */
return file_sequence_sprite();
} }
static int save_PNG(Sprite *sprite) static bool save_PNG(FileOp *fop)
{ {
Image *image = fop->seq.image;
png_uint_32 width, height, y; png_uint_32 width, height, y;
png_structp png_ptr; png_structp png_ptr;
png_infop info_ptr; png_infop info_ptr;
png_colorp palette; png_colorp palette;
png_bytep row_pointer; png_bytep row_pointer;
int color_type; int color_type;
Image *image;
int pass, number_passes; int pass, number_passes;
FILE *fp; FILE *fp;
/* open the file */ /* open the file */
fp = fopen(sprite->filename, "wb"); fp = fopen(fop->filename, "wb");
if (fp == NULL) if (fp == NULL)
return -1; return FALSE;
/* Create and initialize the png_struct with the desired error handler /* Create and initialize the png_struct with the desired error handler
* functions. If you want to use the default stderr and longjump method, * functions. If you want to use the default stderr and longjump method,
@ -315,11 +311,11 @@ static int save_PNG(Sprite *sprite)
* the library version is compatible with the one used at compile time, * the library version is compatible with the one used at compile time,
* in case we are using dynamically linked libraries. REQUIRED. * in case we are using dynamically linked libraries. REQUIRED.
*/ */
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)fop,
report_png_error, report_png_error); report_png_error, report_png_error);
if (png_ptr == NULL) { if (png_ptr == NULL) {
fclose(fp); fclose(fp);
return -1; return FALSE;
} }
/* Allocate/initialize the image information data. REQUIRED */ /* Allocate/initialize the image information data. REQUIRED */
@ -327,7 +323,7 @@ static int save_PNG(Sprite *sprite)
if (info_ptr == NULL) { if (info_ptr == NULL) {
fclose(fp); fclose(fp);
png_destroy_write_struct(&png_ptr, png_infopp_NULL); png_destroy_write_struct(&png_ptr, png_infopp_NULL);
return -1; return FALSE;
} }
/* Set error handling. REQUIRED if you aren't supplying your own /* Set error handling. REQUIRED if you aren't supplying your own
@ -337,7 +333,7 @@ static int save_PNG(Sprite *sprite)
/* If we get here, we had a problem reading the file */ /* If we get here, we had a problem reading the file */
fclose(fp); fclose(fp);
png_destroy_write_struct(&png_ptr, &info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr);
return -1; return FALSE;
} }
/* set up the output control if you are using standard C streams */ /* set up the output control if you are using standard C streams */
@ -351,18 +347,17 @@ static int save_PNG(Sprite *sprite)
* PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
* currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
*/ */
image = file_sequence_image_to_save();
width = image->w; width = image->w;
height = image->h; height = image->h;
switch (image->imgtype) { switch (image->imgtype) {
case IMAGE_RGB: case IMAGE_RGB:
color_type = _rgba_geta(sprite->bgcolor) < 255 ? color_type = sprite_need_alpha(fop->sprite) ?
PNG_COLOR_TYPE_RGB_ALPHA: PNG_COLOR_TYPE_RGB_ALPHA:
PNG_COLOR_TYPE_RGB; PNG_COLOR_TYPE_RGB;
break; break;
case IMAGE_GRAYSCALE: case IMAGE_GRAYSCALE:
color_type = _graya_geta(sprite->bgcolor) < 255 ? color_type = sprite_need_alpha(fop->sprite) ?
PNG_COLOR_TYPE_GRAY_ALPHA: PNG_COLOR_TYPE_GRAY_ALPHA:
PNG_COLOR_TYPE_GRAY; PNG_COLOR_TYPE_GRAY;
break; break;
@ -386,7 +381,7 @@ static int save_PNG(Sprite *sprite)
* png_sizeof(png_color)); * png_sizeof(png_color));
/* ... set palette colors ... */ /* ... set palette colors ... */
for (c = 0; c < PNG_MAX_PALETTE_LENGTH; c++) { for (c = 0; c < PNG_MAX_PALETTE_LENGTH; c++) {
file_sequence_get_color(c, &r, &g, &b); fop_sequence_get_color(fop, c, &r, &g, &b);
palette[c].red = _rgb_scale_6[r]; palette[c].red = _rgb_scale_6[r];
palette[c].green = _rgb_scale_6[g]; palette[c].green = _rgb_scale_6[g];
palette[c].blue = _rgb_scale_6[b]; palette[c].blue = _rgb_scale_6[b];
@ -474,7 +469,10 @@ static int save_PNG(Sprite *sprite)
/* write the line */ /* write the line */
png_write_rows(png_ptr, &row_pointer, 1); png_write_rows(png_ptr, &row_pointer, 1);
do_progress(100 * y / height);
fop_progress(fop,
(float)((float)pass + (float)(y+1) / (float)(height))
/ (float)number_passes);
} }
} }
@ -500,7 +498,7 @@ static int save_PNG(Sprite *sprite)
fclose(fp); fclose(fp);
/* all right */ /* all right */
return 0; return TRUE;
} }
/* static int configure_png(void) */ /* static int configure_png(void) */

View File

@ -28,14 +28,13 @@
#include "jinete/jbase.h" #include "jinete/jbase.h"
#include "console/console.h"
#include "file/file.h" #include "file/file.h"
#include "raster/raster.h" #include "raster/raster.h"
#endif #endif
static int save_TGA(Sprite *sprite); static bool load_TGA(FileOp *fop);
static Sprite *load_TGA(const char *filename); static bool save_TGA(FileOp *fop);
FileFormat format_tga = FileFormat format_tga =
{ {
@ -191,7 +190,7 @@ static void rle_tga_read16(ase_uint32 *address, int w, PACKFILE *f)
* structure and storing the palette data in the specified palette (this * structure and storing the palette data in the specified palette (this
* should be an array of at least 256 RGB structures). * should be an array of at least 256 RGB structures).
*/ */
static Sprite *load_TGA(const char *filename) static bool load_TGA(FileOp *fop)
{ {
unsigned char image_id[256], image_palette[256][3], rgb[4]; unsigned char image_id[256], image_palette[256][3], rgb[4];
unsigned char id_length, palette_type, image_type, palette_entry_size; unsigned char id_length, palette_type, image_type, palette_entry_size;
@ -204,12 +203,9 @@ static Sprite *load_TGA(const char *filename)
PACKFILE *f; PACKFILE *f;
int type; int type;
f = pack_fopen(filename, F_READ); f = pack_fopen(fop->filename, F_READ);
if (!f) { if (!f)
if (!file_sequence_sprite()) return FALSE;
console_printf(_("Error opening file.\n"));
return NULL;
}
*allegro_errno = 0; *allegro_errno = 0;
@ -252,7 +248,7 @@ static Sprite *load_TGA(const char *filename)
} }
else if (palette_type != 0) { else if (palette_type != 0) {
pack_fclose(f); pack_fclose(f);
return NULL; return FALSE;
} }
/* Image type: /* Image type:
@ -273,14 +269,14 @@ static Sprite *load_TGA(const char *filename)
case 1: case 1:
if ((palette_type != 1) || (bpp != 8)) { if ((palette_type != 1) || (bpp != 8)) {
pack_fclose(f); pack_fclose(f);
return NULL; return FALSE;
} }
for (i=0; i<palette_colors; i++) { for (i=0; i<palette_colors; i++) {
file_sequence_set_color(i, fop_sequence_set_color(fop, i,
image_palette[i][2] >> 2, image_palette[i][2] >> 2,
image_palette[i][1] >> 2, image_palette[i][1] >> 2,
image_palette[i][0] >> 2); image_palette[i][0] >> 2);
} }
type = IMAGE_INDEXED; type = IMAGE_INDEXED;
@ -292,7 +288,7 @@ static Sprite *load_TGA(const char *filename)
((bpp != 15) && (bpp != 16) && ((bpp != 15) && (bpp != 16) &&
(bpp != 24) && (bpp != 32))) { (bpp != 24) && (bpp != 32))) {
pack_fclose(f); pack_fclose(f);
return NULL; return FALSE;
} }
type = IMAGE_RGB; type = IMAGE_RGB;
@ -302,11 +298,11 @@ static Sprite *load_TGA(const char *filename)
case 3: case 3:
if ((palette_type != 0) || (bpp != 8)) { if ((palette_type != 0) || (bpp != 8)) {
pack_fclose(f); pack_fclose(f);
return NULL; return FALSE;
} }
for (i=0; i<256; i++) for (i=0; i<256; i++)
file_sequence_set_color(i, i>>2, i>>2, i>>2); fop_sequence_set_color(fop, i, i>>2, i>>2, i>>2);
type = IMAGE_GRAYSCALE; type = IMAGE_GRAYSCALE;
break; break;
@ -315,13 +311,13 @@ static Sprite *load_TGA(const char *filename)
/* TODO add support for more TGA types? */ /* TODO add support for more TGA types? */
pack_fclose(f); pack_fclose(f);
return NULL; return FALSE;
} }
image = file_sequence_image(type, image_width, image_height); image = fop_sequence_image(fop, type, image_width, image_height);
if (!image) { if (!image) {
pack_fclose(f); pack_fclose(f);
return NULL; return FALSE;
} }
for (y=image_height; y; y--) { for (y=image_height; y; y--) {
@ -385,48 +381,46 @@ static Sprite *load_TGA(const char *filename)
} }
if (image_height > 1) if (image_height > 1)
do_progress(100 * (image_height-y) / image_height); fop_progress(fop, (float)(image_height-y) / (float)(image_height));
} }
if (*allegro_errno) { if (*allegro_errno) {
console_printf(_("Error reading bytes.\n")); fop_error(fop, _("Error reading bytes.\n"));
pack_fclose(f); pack_fclose(f);
return NULL; return FALSE;
} }
pack_fclose(f); pack_fclose(f);
return file_sequence_sprite(); return TRUE;
} }
/* save_tga: /* save_tga:
* Writes a bitmap into a TGA file, using the specified palette (this * Writes a bitmap into a TGA file, using the specified palette (this
* should be an array of at least 256 RGB structures). * should be an array of at least 256 RGB structures).
*/ */
static int save_TGA(Sprite *sprite) static bool save_TGA(FileOp *fop)
{ {
Image *image = fop->seq.image;
unsigned char image_palette[256][3]; unsigned char image_palette[256][3];
int x, y, c, r, g, b; int x, y, c, r, g, b;
int depth = (sprite->imgtype == IMAGE_RGB) ? 32 : 8; int depth = (image->imgtype == IMAGE_RGB) ? 32 : 8;
bool need_pal = (sprite->imgtype == IMAGE_INDEXED)? TRUE: FALSE; bool need_pal = (image->imgtype == IMAGE_INDEXED)? TRUE: FALSE;
PACKFILE *f; PACKFILE *f;
Image *image;
f = pack_fopen(sprite->filename, F_WRITE); f = pack_fopen(fop->filename, F_WRITE);
if (!f) { if (!f) {
console_printf(_("Error creating file.\n")); fop_error(fop, _("Error creating file.\n"));
return -1; return FALSE;
} }
image = file_sequence_image_to_save();
*allegro_errno = 0; *allegro_errno = 0;
pack_putc(0, f); /* id length (no id saved) */ pack_putc(0, f); /* id length (no id saved) */
pack_putc((need_pal) ? 1 : 0, f); /* palette type */ pack_putc((need_pal) ? 1 : 0, f); /* palette type */
/* image type */ /* image type */
pack_putc((sprite->imgtype == IMAGE_RGB ) ? 2 : pack_putc((image->imgtype == IMAGE_RGB ) ? 2 :
(sprite->imgtype == IMAGE_GRAYSCALE) ? 3 : (image->imgtype == IMAGE_GRAYSCALE) ? 3 :
(sprite->imgtype == IMAGE_INDEXED ) ? 1 : 0, f); (image->imgtype == IMAGE_INDEXED ) ? 1 : 0, f);
pack_iputw(0, f); /* first colour */ pack_iputw(0, f); /* first colour */
pack_iputw((need_pal) ? 256 : 0, f); /* number of colours */ pack_iputw((need_pal) ? 256 : 0, f); /* number of colours */
pack_putc((need_pal) ? 24 : 0, f); /* palette entry size */ pack_putc((need_pal) ? 24 : 0, f); /* palette entry size */
@ -437,11 +431,11 @@ static int save_TGA(Sprite *sprite)
pack_putc(depth, f); /* bits per pixel */ pack_putc(depth, f); /* bits per pixel */
/* descriptor (bottom to top, 8-bit alpha) */ /* descriptor (bottom to top, 8-bit alpha) */
pack_putc(sprite->imgtype == IMAGE_RGB ? 8: 0, f); pack_putc(image->imgtype == IMAGE_RGB ? 8: 0, f);
if (need_pal) { if (need_pal) {
for (y=0; y<256; y++) { for (y=0; y<256; y++) {
file_sequence_get_color(y, &r, &g, &b); fop_sequence_get_color(fop, y, &r, &g, &b);
image_palette[y][2] = _rgb_scale_6[r]; image_palette[y][2] = _rgb_scale_6[r];
image_palette[y][1] = _rgb_scale_6[g]; image_palette[y][1] = _rgb_scale_6[g];
image_palette[y][0] = _rgb_scale_6[b]; image_palette[y][0] = _rgb_scale_6[b];
@ -449,40 +443,37 @@ static int save_TGA(Sprite *sprite)
pack_fwrite(image_palette, 768, f); pack_fwrite(image_palette, 768, f);
} }
switch (sprite->imgtype) { switch (image->imgtype) {
case IMAGE_RGB: case IMAGE_RGB:
for (y=image->h; y; y--) { for (y=image->h-1; y>=0; y--) {
for (x=0; x<image->w; x++) { for (x=0; x<image->w; x++) {
c = image_getpixel(image, x, y-1); c = image_getpixel(image, x, y);
pack_putc(_rgba_getb(c), f); pack_putc(_rgba_getb(c), f);
pack_putc(_rgba_getg(c), f); pack_putc(_rgba_getg(c), f);
pack_putc(_rgba_getr(c), f); pack_putc(_rgba_getr(c), f);
pack_putc(_rgba_geta(c), f); pack_putc(_rgba_geta(c), f);
} }
if (image->h > 1) fop_progress(fop, (float)(image->h-y) / (float)(image->h));
do_progress(100 * (image->h-y) / (image->h-1));
} }
break; break;
case IMAGE_GRAYSCALE: case IMAGE_GRAYSCALE:
for (y=image->h; y; y--) { for (y=image->h-1; y>=0; y--) {
for (x=0; x<image->w; x++) for (x=0; x<image->w; x++)
pack_putc(_graya_getk(image_getpixel(image, x, y-1)), f); pack_putc(_graya_getk(image_getpixel(image, x, y)), f);
if (image->h > 1) fop_progress(fop, (float)(image->h-y) / (float)(image->h));
do_progress(100 * (image->h-y) / (image->h-1));
} }
break; break;
case IMAGE_INDEXED: case IMAGE_INDEXED:
for (y=image->h; y; y--) { for (y=image->h-1; y>=0; y--) {
for (x=0; x<image->w; x++) for (x=0; x<image->w; x++)
pack_putc(image_getpixel(image, x, y-1), f); pack_putc(image_getpixel(image, x, y), f);
if (image->h > 1) fop_progress(fop, (float)(image->h-y) / (float)(image->h));
do_progress(100 * (image->h-y) / (image->h-1));
} }
break; break;
} }
@ -490,9 +481,9 @@ static int save_TGA(Sprite *sprite)
pack_fclose(f); pack_fclose(f);
if (*allegro_errno) { if (*allegro_errno) {
console_printf(_("Error writing bytes.\n")); fop_error(fop, _("Error writing bytes.\n"));
return -1; return FALSE;
} }
else else
return 0; return TRUE;
} }

View File

@ -76,9 +76,6 @@ void intl_set_lang(const char *lang)
/* clear msgids and load them again */ /* clear msgids and load them again */
msgids_clear(); msgids_clear();
intl_load_lang(); intl_load_lang();
/* reload the main menu */
rebuild_root_menu();
} }
/* int init_intl(void) */ /* int init_intl(void) */

View File

@ -231,7 +231,9 @@ enum {
typedef unsigned int JID; typedef unsigned int JID;
typedef void *JThread;
typedef void *JMutex; typedef void *JMutex;
typedef struct jaccel *JAccel; typedef struct jaccel *JAccel;
typedef struct jhook *JHook; typedef struct jhook *JHook;
typedef struct jquickmenu *JQuickMenu; typedef struct jquickmenu *JQuickMenu;
@ -249,9 +251,6 @@ typedef struct jxmlnode *JXmlNode;
typedef struct jxmlelem *JXmlElem; typedef struct jxmlelem *JXmlElem;
typedef struct jxmltext *JXmlText; typedef struct jxmltext *JXmlText;
typedef void (*JFunc) (void *data, void *user_data);
typedef int (*JCompareFunc) (const void *a, const void *b);
typedef int (*JCompareDataFunc) (const void *a, const void *b, void *user_data);
typedef bool (*JMessageFunc) (JWidget widget, JMessage msg); typedef bool (*JMessageFunc) (JWidget widget, JMessage msg);
typedef void (*JDrawFunc) (JWidget widget); typedef void (*JDrawFunc) (JWidget widget);

View File

@ -46,9 +46,10 @@ bool jcombobox_is_editable(JWidget combobox);
bool jcombobox_is_clickopen(JWidget combobox); bool jcombobox_is_clickopen(JWidget combobox);
bool jcombobox_is_casesensitive(JWidget combobox); bool jcombobox_is_casesensitive(JWidget combobox);
void jcombobox_add_string(JWidget combobox, const char *string); void jcombobox_add_string(JWidget combobox, const char *string, void *data);
void jcombobox_del_string(JWidget combobox, const char *string); void jcombobox_del_string(JWidget combobox, const char *string);
void jcombobox_del_index(JWidget combobox, int index); void jcombobox_del_index(JWidget combobox, int index);
void jcombobox_clear(JWidget combobox);
void jcombobox_select_index(JWidget combobox, int index); void jcombobox_select_index(JWidget combobox, int index);
void jcombobox_select_string(JWidget combobox, const char *string); void jcombobox_select_string(JWidget combobox, const char *string);
@ -56,10 +57,12 @@ int jcombobox_get_selected_index(JWidget combobox);
const char *jcombobox_get_selected_string(JWidget combobox); const char *jcombobox_get_selected_string(JWidget combobox);
const char *jcombobox_get_string(JWidget combobox, int index); const char *jcombobox_get_string(JWidget combobox, int index);
void *jcombobox_get_data(JWidget combobox, int index);
int jcombobox_get_index(JWidget combobox, const char *string); int jcombobox_get_index(JWidget combobox, const char *string);
int jcombobox_get_count(JWidget combobox); int jcombobox_get_count(JWidget combobox);
JWidget jcombobox_get_entry_widget(JWidget combobox); JWidget jcombobox_get_entry_widget(JWidget combobox);
JWidget jcombobox_get_button_widget(JWidget combobox);
JI_END_DECLS JI_END_DECLS

View File

@ -38,6 +38,7 @@ typedef struct ComboBox
JWidget entry; JWidget entry;
JWidget button; JWidget button;
JWidget window; JWidget window;
JWidget listbox;
JList items; JList items;
int selected; int selected;
bool editable : 1; bool editable : 1;
@ -45,6 +46,12 @@ typedef struct ComboBox
bool casesensitive : 1; bool casesensitive : 1;
} ComboBox; } ComboBox;
typedef struct ComboItem
{
char *text;
void *data;
} ComboItem;
#define COMBOBOX(widget) ((ComboBox *)jwidget_get_data(widget, JI_COMBOBOX)) #define COMBOBOX(widget) ((ComboBox *)jwidget_get_data(widget, JI_COMBOBOX))
#define IS_VALID_ITEM(widget, index) \ #define IS_VALID_ITEM(widget, index) \
(index >= 0 && index < jlist_length(COMBOBOX(widget)->items)) (index >= 0 && index < jlist_length(COMBOBOX(widget)->items))
@ -58,13 +65,16 @@ static void combobox_close_window(JWidget widget);
static void combobox_switch_window(JWidget widget); static void combobox_switch_window(JWidget widget);
static JRect combobox_get_windowpos(ComboBox *combobox); static JRect combobox_get_windowpos(ComboBox *combobox);
static ComboItem *comboitem_new(const char *text, void *data);
static void comboitem_free(ComboItem *item);
JWidget jcombobox_new(void) JWidget jcombobox_new(void)
{ {
JWidget widget = jbox_new(JI_HORIZONTAL); JWidget widget = jwidget_new(JI_COMBOBOX);
ComboBox *combobox = jnew(ComboBox, 1); ComboBox *combobox = jnew(ComboBox, 1);
combobox->entry = jentry_new(256, ""); combobox->entry = jentry_new(256, "");
combobox->button = jbutton_new("^"); combobox->button = jbutton_new("");
combobox->window = NULL; combobox->window = NULL;
combobox->items = jlist_new(); combobox->items = jlist_new();
combobox->selected = 0; combobox->selected = 0;
@ -91,6 +101,8 @@ JWidget jcombobox_new(void)
jcombobox_editable(widget, combobox->editable); jcombobox_editable(widget, combobox->editable);
jwidget_init_theme(widget);
return widget; return widget;
} }
@ -145,12 +157,13 @@ bool jcombobox_is_casesensitive(JWidget widget)
return combobox->casesensitive; return combobox->casesensitive;
} }
void jcombobox_add_string(JWidget widget, const char *string) void jcombobox_add_string(JWidget widget, const char *string, void *data)
{ {
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
bool sel_first = jlist_empty(combobox->items); bool sel_first = jlist_empty(combobox->items);
ComboItem *item = comboitem_new(string, data);
jlist_append(combobox->items, jstrdup(string)); jlist_append(combobox->items, item);
if (sel_first) if (sel_first)
jcombobox_select_index(widget, 0); jcombobox_select_index(widget, 0);
@ -164,17 +177,34 @@ void jcombobox_del_string(JWidget widget, const char *string)
void jcombobox_del_index(JWidget widget, int index) void jcombobox_del_index(JWidget widget, int index)
{ {
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
ComboItem *item = jlist_nth_data(combobox->items, index);
jlist_remove(combobox->items, jlist_nth_data(combobox->items, index)); jlist_remove(combobox->items, item);
comboitem_free(item);
}
void jcombobox_clear(JWidget widget)
{
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
JLink link;
JI_LIST_FOR_EACH(combobox->items, link)
comboitem_free(link->data);
jlist_clear(combobox->items);
} }
void jcombobox_select_index(JWidget widget, int index) void jcombobox_select_index(JWidget widget, int index)
{ {
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
JLink link = jlist_nth_link(combobox->items, index); JLink link = jlist_nth_link(combobox->items, index);
ComboItem *item;
if (link != combobox->items->end) { if (link != combobox->items->end) {
combobox->selected = index; combobox->selected = index;
jwidget_set_text(combobox->entry, link->data);
item = link->data;
jwidget_set_text(combobox->entry, item->text);
} }
} }
@ -194,15 +224,29 @@ const char *jcombobox_get_selected_string(JWidget widget)
{ {
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
return jlist_nth_data(combobox->items, combobox->selected); return jcombobox_get_string(widget, combobox->selected);
} }
const char *jcombobox_get_string(JWidget widget, int index) const char *jcombobox_get_string(JWidget widget, int index)
{ {
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
if (index >= 0 && index < jlist_length(combobox->items)) if (index >= 0 && index < jlist_length(combobox->items)) {
return jlist_nth_link(combobox->items, index)->data; ComboItem *item = jlist_nth_link(combobox->items, index)->data;
return item->text;
}
else
return NULL;
}
void *jcombobox_get_data(JWidget widget, int index)
{
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
if (index >= 0 && index < jlist_length(combobox->items)) {
ComboItem *item = jlist_nth_link(combobox->items, index)->data;
return item->data;
}
else else
return NULL; return NULL;
} }
@ -214,8 +258,10 @@ int jcombobox_get_index(JWidget widget, const char *string)
JLink link; JLink link;
JI_LIST_FOR_EACH(combobox->items, link) { JI_LIST_FOR_EACH(combobox->items, link) {
if ((combobox->casesensitive && ustrcmp(link->data, string) == 0) || ComboItem *item = link->data;
(!combobox->casesensitive && ustricmp(link->data, string) == 0))
if ((combobox->casesensitive && ustrcmp(item->text, string) == 0) ||
(!combobox->casesensitive && ustricmp(item->text, string) == 0))
return index; return index;
index++; index++;
} }
@ -237,8 +283,17 @@ JWidget jcombobox_get_entry_widget(JWidget widget)
return combobox->entry; return combobox->entry;
} }
JWidget jcombobox_get_button_widget(JWidget widget)
{
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
return combobox->button;
}
static bool combobox_msg_proc(JWidget widget, JMessage msg) static bool combobox_msg_proc(JWidget widget, JMessage msg)
{ {
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
switch (msg->type) { switch (msg->type) {
case JM_CLOSE: case JM_CLOSE:
@ -246,28 +301,65 @@ static bool combobox_msg_proc(JWidget widget, JMessage msg)
break; break;
case JM_DESTROY: case JM_DESTROY:
{ jcombobox_clear(widget);
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); jlist_free(combobox->items);
JLink link; jfree(combobox);
break;
JI_LIST_FOR_EACH(combobox->items, link) case JM_REQSIZE: {
jfree(link->data); int w, h;
jlist_free(combobox->items); msg->reqsize.w = 0;
jfree(combobox); msg->reqsize.h = 0;
jwidget_request_size(combobox->entry, &w, &h);
msg->reqsize.w += w;
msg->reqsize.h += h;
jwidget_request_size(combobox->button, &w, &h);
msg->reqsize.w += w;
msg->reqsize.h = MAX(msg->reqsize.h, h);
return TRUE;
}
case JM_SETPOS: {
JRect cbox = jrect_new_copy(&msg->setpos.rect);
int w, h;
jrect_copy(widget->rc, cbox);
/* button */
jwidget_request_size(combobox->button, &w, &h);
cbox->x1 = msg->setpos.rect.x2 - w;
jwidget_set_rect(combobox->button, cbox);
/* entry */
cbox->x2 = cbox->x1;
cbox->x1 = msg->setpos.rect.x1;
jwidget_set_rect(combobox->entry, cbox);
jrect_free(cbox);
return TRUE;
}
case JM_WINMOVE:
if (combobox->window) {
JRect rc = combobox_get_windowpos(combobox);
jwindow_move(combobox->window, rc);
jrect_free(rc);
} }
break; break;
case JM_WINMOVE: case JM_BUTTONPRESSED:
{ if (combobox->window != NULL) {
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); if (!jwidget_has_mouse(jwidget_get_view(combobox->listbox))) {
if (combobox->window) { combobox_close_window(widget);
JRect rc = combobox_get_windowpos(combobox); return TRUE;
jwindow_move(combobox->window, rc);
jrect_free(rc);
} }
} }
break; break;
} }
return FALSE; return FALSE;
@ -384,20 +476,24 @@ static void combobox_open_window(JWidget widget)
{ {
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX); ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
if (!combobox->window) { if (!combobox->window) {
JWidget view, listbox; JWidget view;
JLink link; JLink link;
int size; int size;
JRect rc; JRect rc;
combobox->window = jwindow_new(NULL); combobox->window = jwindow_new(NULL);
view = jview_new(); view = jview_new();
listbox = jlistbox_new(); combobox->listbox = jlistbox_new();
listbox->user_data[0] = widget; combobox->listbox->user_data[0] = widget;
jwidget_add_hook(listbox, JI_WIDGET, combobox_listbox_msg_proc, NULL); jwidget_add_hook(combobox->listbox, JI_WIDGET,
combobox_listbox_msg_proc, NULL);
JI_LIST_FOR_EACH(combobox->items, link) JI_LIST_FOR_EACH(combobox->items, link) {
jwidget_add_child(listbox, jlistitem_new(link->data)); ComboItem *item = link->data;
jwidget_add_child(combobox->listbox,
jlistitem_new(item->text));
}
jwindow_ontop(combobox->window, TRUE); jwindow_ontop(combobox->window, TRUE);
jwidget_noborders(combobox->window); jwidget_noborders(combobox->window);
@ -406,14 +502,14 @@ static void combobox_open_window(JWidget widget)
jwidget_set_min_size jwidget_set_min_size
(view, (view,
jrect_w(combobox->entry->rc), jrect_w(combobox->entry->rc),
2+(2+jwidget_get_text_height(listbox))*MID(1, size, 10)+2); 2+(2+jwidget_get_text_height(combobox->listbox))*MID(1, size, 10)+2);
jwidget_add_child(combobox->window, view); jwidget_add_child(combobox->window, view);
jview_attach(view, listbox); jview_attach(view, combobox->listbox);
jwidget_signal_off(listbox); jwidget_signal_off(combobox->listbox);
jlistbox_select_index(listbox, combobox->selected); jlistbox_select_index(combobox->listbox, combobox->selected);
jwidget_signal_on(listbox); jwidget_signal_on(combobox->listbox);
jwindow_remap(combobox->window); jwindow_remap(combobox->window);
@ -421,8 +517,10 @@ static void combobox_open_window(JWidget widget)
jwindow_position(combobox->window, rc->x1, rc->y1); jwindow_position(combobox->window, rc->x1, rc->y1);
jrect_free(rc); jrect_free(rc);
jmanager_add_msg_filter(JM_BUTTONPRESSED, widget);
jwindow_open_bg(combobox->window); jwindow_open_bg(combobox->window);
jmanager_set_focus(listbox); jmanager_set_focus(combobox->listbox);
} }
} }
@ -433,6 +531,7 @@ static void combobox_close_window(JWidget widget)
jwindow_close(combobox->window, widget); jwindow_close(combobox->window, widget);
combobox->window = NULL; combobox->window = NULL;
jmanager_remove_msg_filter(JM_BUTTONPRESSED, widget);
jmanager_set_focus(combobox->entry); jmanager_set_focus(combobox->entry);
} }
} }
@ -457,3 +556,23 @@ static JRect combobox_get_windowpos(ComboBox *combobox)
jrect_displace(rc, 0, -(jrect_h(rc)+jrect_h(combobox->entry->rc))); jrect_displace(rc, 0, -(jrect_h(rc)+jrect_h(combobox->entry->rc)));
return rc; return rc;
} }
static ComboItem *comboitem_new(const char *text, void *data)
{
ComboItem *comboitem = jnew(ComboItem, 1);
if (!comboitem)
return NULL;
comboitem->text = jstrdup(text);
comboitem->data = data;
return comboitem;
}
static void comboitem_free(ComboItem *comboitem)
{
if (comboitem->text)
jfree(comboitem->text);
jfree(comboitem);
}

View File

@ -33,6 +33,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#include <allegro/unicode.h>
#include "jinete/jinete.h" #include "jinete/jinete.h"
@ -133,12 +134,27 @@ static JWidget convert_tag_to_widget(Tag *tag)
Attr *right = tag_get_attr(tag, "right"); Attr *right = tag_get_attr(tag, "right");
Attr *top = tag_get_attr(tag, "top"); Attr *top = tag_get_attr(tag, "top");
Attr *bottom = tag_get_attr(tag, "bottom"); Attr *bottom = tag_get_attr(tag, "bottom");
Attr *bevel = tag_get_attr(tag, "bevel");
jwidget_set_align(widget, jwidget_set_align(widget,
(left ? JI_LEFT: (left ? JI_LEFT: (right ? JI_RIGHT: JI_CENTER)) |
right ? JI_RIGHT: JI_CENTER) | (top ? JI_TOP: (bottom ? JI_BOTTOM: JI_MIDDLE)));
(top ? JI_TOP:
bottom ? JI_BOTTOM: JI_MIDDLE)); if (bevel) {
int c, b[4];
char *tok;
for (c=0; c<4; ++c)
b[c] = 0;
for (tok=ustrtok(bevel->value, " "), c=0;
tok;
tok=ustrtok(NULL, " "), ++c) {
if (c < 4)
b[c] = ustrtol(tok, NULL, 10);
}
jbutton_set_bevel(widget, b[0], b[1], b[2], b[3]);
}
} }
} }
} }
@ -155,10 +171,8 @@ static JWidget convert_tag_to_widget(Tag *tag)
Attr *bottom = tag_get_attr(tag, "bottom"); Attr *bottom = tag_get_attr(tag, "bottom");
jwidget_set_align(widget, jwidget_set_align(widget,
(center ? JI_CENTER: (center ? JI_CENTER: (right ? JI_RIGHT: JI_LEFT)) |
right ? JI_RIGHT: JI_LEFT) | (top ? JI_TOP: (bottom ? JI_BOTTOM: JI_MIDDLE)));
(top ? JI_TOP:
bottom ? JI_BOTTOM: JI_MIDDLE));
} }
} }
} }

View File

@ -64,6 +64,7 @@
#include "jinete/jsystem.h" #include "jinete/jsystem.h"
#include "jinete/jtextbox.h" #include "jinete/jtextbox.h"
#include "jinete/jtheme.h" #include "jinete/jtheme.h"
#include "jinete/jthread.h"
#include "jinete/jview.h" #include "jinete/jview.h"
#include "jinete/jwidget.h" #include "jinete/jwidget.h"
#include "jinete/jwindow.h" #include "jinete/jwindow.h"

View File

@ -33,7 +33,7 @@
#include "jinete/jlist.h" #include "jinete/jlist.h"
#ifdef USE_JUNKLIST #ifdef USE_JUNKLIST /* TODO warning not thread safe */
static JList junklist = NULL; static JList junklist = NULL;
#endif #endif

View File

@ -533,12 +533,7 @@ bool jmanager_generate_messages(JWidget manager)
count = 0; count = 0;
while (t - timers[c]->last_time > timers[c]->interval) { while (t - timers[c]->last_time > timers[c]->interval) {
timers[c]->last_time += timers[c]->interval; timers[c]->last_time += timers[c]->interval;
++count;
msg = jmessage_new(JM_TIMER);
msg->timer.count = count;
msg->timer.timer_id = c;
jmessage_add_dest(msg, timers[c]->widget);
jmanager_enqueue_message(msg);
/* we spend too much time here */ /* we spend too much time here */
if (ji_clock - t > timers[c]->interval) { if (ji_clock - t > timers[c]->interval) {
@ -546,6 +541,14 @@ bool jmanager_generate_messages(JWidget manager)
break; break;
} }
} }
if (count > 0) {
msg = jmessage_new(JM_TIMER);
msg->timer.count = count;
msg->timer.timer_id = c;
jmessage_add_dest(msg, timers[c]->widget);
jmanager_enqueue_message(msg);
}
} }
} }
} }
@ -604,11 +607,26 @@ int jmanager_add_timer(JWidget widget, int interval)
void jmanager_remove_timer(int timer_id) void jmanager_remove_timer(int timer_id)
{ {
JMessage message;
JLink link, next;
assert(timer_id >= 0 && timer_id < n_timers); assert(timer_id >= 0 && timer_id < n_timers);
assert(timers[timer_id] != NULL); assert(timers[timer_id] != NULL);
jfree(timers[timer_id]); jfree(timers[timer_id]);
timers[timer_id] = NULL; timers[timer_id] = NULL;
/* remove messages of this timer in the queue */
JI_LIST_FOR_EACH_SAFE(msg_queue, link, next) {
message = link->data;
if (!message->any.used &&
message->any.type == JM_TIMER &&
message->timer.timer_id == timer_id) {
printf("REMOVING A TIMER MESSAGE FROM THE QUEUE!!\n"); fflush(stdout);
jmessage_free(link->data);
jlist_delete_link(msg_queue, link);
}
}
} }
void jmanager_start_timer(int timer_id) void jmanager_start_timer(int timer_id)

View File

@ -31,6 +31,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <allegro/unicode.h>
void *jmalloc(unsigned long n_bytes) void *jmalloc(unsigned long n_bytes)
{ {
@ -80,6 +81,6 @@ void jfree(void *mem)
char *jstrdup(const char *string) char *jstrdup(const char *string)
{ {
return strdup(string); return ustrdup(string);
} }

View File

@ -240,6 +240,13 @@ JAccel jmenuitem_get_accel(JWidget widget)
return MITEM(widget)->accel; return MITEM(widget)->accel;
} }
bool jmenuitem_has_submenu_opened(JWidget widget)
{
assert_valid_widget(widget);
return MITEM(widget)->submenu_menubox != NULL;
}
void jmenubox_set_menu(JWidget widget, JWidget widget_menu) void jmenubox_set_menu(JWidget widget, JWidget widget_menu)
{ {
JWidget old_menu; JWidget old_menu;

View File

@ -45,6 +45,7 @@ JWidget jmenubox_get_menu(JWidget menubox);
JWidget jmenubar_get_menu(JWidget menubar); JWidget jmenubar_get_menu(JWidget menubar);
JWidget jmenuitem_get_submenu(JWidget menuitem); JWidget jmenuitem_get_submenu(JWidget menuitem);
JAccel jmenuitem_get_accel(JWidget menuitem); JAccel jmenuitem_get_accel(JWidget menuitem);
bool jmenuitem_has_submenu_opened(JWidget menuitem);
void jmenubox_set_menu(JWidget menubox, JWidget menu); void jmenubox_set_menu(JWidget menubox, JWidget menu);
void jmenubar_set_menu(JWidget menubar, JWidget menu); void jmenubar_set_menu(JWidget menubar, JWidget menu);

View File

@ -96,7 +96,7 @@ struct jmessage_signal
struct jmessage_timer struct jmessage_timer
{ {
struct jmessage_any any; struct jmessage_any any;
int count; /* cound=0 if it's first msg of timer-chain */ int count; /* accumulated calls */
int timer_id; /* number of timer */ int timer_id; /* number of timer */
}; };

99
src/jinete/jthread.c Normal file
View File

@ -0,0 +1,99 @@
/* Jinete - a GUI library
* Copyright (C) 2003, 2004, 2005, 2007, 2008 David A. Capello.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the Jinete nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <allegro.h>
#include <assert.h>
#include "jinete/jthread.h"
#undef UNIX_LIKE
#if defined ALLEGRO_UNIX || \
defined ALLEGRO_LINUX || \
defined ALLEGRO_MACOSX || \
defined ALLEGRO_BEOS || \
defined ALLEGRO_QNX
#define UNIX_LIKE
#endif
#if defined ALLEGRO_WINDOWS
#include <winalleg.h>
#include <process.h>
#elif defined UNIX_LIKE
#include <pthread.h>
#endif
#if defined UNIX_LIKE
struct pthread_proxy_data {
void (*proc)(JThread thread, void *data);
void *data;
};
static void *pthread_proxy(void *arg)
{
pthread_proxy_data *ptr = arg;
void (*proc)(JThread thread, void *data) = ptr->proc;
void *data = ptr->data;
jfree(ptr);
(*proc)(data);
return NULL;
}
#endif
JThread jthread_new(void (*proc)(void *data), void *data)
{
#if defined ALLEGRO_WINDOWS
return (JThread)_beginthread(proc, 0, data);
#elif defined UNIX_LIKE
pthread_t thread = 0;
struct pthread_proxy_data *ptr = jnew(struct pthread_proxy_data, 1);
ptr->proc = proc;
ptr->data = data;
if (pthread_create(&thread, NULL, pthread_proxy, ptr))
return NULL;
else
return (JThread)thread;
#else
#error ASE doesn\'t support threads for your platform
#endif
}
void jthread_join(JThread thread)
{
#if defined ALLEGRO_WINDOWS
WaitForSingleObject(thread, INFINITE);
#elif defined UNIX_LIKE
pthread_join((pthread_t)thread, NULL);
#else
#error ASE doesn\'t support threads for your platform
#endif
}

44
src/jinete/jthread.h Normal file
View File

@ -0,0 +1,44 @@
/* Jinete - a GUI library
* Copyright (C) 2003, 2004, 2005, 2007, 2008 David A. Capello.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name of the Jinete nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef JINETE_THREAD_H
#define JINETE_THREAD_H
#include "jinete/jbase.h"
JI_BEGIN_DECLS
JThread jthread_new(void (*proc)(void *data), void *data);
void jthread_join(JThread thread);
JI_END_DECLS
#endif /* JINETE_THREAD_H */

View File

@ -232,7 +232,7 @@ JHook jwidget_get_hook(JWidget widget, int type)
*/ */
void *jwidget_get_data(JWidget widget, int type) void *jwidget_get_data(JWidget widget, int type)
{ {
JLink link; register JLink link;
assert_valid_widget(widget); assert_valid_widget(widget);
JI_LIST_FOR_EACH(widget->hooks, link) { JI_LIST_FOR_EACH(widget->hooks, link) {

View File

@ -60,6 +60,7 @@ enum {
ICON_MENU_MARK, ICON_MENU_MARK,
ICON_RADIO_EDGE, ICON_RADIO_EDGE,
ICON_RADIO_MARK, ICON_RADIO_MARK,
ICON_COMBOBOX,
ICONS, ICONS,
}; };
@ -86,12 +87,10 @@ static struct {
{ TRUE, default_theme_imenum }, { TRUE, default_theme_imenum },
{ FALSE, default_theme_iradioe }, { FALSE, default_theme_iradioe },
{ FALSE, default_theme_iradiom }, { FALSE, default_theme_iradiom },
{ FALSE, default_theme_icombobox },
}; };
static BITMAP *icons_bitmap[ICONS] = { static BITMAP *icons_bitmap[ICONS];
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
static void theme_destroy(void); static void theme_destroy(void);
static void theme_regen(void); static void theme_regen(void);
@ -138,11 +137,15 @@ static bool theme_button_msg_proc(JWidget widget, JMessage msg);
JTheme jtheme_new_standard(void) JTheme jtheme_new_standard(void)
{ {
JTheme theme; JTheme theme;
int c;
theme = jtheme_new(); theme = jtheme_new();
if (!theme) if (!theme)
return NULL; return NULL;
for (c=0; c<ICONS; c++)
icons_bitmap[c] = NULL;
theme->name = "Standard Theme"; theme->name = "Standard Theme";
theme->check_icon_size = 8; theme->check_icon_size = 8;
theme->radio_icon_size = 8; theme->radio_icon_size = 8;
@ -327,6 +330,12 @@ static void theme_init_widget(JWidget widget)
BORDER(1); BORDER(1);
break; break;
case JI_COMBOBOX: {
JWidget button = jcombobox_get_button_widget(widget);
ji_generic_button_set_icon(button, icons_bitmap[ICON_COMBOBOX]);
break;
}
case JI_MENU: case JI_MENU:
case JI_MENUBAR: case JI_MENUBAR:
case JI_MENUBOX: case JI_MENUBOX:

View File

@ -296,6 +296,18 @@ static unsigned char default_theme_iclose[66] = {
0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0
}; };
static unsigned char default_theme_icombobox[66] = {
8, 8,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 0, 0,
0, 0, 1, 1, 1, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
static unsigned char default_theme_imenum[66] = { static unsigned char default_theme_imenum[66] = {
8, 8, 8, 8,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

Binary file not shown.

View File

@ -44,7 +44,7 @@ int main(int argc, char *argv[])
set_uformat(U_ASCII); set_uformat(U_ASCII);
/* initialises the application */ /* initialises the application */
if (app_init(argc, argv) < 0) if (!app_init(argc, argv))
return 1; return 1;
app_loop(); app_loop();

View File

@ -206,7 +206,7 @@ void set_current_editor(JWidget editor)
set_current_sprite(editor_get_sprite(current_editor)); set_current_sprite(editor_get_sprite(current_editor));
app_refresh_screen(); app_refresh_screen();
rebuild_sprite_list(); app_realloc_sprite_list();
} }
} }
@ -221,7 +221,7 @@ void set_sprite_in_current_editor(Sprite *sprite)
jwidget_dirty(jwidget_get_view(current_editor)); jwidget_dirty(jwidget_get_view(current_editor));
app_refresh_screen(); app_refresh_screen();
rebuild_sprite_list(); app_realloc_sprite_list();
} }
} }

View File

@ -81,6 +81,8 @@ enum {
GFX_ARROW_LEFT, GFX_ARROW_LEFT,
GFX_ARROW_RIGHT, GFX_ARROW_RIGHT,
GFX_ARROW_UP,
GFX_ARROW_DOWN,
GFX_BOX_SHOW, GFX_BOX_SHOW,
GFX_BOX_HIDE, GFX_BOX_HIDE,

View File

@ -259,14 +259,14 @@ static DATA gfx_data[GFX_BITMAP_COUNT] =
/* GFX_FILE_HOME */ /* GFX_FILE_HOME */
{ 7, 9, { 7, 9,
" # " " # "
" # # " " ### "
" # # " " ##### "
"#######" "#######"
"# #" "#######"
"# ### #" "## ##"
"# # # #" "## ##"
"# # # #" "## ##"
"#######" }, "## ##" },
/* GFX_FILE_FONTS */ /* GFX_FILE_FONTS */
{ 7, 9, { 7, 9,
" " " "
@ -450,6 +450,26 @@ static DATA gfx_data[GFX_BITMAP_COUNT] =
" ## " " ## "
" # " " # "
" " }, " " },
/* GFX_ARROW_UP */
{ 8, 8,
" "
" "
" # "
" ### "
" ##### "
"####### "
" "
" " },
/* GFX_ARROW_DOWN */
{ 8, 8,
" "
" "
"####### "
" ##### "
" ### "
" # "
" "
" " },
/* GFX_BOX_SHOW */ /* GFX_BOX_SHOW */
{ 8, 8, { 8, 8,
" #### " " #### "

View File

@ -54,10 +54,8 @@
#endif #endif
#define REBUILD_LOCK 1 #define REBUILD_RECENT_LIST 2
#define REBUILD_ROOT_MENU 2 #define REFRESH_FULL_SCREEN 4
#define REBUILD_RECENT_LIST 8
#define REBUILD_FULLREFRESH 16
/**************************************************************/ /**************************************************************/
@ -82,7 +80,20 @@ static int try_depths[] = { 32, 24, 16, 15, 8 };
/**************************************************************/ /**************************************************************/
typedef struct Monitor {
/**
* Returns true when the job is done and the monitor can be removed.
*/
bool (*proc)(void *);
void *data;
bool lock;
} Monitor;
static JWidget manager = NULL; static JWidget manager = NULL;
static int monitor_timer = -1;
static JList monitors;
static bool ji_screen_created = FALSE; static bool ji_screen_created = FALSE;
static volatile int next_idle_flags = 0; static volatile int next_idle_flags = 0;
@ -92,6 +103,9 @@ static JList icon_buttons;
static bool double_buffering; static bool double_buffering;
static int screen_scaling; static int screen_scaling;
static Monitor *monitor_new(bool (*proc)(void *), void *data);
static void monitor_free(Monitor *monitor);
/* load & save graphics configuration */ /* load & save graphics configuration */
static void load_gui_config(int *w, int *h, int *bpp, bool *fullscreen); static void load_gui_config(int *w, int *h, int *bpp, bool *fullscreen);
static void save_gui_config(void); static void save_gui_config(void);
@ -106,7 +120,7 @@ static void regen_theme_and_fixup_icons(void);
*/ */
static void display_switch_in_callback() static void display_switch_in_callback()
{ {
next_idle_flags |= REBUILD_FULLREFRESH; next_idle_flags |= REFRESH_FULL_SCREEN;
} }
END_OF_STATIC_FUNCTION(display_switch_in_callback); END_OF_STATIC_FUNCTION(display_switch_in_callback);
@ -222,6 +236,8 @@ int init_module_gui(void)
} }
gfx_done:; gfx_done:;
monitors = jlist_new();
/* create the default-manager */ /* create the default-manager */
manager = jmanager_new(); manager = jmanager_new();
jwidget_add_hook(manager, JI_WIDGET, manager_msg_proc, NULL); jwidget_add_hook(manager, JI_WIDGET, manager_msg_proc, NULL);
@ -261,6 +277,14 @@ int init_module_gui(void)
void exit_module_gui(void) void exit_module_gui(void)
{ {
JLink link;
JI_LIST_FOR_EACH(monitors, link) {
monitor_free(link->data);
}
jlist_free(monitors);
monitors = NULL;
if (double_buffering) { if (double_buffering) {
BITMAP *old_bmp = ji_screen; BITMAP *old_bmp = ji_screen;
ji_set_screen(screen); ji_set_screen(screen);
@ -281,6 +305,24 @@ void exit_module_gui(void)
remove_timer(); remove_timer();
} }
static Monitor *monitor_new(bool (*proc)(void *), void *data)
{
Monitor *monitor = jnew(Monitor, 1);
if (!monitor)
return NULL;
monitor->proc = proc;
monitor->data = data;
monitor->lock = FALSE;
return monitor;
}
static void monitor_free(Monitor *monitor)
{
jfree(monitor);
}
static void load_gui_config(int *w, int *h, int *bpp, bool *fullscreen) static void load_gui_config(int *w, int *h, int *bpp, bool *fullscreen)
{ {
*w = get_config_int("GfxMode", "Width", 0); *w = get_config_int("GfxMode", "Width", 0);
@ -347,23 +389,14 @@ void gui_run(void)
void gui_feedback(void) void gui_feedback(void)
{ {
/* menu stuff */ /* menu stuff */
if (!(next_idle_flags & REBUILD_LOCK)) { if (next_idle_flags & REBUILD_RECENT_LIST) {
if (next_idle_flags & REBUILD_ROOT_MENU) { if (app_realloc_recent_list())
next_idle_flags ^= REBUILD_ROOT_MENU;
load_root_menu();
next_idle_flags |= REBUILD_RECENT_LIST;
}
if (next_idle_flags & REBUILD_RECENT_LIST) {
next_idle_flags ^= REBUILD_RECENT_LIST; next_idle_flags ^= REBUILD_RECENT_LIST;
app_realloc_recent_list(); }
}
if (next_idle_flags & REBUILD_FULLREFRESH) { if (next_idle_flags & REFRESH_FULL_SCREEN) {
next_idle_flags ^= REBUILD_FULLREFRESH; next_idle_flags ^= REFRESH_FULL_SCREEN;
update_screen_for_sprite(current_sprite); update_screen_for_sprite(current_sprite);
}
} }
/* record file if is necessary */ /* record file if is necessary */
@ -534,26 +567,6 @@ JWidget load_widget(const char *filename, const char *name)
return widget; return widget;
} }
void rebuild_lock(void)
{
next_idle_flags |= REBUILD_LOCK;
}
void rebuild_unlock(void)
{
next_idle_flags &= ~REBUILD_LOCK;
}
void rebuild_root_menu(void)
{
next_idle_flags |= REBUILD_ROOT_MENU;
}
void rebuild_sprite_list(void)
{
app_realloc_sprite_list();
}
void rebuild_recent_list(void) void rebuild_recent_list(void)
{ {
next_idle_flags |= REBUILD_RECENT_LIST; next_idle_flags |= REBUILD_RECENT_LIST;
@ -708,6 +721,16 @@ JWidget check_button_new(const char *text, int b1, int b2, int b3, int b4)
return widget; return widget;
} }
void add_gui_monitor(bool (*proc)(void *data), void *data)
{
jlist_append(monitors, monitor_new(proc, data));
if (monitor_timer < 0)
monitor_timer = jmanager_add_timer(manager, 100);
jmanager_start_timer(monitor_timer);
}
/**********************************************************************/ /**********************************************************************/
/* manager event handler */ /* manager event handler */
@ -719,6 +742,32 @@ static bool manager_msg_proc(JWidget widget, JMessage msg)
gui_feedback(); gui_feedback();
break; break;
case JM_TIMER:
if (msg->timer.timer_id == monitor_timer) {
JLink link, next;
JI_LIST_FOR_EACH_SAFE(monitors, link, next) {
Monitor *monitor = link->data;
/* is the monitor not lock? */
if (!monitor->lock) {
/* call the monitor procedure */
monitor->lock = TRUE;
if ((*monitor->proc)(monitor->data)) {
/* the function returns true, the job is done... remove the monitor */
monitor_free(link->data);
jlist_delete_link(monitors, link);
}
else
monitor->lock = FALSE;
}
}
/* is monitors empty? we can stop the timer so */
if (jlist_empty(monitors))
jmanager_stop_timer(monitor_timer);
}
break;
case JM_CHAR: { case JM_CHAR: {
Command *command = command_get_by_key(msg); Command *command = command_get_by_key(msg);
if (!command) if (!command)

View File

@ -45,10 +45,6 @@ void save_window_pos(JWidget window, const char *section);
JWidget load_widget(const char *filename, const char *name); JWidget load_widget(const char *filename, const char *name);
void rebuild_lock(void);
void rebuild_unlock(void);
void rebuild_root_menu(void);
void rebuild_sprite_list(void);
void rebuild_recent_list(void); void rebuild_recent_list(void);
void hook_signal(JWidget widget, void hook_signal(JWidget widget,
@ -65,4 +61,6 @@ JWidget radio_button_new(int radio_group, int b1, int b2, int b3, int b4);
JWidget check_button_new(const char *text, int b1, int b2, int b3, int b4); JWidget check_button_new(const char *text, int b1, int b2, int b3, int b4);
/* void change_to_button_style(JWidget widget, int b1, int b2, int b3, int b4); */ /* void change_to_button_style(JWidget widget, int b1, int b2, int b3, int b4); */
void add_gui_monitor(bool (*proc)(void *data), void *data);
#endif /* MODULES_GUI_H */ #endif /* MODULES_GUI_H */

View File

@ -46,6 +46,7 @@ static JWidget frame_popup_menu;
static JWidget cel_popup_menu; static JWidget cel_popup_menu;
static JWidget filters_popup_menu; static JWidget filters_popup_menu;
static int load_root_menu(void);
static JWidget load_menu_by_id(JXml xml, const char *id, const char *filename); static JWidget load_menu_by_id(JXml xml, const char *id, const char *filename);
static JWidget convert_xmlelem_to_menu(JXmlElem elem); static JWidget convert_xmlelem_to_menu(JXmlElem elem);
static JWidget convert_xmlelem_to_menuitem(JXmlElem elem); static JWidget convert_xmlelem_to_menuitem(JXmlElem elem);
@ -75,7 +76,24 @@ void exit_module_rootmenu(void)
if (filters_popup_menu) jwidget_free(filters_popup_menu); if (filters_popup_menu) jwidget_free(filters_popup_menu);
} }
int load_root_menu(void) JWidget get_root_menu(void) { return root_menu; }
JWidget get_recent_list_menuitem(void) { return recent_list_menuitem; }
JWidget get_layer_popup_menu(void) { return layer_popup_menu; }
JWidget get_frame_popup_menu(void) { return frame_popup_menu; }
JWidget get_cel_popup_menu(void) { return cel_popup_menu; }
/* void show_fx_popup_menu(void) */
/* { */
/* if (is_interactive() && */
/* filters_popup_menuitem && */
/* jmenuitem_get_submenu(filters_popup_menuitem)) { */
/* jmenu_popup(jmenuitem_get_submenu(filters_popup_menuitem), */
/* jmouse_x(0), jmouse_y(0)); */
/* } */
/* } */
static int load_root_menu(void)
{ {
JLink link, link2; JLink link, link2;
DIRS *dirs, *dir; DIRS *dirs, *dir;
@ -199,23 +217,6 @@ int load_root_menu(void)
return 0; return 0;
} }
JWidget get_root_menu(void) { return root_menu; }
JWidget get_recent_list_menuitem(void) { return recent_list_menuitem; }
JWidget get_layer_popup_menu(void) { return layer_popup_menu; }
JWidget get_frame_popup_menu(void) { return frame_popup_menu; }
JWidget get_cel_popup_menu(void) { return cel_popup_menu; }
/* void show_fx_popup_menu(void) */
/* { */
/* if (is_interactive() && */
/* filters_popup_menuitem && */
/* jmenuitem_get_submenu(filters_popup_menuitem)) { */
/* jmenu_popup(jmenuitem_get_submenu(filters_popup_menuitem), */
/* jmouse_x(0), jmouse_y(0)); */
/* } */
/* } */
static JWidget load_menu_by_id(JXml xml, const char *id, const char *filename) static JWidget load_menu_by_id(JXml xml, const char *id, const char *filename)
{ {
JWidget menu = NULL; JWidget menu = NULL;

View File

@ -33,8 +33,6 @@ enum {
int init_module_rootmenu(void); int init_module_rootmenu(void);
void exit_module_rootmenu(void); void exit_module_rootmenu(void);
int load_root_menu(void);
JWidget get_root_menu(void); JWidget get_root_menu(void);
JWidget get_recent_list_menuitem(void); JWidget get_recent_list_menuitem(void);

View File

@ -115,7 +115,7 @@ void set_clipboard_sprite(Sprite *sprite)
clipboard_sprite = sprite; clipboard_sprite = sprite;
if (is_interactive()) if (is_interactive())
rebuild_sprite_list(); app_realloc_sprite_list();
} }
/* adds the "sprite" in the list of sprites */ /* adds the "sprite" in the list of sprites */
@ -130,7 +130,7 @@ void sprite_mount(Sprite *sprite)
get_filename(sprite->filename), sprite); get_filename(sprite->filename), sprite);
/* rebuild the menu list of sprites */ /* rebuild the menu list of sprites */
rebuild_sprite_list(); app_realloc_sprite_list();
} }
} }
@ -149,7 +149,7 @@ void sprite_unmount(Sprite *sprite)
tabs_remove_tab(app_get_tabs_bar(), sprite); tabs_remove_tab(app_get_tabs_bar(), sprite);
/* rebuild the menu list of sprites */ /* rebuild the menu list of sprites */
rebuild_sprite_list(); app_realloc_sprite_list();
/* select other sprites in the editors where are this sprite */ /* select other sprites in the editors where are this sprite */
editors_hide_sprite(sprite); editors_hide_sprite(sprite);

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello * Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -24,6 +24,7 @@
#include "jinete/jbase.h" #include "jinete/jbase.h"
#include "jinete/jlist.h" #include "jinete/jlist.h"
#include "jinete/jmutex.h"
#include "raster/gfxobj.h" #include "raster/gfxobj.h"
@ -35,46 +36,79 @@
/* void *data; */ /* void *data; */
/* } Property; */ /* } Property; */
static JMutex objects_mutex;
static unsigned int object_id = 0; /* last object ID created */ static unsigned int object_id = 0; /* last object ID created */
static JList objects; /* graphics objects list */ static JList objects; /* graphics objects list */
GfxObj *gfxobj_new (int type, int size) bool gfxobj_init(void)
{
objects_mutex = jmutex_new();
if (!objects_mutex)
return FALSE;
objects = jlist_new();
if (!objects)
return FALSE;
return TRUE;
}
void gfxobj_exit(void)
{
jlist_free(objects);
jmutex_free(objects_mutex);
}
GfxObj *gfxobj_new(int type, int size)
{ {
GfxObj *gfxobj; GfxObj *gfxobj;
gfxobj = jmalloc (size); gfxobj = jmalloc(size);
if (!gfxobj) if (!gfxobj)
return NULL; return NULL;
gfxobj->type = type; jmutex_lock(objects_mutex);
gfxobj->id = ++object_id; {
/* gfxobj->properties = NULL; */ gfxobj->type = type;
gfxobj->id = ++object_id;
if (!objects) /* gfxobj->properties = NULL; */
objects = jlist_new(); jlist_append(objects, gfxobj);
jlist_append(objects, gfxobj); }
jmutex_unlock(objects_mutex);
return gfxobj; return gfxobj;
} }
void gfxobj_free (GfxObj *gfxobj) void gfxobj_free(GfxObj *gfxobj)
{ {
jlist_remove (objects, gfxobj); jmutex_lock(objects_mutex);
jfree (gfxobj); {
jlist_remove(objects, gfxobj);
}
jmutex_unlock(objects_mutex);
jfree(gfxobj);
} }
GfxObj *gfxobj_find (unsigned int id) GfxObj *gfxobj_find(unsigned int id)
{ {
GfxObj *ret = NULL;
JLink link; JLink link;
jmutex_lock(objects_mutex);
{
JI_LIST_FOR_EACH(objects, link) JI_LIST_FOR_EACH(objects, link)
if (((GfxObj *)link->data)->id == id) if (((GfxObj *)link->data)->id == id) {
return (GfxObj *)link->data; ret = (GfxObj *)link->data;
break;
}
}
jmutex_unlock(objects_mutex);
return NULL; return ret;
} }
void _gfxobj_set_id (GfxObj *gfxobj, int id) void _gfxobj_set_id(GfxObj *gfxobj, int id)
{ {
/* TODO */ /* TODO */
/* ji_assert (!gfxobj_find (id)); */ /* ji_assert (!gfxobj_find (id)); */
@ -83,7 +117,7 @@ void _gfxobj_set_id (GfxObj *gfxobj, int id)
} }
#if 0 #if 0
void gfxobj_set_data (GfxObj *gfxobj, const char *key, void *data) void gfxobj_set_data(GfxObj *gfxobj, const char *key, void *data)
{ {
Property *property; Property *property;

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello * Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -45,6 +45,9 @@ struct GfxObj
/* struct GfxObjProperty *properties; */ /* struct GfxObjProperty *properties; */
}; };
bool gfxobj_init(void);
void gfxobj_exit(void);
GfxObj *gfxobj_new(int type, int size); GfxObj *gfxobj_new(int type, int size);
void gfxobj_free(GfxObj *gfxobj); void gfxobj_free(GfxObj *gfxobj);

View File

@ -38,10 +38,8 @@ typedef struct PAL
PALETTE pal; PALETTE pal;
} PAL; } PAL;
static int index_count; static Layer *index2layer(Layer *layer, int index, int *index_count);
static int layer2index(const Layer *layer, const Layer *find_layer, int *index_count);
static Layer *index2layer(Layer *layer, int index);
static int layer2index(const Layer *layer, const Layer *find_layer);
static Sprite *general_copy(const Sprite *sprite); static Sprite *general_copy(const Sprite *sprite);
@ -316,6 +314,20 @@ void sprite_mark_as_saved(Sprite *sprite)
sprite->associated_to_file = TRUE; sprite->associated_to_file = TRUE;
} }
bool sprite_need_alpha(Sprite *sprite)
{
switch (sprite->imgtype) {
case IMAGE_RGB:
return _rgba_geta(sprite->bgcolor) < 255;
case IMAGE_GRAYSCALE:
return _graya_geta(sprite->bgcolor) < 255;
}
return FALSE;
}
bool sprite_lock(Sprite *sprite) bool sprite_lock(Sprite *sprite)
{ {
bool res = FALSE; bool res = FALSE;
@ -734,31 +746,31 @@ void sprite_generate_mask_boundaries(Sprite *sprite)
Layer *sprite_index2layer(Sprite *sprite, int index) Layer *sprite_index2layer(Sprite *sprite, int index)
{ {
index_count = -1; int index_count = -1;
return index2layer(sprite->set, index); return index2layer(sprite->set, index, &index_count);
} }
int sprite_layer2index(const Sprite *sprite, const Layer *layer) int sprite_layer2index(const Sprite *sprite, const Layer *layer)
{ {
index_count = -1; int index_count = -1;
return layer2index(sprite->set, layer); return layer2index(sprite->set, layer, &index_count);
} }
static Layer *index2layer(Layer *layer, int index) static Layer *index2layer(Layer *layer, int index, int *index_count)
{ {
if (index == index_count) if (index == *index_count)
return layer; return layer;
else { else {
index_count++; (*index_count)++;
if (layer_is_set (layer)) { if (layer_is_set (layer)) {
Layer *found; Layer *found;
JLink link; JLink link;
JI_LIST_FOR_EACH(layer->layers, link) { JI_LIST_FOR_EACH(layer->layers, link) {
if ((found = index2layer(link->data, index))) if ((found = index2layer(link->data, index, index_count)))
return found; return found;
} }
} }
@ -767,19 +779,19 @@ static Layer *index2layer(Layer *layer, int index)
} }
} }
static int layer2index(const Layer *layer, const Layer *find_layer) static int layer2index(const Layer *layer, const Layer *find_layer, int *index_count)
{ {
if (layer == find_layer) if (layer == find_layer)
return index_count; return *index_count;
else { else {
index_count++; (*index_count)++;
if (layer_is_set (layer)) { if (layer_is_set(layer)) {
JLink link; JLink link;
int found; int found;
JI_LIST_FOR_EACH(layer->layers, link) { JI_LIST_FOR_EACH(layer->layers, link) {
if ((found = layer2index(link->data, find_layer)) >= 0) if ((found = layer2index(link->data, find_layer, index_count)) >= 0)
return found; return found;
} }
} }

View File

@ -80,6 +80,8 @@ bool sprite_is_associated_to_file(Sprite *sprite);
bool sprite_is_locked(Sprite *sprite); bool sprite_is_locked(Sprite *sprite);
void sprite_mark_as_saved(Sprite *sprite); void sprite_mark_as_saved(Sprite *sprite);
bool sprite_need_alpha(Sprite *sprite);
bool sprite_lock(Sprite *sprite); bool sprite_lock(Sprite *sprite);
void sprite_unlock(Sprite *sprite); void sprite_unlock(Sprite *sprite);

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello * Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -24,6 +24,7 @@
#include "jinete/jinete.h" #include "jinete/jinete.h"
#include "console/console.h" #include "console/console.h"
#include "core/app.h"
#include "file/file.h" #include "file/file.h"
#include "modules/gui.h" #include "modules/gui.h"
#include "modules/sprites.h" #include "modules/sprites.h"
@ -128,7 +129,7 @@ void SaveSprite(const char *filename)
} }
sprite_set_filename(current_sprite, filename); sprite_set_filename(current_sprite, filename);
rebuild_sprite_list(); app_realloc_sprite_list();
if (sprite_save(current_sprite) == 0) if (sprite_save(current_sprite) == 0)
sprite_mark_as_saved(current_sprite); sprite_mark_as_saved(current_sprite);

View File

@ -16,19 +16,24 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#ifndef FILE_ASE_H #ifndef TEST_TEST_H
#define FILE_ASE_H #define TEST_TEST_H
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <allegro.h>
struct Sprite; void trace(const char *format, ...)
{
char buf[4096];
va_list ap;
struct Sprite *ase_file_read_f(FILE *f); va_start(ap, format);
int ase_file_write_f(FILE *f, struct Sprite *sprite); uvszprintf(buf, sizeof(buf), format, ap);
va_end(ap);
int fgetw(FILE *file); fputs(buf, stdout);
long fgetl(FILE *file); fflush(stdout);
int fputw(int w, FILE *file); }
int fputl(long l, FILE *file);
#endif /* FILE_ASE_H */ #endif /* TEST_TEST_H */

106
src/test/test_file_system.c Normal file
View File

@ -0,0 +1,106 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "test/test.h"
#include "jinete/jinete.h"
#include "core/file_system.h"
static void display_fileitem(FileItem *fi, int level, int deep)
{
JList list;
JLink link;
int c;
if (level == 0)
printf("+ ");
else
printf(" ");
for (c=0; c<level; ++c)
printf(" ");
printf("%s (%s)\n",
fileitem_get_filename(fi),
fileitem_get_displayname(fi));
fflush(stdout);
if (!fileitem_is_browsable(fi) || deep == 0)
return;
list = fileitem_get_children(fi);
if (list) {
JI_LIST_FOR_EACH(list, link) {
display_fileitem(link->data, level+1, deep-1);
}
}
}
int main(int argc, char *argv[])
{
allegro_init();
assert(file_system_init());
trace("*** Listing root of the file-system (deep = 2)...\n");
{
FileItem *root = get_root_fileitem();
assert(root != NULL);
display_fileitem(root, 0, 2);
}
#ifdef ALLEGRO_WINDOWS
trace("*** Testing specific directories retrieval...\n");
{
FileItem *c_drive;
FileItem *my_pc;
trace("*** Getting 'C:\\' using 'get_fileitem_from_path'...\n");
c_drive = get_fileitem_from_path("C:\\");
assert(c_drive != NULL);
trace("*** Displaying 'C:\\'...\n");
display_fileitem(c_drive, 0, 0);
trace("*** Getting 'My PC' (using 'fileitem_get_parent')...\n");
my_pc = fileitem_get_parent(c_drive);
assert(my_pc != NULL);
trace("*** Listing 'My PC'...\n");
display_fileitem(my_pc, 0, 1);
}
#endif
trace("*** Testing 'filename_has_extension'...\n");
{
assert(filename_has_extension("hi.png", "png"));
assert(!filename_has_extension("hi.png", "pngg"));
assert(!filename_has_extension("hi.png", "ppng"));
assert(filename_has_extension("hi.jpeg", "jpg,jpeg"));
assert(filename_has_extension("hi.jpg", "jpg,jpeg"));
assert(!filename_has_extension("hi.ase", "jpg,jpeg"));
assert(filename_has_extension("hi.ase", "jpg,jpeg,ase"));
assert(filename_has_extension("hi.ase", "ase,jpg,jpeg"));
trace("+ All OK.\n");
}
file_system_exit();
allegro_exit();
return 0;
}
END_OF_MAIN();

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello * Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -19,23 +19,25 @@
#ifndef UTIL_HASH_H #ifndef UTIL_HASH_H
#define UTIL_HASH_H #define UTIL_HASH_H
typedef struct HashBucket { typedef struct HashBucket
{
char *key; char *key;
void *data; void *data;
struct HashBucket *next; struct HashBucket *next;
} HashBucket; } HashBucket;
typedef struct HashTable { typedef struct HashTable
{
int size; int size;
HashBucket **table; HashBucket **table;
} HashTable; } HashTable;
HashTable *hash_new (int size); HashTable *hash_new(int size);
void hash_free (HashTable *table, void (*func) (void *)); void hash_free(HashTable *table, void (*func)(void *));
void *hash_insert (HashTable *table, const char *key, void *data); void *hash_insert(HashTable *table, const char *key, void *data);
void *hash_lookup (HashTable *table, const char *key); void *hash_lookup(HashTable *table, const char *key);
void *hash_remove (HashTable *table, const char *key); void *hash_remove(HashTable *table, const char *key);
void hash_enumerate (HashTable *table, void (*callback) (const char *, void *)); void hash_enumerate(HashTable *table, void (*callback)(const char *, void *));
#endif /* UTIL_HASH_H */ #endif /* UTIL_HASH_H */

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello * Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -29,8 +29,9 @@
#include <stdlib.h> #include <stdlib.h>
#include "console/console.h" #include "core/app.h"
#include "raster/image.h" #include "raster/image.h"
#include "widgets/statebar.h"
#endif #endif
@ -40,6 +41,7 @@ static float FRandom (float amount);
void mapgen (Image *image, int seed, float fractal_factor) void mapgen (Image *image, int seed, float fractal_factor)
{ {
Progress *progress = NULL;
float **map; float **map;
float amount = 128; float amount = 128;
float min, max; float min, max;
@ -51,9 +53,9 @@ void mapgen (Image *image, int seed, float fractal_factor)
/**********************************************************************/ /**********************************************************************/
/* create the map */ /* create the map */
map = malloc (sizeof (float *) * size); map = malloc (sizeof(float *) * size);
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
map[i] = malloc (sizeof (float) * size); map[i] = malloc(sizeof(float) * size);
/* Do the corners */ /* Do the corners */
map[0][0] = 0; /* map[0][0] = FRandom(amount); */ map[0][0] = 0; /* map[0][0] = FRandom(amount); */
@ -62,7 +64,9 @@ void mapgen (Image *image, int seed, float fractal_factor)
map[0][size-1] = map[0][0]; map[0][size-1] = map[0][0];
amount /= fractal_factor; amount /= fractal_factor;
add_progress (128); if (app_get_status_bar())
progress = progress_new(app_get_status_bar());
for (i=128; i>0; i/=2) { for (i=128; i>0; i/=2) {
/* This is the square phase */ /* This is the square phase */
for (j=i; j<size; j+=2*i) for (j=i; j<size; j+=2*i)
@ -92,9 +96,12 @@ void mapgen (Image *image, int seed, float fractal_factor)
amount /= fractal_factor; amount /= fractal_factor;
do_progress (100 * (128-i) / 128); if (progress)
progress_update(progress, (128.0f-i) / 128.0f);
} }
del_progress ();
if (progress)
progress_free(progress);
/**********************************************************************/ /**********************************************************************/
/* Copy the map to the image */ /* Copy the map to the image */
@ -112,12 +119,12 @@ void mapgen (Image *image, int seed, float fractal_factor)
k = (int)((map[i][j] - min)/(max - min) * 256); k = (int)((map[i][j] - min)/(max - min) * 256);
if (k > 255) if (k > 255)
k = 255; k = 255;
image_putpixel (image, i, j, k); image_putpixel(image, i, j, k);
} }
for (i=0; i<size; i++) for (i=0; i<size; i++)
jfree (map[i]); jfree(map[i]);
jfree (map); jfree(map);
} }
/* Handles wrapping when seeking neighbours */ /* Handles wrapping when seeking neighbours */

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello * Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -304,10 +304,10 @@ int quantize_bitmaps1 (Stock *stock, RGB *pal, int *bmp_i, int fill_other)
/*Create the tree structure*/ /*Create the tree structure*/
tree=create_node(0,0,0,64,64,64,0); tree=create_node(0,0,0,64,64,64,0);
/*Scan the bitmaps*/ /*Scan the bitmaps*/
add_progress(stock->nimage+1); /* add_progress(stock->nimage+1); */
for (c_bmp=0;c_bmp<stock->nimage;c_bmp++) { for (c_bmp=0;c_bmp<stock->nimage;c_bmp++) {
if (stock->image[c_bmp]) { if (stock->image[c_bmp]) {
add_progress(stock->image[c_bmp]->h); /* add_progress(stock->image[c_bmp]->h); */
for (y=0;y<stock->image[c_bmp]->h;y++) { for (y=0;y<stock->image[c_bmp]->h;y++) {
for (x=0;x<stock->image[c_bmp]->w;x++) { for (x=0;x<stock->image[c_bmp]->w;x++) {
c=stock->image[c_bmp]->method->getpixel(stock->image[c_bmp],x,y); c=stock->image[c_bmp]->method->getpixel(stock->image[c_bmp],x,y);
@ -327,11 +327,11 @@ int quantize_bitmaps1 (Stock *stock, RGB *pal, int *bmp_i, int fill_other)
node=node->parent; node=node->parent;
} while (node); } while (node);
} }
do_progress(y); /* do_progress(y); */
} }
del_progress(); /* del_progress(); */
} }
do_progress(c_bmp); /* do_progress(c_bmp); */
} }
/*Collapse empty nodes in the tree, and count leaves*/ /*Collapse empty nodes in the tree, and count leaves*/
tree=collapse_empty(tree,&n_colours); tree=collapse_empty(tree,&n_colours);
@ -341,19 +341,19 @@ int quantize_bitmaps1 (Stock *stock, RGB *pal, int *bmp_i, int fill_other)
} }
/*Collapse nodes until there are few enough to fit in the palette*/ /*Collapse nodes until there are few enough to fit in the palette*/
if (n_colours > n_entries) { if (n_colours > n_entries) {
int n_colours1 = n_colours; /* int n_colours1 = n_colours; */
add_progress(n_colours1 - n_entries); /* add_progress(n_colours1 - n_entries); */
while (n_colours>n_entries) { while (n_colours>n_entries) {
Ep=0xFFFFFFFFul; Ep=0xFFFFFFFFul;
minimum_Ep(tree,&Ep); minimum_Ep(tree,&Ep);
tree=collapse_nodes(tree,&n_colours,n_entries,Ep); tree=collapse_nodes(tree,&n_colours,n_entries,Ep);
if (n_colours > n_entries) /* if (n_colours > n_entries) */
do_progress(n_colours1 - n_colours); /* do_progress(n_colours1 - n_colours); */
} }
del_progress(); /* del_progress(); */
} }
del_progress(); /* del_progress(); */
/*Fill palette*/ /*Fill palette*/
c=0; c=0;
fill_palette(tree,&c,pal,1); fill_palette(tree,&c,pal,1);

View File

@ -1068,8 +1068,7 @@ static bool editor_msg_proc(JWidget widget, JMessage msg)
} }
case JM_TIMER: case JM_TIMER:
if (msg->timer.timer_id == editor->mask_timer_id && if (msg->timer.timer_id == editor->mask_timer_id) {
msg->timer.count == 0) {
if (editor->sprite) { if (editor->sprite) {
editor_draw_mask_safe(widget); editor_draw_mask_safe(widget);

489
src/widgets/fileview.c Normal file
View File

@ -0,0 +1,489 @@
/* ASE - Allegro Sprite Editor
* Copyright (C) 2008 David A. Capello
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#ifndef USE_PRECOMPILED_HEADER
#include <assert.h>
#include <allegro.h>
#include "jinete/jinete.h"
#include "modules/gfx.h"
#include "widgets/fileview.h"
#endif
typedef struct FileView
{
FileItem *current_folder;
JList list;
bool req_valid;
int req_w, req_h;
FileItem *selected;
const char *exts;
} FileView;
static FileView *fileview_data(JWidget widget);
static bool fileview_msg_proc(JWidget widget, JMessage msg);
static void fileview_get_fileitem_size(JWidget widget, FileItem *fi, int *w, int *h);
static void fileview_make_selected_fileitem_visible(JWidget widget);
static void fileview_regenerate_list(JWidget widget);
static int fileview_get_selected_index(JWidget widget);
static void fileview_select_index(JWidget widget, int index);
JWidget fileview_new(FileItem *start_folder, const char *exts)
{
JWidget widget = jwidget_new(fileview_type());
FileView *fileview = jnew(FileView, 1);
if (!start_folder)
start_folder = get_root_fileitem();
else {
while (!fileitem_is_folder(start_folder) &&
fileitem_get_parent(start_folder) != NULL) {
start_folder = fileitem_get_parent(start_folder);
}
}
jwidget_add_hook(widget, fileview_type(),
fileview_msg_proc, fileview);
jwidget_focusrest(widget, TRUE);
fileview->current_folder = start_folder;
fileview->list = NULL;
fileview->req_valid = FALSE;
fileview->selected = NULL;
fileview->exts = exts;
fileview_regenerate_list(widget);
return widget;
}
int fileview_type(void)
{
static int type = 0;
if (!type)
type = ji_register_widget_type();
return type;
}
FileItem *fileview_get_current_folder(JWidget widget)
{
return fileview_data(widget)->current_folder;
}
FileItem *fileview_get_selected(JWidget widget)
{
return fileview_data(widget)->selected;
}
void fileview_set_current_folder(JWidget widget, FileItem *folder)
{
FileView *fileview = fileview_data(widget);
assert(folder != NULL);
assert(fileitem_is_browsable(folder));
fileview->current_folder = folder;
fileview->req_valid = FALSE;
fileview->selected = NULL;
fileview_regenerate_list(widget);
/* select first folder */
if (!jlist_empty(fileview->list) &&
fileitem_is_browsable(jlist_first_data(fileview->list))) {
fileview_select_index(widget, 0);
}
jwidget_emit_signal(widget, SIGNAL_FILEVIEW_CURRENT_FOLDER_CHANGED);
jwidget_dirty(widget);
jview_update(jwidget_get_view(widget));
}
void fileview_goup(JWidget widget)
{
FileView *fileview = fileview_data(widget);
FileItem *folder = fileview->current_folder;
FileItem *parent = fileitem_get_parent(folder);
if (parent) {
fileview_set_current_folder(widget, parent);
fileview->selected = folder;
}
}
static FileView *fileview_data(JWidget widget)
{
return jwidget_get_data(widget, fileview_type());
}
static bool fileview_msg_proc(JWidget widget, JMessage msg)
{
FileView *fileview = fileview_data(widget);
switch (msg->type) {
case JM_DESTROY:
jfree(fileview);
break;
case JM_REQSIZE:
if (!fileview->req_valid) {
FileItem *fileitem;
int w, h, iw, ih;
JLink link;
w = 0;
h = 0;
/* rows */
JI_LIST_FOR_EACH(fileview->list, link) {
fileitem = link->data;
fileview_get_fileitem_size(widget, fileitem, &iw, &ih);
w = MAX(w, iw);
h += ih;
}
fileview->req_valid = TRUE;
fileview->req_w = w;
fileview->req_h = h;
}
msg->reqsize.w = fileview->req_w;
msg->reqsize.h = fileview->req_h;
return TRUE;
case JM_DRAW: {
FileItem *fi;
JLink link;
int iw, ih;
int th = jwidget_get_text_height(widget);
int x, y = widget->rc->y1;
int row = 0;
int bgcolor;
int fgcolor;
jdraw_rectfill(widget->rc, makecol(255, 255, 255));
/* rows */
JI_LIST_FOR_EACH(fileview->list, link) {
fi = link->data;
fileview_get_fileitem_size(widget, fi, &iw, &ih);
if (fi == fileview->selected) {
bgcolor = ji_color_selected();
fgcolor = ji_color_background();
}
else {
bgcolor = row ? makecol(240, 240, 240):
makecol(255, 255, 255);
fgcolor =
fileitem_is_folder(fi) &&
!fileitem_is_browsable(fi) ? makecol(255, 200, 200):
ji_color_foreground();
}
rectfill(ji_screen,
widget->rc->x1, y,
widget->rc->x2-1, y+2+th+2-1,
bgcolor);
x = widget->rc->x1+2;
if (fileitem_is_folder(fi)) {
jdraw_text(widget->text_font,
"[+]", x, y+2,
fgcolor, 0, FALSE);
x += ji_font_text_len(widget->text_font, "[+]")+2;
}
jdraw_text(widget->text_font,
fileitem_get_displayname(fi), x, y+2,
fgcolor, 0, FALSE);
y += ih;
row ^= 1;
}
break;
}
case JM_BUTTONPRESSED:
jwidget_capture_mouse(widget);
case JM_MOTION:
if (jwidget_has_capture(widget)) {
FileItem *fi;
JLink link;
int iw, ih;
int th = jwidget_get_text_height(widget);
int y = widget->rc->y1;
FileItem *old_selected = fileview->selected;
fileview->selected = NULL;
/* rows */
JI_LIST_FOR_EACH(fileview->list, link) {
fi = link->data;
fileview_get_fileitem_size(widget, fi, &iw, &ih);
if (((msg->mouse.y >= y) && (msg->mouse.y < y+2+th+2)) ||
(link == jlist_first(fileview->list) && msg->mouse.y < y) ||
(link == jlist_last(fileview->list) && msg->mouse.y >= y+2+th+2)) {
fileview->selected = fi;
fileview_make_selected_fileitem_visible(widget);
break;
}
y += ih;
}
if (old_selected != fileview->selected) {
jwidget_dirty(widget);
jwidget_emit_signal(widget, SIGNAL_FILEVIEW_FILE_SELECTED);
}
}
break;
case JM_BUTTONRELEASED:
if (jwidget_has_capture(widget)) {
jwidget_release_mouse(widget);
}
break;
case JM_CHAR:
if (jwidget_has_focus(widget)) {
int select = fileview_get_selected_index(widget);
JWidget view = jwidget_get_view(widget);
int bottom = MAX(0, jlist_length(fileview->list)-1);
switch (msg->key.scancode) {
case KEY_UP:
if (select >= 0)
select--;
else
select = 0;
break;
case KEY_DOWN:
if (select >= 0)
select++;
else
select = 0;
break;
case KEY_HOME:
select = 0;
break;
case KEY_END:
select = bottom;
break;
case KEY_PGUP:
case KEY_PGDN: {
int sgn = (msg->key.scancode == KEY_PGUP) ? -1: 1;
JRect vp = jview_get_viewport_position(view);
if (select < 0)
select = 0;
select += sgn * jrect_h(vp) / (2+jwidget_get_text_height(widget)+2);
jrect_free(vp);
break;
}
case KEY_LEFT:
case KEY_RIGHT:
if (select >= 0) {
JRect vp = jview_get_viewport_position(view);
int sgn = (msg->key.scancode == KEY_LEFT) ? -1: 1;
int scroll_x, scroll_y;
jview_get_scroll(view, &scroll_x, &scroll_y);
jview_set_scroll(view, scroll_x + jrect_w(vp)/2*sgn, scroll_y);
jrect_free(vp);
}
break;
case KEY_ENTER:
if (fileview->selected) {
if (fileitem_is_browsable(fileview->selected)) {
fileview_set_current_folder(widget, fileview->selected);
return TRUE;
}
else {
jwidget_emit_signal(widget, SIGNAL_FILEVIEW_FILE_ACCEPT);
return TRUE;
}
}
else
return FALSE;
case KEY_BACKSPACE:
fileview_goup(widget);
return TRUE;
default:
return FALSE;
}
fileview_select_index(widget, MID(0, select, bottom));
return TRUE;
}
break;
case JM_WHEEL: {
JWidget view = jwidget_get_view(widget);
if (view) {
int scroll_x, scroll_y;
jview_get_scroll(view, &scroll_x, &scroll_y);
jview_set_scroll(view,
scroll_x,
scroll_y +
(jmouse_z(1) - jmouse_z(0))
*(2+jwidget_get_text_height(widget)+2)*3);
}
break;
}
case JM_DOUBLECLICK:
if (fileview->selected) {
if (fileitem_is_browsable(fileview->selected)) {
fileview_set_current_folder(widget, fileview->selected);
return TRUE;
}
else {
jwidget_emit_signal(widget, SIGNAL_FILEVIEW_FILE_ACCEPT);
return TRUE;
}
}
break;
}
return FALSE;
}
static void fileview_get_fileitem_size(JWidget widget, FileItem *fi, int *w, int *h)
{
/* char buf[512]; */
int len = 0;
if (fileitem_is_folder(fi)) {
len += ji_font_text_len(widget->text_font, "[+]")+2;
}
len += ji_font_text_len(widget->text_font,
fileitem_get_displayname(fi));
/* if (!fileitem_is_folder(fi)) { */
/* len += 2+ji_font_text_len(widget->text_font, buf); */
/* } */
*w = 2+len+2;
*h = 2+jwidget_get_text_height(widget)+2;
}
static void fileview_make_selected_fileitem_visible(JWidget widget)
{
FileView *fileview = fileview_data(widget);
JWidget view = jwidget_get_view(widget);
JRect vp = jview_get_viewport_position(view);
FileItem *fi;
JLink link;
int iw, ih;
int th = jwidget_get_text_height(widget);
int y = widget->rc->y1;
int scroll_x, scroll_y;
jview_get_scroll(view, &scroll_x, &scroll_y);
/* rows */
JI_LIST_FOR_EACH(fileview->list, link) {
fi = link->data;
fileview_get_fileitem_size(widget, fi, &iw, &ih);
if (fi == fileview->selected) {
if (y < vp->y1)
jview_set_scroll(view, scroll_x, y - widget->rc->y1);
else if (y > vp->y2 - (2+th+2))
jview_set_scroll(view, scroll_x,
y - widget->rc->y1 - jrect_h(vp) + (2+th+2));
break;
}
y += ih;
}
jrect_free(vp);
}
static void fileview_regenerate_list(JWidget widget)
{
FileView *fileview = fileview_data(widget);
FileItem *fileitem;
JLink link, next;
JList children;
if (fileview->list)
jlist_free(fileview->list);
/* get the list of children */
children = fileitem_get_children(fileview->current_folder);
if (children) {
fileview->list = jlist_copy(children);
/* filter the list */
if (fileview->exts) {
JI_LIST_FOR_EACH_SAFE(fileview->list, link, next) {
fileitem = link->data;
if (!fileitem_is_folder(fileitem) &&
!fileitem_has_extension(fileitem, fileview->exts)) {
jlist_delete_link(fileview->list, link);
}
}
}
}
else
fileview->list = jlist_new();
}
static int fileview_get_selected_index(JWidget widget)
{
FileView *fileview = fileview_data(widget);
JLink link;
int i = 0;
JI_LIST_FOR_EACH(fileview->list, link) {
if (link->data == fileview->selected)
return i;
i++;
}
return -1;
}
static void fileview_select_index(JWidget widget, int index)
{
FileView *fileview = fileview_data(widget);
FileItem *old_selected = fileview->selected;
fileview->selected = jlist_nth_data(fileview->list, index);
if (old_selected != fileview->selected) {
fileview_make_selected_fileitem_visible(widget);
jwidget_dirty(widget);
jwidget_emit_signal(widget, SIGNAL_FILEVIEW_FILE_SELECTED);
}
}

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello * Copyright (C) 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -16,26 +16,25 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
extern FileType filetype_ase; #ifndef WIDGETS_FILEVIEW_H
extern FileType filetype_bmp; #define WIDGETS_FILEVIEW_H
extern FileType filetype_fli;
extern FileType filetype_jpeg;
extern FileType filetype_pcx;
extern FileType filetype_tga;
extern FileType filetype_gif;
extern FileType filetype_ico;
extern FileType filetype_png;
static FileType *filetypes[] = #include "jinete/jbase.h"
{
&filetype_ase, #include "core/file_system.h"
&filetype_bmp,
&filetype_fli, /* TODO use some JI_SIGNAL_USER */
&filetype_jpeg, #define SIGNAL_FILEVIEW_FILE_SELECTED 0x10006
&filetype_pcx, #define SIGNAL_FILEVIEW_FILE_ACCEPT 0x10007
&filetype_tga, #define SIGNAL_FILEVIEW_CURRENT_FOLDER_CHANGED 0x10008
&filetype_gif,
&filetype_ico, JWidget fileview_new(FileItem *start_folder, const char *exts);
&filetype_png, int fileview_type(void);
NULL
}; FileItem *fileview_get_current_folder(JWidget fileview);
FileItem *fileview_get_selected(JWidget fileview);
void fileview_set_current_folder(JWidget widget, FileItem *folder);
void fileview_goup(JWidget fileview);
#endif /* WIDGETS_FILEVIEW_H */

View File

@ -60,8 +60,6 @@ static void button_command(JWidget widget, void *data);
static void update_from_layer(StatusBar *status_bar); static void update_from_layer(StatusBar *status_bar);
static void play_animation(void);
JWidget status_bar_new(void) JWidget status_bar_new(void)
{ {
#define BUTTON_NEW(name, text, data) \ #define BUTTON_NEW(name, text, data) \
@ -85,7 +83,7 @@ JWidget status_bar_new(void)
status_bar->widget = widget; status_bar->widget = widget;
status_bar->timeout = 0; status_bar->timeout = 0;
status_bar->nprogress = 0; status_bar->progress = jlist_new();
/* construct the commands box */ /* construct the commands box */
box1 = jbox_new(JI_HORIZONTAL); box1 = jbox_new(JI_HORIZONTAL);
@ -154,55 +152,6 @@ void status_bar_set_text(JWidget widget, int msecs, const char *format, ...)
} }
} }
void status_bar_do_progress(JWidget widget, int progress)
{
StatusBar *status_bar = status_bar_data(widget);
int n = status_bar->nprogress-1;
if (n >= 0) {
progress = MID(0, progress, status_bar->progress[n].max);
if (status_bar->progress[n].pos != progress) {
status_bar->progress[n].pos = progress;
jwidget_dirty(widget);
}
}
}
void status_bar_add_progress(JWidget widget, int max)
{
StatusBar *status_bar = status_bar_data(widget);
int n = status_bar->nprogress++;
status_bar->progress[n].max = max;
status_bar->progress[n].pos = 0;
ji_dirty_region = jregion_new(NULL, 0);
jwidget_dirty(widget);
}
void status_bar_del_progress(JWidget widget)
{
StatusBar *status_bar = status_bar_data(widget);
jwidget_dirty(widget);
/* to show 100% progress-bar */
if (status_bar->nprogress == 1) {
status_bar->progress[0].pos = status_bar->progress[0].max;
jwidget_flush_redraw(widget);
jmanager_dispatch_messages(ji_get_default_manager());
rest(5);
jwidget_dirty(widget);
jregion_free(ji_dirty_region);
ji_dirty_region = NULL;
}
status_bar->nprogress--;
}
void status_bar_update(JWidget widget) void status_bar_update(JWidget widget)
{ {
StatusBar *status_bar = status_bar_data(widget); StatusBar *status_bar = status_bar_data(widget);
@ -210,15 +159,56 @@ void status_bar_update(JWidget widget)
update_from_layer(status_bar); update_from_layer(status_bar);
} }
Progress *progress_new(JWidget status_bar)
{
Progress *progress = jnew(Progress, 1);
if (!progress)
return NULL;
progress->status_bar = status_bar;
progress->pos = 0.0f;
jlist_append(status_bar_data(status_bar)->progress,
progress);
jwidget_dirty(status_bar);
return progress;
}
void progress_free(Progress *progress)
{
jlist_remove(status_bar_data(progress->status_bar)->progress,
progress);
jwidget_dirty(progress->status_bar);
jfree(progress);
}
void progress_update(Progress *progress, float progress_pos)
{
if (progress->pos != progress_pos) {
progress->pos = progress_pos;
jwidget_dirty(progress->status_bar);
}
}
static bool status_bar_msg_proc(JWidget widget, JMessage msg) static bool status_bar_msg_proc(JWidget widget, JMessage msg)
{ {
StatusBar *status_bar = status_bar_data(widget); StatusBar *status_bar = status_bar_data(widget);
switch (msg->type) { switch (msg->type) {
case JM_DESTROY: case JM_DESTROY: {
JLink link;
JI_LIST_FOR_EACH(status_bar->progress, link) {
jfree(link->data);
}
jlist_free(status_bar->progress);
jfree(status_bar); jfree(status_bar);
break; break;
}
case JM_REQSIZE: case JM_REQSIZE:
msg->reqsize.w = msg->reqsize.h = msg->reqsize.w = msg->reqsize.h =
@ -238,63 +228,53 @@ static bool status_bar_msg_proc(JWidget widget, JMessage msg)
break; break;
case JM_DRAW: { case JM_DRAW: {
JRect rect = jwidget_get_rect(widget); JRect rc = jwidget_get_rect(widget);
jdraw_rectedge(rect, ji_color_facelight(), ji_color_faceshadow()); jdraw_rectedge(rc, ji_color_facelight(), ji_color_faceshadow());
jrect_shrink(rect, 1); jrect_shrink(rc, 1);
jdraw_rect(rect, ji_color_face()); jdraw_rect(rc, ji_color_face());
jrect_shrink(rect, 1); jrect_shrink(rc, 1);
/* progress bar */
if (status_bar->nprogress > 0) {
int i, pos, x1, y1, x2, y2;
double x, width;
jdraw_rectedge(rect,
ji_color_faceshadow(),
ji_color_facelight());
jrect_shrink(rect, 1);
x1 = rect->x1;
y1 = rect->y1;
x2 = rect->x2-1;
y2 = rect->y2-1;
x = x1;
width = x2-x1+1;
for (i=0; i<status_bar->nprogress; i++) {
if (status_bar->progress[i].max > 0) {
pos = status_bar->progress[i].pos;
if (status_bar->nprogress == 1)
pos = MID(0, pos, status_bar->progress[i].max);
else
pos = MID(0, pos, status_bar->progress[i].max-1);
width /= (double)status_bar->progress[i].max;
x += width * (double)pos;
}
}
x = MID(x1, x, x2);
rectfill(ji_screen, x1, y1, x, y2, ji_color_selected());
if (x < x2)
rectfill(ji_screen, x+1, y1, x2, y2, ji_color_background());
}
/* status bar text */ /* status bar text */
else if (widget->text) { if (widget->text) {
jdraw_rectfill(rect, ji_color_face()); jdraw_rectfill(rc, ji_color_face());
text_mode(-1); text_mode(-1);
textout(ji_screen, widget->text_font, widget->text, textout(ji_screen, widget->text_font, widget->text,
rect->x1+2, rc->x1+2,
(widget->rc->y1+widget->rc->y2)/2-text_height(widget->text_font)/2, (widget->rc->y1+widget->rc->y2)/2-text_height(widget->text_font)/2,
ji_color_foreground()); ji_color_foreground());
} }
jrect_free(rect); /* draw progress bar */
if (!jlist_empty(status_bar->progress)) {
int width = 64;
int y1, y2;
int x = rc->x2 - (width+4);
JLink link;
y1 = rc->y1;
y2 = rc->y2-1;
JI_LIST_FOR_EACH(status_bar->progress, link) {
Progress *progress = link->data;
int u = (int)((float)(width-2)*progress->pos);
u = MID(0, u, width-2);
rect(ji_screen, x, y1, x+width-1, y2, ji_color_foreground());
if (u > 0)
rectfill(ji_screen, x+1, y1+1, x+u, y2-1, ji_color_selected());
if (1+u < width-2)
rectfill(ji_screen, x+1+u, y1+1, x+width-2, y2-1, ji_color_background());
x -= width+4;
}
}
jrect_free(rc);
return TRUE; return TRUE;
} }
@ -369,41 +349,37 @@ static void button_command(JWidget widget, void *data)
Sprite *sprite = current_sprite; Sprite *sprite = current_sprite;
if (sprite) { if (sprite) {
int old_frame = sprite->frame; const char *cmd = NULL;
switch ((int)data) { switch ((int)data) {
case ACTION_LAYER: case ACTION_LAYER:
command_execute(command_get_by_name(CMD_LAYER_PROPERTIES), NULL); cmd = CMD_LAYER_PROPERTIES;
break; break;
case ACTION_FIRST: case ACTION_FIRST:
sprite->frame = 0; cmd = CMD_GOTO_FIRST_FRAME;
break; break;
case ACTION_PREV: case ACTION_PREV:
if ((--sprite->frame) < 0) cmd = CMD_GOTO_PREVIOUS_FRAME;
sprite->frame = sprite->frames-1;
break; break;
case ACTION_PLAY: case ACTION_PLAY:
play_animation(); cmd = CMD_PLAY_ANIMATION;
break; break;
case ACTION_NEXT: case ACTION_NEXT:
if ((++sprite->frame) >= sprite->frames) cmd = CMD_GOTO_NEXT_FRAME;
sprite->frame = 0;
break; break;
case ACTION_LAST: case ACTION_LAST:
sprite->frame = sprite->frames-1; cmd = CMD_GOTO_LAST_FRAME;
break; break;
} }
if (sprite->frame != old_frame) { if (cmd)
update_from_layer(widget->user_data[0]); command_execute(command_get_by_name(cmd), NULL);
update_screen_for_sprite(sprite);
}
} }
} }
@ -436,83 +412,3 @@ static void update_from_layer(StatusBar *status_bar)
jwidget_disable(status_bar->slider); jwidget_disable(status_bar->slider);
} }
} }
/***********************************************************************
Animation Playing stuff
***********************************************************************/
static int speed_timer;
static void speed_timer_callback(void)
{
speed_timer++;
}
END_OF_STATIC_FUNCTION(speed_timer_callback);
static void play_animation(void)
{
Sprite *sprite = current_sprite;
int old_frame, msecs;
bool done = FALSE;
if (sprite->frames < 2)
return;
jmouse_hide();
old_frame = sprite->frame;
LOCK_VARIABLE(speed_timer);
LOCK_FUNCTION(speed_timer_callback);
clear_keybuf();
/* clear all the screen */
clear_bitmap(ji_screen);
/* do animation */
speed_timer = 0;
while (!done) {
msecs = sprite_get_frlen(sprite, sprite->frame);
install_int_ex(speed_timer_callback, MSEC_TO_TIMER(msecs));
set_palette(sprite_get_palette(sprite, sprite->frame));
editor_draw_sprite_safe(current_editor, 0, 0, sprite->w, sprite->h);
do {
poll_mouse();
poll_keyboard();
if (keypressed() || mouse_b)
done = TRUE;
gui_feedback();
} while (!done && (speed_timer <= 0));
if (!done) {
sprite->frame++;
if (sprite->frame >= sprite->frames)
sprite->frame = 0;
speed_timer--;
}
gui_feedback();
}
/* if right-click or ESC */
if (mouse_b == 2 || (keypressed() && (readkey()>>8) == KEY_ESC))
/* return to the old frame position */
sprite->frame = old_frame;
/* refresh all */
set_current_palette(sprite_get_palette(sprite, sprite->frame), TRUE);
jmanager_refresh_screen();
gui_feedback();
while (mouse_b)
poll_mouse();
clear_keybuf();
remove_int(speed_timer_callback);
jmouse_show();
}

View File

@ -22,17 +22,19 @@
#include "jinete/jbase.h" #include "jinete/jbase.h"
typedef struct Progress
{
JWidget status_bar;
float pos;
} Progress;
typedef struct StatusBar typedef struct StatusBar
{ {
JWidget widget; JWidget widget;
int timeout; int timeout;
/* progress bar */ /* progress bar */
int nprogress; JList progress;
struct {
int max;
int pos;
} progress[2];
/* box of main commands */ /* box of main commands */
JWidget commands_box; JWidget commands_box;
@ -45,17 +47,20 @@ typedef struct StatusBar
JWidget b_last; /* go to last frame */ JWidget b_last; /* go to last frame */
} StatusBar; } StatusBar;
/* status_bar */
JWidget status_bar_new(void); JWidget status_bar_new(void);
int status_bar_type(void); int status_bar_type(void);
StatusBar *status_bar_data(JWidget status_bar); StatusBar *status_bar_data(JWidget status_bar);
void status_bar_set_text(JWidget status_bar, int msecs, const char *format, ...); void status_bar_set_text(JWidget status_bar, int msecs, const char *format, ...);
void status_bar_do_progress(JWidget status_bar, int progress);
void status_bar_add_progress(JWidget status_bar, int max);
void status_bar_del_progress(JWidget status_bar);
void status_bar_update(JWidget status_bar); void status_bar_update(JWidget status_bar);
/* progress */
Progress *progress_new(JWidget status_bar);
void progress_free(Progress *progress);
void progress_update(Progress *progress, float progress_pos);
#endif /* WIDGETS_STATEBAR_H */ #endif /* WIDGETS_STATEBAR_H */

View File

@ -1,5 +1,5 @@
/* ASE - Allegro Sprite Editor /* ASE - Allegro Sprite Editor
* Copyright (C) 2001-2005, 2007 David A. Capello * Copyright (C) 2001-2005, 2007, 2008 David A. Capello
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -315,7 +315,7 @@ static bool tabs_msg_proc(JWidget widget, JMessage msg)
/* Tabs *tabs = jwidget_get_data(parent, tabs_type()); */ /* Tabs *tabs = jwidget_get_data(parent, tabs_type()); */
/* int dir = (int)jwidget_get_data(widget, tabs_type()); */ /* int dir = (int)jwidget_get_data(widget, tabs_type()); */
int dir = jmanager_get_capture() == tabs->button_left ? -1: 1; int dir = jmanager_get_capture() == tabs->button_left ? -1: 1;
set_scroll_x(widget, tabs->scroll_x + dir*8); set_scroll_x(widget, tabs->scroll_x + dir*8*msg->timer.count);
break; break;
} }