From 5b252c30f5af4072fa30d06eabe9a3596490161d Mon Sep 17 00:00:00 2001 From: David Capello Date: Mon, 14 Oct 2013 19:58:11 -0300 Subject: [PATCH] Add support for Unicode file names on Windows - Fixed issue #46: open .png files with Unicode chars - Fixed issue #150: ability to uncompress program in folders w/Unicode chars - Added base::utf8_iterator - Added base::FileHandle - Added base::get_app_path() - Modified ui::KeyMessage::ascii() -> unicodeChar() - Removed JI_NOTEXT flag - Added app::XmlDocumentRef class and app::open_xml() function - Added support for Unicode text exchange with Win32 clipboard --- CMakeLists.txt | 3 + .../include/allegro/platform/aintwin.h | 2 +- src/allegro/src/file.c | 2 +- src/allegro/src/win/utf8.h | 30 +++++ src/allegro/src/win/wdxver.c | 10 +- src/allegro/src/win/wsystem.c | 56 ++++---- src/allegro/src/win/wthread.c | 17 ++- src/allegro/src/win/wwnd.c | 14 +- src/app/CMakeLists.txt | 1 + src/app/app_menus.cpp | 8 +- src/app/commands/cmd_about.cpp | 2 +- src/app/commands/cmd_configure_tools.cpp | 2 - src/app/commands/cmd_developer_console.cpp | 2 +- src/app/commands/cmd_duplicate_sprite.cpp | 12 +- src/app/commands/cmd_frame_properties.cpp | 2 +- src/app/commands/cmd_goto_frame.cpp | 2 +- src/app/commands/cmd_launch.cpp | 5 +- src/app/commands/cmd_open_file.cpp | 7 +- src/app/commands/cmd_options.cpp | 2 - src/app/commands/cmd_palette_editor.cpp | 11 +- src/app/commands/cmd_refresh.cpp | 2 +- src/app/commands/cmd_save_file.cpp | 25 ++-- .../filters/cmd_convolution_matrix.cpp | 4 +- .../filters/convolution_matrix_stock.cpp | 14 +- .../filters/filter_target_buttons.cpp | 7 +- src/app/console.cpp | 29 ++-- src/app/dialogs/aniedit.cpp | 2 +- src/app/document.cpp | 7 +- src/app/document.h | 17 ++- src/app/drop_files.cpp | 2 +- src/app/file/ase_format.cpp | 8 +- src/app/file/bmp_format.cpp | 12 +- src/app/file/file.cpp | 83 ++++++------ src/app/file/fli_format.cpp | 18 +-- src/app/file/ico_format.cpp | 6 +- src/app/file/jpeg_format.cpp | 18 +-- src/app/file/pcx_format.cpp | 6 +- src/app/file/png_format.cpp | 8 +- src/app/file/tga_format.cpp | 6 +- src/app/file_system.cpp | 49 ++++--- src/app/gui_xml.cpp | 16 +-- src/app/gui_xml.h | 14 +- src/app/ini_file.cpp | 13 +- src/app/log.cpp | 2 +- src/app/modules/gui.cpp | 2 +- src/app/resource_finder.cpp | 19 ++- src/app/resource_finder.h | 2 +- src/app/tools/tool_box.cpp | 4 +- src/app/ui/button_set.cpp | 2 +- src/app/ui/color_button.cpp | 2 +- src/app/ui/context_bar.cpp | 2 +- src/app/ui/file_list.cpp | 14 +- src/app/ui/file_selector.cpp | 13 +- src/app/ui/main_window.cpp | 5 +- src/app/ui/popup_window_pin.cpp | 2 +- src/app/ui/popup_window_pin.h | 2 +- src/app/ui/skin/skin_theme.cpp | 21 ++- src/app/ui/status_bar.cpp | 14 +- src/app/ui/toolbar.cpp | 2 +- src/app/widget_loader.cpp | 65 ++++----- src/app/widget_loader.h | 7 +- src/app/widget_not_found.h | 6 +- src/app/widget_type_mismatch.h | 4 +- src/app/xml_document.cpp | 49 +++++++ .../{file/file_handle.h => xml_document.h} | 28 ++-- src/app/xml_exception.cpp | 2 +- src/app/xml_exception.h | 2 +- src/base/CMakeLists.txt | 1 + src/base/file_handle.cpp | 48 +++++++ src/base/file_handle.h | 25 ++++ src/base/fs.h | 1 + src/base/fs_unix.h | 5 + src/base/fs_win32.h | 21 ++- src/base/launcher.cpp | 11 +- src/base/memory_dump_win32.h | 8 +- src/base/shared_ptr.h | 15 ++- src/base/string.cpp | 60 +++++++++ src/base/string.h | 118 +++++++++++++++++ src/base/string_unittest.cpp | 59 +++++++++ src/main/main.cpp | 5 +- src/she/she_alleg4.cpp | 4 +- src/ui/accelerator.cpp | 44 +++---- src/ui/accelerator.h | 6 +- src/ui/alert.cpp | 2 +- src/ui/base.h | 3 +- src/ui/button.cpp | 8 +- src/ui/button.h | 8 +- src/ui/clipboard.cpp | 26 ++-- src/ui/combobox.cpp | 25 ++-- src/ui/combobox.h | 10 +- src/ui/custom_label.cpp | 2 +- src/ui/custom_label.h | 2 +- src/ui/entry.cpp | 124 ++++++++++-------- src/ui/int_entry.cpp | 2 +- src/ui/keys.cpp | 2 +- src/ui/keys.h | 2 +- src/ui/label.cpp | 4 +- src/ui/label.h | 2 +- src/ui/link_label.cpp | 6 +- src/ui/link_label.h | 10 +- src/ui/listitem.cpp | 2 +- src/ui/listitem.h | 2 +- src/ui/manager.cpp | 22 ++-- src/ui/menu.cpp | 10 +- src/ui/menu.h | 2 +- src/ui/message.cpp | 4 +- src/ui/message.h | 6 +- src/ui/popup_window.cpp | 2 +- src/ui/popup_window.h | 2 +- src/ui/separator.cpp | 2 +- src/ui/separator.h | 2 +- src/ui/textbox.cpp | 2 +- src/ui/textbox.h | 2 +- src/ui/theme.cpp | 16 +-- src/ui/tooltips.cpp | 2 +- src/ui/tooltips.h | 4 +- src/ui/widget.cpp | 31 ++--- src/ui/widget.h | 15 ++- src/ui/window.cpp | 6 +- src/ui/window.h | 2 +- src/updater/user_agent_win.c | 5 +- 121 files changed, 1020 insertions(+), 617 deletions(-) create mode 100644 src/allegro/src/win/utf8.h create mode 100644 src/app/xml_document.cpp rename src/app/{file/file_handle.h => xml_document.h} (62%) create mode 100644 src/base/file_handle.cpp create mode 100644 src/base/file_handle.h create mode 100644 src/base/string_unittest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f1777533..308564e80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -220,6 +220,9 @@ if(WIN32) # Windows XP is the minimum supported platform. add_definitions(-D_WIN32_WINNT=0x0501 -DWINVER=0x0501) + # We need Unicode support + add_definitions(-DUNICODE -D_UNICODE) + endif(WIN32) # -- Mac OS X -- diff --git a/src/allegro/include/allegro/platform/aintwin.h b/src/allegro/include/allegro/platform/aintwin.h index 7adbd1677..d306b966b 100644 --- a/src/allegro/include/allegro/platform/aintwin.h +++ b/src/allegro/include/allegro/platform/aintwin.h @@ -69,7 +69,7 @@ AL_FUNC(void, save_window_pos, (void)); /* main window */ #define WND_TITLE_SIZE 128 -AL_ARRAY(char, wnd_title); +AL_ARRAY(wchar_t, wnd_title); AL_VAR(int, wnd_x); AL_VAR(int, wnd_y); AL_VAR(int, wnd_width); diff --git a/src/allegro/src/file.c b/src/allegro/src/file.c index a1abe232c..77295a2c5 100644 --- a/src/allegro/src/file.c +++ b/src/allegro/src/file.c @@ -1961,7 +1961,7 @@ PACKFILE *pack_fopen_chunk(PACKFILE *f, int pack) do { size = new_size; tmp_dir = _AL_REALLOC(tmp_dir, size); - new_size = GetTempPath(size, tmp_dir); + new_size = GetTempPathA(size, tmp_dir); } while ( (size < new_size) && (new_size > 0) ); /* Check if we retrieved the path OK */ diff --git a/src/allegro/src/win/utf8.h b/src/allegro/src/win/utf8.h new file mode 100644 index 000000000..448e4c405 --- /dev/null +++ b/src/allegro/src/win/utf8.h @@ -0,0 +1,30 @@ +// Copyright (C) 2013 by David Capello + +#ifndef ALLEGRO_WIN_UTF8_H +#define ALLEGRO_WIN_UTF8_H + +static char* convert_widechar_to_utf8(const wchar_t* wstr) +{ + char* u8str; + int wlen = wcslen(wstr); + int u8len = WideCharToMultiByte(CP_UTF8, 0, wstr, wlen, NULL, 0, NULL, NULL); + u8len++; + u8str = _AL_MALLOC(u8len); + u8str[u8len-1] = 0; + WideCharToMultiByte(CP_UTF8, 0, wstr, wlen, u8str, u8len, NULL, NULL); + return u8str; +} + +static wchar_t* convert_utf8_to_widechar(const char* u8str) +{ + wchar_t* wstr; + int u8len = strlen(u8str); + int wlen = MultiByteToWideChar(CP_UTF8, 0, u8str, u8len, NULL, 0); + wlen++; + wstr = _AL_MALLOC(wlen * sizeof(wchar_t)); + wstr[wlen-1] = 0; + MultiByteToWideChar(CP_UTF8, 0, u8str, u8len, wstr, wlen); + return wstr; +} + +#endif diff --git a/src/allegro/src/win/wdxver.c b/src/allegro/src/win/wdxver.c index 00ae6fe8b..d954cfbbc 100644 --- a/src/allegro/src/win/wdxver.c +++ b/src/allegro/src/win/wdxver.c @@ -105,7 +105,7 @@ int get_dx_ver(void) } /* First check for DX 8 and 9 */ - dsetup_hinst = LoadLibrary( "DSETUP.DLL" ); + dsetup_hinst = LoadLibrary( L"DSETUP.DLL" ); if ( dsetup_hinst ) { DSetupCreate = (DSETUPCREATE)GetProcAddress(dsetup_hinst, "DirectXSetupGetVersion"); if ( DSetupCreate ) { @@ -171,10 +171,10 @@ int get_dx_ver(void) dx_version = 0x200; /* we are not supposed to be able to tell which SP we are on, so check for DInput */ - dinput_hinst = LoadLibrary("DINPUT.DLL"); + dinput_hinst = LoadLibrary(L"DINPUT.DLL"); if (!dinput_hinst) { /* no DInput... must be DX2 on NT 4 pre-SP3 */ - OutputDebugString("Couldn't LoadLibrary DInput\r\n"); + OutputDebugString(L"Couldn't LoadLibrary DInput\r\n"); return dx_version; } @@ -200,7 +200,7 @@ int get_dx_ver(void) /* now we know we are in Windows 9x (or maybe 3.1), so anything's possible; * first see if DDRAW.DLL even exists. */ - ddraw_hinst = LoadLibrary("DDRAW.DLL"); + ddraw_hinst = LoadLibrary(L"DDRAW.DLL"); if (!ddraw_hinst) { dx_version = 0; goto End; @@ -236,7 +236,7 @@ int get_dx_ver(void) dx_version = 0x200; /* see if we can create the DirectInput object */ - dinput_hinst = LoadLibrary("DINPUT.DLL"); + dinput_hinst = LoadLibrary(L"DINPUT.DLL"); if (!dinput_hinst) { /* no DInput... must be DX2 */ goto End; diff --git a/src/allegro/src/win/wsystem.c b/src/allegro/src/win/wsystem.c index 7399d1e73..4d976e0bb 100644 --- a/src/allegro/src/win/wsystem.c +++ b/src/allegro/src/win/wsystem.c @@ -25,6 +25,7 @@ #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" +#include "utf8.h" #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile @@ -235,10 +236,10 @@ static void sys_directx_exit(void) */ static void sys_directx_get_executable_name(char *output, int size) { - char *temp = _AL_MALLOC_ATOMIC(size); + wchar_t* temp = _AL_MALLOC_ATOMIC(size); if (GetModuleFileName(allegro_inst, temp, size)) - do_uconvert(temp, U_ASCII, output, U_CURRENT, size); + do_uconvert((char*)temp, U_UNICODE, output, U_CURRENT, size); else usetc(output, 0); @@ -254,7 +255,7 @@ static void sys_directx_set_window_title(AL_CONST char *name) { HWND allegro_wnd = win_get_window(); - do_uconvert(name, U_CURRENT, wnd_title, U_ASCII, WND_TITLE_SIZE); + do_uconvert(name, U_CURRENT, (char*)wnd_title, U_UNICODE, WND_TITLE_SIZE); SetWindowText(allegro_wnd, wnd_title); } @@ -320,8 +321,8 @@ static void sys_directx_message(AL_CONST char *msg) msg += uwidth(msg); MessageBoxW(allegro_wnd, - (unsigned short *)uconvert(msg, U_CURRENT, tmp1, U_UNICODE, ALLEGRO_MESSAGE_SIZE), - (unsigned short *)uconvert(wnd_title, U_ASCII, tmp2, U_UNICODE, sizeof(tmp2)), + (wchar_t*)uconvert(msg, U_CURRENT, tmp1, U_UNICODE, ALLEGRO_MESSAGE_SIZE), + (wchar_t*)uconvert((char*)wnd_title, U_CURRENT, tmp2, U_UNICODE, sizeof(tmp2)), MB_OK); _AL_FREE(tmp1); @@ -334,7 +335,7 @@ static void sys_directx_message(AL_CONST char *msg) */ static void sys_directx_assert(AL_CONST char *msg) { - OutputDebugString(msg); /* thread safe */ + OutputDebugStringA(msg); /* thread safe */ DebugBreak(); } @@ -447,7 +448,7 @@ static void sys_directx_yield_timeslice(void) */ static int sys_directx_trace_handler(AL_CONST char *msg) { - OutputDebugString(msg); /* thread safe */ + OutputDebugStringA(msg); /* thread safe */ return 0; } @@ -458,25 +459,26 @@ static int sys_directx_trace_handler(AL_CONST char *msg) * which makes it look as if the application can still have a normal * main() function. */ -int _WinMain(void *_main, void *hInst, void *hPrev, char *Cmd, int nShow) +int _WinMain(void* _main, void* hInst, void* hPrev, char* Cmd, int nShow) { - int (*mainfunc) (int argc, char *argv[]) = (int (*)(int, char *[]))_main; - char *argbuf; - char *cmdline; - char **argv; + int (*mainfunc)(int argc, char *argv[]) = (int (*)(int, char *[]))_main; + wchar_t* argbuf; + wchar_t* cmdline; + wchar_t* arg_w; + char** argv; int argc; int argc_max; - int i, q; + int i, j, q; /* can't use parameter because it doesn't include the executable name */ cmdline = GetCommandLine(); - i = strlen(cmdline) + 1; + i = sizeof(wchar_t) * (wcslen(cmdline) + 1); argbuf = _AL_MALLOC(i); memcpy(argbuf, cmdline, i); argc = 0; argc_max = 64; - argv = _AL_MALLOC(sizeof(char *) * argc_max); + argv = _AL_MALLOC(sizeof(char*) * argc_max); if (!argv) { _AL_FREE(argbuf); return 1; @@ -486,11 +488,11 @@ int _WinMain(void *_main, void *hInst, void *hPrev, char *Cmd, int nShow) /* parse commandline into argc/argv format */ while (argbuf[i]) { - while ((argbuf[i]) && (uisspace(argbuf[i]))) + while ((argbuf[i]) && (iswspace(argbuf[i]))) i++; if (argbuf[i]) { - if ((argbuf[i] == '\'') || (argbuf[i] == '"')) { + if ((argbuf[i] == L'\'') || (argbuf[i] == L'"')) { q = argbuf[i++]; if (!argbuf[i]) break; @@ -498,7 +500,8 @@ int _WinMain(void *_main, void *hInst, void *hPrev, char *Cmd, int nShow) else q = 0; - argv[argc++] = &argbuf[i]; + arg_w = argbuf+i; + ++argc; if (argc >= argc_max) { argc_max += 64; @@ -509,23 +512,28 @@ int _WinMain(void *_main, void *hInst, void *hPrev, char *Cmd, int nShow) } } - while ((argbuf[i]) && ((q) ? (argbuf[i] != q) : (!uisspace(argbuf[i])))) + while ((argbuf[i]) && ((q) ? (argbuf[i] != q) : (!iswspace(argbuf[i])))) i++; if (argbuf[i]) { argbuf[i] = 0; i++; } + + argv[argc-1] = convert_widechar_to_utf8(arg_w); } } argv[argc] = NULL; + _AL_FREE(argbuf); + /* call the application entry point */ i = mainfunc(argc, argv); + for (j=0; jdoc()); - TiXmlHandle handle(&doc); + XmlDocumentRef doc(GuiXml::instance()->doc()); + TiXmlHandle handle(doc); const char* path = GuiXml::instance()->filename(); /**************************************************/ @@ -304,7 +304,7 @@ Widget* AppMenus::convertXmlelemToMenuitem(TiXmlElement* elem) { // is it a ? if (strcmp(elem->Value(), "separator") == 0) - return new Separator(NULL, JI_HORIZONTAL); + return new Separator("", JI_HORIZONTAL); const char* command_name = elem->Attribute("command"); Command* command = @@ -361,7 +361,7 @@ Widget* AppMenus::createInvalidVersionMenuitem() subMenu->addChild(new AppMenuItem(PACKAGE " is using a customized gui.xml (maybe from your HOME directory).", NULL, NULL)); subMenu->addChild(new AppMenuItem("You should update your customized gui.xml file to the new version to get", NULL, NULL)); subMenu->addChild(new AppMenuItem("the latest commands available.", NULL, NULL)); - subMenu->addChild(new Separator(NULL, JI_HORIZONTAL)); + subMenu->addChild(new Separator("", JI_HORIZONTAL)); subMenu->addChild(new AppMenuItem("You can bypass this validation adding the correct version", NULL, NULL)); subMenu->addChild(new AppMenuItem("number in element.", NULL, NULL)); menuitem->setSubmenu(subMenu); diff --git a/src/app/commands/cmd_about.cpp b/src/app/commands/cmd_about.cpp index 8c77eea94..6a9d16ae5 100644 --- a/src/app/commands/cmd_about.cpp +++ b/src/app/commands/cmd_about.cpp @@ -53,7 +53,7 @@ void AboutCommand::onExecute(Context* context) Label* title = new Label(PACKAGE " v" VERSION); Label* subtitle = new Label("Animated sprite editor && pixel art tool"); Separator* authors_separator1 = new Separator("Authors:", JI_HORIZONTAL | JI_TOP); - Separator* authors_separator2 = new Separator(NULL, JI_HORIZONTAL); + Separator* authors_separator2 = new Separator("", JI_HORIZONTAL); Label* author1 = new LinkLabel("http://dacap.com.ar/", "David Capello"); Label* author1_desc = new Label("| Programming"); Label* author2 = new LinkLabel("http://ilkke.blogspot.com/", "Ilija Melentijevic"); diff --git a/src/app/commands/cmd_configure_tools.cpp b/src/app/commands/cmd_configure_tools.cpp index 381db808f..fa31b0acd 100644 --- a/src/app/commands/cmd_configure_tools.cpp +++ b/src/app/commands/cmd_configure_tools.cpp @@ -40,8 +40,6 @@ #include "raster/mask.h" #include "ui/ui.h" -#include - namespace app { using namespace gfx; diff --git a/src/app/commands/cmd_developer_console.cpp b/src/app/commands/cmd_developer_console.cpp index 1c6a3adfa..64e399703 100644 --- a/src/app/commands/cmd_developer_console.cpp +++ b/src/app/commands/cmd_developer_console.cpp @@ -53,7 +53,7 @@ public: for (Documents::const_iterator it = context->getDocuments().begin(), end = context->getDocuments().end(); it != end; ++it) { - m_docs.addItem((*it)->getFilename()); + m_docs.addItem((*it)->getFilename().c_str()); } m_docs.addItem("---------"); } diff --git a/src/app/commands/cmd_duplicate_sprite.cpp b/src/app/commands/cmd_duplicate_sprite.cpp index 58d127bd7..701d9fec3 100644 --- a/src/app/commands/cmd_duplicate_sprite.cpp +++ b/src/app/commands/cmd_duplicate_sprite.cpp @@ -28,10 +28,10 @@ #include "app/load_widget.h" #include "app/modules/editors.h" #include "app/ui_context.h" +#include "base/path.h" #include "raster/sprite.h" #include "ui/ui.h" -#include #include namespace app { @@ -65,7 +65,6 @@ void DuplicateSpriteCommand::onExecute(Context* context) Widget* src_name, *dst_name, *flatten; const ContextReader reader(context); const Document* document = reader.document(); - char buf[1024]; /* load the window widget */ base::UniquePtr window(app::load_widget("duplicate_sprite.xml", "duplicate_sprite")); @@ -74,10 +73,9 @@ void DuplicateSpriteCommand::onExecute(Context* context) dst_name = window->findChild("dst_name"); flatten = window->findChild("flatten"); - src_name->setText(get_filename(document->getFilename())); - - std::sprintf(buf, "%s Copy", document->getFilename()); - dst_name->setText(buf); + base::string fn = document->getFilename(); + src_name->setText(base::get_file_name(fn)); + dst_name->setText(base::get_file_title(fn) + " Copy." + base::get_file_extension(fn)); if (get_config_bool("DuplicateSprite", "Flatten", false)) flatten->setSelected(true); @@ -95,7 +93,7 @@ void DuplicateSpriteCommand::onExecute(Context* context) else docCopy = document->duplicate(DuplicateExactCopy); - docCopy->setFilename(dst_name->getText()); + docCopy->setFilename(dst_name->getText().c_str()); context->addDocument(docCopy); } diff --git a/src/app/commands/cmd_frame_properties.cpp b/src/app/commands/cmd_frame_properties.cpp index 22417ff74..19aa866aa 100644 --- a/src/app/commands/cmd_frame_properties.cpp +++ b/src/app/commands/cmd_frame_properties.cpp @@ -119,7 +119,7 @@ void FramePropertiesCommand::onExecute(Context* context) window->openWindowInForeground(); if (window->getKiller() == ok) { - int num = strtol(frlen->getText(), NULL, 10); + int num = frlen->getTextInt(); if (m_target == ALL_FRAMES) { if (Alert::show("Warning" diff --git a/src/app/commands/cmd_goto_frame.cpp b/src/app/commands/cmd_goto_frame.cpp index 6d7e73429..4a7edb6f0 100644 --- a/src/app/commands/cmd_goto_frame.cpp +++ b/src/app/commands/cmd_goto_frame.cpp @@ -158,7 +158,7 @@ protected: if (window->getKiller() != ok) return editor->getFrame(); - m_frame = strtol(frame->getText(), NULL, 10); + m_frame = frame->getTextInt(); } return MID(FrameNumber(0), FrameNumber(m_frame-1), editor->getSprite()->getLastFrame()); diff --git a/src/app/commands/cmd_launch.cpp b/src/app/commands/cmd_launch.cpp index 2c72a794b..2832f6fb6 100644 --- a/src/app/commands/cmd_launch.cpp +++ b/src/app/commands/cmd_launch.cpp @@ -25,8 +25,7 @@ #include "app/launcher.h" #include "app/resource_finder.h" #include "base/compiler_specific.h" - -#include +#include "base/fs.h" namespace app { @@ -80,7 +79,7 @@ void LaunchCommand::onExecute(Context* context) rf.findInDocsDir(m_path.c_str()); while (const char* path = rf.next()) { - if (!exists(path)) + if (!base::file_exists(path)) continue; launcher::open_file(path); diff --git a/src/app/commands/cmd_open_file.cpp b/src/app/commands/cmd_open_file.cpp index 37d365152..64948d9b8 100644 --- a/src/app/commands/cmd_open_file.cpp +++ b/src/app/commands/cmd_open_file.cpp @@ -39,8 +39,7 @@ #include "raster/sprite.h" #include "ui/ui.h" -#include -#include +#include static const int kMonitoringPeriod = 100; @@ -62,7 +61,7 @@ private: class OpenFileJob : public Job, public IFileOpProgress { public: - OpenFileJob(FileOp* fop, const char* filename) + OpenFileJob(FileOp* fop) : Job("Loading file") , m_fop(fop) { @@ -132,7 +131,7 @@ void OpenFileCommand::onExecute(Context* context) unrecent = true; } else { - OpenFileJob task(fop, get_filename(m_filename.c_str())); + OpenFileJob task(fop); task.showProgressWindow(); // Post-load processing, it is called from the GUI because may require user intervention. diff --git a/src/app/commands/cmd_options.cpp b/src/app/commands/cmd_options.cpp index 980ddb34e..1fa8fd713 100644 --- a/src/app/commands/cmd_options.cpp +++ b/src/app/commands/cmd_options.cpp @@ -36,8 +36,6 @@ #include "raster/image.h" #include "ui/ui.h" -#include - namespace app { using namespace ui; diff --git a/src/app/commands/cmd_palette_editor.cpp b/src/app/commands/cmd_palette_editor.cpp index ed7f59f84..b133cc755 100644 --- a/src/app/commands/cmd_palette_editor.cpp +++ b/src/app/commands/cmd_palette_editor.cpp @@ -48,6 +48,8 @@ #include "app/undoers/set_palette_colors.h" #include "base/bind.h" #include "base/compiler_specific.h" +#include "base/fs.h" +#include "base/path.h" #include "gfx/hsv.h" #include "gfx/rgb.h" #include "gfx/size.h" @@ -59,9 +61,8 @@ #include "ui/graphics.h" #include "ui/ui.h" -#include -#include -#include +#include +#include #include namespace app { @@ -599,9 +600,9 @@ void PaletteEntryEditor::onSavePaletteClick(Event& ev) again: filename = app::show_file_selector("Save Palette", "", "png,pcx,bmp,tga,col,gpl"); if (!filename.empty()) { - if (exists(filename.c_str())) { + if (base::file_exists(filename)) { ret = Alert::show("Warning<showTip(1000, "Current memory: %.16g KB (%lu)\n" diff --git a/src/app/commands/cmd_save_file.cpp b/src/app/commands/cmd_save_file.cpp index 9e80960a7..4a64f5ff9 100644 --- a/src/app/commands/cmd_save_file.cpp +++ b/src/app/commands/cmd_save_file.cpp @@ -31,20 +31,20 @@ #include "app/recent_files.h" #include "app/ui/status_bar.h" #include "base/bind.h" +#include "base/fs.h" +#include "base/path.h" #include "base/thread.h" #include "base/unique_ptr.h" #include "raster/sprite.h" #include "ui/ui.h" -#include - static const int kMonitoringPeriod = 100; namespace app { class SaveFileJob : public Job, public IFileOpProgress { public: - SaveFileJob(FileOp* fop, const char* filename) + SaveFileJob(FileOp* fop) : Job("Saving file") , m_fop(fop) { @@ -81,7 +81,7 @@ static void save_document_in_background(Document* document, bool mark_as_saved) if (!fop) return; - SaveFileJob job(fop, get_filename(document->getFilename())); + SaveFileJob job(fop); job.showProgressWindow(); if (fop->has_error()) { @@ -89,13 +89,13 @@ static void save_document_in_background(Document* document, bool mark_as_saved) console.printf(fop->error.c_str()); } else { - App::instance()->getRecentFiles()->addRecentFile(document->getFilename()); + App::instance()->getRecentFiles()->addRecentFile(document->getFilename().c_str()); if (mark_as_saved) document->markAsSaved(); StatusBar::instance() ->setStatusText(2000, "File %s, saved.", - get_filename(document->getFilename())); + base::get_file_name(document->getFilename())); } } @@ -119,23 +119,22 @@ static void save_as_dialog(const ContextReader& reader, const char* dlg_title, b filename = newfilename; - /* does the file exist? */ - if (exists(filename.c_str())) { - /* ask if the user wants overwrite the file? */ + if (base::file_exists(filename.c_str())) { + // Ask if the user wants overwrite the existent file? ret = ui::Alert::show("Warning< per example: we back doing nothing */ + // "cancel" or per example: we back doing nothing else if (ret != 2) return; - /* "no": we must back to select other file-name */ + // "no": we must back to select other file-name } { diff --git a/src/app/commands/filters/cmd_convolution_matrix.cpp b/src/app/commands/filters/cmd_convolution_matrix.cpp index c018f9c1d..3d7169387 100644 --- a/src/app/commands/filters/cmd_convolution_matrix.cpp +++ b/src/app/commands/filters/cmd_convolution_matrix.cpp @@ -117,7 +117,7 @@ private: UI_FOREACH_WIDGET(m_stockListBox->getChildren(), it) { Widget* child = *it; - if (strcmp(child->getText(), oldSelected) == 0) { + if (child->getText() == oldSelected) { select_this = child; break; } @@ -135,7 +135,7 @@ private: void onMatrixChange() { ListItem* selected = m_stockListBox->getSelectedChild(); - SharedPtr matrix = m_stock.getByName(selected->getText()); + SharedPtr matrix = m_stock.getByName(selected->getText().c_str()); Target newTarget = matrix->getDefaultTarget(); m_filter.setMatrix(matrix); diff --git a/src/app/commands/filters/convolution_matrix_stock.cpp b/src/app/commands/filters/convolution_matrix_stock.cpp index 4ffa588c6..553e5baa8 100644 --- a/src/app/commands/filters/convolution_matrix_stock.cpp +++ b/src/app/commands/filters/convolution_matrix_stock.cpp @@ -24,10 +24,10 @@ #include "app/commands/filters/convolution_matrix_stock.h" -#include "base/unique_ptr.h" -#include "filters/convolution_matrix.h" #include "app/resource_finder.h" #include "app/util/filetoks.h" +#include "base/file_handle.h" +#include "filters/convolution_matrix.h" namespace app { @@ -50,13 +50,6 @@ SharedPtr ConvolutionMatrixStock::getByName(const char* name) return SharedPtr(0); } -namespace { - class FileDestroyer { - public: - static void destroy(FILE* ptr) { fclose(ptr); } - }; -} - void ConvolutionMatrixStock::reloadStock() { #define READ_TOK() { \ @@ -75,7 +68,6 @@ void ConvolutionMatrixStock::reloadStock() char *s, buf[256], leavings[4096]; int i, c, x, y, w, h, div, bias; SharedPtr matrix; - base::UniquePtr f; std::string name; cleanStock(); @@ -86,7 +78,7 @@ void ConvolutionMatrixStock::reloadStock() while (const char* path = rf.next()) { // Open matrices stock file - f.reset(fopen(path, "r"), fclose); + base::FileHandle f = base::open_file(path, "r"); if (!f) continue; diff --git a/src/app/commands/filters/filter_target_buttons.cpp b/src/app/commands/filters/filter_target_buttons.cpp index db98ddaf1..40b7e800f 100644 --- a/src/app/commands/filters/filter_target_buttons.cpp +++ b/src/app/commands/filters/filter_target_buttons.cpp @@ -22,9 +22,6 @@ #include "app/commands/filters/filter_target_buttons.h" -#include -#include - #include "app/modules/gfx.h" #include "app/modules/gui.h" #include "app/ui/skin/skin_parts.h" @@ -35,6 +32,8 @@ #include "ui/theme.h" #include "ui/widget.h" +#include + namespace app { using namespace filters; @@ -100,7 +99,7 @@ FilterTargetButtons::FilterTargetButtons(int imgtype, bool withChannels) } // Create the button to select "image" target - images = new Button(NULL); + images = new Button(""); setup_bevels(images, withChannels ? 0: 2, withChannels ? 0: 2, 2, 2); diff --git a/src/app/console.cpp b/src/app/console.cpp index a9fdb3801..be848cd92 100644 --- a/src/app/console.cpp +++ b/src/app/console.cpp @@ -20,7 +20,6 @@ #include "config.h" #endif -#include #include #include @@ -58,7 +57,7 @@ Console::Console() Window* window = new Window(false, "Errors Console"); Grid* grid = new Grid(1, false); View* view = new View(); - TextBox* textbox = new TextBox(NULL, JI_WORDWRAP); + TextBox* textbox = new TextBox("", JI_WORDWRAP); Button* button = new Button("&Cancel"); if (!grid || !textbox || !button) @@ -109,19 +108,16 @@ Console::~Console() } } -void Console::printf(const char *format, ...) +void Console::printf(const char* format, ...) { - char buf[1024]; // TODO warning buffer overflow + char buf[4096]; // TODO warning buffer overflow va_list ap; va_start(ap, format); - uvsprintf(buf, format, ap); + vsprintf(buf, format, ap); va_end(ap); if (wid_console) { - const char* text; - char* final; - // Open the window if (!wid_console->isVisible()) { wid_console->openWindow(); @@ -140,19 +136,14 @@ void Console::printf(const char *format, ...) wid_console->invalidate(); } - text = wid_textbox->getText(); - if (!text) - final = base_strdup(buf); - else { - final = (char*)base_malloc(ustrlen(text) + ustrlen(buf) + 1); + const std::string& text = wid_textbox->getText(); - ustrcpy(final, empty_string); - ustrcat(final, text); - ustrcat(final, buf); - } + base::string final; + if (!text.empty()) + final += text; + final += buf; - wid_textbox->setText(final); - base_free(final); + wid_textbox->setText(final.c_str()); } else { fputs(buf, stdout); diff --git a/src/app/dialogs/aniedit.cpp b/src/app/dialogs/aniedit.cpp index 4519ffc20..1dad395d4 100644 --- a/src/app/dialogs/aniedit.cpp +++ b/src/app/dialogs/aniedit.cpp @@ -221,7 +221,7 @@ void switch_between_animation_and_sprite_editor(Context* context) // Create the window & the animation-editor { - base::UniquePtr window(new Window(true, NULL)); + base::UniquePtr window(new Window(true, "")); AnimationEditor anieditor(context); window->addChild(&anieditor); diff --git a/src/app/document.cpp b/src/app/document.cpp index 3dcf6e275..0b3bd8e28 100644 --- a/src/app/document.cpp +++ b/src/app/document.cpp @@ -189,12 +189,7 @@ void Document::notifyCelCopied(Layer* fromLayer, FrameNumber fromFrame, Layer* t notifyObservers(&DocumentObserver::onCelCopied, ev); } -const char* Document::getFilename() const -{ - return m_filename.c_str(); -} - -void Document::setFilename(const char* filename) + void Document::setFilename(const base::string& filename) { m_filename = filename; } diff --git a/src/app/document.h b/src/app/document.h index 2c50ba5c6..6b3c807e5 100644 --- a/src/app/document.h +++ b/src/app/document.h @@ -19,17 +19,16 @@ #ifndef APP_DOCUMENT_H_INCLUDED #define APP_DOCUMENT_H_INCLUDED -#include "base/disable_copying.h" -#include "base/shared_ptr.h" -#include "base/unique_ptr.h" #include "app/document_id.h" -#include "gfx/transformation.h" +#include "base/disable_copying.h" #include "base/observable.h" +#include "base/shared_ptr.h" +#include "base/string.h" +#include "base/unique_ptr.h" +#include "gfx/transformation.h" #include "raster/frame_number.h" #include "raster/pixel_format.h" -#include - namespace base { class mutex; } @@ -110,8 +109,8 @@ namespace app { ////////////////////////////////////////////////////////////////////// // File related properties - const char* getFilename() const; - void setFilename(const char* filename); + const base::string& getFilename() const { return m_filename; } + void setFilename(const base::string& filename); bool isModified() const; bool isAssociatedToFile() const; @@ -201,7 +200,7 @@ namespace app { base::UniquePtr m_undo; // Document's file name (from where it was loaded, where it is saved). - std::string m_filename; + base::string m_filename; // True if this sprite is associated to a file in the file-system. bool m_associated_to_file; diff --git a/src/app/drop_files.cpp b/src/app/drop_files.cpp index dfe62094b..34c509956 100644 --- a/src/app/drop_files.cpp +++ b/src/app/drop_files.cpp @@ -139,7 +139,7 @@ static LRESULT CALLBACK ase_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM if (length > 0) { TCHAR* lpstr = new TCHAR[length+1]; DragQueryFile(hdrop, index, lpstr, length+1); - dropped_files->push_back(lpstr); + dropped_files->push_back(base::to_utf8(lpstr)); delete[] lpstr; } } diff --git a/src/app/file/ase_format.cpp b/src/app/file/ase_format.cpp index 862de2a25..438be277c 100644 --- a/src/app/file/ase_format.cpp +++ b/src/app/file/ase_format.cpp @@ -23,10 +23,10 @@ #include "app/document.h" #include "app/file/file.h" #include "app/file/file_format.h" -#include "app/file/file_handle.h" #include "app/file/format_options.h" #include "base/cfile.h" #include "base/exception.h" +#include "base/file_handle.h" #include "raster/raster.h" #include "zlib.h" @@ -137,9 +137,7 @@ FileFormat* CreateAseFormat() bool AseFormat::onLoad(FileOp *fop) { - FileHandle f(fop->filename.c_str(), "rb"); - if (!f) - return false; + FileHandle f(open_file_with_exception(fop->filename, "rb")); ASE_Header header; if (!ase_file_read_header(f, &header)) { @@ -291,7 +289,7 @@ bool AseFormat::onSave(FileOp *fop) ASE_Header header; ASE_FrameHeader frame_header; - FileHandle f(fop->filename.c_str(), "wb"); + FileHandle f(open_file_with_exception(fop->filename, "wb")); /* prepare the header */ ase_file_prepare_header(f, &header, sprite); diff --git a/src/app/file/bmp_format.cpp b/src/app/file/bmp_format.cpp index 81af739de..f78c23682 100644 --- a/src/app/file/bmp_format.cpp +++ b/src/app/file/bmp_format.cpp @@ -24,9 +24,9 @@ #include "app/file/file.h" #include "app/file/file_format.h" -#include "app/file/file_handle.h" #include "app/file/format_options.h" #include "base/cfile.h" +#include "base/file_handle.h" #include "raster/raster.h" #include @@ -611,9 +611,7 @@ bool BmpFormat::onLoad(FileOp *fop) PixelFormat pixelFormat; int format; - FileHandle f(fop->filename.c_str(), "rb"); - if (!f) - return false; + FileHandle f(open_file_with_exception(fop->filename, "rb")); if (read_bmfileheader(f, &fileheader) != 0) return false; @@ -739,11 +737,7 @@ bool BmpFormat::onSave(FileOp *fop) bfSize = 54 + biSizeImage; /* header + image data */ } - FileHandle f(fop->filename.c_str(), "wb"); - if (!f) { - fop_error(fop, "Error creating file.\n"); - return false; - } + FileHandle f(open_file_with_exception(fop->filename, "wb")); /* file_header */ fputw(0x4D42, f); /* bfType ("BM") */ diff --git a/src/app/file/file.cpp b/src/app/file/file.cpp index 4b6b08abe..8e422f116 100644 --- a/src/app/file/file.cpp +++ b/src/app/file/file.cpp @@ -20,26 +20,29 @@ #include "config.h" #endif +#include "app/file/file.h" + #include "app/app.h" -#include "app/ui/status_bar.h" -#include "base/mutex.h" -#include "base/scoped_lock.h" -#include "base/shared_ptr.h" -#include "base/string.h" #include "app/console.h" #include "app/document.h" -#include "app/file/file.h" #include "app/file/file_format.h" #include "app/file/file_formats_manager.h" #include "app/file/format_options.h" #include "app/modules/gui.h" #include "app/modules/palettes.h" +#include "app/ui/status_bar.h" +#include "base/fs.h" +#include "base/mutex.h" +#include "base/path.h" +#include "base/scoped_lock.h" +#include "base/shared_ptr.h" +#include "base/string.h" #include "raster/quantization.h" #include "raster/raster.h" #include "ui/alert.h" #include -#include +#include namespace app { @@ -143,13 +146,13 @@ FileOp* fop_to_load_document(const char* filename, int flags) if (!fop) return NULL; - /* get the extension of the filename (in lower case) */ - std::string extension = base::string_to_lower(get_extension(filename)); + // Get the extension of the filename (in lower case) + base::string extension = base::string_to_lower(base::get_file_extension(filename)); PRINTF("Loading file \"%s\" (%s)\n", filename, extension.c_str()); - /* does file exist? */ - if (!file_exists(filename, FA_ALL, NULL)) { + // Does file exist? + if (!base::file_exists(filename)) { fop_error(fop, "File not found: \"%s\"\n", filename); goto done; } @@ -230,7 +233,6 @@ done:; FileOp* fop_to_save_document(Document* document) { - char extension[32], buf[2048]; FileOp *fop; bool fatal; @@ -238,25 +240,24 @@ FileOp* fop_to_save_document(Document* document) if (!fop) return NULL; - /* document to save */ + // Document to save fop->document = document; - /* get the extension of the filename (in lower case) */ - ustrcpy(extension, get_extension(fop->document->getFilename())); - ustrlwr(extension); + // Get the extension of the filename (in lower case) + base::string extension = base::string_to_lower(base::get_file_extension(fop->document->getFilename())); - PRINTF("Saving document \"%s\" (%s)\n", fop->document->getFilename(), extension); + PRINTF("Saving document \"%s\" (%s)\n", fop->document->getFilename(), extension.c_str()); /* get the format through the extension of the filename */ - fop->format = get_fileformat(extension); + fop->format = get_fileformat(extension.c_str()); if (!fop->format || !fop->format->support(FILE_SUPPORT_SAVE)) { fop_error(fop, "ASEPRITE can't save \"%s\" files\n", extension); return fop; } - /* warnings */ - ustrcpy(buf, empty_string); + // Warnings + base::string warnings; fatal = false; /* check image type support */ @@ -264,29 +265,32 @@ FileOp* fop_to_save_document(Document* document) case IMAGE_RGB: if (!(fop->format->support(FILE_SUPPORT_RGB))) { - usprintf(buf+ustrlen(buf), "<<- %s", "RGB format"); + warnings += "<<- RGB format"; fatal = true; } + if (!(fop->format->support(FILE_SUPPORT_RGBA)) && fop->document->getSprite()->needAlpha()) { - usprintf(buf+ustrlen(buf), "<<- %s", "Alpha channel"); + + warnings += "<<- Alpha channel"; } break; case IMAGE_GRAYSCALE: if (!(fop->format->support(FILE_SUPPORT_GRAY))) { - usprintf(buf+ustrlen(buf), "<<- Grayscale format"); + warnings += "<<- Grayscale format"; fatal = true; } if (!(fop->format->support(FILE_SUPPORT_GRAYA)) && fop->document->getSprite()->needAlpha()) { - usprintf(buf+ustrlen(buf), "<<- Alpha channel"); + + warnings += "<<- Alpha channel"; } break; case IMAGE_INDEXED: if (!(fop->format->support(FILE_SUPPORT_INDEXED))) { - usprintf(buf+ustrlen(buf), "<<- Indexed format"); + warnings += "<<- Indexed format"; fatal = true; } break; @@ -296,14 +300,14 @@ FileOp* fop_to_save_document(Document* document) if (fop->document->getSprite()->getTotalFrames() > 1) { if (!fop->format->support(FILE_SUPPORT_FRAMES) && !fop->format->support(FILE_SUPPORT_SEQUENCES)) { - usprintf(buf+ustrlen(buf), "<<- Frames"); + warnings += "<<- Frames"; } } // layers support if (fop->document->getSprite()->getFolder()->getLayersCount() > 1) { if (!(fop->format->support(FILE_SUPPORT_LAYERS))) { - usprintf(buf+ustrlen(buf), "<<- Layers"); + warnings += "<<- Layers"; } } @@ -311,25 +315,25 @@ FileOp* fop_to_save_document(Document* document) if (fop->document->getSprite()->getPalettes().size() > 1) { if (!fop->format->support(FILE_SUPPORT_PALETTES) && !fop->format->support(FILE_SUPPORT_SEQUENCES)) { - usprintf(buf+ustrlen(buf), "<<- Palette changes between frames"); + warnings += "<<- Palette changes between frames"; } } - /* show the confirmation alert */ - if (ugetc(buf)) { - /* interative */ + // Show the confirmation alert + if (!warnings.empty()) { + // Interative if (App::instance()->isGui()) { int ret; if (fatal) ret = ui::Alert::show("Error<format->name(), buf); + fop->format->name(), warnings.c_str()); else ret = ui::Alert::show("Warning<format->name(), buf); + fop->format->name(), warnings.c_str()); /* operation can't be done (by fatal error) or the user cancel the operation */ @@ -338,9 +342,9 @@ FileOp* fop_to_save_document(Document* document) return NULL; } } - /* no interactive & fatal error? */ + // No interactive & fatal error? else if (fatal) { - fop_error(fop, buf); + fop_error(fop, warnings.c_str()); return fop; } } @@ -355,10 +359,10 @@ FileOp* fop_to_save_document(Document* document) } // To save more frames else { - char buf[256], left[256], right[256]; + char left[256], right[256]; int width, start_from; - start_from = split_filename(fop->document->getFilename(), left, right, &width); + start_from = split_filename(fop->document->getFilename().c_str(), left, right, &width); if (start_from < 0) { start_from = 0; width = @@ -368,8 +372,9 @@ FileOp* fop_to_save_document(Document* document) } for (FrameNumber frame(0); framedocument->getSprite()->getTotalFrames(); ++frame) { - /* get the name for this frame */ - usprintf(buf, "%s%0*d%s", left, width, start_from+frame, right); + // Get the name for this frame + char buf[4096]; + sprintf(buf, "%s%0*d%s", left, width, start_from+frame, right); fop->seq.filename_list.push_back(buf); } } diff --git a/src/app/file/fli_format.cpp b/src/app/file/fli_format.cpp index 2d92f5d80..246f9b3ea 100644 --- a/src/app/file/fli_format.cpp +++ b/src/app/file/fli_format.cpp @@ -23,10 +23,10 @@ #include "app/document.h" #include "app/file/file.h" #include "app/file/file_format.h" -#include "app/file/file_handle.h" #include "app/file/fli/fli.h" #include "app/file/format_options.h" #include "app/modules/palettes.h" +#include "base/file_handle.h" #include "raster/raster.h" #include @@ -34,6 +34,8 @@ namespace app { +using namespace base; + static int get_time_precision(Sprite *sprite); class FliFormat : public FileFormat { @@ -79,7 +81,7 @@ bool FliFormat::onLoad(FileOp* fop) int index = 0; // Open the file to read in binary mode - FileHandle f(fop->filename.c_str(), "rb"); + FileHandle f(open_file_with_exception(fop->filename, "rb")); fli_read_header(f, &fli_header); fseek(f, 128, SEEK_SET); @@ -94,9 +96,9 @@ bool FliFormat::onLoad(FileOp* fop) h = fli_header.height; // Create the bitmaps - base::UniquePtr bmp(Image::create(IMAGE_INDEXED, w, h)); - base::UniquePtr old(Image::create(IMAGE_INDEXED, w, h)); - base::UniquePtr pal(new Palette(FrameNumber(0), 256)); + UniquePtr bmp(Image::create(IMAGE_INDEXED, w, h)); + UniquePtr old(Image::create(IMAGE_INDEXED, w, h)); + UniquePtr pal(new Palette(FrameNumber(0), 256)); // Create the image Sprite* sprite = new Sprite(IMAGE_INDEXED, w, h, 256); @@ -207,13 +209,13 @@ bool FliFormat::onSave(FileOp* fop) fli_header.oframe1 = fli_header.oframe2 = 0; /* open the file to write in binary mode */ - FileHandle f(fop->filename.c_str(), "wb"); + FileHandle f(open_file_with_exception(fop->filename, "wb")); fseek(f, 128, SEEK_SET); // Create the bitmaps - base::UniquePtr bmp(Image::create(IMAGE_INDEXED, sprite->getWidth(), sprite->getHeight())); - base::UniquePtr old(Image::create(IMAGE_INDEXED, sprite->getWidth(), sprite->getHeight())); + UniquePtr bmp(Image::create(IMAGE_INDEXED, sprite->getWidth(), sprite->getHeight())); + UniquePtr old(Image::create(IMAGE_INDEXED, sprite->getWidth(), sprite->getHeight())); // Write frame by frame for (FrameNumber frpos(0); diff --git a/src/app/file/ico_format.cpp b/src/app/file/ico_format.cpp index 41d92ad12..785303e6c 100644 --- a/src/app/file/ico_format.cpp +++ b/src/app/file/ico_format.cpp @@ -25,9 +25,9 @@ #include "app/document.h" #include "app/file/file.h" #include "app/file/file_format.h" -#include "app/file/file_handle.h" #include "app/file/format_options.h" #include "base/cfile.h" +#include "base/file_handle.h" #include "raster/raster.h" #include @@ -90,7 +90,7 @@ struct BITMAPINFOHEADER { bool IcoFormat::onLoad(FileOp* fop) { - FileHandle f(fop->filename.c_str(), "rb"); + FileHandle f(open_file_with_exception(fop->filename, "rb")); // Read the icon header ICONDIR header; @@ -242,7 +242,7 @@ bool IcoFormat::onSave(FileOp* fop) int c, x, y, b, m, v; FrameNumber n, num = sprite->getTotalFrames(); - FileHandle f(fop->filename.c_str(), "wb"); + FileHandle f(open_file_with_exception(fop->filename, "wb")); offset = 6 + num*16; // ICONDIR + ICONDIRENTRYs diff --git a/src/app/file/jpeg_format.cpp b/src/app/file/jpeg_format.cpp index 75ef431ce..28fd142bf 100644 --- a/src/app/file/jpeg_format.cpp +++ b/src/app/file/jpeg_format.cpp @@ -24,12 +24,12 @@ #include "app/console.h" #include "app/file/file.h" #include "app/file/file_format.h" -#include "app/file/file_handle.h" #include "app/file/format_options.h" #include "app/find_widget.h" #include "app/ini_file.h" #include "app/load_widget.h" #include "base/compiler_specific.h" +#include "base/file_handle.h" #include "base/memory.h" #include "raster/raster.h" #include "ui/ui.h" @@ -42,6 +42,8 @@ namespace app { +using namespace base; + class JpegFormat : public FileFormat { // Data for JPEG files class JpegOptions : public FormatOptions { @@ -110,9 +112,7 @@ bool JpegFormat::onLoad(FileOp* fop) JDIMENSION buffer_height; int c; - FileHandle file(fop->filename.c_str(), "rb"); - if (!file) - return false; + FileHandle file(open_file_with_exception(fop->filename, "rb")); // Initialize the JPEG decompression object with error handling. jerr.fop = fop; @@ -247,11 +247,7 @@ bool JpegFormat::onSave(FileOp* fop) int c; // Open the file for write in it. - FileHandle file(fop->filename.c_str(), "wb"); - if (!file) { - fop_error(fop, "Error creating file.\n"); - return false; - } + FileHandle file(open_file_with_exception(fop->filename, "wb")); // Allocate and initialize JPEG compression object. jerr.fop = fop; @@ -367,7 +363,7 @@ SharedPtr JpegFormat::onGetFormatOptions(FileOp* fop) return jpeg_options; // Load the window to ask to the user the JPEG options he wants. - base::UniquePtr window(app::load_widget("jpeg_options.xml", "jpeg_options")); + UniquePtr window(app::load_widget("jpeg_options.xml", "jpeg_options")); ui::Slider* slider_quality = app::find_widget(window, "quality"); ui::Widget* ok = app::find_widget(window, "ok"); @@ -385,7 +381,7 @@ SharedPtr JpegFormat::onGetFormatOptions(FileOp* fop) return jpeg_options; } - catch (base::Exception& e) { + catch (std::exception& e) { Console::showException(e); return SharedPtr(0); } diff --git a/src/app/file/pcx_format.cpp b/src/app/file/pcx_format.cpp index 75f798b46..674685c4b 100644 --- a/src/app/file/pcx_format.cpp +++ b/src/app/file/pcx_format.cpp @@ -24,9 +24,9 @@ #include "app/file/file.h" #include "app/file/file_format.h" -#include "app/file/file_handle.h" #include "app/file/format_options.h" #include "base/cfile.h" +#include "base/file_handle.h" #include "raster/raster.h" #include @@ -66,7 +66,7 @@ bool PcxFormat::onLoad(FileOp* fop) int x, y; char ch = 0; - FileHandle f(fop->filename.c_str(), "rb"); + FileHandle f(open_file_with_exception(fop->filename, "rb")); fgetc(f); /* skip manufacturer ID */ fgetc(f); /* skip version flag */ @@ -193,7 +193,7 @@ bool PcxFormat::onSave(FileOp* fop) char runchar; char ch = 0; - FileHandle f(fop->filename.c_str(), "wb"); + FileHandle f(open_file_with_exception(fop->filename, "wb")); if (image->getPixelFormat() == IMAGE_RGB) { depth = 24; diff --git a/src/app/file/png_format.cpp b/src/app/file/png_format.cpp index eae755b62..e7840835b 100644 --- a/src/app/file/png_format.cpp +++ b/src/app/file/png_format.cpp @@ -24,9 +24,9 @@ #include "app/document.h" #include "app/file/file.h" #include "app/file/file_format.h" -#include "app/file/file_handle.h" #include "app/file/format_options.h" #include "app/ini_file.h" +#include "base/file_handle.h" #include "raster/raster.h" #include @@ -36,6 +36,8 @@ namespace app { +using namespace base; + class PngFormat : public FileFormat { const char* onGetName() const { return "png"; } const char* onGetExtensions() const { return "png"; } @@ -78,7 +80,7 @@ bool PngFormat::onLoad(FileOp* fop) png_bytep row_pointer; PixelFormat pixelFormat; - FileHandle fp(fop->filename.c_str(), "rb"); + FileHandle fp(open_file_with_exception(fop->filename, "rb")); /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, @@ -337,7 +339,7 @@ bool PngFormat::onSave(FileOp* fop) int pass, number_passes; /* open the file */ - FileHandle fp(fop->filename.c_str(), "wb"); + FileHandle fp(open_file_with_exception(fop->filename, "wb")); /* Create and initialize the png_struct with the desired error handler * functions. If you want to use the default stderr and longjump method, diff --git a/src/app/file/tga_format.cpp b/src/app/file/tga_format.cpp index 4372c6d77..c90dd9109 100644 --- a/src/app/file/tga_format.cpp +++ b/src/app/file/tga_format.cpp @@ -25,9 +25,9 @@ #include "app/file/file.h" #include "app/file/file_format.h" -#include "app/file/file_handle.h" #include "app/file/format_options.h" #include "base/cfile.h" +#include "base/file_handle.h" #include "raster/raster.h" #include @@ -210,7 +210,7 @@ bool TgaFormat::onLoad(FileOp* fop) unsigned int c, i, x, y, yc; int compressed; - FileHandle f(fop->filename.c_str(), "rb"); + FileHandle f(open_file_with_exception(fop->filename, "rb")); id_length = fgetc(f); palette_type = fgetc(f); @@ -405,7 +405,7 @@ bool TgaFormat::onSave(FileOp* fop) int depth = (image->getPixelFormat() == IMAGE_RGB) ? 32 : 8; bool need_pal = (image->getPixelFormat() == IMAGE_INDEXED)? true: false; - FileHandle f(fop->filename.c_str(), "wb"); + FileHandle f(open_file_with_exception(fop->filename, "wb")); fputc(0, f); /* id length (no id saved) */ fputc((need_pal) ? 1 : 0, f); /* palette type */ diff --git a/src/app/file_system.cpp b/src/app/file_system.cpp index 85260ef90..5e511ad78 100644 --- a/src/app/file_system.cpp +++ b/src/app/file_system.cpp @@ -25,6 +25,11 @@ #include "config.h" #endif +#include "app/file_system.h" + +#include "base/path.h" +#include "base/string.h" + #include #include #include @@ -58,9 +63,6 @@ #include #endif -#include "app/file_system.h" -#include "base/path.h" - ////////////////////////////////////////////////////////////////////// #ifdef USE_PIDLS @@ -320,7 +322,6 @@ IFileItem* FileSystemModule::getFileItemFromPath(const base::string& path) #ifdef USE_PIDLS { ULONG cbEaten; - WCHAR wStr[MAX_PATH]; LPITEMIDLIST fullpidl = NULL; SFGAOF attrib = SFGAO_FOLDER; @@ -330,12 +331,10 @@ IFileItem* FileSystemModule::getFileItemFromPath(const base::string& path) return fileitem; } - MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, - path.c_str(), path.size()+1, wStr, MAX_PATH); - if (shl_idesktop->ParseDisplayName(NULL, NULL, - wStr, &cbEaten, - &fullpidl, - &attrib) != S_OK) { + if (shl_idesktop->ParseDisplayName + (NULL, NULL, + const_cast(base::from_utf8(path).c_str()), + &cbEaten, &fullpidl, &attrib) != S_OK) { //PRINTF("FS: > (null)\n"); return NULL; } @@ -708,7 +707,7 @@ int FileItem::compare(const FileItem& that) const static void update_by_pidl(FileItem* fileitem) { STRRET strret; - TCHAR pszName[MAX_PATH]; + WCHAR pszName[MAX_PATH]; IShellFolder *pFolder = NULL; if (fileitem == rootitem) @@ -729,13 +728,13 @@ static void update_by_pidl(FileItem* fileitem) SHGDN_NORMAL | SHGDN_FORPARSING, &strret) == S_OK) { StrRetToBuf(&strret, fileitem->pidl, pszName, MAX_PATH); - fileitem->filename = pszName; + fileitem->filename = base::to_utf8(pszName); } else if (shl_idesktop->GetDisplayNameOf(fileitem->fullpidl, SHGDN_NORMAL | SHGDN_FORPARSING, &strret) == S_OK) { StrRetToBuf(&strret, fileitem->fullpidl, pszName, MAX_PATH); - fileitem->filename = pszName; + fileitem->filename = base::to_utf8(pszName); } else fileitem->filename = "ERR"; @@ -749,14 +748,14 @@ static void update_by_pidl(FileItem* fileitem) SHGDN_INFOLDER, &strret) == S_OK) { StrRetToBuf(&strret, fileitem->pidl, pszName, MAX_PATH); - fileitem->displayname = pszName; + fileitem->displayname = base::to_utf8(pszName); } else if (fileitem->isFolder() && shl_idesktop->GetDisplayNameOf(fileitem->fullpidl, SHGDN_INFOLDER, &strret) == S_OK) { StrRetToBuf(&strret, fileitem->fullpidl, pszName, MAX_PATH); - fileitem->displayname = pszName; + fileitem->displayname = base::to_utf8(pszName); } else { fileitem->displayname = base::get_file_name(fileitem->filename); @@ -884,12 +883,10 @@ static base::string get_key_for_pidl(LPITEMIDLIST pidl) return key; #else STRRET strret; - TCHAR pszName[MAX_PATH]; - char key[4096]; + WCHAR pszName[MAX_PATH]; + WCHAR key[4096] = { 0 }; int len; - ustrcpy(key, empty_string); - // Go pidl by pidl from the fullpidl to the root (desktop) //PRINTF("FS: ***\n"); pidl = clone_pidl(pidl); @@ -901,20 +898,20 @@ static base::string get_key_for_pidl(LPITEMIDLIST pidl) //PRINTF("FS: + %s\n", pszName); - len = ustrlen(pszName); + len = wcslen(pszName); if (len > 0) { if (*key) { - if (pszName[len-1] != '\\') { - memmove(key+len+1, key, ustrlen(key)+1); - key[len] = '\\'; + if (pszName[len-1] != L'\\') { + memmove(key+len+1, key, sizeof(WCHAR)*(wcslen(key)+1)); + key[len] = L'\\'; } else - memmove(key+len, key, ustrlen(key)+1); + memmove(key+len, key, sizeof(WCHAR)*(wcslen(key)+1)); } else key[len] = 0; - memcpy(key, pszName, len); + memcpy(key, pszName, sizeof(WCHAR)*len); } } remove_last_pidl(pidl); @@ -922,7 +919,7 @@ static base::string get_key_for_pidl(LPITEMIDLIST pidl) free_pidl(pidl); //PRINTF("FS: =%s\n***\n", key); - return key; + return base::to_utf8(key); #endif } diff --git a/src/app/gui_xml.cpp b/src/app/gui_xml.cpp index e28f573c0..f8bbe86e7 100644 --- a/src/app/gui_xml.cpp +++ b/src/app/gui_xml.cpp @@ -23,6 +23,7 @@ #include "app/gui_xml.h" #include "app/resource_finder.h" +#include "app/xml_document.h" #include "app/xml_exception.h" #include "base/fs.h" @@ -54,9 +55,9 @@ GuiXml::GuiXml() PRINTF(" - \"%s\" found\n", path); - // Try to load the XML file - if (!m_doc.LoadFile(path)) - throw XmlException(&m_doc); + // Load the XML file. As we've already checked "path" existence, + // in a case of exception we should show the error and stop. + m_doc = app::open_xml(path); // Done, we load the file successfully. return; @@ -65,14 +66,9 @@ GuiXml::GuiXml() throw base::Exception("gui.xml was not found"); } -TiXmlDocument& GuiXml::doc() +base::string GuiXml::version() { - return m_doc; -} - -std::string GuiXml::version() -{ - TiXmlHandle handle(&m_doc); + TiXmlHandle handle(m_doc); TiXmlElement* xmlKey = handle.FirstChild("gui").ToElement(); if (xmlKey && xmlKey->Attribute("version")) { diff --git a/src/app/gui_xml.h b/src/app/gui_xml.h index 140c3ba8b..7491b00d6 100644 --- a/src/app/gui_xml.h +++ b/src/app/gui_xml.h @@ -19,8 +19,8 @@ #ifndef APP_GUI_XML_INCLUDED #define APP_GUI_XML_INCLUDED -#include -#include "tinyxml.h" +#include "app/xml_document.h" +#include "base/string.h" namespace app { @@ -33,19 +33,21 @@ namespace app { static GuiXml* instance(); // Returns the tinyxml document instance. - TiXmlDocument& doc(); + XmlDocumentRef doc() { + return m_doc; + } // Returns the name of the gui.xml file. const char* filename() { - return m_doc.Value(); + return m_doc->Value(); } - std::string version(); + base::string version(); private: GuiXml(); - TiXmlDocument m_doc; + XmlDocumentRef m_doc; }; } // namespace app diff --git a/src/app/ini_file.cpp b/src/app/ini_file.cpp index 86560b7b3..b68533660 100644 --- a/src/app/ini_file.cpp +++ b/src/app/ini_file.cpp @@ -23,6 +23,7 @@ #include "app/ini_file.h" #include "app/resource_finder.h" +#include "base/fs.h" #include "ui/rect.h" #include @@ -33,19 +34,19 @@ namespace app { using namespace gfx; -static char config_filename[512]; +static std::string config_filename; ConfigModule::ConfigModule() { ResourceFinder rf; rf.findConfigurationFile(); - config_filename[0] = 0; + config_filename.clear(); // Search the configuration file from first to last path while (const char* path = rf.next()) { - if (exists(path)) { - ustrcpy(config_filename, path); + if (base::file_exists(path)) { + config_filename = path; break; } } @@ -53,9 +54,9 @@ ConfigModule::ConfigModule() // If the file wasn't found, we will create configuration file // in the first path if (config_filename[0] == 0 && rf.first()) - ustrcpy(config_filename, rf.first()); + config_filename = rf.first(); - override_config_file(config_filename); + override_config_file(config_filename.c_str()); } ConfigModule::~ConfigModule() diff --git a/src/app/log.cpp b/src/app/log.cpp index 8c2593aba..0a292d282 100644 --- a/src/app/log.cpp +++ b/src/app/log.cpp @@ -47,7 +47,7 @@ namespace app { #ifdef NEED_LOG // log file info static std::string log_filename; -static FILE *log_fileptr = NULL; +static FILE* log_fileptr = NULL; #endif static LoggerModule* logger_instance = NULL; diff --git a/src/app/modules/gui.cpp b/src/app/modules/gui.cpp index 0a58a17ed..e3c413e22 100644 --- a/src/app/modules/gui.cpp +++ b/src/app/modules/gui.cpp @@ -653,7 +653,7 @@ bool Shortcut::is_pressed(Message* msg) if (accel) { return accel->check(msg->keyModifiers(), static_cast(msg)->scancode(), - static_cast(msg)->ascii()); + static_cast(msg)->unicodeChar()); } return false; } diff --git a/src/app/resource_finder.cpp b/src/app/resource_finder.cpp index c30f5c112..dcc3ca6fe 100644 --- a/src/app/resource_finder.cpp +++ b/src/app/resource_finder.cpp @@ -24,6 +24,8 @@ #include #include "app/resource_finder.h" +#include "base/fs.h" +#include "base/path.h" namespace app { @@ -48,24 +50,19 @@ const char* ResourceFinder::next() return m_paths[m_current++].c_str(); } -void ResourceFinder::addPath(std::string path) +void ResourceFinder::addPath(const std::string& path) { m_paths.push_back(path); } void ResourceFinder::findInBinDir(const char* filename) { - char buf[1024], path[1024]; - - get_executable_name(path, sizeof(path)); - replace_filename(buf, path, filename, sizeof(buf)); - - addPath(buf); + addPath(base::join_path(base::get_file_path(base::get_app_path()), filename)); } void ResourceFinder::findInDataDir(const char* filename) { - char buf[1024]; + char buf[4096]; #if defined ALLEGRO_UNIX || defined ALLEGRO_MACOSX @@ -104,7 +101,7 @@ void ResourceFinder::findInDataDir(const char* filename) void ResourceFinder::findInDocsDir(const char* filename) { - char buf[1024]; + char buf[4096]; #if defined ALLEGRO_UNIX || defined ALLEGRO_MACOSX @@ -140,8 +137,8 @@ void ResourceFinder::findInHomeDir(const char* filename) { #if defined ALLEGRO_UNIX || defined ALLEGRO_MACOSX - char *env = getenv("HOME"); - char buf[1024]; + char* env = getenv("HOME"); + char buf[4096]; if ((env) && (*env)) { // $HOME/filename diff --git a/src/app/resource_finder.h b/src/app/resource_finder.h index 131eaadbf..ee0c9fbb7 100644 --- a/src/app/resource_finder.h +++ b/src/app/resource_finder.h @@ -31,7 +31,7 @@ namespace app { const char* first(); const char* next(); - void addPath(std::string path); + void addPath(const std::string& path); void findInBinDir(const char* filename); void findInDataDir(const char* filename); diff --git a/src/app/tools/tool_box.cpp b/src/app/tools/tool_box.cpp index c596952cb..d3d34678b 100644 --- a/src/app/tools/tool_box.cpp +++ b/src/app/tools/tool_box.cpp @@ -156,8 +156,8 @@ void ToolBox::loadTools() { PRINTF("Loading ASEPRITE tools\n"); - TiXmlDocument& doc(GuiXml::instance()->doc()); - TiXmlHandle handle(&doc); + XmlDocumentRef doc(GuiXml::instance()->doc()); + TiXmlHandle handle(doc); // For each group TiXmlElement* xmlGroup = handle.FirstChild("gui").FirstChild("tools").FirstChild("group").ToElement(); diff --git a/src/app/ui/button_set.cpp b/src/app/ui/button_set.cpp index 9430474d4..7cc0721c1 100644 --- a/src/app/ui/button_set.cpp +++ b/src/app/ui/button_set.cpp @@ -43,7 +43,7 @@ class ButtonSet::Item : public RadioButton { public: Item(int index, int radioGroup, int b1, int b2, int b3, int b4) - : RadioButton(NULL, radioGroup, kButtonWidget) + : RadioButton("", radioGroup, kButtonWidget) , m_index(index) { setRadioGroup(radioGroup); diff --git a/src/app/ui/color_button.cpp b/src/app/ui/color_button.cpp index 9dc667bcf..29e42b67e 100644 --- a/src/app/ui/color_button.cpp +++ b/src/app/ui/color_button.cpp @@ -217,7 +217,7 @@ void ColorButton::onPaint(PaintEvent& ev) // TODO use "ev.getGraphics()" if (color.isValid()) textcolor = color_utils::blackandwhite_neg(ui::rgba(color.getRed(), color.getGreen(), color.getBlue())); - jdraw_text(ji_screen, getFont(), getText(), text.x1, text.y1, + jdraw_text(ji_screen, getFont(), getText().c_str(), text.x1, text.y1, textcolor, ColorNone, false, jguiscale()); } diff --git a/src/app/ui/context_bar.cpp b/src/app/ui/context_bar.cpp index 232ad812a..a94f0a0ab 100644 --- a/src/app/ui/context_bar.cpp +++ b/src/app/ui/context_bar.cpp @@ -139,7 +139,7 @@ private: Rect rc = getBounds(); rc.y += rc.h; rc.w *= 3; - m_popupWindow = new PopupWindow(NULL, false); + m_popupWindow = new PopupWindow("", false); m_popupWindow->setAutoRemap(false); m_popupWindow->setBounds(rc); diff --git a/src/app/ui/file_list.cpp b/src/app/ui/file_list.cpp index 4819d2fbe..3b078747f 100644 --- a/src/app/ui/file_list.cpp +++ b/src/app/ui/file_list.cpp @@ -293,7 +293,7 @@ bool FileList::onProcessMessage(Message* msg) if (hasFocus()) { KeyMessage* keyMsg = static_cast(msg); KeyScancode scancode = keyMsg->scancode(); - int ascii = keyMsg->ascii(); + int unicodeChar = keyMsg->unicodeChar(); int select = getSelectedIndex(); View* view = View::getView(this); int bottom = m_list.size(); @@ -358,15 +358,15 @@ bool FileList::onProcessMessage(Message* msg) goUp(); return true; default: - if (ascii == ' ' || - (utolower(ascii) >= 'a' && - utolower(ascii) <= 'z') || - (utolower(ascii) >= '0' && - utolower(ascii) <= '9')) { + if (unicodeChar == ' ' || + (utolower(unicodeChar) >= 'a' && + utolower(unicodeChar) <= 'z') || + (utolower(unicodeChar) >= '0' && + utolower(unicodeChar) <= '9')) { if (ji_clock - m_isearchClock > ISEARCH_KEYPRESS_INTERVAL_MSECS) m_isearch.clear(); - m_isearch.push_back(ascii); + m_isearch.push_back(unicodeChar); int i, chrs = m_isearch.size(); FileItemList::iterator diff --git a/src/app/ui/file_selector.cpp b/src/app/ui/file_selector.cpp index 66f079d3d..cc6f2ffbd 100644 --- a/src/app/ui/file_selector.cpp +++ b/src/app/ui/file_selector.cpp @@ -115,7 +115,7 @@ public: protected: virtual bool onProcessMessage(Message* msg) OVERRIDE { if (msg->type() == kKeyUpMessage && - static_cast(msg)->ascii() >= 32) { + static_cast(msg)->unicodeChar() >= 32) { // Check if all keys are released for (int c=0; cgetText(); - char *p = get_extension(filename); - char buf[MAX_PATH]; + base::string ext = base::get_file_extension(m_fileName->getText()); - if (p && *p != 0) { - ustrcpy(buf, get_extension(filename)); - ustrlwr(buf); - m_fileType->setSelectedItemIndex(m_fileType->findItemIndex(buf)); + if (!ext.empty()) { + ext = base::string_to_lower(ext); + m_fileType->setSelectedItemIndex(m_fileType->findItemIndex(ext.c_str())); } } diff --git a/src/app/ui/main_window.cpp b/src/app/ui/main_window.cpp index ddfaf82fa..cdd436e69 100644 --- a/src/app/ui/main_window.cpp +++ b/src/app/ui/main_window.cpp @@ -48,7 +48,7 @@ namespace app { using namespace ui; MainWindow::MainWindow() - : Window(true, NULL) + : Window(true, "") , m_lastSplitterPos(0.0) , m_advancedMode(false) { @@ -206,7 +206,8 @@ void MainWindow::mouseOverTab(Tabs* tabs, TabView* tabView) if (tabView) { DocumentView* docView = static_cast(tabView); Document* document = docView->getDocument(); - m_statusBar->setStatusText(250, "%s", static_cast(document->getFilename())); + m_statusBar->setStatusText(250, "%s", + document->getFilename().c_str()); } else { m_statusBar->clearText(); diff --git a/src/app/ui/popup_window_pin.cpp b/src/app/ui/popup_window_pin.cpp index 970317054..3daf7b52d 100644 --- a/src/app/ui/popup_window_pin.cpp +++ b/src/app/ui/popup_window_pin.cpp @@ -38,7 +38,7 @@ namespace app { using namespace app::skin; using namespace ui; -PopupWindowPin::PopupWindowPin(const char* text, bool close_on_buttonpressed) +PopupWindowPin::PopupWindowPin(const base::string& text, bool close_on_buttonpressed) : PopupWindow(text, close_on_buttonpressed) , m_pin("") { diff --git a/src/app/ui/popup_window_pin.h b/src/app/ui/popup_window_pin.h index 7c3f3cbfb..b187d8dfb 100644 --- a/src/app/ui/popup_window_pin.h +++ b/src/app/ui/popup_window_pin.h @@ -26,7 +26,7 @@ namespace app { class PopupWindowPin : public ui::PopupWindow { public: - PopupWindowPin(const char* text, bool close_on_buttonpressed); + PopupWindowPin(const base::string& text, bool close_on_buttonpressed); protected: virtual bool onProcessMessage(ui::Message* msg) OVERRIDE; diff --git a/src/app/ui/skin/skin_theme.cpp b/src/app/ui/skin/skin_theme.cpp index de725437a..851f31ce9 100644 --- a/src/app/ui/skin/skin_theme.cpp +++ b/src/app/ui/skin/skin_theme.cpp @@ -29,8 +29,10 @@ #include "app/ui/skin/skin_property.h" #include "app/ui/skin/skin_slider_property.h" #include "app/ui/skin/skin_theme.h" +#include "app/xml_document.h" #include "app/xml_exception.h" #include "base/bind.h" +#include "base/fs.h" #include "base/shared_ptr.h" #include "gfx/border.h" #include "gfx/point.h" @@ -377,7 +379,7 @@ void SkinTheme::reload_skin() rf.findInDataDir(sheet_filename.c_str()); while (const char* path = rf.next()) { - if (exists(path)) { + if (base::file_exists(path)) { int old_color_conv = _color_conv; set_color_conversion(COLORCONV_NONE); @@ -421,14 +423,11 @@ void SkinTheme::onRegenerate() rf.findInDataDir(xml_filename.c_str()); while (const char* path = rf.next()) { - if (!exists(path)) + if (!base::file_exists(path)) continue; - TiXmlDocument doc; - if (!doc.LoadFile(path)) - throw XmlException(&doc); - - TiXmlHandle handle(&doc); + XmlDocumentRef doc = open_xml(path); + TiXmlHandle handle(doc); // Load colors { @@ -1134,7 +1133,7 @@ void SkinTheme::paintListItem(ui::PaintEvent& ev) if (widget->hasText()) { // Text - jdraw_text(ji_screen, widget->getFont(), widget->getText(), x, y, + jdraw_text(ji_screen, widget->getFont(), widget->getText().c_str(), x, y, fg, bg, true, jguiscale()); // Background @@ -1495,7 +1494,7 @@ void SkinTheme::paintComboBoxEntry(ui::PaintEvent& ev) Entry* widget = static_cast(ev.getSource()); bool password = widget->isPassword(); int scroll, caret, state, selbeg, selend; - const char *text = widget->getText(); + const char *text = widget->getText().c_str(); int c, ch, x, y, w; int x1, y1, x2, y2; int caret_x; @@ -1816,7 +1815,7 @@ void SkinTheme::drawTextStringDeprecated(const char *t, ui::Color fg_color, ui:: int x, y, w, h; if (!t) { - t = widget->getText(); + t = widget->getText().c_str(); w = jwidget_get_text_length(widget); h = jwidget_get_text_height(widget); } @@ -1887,7 +1886,7 @@ void SkinTheme::drawTextString(Graphics* g, const char *t, ui::Color fg_color, u g->setFont(widget->getFont()); if (!t) - t = widget->getText(); + t = widget->getText().c_str(); textrc.setSize(g->measureString(t)); diff --git a/src/app/ui/status_bar.cpp b/src/app/ui/status_bar.cpp index e83e1ff28..96b62900f 100644 --- a/src/app/ui/status_bar.cpp +++ b/src/app/ui/status_bar.cpp @@ -127,9 +127,9 @@ public: scancode == kKeyEnterPad) { Command* cmd = CommandsModule::instance()->getCommandByName(CommandId::GotoFrame); Params params; - int frame = strtol(this->getText(), NULL, 10); + int frame = getTextInt(); if (frame > 0) { - params.set("frame", this->getText()); + params.set("frame", getText().c_str()); UIContext::instance()->executeCommand(cmd, ¶ms); } // Select the text again @@ -162,7 +162,7 @@ StatusBar::StatusBar() #define ICON_NEW(name, icon, action) \ { \ - BUTTON_NEW((name), NULL, (action)); \ + BUTTON_NEW((name), "", (action)); \ set_gfxicon_to_button((name), icon, icon##_SELECTED, icon##_DISABLED, JI_CENTER | JI_MIDDLE); \ } @@ -547,13 +547,13 @@ bool StatusBar::onProcessMessage(Message* msg) } // Status bar text - if (this->getTextSize() > 0) { - textout_ex(doublebuffer, this->getFont(), this->getText(), + if (getTextSize() > 0) { + textout_ex(doublebuffer, getFont(), getText().c_str(), x, - rc.y + rc.h/2 - text_height(this->getFont())/2, + rc.y + rc.h/2 - text_height(getFont())/2, to_system(text_color), -1); - x += ji_font_text_len(this->getFont(), this->getText()) + 4*jguiscale(); + x += ji_font_text_len(getFont(), getText().c_str()) + 4*jguiscale(); } // Draw progress bar diff --git a/src/app/ui/toolbar.cpp b/src/app/ui/toolbar.cpp index cddedc0fe..03031c43d 100644 --- a/src/app/ui/toolbar.cpp +++ b/src/app/ui/toolbar.cpp @@ -398,7 +398,7 @@ void ToolBar::openPopupWindow(int group_index, ToolGroup* tool_group) // In case this tool contains more than just one tool, show the popup window m_open_on_hot = true; - m_popupWindow = new PopupWindow(NULL, false); + m_popupWindow = new PopupWindow("", false); m_popupWindow->Close.connect(Bind(&ToolBar::onClosePopup, this)); ToolStrip* toolstrip = new ToolStrip(tool_group, this); diff --git a/src/app/widget_loader.cpp b/src/app/widget_loader.cpp index 4f90f53df..d35765fdf 100644 --- a/src/app/widget_loader.cpp +++ b/src/app/widget_loader.cpp @@ -24,11 +24,13 @@ #include "app/app.h" #include "app/modules/gui.h" +#include "app/xml_document.h" #include "app/resource_finder.h" #include "app/ui/color_button.h" #include "app/widget_not_found.h" #include "app/xml_exception.h" #include "base/bind.h" +#include "base/fs.h" #include "base/memory.h" #include "ui/ui.h" @@ -76,12 +78,12 @@ Widget* WidgetLoader::loadWidget(const char* fileName, const char* widgetId) rf.addPath(fileName); - buf = "app/ui/"; + buf = "widgets/"; buf += fileName; rf.findInDataDir(buf.c_str()); while (const char* path = rf.next()) { - if (exists(path)) { + if (base::file_exists(path)) { buf = path; found = true; break; @@ -91,24 +93,23 @@ Widget* WidgetLoader::loadWidget(const char* fileName, const char* widgetId) if (!found) throw WidgetNotFound(widgetId); - widget = loadWidgetFromXmlFile(buf.c_str(), widgetId); + widget = loadWidgetFromXmlFile(buf, widgetId); if (!widget) throw WidgetNotFound(widgetId); return widget; } -Widget* WidgetLoader::loadWidgetFromXmlFile(const char* xmlFilename, const char* widgetId) +Widget* WidgetLoader::loadWidgetFromXmlFile(const base::string& xmlFilename, + const base::string& widgetId) { Widget* widget = NULL; m_tooltipManager = NULL; - TiXmlDocument doc; - if (!doc.LoadFile(xmlFilename)) - throw XmlException(&doc); + XmlDocumentRef doc(open_xml(xmlFilename)); + TiXmlHandle handle(doc); // Search the requested widget. - TiXmlHandle handle(&doc); TiXmlElement* xmlElement = handle .FirstChild("gui") .FirstChildElement().ToElement(); @@ -116,7 +117,7 @@ Widget* WidgetLoader::loadWidgetFromXmlFile(const char* xmlFilename, const char* while (xmlElement) { const char* nodename = xmlElement->Attribute("id"); - if (nodename && ustrcmp(nodename, widgetId) == 0) { + if (nodename && nodename == widgetId) { widget = convertXmlElementToWidget(xmlElement, NULL); break; } @@ -129,7 +130,7 @@ Widget* WidgetLoader::loadWidgetFromXmlFile(const char* xmlFilename, const char* Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget* root) { - const char *elem_name = elem->Value(); + const std::string elem_name = elem->Value(); Widget* widget = NULL; Widget* child; @@ -142,7 +143,7 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget widget = it->second->createWidgetFromXml(elem); } // Boxes - else if (ustrcmp(elem_name, "box") == 0) { + else if (elem_name == "box") { bool horizontal = bool_attr_is_true(elem, "horizontal"); bool vertical = bool_attr_is_true(elem, "vertical"); bool homogeneous = bool_attr_is_true(elem, "homogeneous"); @@ -151,25 +152,25 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget vertical ? JI_VERTICAL: 0) | (homogeneous ? JI_HOMOGENEOUS: 0)); } - else if (ustrcmp(elem_name, "vbox") == 0) { + else if (elem_name == "vbox") { bool homogeneous = bool_attr_is_true(elem, "homogeneous"); widget = new VBox(); if (homogeneous) widget->setAlign(widget->getAlign() | JI_HOMOGENEOUS); } - else if (ustrcmp(elem_name, "hbox") == 0) { + else if (elem_name == "hbox") { bool homogeneous = bool_attr_is_true(elem, "homogeneous"); widget = new HBox(); if (homogeneous) widget->setAlign(widget->getAlign() | JI_HOMOGENEOUS); } - else if (ustrcmp(elem_name, "boxfiller") == 0) { + else if (elem_name == "boxfiller") { widget = new BoxFiller(); } // Button - else if (ustrcmp(elem_name, "button") == 0) { + else if (elem_name == "button") { const char *text = elem->Attribute("text"); widget = new Button(text ? TRANSLATE_ATTR(text): NULL); @@ -210,7 +211,7 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget } } // Check - else if (ustrcmp(elem_name, "check") == 0) { + else if (elem_name == "check") { const char *text = elem->Attribute("text"); const char *looklike = elem->Attribute("looklike"); @@ -236,11 +237,11 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget } } /* combobox */ - else if (ustrcmp(elem_name, "combobox") == 0) { + else if (elem_name == "combobox") { widget = new ComboBox(); } /* entry */ - else if (ustrcmp(elem_name, "entry") == 0) { + else if (elem_name == "entry") { const char* maxsize = elem->Attribute("maxsize"); const char* text = elem->Attribute("text"); const char* suffix = elem->Attribute("suffix"); @@ -261,7 +262,7 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget throw std::runtime_error(" element found without 'maxsize' attribute"); } /* grid */ - else if (ustrcmp(elem_name, "grid") == 0) { + else if (elem_name == "grid") { const char *columns = elem->Attribute("columns"); bool same_width_columns = bool_attr_is_true(elem, "same_width_columns"); @@ -271,7 +272,7 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget } } /* label */ - else if (ustrcmp(elem_name, "label") == 0) { + else if (elem_name == "label") { const char *text = elem->Attribute("text"); widget = new Label(text ? TRANSLATE_ATTR(text): NULL); @@ -288,17 +289,17 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget } } /* listbox */ - else if (ustrcmp(elem_name, "listbox") == 0) { + else if (elem_name == "listbox") { widget = new ListBox(); } /* listitem */ - else if (ustrcmp(elem_name, "listitem") == 0) { + else if (elem_name == "listitem") { const char *text = elem->Attribute("text"); widget = new ListItem(text ? TRANSLATE_ATTR(text): NULL); } /* splitter */ - else if (ustrcmp(elem_name, "splitter") == 0) { + else if (elem_name == "splitter") { bool horizontal = bool_attr_is_true(elem, "horizontal"); bool vertical = bool_attr_is_true(elem, "vertical"); const char* by = elem->Attribute("by"); @@ -317,7 +318,7 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget widget = splitter; } /* radio */ - else if (ustrcmp(elem_name, "radio") == 0) { + else if (elem_name == "radio") { const char* text = elem->Attribute("text"); const char* group = elem->Attribute("group"); const char *looklike = elem->Attribute("looklike"); @@ -345,7 +346,7 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget } } /* separator */ - else if (ustrcmp(elem_name, "separator") == 0) { + else if (elem_name == "separator") { const char *text = elem->Attribute("text"); bool center = bool_attr_is_true(elem, "center"); bool right = bool_attr_is_true(elem, "right"); @@ -354,7 +355,7 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget bool horizontal = bool_attr_is_true(elem, "horizontal"); bool vertical = bool_attr_is_true(elem, "vertical"); - widget = new Separator(text ? TRANSLATE_ATTR(text): NULL, + widget = new Separator(text ? TRANSLATE_ATTR(text): "", (horizontal ? JI_HORIZONTAL: 0) | (vertical ? JI_VERTICAL: 0) | (center ? JI_CENTER: @@ -363,7 +364,7 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget (bottom ? JI_BOTTOM: JI_TOP))); } /* slider */ - else if (ustrcmp(elem_name, "slider") == 0) { + else if (elem_name == "slider") { const char *min = elem->Attribute("min"); const char *max = elem->Attribute("max"); int min_value = min != NULL ? ustrtol(min, NULL, 10): 0; @@ -372,30 +373,30 @@ Widget* WidgetLoader::convertXmlElementToWidget(const TiXmlElement* elem, Widget widget = new Slider(min_value, max_value, min_value); } /* textbox */ - else if (ustrcmp(elem_name, "textbox") == 0) { + else if (elem_name == "textbox") { bool wordwrap = bool_attr_is_true(elem, "wordwrap"); widget = new TextBox(elem->GetText(), wordwrap ? JI_WORDWRAP: 0); } /* view */ - else if (ustrcmp(elem_name, "view") == 0) { + else if (elem_name == "view") { widget = new View(); } /* window */ - else if (ustrcmp(elem_name, "window") == 0) { + else if (elem_name == "window") { const char *text = elem->Attribute("text"); if (text) { bool desktop = bool_attr_is_true(elem, "desktop"); if (desktop) - widget = new Window(true, NULL); + widget = new Window(true, ""); else widget = new Window(false, TRANSLATE_ATTR(text)); } } /* colorpicker */ - else if (ustrcmp(elem_name, "colorpicker") == 0) { + else if (elem_name == "colorpicker") { widget = new ColorButton(Color::fromMask(), app_get_current_pixel_format()); } diff --git a/src/app/widget_loader.h b/src/app/widget_loader.h index 96340d869..ea4f32716 100644 --- a/src/app/widget_loader.h +++ b/src/app/widget_loader.h @@ -20,9 +20,9 @@ #define APP_WIDGET_LOADER_H_INCLUDED #include "app/widget_type_mismatch.h" +#include "base/string.h" #include -#include class TiXmlElement; @@ -69,10 +69,11 @@ namespace app { } private: - ui::Widget* loadWidgetFromXmlFile(const char* xmlFilename, const char* widgetId); + ui::Widget* loadWidgetFromXmlFile(const base::string& xmlFilename, + const base::string& widgetId); ui::Widget* convertXmlElementToWidget(const TiXmlElement* elem, ui::Widget* root); - typedef std::map TypeCreatorsMap; + typedef std::map TypeCreatorsMap; TypeCreatorsMap m_typeCreators; ui::TooltipManager* m_tooltipManager; diff --git a/src/app/widget_not_found.h b/src/app/widget_not_found.h index 4b4dd3774..351764ebd 100644 --- a/src/app/widget_not_found.h +++ b/src/app/widget_not_found.h @@ -26,9 +26,9 @@ namespace app { class WidgetNotFound : public std::runtime_error { public: - WidgetNotFound(const char* widgetId) - : std::runtime_error(std::string("A data file is corrupted.\nPlease reinstall the program\n\n" - "Details: Widget not found: ") + widgetId) { } + WidgetNotFound(const std::string& widgetId) + : std::runtime_error("A data file is corrupted.\nPlease reinstall the program\n\n" + "Details: Widget not found: " + widgetId) { } }; } // namespace app diff --git a/src/app/widget_type_mismatch.h b/src/app/widget_type_mismatch.h index cca19fcfa..0af544aee 100644 --- a/src/app/widget_type_mismatch.h +++ b/src/app/widget_type_mismatch.h @@ -26,8 +26,8 @@ namespace app { class WidgetTypeMismatch : public std::runtime_error { public: - WidgetTypeMismatch(const char* widgetId) - : std::runtime_error(std::string("Widget ") + widgetId + + WidgetTypeMismatch(const std::string& widgetId) + : std::runtime_error("Widget " + widgetId + " of the expected type.\nPlease reinstall the program.\n\n") { } }; diff --git a/src/app/xml_document.cpp b/src/app/xml_document.cpp new file mode 100644 index 000000000..a8ba28dbc --- /dev/null +++ b/src/app/xml_document.cpp @@ -0,0 +1,49 @@ +/* Aseprite + * Copyright (C) 2001-2013 David 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 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "app/xml_document.h" + +#include "app/xml_exception.h" +#include "base/file_handle.h" + +#include "tinyxml.h" + +namespace app { + +using namespace base; + +XmlDocumentRef open_xml(const string& filename) +{ + FileHandle file(open_file(filename, "rb")); + if (!file) + throw Exception("Error loading file: " + filename); + + // Try to load the XML file + XmlDocumentRef doc(new TiXmlDocument()); + doc->SetValue(filename.c_str()); + if (!doc->LoadFile(file)) + throw XmlException(doc); + + return doc; +} + +} // namespace app diff --git a/src/app/file/file_handle.h b/src/app/xml_document.h similarity index 62% rename from src/app/file/file_handle.h rename to src/app/xml_document.h index 1045154b7..514fd3b41 100644 --- a/src/app/file/file_handle.h +++ b/src/app/xml_document.h @@ -16,29 +16,21 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#ifndef APP_FILE_HANDLE_FORMAT_H_INCLUDED -#define APP_FILE_HANDLE_FORMAT_H_INCLUDED +#ifndef APP_XML_DOCUMENT_H_INCLUDED +#define APP_XML_DOCUMENT_H_INCLUDED #include "base/exception.h" -#include "base/unique_ptr.h" +#include "base/shared_ptr.h" +#include "base/string.h" -#include -#include +#include "tinyxml.h" -class FileHandle -{ -public: - FileHandle(const char* fileName, const char* mode) - : m_handle(std::fopen(fileName, mode), std::fclose) - { - if (!m_handle) - throw base::Exception(std::string("Cannot open ") + fileName); - } +namespace app { - operator std::FILE*() { return m_handle; } + typedef SharedPtr XmlDocumentRef; -private: - base::UniquePtr m_handle; -}; + XmlDocumentRef open_xml(const base::string& filename); + +} // namespace app #endif diff --git a/src/app/xml_exception.cpp b/src/app/xml_exception.cpp index ee393a4d9..59abcb8e0 100644 --- a/src/app/xml_exception.cpp +++ b/src/app/xml_exception.cpp @@ -28,7 +28,7 @@ namespace app { -XmlException::XmlException(TiXmlDocument* doc) throw() +XmlException::XmlException(const TiXmlDocument* doc) throw() { try { char buf[4096]; // TODO Overflow diff --git a/src/app/xml_exception.h b/src/app/xml_exception.h index eb439126a..b5da02659 100644 --- a/src/app/xml_exception.h +++ b/src/app/xml_exception.h @@ -27,7 +27,7 @@ namespace app { class XmlException : public base::Exception { public: - XmlException(TiXmlDocument* doc) throw(); + XmlException(const TiXmlDocument* doc) throw(); }; } // namespace app diff --git a/src/base/CMakeLists.txt b/src/base/CMakeLists.txt index 7f077c311..24f7268ed 100644 --- a/src/base/CMakeLists.txt +++ b/src/base/CMakeLists.txt @@ -21,6 +21,7 @@ add_library(base-lib convert_to.cpp errno_string.cpp exception.cpp + file_handle.cpp fs.cpp launcher.cpp mem_utils.cpp diff --git a/src/base/file_handle.cpp b/src/base/file_handle.cpp new file mode 100644 index 000000000..1de1450a6 --- /dev/null +++ b/src/base/file_handle.cpp @@ -0,0 +1,48 @@ +// Aseprite Base Library +// Copyright (c) 2001-2013 David Capello +// +// This source file is distributed under MIT license, +// please read LICENSE.txt for more information. + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "base/file_handle.h" + +#include "base/string.h" + +#include + +#ifdef WIN32 +#include +#endif + +using namespace std; + +namespace base { + +FILE* open_file_raw(const string& filename, const string& mode) +{ +#ifdef WIN32 + return _wfopen(from_utf8(filename).c_str(), + from_utf8(mode).c_str()); +#else + return fopen(filename.c_str(), mode); +#endif +} + +FileHandle open_file(const string& filename, const string& mode) +{ + return FileHandle(open_file_raw(filename, mode), fclose); +} + +FileHandle open_file_with_exception(const string& filename, const string& mode) +{ + FileHandle f(open_file_raw(filename, mode), fclose); + if (!f) + throw runtime_error("Cannot open " + filename); + return f; +} + +} diff --git a/src/base/file_handle.h b/src/base/file_handle.h new file mode 100644 index 000000000..5357584be --- /dev/null +++ b/src/base/file_handle.h @@ -0,0 +1,25 @@ +// Aseprite Base Library +// Copyright (c) 2001-2013 David Capello +// +// This source file is distributed under MIT license, +// please read LICENSE.txt for more information. + +#ifndef BASE_OPEN_FILE_H_INCLUDED +#define BASE_OPEN_FILE_H_INCLUDED + +#include "base/shared_ptr.h" +#include "base/string.h" + +#include + +namespace base { + + typedef SharedPtr FileHandle; + + FILE* open_file_raw(const string& filename, const string& mode); + FileHandle open_file(const string& filename, const string& mode); + FileHandle open_file_with_exception(const string& filename, const string& mode); + +} + +#endif diff --git a/src/base/fs.h b/src/base/fs.h index cf496a50d..2578be391 100644 --- a/src/base/fs.h +++ b/src/base/fs.h @@ -17,6 +17,7 @@ namespace base { void make_directory(const string& path); void remove_directory(const string& path); + string get_app_path(); string get_temp_path(); } diff --git a/src/base/fs_unix.h b/src/base/fs_unix.h index 61c5e3d6c..f8456a590 100644 --- a/src/base/fs_unix.h +++ b/src/base/fs_unix.h @@ -42,6 +42,11 @@ void remove_directory(const string& path) } } +string get_app_path() +{ + return getexecname(); +} + string get_temp_path() { char* tmpdir = getenv("TMPDIR"); diff --git a/src/base/fs_win32.h b/src/base/fs_win32.h index c0470fbbb..48ebc5774 100644 --- a/src/base/fs_win32.h +++ b/src/base/fs_win32.h @@ -7,11 +7,13 @@ #include #include +#include "base/string.h" + namespace base { bool file_exists(const string& path) { - DWORD attr = ::GetFileAttributes(path.c_str()); + DWORD attr = ::GetFileAttributes(from_utf8(path).c_str()); // GetFileAttributes returns INVALID_FILE_ATTRIBUTES in case of // fail. @@ -21,7 +23,7 @@ bool file_exists(const string& path) bool directory_exists(const string& path) { - DWORD attr = ::GetFileAttributes(path.c_str()); + DWORD attr = ::GetFileAttributes(from_utf8(path).c_str()); return ((attr != INVALID_FILE_ATTRIBUTES) && ((attr & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)); @@ -29,7 +31,7 @@ bool directory_exists(const string& path) void make_directory(const string& path) { - BOOL result = ::CreateDirectory(path.c_str(), NULL); + BOOL result = ::CreateDirectory(from_utf8(path).c_str(), NULL); if (result == 0) { // TODO add GetLastError() value into the exception throw std::runtime_error("Error creating directory"); @@ -38,18 +40,27 @@ void make_directory(const string& path) void remove_directory(const string& path) { - BOOL result = ::RemoveDirectory(path.c_str()); + BOOL result = ::RemoveDirectory(from_utf8(path).c_str()); if (result == 0) { // TODO add GetLastError() value into the exception throw std::runtime_error("Error removing directory"); } } +string get_app_path() +{ + TCHAR buffer[MAX_PATH+1]; + if (::GetModuleFileName(NULL, buffer, sizeof(buffer)/sizeof(TCHAR))) + return to_utf8(buffer); + else + return ""; +} + string get_temp_path() { TCHAR buffer[MAX_PATH+1]; DWORD result = GetTempPath(sizeof(buffer)/sizeof(TCHAR), buffer); - return string(buffer); + return to_utf8(buffer); } } diff --git a/src/base/launcher.cpp b/src/base/launcher.cpp index d642f27bc..321ff2c41 100644 --- a/src/base/launcher.cpp +++ b/src/base/launcher.cpp @@ -10,6 +10,7 @@ #include "base/launcher.h" #include "base/exception.h" +#include "base/string.h" #ifdef WIN32 #include @@ -17,7 +18,7 @@ #define SEE_MASK_DEFAULT 0x00000000 #endif -static int win32_shell_execute(const char* verb, const char* file, const char* params) +static int win32_shell_execute(const wchar_t* verb, const wchar_t* file, const wchar_t* params) { SHELLEXECUTEINFO sh; ZeroMemory((LPVOID)&sh, sizeof(sh)); @@ -70,7 +71,8 @@ bool open_file(const std::string& file) #ifdef WIN32 - ret = win32_shell_execute("open", file.c_str(), NULL); + ret = win32_shell_execute(L"open", + base::from_utf8(file).c_str(), NULL); #elif __APPLE__ @@ -88,7 +90,10 @@ bool open_file(const std::string& file) bool open_folder(const std::string& file) { #ifdef WIN32 - int ret = win32_shell_execute(NULL, "explorer", ("/e,/select,\"" + file + "\"").c_str()); + int ret = win32_shell_execute(NULL, + L"explorer", + (L"/e,/select,\"" + base::from_utf8(file) + L"\"").c_str()); + return (ret == 0); #else return false; diff --git a/src/base/memory_dump_win32.h b/src/base/memory_dump_win32.h index 9c87c6047..656e51831 100644 --- a/src/base/memory_dump_win32.h +++ b/src/base/memory_dump_win32.h @@ -12,13 +12,15 @@ #include #endif -static std::string memoryDumpFile; +#include "base/string.h" + +static std::wstring memoryDumpFile; class base::MemoryDump::MemoryDumpImpl { public: MemoryDumpImpl() { - memoryDumpFile = "memory.dmp"; + memoryDumpFile = L"memory.dmp"; ::SetUnhandledExceptionFilter(MemoryDumpImpl::unhandledException); } @@ -27,7 +29,7 @@ public: } void setFileName(const std::string& fileName) { - memoryDumpFile = fileName; + memoryDumpFile = base::from_utf8(fileName); } static LONG WINAPI unhandledException(_EXCEPTION_POINTERS* exceptionPointers) { diff --git a/src/base/shared_ptr.h b/src/base/shared_ptr.h index 240e51cd7..ad02de5d5 100644 --- a/src/base/shared_ptr.h +++ b/src/base/shared_ptr.h @@ -60,7 +60,8 @@ public: ~SharedPtrRefCounterImpl() { - m_deleter(m_ptr); + if (m_ptr) + m_deleter(m_ptr); } private: @@ -89,7 +90,8 @@ public: m_refCount = new SharedPtrRefCounterImpl >(ptr, DefaultSharedPtrDeleter()); } catch (...) { - DefaultSharedPtrDeleter()(ptr); + if (ptr) + DefaultSharedPtrDeleter()(ptr); throw; } m_ptr = ptr; @@ -104,7 +106,8 @@ public: m_refCount = new SharedPtrRefCounterImpl(ptr, deleter); } catch (...) { - deleter(ptr); + if (ptr) + deleter(ptr); throw; } m_ptr = ptr; @@ -146,7 +149,8 @@ public: m_refCount = new SharedPtrRefCounterImpl >(ptr, DefaultSharedPtrDeleter()); } catch (...) { - DefaultSharedPtrDeleter()(ptr); + if (ptr) + DefaultSharedPtrDeleter()(ptr); throw; } m_ptr = ptr; @@ -168,7 +172,8 @@ public: m_refCount = new SharedPtrRefCounterImpl(ptr, deleter); } catch (...) { - deleter(ptr); + if (ptr) + deleter(ptr); throw; } m_ptr = ptr; diff --git a/src/base/string.cpp b/src/base/string.cpp index 35ae68f01..21ec1a0e3 100644 --- a/src/base/string.cpp +++ b/src/base/string.cpp @@ -9,8 +9,13 @@ #endif #include "base/string.h" +#include #include +#ifdef WIN32 +#include +#endif + namespace base { string string_to_lower(const string& original) @@ -33,4 +38,59 @@ string string_to_upper(const string& original) return result; } +#ifdef WIN32 + +string to_utf8(const std::wstring& src) +{ + int required_size = + ::WideCharToMultiByte(CP_UTF8, 0, + src.c_str(), src.size(), + NULL, 0, NULL, NULL); + + if (required_size == 0) + return string(); + + std::vector buf(++required_size); + + ::WideCharToMultiByte(CP_UTF8, 0, + src.c_str(), src.size(), + &buf[0], required_size, + NULL, NULL); + + return base::string(&buf[0]); +} + +std::wstring from_utf8(const string& src) +{ + int required_size = + MultiByteToWideChar(CP_UTF8, 0, + src.c_str(), src.size(), + NULL, 0); + + if (required_size == 0) + return std::wstring(); + + std::vector buf(++required_size); + + ::MultiByteToWideChar(CP_UTF8, 0, + src.c_str(), src.size(), + &buf[0], required_size); + + return std::wstring(&buf[0]); +} + +#endif // WIN32 + +int utf8_length(const string& utf8string) +{ + utf8_const_iterator it(utf8string.begin()); + utf8_const_iterator end(utf8string.end()); + int c = 0; + + while (it != end) + ++it, ++c; + + return c; +} + } // namespace base diff --git a/src/base/string.h b/src/base/string.h index 51c8288e3..4e19fee97 100644 --- a/src/base/string.h +++ b/src/base/string.h @@ -8,6 +8,7 @@ #define BASE_STRING_H_INCLUDED #include +#include namespace base { @@ -16,6 +17,123 @@ namespace base { string string_to_lower(const string& original); string string_to_upper(const string& original); + string to_utf8(const std::wstring& widestring); + std::wstring from_utf8(const string& utf8string); + + int utf8_length(const string& utf8string); + + template + class utf8_iteratorT : public std::iterator { + public: + explicit utf8_iteratorT(const SubIterator& it) + : m_internal(it) { + } + + utf8_iteratorT& operator++() { + int c = *m_internal; + ++m_internal; + + if (c & 0x80) { + int n = 1; + while (c & (0x80>>n)) + n++; + + c &= (1<<(8-n))-1; + + while (--n > 0) { + int t = *m_internal; + ++m_internal; + + if ((!(t & 0x80)) || (t & 0x40)) { + --m_internal; + return *this; + } + + c = (c<<6) | (t & 0x3F); + } + } + + return *this; + } + + utf8_iteratorT& operator+=(int i) { + while (i--) + operator++(); + return *this; + } + + utf8_iteratorT operator+(int i) { + utf8_iteratorT it(*this); + it += i; + return it; + } + + const int operator*() const { + SubIterator it = m_internal; + int c = *it; + ++it; + + if (c & 0x80) { + int n = 1; + while (c & (0x80>>n)) + n++; + + c &= (1<<(8-n))-1; + + while (--n > 0) { + int t = *it; + ++it; + + if ((!(t & 0x80)) || (t & 0x40)) + return '^'; + + c = (c<<6) | (t & 0x3F); + } + } + + return c; + } + + bool operator==(const utf8_iteratorT& it) const { + return m_internal == it.m_internal; + } + + bool operator!=(const utf8_iteratorT& it) const { + return m_internal != it.m_internal; + } + + pointer operator->() { + return m_internal.operator->(); + } + + private: + SubIterator m_internal; + }; + + class utf8_iterator : public utf8_iteratorT { + public: + utf8_iterator(const utf8_iteratorT& it) + : utf8_iteratorT(it) { + } + explicit utf8_iterator(const string::iterator& it) + : utf8_iteratorT(it) { + } + }; + + class utf8_const_iterator : public utf8_iteratorT { + public: + utf8_const_iterator(const utf8_iteratorT& it) + : utf8_iteratorT(it) { + } + explicit utf8_const_iterator(const string::const_iterator& it) + : utf8_iteratorT(it) { + } + }; + } #endif diff --git a/src/base/string_unittest.cpp b/src/base/string_unittest.cpp new file mode 100644 index 000000000..606212eef --- /dev/null +++ b/src/base/string_unittest.cpp @@ -0,0 +1,59 @@ +// Aseprite Base Library +// Copyright (c) 2001-2013 David Capello +// +// This source file is distributed under MIT license, +// please read LICENSE.txt for more information. + +#include + +#include "base/string.h" + +#include + +using namespace base; + +bool all(int) { return true; } + +TEST(String, Utf8Iterator) +{ + string a = "Hello"; + int value = std::count_if(utf8_iterator(a.begin()), + utf8_iterator(a.end()), all); + ASSERT_EQ(5, value); + ASSERT_EQ('H', *(utf8_iterator(a.begin()))); + ASSERT_EQ('e', *(utf8_iterator(a.begin())+1)); + ASSERT_EQ('l', *(utf8_iterator(a.begin())+2)); + ASSERT_EQ('l', *(utf8_iterator(a.begin())+3)); + ASSERT_EQ('o', *(utf8_iterator(a.begin())+4)); + + string b = "Copyright \xC2\xA9"; + value = std::count_if(utf8_iterator(b.begin()), + utf8_iterator(b.end()), all); + ASSERT_EQ(11, value); + ASSERT_EQ('C', *(utf8_iterator(b.begin()))); + ASSERT_EQ('o', *(utf8_iterator(b.begin())+1)); + ASSERT_EQ(0xA9, *(utf8_iterator(b.begin())+10)); + ASSERT_TRUE((utf8_iterator(b.begin())+11) == utf8_iterator(b.end())); + + string c = "\xf0\x90\x8d\x86\xe6\x97\xa5\xd1\x88"; + value = std::count_if(utf8_iterator(c.begin()), + utf8_iterator(c.end()), all); + ASSERT_EQ(3, value); + ASSERT_EQ(0x10346, *(utf8_iterator(c.begin()))); + ASSERT_EQ(0x65E5, *(utf8_iterator(c.begin())+1)); + ASSERT_EQ(0x448, *(utf8_iterator(c.begin())+2)); + ASSERT_TRUE((utf8_iterator(c.begin())+3) == utf8_iterator(c.end())); + + string d = "\xf0\xa4\xad\xa2"; + value = std::count_if(utf8_iterator(d.begin()), + utf8_iterator(d.end()), all); + ASSERT_EQ(1, value); + ASSERT_EQ(0x24B62, *(utf8_iterator(d.begin()))); + ASSERT_TRUE((utf8_iterator(d.begin())+1) == utf8_iterator(d.end())); +} + +int main(int argc, char** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/src/main/main.cpp b/src/main/main.cpp index 063cc1e9f..81c314b10 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -84,7 +84,7 @@ int app_main(int argc, char* argv[]) std::srand(static_cast(std::time(NULL))); #ifdef WIN32 - CoInitialize(NULL); + ::CoInitialize(NULL); #endif try { @@ -105,6 +105,9 @@ int app_main(int argc, char* argv[]) } catch (std::exception& e) { std::cerr << e.what() << '\n'; +#ifdef WIN32 + ::MessageBoxA(NULL, e.what(), PACKAGE, MB_OK | MB_ICONERROR); +#endif return 1; } } diff --git a/src/she/she_alleg4.cpp b/src/she/she_alleg4.cpp index 579656aa1..06f3f50a5 100644 --- a/src/she/she_alleg4.cpp +++ b/src/she/she_alleg4.cpp @@ -11,6 +11,7 @@ #include "she.h" #include +#include #ifdef ALLEGRO_WINDOWS #include #endif @@ -272,7 +273,8 @@ class Alleg4System : public System { public: Alleg4System() { allegro_init(); - set_uformat(U_ASCII); + set_uformat(U_UTF8); + _al_detect_filename_encoding(); install_timer(); // Register PNG as a supported bitmap type diff --git a/src/ui/accelerator.cpp b/src/ui/accelerator.cpp index 0a8289f66..d9c5b7fa8 100644 --- a/src/ui/accelerator.cpp +++ b/src/ui/accelerator.cpp @@ -21,13 +21,13 @@ namespace ui { -void Accelerator::addKey(KeyModifiers modifiers, KeyScancode scancode, int ascii) +void Accelerator::addKey(KeyModifiers modifiers, KeyScancode scancode, int unicodeChar) { KeyCombo key; key.modifiers = modifiers; key.scancode = scancode; - key.ascii = ascii; + key.unicodeChar = unicodeChar; m_combos.push_back(key); } @@ -36,7 +36,7 @@ static void process_one_word(Accelerator* accel, char* word) { KeyModifiers modifiers = kKeyNoneModifier; KeyScancode scancode = kKeyNil; - int ascii = 0; + int unicodeChar = 0; char* tok; // Special case: plus sign @@ -65,10 +65,10 @@ static void process_one_word(Accelerator* accel, char* word) else if (tok[1] == 0) { if (((*tok >= 'a') && (*tok <= 'z')) || ((*tok >= 'A') && (*tok <= 'Z'))) { - ascii = tolower(*tok); + unicodeChar = tolower(*tok); } else { - ascii = *tok; + unicodeChar = *tok; } if (((*tok >= 'a') && (*tok <= 'z')) || @@ -171,7 +171,7 @@ static void process_one_word(Accelerator* accel, char* word) } } - accel->addKey(modifiers, scancode, ascii); + accel->addKey(modifiers, scancode, unicodeChar); } void Accelerator::addKeysFromString(const char* string) @@ -323,8 +323,8 @@ std::string Accelerator::KeyCombo::toString() ustrcat(buf, "Shift+"); // Key - if (this->ascii) - usprintf(buf+ustrlen(buf), "%c", toupper(this->ascii)); + if (this->unicodeChar) + usprintf(buf+ustrlen(buf), "%c", toupper(this->unicodeChar)); else if (this->scancode) ustrcat(buf, table[this->scancode]); else @@ -339,7 +339,7 @@ std::string Accelerator::toString() return m_combos.front().toString(); } -bool Accelerator::check(KeyModifiers modifiers, KeyScancode scancode, int ascii) +bool Accelerator::check(KeyModifiers modifiers, KeyScancode scancode, int unicodeChar) { #ifdef REPORT_KEYS char buf[256]; @@ -359,10 +359,10 @@ bool Accelerator::check(KeyModifiers modifiers, KeyScancode scancode, int ascii) (scancode >= kKeySpace && scancode <= kKeyDown) || (scancode >= kKeyEnterPad && scancode <= kKeyNoconvert) || (scancode == kKeyKanji)) { - ascii = 0; + unicodeChar = 0; } // For Ctrl+number - /* scancode ascii + /* scancode unicodeChar Ctrl+0 27 0 Ctrl+1 28 2 Ctrl+2 29 0 @@ -375,22 +375,22 @@ bool Accelerator::check(KeyModifiers modifiers, KeyScancode scancode, int ascii) Ctrl+9 36 2 */ else if ((scancode >= kKey0 && scancode <= kKey9) && - (ascii < 32 || ascii == 127)) { - ascii = '0' + scancode - kKey0; + (unicodeChar < 32 || unicodeChar == 127)) { + unicodeChar = '0' + scancode - kKey0; scancode = kKeyNil; } // For Ctrl+letter - else if (ascii >= 1 && ascii <= 'z'-'a'+1) { - ascii = 'a'+ascii-1; + else if (unicodeChar >= 1 && unicodeChar <= 'z'-'a'+1) { + unicodeChar = 'a'+unicodeChar-1; scancode = kKeyNil; } - // For any other legal ASCII code - else if (ascii >= ' ') { - ascii = tolower(ascii); + // For any other legal Unicode code + else if (unicodeChar >= ' ') { + unicodeChar = tolower(unicodeChar); /* without shift (because characters like '*' can be trigger with "Shift+8", so we don't want "Shift+*") */ - if (!(ascii >= 'a' && ascii <= 'z')) + if (!(unicodeChar >= 'a' && unicodeChar <= 'z')) modifiers = (KeyModifiers)((int)modifiers & ((int)~kKeyShiftModifier)); scancode = kKeyNil; @@ -400,7 +400,7 @@ bool Accelerator::check(KeyModifiers modifiers, KeyScancode scancode, int ascii) #ifdef REPORT_KEYS { base::UniquePtr a2(new Accelerator); - a2->addKey(modifiers, scancode, ascii); + a2->addKey(modifiers, scancode, unicodeChar); buf2 = a2->getString(); } #endif @@ -409,13 +409,13 @@ bool Accelerator::check(KeyModifiers modifiers, KeyScancode scancode, int ascii) it != end; ++it) { #ifdef REPORT_KEYS printf("%3d==%3d %3d==%3d %s==%s ", - it->scancode, scancode, it->ascii, ascii, + it->scancode, scancode, it->unicodeChar, unicodeChar, it->getString().c_str(), buf2.c_str(); #endif if ((it->modifiers == modifiers) && ((it->scancode != kKeyNil && it->scancode == scancode) || - (it->ascii && it->ascii == ascii))) { + (it->unicodeChar && it->unicodeChar == unicodeChar))) { #ifdef REPORT_KEYS printf("true\n"); diff --git a/src/ui/accelerator.h b/src/ui/accelerator.h index 548bde94a..567d78358 100644 --- a/src/ui/accelerator.h +++ b/src/ui/accelerator.h @@ -17,7 +17,7 @@ namespace ui { class Accelerator { public: - void addKey(KeyModifiers modifiers, KeyScancode scancode, int ascii); + void addKey(KeyModifiers modifiers, KeyScancode scancode, int unicodeChar); // Adds keys from strings like " " void addKeysFromString(const char* string); @@ -25,14 +25,14 @@ namespace ui { bool isEmpty() const { return m_combos.empty(); } std::string toString(); - bool check(KeyModifiers modifiers, KeyScancode scancode, int ascii); + bool check(KeyModifiers modifiers, KeyScancode scancode, int unicodeChar); bool checkFromAllegroKeyArray(); private: struct KeyCombo { KeyModifiers modifiers; KeyScancode scancode; - int ascii; + int unicodeChar; std::string toString(); }; diff --git a/src/ui/alert.cpp b/src/ui/alert.cpp index 2b23b40a3..58197c545 100644 --- a/src/ui/alert.cpp +++ b/src/ui/alert.cpp @@ -139,7 +139,7 @@ void Alert::processString(char* buf, std::vector& labels, std::vector -#include #ifdef WIN32 #include @@ -20,7 +21,7 @@ #pragma warning(disable:4996) // To void MSVC warning about std::copy() with unsafe arguments -static std::string clipboard_text; +static base::string clipboard_text; static void lowlevel_set_clipboard_text(const char *text) { @@ -30,13 +31,13 @@ static void lowlevel_set_clipboard_text(const char *text) const char* ui::clipboard::get_text() { #ifdef WIN32 - if (IsClipboardFormatAvailable(CF_TEXT)) { + if (IsClipboardFormatAvailable(CF_UNICODETEXT)) { if (OpenClipboard(win_get_window())) { - HGLOBAL hglobal = GetClipboardData(CF_TEXT); + HGLOBAL hglobal = GetClipboardData(CF_UNICODETEXT); if (hglobal != NULL) { - LPSTR lpstr = static_cast(GlobalLock(hglobal)); + LPWSTR lpstr = static_cast(GlobalLock(hglobal)); if (lpstr != NULL) { - lowlevel_set_clipboard_text(lpstr); + lowlevel_set_clipboard_text(base::to_utf8(lpstr).c_str()); GlobalUnlock(hglobal); } } @@ -53,21 +54,22 @@ void ui::clipboard::set_text(const char *text) lowlevel_set_clipboard_text(text); #ifdef WIN32 - if (IsClipboardFormatAvailable(CF_TEXT)) { + if (IsClipboardFormatAvailable(CF_UNICODETEXT)) { if (OpenClipboard(win_get_window())) { EmptyClipboard(); if (!clipboard_text.empty()) { - int len = clipboard_text.size(); + std::wstring wstr = base::from_utf8(clipboard_text); + int len = wstr.size(); HGLOBAL hglobal = GlobalAlloc(GMEM_MOVEABLE | - GMEM_ZEROINIT, sizeof(char)*(len+1)); + GMEM_ZEROINIT, sizeof(WCHAR)*(len+1)); - LPSTR lpstr = static_cast(GlobalLock(hglobal)); - std::copy(clipboard_text.begin(), clipboard_text.end(), lpstr); + LPWSTR lpstr = static_cast(GlobalLock(hglobal)); + std::copy(wstr.begin(), wstr.end(), lpstr); GlobalUnlock(hglobal); - SetClipboardData(CF_TEXT, hglobal); + SetClipboardData(CF_UNICODETEXT, hglobal); } CloseClipboard(); } diff --git a/src/ui/combobox.cpp b/src/ui/combobox.cpp index 72f0db439..cffcb43cb 100644 --- a/src/ui/combobox.cpp +++ b/src/ui/combobox.cpp @@ -163,7 +163,7 @@ int ComboBox::addItem(ListItem* item) return m_items.size()-1; } -int ComboBox::addItem(const char* text) +int ComboBox::addItem(const base::string& text) { return addItem(new ListItem(text)); } @@ -178,7 +178,7 @@ void ComboBox::insertItem(int itemIndex, ListItem* item) setSelectedItemIndex(0); } -void ComboBox::insertItem(int itemIndex, const char* text) +void ComboBox::insertItem(int itemIndex, const base::string& text) { insertItem(itemIndex, new ListItem(text)); } @@ -228,17 +228,20 @@ ListItem* ComboBox::getItem(int itemIndex) return NULL; } -const char* ComboBox::getItemText(int itemIndex) const +const base::string& ComboBox::getItemText(int itemIndex) const { if (itemIndex >= 0 && (size_t)itemIndex < m_items.size()) { ListItem* item = m_items[itemIndex]; return item->getText(); } - else - return ""; + else { + // Returns the text of the combo-box (it should be empty). + ASSERT(getText().empty()); + return getText(); + } } -void ComboBox::setItemText(int itemIndex, const char* text) +void ComboBox::setItemText(int itemIndex, const base::string& text) { ASSERT(itemIndex >= 0 && (size_t)itemIndex < m_items.size()); @@ -246,7 +249,7 @@ void ComboBox::setItemText(int itemIndex, const char* text) item->setText(text); } -int ComboBox::findItemIndex(const char* text) +int ComboBox::findItemIndex(const base::string& text) { int itemIndex = 0; @@ -254,8 +257,8 @@ int ComboBox::findItemIndex(const char* text) for (it = m_items.begin(); it != end; ++it) { ListItem* item = *it; - if ((m_casesensitive && ustrcmp(item->getText(), text) == 0) || - (!m_casesensitive && ustricmp(item->getText(), text) == 0)) { + if ((m_casesensitive && item->getText() == text) || + (!m_casesensitive && item->getText() == text)) { return itemIndex; } @@ -358,7 +361,7 @@ void ComboBox::onPreferredSize(PreferredSizeEvent& ev) for (it = m_items.begin(); it != end; ++it) { int item_w = 2*jguiscale()+ - text_length(this->getFont(), (*it)->getText())+ + text_length(getFont(), (*it)->getText().c_str())+ 10*jguiscale(); reqSize.w = MAX(reqSize.w, item_w); @@ -471,7 +474,7 @@ void ComboBox::onButtonClick(Event& ev) void ComboBox::openListBox() { if (!m_window) { - m_window = new Window(false, NULL); + m_window = new Window(false, ""); View* view = new View(); m_listbox = new ComboBoxListBox(this); m_window->setOnTop(true); diff --git a/src/ui/combobox.h b/src/ui/combobox.h index 9e76bc0e8..07736f51c 100644 --- a/src/ui/combobox.h +++ b/src/ui/combobox.h @@ -46,9 +46,9 @@ namespace ui { bool isCaseSensitive(); int addItem(ListItem* item); - int addItem(const char* text); + int addItem(const base::string& text); void insertItem(int itemIndex, ListItem* item); - void insertItem(int itemIndex, const char* text); + void insertItem(int itemIndex, const base::string& text); // Removes the given item (you must delete it). void removeItem(ListItem* item); @@ -61,9 +61,9 @@ namespace ui { int getItemCount() const; ListItem* getItem(int itemIndex); - const char* getItemText(int itemIndex) const; - void setItemText(int itemIndex, const char* text); - int findItemIndex(const char* text); + const base::string& getItemText(int itemIndex) const; + void setItemText(int itemIndex, const base::string& text); + int findItemIndex(const base::string& text); ListItem* getSelectedItem() const; void setSelectedItem(ListItem* item); diff --git a/src/ui/custom_label.cpp b/src/ui/custom_label.cpp index e3d6665fa..c364455fd 100644 --- a/src/ui/custom_label.cpp +++ b/src/ui/custom_label.cpp @@ -12,7 +12,7 @@ namespace ui { -CustomLabel::CustomLabel(const char *text) +CustomLabel::CustomLabel(const base::string& text) : Label(text) { } diff --git a/src/ui/custom_label.h b/src/ui/custom_label.h index c19da4f10..888c8ca7e 100644 --- a/src/ui/custom_label.h +++ b/src/ui/custom_label.h @@ -15,7 +15,7 @@ namespace ui { class CustomLabel : public Label { public: - CustomLabel(const char *text); + CustomLabel(const base::string& text); protected: bool onProcessMessage(Message* msg) OVERRIDE; diff --git a/src/ui/entry.cpp b/src/ui/entry.cpp index fbd131d96..b4b1080a3 100644 --- a/src/ui/entry.cpp +++ b/src/ui/entry.cpp @@ -10,6 +10,7 @@ #include "ui/entry.h" +#include "base/string.h" #include "ui/clipboard.h" #include "ui/font.h" #include "ui/manager.h" @@ -22,8 +23,8 @@ #include #include -#include -#include +#include +#include #define CHARACTER_LENGTH(f, c) ((f)->vtable->char_length((f), (c))) @@ -44,7 +45,7 @@ Entry::Entry(size_t maxsize, const char *format, ...) } // empty string else { - ustrcpy(buf, empty_string); + buf[0] = 0; } m_maxsize = maxsize; @@ -103,22 +104,24 @@ void Entry::hideCaret() void Entry::setCaretPos(int pos) { - const char *text = this->getText(); + base::utf8_const_iterator utf8_begin = base::utf8_const_iterator(getText().begin()); + int textlen = base::utf8_length(getText()); int x, c; m_caret = pos; - /* backward scroll */ + // Backward scroll if (m_caret < m_scroll) m_scroll = m_caret; - /* forward scroll */ + // Forward scroll m_scroll--; do { x = this->rc->x1 + this->border_width.l; for (c=++m_scroll; ; c++) { - x += CHARACTER_LENGTH(this->getFont(), - (c < ustrlen(text))? ugetat(text, c): ' '); + int ch = (c < textlen ? *(utf8_begin+c) : ' '); + + x += CHARACTER_LENGTH(getFont(), ch); if (x >= this->rc->x2-this->border_width.r) break; @@ -133,7 +136,7 @@ void Entry::setCaretPos(int pos) void Entry::selectText(int from, int to) { - int end = ustrlen(this->getText()); + int end = base::utf8_length(getText()); m_select = from; setCaretPos(from); // to move scroll @@ -212,48 +215,48 @@ bool Entry::onProcessMessage(Message* msg) switch (scancode) { - case KEY_LEFT: + case kKeyLeft: if (msg->ctrlPressed()) cmd = EntryCmd::BackwardWord; else cmd = EntryCmd::BackwardChar; break; - case KEY_RIGHT: + case kKeyRight: if (msg->ctrlPressed()) cmd = EntryCmd::ForwardWord; else cmd = EntryCmd::ForwardChar; break; - case KEY_HOME: + case kKeyHome: cmd = EntryCmd::BeginningOfLine; break; - case KEY_END: + case kKeyEnd: cmd = EntryCmd::EndOfLine; break; - case KEY_DEL: + case kKeyDel: if (msg->shiftPressed()) cmd = EntryCmd::Cut; else cmd = EntryCmd::DeleteForward; break; - case KEY_INSERT: + case kKeyInsert: if (msg->shiftPressed()) cmd = EntryCmd::Paste; else if (msg->ctrlPressed()) cmd = EntryCmd::Copy; break; - case KEY_BACKSPACE: + case kKeyBackspace: cmd = EntryCmd::DeleteBackward; break; default: - if (keymsg->ascii() >= 32) { + if (keymsg->unicodeChar() >= 32) { // Ctrl and Alt must be unpressed to insert a character // in the text-field. if ((msg->keyModifiers() & (kKeyCtrlModifier | kKeyAltModifier)) == 0) { @@ -276,7 +279,7 @@ bool Entry::onProcessMessage(Message* msg) if (cmd == EntryCmd::NoOp) break; - executeCmd(cmd, keymsg->ascii(), + executeCmd(cmd, keymsg->unicodeChar(), (msg->shiftPressed()) ? true: false); return true; } @@ -288,7 +291,9 @@ bool Entry::onProcessMessage(Message* msg) case kMouseMoveMessage: if (hasCapture()) { gfx::Point mousePos = static_cast(msg)->position(); - const char *text = this->getText(); + base::utf8_const_iterator utf8_begin = base::utf8_const_iterator(getText().begin()); + base::utf8_const_iterator utf8_end = base::utf8_const_iterator(getText().end()); + int textlen = base::utf8_length(getText()); int c, x; bool move = true; @@ -305,18 +310,17 @@ bool Entry::onProcessMessage(Message* msg) } // Forward scroll else if (mousePos.x >= this->rc->x2) { - if (m_scroll < ustrlen(text)) { + if (m_scroll < textlen) { m_scroll++; x = this->rc->x1 + this->border_width.l; - for (c=m_scroll; ; c++) { - x += CHARACTER_LENGTH(this->getFont(), - (c < ustrlen(text))? ugetat(text, c): ' '); + for (c=m_scroll; utf8_begin != utf8_end; ++c) { + int ch = (c < textlen ? *(utf8_begin+c) : ' '); + + x += CHARACTER_LENGTH(getFont(), ch); if (x > this->rc->x2-this->border_width.r) { c--; break; } - else if (!ugetat (text, c)) - break; } m_caret = c; move = false; @@ -414,6 +418,8 @@ void Entry::onEntryChange() int Entry::getCaretFromMouse(MouseMessage* mousemsg) { + base::utf8_const_iterator utf8_begin = base::utf8_const_iterator(getText().begin()); + base::utf8_const_iterator utf8_end = base::utf8_const_iterator(getText().end()); int c, x, w, mx, caret = m_caret; mx = mousemsg->position().x; @@ -422,8 +428,10 @@ int Entry::getCaretFromMouse(MouseMessage* mousemsg) this->rc->x2-this->border_width.r-1); x = this->rc->x1 + this->border_width.l; - for (c=m_scroll; ugetat(this->getText(), c); c++) { - w = CHARACTER_LENGTH(this->getFont(), ugetat(this->getText(), c)); + + base::utf8_const_iterator utf8_it = utf8_begin + m_scroll; + for (c=m_scroll; utf8_it != utf8_end; ++c, ++utf8_it) { + w = CHARACTER_LENGTH(getFont(), *utf8_it); if (x+w >= this->rc->x2-this->border_width.r) break; if ((mx >= x) && (mx < x+w)) { @@ -433,17 +441,19 @@ int Entry::getCaretFromMouse(MouseMessage* mousemsg) x += w; } - if (!ugetat(this->getText(), c)) + if (utf8_it == utf8_end) { if ((mx >= x) && - (mx <= this->rc->x2-this->border_width.r-1)) + (mx <= this->rc->x2-this->border_width.r-1)) { caret = c; + } + } return caret; } -void Entry::executeCmd(EntryCmd::Type cmd, int ascii, bool shift_pressed) +void Entry::executeCmd(EntryCmd::Type cmd, int unicodeChar, bool shift_pressed) { - std::string text = getText(); + std::wstring text = base::from_utf8(getText()); int c, selbeg, selend; getEntryThemeInfo(NULL, NULL, NULL, &selbeg, &selend); @@ -464,7 +474,7 @@ void Entry::executeCmd(EntryCmd::Type cmd, int ascii, bool shift_pressed) // put the character if (text.size() < m_maxsize) { ASSERT((size_t)m_caret <= text.size()); - text.insert(m_caret++, 1, ascii); + text.insert(m_caret++, 1, unicodeChar); } m_select = -1; @@ -540,8 +550,8 @@ void Entry::executeCmd(EntryCmd::Type cmd, int ascii, bool shift_pressed) if (selbeg >= 0) { // *cut* text! if (cmd == EntryCmd::Cut) { - base::string buf = text.substr(selbeg, selend - selbeg + 1); - clipboard::set_text(buf.c_str()); + std::wstring selected = text.substr(selbeg, selend - selbeg + 1); + clipboard::set_text(base::to_utf8(selected).c_str()); } // remove text @@ -559,9 +569,11 @@ void Entry::executeCmd(EntryCmd::Type cmd, int ascii, bool shift_pressed) break; case EntryCmd::Paste: { - const char *clipboard; + const char* clipboard_str; + + if ((clipboard_str = clipboard::get_text())) { + base::string clipboard(clipboard_str); - if ((clipboard = clipboard::get_text())) { // delete the entire selection if (selbeg >= 0) { text.erase(selbeg, selend-selbeg+1); @@ -571,11 +583,13 @@ void Entry::executeCmd(EntryCmd::Type cmd, int ascii, bool shift_pressed) } // paste text - for (c=0; c= 0) { - base::string buf = text.substr(selbeg, selend - selbeg + 1); - clipboard::set_text(buf.c_str()); + std::wstring selected = text.substr(selbeg, selend - selbeg + 1); + clipboard::set_text(base::to_utf8(selected).c_str()); } break; @@ -606,8 +620,9 @@ void Entry::executeCmd(EntryCmd::Type cmd, int ascii, bool shift_pressed) break; } - if (text != this->getText()) { - this->setText(text.c_str()); + base::string newText = base::to_utf8(text); + if (newText != getText()) { + setText(newText.c_str()); onEntryChange(); } @@ -621,18 +636,20 @@ void Entry::executeCmd(EntryCmd::Type cmd, int ascii, bool shift_pressed) void Entry::forwardWord() { + base::utf8_const_iterator utf8_begin = base::utf8_const_iterator(getText().begin()); + int textlen = base::utf8_length(getText()); int ch; - for (; m_caretgetText()); m_caret++) { - ch = ugetat(this->getText(), m_caret); - if (IS_WORD_CHAR (ch)) + for (; m_caret < textlen; m_caret++) { + ch = *(utf8_begin + m_caret); + if (IS_WORD_CHAR(ch)) break; } - for (; m_caretgetText()); m_caret++) { - ch = ugetat(this->getText(), m_caret); + for (; m_caret < textlen; m_caret++) { + ch = *(utf8_begin + m_caret); if (!IS_WORD_CHAR(ch)) { - m_caret++; + ++m_caret; break; } } @@ -640,18 +657,19 @@ void Entry::forwardWord() void Entry::backwardWord() { + base::utf8_const_iterator utf8_begin = base::utf8_const_iterator(getText().begin()); int ch; - for (m_caret--; m_caret >= 0; m_caret--) { - ch = ugetat(this->getText(), m_caret); + for (--m_caret; m_caret >= 0; --m_caret) { + ch = *(utf8_begin + m_caret); if (IS_WORD_CHAR(ch)) break; } - for (; m_caret >= 0; m_caret--) { - ch = ugetat(this->getText(), m_caret); + for (; m_caret >= 0; --m_caret) { + ch = *(utf8_begin + m_caret); if (!IS_WORD_CHAR(ch)) { - m_caret++; + ++m_caret; break; } } diff --git a/src/ui/int_entry.cpp b/src/ui/int_entry.cpp index 2e78664df..2bac6dfed 100644 --- a/src/ui/int_entry.cpp +++ b/src/ui/int_entry.cpp @@ -105,7 +105,7 @@ void IntEntry::openPopup() if (rc.x+rc.w > JI_SCREEN_W) rc.x = rc.x - rc.w + getBounds().w; - m_popupWindow = new PopupWindow(NULL, false); + m_popupWindow = new PopupWindow("", false); m_popupWindow->setAutoRemap(false); m_popupWindow->setBounds(rc); m_popupWindow->setBgColor(rgba(0, 0, 0, 0)); diff --git a/src/ui/keys.cpp b/src/ui/keys.cpp index d01328494..016edb1d5 100644 --- a/src/ui/keys.cpp +++ b/src/ui/keys.cpp @@ -12,7 +12,7 @@ #include -int ui::scancode_to_ascii(KeyScancode scancode) +int ui::scancode_to_unicode(KeyScancode scancode) { return ::scancode_to_ascii(scancode); } diff --git a/src/ui/keys.h b/src/ui/keys.h index ba1b99d2b..dcaf50df0 100644 --- a/src/ui/keys.h +++ b/src/ui/keys.h @@ -151,7 +151,7 @@ namespace ui { kKeyScancodes = 127 }; - int scancode_to_ascii(KeyScancode scancode); + int scancode_to_unicode(KeyScancode scancode); } // namespace ui diff --git a/src/ui/label.cpp b/src/ui/label.cpp index 02157e817..e46a5f5d7 100644 --- a/src/ui/label.cpp +++ b/src/ui/label.cpp @@ -15,7 +15,7 @@ namespace ui { -Label::Label(const char *text) +Label::Label(const base::string& text) : Widget(kLabelWidget) { setAlign(JI_LEFT | JI_MIDDLE); @@ -37,7 +37,7 @@ void Label::onPreferredSize(PreferredSizeEvent& ev) { gfx::Size sz(0, 0); - if (this->hasText()) { + if (hasText()) { sz.w = jwidget_get_text_length(this); sz.h = jwidget_get_text_height(this); } diff --git a/src/ui/label.h b/src/ui/label.h index cf92bc684..48f84c111 100644 --- a/src/ui/label.h +++ b/src/ui/label.h @@ -16,7 +16,7 @@ namespace ui { class Label : public Widget { public: - Label(const char *text); + Label(const base::string& text); Color getTextColor() const; void setTextColor(Color color); diff --git a/src/ui/link_label.cpp b/src/ui/link_label.cpp index cee425310..8a6f8d742 100644 --- a/src/ui/link_label.cpp +++ b/src/ui/link_label.cpp @@ -18,19 +18,19 @@ namespace ui { -LinkLabel::LinkLabel(const char* urlOrText) +LinkLabel::LinkLabel(const base::string& urlOrText) : CustomLabel(urlOrText) , m_url(urlOrText) { } -LinkLabel::LinkLabel(const char* url, const char* text) +LinkLabel::LinkLabel(const base::string& url, const base::string& text) : CustomLabel(text) , m_url(url) { } -void LinkLabel::setUrl(const char* url) +void LinkLabel::setUrl(const base::string& url) { m_url = url; } diff --git a/src/ui/link_label.h b/src/ui/link_label.h index c1bac016b..f4c99c4d7 100644 --- a/src/ui/link_label.h +++ b/src/ui/link_label.h @@ -18,11 +18,11 @@ namespace ui { class LinkLabel : public CustomLabel { public: - LinkLabel(const char* urlOrText); - LinkLabel(const char* url, const char* text); + LinkLabel(const base::string& urlOrText); + LinkLabel(const base::string& url, const base::string& text); - const char* getUrl() const { return m_url.c_str(); } - void setUrl(const char* url); + const base::string& getUrl() const { return m_url; } + void setUrl(const base::string& url); Signal0 Click; @@ -30,7 +30,7 @@ namespace ui { bool onProcessMessage(Message* msg) OVERRIDE; void onPaint(PaintEvent& ev) OVERRIDE; - std::string m_url; + base::string m_url; }; } // namespace ui diff --git a/src/ui/listitem.cpp b/src/ui/listitem.cpp index e9f148457..5bb1bc7e0 100644 --- a/src/ui/listitem.cpp +++ b/src/ui/listitem.cpp @@ -20,7 +20,7 @@ namespace ui { using namespace gfx; -ListItem::ListItem(const char* text) +ListItem::ListItem(const base::string& text) : Widget(kListItemWidget) { setAlign(JI_LEFT | JI_MIDDLE); diff --git a/src/ui/listitem.h b/src/ui/listitem.h index ba17b37f8..9af36e77e 100644 --- a/src/ui/listitem.h +++ b/src/ui/listitem.h @@ -15,7 +15,7 @@ namespace ui { class ListItem : public Widget { public: - ListItem(const char* text); + ListItem(const base::string& text); protected: void onPaint(PaintEvent& ev) OVERRIDE; diff --git a/src/ui/manager.cpp b/src/ui/manager.cpp index 01d36e047..08703f370 100644 --- a/src/ui/manager.cpp +++ b/src/ui/manager.cpp @@ -398,18 +398,20 @@ bool Manager::generateMessages() // Generate kKeyDownMessage messages. while (keypressed()) { - int readkey_value = readkey(); + int scancode; + int unicode_char = ureadkey(&scancode); int repeat = 0; - - c = readkey_value >> 8; - if (c >= 0 && c < KEY_MAX) { - old_readed_key[c] = key[c]; - repeat = key_repeated[c]++; + { + c = scancode; + if (c >= 0 && c < KEY_MAX) { + old_readed_key[c] = key[c]; + repeat = key_repeated[c]++; + } } Message* msg = new KeyMessage(kKeyDownMessage, - static_cast((readkey_value >> 8) & 0xff), - (readkey_value & 0xff), repeat); + static_cast(scancode), + unicode_char, repeat); broadcastKeyMsg(msg); enqueueMessage(msg); } @@ -424,7 +426,7 @@ bool Manager::generateMessages() // Press/release key interface Message* msg = new KeyMessage(kKeyUpMessage, scancode, - scancode_to_ascii(scancode), 0); + scancode_to_unicode(scancode), 0); old_readed_key[c] = key[c]; key_repeated[c] = 0; @@ -436,7 +438,7 @@ bool Manager::generateMessages() // Press/release key interface Message* msg = new KeyMessage(kKeyDownMessage, scancode, - scancode_to_ascii(scancode), + scancode_to_unicode(scancode), key_repeated[c]++); old_readed_key[c] = key[c]; diff --git a/src/ui/menu.cpp b/src/ui/menu.cpp index 172951430..653410497 100644 --- a/src/ui/menu.cpp +++ b/src/ui/menu.cpp @@ -90,7 +90,7 @@ class CustomizedWindowForMenuBox : public Window { public: CustomizedWindowForMenuBox(MenuBox* menubox) - : Window(false, NULL) + : Window(false, "") { setMoveable(false); // Can't move the window addChild(menubox); @@ -165,7 +165,7 @@ MenuBar::MenuBar() createBase(); } -MenuItem::MenuItem(const char *text) +MenuItem::MenuItem(const base::string& text) : Widget(kMenuItemWidget) { m_accel = NULL; @@ -272,7 +272,7 @@ void Menu::showPopup(int x, int y) } while (jmouse_b(0) != kButtonNone); // New window and new menu-box - Window* window = new Window(false, NULL); + Window* window = new Window(false, ""); MenuBox* menubox = new MenuBox(); MenuBaseData* base = menubox->createBase(); base->was_clicked = true; @@ -483,7 +483,7 @@ bool MenuBox::onProcessMessage(Message* msg) if (((this->type == kMenuBoxWidget) && (msg->keyModifiers() == kKeyNoneModifier || // <-- Inside menu-boxes we can use letters without Alt modifier pressed msg->keyModifiers() == kKeyAltModifier)) || ((this->type == kMenuBarWidget) && (msg->keyModifiers() == kKeyAltModifier))) { - selected = check_for_letter(menu, ui::scancode_to_ascii(static_cast(msg)->scancode())); + selected = check_for_letter(menu, scancode_to_unicode(static_cast(msg)->scancode())); if (selected) { menu->highlightItem(selected, true, true, true); return true; @@ -874,7 +874,7 @@ void MenuItem::onPreferredSize(PreferredSizeEvent& ev) Size size(0, 0); int bar = (this->getParent()->getParent()->type == kMenuBarWidget); - if (this->hasText()) { + if (hasText()) { size.w = + this->border_width.l + jwidget_get_text_length(this) diff --git a/src/ui/menu.h b/src/ui/menu.h index c01a64461..05896ef2e 100644 --- a/src/ui/menu.h +++ b/src/ui/menu.h @@ -95,7 +95,7 @@ namespace ui { class MenuItem : public Widget { public: - MenuItem(const char *text); + MenuItem(const base::string& text); ~MenuItem(); Menu* getSubmenu(); diff --git a/src/ui/message.cpp b/src/ui/message.cpp index 9e84ac585..7e04488e3 100644 --- a/src/ui/message.cpp +++ b/src/ui/message.cpp @@ -67,10 +67,10 @@ void Message::broadcastToChildren(Widget* widget) addRecipient(widget); } -KeyMessage::KeyMessage(MessageType type, KeyScancode scancode, int ascii, int repeat) +KeyMessage::KeyMessage(MessageType type, KeyScancode scancode, int unicodeChar, int repeat) : Message(type) , m_scancode(scancode) - , m_ascii(ascii) + , m_unicodeChar(unicodeChar) , m_repeat(repeat) , m_propagate_to_children(false) , m_propagate_to_parent(true) diff --git a/src/ui/message.h b/src/ui/message.h index 8d4446f39..8607329e2 100644 --- a/src/ui/message.h +++ b/src/ui/message.h @@ -59,10 +59,10 @@ namespace ui { class KeyMessage : public Message { public: - KeyMessage(MessageType type, KeyScancode scancode, int ascii, int repeat); + KeyMessage(MessageType type, KeyScancode scancode, int unicodeChar, int repeat); KeyScancode scancode() const { return m_scancode; } - int ascii() const { return m_ascii; } + int unicodeChar() const { return m_unicodeChar; } int repeat() const { return m_repeat; } bool propagateToChildren() const { return m_propagate_to_children; } bool propagateToParent() const { return m_propagate_to_parent; } @@ -71,7 +71,7 @@ namespace ui { private: KeyScancode m_scancode; - int m_ascii; + int m_unicodeChar; int m_repeat; // repeat=0 means the first time the key is pressed bool m_propagate_to_children : 1; bool m_propagate_to_parent : 1; diff --git a/src/ui/popup_window.cpp b/src/ui/popup_window.cpp index acce465eb..f794344a5 100644 --- a/src/ui/popup_window.cpp +++ b/src/ui/popup_window.cpp @@ -21,7 +21,7 @@ namespace ui { using namespace gfx; -PopupWindow::PopupWindow(const char* text, bool close_on_buttonpressed) +PopupWindow::PopupWindow(const base::string& text, bool close_on_buttonpressed) : Window(false, text) { m_close_on_buttonpressed = close_on_buttonpressed; diff --git a/src/ui/popup_window.h b/src/ui/popup_window.h index 03fc098a1..f8fbb6edf 100644 --- a/src/ui/popup_window.h +++ b/src/ui/popup_window.h @@ -15,7 +15,7 @@ namespace ui { class PopupWindow : public Window { public: - PopupWindow(const char* text, bool close_on_buttonpressed); + PopupWindow(const base::string& text, bool close_on_buttonpressed); ~PopupWindow(); void setHotRegion(const gfx::Region& region); diff --git a/src/ui/separator.cpp b/src/ui/separator.cpp index b26a4d5a3..ce81641d9 100644 --- a/src/ui/separator.cpp +++ b/src/ui/separator.cpp @@ -19,7 +19,7 @@ namespace ui { using namespace gfx; -Separator::Separator(const char* text, int align) +Separator::Separator(const base::string& text, int align) : Widget(kSeparatorWidget) { setAlign(align); diff --git a/src/ui/separator.h b/src/ui/separator.h index f5839a168..57ea20f5d 100644 --- a/src/ui/separator.h +++ b/src/ui/separator.h @@ -15,7 +15,7 @@ namespace ui { class Separator : public Widget { public: - Separator(const char* text, int align); + Separator(const base::string& text, int align); protected: void onPaint(PaintEvent& ev) OVERRIDE; diff --git a/src/ui/textbox.cpp b/src/ui/textbox.cpp index 1992a8cad..9325bc2e4 100644 --- a/src/ui/textbox.cpp +++ b/src/ui/textbox.cpp @@ -22,7 +22,7 @@ namespace ui { -TextBox::TextBox(const char* text, int align) +TextBox::TextBox(const base::string& text, int align) : Widget(kTextBoxWidget) { setFocusStop(true); diff --git a/src/ui/textbox.h b/src/ui/textbox.h index 5de767553..2f31c829f 100644 --- a/src/ui/textbox.h +++ b/src/ui/textbox.h @@ -15,7 +15,7 @@ namespace ui { class TextBox : public Widget { public: - TextBox(const char* text, int align); + TextBox(const base::string& text, int align); protected: bool onProcessMessage(Message* msg) OVERRIDE; diff --git a/src/ui/theme.cpp b/src/ui/theme.cpp index 7e4a2791d..19cb39cfd 100644 --- a/src/ui/theme.cpp +++ b/src/ui/theme.cpp @@ -100,8 +100,8 @@ void drawTextBox(BITMAP* bmp, Widget* widget, int* w, int* h, Color bg, Color fg) { View* view = View::getView(widget); - char *text = (char*)widget->getText(); // TODO warning: removing const modifier - char *beg, *end; + char* text = const_cast(widget->getText().c_str()); + char* beg, *end; int x1, y1, x2, y2; int x, y, chr, len; gfx::Point scroll; @@ -164,7 +164,7 @@ void drawTextBox(BITMAP* bmp, Widget* widget, for (beg=end=text; end; ) { x = x1 - scroll.x; - /* without word-wrap */ + // Without word-wrap if (!(widget->getAlign() & JI_WORDWRAP)) { end = ustrchr(beg, '\n'); if (end) { @@ -172,7 +172,7 @@ void drawTextBox(BITMAP* bmp, Widget* widget, *end = 0; } } - /* with word-wrap */ + // With word-wrap else { old_end = NULL; for (beg_end=beg;;) { @@ -182,7 +182,7 @@ void drawTextBox(BITMAP* bmp, Widget* widget, *end = 0; } - /* to here we can print */ + // To here we can print if ((old_end) && (x+text_length(font, beg) > x1-scroll.x+width)) { if (end) *end = chr; @@ -192,16 +192,16 @@ void drawTextBox(BITMAP* bmp, Widget* widget, *end = 0; break; } - /* we can print one word more */ + // We can print one word more else if (end) { - /* force break */ + // Force break if (chr == '\n') break; *end = chr; beg_end = end+1; } - /* we are in the end of text */ + // We are in the end of text else break; diff --git a/src/ui/tooltips.cpp b/src/ui/tooltips.cpp index d4cdd479c..cf82f79dd 100644 --- a/src/ui/tooltips.cpp +++ b/src/ui/tooltips.cpp @@ -43,7 +43,7 @@ TooltipManager::~TooltipManager() manager->removeMessageFilterFor(this); } -void TooltipManager::addTooltipFor(Widget* widget, const char* text, int arrowAlign) +void TooltipManager::addTooltipFor(Widget* widget, const base::string& text, int arrowAlign) { m_tips[widget] = TipInfo(text, arrowAlign); } diff --git a/src/ui/tooltips.h b/src/ui/tooltips.h index bf7568a6f..613193912 100644 --- a/src/ui/tooltips.h +++ b/src/ui/tooltips.h @@ -23,7 +23,7 @@ namespace ui { TooltipManager(); ~TooltipManager(); - void addTooltipFor(Widget* widget, const char* text, int arrowAlign = 0); + void addTooltipFor(Widget* widget, const base::string& text, int arrowAlign = 0); protected: bool onProcessMessage(Message* msg) OVERRIDE; @@ -36,7 +36,7 @@ namespace ui { int arrowAlign; TipInfo() { } - TipInfo(const char* text, int arrowAlign) + TipInfo(const base::string& text, int arrowAlign) : text(text), arrowAlign(arrowAlign) { } }; diff --git a/src/ui/widget.cpp b/src/ui/widget.cpp index ba8934602..971146f88 100644 --- a/src/ui/widget.cpp +++ b/src/ui/widget.cpp @@ -122,15 +122,15 @@ void Widget::initTheme() int Widget::getTextInt() const { - return ustrtol(m_text.c_str(), NULL, 10); + return strtol(m_text.c_str(), NULL, 10); } double Widget::getTextDouble() const { - return ustrtod(m_text.c_str(), NULL); + return strtod(m_text.c_str(), NULL); } -void Widget::setText(const char *text) +void Widget::setText(const base::string& text) { setTextQuiet(text); onSetText(); @@ -155,16 +155,9 @@ void Widget::setTextf(const char *format, ...) setText(buf); } -void Widget::setTextQuiet(const char *text) +void Widget::setTextQuiet(const base::string& text) { - if (text) { - m_text = text; - flags &= ~JI_NOTEXT; - } - else { - m_text.clear(); - flags |= JI_NOTEXT; - } + m_text = text; } FONT *Widget::getFont() const @@ -719,7 +712,7 @@ void Widget::getDrawableRegion(gfx::Region& region, DrawableRegionFlags flags) int jwidget_get_text_length(const Widget* widget) { #if 1 - return ji_font_text_len(widget->getFont(), widget->getText()); + return ji_font_text_len(widget->getFont(), widget->getText().c_str()); #else /* use cached text size */ return widget->text_size_pix; #endif @@ -751,7 +744,7 @@ void jwidget_get_texticon_info(Widget* widget, text_x = text_y = 0; - /* size of the text */ + // Size of the text if (widget->hasText()) { text_w = jwidget_get_text_length(widget); text_h = jwidget_get_text_height(widget); @@ -793,9 +786,9 @@ void jwidget_get_texticon_info(Widget* widget, else box_y = widget->rc->y1 + widget->border_width.t; - /* with text */ + // With text if (widget->hasText()) { - /* text/icon X position */ + // Text/icon X position if (icon_align & JI_RIGHT) { text_x = box_x; icon_x = box_x + box_w - icon_w; @@ -809,7 +802,7 @@ void jwidget_get_texticon_info(Widget* widget, icon_x = box_x; } - /* text Y position */ + // Text Y position if (icon_align & JI_BOTTOM) { text_y = box_y; icon_y = box_y + box_h - icon_h; @@ -823,9 +816,9 @@ void jwidget_get_texticon_info(Widget* widget, icon_y = box_y; } } - /* without text */ + // Without text else { - /* icon X/Y position */ + // Icon X/Y position icon_x = box_x; icon_y = box_y; } diff --git a/src/ui/widget.h b/src/ui/widget.h index 11b0e0bd2..6b84d45cc 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h @@ -9,6 +9,7 @@ #include +#include "base/string.h" #include "gfx/border.h" #include "gfx/point.h" #include "gfx/rect.h" @@ -96,7 +97,7 @@ namespace ui { WidgetType getType() const { return this->type; } - const std::string& getId() const { return m_id; } + const base::string& getId() const { return m_id; } void setId(const char* id) { m_id = id; } int getAlign() const { return m_align; } @@ -104,15 +105,15 @@ namespace ui { // Text property. - bool hasText() const { return flags & JI_NOTEXT ? false: true; } + bool hasText() const { return !m_text.empty(); } - const char* getText() const { return m_text.c_str(); } + const base::string& getText() const { return m_text; } int getTextInt() const; double getTextDouble() const; size_t getTextSize() const { return m_text.size(); } - void setText(const char* text); + void setText(const base::string& text); void setTextf(const char* text, ...); - void setTextQuiet(const char* text); + void setTextQuiet(const base::string& text); // =============================================================== // COMMON PROPERTIES @@ -359,10 +360,10 @@ namespace ui { virtual void onSetText(); private: - std::string m_id; // Widget's id + base::string m_id; // Widget's id Theme* m_theme; // Widget's theme int m_align; // Widget alignment - std::string m_text; // Widget text + base::string m_text; // Widget text struct FONT *m_font; // Text font type ui::Color m_bgColor; // Background color gfx::Region m_updateRegion;; // Region to be redrawed. diff --git a/src/ui/window.cpp b/src/ui/window.cpp index 14c3d254a..73ea7a230 100644 --- a/src/ui/window.cpp +++ b/src/ui/window.cpp @@ -35,7 +35,7 @@ static gfx::Rect* clickedWindowPos = NULL; static void displace_widgets(Widget* widget, int x, int y); -Window::Window(bool desktop, const char* text) +Window::Window(bool desktop, const base::string& text) : Widget(kWindowWidget) { m_killer = NULL; @@ -123,7 +123,7 @@ void Window::onHitTest(HitTestEvent& ev) gfx::Rect cpos = getChildrenBounds(); // Move - if ((this->hasText()) + if ((hasText()) && (((x >= cpos.x) && (x < cpos.x2()) && (y >= pos.y+this->border_width.b) && @@ -461,7 +461,7 @@ void Window::onPreferredSize(PreferredSizeEvent& ev) } } - if (this->hasText()) + if (hasText()) maxSize.w = MAX(maxSize.w, jwidget_get_text_length(this)); ev.setPreferredSize(this->border_width.l + maxSize.w + this->border_width.r, diff --git a/src/ui/window.h b/src/ui/window.h index b8cd1cdf1..d8280406a 100644 --- a/src/ui/window.h +++ b/src/ui/window.h @@ -20,7 +20,7 @@ namespace ui { class Window : public Widget { public: - Window(bool isDesktop, const char* text); + Window(bool isDesktop, const base::string& text); ~Window(); Widget* getKiller(); diff --git a/src/updater/user_agent_win.c b/src/updater/user_agent_win.c index 6fb8ea59f..0e785020e 100644 --- a/src/updater/user_agent_win.c +++ b/src/updater/user_agent_win.c @@ -30,8 +30,9 @@ BOOL IsWow64() { BOOL isWow64 = FALSE; - fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle("kernel32"), - "IsWow64Process"); + fnIsWow64Process = (LPFN_ISWOW64PROCESS) + GetProcAddress(GetModuleHandle(L"kernel32"), + "IsWow64Process"); if (fnIsWow64Process != NULL) fnIsWow64Process(GetCurrentProcess(), &isWow64);