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>
* src/widgets/editor/editor.c (show_drawing_cursor): Added the

View File

@ -1,10 +1,11 @@
High priority work
------------------
- the user_data of hook_signal should be void*.
- search for TODO;
- Problems:
- test UNDO in 64bits plataforms (reported by Jon Rafkind);
- rename jcombox.c to jcombobox.c
- 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.
- complete palette operations, and palette editor (it needs a slider
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
Copyright (C) 2004-2005, 2007 by David A. Capello
Copyright (C) 2004-2005, 2007, 2008 by David A. Capello
----------------------------------------------------------------------
1. References
@ -19,7 +19,6 @@ BYTE An 8-bit unsigned integer value
WORD A 16-bit unsigned integer value
DWORD A 32-bit unsigned integer value
LONG A 32-bit signed integer value
DOUBLE A 64-bit floating point value
BYTE[n] "n" bytes.
RECT Four LONGs (in the order: x-pos, y-pos, width, heigth)
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
`- Layer3 1
NOTE.2: The layer index is a number to identify any layer in the
sprite, for example:
@ -223,6 +223,7 @@ NOTE.2: The layer index is a number to identify any layer in the
| `- Layer2 4
`- Layer3 5
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.
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), \
$(basename \
$(wildcard src/test/convmatr/*.c) \
$(wildcard src/test/*.c) \
$(wildcard src/test/raster/*.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)
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)
test: $(TESTS)
runtest:
@-$(foreach TEST, $(AUTOTESTS), ./$(TEST))

View File

@ -79,6 +79,7 @@ COMMON_SOURCES = \
src/core/config.c \
src/core/core.c \
src/core/dirs.c \
src/core/file_system.c \
src/core/modules.c \
src/dialogs/canvasze.c \
src/dialogs/colsel.c \
@ -148,6 +149,7 @@ COMMON_SOURCES = \
src/jinete/jsystem.c \
src/jinete/jtextbox.c \
src/jinete/jtheme.c \
src/jinete/jthread.c \
src/jinete/jview.c \
src/jinete/jwidget.c \
src/jinete/jwindow.c \
@ -206,6 +208,7 @@ COMMON_SOURCES = \
src/widgets/editor/cursor.c \
src/widgets/editor/editor.c \
src/widgets/editor/keys.c \
src/widgets/fileview.c \
src/widgets/groupbut.c \
src/widgets/menuitem.c \
src/widgets/paledit.c \
@ -215,6 +218,11 @@ COMMON_SOURCES = \
src/widgets/target.c \
src/widgets/toolbar.c
ifdef WIN32
COMMON_SOURCES += src/core/file_system_win32.c
else
endif
ifdef USE_X86_INT_MULT
COMMON_SOURCES += src/raster/x86/int_mult.s
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
include makefile.cfg
@ -14,8 +14,9 @@ endif
######################################################################
# Flags for MinGW
# CFLAGS = -D_WIN32_WINNT=0x0500
CFLAGS =
LFLAGS = -mwindows
LFLAGS = -mwindows -lshlwapi
ifdef DEBUGMODE
LFLAGS_LAST = -lalld
else

View File

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

View File

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

View File

@ -1,5 +1,5 @@
/* 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
* 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 */
Sprite *sprite = current_sprite;
char *filename = GUI_FileSelect(_("Load .msk File"), "", "msk");
char *filename = ase_file_selector(_("Load .msk File"), "", "msk");
if (filename) {
Mask *mask = load_msk_file(filename);
if (!mask) {

View File

@ -1,5 +1,5 @@
/* 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
* it under the terms of the GNU General Public License as published by
@ -20,23 +20,98 @@
#ifndef USE_PRECOMPILED_HEADER
#include <stdio.h>
#include "jinete/jinete.h"
#include "commands/commands.h"
#include "console/console.h"
#include "core/app.h"
#include "dialogs/filesel.h"
#include "file/file.h"
#include "raster/sprite.h"
#include "modules/editors.h"
#include "modules/gui.h"
#include "modules/recent.h"
#include "modules/sprites.h"
#include "widgets/statebar.h"
#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)
{
char *filename;
/* interactive */
if (!argument) {
filename = GUI_FileSelect(_("Open Sprite"), "",
get_readable_extensions());
char exts[4096];
get_readable_extensions(exts, sizeof(exts));
filename = ase_file_selector(_("Open Sprite"), "", exts);
}
/* load the file specified in the argument */
else {
@ -44,18 +119,38 @@ static void cmd_open_file_execute(const char *argument)
}
if (filename) {
Sprite *sprite = sprite_load(filename);
if (sprite) {
recent_file(filename);
sprite_mount(sprite);
sprite_show(sprite);
}
else {
unrecent_file(filename);
}
FileOp *fop = fop_to_load_sprite(filename);
if (filename != argument)
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
* 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
* it under the terms of the GNU General Public License as published by
@ -20,14 +20,18 @@
#ifndef USE_PRECOMPILED_HEADER
#include <allegro.h>
#include "jinete/jbase.h"
#include "commands/commands.h"
#include "core/app.h"
#include "console/console.h"
#include "file/file.h"
#include "modules/recent.h"
#include "modules/sprites.h"
#include "raster/sprite.h"
#include "widgets/statebar.h"
#endif
@ -44,12 +48,15 @@ static void cmd_save_file_execute(const char *argument)
if (sprite_save(current_sprite) == 0) {
recent_file(current_sprite->filename);
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 {
/* TODO if the user cancel we shouldn't unrecent the file */
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

View File

@ -1,5 +1,5 @@
/* 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
* it under the terms of the GNU General Public License as published by
@ -26,7 +26,7 @@
#include "commands/commands.h"
#include "console/console.h"
/* #include "core/app.h" */
#include "core/app.h"
#include "dialogs/filesel.h"
#include "file/file.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)
{
char filename[4096];
char exts[4096];
char *newfilename;
int ret;
ustrcpy(filename, current_sprite->filename);
get_writable_extensions(exts, sizeof(exts));
for (;;) {
newfilename = GUI_FileSelect(_("Save Sprite"), filename,
get_writable_extensions());
newfilename = ase_file_selector(_("Save Sprite"), filename, exts);
if (!newfilename)
return;
ustrcpy(filename, newfilename);
@ -80,17 +81,15 @@ static void cmd_save_file_as_execute(const char *argument)
}
sprite_set_filename(current_sprite, filename);
rebuild_sprite_list();
app_realloc_sprite_list();
if (sprite_save(current_sprite) == 0) {
recent_file(filename);
sprite_mark_as_saved(current_sprite);
}
else {
/* TODO if the user cancel we shouldn't unrecent the file */
unrecent_file(filename);
console_printf("%s: %s",
_("Error saving sprite file"),
filename);
}
}

View File

@ -1,5 +1,5 @@
/* 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
* 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;
for (;;) {
char *filename = GUI_FileSelect(_("Save .msk File"), filename, "msk");
char *filename = ase_file_selector(_("Save .msk File"), filename, "msk");
if (!filename)
return;

View File

@ -171,36 +171,3 @@ void user_printf(const char *format, ...)
/* else */
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
* 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
* 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 user_printf(const char *format, ...);
void do_progress(int progress);
void add_progress(int max);
void del_progress(void);
#endif /* CONSOLE_H */

View File

@ -37,6 +37,7 @@
#include "core/app.h"
#include "core/cfg.h"
#include "core/core.h"
#include "core/file_system.h"
#include "core/modules.h"
#include "dialogs/options.h"
#include "dialogs/tips.h"
@ -99,7 +100,7 @@ static Option *option_new(int type, const char *data);
static void option_free(Option *option);
/* install and load all initial stuff */
int app_init(int argc, char *argv[])
bool app_init(int argc, char *argv[])
{
exe_name = argv[0];
@ -107,11 +108,15 @@ int app_init(int argc, char *argv[])
intl_init();
/* install the `core' of ASE application */
if (core_init() < 0) {
if (!core_init()) {
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 */
ase_config_init();
@ -120,16 +125,21 @@ int app_init(int argc, char *argv[])
/* search options in the arguments */
if (check_args(argc, argv) < 0)
return -1;
return FALSE;
/* GUI is the default mode */
if (!(ase_mode & MODE_BATCH))
ase_mode |= MODE_GUI;
/* install 'raster' stuff */
if (!gfxobj_init()) {
return FALSE;
}
/* install the modules */
if (modules_init (ase_mode & MODE_GUI ? REQUIRE_INTERFACE:
REQUIRE_SCRIPTING) < 0)
return -1;
if (!modules_init(ase_mode & MODE_GUI ? REQUIRE_INTERFACE:
REQUIRE_SCRIPTING))
return FALSE;
_ji_font_init();
@ -145,7 +155,7 @@ int app_init(int argc, char *argv[])
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
console_printf(_("Error loading default palette from `%s'\n"),
palette_filename);
return -1;
return FALSE;
}
destroy_bitmap(bmp);
@ -157,7 +167,7 @@ int app_init(int argc, char *argv[])
set_current_palette(NULL, TRUE);
/* ok */
return 0;
return TRUE;
}
/* runs ASE main dialog */
@ -335,7 +345,9 @@ void app_exit(void)
/* finalize modules, configuration and core */
modules_exit();
gfxobj_exit();
ase_config_exit();
file_system_exit();
core_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)
{
Sprite *sprite;
JLink link;
#if 1
PRINTF("Reallocating sprite list...\n");
/* insert all other sprites */
JI_LIST_FOR_EACH(get_sprite_list(), link) {
@ -381,115 +388,26 @@ void app_realloc_sprite_list(void)
get_filename(sprite->filename),
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
when a menu callback was called, because, it destroy the menus,
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 menuitem;
PRINTF("Reallocating recent list...\n");
/* update the recent file list menu item */
if (list_menuitem) {
Command *cmd_open_file = command_get_by_name(CMD_OPEN_FILE);
Command *cmd_open_file;
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);
if (submenu) {
jmenuitem_set_submenu(list_menuitem, NULL);
@ -518,6 +436,8 @@ void app_realloc_recent_list(void)
jwidget_add_child(submenu, menuitem);
}
}
return TRUE;
}
int app_get_current_image_type(void)

