mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-27 06:35:16 +00:00
Added threads to load files in background.
Added a new file-selector (using PIDLs for Win32).
This commit is contained in:
parent
2aea148245
commit
528eaab937
33
ChangeLog
33
ChangeLog
@ -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
|
||||
|
7
TODO.txt
7
TODO.txt
@ -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
30
data/jids/filesel.jid
Normal 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>
|
@ -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.
|
||||
|
11
makefile.gcc
11
makefile.gcc
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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" | \
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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) */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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 */
|
||||
|
140
src/core/app.c
140
src/core/app.c
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
946
src/core/file_system.c
Normal 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
46
src/core/file_system.h
Normal 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 */
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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",
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
1221
src/file/file.c
1221
src/file/file.c
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) */
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "jinete/jlist.h"
|
||||
|
||||
#ifdef USE_JUNKLIST
|
||||
#ifdef USE_JUNKLIST /* TODO warning not thread safe */
|
||||
static JList junklist = NULL;
|
||||
#endif
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
99
src/jinete/jthread.c
Normal 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
44
src/jinete/jthread.h
Normal 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 */
|
@ -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) {
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
BIN
src/jinete/themes/stand/icombobox.pcx
Normal file
BIN
src/jinete/themes/stand/icombobox.pcx
Normal file
Binary file not shown.
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,6 +81,8 @@ enum {
|
||||
|
||||
GFX_ARROW_LEFT,
|
||||
GFX_ARROW_RIGHT,
|
||||
GFX_ARROW_UP,
|
||||
GFX_ARROW_DOWN,
|
||||
|
||||
GFX_BOX_SHOW,
|
||||
GFX_BOX_HIDE,
|
||||
|
@ -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,
|
||||
" #### "
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
106
src/test/test_file_system.c
Normal 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();
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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
489
src/widgets/fileview.c
Normal 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);
|
||||
}
|
||||
}
|
@ -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 */
|
@ -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();
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user