From 9bf40439d4375f5b5df3c390203d121fe994fed2 Mon Sep 17 00:00:00 2001 From: David Capello Date: Sat, 11 Oct 2008 20:41:27 +0000 Subject: [PATCH] Added jstring. The file-selector now uses jstrings. --- ChangeLog | 5 + config.h | 2 +- makefile.lst | 1 + src/commands/cmd_load_mask.cpp | 11 +- src/commands/cmd_open_file.cpp | 13 +-- src/commands/cmd_palette_editor.cpp | 30 ++---- src/commands/cmd_save_file.cpp | 18 ++-- src/commands/cmd_save_mask.cpp | 12 +-- src/commands/cmd_sprite_properties.cpp | 4 +- src/core/file_system.cpp | 2 +- src/dialogs/drawtext.cpp | 13 ++- src/dialogs/filesel.cpp | 92 ++++++++-------- src/dialogs/filesel.h | 8 +- src/jinete/jinete.h | 1 + src/jinete/jstring.cpp | 142 +++++++++++++++++++++++++ src/jinete/jstring.h | 119 +++++++++++++++++++++ 16 files changed, 361 insertions(+), 112 deletions(-) create mode 100644 src/jinete/jstring.cpp create mode 100644 src/jinete/jstring.h diff --git a/ChangeLog b/ChangeLog index 126295fdf..348dac501 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2008-10-11 David A. Capello + * src/dialogs/filesel.cpp (ase_file_selector): Now it uses + "jstring" instead of "char*". + + * src/jinete/jstring.h (jstring): Added. + * src/raster/undoable.cpp (Undoable::set_constant_frame_rate): Added. (Undoable::set_frame_length): Renamed to set_frame_duration. diff --git a/config.h b/config.h index bcb3ee18a..c9d1a4525 100644 --- a/config.h +++ b/config.h @@ -25,7 +25,7 @@ /* general information */ #define PACKAGE "ASE" -#define VERSION "0.6b2" +#define VERSION "0.6" #define WEBSITE "http://www.aseprite.org/" #define COPYRIGHT "Copyright (C) 2001-2008 David A. Capello" diff --git a/makefile.lst b/makefile.lst index 4db9d42da..4de8d302a 100644 --- a/makefile.lst +++ b/makefile.lst @@ -147,6 +147,7 @@ COMMON_SOURCES = \ src/jinete/jsep.cpp \ src/jinete/jslider.cpp \ src/jinete/jstream.cpp \ + src/jinete/jstring.cpp \ src/jinete/jsystem.cpp \ src/jinete/jtextbox.cpp \ src/jinete/jtheme.cpp \ diff --git a/src/commands/cmd_load_mask.cpp b/src/commands/cmd_load_mask.cpp index 2217ed922..eabbb0507 100644 --- a/src/commands/cmd_load_mask.cpp +++ b/src/commands/cmd_load_mask.cpp @@ -38,15 +38,13 @@ static void cmd_load_mask_execute(const char *argument) { /* get current sprite */ Sprite *sprite = current_sprite; - char *filename = ase_file_selector(_("Load .msk File"), "", "msk"); - if (filename) { - Mask *mask = load_msk_file(filename); + jstring filename = ase_file_selector(_("Load .msk File"), "", "msk"); + if (!filename.empty()) { + Mask *mask = load_msk_file(filename.c_str()); if (!mask) { jalert("%s<<%s<<%s||%s", _("Error"), _("Error loading .msk file"), - filename, _("&Close")); - - jfree(filename); + filename.c_str(), _("&Close")); return; } @@ -61,7 +59,6 @@ static void cmd_load_mask_execute(const char *argument) sprite_generate_mask_boundaries(sprite); update_screen_for_sprite(sprite); - jfree(filename); } } diff --git a/src/commands/cmd_open_file.cpp b/src/commands/cmd_open_file.cpp index f70efcc71..d47492ce7 100644 --- a/src/commands/cmd_open_file.cpp +++ b/src/commands/cmd_open_file.cpp @@ -142,7 +142,7 @@ static void monitor_free(void *_data) */ static void cmd_open_file_execute(const char *argument) { - char *filename; + jstring filename; /* interactive */ if (!argument) { @@ -152,11 +152,11 @@ static void cmd_open_file_execute(const char *argument) } /* load the file specified in the argument */ else { - filename = (char *)argument; + filename = argument; } - if (filename) { - FileOp *fop = fop_to_load_sprite(filename, FILE_LOAD_SEQUENCE_ASK); + if (!filename.empty()) { + FileOp *fop = fop_to_load_sprite(filename.c_str(), FILE_LOAD_SEQUENCE_ASK); if (fop) { if (fop->error) { @@ -173,7 +173,7 @@ static void cmd_open_file_execute(const char *argument) data->thread = thread; data->alert_window = jalert_new(PACKAGE "<monitor = add_gui_monitor(monitor_openfile_bg, @@ -224,9 +224,6 @@ static void cmd_open_file_execute(const char *argument) else { /* do nothing (the user cancelled or something like that) */ } - - if (filename != argument) - jfree(filename); } } diff --git a/src/commands/cmd_palette_editor.cpp b/src/commands/cmd_palette_editor.cpp index f2543c73c..08b4bbef3 100644 --- a/src/commands/cmd_palette_editor.cpp +++ b/src/commands/cmd_palette_editor.cpp @@ -284,11 +284,9 @@ static void select_all_command(JWidget widget) static void load_command(JWidget widget) { Palette *palette; - char *filename; - - filename = ase_file_selector(_("Load Palette"), "", "pcx,bmp,tga,lbm,col"); - if (filename) { - palette = palette_load(filename); + jstring filename = ase_file_selector(_("Load Palette"), "", "pcx,bmp,tga,lbm,col"); + if (!filename.empty()) { + palette = palette_load(filename.c_str()); if (!palette) { jalert(_("Error<filename); + filename = sprite->filename; get_writable_extensions(exts, sizeof(exts)); for (;;) { newfilename = ase_file_selector(_("Save Sprite"), filename, exts); - if (!newfilename) + if (newfilename.empty()) return; - ustrcpy(filename, newfilename); - jfree(newfilename); + + filename = newfilename; /* does the file exist? */ - if (exists(filename)) { + if (exists(filename.c_str())) { /* ask if the user wants overwrite the file? */ ret = jalert("%s<<%s<<%s||%s||%s||%s", _("Warning"), _("File exists, overwrite it?"), - get_filename(filename), + get_filename(filename.c_str()), _("&Yes"), _("&No"), _("&Cancel")); } else @@ -224,7 +224,7 @@ static void cmd_save_file_as_execute(const char *argument) /* "no": we must back to select other file-name */ } - sprite_set_filename(sprite, filename); + sprite_set_filename(sprite, filename.c_str()); app_realloc_sprite_list(); save_sprite_in_background(sprite); diff --git a/src/commands/cmd_save_mask.cpp b/src/commands/cmd_save_mask.cpp index b21d0ed0d..555ef7a9e 100644 --- a/src/commands/cmd_save_mask.cpp +++ b/src/commands/cmd_save_mask.cpp @@ -42,20 +42,20 @@ static void cmd_save_mask_execute(const char *argument) { /* get current sprite */ Sprite *sprite = current_sprite; - char *filename = "default.msk"; + jstring filename = "default.msk"; int ret; for (;;) { filename = ase_file_selector(_("Save .msk File"), filename, "msk"); - if (!filename) + if (filename.empty()) return; /* does the file exist? */ - if (exists(filename)) { + if (exists(filename.c_str())) { /* ask if the user wants overwrite the file? */ ret = jalert("%s<<%s<<%s||%s||%s||%s", _("Warning"), _("File exists, overwrite it?"), - get_filename(filename), + get_filename(filename.c_str()), _("&Yes"), _("&No"), _("&Cancel")); } else @@ -71,10 +71,10 @@ static void cmd_save_mask_execute(const char *argument) /* "no": we must back to select other file-name */ } - if (save_msk_file(sprite->mask, filename) != 0) + if (save_msk_file(sprite->mask, filename.c_str()) != 0) jalert("%s<<%s<<%s||%s", _("Error"), _("Error saving .msk file"), - filename, _("&Close")); + filename.c_str(), _("&Close")); } Command cmd_save_mask = { diff --git a/src/commands/cmd_sprite_properties.cpp b/src/commands/cmd_sprite_properties.cpp index 010050434..83ff4611a 100644 --- a/src/commands/cmd_sprite_properties.cpp +++ b/src/commands/cmd_sprite_properties.cpp @@ -43,7 +43,7 @@ static void cmd_sprite_properties_execute(const char *argument) { JWidget window, killer, name, type, size, frames, speed, ok; Sprite *sprite = current_sprite; - char *imgtype_text; + jstring imgtype_text; char buf[256]; /* load the window widget */ @@ -82,7 +82,7 @@ static void cmd_sprite_properties_execute(const char *argument) jwidget_set_text(name, sprite->filename); /* color mode */ - jwidget_set_text(type, imgtype_text); + jwidget_set_text(type, imgtype_text.c_str()); /* sprite size (width and height) */ usprintf(buf, "%dx%d (", sprite->w, sprite->h); diff --git a/src/core/file_system.cpp b/src/core/file_system.cpp index 7c1df4ab9..adbd99a41 100644 --- a/src/core/file_system.cpp +++ b/src/core/file_system.cpp @@ -108,7 +108,7 @@ struct FileItem #endif }; -/* the root of the file-system */ +// the root of the file-system static FileItem *rootitem = NULL; static HashTable *hash_fileitems = NULL; static unsigned int current_file_system_version = 0; diff --git a/src/dialogs/drawtext.cpp b/src/dialogs/drawtext.cpp index baa4f0c4f..1b3a8794f 100644 --- a/src/dialogs/drawtext.cpp +++ b/src/dialogs/drawtext.cpp @@ -278,15 +278,14 @@ static FONT *my_load_font(const char *filename) static void button_font_command(JWidget widget) { - char *filename; + jstring filename = + ase_file_selector(_("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); + if (!filename.empty()) { + set_config_string("DrawText", "Font", filename.c_str()); update_button_text(); - jfree(filename); } } diff --git a/src/dialogs/filesel.cpp b/src/dialogs/filesel.cpp index 07a5252dd..f7c2ec226 100644 --- a/src/dialogs/filesel.cpp +++ b/src/dialogs/filesel.cpp @@ -18,7 +18,9 @@ #include "config.h" -#include +#include +#include + #include #include #include @@ -69,9 +71,9 @@ static bool filetype_msg_proc(JWidget widget, JMessage msg); * - the 'core/file_system' routines. * - the 'widgets/fileview' widget. */ -char *ase_file_selector(const char *message, - const char *init_path, - const char *exts) +jstring ase_file_selector(const jstring& message, + const jstring& init_path, + const jstring& exts) { static JWidget window = NULL; FileItem *start_folder = NULL; @@ -79,9 +81,7 @@ char *ase_file_selector(const char *message, JWidget goback, goforward, goup; JWidget filename_entry; JWidget filetype; - char buf[512]; - char *result = NULL; - char *tok; + jstring result; file_system_refresh(); @@ -92,45 +92,42 @@ char *ase_file_selector(const char *message, navigation_history); } - /* 'buf' will contain the start folder path */ - ustrcpy(buf, init_path); + // use the current path + jstring start_folder_path; - /* use the current path */ - if (get_filename(buf) == buf) { - char path[512]; + // if init_path doesn't contain a path... + if (init_path.filepath().empty()) { + // get the saved `path' in the configuration file + jstring path = get_config_string("FileSelect", "CurrentDirectory", ""); + start_folder = get_fileitem_from_path(path.c_str()); - /* get saved `path' */ - ustrcpy(path, get_config_string("FileSelect", "CurrentDirectory", "")); - start_folder = get_fileitem_from_path(path); + // is the folder find? if (!start_folder) { - /* if the `path' doesn't exist */ - if ((!ugetat(path, 0)) || (!ji_dir_exists(path))) { - /* try to get current `path' */ + // if the `path' doesn't exist... + if (path.empty() || (!ji_dir_exists(path.c_str()))) { + // we can get the current `path' from the system #ifdef HAVE_DRIVES int drive = _al_getdrive(); #else int drive = 0; #endif - - _al_getdcwd(drive, path, sizeof(path) - ucwidth(OTHER_PATH_SEPARATOR)); + char tmp[1024]; + _al_getdcwd(drive, tmp, sizeof(tmp) - ucwidth(OTHER_PATH_SEPARATOR)); + path = tmp; } - fix_filename_case(path); - fix_filename_slashes(path); - put_backslash(path); - - ustrcat(path, buf); - ustrcpy(buf, path); + start_folder_path = path / init_path; } } else { - /* remove the filename */ - *get_filename(buf) = 0; + // remove the filename + start_folder_path = init_path.filepath() / ""; } + start_folder_path.fix_separators(); if (!start_folder) - start_folder = get_fileitem_from_path(buf); - + start_folder = get_fileitem_from_path(start_folder_path.c_str()); + if (!window) { JWidget view, location; @@ -159,7 +156,7 @@ char *ase_file_selector(const char *message, jbutton_add_command(goup, goup_command); view = jview_new(); - fileview = fileview_new(start_folder, exts); + fileview = fileview_new(start_folder, exts.c_str()); jwidget_add_hook(fileview, -1, fileview_msg_proc, NULL); jwidget_add_hook(location, -1, location_msg_proc, NULL); @@ -196,20 +193,21 @@ char *ase_file_selector(const char *message, /* 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); - } + + std::vector tokens; + std::vector::iterator tok; + + exts.split(',', tokens); + for (tok=tokens.begin(); tok!=tokens.end(); ++tok) + jcombobox_add_string(filetype, tok->c_str(), NULL); /* file name entry field */ filename_entry = jwidget_find_name(window, "filename"); - jwidget_set_text(filename_entry, get_filename(init_path)); + jwidget_set_text(filename_entry, init_path.filename().c_str()); select_filetype_from_filename(window); /* setup the title of the window */ - jwidget_set_text(window, message); + jwidget_set_text(window, message.c_str()); /* get the ok-button */ ok = jwidget_find_name(window, "ok"); @@ -221,26 +219,22 @@ char *ase_file_selector(const char *message, 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)); + jstring buf = fileitem_get_filename(folder); + 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)); + if (buf.extension().empty()) { + buf += '.'; + buf += jcombobox_get_selected_string(filetype); } /* duplicate the buffer to return a new string */ - result = jstrdup(buf); + result = buf; /* save the path in the configuration file */ set_config_string("FileSelect", "CurrentDirectory", diff --git a/src/dialogs/filesel.h b/src/dialogs/filesel.h index cdde323be..9eac12911 100644 --- a/src/dialogs/filesel.h +++ b/src/dialogs/filesel.h @@ -19,9 +19,11 @@ #ifndef DIALOGS_FILESEL_H #define DIALOGS_FILESEL_H -char *ase_file_selector(const char *message, - const char *init_path, - const char *exts); +#include "jinete/jstring.h" + +jstring ase_file_selector(const jstring& message, + const jstring& init_path, + const jstring& exts); #endif /* DIALOGS_FILESEL_H */ diff --git a/src/jinete/jinete.h b/src/jinete/jinete.h index 2f98a346e..fe85475c7 100644 --- a/src/jinete/jinete.h +++ b/src/jinete/jinete.h @@ -62,6 +62,7 @@ #include "jinete/jsep.h" #include "jinete/jslider.h" #include "jinete/jstream.h" +#include "jinete/jstring.h" #include "jinete/jsystem.h" #include "jinete/jtextbox.h" #include "jinete/jtheme.h" diff --git a/src/jinete/jstring.cpp b/src/jinete/jstring.cpp new file mode 100644 index 000000000..8f2e9276a --- /dev/null +++ b/src/jinete/jstring.cpp @@ -0,0 +1,142 @@ +/* Jinete - a GUI library + * Copyright (C) 2003-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 + +#include "jinete/jstring.h" + +#if defined ALLEGRO_WINDOWS + const char jstring::separator = '\\'; +#else + const char jstring::separator = '/'; +#endif + +jstring jstring::filepath() const +{ + const_reverse_iterator rit; + jstring res; + + for (rit=rbegin(); rit!=rend(); ++rit) + if (is_separator(*rit)) + break; + + if (rit != rend()) { + ++rit; + std::copy(begin(), const_iterator(rit.base()), + std::back_inserter(res)); + } + + return res; +} + +jstring jstring::filename() const +{ + const_reverse_iterator rit; + jstring res; + + for (rit=rbegin(); rit!=rend(); ++rit) + if (is_separator(*rit)) + break; + + std::copy(const_iterator(rit.base()), end(), + std::back_inserter(res)); + + return res; +} + +jstring jstring::extension() const +{ + const_reverse_iterator rit; + jstring res; + + // search for the first dot from the end of the string + for (rit=rbegin(); rit!=rend(); ++rit) { + if (is_separator(*rit)) + return res; + else if (*rit == '.') + break; + } + + if (rit != rend()) { + std::copy(const_iterator(rit.base()), end(), + std::back_inserter(res)); + } + + return res; +} + +jstring jstring::filetitle() const +{ + const_reverse_iterator rit; + const_iterator last_dot = end(); + jstring res; + + for (rit=rbegin(); rit!=rend(); ++rit) { + if (is_separator(*rit)) + break; + else if (*rit == '.' && last_dot == end()) + last_dot = rit.base()-1; + } + + for (const_iterator it(rit.base()); it!=end(); ++it) { + if (it == last_dot) + break; + else + res.push_back(*it); + } + + return res; +} + +jstring jstring::operator/(const jstring& component) const +{ + jstring res(*this); + res /= component; + return res; +} + +/** + * Adds a the file name @a component in the path (this string) + * separated with a slash. + */ +jstring& jstring::operator/=(const jstring& component) +{ + if (!empty() && !is_separator(*(end()-1))) + push_back(jstring::separator); + + operator+=(component); + return *this; +} + +void jstring::fix_separators() +{ + std::replace_if(begin(), end(), jstring::is_separator, jstring::separator); +} diff --git a/src/jinete/jstring.h b/src/jinete/jstring.h new file mode 100644 index 000000000..b1ea328f4 --- /dev/null +++ b/src/jinete/jstring.h @@ -0,0 +1,119 @@ +/* Jinete - a GUI library + * Copyright (C) 2003-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_STRING_H +#define JINETE_STRING_H + +#include + +/** + * A string of characters. + */ +class jstring : public std::basic_string +{ +public: + static const char separator; + + jstring() { + } + + explicit jstring(int length) + : std::string(length, static_cast(0)) + { + } + + jstring(const jstring& str) + : std::string(str) + { + } + + jstring(const std::string& str) + : std::string(str) + { + } + + jstring(const char* str) + : std::string(str) + { + } + + jstring(const char* str, int length) + : std::string(str, length) + { + } + + static bool is_separator(char c) { + return (c == '\\' || c == '/'); + } + + jstring filepath() const; + jstring filename() const; + jstring extension() const; + jstring filetitle() const; + + jstring operator/(const jstring& component) const; + jstring& operator/=(const jstring& component); + void fix_separators(); + + template + void split(value_type separator, List& result) const + { + jstring tok; + + tok.reserve(size()); + + for (const_iterator it=begin(); it!=end(); ++it) { + if (*it == separator) { + result.push_back(tok); + tok.clear(); + } + else + tok.push_back(*it); + } + } + +}; + +inline jstring operator+(const jstring& _s1, const char* _s2) +{ + jstring _res(_s1); + _res.append(jstring(_s2)); + return _res; +} + +inline jstring operator+(const char* _s1, const jstring& _s2) +{ + jstring _res(_s1); + _res.append(_s2); + return _res; +} + +#endif /* JINETE_STRING_H */