View File

@ -1,5 +1,5 @@
/* 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
* it under the terms of the GNU General Public License as published by
@ -21,14 +21,14 @@
#include "jinete/jbase.h"
int app_init(int argc, char *argv[]);
bool app_init(int argc, char *argv[]);
void app_loop(void);
void app_exit(void);
void app_refresh_screen(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);

View File

@ -51,7 +51,7 @@ static char *log_filename = NULL;
static FILE *log_fileptr = NULL;
#endif
int core_init(void)
bool core_init(void)
{
#ifdef NEED_LOG
char buf[512];
@ -71,7 +71,7 @@ int core_init(void)
dirs_free(dirs);
#endif
return 0;
return TRUE;
}
void core_exit(void)
@ -121,5 +121,5 @@ void verbose_printf(const char *format, ...)
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
* 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
* it under the terms of the GNU General Public License as published by
@ -30,7 +30,7 @@ enum {
extern int ase_mode;
int core_init(void);
bool core_init(void);
void core_exit(void);
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);
int modules_init(int requirements)
bool modules_init(int requirements)
{
int c;
@ -76,11 +76,12 @@ int modules_init(int requirements)
if (module[c].reqs & requirements) {
PRINTF("Installing module: %s\n", module[c].name);
if ((*module[c].init)() < 0)
return -1;
return FALSE;
module[c].installed = TRUE;
}
return 0;
return TRUE;
}
void modules_exit(void)

View File

@ -1,5 +1,5 @@
/* 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
* it under the terms of the GNU General Public License as published by
@ -19,10 +19,12 @@
#ifndef CORE_MODULES_H
#define CORE_MODULES_H
#include "jinete/jbase.h"
#define REQUIRE_INTERFACE 1
#define REQUIRE_SCRIPTING 2
int modules_init(int requirements);
bool modules_init(int requirements);
void modules_exit(void);
#endif /* CORE_MODULES_H */

View File

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

View File

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

View File

@ -20,20 +20,10 @@
#ifndef USE_PRECOMPILED_HEADER
#include <assert.h>
#include <allegro.h>
#include <allegro/internal/aintern.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"
@ -41,6 +31,7 @@
#include "core/dirs.h"
#include "modules/gfx.h"
#include "modules/gui.h"
#include "widgets/fileview.h"
#endif
@ -48,38 +39,50 @@
# define HAVE_DRIVES
#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 add_bookmark_command(JWidget widget, void *data);
static void del_bookmark_command(JWidget widget, void *data);
static void fill_bookmarks_combobox(JWidget combobox);
static void home_command(JWidget widget);
static void fonts_command(JWidget widget);
static void palettes_command(JWidget widget);
static void mkdir_command(JWidget widget);
static void update_location(JWidget window);
static void update_navigation_buttons(JWidget window);
static void add_in_navigation_history(FileItem *folder);
static void select_filetype_from_filename(JWidget window);
static void goback_command(JWidget widget);
static void goforward_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.
*
* It add some extra functionalities to the default Jinete
* file-selection dialog.
*
* @see ji_file_select_ex.
* The routine that shows the dialog to select a file in ASE.
*/
char *GUI_FileSelect(const char *message,
const char *init_path,
const char *exts)
char *ase_file_selector(const char *message,
const char *init_path,
const char *exts)
{
JWidget box_left, button_home;
JWidget button_fonts, button_palettes, button_mkdir;
JWidget box_top, box_top2, combobox, add_bookmark, del_bookmark, entry_path;
JWidget widget_extension;
char buf[512], *selected_filename;
static JWidget window = NULL;
JWidget fileview, box, ok;
JWidget goback, goforward, goup;
JWidget filename_entry;
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);
/* insert the path */
/* use the current path */
if (get_filename(buf) == buf) {
char path[512];
@ -105,297 +108,410 @@ char *GUI_FileSelect(const char *message,
ustrcat(path, buf);
ustrcpy(buf, path);
}
else {
/* remove the filename */
*get_filename(buf) = 0;
}
if (!window) {
JWidget view, location;
/**********************************************************************/
/* prepare left side */
/* load the window widget */
window = load_widget("filesel.jid", "file_selector");
if (!window)
return NULL;
box_left = jbox_new(JI_VERTICAL);
button_home = jbutton_new(NULL);
button_fonts = jbutton_new(NULL);
button_palettes = jbutton_new(NULL);
button_mkdir = jbutton_new(NULL);
box = jwidget_find_name(window, "box");
goback = jwidget_find_name(window, "goback");
goforward = jwidget_find_name(window, "goforward");
goup = jwidget_find_name(window, "goup");
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);
add_gfxicon_to_button(button_fonts, GFX_FILE_FONTS, JI_CENTER | JI_MIDDLE);
add_gfxicon_to_button(button_palettes, GFX_FILE_PALETTES, JI_CENTER | JI_MIDDLE);
add_gfxicon_to_button(button_mkdir, GFX_FILE_MKDIR, JI_CENTER | JI_MIDDLE);
jwidget_focusrest(goback, FALSE);
jwidget_focusrest(goforward, FALSE);
jwidget_focusrest(goup, FALSE);
/* hook signals */
jbutton_add_command(button_home, home_command);
jbutton_add_command(button_fonts, fonts_command);
jbutton_add_command(button_palettes, palettes_command);
jbutton_add_command(button_mkdir, mkdir_command);
add_gfxicon_to_button(goback, GFX_ARROW_LEFT, JI_CENTER | JI_MIDDLE);
add_gfxicon_to_button(goforward, GFX_ARROW_RIGHT, JI_CENTER | JI_MIDDLE);
add_gfxicon_to_button(goup, GFX_ARROW_UP, JI_CENTER | JI_MIDDLE);
jwidget_add_childs(box_left,
button_home, button_fonts,
button_palettes, button_mkdir, NULL);
jbutton_add_command(goback, goback_command);
jbutton_add_command(goforward, goforward_command);
jbutton_add_command(goup, goup_command);
/**********************************************************************/
/* prepare top side */
view = jview_new();
fileview = fileview_new(get_fileitem_from_path(buf), exts);
box_top = jbox_new(JI_HORIZONTAL);
box_top2 = jbox_new(JI_HORIZONTAL | JI_HOMOGENEOUS);
combobox = jcombobox_new();
entry_path = jcombobox_get_entry_widget(combobox);
add_bookmark = jbutton_new("+");
del_bookmark = jbutton_new("-");
jwidget_add_hook(fileview, -1, fileview_msg_proc, NULL);
jwidget_add_hook(location, -1, location_msg_proc, NULL);
jwidget_add_hook(filetype, -1, filetype_msg_proc, NULL);
#ifdef HAVE_DRIVES
jcombobox_casesensitive(combobox, FALSE);
#else
jcombobox_casesensitive(combobox, TRUE);
#endif
jwidget_set_name(fileview, "fileview");
jwidget_magnetic(fileview, TRUE);
jwidget_noborders(box_top2);
jbutton_set_bevel(add_bookmark, 2, 0, 2, 0);
jbutton_set_bevel(del_bookmark, 0, 2, 0, 2);
jcombobox_editable(combobox, TRUE);
jcombobox_clickopen(combobox, FALSE);
jview_attach(view, fileview);
jwidget_expansive(view, TRUE);
jwidget_add_hook(combobox, JI_WIDGET, combobox_msg_proc, NULL);
jbutton_add_command_data(add_bookmark, add_bookmark_command, combobox);
jbutton_add_command_data(del_bookmark, del_bookmark_command, combobox);
jwidget_add_child(box, view);
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_add_childs(box_top, combobox, box_top2, NULL);
jwidget_add_childs(box_top2, add_bookmark, del_bookmark, NULL);
jwidget_signal_off(fileview);
fileview_set_current_folder(fileview, get_fileitem_from_path(buf));
jwidget_signal_on(fileview);
}
/**********************************************************************/
/* prepare widget_extension */
/* current location */
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);
jwidget_set_name(box_left, "left");
jwidget_set_name(box_top, "top");
jwidget_set_name(entry_path, "path");
jwidget_add_childs(widget_extension, box_left, box_top, NULL);
/* fill file-type combo-box */
jcombobox_clear(filetype);
ustrcpy(buf, exts);
for (tok = ustrtok(buf, ",");
tok != NULL;
tok = ustrtok(NULL, ",")) {
jcombobox_add_string(filetype, tok, NULL);
}
/* call the jinete file selector */
selected_filename = ji_file_select_ex(message, buf, exts, widget_extension);
if (selected_filename) {
char *s, *name_dup = jstrdup(selected_filename);
/* file name entry field */
filename_entry = jwidget_find_name(window, "filename");
jwidget_set_text(filename_entry, get_filename(init_path));
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 */
s = get_filename(name_dup);
if (s)
*s = 0;
set_config_string("FileSelect", "CurrentDirectory", name_dup);
jfree(name_dup);
{
char *name_dup = jstrdup(result);
char *s = get_filename(name_dup);
if (s)
*s = 0;
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:
if (msg->signal.num == JI_SIGNAL_COMBOBOX_SELECT) {
ji_file_select_enter_to_path(jcombobox_get_selected_string(widget));
return TRUE;
}
break;
while (fileitem != NULL) {
jlist_prepend(locations, fileitem);
fileitem = fileitem_get_parent(fileitem);
}
/* 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;
}
/**
* Adds a new bookmark.
*/
static void add_bookmark_command(JWidget widget, void *data)
static bool location_msg_proc(JWidget widget, JMessage msg)
{
JWidget combobox = data;
char buf[64], path[1024];
int count;
if (msg->type == JM_SIGNAL) {
switch (msg->signal.num) {
case JI_SIGNAL_COMBOBOX_SELECT: {
FileItem *fileitem =
jcombobox_get_data(widget,
jcombobox_get_selected_index(widget));
count = get_config_int("Bookmarks", "Count", 0);
count = MID(0, count, 256);
if (fileitem) {
JWidget fileview = jwidget_find_name(jwidget_get_window(widget),
"fileview");
if (count < 256) {
replace_filename(path, ji_file_select_get_current_path(), "", 1024);
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));
fileview_set_current_folder(fileview, fileitem);
}
break;
}
usprintf(buf, "Mark%02d", index);
set_config_string("Bookmarks", buf, "");
set_config_int("Bookmarks", "Count", count-1);
}
}
return FALSE;
}
/**
* Fills the combo-box with the existent bookmarks.
*/
static void fill_bookmarks_combobox(JWidget combobox)
static bool filetype_msg_proc(JWidget widget, JMessage msg)
{
const char *path;
char buf[256];
int c, count;
if (msg->type == JM_SIGNAL) {
switch (msg->signal.num) {
count = get_config_int("Bookmarks", "Count", 0);
count = MID(0, count, 256);
case JI_SIGNAL_COMBOBOX_SELECT: {
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++) {
usprintf(buf, "Mark%02d", c);
path = get_config_string("Bookmarks", buf, "");
if (path && *path)
jcombobox_add_string(combobox, path);
}
}
ustrcpy(buf, jwidget_get_text(entry));
p = get_extension(buf);
if (p && *p != 0) {
ustrcpy(p, ext);
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;
}
}
dirs_free(dirs);
return FALSE;
}
/**
* 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
* 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
* it under the terms of the GNU General Public License as published by
@ -19,9 +19,9 @@
#ifndef DIALOGS_FILESEL_H
#define DIALOGS_FILESEL_H
char *GUI_FileSelect(const char *message,
const char *init_path,
const char *exts);
char *ase_file_selector(const char *message,
const char *init_path,
const char *exts);
#endif /* DIALOGS_FILESEL_H */

View File

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

View File

@ -24,8 +24,7 @@
#include "jinete/jlist.h"
#include "console/console.h"
#include "file/ase_format.h"
/* #include "file/ase_format.h" */
#include "file/file.h"
#include "raster/raster.h"
@ -69,17 +68,14 @@ typedef struct ASE_FrameHeader
ase_uint16 duration;
} ASE_FrameHeader;
static Sprite *load_ASE(const char *filename);
static int save_ASE(Sprite *sprite);
static bool load_ASE(FileOp *fop);
static bool save_ASE(FileOp *fop);
static ASE_FrameHeader *current_frame_header = NULL;
static int chunk_type;
static int chunk_start;
static Sprite *ase_file_read(const char *filename);
static int ase_file_write(Sprite *sprite);
static int ase_file_read_header(FILE *f, ASE_Header *header);
static bool 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_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_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_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 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 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 Mask *ase_file_read_mask_chunk(FILE *f);
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 =
{
"ase",
"ase",
"ase,aseprite",
"ase,aseprite",
load_ASE,
save_ASE,
FILE_SUPPORT_RGB |
@ -125,45 +126,7 @@ FileFormat format_ase =
FILE_SUPPORT_PATHS_REPOSITORY
};
static Sprite *load_ASE(const char *filename)
{
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)
static bool load_ASE(FileOp *fop)
{
Sprite *sprite = NULL;
ASE_Header header;
@ -174,11 +137,17 @@ Sprite *ase_file_read_f(FILE *f)
int chunk_pos;
int chunk_size;
int chunk_type;
int c, frpos;
int c, frame;
FILE *f;
if (ase_file_read_header(f, &header) != 0) {
console_printf(_("Error reading header\n"));
return NULL;
f = fopen(fop->filename, "rb");
if (!f)
return FALSE;
if (!ase_file_read_header(f, &header)) {
fop_error(fop, _("Error reading header\n"));
fclose(f);
return FALSE;
}
/* create the new sprite */
@ -186,8 +155,9 @@ Sprite *ase_file_read_f(FILE *f)
header.depth == 16 ? IMAGE_GRAYSCALE: IMAGE_INDEXED,
header.width, header.height);
if (!sprite) {
console_printf(_("Error creating sprite with file spec\n"));
return NULL;
fop_error(fop, _("Error creating sprite with file spec\n"));
fclose(f);
return FALSE;
}
/* set frames and speed */
@ -215,14 +185,11 @@ Sprite *ase_file_read_f(FILE *f)
last_layer = sprite->set;
current_level = -1;
/* progress */
add_progress(header.size);
/* 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 */
frame_pos = ftell(f);
do_progress(frame_pos);
fop_progress(fop, (float)frame_pos / (float)header.size);
/* read 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) {
/* use frame-duration field? */
if (frame_header.duration > 0)
sprite_set_frlen(sprite, frame_header.duration, frpos);
sprite_set_frlen(sprite, frame_header.duration, frame);
/* read chunks */
for (c=0; c<frame_header.chunks; c++) {
/* start chunk position */
chunk_pos = ftell(f);
do_progress(chunk_pos);
fop_progress(fop, (float)chunk_pos / (float)header.size);
/* read chunk information */
chunk_size = fgetl(f);
@ -247,7 +214,7 @@ Sprite *ase_file_read_f(FILE *f)
/* only for 8 bpp images */
case ASE_FILE_CHUNK_FLI_COLOR:
/* console_printf ("Color chunk\n"); */
/* fop_error(fop, "Color chunk\n"); */
if (sprite->imgtype == IMAGE_INDEXED) {
/* TODO fix to read palette-per-frame */
@ -256,11 +223,11 @@ Sprite *ase_file_read_f(FILE *f)
sprite_set_palette(sprite, palette, 0);
}
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;
case ASE_FILE_CHUNK_LAYER: {
/* console_printf("Layer chunk\n"); */
/* fop_error(fop, "Layer chunk\n"); */
ase_file_read_layer_chunk(f, sprite,
&last_layer,
@ -269,32 +236,32 @@ Sprite *ase_file_read_f(FILE *f)
}
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;
}
case ASE_FILE_CHUNK_MASK: {
Mask *mask;
/* console_printf("Mask chunk\n"); */
/* fop_error(fop, "Mask chunk\n"); */
mask = ase_file_read_mask_chunk(f);
if (mask)
sprite_add_mask(sprite, mask);
else
console_printf(_("Warning: error loading a mask chunk\n"));
fop_error(fop, _("Warning: error loading a mask chunk\n"));
break;
}
case ASE_FILE_CHUNK_PATH:
/* console_printf("Path chunk\n"); */
/* fop_error(fop, "Path chunk\n"); */
break;
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;
}
@ -307,37 +274,38 @@ Sprite *ase_file_read_f(FILE *f)
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_FrameHeader frame_header;
JLink link;
int frpos;
int frame;
FILE *f;
f = fopen(fop->filename, "wb");
if (!f)
return FALSE;
/* prepare the header */
ase_file_prepare_header(f, &header, sprite);
/* add a new progress bar */
add_progress(sprite->frames);
/* write frame */
for (frpos=0; frpos<sprite->frames; frpos++) {
/* progress */
do_progress(frpos);
for (frame=0; frame<sprite->frames; frame++) {
/* prepare the header */
ase_file_prepare_frame_header(f, &frame_header);
/* 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 */
if (frpos == 0) {
if (frame == 0) {
/* color chunk */
if (sprite->imgtype == IMAGE_INDEXED)
/* TODO fix this to write palette per-frame */
@ -353,27 +321,30 @@ int ase_file_write_f(FILE *f, Sprite *sprite)
}
/* 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 */
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 */
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->size = fgetl(f);
header->magic = fgetw(f);
if (header->magic != ASE_FILE_MAGIC)
return -1;
return FALSE;
header->frames = 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);
fseek(f, header->pos+128, SEEK_SET);
return 0;
return TRUE;
}
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)) {
Cel *cel = layer_get_cel(layer, frpos);
Cel *cel = layer_get_cel(layer, frame);
if (cel) {
/* console_printf("New cel in frpos %d, in layer %d\n", */
/* frpos, sprite_layer2index(sprite, layer)); */
/* fop_error(fop, "New cel in frame %d, in layer %d\n", */
/* frame, sprite_layer2index(sprite, layer)); */
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)) {
JLink 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);
/* 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;
/* 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);
if (!layer) {
console_printf(_("Frame %d didn't found layer with index %d\n"),
frpos, layer_index);
fop_error(fop, _("Frame %d didn't found layer with index %d\n"),
frame, layer_index);
return NULL;
}
/* console_printf("Layer found: %d -> %s\n", layer_index, layer->name); */
/* create the new frame */
cel = cel_new(frpos, 0);
cel = cel_new(frame, 0);
cel_set_position(cel, x, y);
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);
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;
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);
image->method->putpixel(image, x, y, _graya(k, a));
}
fop_progress(fop, (float)ftell(f) / (float)header->size);
}
do_progress(ftell(f));
break;
case IMAGE_INDEXED:
for (y=0; y<image->h; y++) {
for (x=0; x<image->w; x++)
image->method->putpixel(image, x, y, fgetc(f));
fop_progress(fop, (float)ftell(f) / (float)header->size);
}
do_progress(ftell(f));
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: {
/* read link position */
int link_frpos = fgetw(f);
Cel *link = layer_get_cel(layer, link_frpos);
int link_frame = fgetw(f);
Cel *link = layer_get_cel(layer, link_frame);
if (link)
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->h, f);
/* TODO */
/* add_progress(image->h); */
/* pixel data */
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_geta(c), f);
}
/* do_progress(y); */
}
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_geta(c), f);
}
/* do_progress(y); */
}
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 (x=0; x<image->w; x++)
fputc(image->method->getpixel(image, x, y), f);
/* do_progress(y); */
}
break;
}
/* del_progress(); */
}
else {
/* width and height */
@ -993,7 +955,7 @@ static void ase_file_write_mask_chunk(FILE *f, Mask *mask)
}
/* returns a word (16 bits) */
int fgetw(FILE *file)
static int fgetw(FILE *file)
{
int b1, b2;
@ -1010,7 +972,7 @@ int fgetw(FILE *file)
}
/* returns a dword (32 bits) */
long fgetl(FILE *file)
static long fgetl(FILE *file)
{
int b1, b2, b3, b4;
@ -1035,7 +997,7 @@ long fgetl(FILE *file)
}
/* returns 0 in success or -1 in error */
int fputw(int w, FILE *file)
static int fputw(int w, FILE *file)
{
int b1, b2;
@ -1051,7 +1013,7 @@ int fputw(int w, FILE *file)
}
/* 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;

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,9 @@
#ifndef FILE_H
#define FILE_H
#include "jinete/jbase.h"
#include <allegro/color.h>
#define FILE_SUPPORT_RGB (1<<0)
#define FILE_SUPPORT_RGBA (1<<1)
#define FILE_SUPPORT_GRAY (1<<2)
@ -31,8 +34,18 @@
#define FILE_SUPPORT_MASKS_REPOSITORY (1<<9)
#define FILE_SUPPORT_PATHS_REPOSITORY (1<<10)
typedef struct Sprite *(*FileLoad)(const char *filename);
typedef int (*FileSave)(struct Sprite *sprite);
struct Image;
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 */
typedef struct FileFormat
@ -44,22 +57,62 @@ typedef struct FileFormat
int flags;
} 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);
void file_sequence_get_color(int index, int *r, int *g, int *b);
struct Image *file_sequence_image(int imgtype, int w, int h);
struct Sprite *file_sequence_sprite(void);
struct Image *file_sequence_image_to_save(void);
/* shared fields between threads */
JMutex mutex; /* mutex to access to the next two fields */
float progress; /* progress (1.0 is ready) */
char *error; /* error string */
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 */
const char *get_readable_extensions(void);
const char *get_writable_extensions(void);
void get_readable_extensions(char *buf, int size);
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);
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 */

View File

@ -23,7 +23,6 @@
#include <allegro/color.h>
#include <stdio.h>
#include "console/console.h"
#include "file/file.h"
#include "modules/palette.h"
#include "raster/raster.h"
@ -33,8 +32,8 @@
#endif
static Sprite *load_FLI(const char *filename);
static int save_FLI(Sprite *sprite);
static bool load_FLI(FileOp *fop);
static bool save_FLI(FileOp *fop);
static int get_time_precision(Sprite *sprite);
@ -50,7 +49,7 @@ FileFormat format_fli =
};
/* loads a FLI/FLC file */
static Sprite *load_FLI(const char *filename)
static bool load_FLI(FileOp *fop)
{
#define SETPAL() \
do { \
@ -77,9 +76,9 @@ static Sprite *load_FLI(const char *filename)
FILE *f;
/* open the file to read in binary mode */
f = fopen(filename, "rb");
f = fopen(fop->filename, "rb");
if (!f)
return NULL;
return FALSE;
fli_read_header(f, &fli_header);
fseek(f, 128, SEEK_SET);
@ -92,11 +91,11 @@ static Sprite *load_FLI(const char *filename)
bmp = image_new(IMAGE_INDEXED, w, h);
old = image_new(IMAGE_INDEXED, w, h);
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 (old) image_free(old);
fclose(f);
return NULL;
return FALSE;
}
/* create the image */
@ -110,8 +109,6 @@ static Sprite *load_FLI(const char *filename)
sprite_set_speed(sprite, fli_header.speed);
/* write frame by frame */
add_progress(100);
inc_frpos_out = FALSE;
for (frpos_in=frpos_out=0;
@ -156,15 +153,12 @@ static Sprite *load_FLI(const char *filename)
memcpy(omap, cmap, 768);
/* update progress */
if (sprite->frames > 1)
do_progress(100 * (frpos_in) / (sprite->frames-1));
fop_progress(fop, (float)(frpos_in+1) / (float)(sprite->frames));
}
/* update sprites frames */
sprite_set_frames(sprite, frpos_out+1);
del_progress();
/* close the file */
fclose(f);
@ -172,12 +166,14 @@ static Sprite *load_FLI(const char *filename)
image_free(bmp);
image_free(old);
return sprite;
fop->sprite = sprite;
return TRUE;
}
/* 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 omap[768];
s_fli_header fli_header;
@ -207,9 +203,9 @@ static int save_FLI(Sprite *sprite)
fli_header.oframe1 = fli_header.oframe2 = 0;
/* open the file to write in binary mode */
f = fopen(sprite->filename, "wb");
f = fopen(fop->filename, "wb");
if (!f)
return -1;
return FALSE;
fseek(f, 128, SEEK_SET);
@ -217,16 +213,14 @@ static int save_FLI(Sprite *sprite)
bmp = image_new(IMAGE_INDEXED, sprite->w, sprite->h);
old = image_new(IMAGE_INDEXED, sprite->w, sprite->h);
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 (old) image_free(old);
fclose(f);
return -1;
return FALSE;
}
/* write frame by frame */
add_progress(100);
for (frpos=0;
frpos<sprite->frames;
frpos++) {
@ -262,12 +256,9 @@ static int save_FLI(Sprite *sprite)
}
/* update progress */
if (sprite->frames > 1)
do_progress(100 * (frpos) / (sprite->frames-1));
fop_progress(fop, (float)(frpos+1) / (float)(sprite->frames));
}
del_progress();
/* write the header and close the file */
fli_write_header(f, &fli_header);
fclose(f);
@ -276,7 +267,7 @@ static int save_FLI(Sprite *sprite)
image_free(bmp);
image_free(old);
return 0;
return TRUE;
}
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
gif_save_animation (const char *filename, GIF_ANIMATION *gif,
void (*progress) (int))
void (*progress) (void *, float),
void *dp)
{
int frame;
int i, j;
@ -125,7 +126,7 @@ gif_save_animation (const char *filename, GIF_ANIMATION *gif,
pack_putc (0, file);
}
progress(0);
progress(dp, 0.0f);
for (frame = 0; frame < gif->frames_count; frame++)
{
int w = gif->frames[frame].w;
@ -169,9 +170,9 @@ gif_save_animation (const char *filename, GIF_ANIMATION *gif,
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. */
@ -205,7 +206,7 @@ deinterlace (unsigned char *bmp, int w, int h)
}
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;
unsigned char *bmp = NULL;
@ -252,11 +253,11 @@ load_object (PACKFILE * file, long size, void (*progress) (int))
have_global_palette = 1;
}
progress(0);
progress(dp, 0.0f);
do
{
i = pack_getc (file);
progress(100 * i / size);
progress(dp, (float)i / (float)size);
switch (i)
{
@ -361,7 +362,7 @@ load_object (PACKFILE * file, long size, void (*progress) (int))
case 0x3b:
/* GIF Trailer. */
pack_fclose (file);
progress(100);
progress(dp, 1.0f);
return gif;
}
}
@ -388,7 +389,7 @@ load_object (PACKFILE * file, long size, void (*progress) (int))
* All bitmaps will have a color depth of 8.
*/
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;
GIF_ANIMATION *gif = NULL;
@ -402,7 +403,7 @@ gif_load_animation (const char *filename, void (*progress) (int))
file = pack_fopen (filename, "r");
if (file)
gif = load_object (file, size, progress);
gif = load_object (file, size, progress, dp);
return gif;
}

View File

@ -37,9 +37,11 @@ struct GIF_FRAME
GIF_ANIMATION *gif_create_animation(int frames_count);
void gif_destroy_animation(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,
void (*progress) (int));
void (*progress) (void *, float),
void *dp);
#endif

View File

@ -31,7 +31,6 @@
#include "jinete/jbase.h"
#include "console/console.h"
#include "file/file.h"
#include "modules/palette.h"
#include "raster/raster.h"
@ -43,8 +42,8 @@
#endif
static Sprite *load_GIF(const char *filename);
static int save_GIF(Sprite *sprite);
static bool load_GIF(FileOp *fop);
static bool save_GIF(FileOp *fop);
FileFormat format_gif =
{
@ -78,7 +77,7 @@ static void render_gif_frame(GIF_FRAME *frame, Image *image,
/* load_GIF:
* Loads a GIF into a sprite.
*/
static Sprite *load_GIF(const char *filename)
static bool load_GIF(FileOp *fop)
{
GIF_ANIMATION *gif = NULL;
Sprite *sprite = NULL;
@ -90,13 +89,10 @@ static Sprite *load_GIF(const char *filename)
PALETTE opal, npal;
int i, c;
add_progress(100);
gif = gif_load_animation(filename, do_progress);
del_progress();
gif = gif_load_animation(fop->filename, fop_progress, fop);
if (!gif) {
console_printf(_("Error loading GIF file.\n"));
return NULL;
fop_error(fop, _("Error loading GIF file.\n"));
return FALSE;
}
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);
gif_destroy_animation(gif);
console_printf(_("Error creating temporary image.\n"));
return NULL;
fop_error(fop, _("Error creating temporary image.\n"));
return FALSE;
}
sprite = sprite_new(IMAGE_INDEXED, gif->width, gif->height);
if (!sprite) {
gif_destroy_animation(gif);
image_free(current_image);
console_printf(_("Error creating sprite.\n"));
return NULL;
fop_error(fop, _("Error creating sprite.\n"));
return FALSE;
}
sprite_set_frames(sprite, gif->frames_count);
@ -125,8 +121,8 @@ static Sprite *load_GIF(const char *filename)
gif_destroy_animation(gif);
image_free(current_image);
sprite_free(sprite);
console_printf(_("Error creating main layer.\n"));
return NULL;
fop_error(fop, _("Error creating main layer.\n"));
return FALSE;
}
layer_add_layer(sprite->set, layer);
@ -180,7 +176,7 @@ static Sprite *load_GIF(const char *filename)
if (!cel || !image) {
if (cel) cel_free(cel);
if (image) image_free(image);
console_printf(_("Error creating cel %d.\n"), i);
fop_error(fop, _("Error creating cel %d.\n"), i);
break;
}
@ -260,7 +256,8 @@ static Sprite *load_GIF(const char *filename)
image_free(current_image);
image_free(current_image_old);
return sprite;
fop->sprite = sprite;
return TRUE;
}
/* 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
* as transparent.
*/
static int save_GIF(Sprite *sprite)
static bool save_GIF(FileOp *fop)
{
Sprite *sprite = fop->sprite;
GIF_ANIMATION *gif;
int x1, y1, x2, y2;
int u1, v1, u2, v2;
@ -300,16 +298,16 @@ static int save_GIF(Sprite *sprite)
if (!bmp || !old) {
if (bmp) image_free(bmp);
if (old) image_free(old);
console_printf(_("Not enough memory for temporary bitmaps.\n"));
return -1;
fop_error(fop, _("Not enough memory for temporary bitmaps.\n"));
return FALSE;
}
gif = gif_create_animation(sprite->frames);
if (!gif) {
image_free(bmp);
image_free(old);
console_printf(_("Error creating GIF structure.\n"));
return -1;
fop_error(fop, _("Error creating GIF structure.\n"));
return FALSE;
}
gif->width = sprite->w;
@ -327,8 +325,6 @@ static int save_GIF(Sprite *sprite)
/* avoid compilation warnings */
x1 = y1 = x2 = y2 = 0;
add_progress(2);
add_progress(sprite->frames);
for (i = 0; i < sprite->frames; i++) {
/* frame palette */
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 */
image_copy(old, bmp, 0, 0);
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);
return ret;
return ret == 0 ? TRUE: FALSE;
}

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
/* 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
* it under the terms of the GNU General Public License as published by
@ -23,7 +23,6 @@
#include <stdio.h>
#include <stdlib.h>
#include "console/console.h"
#include "core/app.h"
#include "core/cfg.h"
#include "core/core.h"
@ -36,8 +35,8 @@
#endif
static Sprite *load_PNG(const char *filename);
static int save_PNG(Sprite *sprite);
static bool load_PNG(FileOp *fop);
static bool save_PNG(FileOp *fop);
/* 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)
{
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;
unsigned int sig_read = 0;
@ -75,12 +74,9 @@ static Sprite *load_PNG(const char *filename)
int imgtype;
FILE *fp;
fp = fopen(filename, "rb");
if (!fp) {
if (!file_sequence_sprite())
console_printf(_("Error opening file.\n"));
return NULL;
}
fp = fopen(fop->filename, "rb");
if (!fp)
return FALSE;
/* Create and initialize the png_struct with the desired error handler
* 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
* 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);
if (png_ptr == NULL) {
console_printf("png_create_read_struct\n");
fop_error(fop, "png_create_read_struct\n");
fclose(fp);
return NULL;
return FALSE;
}
/* Allocate/initialize the memory for image information. */
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL) {
console_printf("png_create_info_struct\n");
fop_error(fop, "png_create_info_struct\n");
fclose(fp);
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
* the normal method of doing things with libpng).
*/
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 */
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
fclose(fp);
/* 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 */
@ -175,18 +171,18 @@ static Sprite *load_PNG(const char *filename)
imgtype = IMAGE_INDEXED;
break;
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);
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) {
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);
fclose(fp);
return NULL;
return FALSE;
}
/* read palette */
@ -196,13 +192,13 @@ static Sprite *load_PNG(const char *filename)
int c;
for (c = 0; c < num_palette; c++) {
file_sequence_set_color(c,
palette[c].red / 4,
palette[c].green / 4,
palette[c].blue / 4);
fop_sequence_set_color(fop, c,
palette[c].red / 4,
palette[c].green / 4,
palette[c].blue / 4);
}
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);
@ -287,27 +285,25 @@ static Sprite *load_PNG(const char *filename)
/* close the file */
fclose(fp);
/* return the sprite */
return file_sequence_sprite();
return TRUE;
}
static int save_PNG(Sprite *sprite)
static bool save_PNG(FileOp *fop)
{
Image *image = fop->seq.image;
png_uint_32 width, height, y;
png_structp png_ptr;
png_infop info_ptr;
png_colorp palette;
png_bytep row_pointer;
int color_type;
Image *image;
int pass, number_passes;
FILE *fp;
/* open the file */
fp = fopen(sprite->filename, "wb");
fp = fopen(fop->filename, "wb");
if (fp == NULL)
return -1;
return FALSE;
/* Create and initialize the png_struct with the desired error handler
* 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,
* 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);
if (png_ptr == NULL) {
fclose(fp);
return -1;
return FALSE;
}
/* Allocate/initialize the image information data. REQUIRED */
@ -327,7 +323,7 @@ static int save_PNG(Sprite *sprite)
if (info_ptr == NULL) {
fclose(fp);
png_destroy_write_struct(&png_ptr, png_infopp_NULL);
return -1;
return FALSE;
}
/* 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 */
fclose(fp);
png_destroy_write_struct(&png_ptr, &info_ptr);
return -1;
return FALSE;
}
/* 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
* currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
*/
image = file_sequence_image_to_save();
width = image->w;
height = image->h;
switch (image->imgtype) {
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;
break;
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;
break;
@ -386,7 +381,7 @@ static int save_PNG(Sprite *sprite)
* png_sizeof(png_color));
/* ... set palette colors ... */
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].green = _rgb_scale_6[g];
palette[c].blue = _rgb_scale_6[b];
@ -474,7 +469,10 @@ static int save_PNG(Sprite *sprite)
/* write the line */
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);
/* all right */
return 0;
return TRUE;
}
/* static int configure_png(void) */

View File

@ -28,14 +28,13 @@
#include "jinete/jbase.h"
#include "console/console.h"
#include "file/file.h"
#include "raster/raster.h"
#endif
static int save_TGA(Sprite *sprite);
static Sprite *load_TGA(const char *filename);
static bool load_TGA(FileOp *fop);
static bool save_TGA(FileOp *fop);
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
* 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 id_length, palette_type, image_type, palette_entry_size;
@ -204,12 +203,9 @@ static Sprite *load_TGA(const char *filename)
PACKFILE *f;
int type;
f = pack_fopen(filename, F_READ);
if (!f) {
if (!file_sequence_sprite())
console_printf(_("Error opening file.\n"));
return NULL;
}
f = pack_fopen(fop->filename, F_READ);
if (!f)
return FALSE;
*allegro_errno = 0;
@ -252,7 +248,7 @@ static Sprite *load_TGA(const char *filename)
}
else if (palette_type != 0) {
pack_fclose(f);
return NULL;
return FALSE;
}
/* Image type:
@ -273,14 +269,14 @@ static Sprite *load_TGA(const char *filename)
case 1:
if ((palette_type != 1) || (bpp != 8)) {
pack_fclose(f);
return NULL;
return FALSE;
}
for (i=0; i<palette_colors; i++) {
file_sequence_set_color(i,
image_palette[i][2] >> 2,
image_palette[i][1] >> 2,
image_palette[i][0] >> 2);
fop_sequence_set_color(fop, i,
image_palette[i][2] >> 2,
image_palette[i][1] >> 2,
image_palette[i][0] >> 2);
}
type = IMAGE_INDEXED;
@ -292,7 +288,7 @@ static Sprite *load_TGA(const char *filename)
((bpp != 15) && (bpp != 16) &&
(bpp != 24) && (bpp != 32))) {
pack_fclose(f);
return NULL;
return FALSE;
}
type = IMAGE_RGB;
@ -302,11 +298,11 @@ static Sprite *load_TGA(const char *filename)
case 3:
if ((palette_type != 0) || (bpp != 8)) {
pack_fclose(f);
return NULL;
return FALSE;
}
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;
break;
@ -315,13 +311,13 @@ static Sprite *load_TGA(const char *filename)
/* TODO add support for more TGA types? */
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) {
pack_fclose(f);
return NULL;
return FALSE;
}
for (y=image_height; y; y--) {
@ -385,48 +381,46 @@ static Sprite *load_TGA(const char *filename)
}
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) {
console_printf(_("Error reading bytes.\n"));
fop_error(fop, _("Error reading bytes.\n"));
pack_fclose(f);
return NULL;
return FALSE;
}
pack_fclose(f);
return file_sequence_sprite();
return TRUE;
}
/* save_tga:
* Writes a bitmap into a TGA file, using the specified palette (this
* 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];
int x, y, c, r, g, b;
int depth = (sprite->imgtype == IMAGE_RGB) ? 32 : 8;
bool need_pal = (sprite->imgtype == IMAGE_INDEXED)? TRUE: FALSE;
int depth = (image->imgtype == IMAGE_RGB) ? 32 : 8;
bool need_pal = (image->imgtype == IMAGE_INDEXED)? TRUE: FALSE;
PACKFILE *f;
Image *image;
f = pack_fopen(sprite->filename, F_WRITE);
f = pack_fopen(fop->filename, F_WRITE);
if (!f) {
console_printf(_("Error creating file.\n"));
return -1;
fop_error(fop, _("Error creating file.\n"));
return FALSE;
}
image = file_sequence_image_to_save();
*allegro_errno = 0;
pack_putc(0, f); /* id length (no id saved) */
pack_putc((need_pal) ? 1 : 0, f); /* palette type */
/* image type */
pack_putc((sprite->imgtype == IMAGE_RGB ) ? 2 :
(sprite->imgtype == IMAGE_GRAYSCALE) ? 3 :
(sprite->imgtype == IMAGE_INDEXED ) ? 1 : 0, f);
pack_putc((image->imgtype == IMAGE_RGB ) ? 2 :
(image->imgtype == IMAGE_GRAYSCALE) ? 3 :
(image->imgtype == IMAGE_INDEXED ) ? 1 : 0, f);
pack_iputw(0, f); /* first colour */
pack_iputw((need_pal) ? 256 : 0, f); /* number of colours */
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 */
/* 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) {
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][1] = _rgb_scale_6[g];
image_palette[y][0] = _rgb_scale_6[b];
@ -449,40 +443,37 @@ static int save_TGA(Sprite *sprite)
pack_fwrite(image_palette, 768, f);
}
switch (sprite->imgtype) {
switch (image->imgtype) {
case IMAGE_RGB:
for (y=image->h; y; y--) {
for (y=image->h-1; y>=0; y--) {
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_getg(c), f);
pack_putc(_rgba_getr(c), f);
pack_putc(_rgba_geta(c), f);
}
if (image->h > 1)
do_progress(100 * (image->h-y) / (image->h-1));
fop_progress(fop, (float)(image->h-y) / (float)(image->h));
}
break;
case IMAGE_GRAYSCALE:
for (y=image->h; y; y--) {
for (y=image->h-1; y>=0; y--) {
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)
do_progress(100 * (image->h-y) / (image->h-1));
fop_progress(fop, (float)(image->h-y) / (float)(image->h));
}
break;
case IMAGE_INDEXED:
for (y=image->h; y; y--) {
for (y=image->h-1; y>=0; y--) {
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)
do_progress(100 * (image->h-y) / (image->h-1));
fop_progress(fop, (float)(image->h-y) / (float)(image->h));
}
break;
}
@ -490,9 +481,9 @@ static int save_TGA(Sprite *sprite)
pack_fclose(f);
if (*allegro_errno) {
console_printf(_("Error writing bytes.\n"));
return -1;
fop_error(fop, _("Error writing bytes.\n"));
return FALSE;
}
else
return 0;
return TRUE;
}

View File

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

View File

@ -231,7 +231,9 @@ enum {
typedef unsigned int JID;
typedef void *JThread;
typedef void *JMutex;
typedef struct jaccel *JAccel;
typedef struct jhook *JHook;
typedef struct jquickmenu *JQuickMenu;
@ -249,9 +251,6 @@ typedef struct jxmlnode *JXmlNode;
typedef struct jxmlelem *JXmlElem;
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 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_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_index(JWidget combobox, int index);
void jcombobox_clear(JWidget combobox);
void jcombobox_select_index(JWidget combobox, int index);
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_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_count(JWidget combobox);
JWidget jcombobox_get_entry_widget(JWidget combobox);
JWidget jcombobox_get_button_widget(JWidget combobox);
JI_END_DECLS

View File

@ -38,6 +38,7 @@ typedef struct ComboBox
JWidget entry;
JWidget button;
JWidget window;
JWidget listbox;
JList items;
int selected;
bool editable : 1;
@ -45,6 +46,12 @@ typedef struct ComboBox
bool casesensitive : 1;
} ComboBox;
typedef struct ComboItem
{
char *text;
void *data;
} ComboItem;
#define COMBOBOX(widget) ((ComboBox *)jwidget_get_data(widget, JI_COMBOBOX))
#define IS_VALID_ITEM(widget, index) \
(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 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 widget = jbox_new(JI_HORIZONTAL);
JWidget widget = jwidget_new(JI_COMBOBOX);
ComboBox *combobox = jnew(ComboBox, 1);
combobox->entry = jentry_new(256, "");
combobox->button = jbutton_new("^");
combobox->button = jbutton_new("");
combobox->window = NULL;
combobox->items = jlist_new();
combobox->selected = 0;
@ -91,6 +101,8 @@ JWidget jcombobox_new(void)
jcombobox_editable(widget, combobox->editable);
jwidget_init_theme(widget);
return widget;
}
@ -145,12 +157,13 @@ bool jcombobox_is_casesensitive(JWidget widget)
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);
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)
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)
{
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)
{
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
JLink link = jlist_nth_link(combobox->items, index);
ComboItem *item;
if (link != combobox->items->end) {
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);
return jlist_nth_data(combobox->items, combobox->selected);
return jcombobox_get_string(widget, combobox->selected);
}
const char *jcombobox_get_string(JWidget widget, int index)
{
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
if (index >= 0 && index < jlist_length(combobox->items))
return jlist_nth_link(combobox->items, index)->data;
if (index >= 0 && index < jlist_length(combobox->items)) {
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
return NULL;
}
@ -214,8 +258,10 @@ int jcombobox_get_index(JWidget widget, const char *string)
JLink link;
JI_LIST_FOR_EACH(combobox->items, link) {
if ((combobox->casesensitive && ustrcmp(link->data, string) == 0) ||
(!combobox->casesensitive && ustricmp(link->data, string) == 0))
ComboItem *item = link->data;
if ((combobox->casesensitive && ustrcmp(item->text, string) == 0) ||
(!combobox->casesensitive && ustricmp(item->text, string) == 0))
return index;
index++;
}
@ -237,8 +283,17 @@ JWidget jcombobox_get_entry_widget(JWidget widget)
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)
{
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
switch (msg->type) {
case JM_CLOSE:
@ -246,28 +301,65 @@ static bool combobox_msg_proc(JWidget widget, JMessage msg)
break;
case JM_DESTROY:
{
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
JLink link;
jcombobox_clear(widget);
jlist_free(combobox->items);
jfree(combobox);
break;
JI_LIST_FOR_EACH(combobox->items, link)
jfree(link->data);
case JM_REQSIZE: {
int w, h;
jlist_free(combobox->items);
jfree(combobox);
msg->reqsize.w = 0;
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;
case JM_WINMOVE:
{
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
if (combobox->window) {
JRect rc = combobox_get_windowpos(combobox);
jwindow_move(combobox->window, rc);
jrect_free(rc);
case JM_BUTTONPRESSED:
if (combobox->window != NULL) {
if (!jwidget_has_mouse(jwidget_get_view(combobox->listbox))) {
combobox_close_window(widget);
return TRUE;
}
}
break;
}
return FALSE;
@ -384,20 +476,24 @@ static void combobox_open_window(JWidget widget)
{
ComboBox *combobox = jwidget_get_data(widget, JI_COMBOBOX);
if (!combobox->window) {
JWidget view, listbox;
JWidget view;
JLink link;
int size;
JRect rc;
combobox->window = jwindow_new(NULL);
view = jview_new();
listbox = jlistbox_new();
combobox->listbox = jlistbox_new();
listbox->user_data[0] = widget;
jwidget_add_hook(listbox, JI_WIDGET, combobox_listbox_msg_proc, NULL);
combobox->listbox->user_data[0] = widget;
jwidget_add_hook(combobox->listbox, JI_WIDGET,
combobox_listbox_msg_proc, NULL);
JI_LIST_FOR_EACH(combobox->items, link)
jwidget_add_child(listbox, jlistitem_new(link->data));
JI_LIST_FOR_EACH(combobox->items, link) {
ComboItem *item = link->data;
jwidget_add_child(combobox->listbox,
jlistitem_new(item->text));
}
jwindow_ontop(combobox->window, TRUE);
jwidget_noborders(combobox->window);
@ -406,14 +502,14 @@ static void combobox_open_window(JWidget widget)
jwidget_set_min_size
(view,
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);
jview_attach(view, listbox);
jview_attach(view, combobox->listbox);
jwidget_signal_off(listbox);
jlistbox_select_index(listbox, combobox->selected);
jwidget_signal_on(listbox);
jwidget_signal_off(combobox->listbox);
jlistbox_select_index(combobox->listbox, combobox->selected);
jwidget_signal_on(combobox->listbox);
jwindow_remap(combobox->window);
@ -421,8 +517,10 @@ static void combobox_open_window(JWidget widget)
jwindow_position(combobox->window, rc->x1, rc->y1);
jrect_free(rc);
jmanager_add_msg_filter(JM_BUTTONPRESSED, widget);
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);
combobox->window = NULL;
jmanager_remove_msg_filter(JM_BUTTONPRESSED, widget);
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)));
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 <string.h>
#include <limits.h>
#include <allegro/unicode.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 *top = tag_get_attr(tag, "top");
Attr *bottom = tag_get_attr(tag, "bottom");
Attr *bevel = tag_get_attr(tag, "bevel");
jwidget_set_align(widget,
(left ? JI_LEFT:
right ? JI_RIGHT: JI_CENTER) |
(top ? JI_TOP:
bottom ? JI_BOTTOM: JI_MIDDLE));
(left ? JI_LEFT: (right ? JI_RIGHT: JI_CENTER)) |
(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");
jwidget_set_align(widget,
(center ? JI_CENTER:
right ? JI_RIGHT: JI_LEFT) |
(top ? JI_TOP:
bottom ? JI_BOTTOM: JI_MIDDLE));
(center ? JI_CENTER: (right ? JI_RIGHT: JI_LEFT)) |
(top ? JI_TOP: (bottom ? JI_BOTTOM: JI_MIDDLE)));
}
}
}

View File

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

View File

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

View File

@ -533,12 +533,7 @@ bool jmanager_generate_messages(JWidget manager)
count = 0;
while (t - timers[c]->last_time > timers[c]->interval) {
timers[c]->last_time += timers[c]->interval;
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);
++count;
/* we spend too much time here */
if (ji_clock - t > timers[c]->interval) {
@ -546,6 +541,14 @@ bool jmanager_generate_messages(JWidget manager)
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)
{
JMessage message;
JLink link, next;
assert(timer_id >= 0 && timer_id < n_timers);
assert(timers[timer_id] != NULL);
jfree(timers[timer_id]);
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)

View File

@ -31,6 +31,7 @@
#include <stdlib.h>
#include <string.h>
#include <allegro/unicode.h>
void *jmalloc(unsigned long n_bytes)
{
@ -80,6 +81,6 @@ void jfree(void *mem)
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;
}
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)
{
JWidget old_menu;

View File

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

View File

@ -96,7 +96,7 @@ struct jmessage_signal
struct jmessage_timer
{
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 */
};

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)
{
JLink link;
register JLink link;
assert_valid_widget(widget);
JI_LIST_FOR_EACH(widget->hooks, link) {

View File

@ -60,6 +60,7 @@ enum {
ICON_MENU_MARK,
ICON_RADIO_EDGE,
ICON_RADIO_MARK,
ICON_COMBOBOX,
ICONS,
};
@ -86,12 +87,10 @@ static struct {
{ TRUE, default_theme_imenum },
{ FALSE, default_theme_iradioe },
{ FALSE, default_theme_iradiom },
{ FALSE, default_theme_icombobox },
};
static BITMAP *icons_bitmap[ICONS] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
static BITMAP *icons_bitmap[ICONS];
static void theme_destroy(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 theme;
int c;
theme = jtheme_new();
if (!theme)
return NULL;
for (c=0; c<ICONS; c++)
icons_bitmap[c] = NULL;
theme->name = "Standard Theme";
theme->check_icon_size = 8;
theme->radio_icon_size = 8;
@ -327,6 +330,12 @@ static void theme_init_widget(JWidget widget)
BORDER(1);
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_MENUBAR:
case JI_MENUBOX:

View File

@ -296,6 +296,18 @@ static unsigned char default_theme_iclose[66] = {
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] = {
8, 8,
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);
/* initialises the application */
if (app_init(argc, argv) < 0)
if (!app_init(argc, argv))
return 1;
app_loop();

View File

@ -206,7 +206,7 @@ void set_current_editor(JWidget editor)
set_current_sprite(editor_get_sprite(current_editor));
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));
app_refresh_screen();
rebuild_sprite_list();
app_realloc_sprite_list();
}
}

View File

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

View File

@ -259,14 +259,14 @@ static DATA gfx_data[GFX_BITMAP_COUNT] =
/* GFX_FILE_HOME */
{ 7, 9,
" # "
" # # "
" # # "
" ### "
" ##### "
"#######"
"# #"
"# ### #"
"# # # #"
"# # # #"
"#######" },
"#######"
"## ##"
"## ##"
"## ##"
"## ##" },
/* GFX_FILE_FONTS */
{ 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 */
{ 8, 8,
" #### "

View File

@ -54,10 +54,8 @@
#endif
#define REBUILD_LOCK 1
#define REBUILD_ROOT_MENU 2
#define REBUILD_RECENT_LIST 8
#define REBUILD_FULLREFRESH 16
#define REBUILD_RECENT_LIST 2
#define REFRESH_FULL_SCREEN 4
/**************************************************************/
@ -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 int monitor_timer = -1;
static JList monitors;
static bool ji_screen_created = FALSE;
static volatile int next_idle_flags = 0;
@ -92,6 +103,9 @@ static JList icon_buttons;
static bool double_buffering;
static int screen_scaling;
static Monitor *monitor_new(bool (*proc)(void *), void *data);
static void monitor_free(Monitor *monitor);
/* load & save graphics configuration */
static void load_gui_config(int *w, int *h, int *bpp, bool *fullscreen);
static void save_gui_config(void);
@ -106,7 +120,7 @@ static void regen_theme_and_fixup_icons(void);
*/
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);
@ -222,6 +236,8 @@ int init_module_gui(void)
}
gfx_done:;
monitors = jlist_new();
/* create the default-manager */
manager = jmanager_new();
jwidget_add_hook(manager, JI_WIDGET, manager_msg_proc, NULL);
@ -261,6 +277,14 @@ int init_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) {
BITMAP *old_bmp = ji_screen;
ji_set_screen(screen);
@ -281,6 +305,24 @@ void exit_module_gui(void)
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)
{
*w = get_config_int("GfxMode", "Width", 0);
@ -347,23 +389,14 @@ void gui_run(void)
void gui_feedback(void)
{
/* menu stuff */
if (!(next_idle_flags & REBUILD_LOCK)) {
if (next_idle_flags & REBUILD_ROOT_MENU) {
next_idle_flags ^= REBUILD_ROOT_MENU;
load_root_menu();
next_idle_flags |= REBUILD_RECENT_LIST;
}
if (next_idle_flags & REBUILD_RECENT_LIST) {
if (next_idle_flags & REBUILD_RECENT_LIST) {
if (app_realloc_recent_list())
next_idle_flags ^= REBUILD_RECENT_LIST;
app_realloc_recent_list();
}
}
if (next_idle_flags & REBUILD_FULLREFRESH) {
next_idle_flags ^= REBUILD_FULLREFRESH;
update_screen_for_sprite(current_sprite);
}
if (next_idle_flags & REFRESH_FULL_SCREEN) {
next_idle_flags ^= REFRESH_FULL_SCREEN;
update_screen_for_sprite(current_sprite);
}
/* record file if is necessary */
@ -534,26 +567,6 @@ JWidget load_widget(const char *filename, const char *name)
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)
{
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;
}
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 */
@ -719,6 +742,32 @@ static bool manager_msg_proc(JWidget widget, JMessage msg)
gui_feedback();
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: {
Command *command = command_get_by_key(msg);
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);
void rebuild_lock(void);
void rebuild_unlock(void);
void rebuild_root_menu(void);
void rebuild_sprite_list(void);
void rebuild_recent_list(void);
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);
/* 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 */

View File

@ -46,6 +46,7 @@ static JWidget frame_popup_menu;
static JWidget cel_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 convert_xmlelem_to_menu(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);
}
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;
DIRS *dirs, *dir;
@ -199,23 +217,6 @@ int load_root_menu(void)
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)
{
JWidget menu = NULL;

View File

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

View File

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

View File

@ -1,5 +1,5 @@
/* 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
* it under the terms of the GNU General Public License as published by
@ -24,6 +24,7 @@
#include "jinete/jbase.h"
#include "jinete/jlist.h"
#include "jinete/jmutex.h"
#include "raster/gfxobj.h"
@ -35,46 +36,79 @@
/* void *data; */
/* } Property; */
static JMutex objects_mutex;
static unsigned int object_id = 0; /* last object ID created */
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 = jmalloc (size);
gfxobj = jmalloc(size);
if (!gfxobj)
return NULL;
gfxobj->type = type;
gfxobj->id = ++object_id;
/* gfxobj->properties = NULL; */
if (!objects)
objects = jlist_new();
jlist_append(objects, gfxobj);
jmutex_lock(objects_mutex);
{
gfxobj->type = type;
gfxobj->id = ++object_id;
/* gfxobj->properties = NULL; */
jlist_append(objects, gfxobj);
}
jmutex_unlock(objects_mutex);
return gfxobj;
}
void gfxobj_free (GfxObj *gfxobj)
void gfxobj_free(GfxObj *gfxobj)
{
jlist_remove (objects, gfxobj);
jfree (gfxobj);
jmutex_lock(objects_mutex);
{
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;
jmutex_lock(objects_mutex);
{
JI_LIST_FOR_EACH(objects, link)
if (((GfxObj *)link->data)->id == id)
return (GfxObj *)link->data;
if (((GfxObj *)link->data)->id == id) {
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 */
/* ji_assert (!gfxobj_find (id)); */
@ -83,7 +117,7 @@ void _gfxobj_set_id (GfxObj *gfxobj, int id)
}
#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;

View File

@ -1,5 +1,5 @@
/* 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
* it under the terms of the GNU General Public License as published by
@ -45,6 +45,9 @@ struct GfxObj
/* struct GfxObjProperty *properties; */
};
bool gfxobj_init(void);
void gfxobj_exit(void);
GfxObj *gfxobj_new(int type, int size);
void gfxobj_free(GfxObj *gfxobj);

View File

@ -38,10 +38,8 @@ typedef struct PAL
PALETTE pal;
} PAL;
static int index_count;
static Layer *index2layer(Layer *layer, int index);
static int layer2index(const Layer *layer, const Layer *find_layer);
static Layer *index2layer(Layer *layer, int index, int *index_count);
static int layer2index(const Layer *layer, const Layer *find_layer, int *index_count);
static Sprite *general_copy(const Sprite *sprite);
@ -316,6 +314,20 @@ void sprite_mark_as_saved(Sprite *sprite)
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 res = FALSE;
@ -734,31 +746,31 @@ void sprite_generate_mask_boundaries(Sprite *sprite)
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)
{
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;
else {
index_count++;
(*index_count)++;
if (layer_is_set (layer)) {
Layer *found;
JLink link;
JI_LIST_FOR_EACH(layer->layers, link) {
if ((found = index2layer(link->data, index)))
if ((found = index2layer(link->data, index, index_count)))
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)
return index_count;
return *index_count;
else {
index_count++;
(*index_count)++;
if (layer_is_set (layer)) {
if (layer_is_set(layer)) {
JLink link;
int found;
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;
}
}

View File

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

View File

@ -1,5 +1,5 @@
/* 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
* it under the terms of the GNU General Public License as published by
@ -24,6 +24,7 @@
#include "jinete/jinete.h"
#include "console/console.h"
#include "core/app.h"
#include "file/file.h"
#include "modules/gui.h"
#include "modules/sprites.h"
@ -128,7 +129,7 @@ void SaveSprite(const char *filename)
}
sprite_set_filename(current_sprite, filename);
rebuild_sprite_list();
app_realloc_sprite_list();
if (sprite_save(current_sprite) == 0)
sprite_mark_as_saved(current_sprite);

View File

@ -16,19 +16,24 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef FILE_ASE_H
#define FILE_ASE_H
#ifndef TEST_TEST_H
#define TEST_TEST_H
#include <assert.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);
int ase_file_write_f(FILE *f, struct Sprite *sprite);
va_start(ap, format);
uvszprintf(buf, sizeof(buf), format, ap);
va_end(ap);
int fgetw(FILE *file);
long fgetl(FILE *file);
int fputw(int w, FILE *file);
int fputl(long l, FILE *file);
fputs(buf, stdout);
fflush(stdout);
}
#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
* 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
* it under the terms of the GNU General Public License as published by
@ -19,23 +19,25 @@
#ifndef UTIL_HASH_H
#define UTIL_HASH_H
typedef struct HashBucket {
typedef struct HashBucket
{
char *key;
void *data;
struct HashBucket *next;
} HashBucket;
typedef struct HashTable {
typedef struct HashTable
{
int size;
HashBucket **table;
} HashTable;
HashTable *hash_new (int size);
void hash_free (HashTable *table, void (*func) (void *));
HashTable *hash_new(int size);
void hash_free(HashTable *table, void (*func)(void *));
void *hash_insert (HashTable *table, const char *key, void *data);
void *hash_lookup (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_insert(HashTable *table, const char *key, void *data);
void *hash_lookup(HashTable *table, const char *key);
void *hash_remove(HashTable *table, const char *key);
void hash_enumerate(HashTable *table, void (*callback)(const char *, void *));
#endif /* UTIL_HASH_H */

View File

@ -1,5 +1,5 @@
/* 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
* it under the terms of the GNU General Public License as published by
@ -29,8 +29,9 @@
#include <stdlib.h>
#include "console/console.h"
#include "core/app.h"
#include "raster/image.h"
#include "widgets/statebar.h"
#endif
@ -40,6 +41,7 @@ static float FRandom (float amount);
void mapgen (Image *image, int seed, float fractal_factor)
{
Progress *progress = NULL;
float **map;
float amount = 128;
float min, max;
@ -51,9 +53,9 @@ void mapgen (Image *image, int seed, float fractal_factor)
/**********************************************************************/
/* create the map */
map = malloc (sizeof (float *) * size);
map = malloc (sizeof(float *) * size);
for (i = 0; i < size; i++)
map[i] = malloc (sizeof (float) * size);
map[i] = malloc(sizeof(float) * size);
/* Do the corners */
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];
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) {
/* This is the square phase */
for (j=i; j<size; j+=2*i)
@ -92,9 +96,12 @@ void mapgen (Image *image, int seed, float 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 */
@ -112,12 +119,12 @@ void mapgen (Image *image, int seed, float fractal_factor)
k = (int)((map[i][j] - min)/(max - min) * 256);
if (k > 255)
k = 255;
image_putpixel (image, i, j, k);
image_putpixel(image, i, j, k);
}
for (i=0; i<size; i++)
jfree (map[i]);
jfree (map);
jfree(map[i]);
jfree(map);
}
/* Handles wrapping when seeking neighbours */

View File

@ -1,5 +1,5 @@
/* 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
* 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*/
tree=create_node(0,0,0,64,64,64,0);
/*Scan the bitmaps*/
add_progress(stock->nimage+1);
/* add_progress(stock->nimage+1); */
for (c_bmp=0;c_bmp<stock->nimage;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 (x=0;x<stock->image[c_bmp]->w;x++) {
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;
} 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*/
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*/
if (n_colours > n_entries) {
int n_colours1 = n_colours;
add_progress(n_colours1 - n_entries);
/* int n_colours1 = n_colours; */
/* add_progress(n_colours1 - n_entries); */
while (n_colours>n_entries) {
Ep=0xFFFFFFFFul;
minimum_Ep(tree,&Ep);
tree=collapse_nodes(tree,&n_colours,n_entries,Ep);
if (n_colours > n_entries)
do_progress(n_colours1 - n_colours);
/* if (n_colours > n_entries) */
/* do_progress(n_colours1 - n_colours); */
}
del_progress();
/* del_progress(); */
}
del_progress();
/* del_progress(); */
/*Fill palette*/
c=0;
fill_palette(tree,&c,pal,1);

View File

@ -1068,8 +1068,7 @@ static bool editor_msg_proc(JWidget widget, JMessage msg)
}
case JM_TIMER:
if (msg->timer.timer_id == editor->mask_timer_id &&
msg->timer.count == 0) {
if (msg->timer.timer_id == editor->mask_timer_id) {
if (editor->sprite) {
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
* 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
* 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
*/
extern FileType filetype_ase;
extern FileType filetype_bmp;
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;
#ifndef WIDGETS_FILEVIEW_H
#define WIDGETS_FILEVIEW_H
static FileType *filetypes[] =
{
&filetype_ase,
&filetype_bmp,
&filetype_fli,
&filetype_jpeg,
&filetype_pcx,
&filetype_tga,
&filetype_gif,
&filetype_ico,
&filetype_png,
NULL
};
#include "jinete/jbase.h"
#include "core/file_system.h"
/* TODO use some JI_SIGNAL_USER */
#define SIGNAL_FILEVIEW_FILE_SELECTED 0x10006
#define SIGNAL_FILEVIEW_FILE_ACCEPT 0x10007
#define SIGNAL_FILEVIEW_CURRENT_FOLDER_CHANGED 0x10008
JWidget fileview_new(FileItem *start_folder, const char *exts);
int fileview_type(void);
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 play_animation(void);
JWidget status_bar_new(void)
{
#define BUTTON_NEW(name, text, data) \
@ -85,7 +83,7 @@ JWidget status_bar_new(void)
status_bar->widget = widget;
status_bar->timeout = 0;
status_bar->nprogress = 0;
status_bar->progress = jlist_new();
/* construct the commands box */
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)
{
StatusBar *status_bar = status_bar_data(widget);
@ -210,15 +159,56 @@ void status_bar_update(JWidget widget)
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)
{
StatusBar *status_bar = status_bar_data(widget);
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);
break;
}
case JM_REQSIZE:
msg->reqsize.w = msg->reqsize.h =
@ -238,63 +228,53 @@ static bool status_bar_msg_proc(JWidget widget, JMessage msg)
break;
case JM_DRAW: {
JRect rect = jwidget_get_rect(widget);
JRect rc = jwidget_get_rect(widget);
jdraw_rectedge(rect, ji_color_facelight(), ji_color_faceshadow());
jrect_shrink(rect, 1);
jdraw_rectedge(rc, ji_color_facelight(), ji_color_faceshadow());
jrect_shrink(rc, 1);
jdraw_rect(rect, ji_color_face());
jrect_shrink(rect, 1);
jdraw_rect(rc, ji_color_face());
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 */
else if (widget->text) {
jdraw_rectfill(rect, ji_color_face());
if (widget->text) {
jdraw_rectfill(rc, ji_color_face());
text_mode(-1);
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,
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;
}
@ -369,41 +349,37 @@ static void button_command(JWidget widget, void *data)
Sprite *sprite = current_sprite;
if (sprite) {
int old_frame = sprite->frame;
const char *cmd = NULL;
switch ((int)data) {
case ACTION_LAYER:
command_execute(command_get_by_name(CMD_LAYER_PROPERTIES), NULL);
cmd = CMD_LAYER_PROPERTIES;
break;
case ACTION_FIRST:
sprite->frame = 0;
cmd = CMD_GOTO_FIRST_FRAME;
break;
case ACTION_PREV:
if ((--sprite->frame) < 0)
sprite->frame = sprite->frames-1;
cmd = CMD_GOTO_PREVIOUS_FRAME;
break;
case ACTION_PLAY:
play_animation();
cmd = CMD_PLAY_ANIMATION;
break;
case ACTION_NEXT:
if ((++sprite->frame) >= sprite->frames)
sprite->frame = 0;
cmd = CMD_GOTO_NEXT_FRAME;
break;
case ACTION_LAST:
sprite->frame = sprite->frames-1;
cmd = CMD_GOTO_LAST_FRAME;
break;
}
if (sprite->frame != old_frame) {
update_from_layer(widget->user_data[0]);
update_screen_for_sprite(sprite);
}
if (cmd)
command_execute(command_get_by_name(cmd), NULL);
}
}
@ -436,83 +412,3 @@ static void update_from_layer(StatusBar *status_bar)
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"
typedef struct Progress
{
JWidget status_bar;
float pos;
} Progress;
typedef struct StatusBar
{
JWidget widget;
int timeout;
/* progress bar */
int nprogress;
struct {
int max;
int pos;
} progress[2];
JList progress;
/* box of main commands */
JWidget commands_box;
@ -45,17 +47,20 @@ typedef struct StatusBar
JWidget b_last; /* go to last frame */
} StatusBar;
/* status_bar */
JWidget status_bar_new(void);
int status_bar_type(void);
StatusBar *status_bar_data(JWidget status_bar);
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);
/* progress */
Progress *progress_new(JWidget status_bar);
void progress_free(Progress *progress);
void progress_update(Progress *progress, float progress_pos);
#endif /* WIDGETS_STATEBAR_H */

View File

@ -1,5 +1,5 @@
/* 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
* 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()); */
/* int dir = (int)jwidget_get_data(widget, tabs_type()); */
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;
}