diff --git a/dlib/CMakeLists.txt b/dlib/CMakeLists.txt index aa1901fbb..b0fcd5e94 100644 --- a/dlib/CMakeLists.txt +++ b/dlib/CMakeLists.txt @@ -51,7 +51,7 @@ IF (NOT DLIB_ISO_CPP_ONLY) if (DLIB_NO_GUI_SUPPORT) set (dlib_needed_libraries ws2_32) else() - set (dlib_needed_libraries ws2_32 comctl32 gdi32) + set (dlib_needed_libraries ws2_32 comctl32 gdi32 imm32) endif() ELSEIF(APPLE) ############################################################################ FIND_LIBRARY(pthreadlib pthread) diff --git a/dlib/algs.h b/dlib/algs.h index eb6a5ccbc..5bac57cf5 100644 --- a/dlib/algs.h +++ b/dlib/algs.h @@ -6,19 +6,6 @@ // this file contains miscellaneous stuff -#include // for std::swap -#include // for std::bad_alloc -#include // for the exceptions -#include -#include "platform.h" -#include "assert.h" -#include "error.h" -#include "noncopyable.h" -#include "enable_if.h" -#include "uintn.h" - - - #ifdef _MSC_VER // Disable the following warnings for Visual Studio @@ -56,6 +43,19 @@ #endif +#include // for std::swap +#include // for std::bad_alloc +#include // for the exceptions +#include +#include "platform.h" +#include "assert.h" +#include "error.h" +#include "noncopyable.h" +#include "enable_if.h" +#include "uintn.h" + + + // ---------------------------------------------------------------------------------------- /*!A _dT !*/ diff --git a/dlib/all/source.cpp b/dlib/all/source.cpp index efd70d84f..9e53db416 100644 --- a/dlib/all/source.cpp +++ b/dlib/all/source.cpp @@ -15,6 +15,7 @@ #include "../md5/md5_kernel_1.cpp" #include "../pixel.cpp" #include "../tokenizer/tokenizer_kernel_1.cpp" +#include "../unicode/unicode.cpp" #ifndef DLIB_ISO_CPP_ONLY // Code that depends on OS specific APIs diff --git a/dlib/gui_core/gui_core_kernel_1.cpp b/dlib/gui_core/gui_core_kernel_1.cpp index 241cc1809..9be3bada0 100644 --- a/dlib/gui_core/gui_core_kernel_1.cpp +++ b/dlib/gui_core/gui_core_kernel_1.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net) +// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), Keita Mochizuki // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_GUI_CORE_KERNEL_1_CPp_ #define DLIB_GUI_CORE_KERNEL_1_CPp_ @@ -14,6 +14,7 @@ #pragma comment (lib, "gdi32.lib") #pragma comment (lib, "comctl32.lib") #pragma comment (lib, "user32.lib") +#pragma comment (lib, "imm32.lib") #endif @@ -44,7 +45,7 @@ namespace dlib static bool core_has_been_initialized = false; static bool quit_windows_loop = false; static bool set_window_title_done = true; - static std::string window_title; + static std::wstring window_title; static bool move_window_done = true; static HWND move_window_hwnd = NULL; static int move_window_width = 0; @@ -54,6 +55,7 @@ namespace dlib static bool request_new_window = false; static DWORD dwStyle; static HWND new_window = NULL; + static bool in_ime_composition = false; // the window_table.get_mutex() mutex locks the above 11 variables @@ -549,7 +551,7 @@ namespace dlib case WM_USER+CALL_SET_WINDOW_TITLE: if (hwnd == helper_window) { - SetWindowText((HWND)wParam,window_title.c_str()); + SetWindowTextW((HWND)wParam,window_title.c_str()); set_window_title_done = true; et_signaler.broadcast(); } @@ -588,6 +590,8 @@ namespace dlib case WM_SYSKEYDOWN: case WM_KEYDOWN: { + if (in_ime_composition) break; + base_window** win_ = window_table[hwnd]; base_window* win; if (win_) @@ -1109,6 +1113,39 @@ namespace dlib } return DefWindowProc (hwnd, message, wParam, lParam); + case WM_IME_STARTCOMPOSITION: + in_ime_composition = true; + break; + + case WM_IME_COMPOSITION: + { + in_ime_composition = false; + base_window** win_ = window_table[hwnd]; + base_window* win; + if (win_) + win = *win_; + else + break; + HIMC hImc = ImmGetContext(hwnd); + if (lParam & GCS_RESULTSTR){ + WCHAR wc; + LONG bufbyte = ImmGetCompositionStringW(hImc, GCS_RESULTSTR, &wc, 0); + if (bufbyte != IMM_ERROR_NODATA && bufbyte != IMM_ERROR_GENERAL){ + bufbyte += sizeof(WCHAR); + + + WCHAR *buf = new WCHAR[bufbyte / sizeof(WCHAR)]; + ImmGetCompositionStringW(hImc, GCS_RESULTSTR, buf, bufbyte); + buf[bufbyte / sizeof(WCHAR) - 1] = L'\0'; + + // signal the putstring event + win->on_string_put(std::wstring(buf)); + delete [] buf; + } + } + ImmReleaseContext(hwnd, hImc); + } + break; default: break; @@ -1578,7 +1615,23 @@ namespace dlib void base_window:: set_title ( - const std::string& title + const std::string &title + ) + { + set_title(convert_mbstring_to_wstring(title)); + } + + void base_window:: + set_title ( + const ustring &title + ) + { + set_title(convert_utf32_to_wstring(title)); + } + + void base_window:: + set_title ( + const std::wstring& title ) { DLIB_ASSERT(is_closed() == false, @@ -1596,7 +1649,7 @@ namespace dlib if (get_thread_id() == gui_core_kernel_1_globals::event_thread_id) { - SetWindowText(hwnd,title.c_str()); + SetWindowTextW(hwnd,title.c_str()); } else { @@ -1902,6 +1955,20 @@ namespace dlib void put_on_clipboard ( const std::string& str ) + { + put_on_clipboard(convert_mbstring_to_wstring(str)); + } + + void put_on_clipboard ( + const dlib::ustring& str + ) + { + put_on_clipboard(convert_utf32_to_wstring(str)); + } + + void put_on_clipboard ( + const std::wstring& str + ) { using namespace gui_core_kernel_1_globals; using namespace std; @@ -1913,34 +1980,34 @@ namespace dlib EmptyClipboard(); auto_mutex M(window_table.get_mutex()); - const unsigned long newlines = count(str.begin(),str.end(),'\n'); + const unsigned long newlines = count(str.begin(),str.end(),L'\n'); - HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE,str.size()+newlines+1); + HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE,(str.size()+newlines+1)*sizeof(wchar_t)); if (mem != NULL) { - char* buf = reinterpret_cast(GlobalLock(mem)); + wchar_t* buf = reinterpret_cast(GlobalLock(mem)); if (buf != NULL) { // copy str into buf while also replacing all the \n with \r\n - for (string::size_type i = 0; i < str.size(); ++i) + for (wstring::size_type i = 0; i < str.size(); ++i) { - if (str[i] != '\n') + if (str[i] != L'\n') { *buf = str[i]; ++buf; } else { - *buf = '\r'; + *buf = L'\r'; ++buf; - *buf = '\n'; + *buf = L'\n'; ++buf; } } - *buf = '\0'; + *buf = L'\0'; GlobalUnlock(mem); - SetClipboardData(CF_TEXT,mem); + SetClipboardData(CF_UNICODETEXT,mem); } } CloseClipboard(); @@ -1952,6 +2019,24 @@ namespace dlib void get_from_clipboard ( std::string& str ) + { + std::wstring wstr; + get_from_clipboard(wstr); + str = convert_wstring_to_mbstring(wstr); + } + + void get_from_clipboard ( + dlib::ustring& str + ) + { + std::wstring wstr; + get_from_clipboard(wstr); + str = convert_wstring_to_utf32(wstr); + } + + void get_from_clipboard ( + std::wstring& str + ) { using namespace gui_core_kernel_1_globals; using namespace std; @@ -1962,19 +2047,19 @@ namespace dlib if (OpenClipboard(helper_window)) { - HANDLE data = GetClipboardData(CF_TEXT); + HANDLE data = GetClipboardData(CF_UNICODETEXT); if (data != NULL) { - char* buf = reinterpret_cast(GlobalLock(data)); + wchar_t* buf = reinterpret_cast(GlobalLock(data)); if (buf != 0) { str.clear(); // copy the data from buf into str while also removing any '\r' // characters. - while (*buf != '\0') + while (*buf != L'\0') { - if (*buf != '\r') + if (*buf != L'\r') str += *buf; ++buf; } diff --git a/dlib/gui_core/gui_core_kernel_1.h b/dlib/gui_core/gui_core_kernel_1.h index 6414fd287..155fd6e80 100644 --- a/dlib/gui_core/gui_core_kernel_1.h +++ b/dlib/gui_core/gui_core_kernel_1.h @@ -1,4 +1,4 @@ -// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net) +// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), Keita Mochizuki // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_GUI_CORE_KERNEl_1_ #define DLIB_GUI_CORE_KERNEl_1_ @@ -38,6 +38,7 @@ #include "../assert.h" #include "../queue.h" #include "../pixel.h" +#include "../unicode.h" namespace dlib @@ -136,12 +137,28 @@ namespace dlib const std::string& str ); + void put_on_clipboard ( + const std::wstring& str + ); + + void put_on_clipboard ( + const dlib::ustring& str + ); + // ---------------------------------------------------------------------------------------- void get_from_clipboard ( std::string& str ); + void get_from_clipboard ( + std::wstring& str + ); + + void get_from_clipboard ( + dlib::ustring& str + ); + // ---------------------------------------------------------------------------------------- class base_window @@ -186,6 +203,14 @@ namespace dlib const std::string& title ); + void set_title ( + const std::wstring& title + ); + + void set_title ( + const ustring& title + ); + virtual void show ( ); @@ -353,6 +378,10 @@ namespace dlib bool is_printable, unsigned long state ){} + + virtual void on_string_put ( + const std::wstring &str + ){} private: diff --git a/dlib/gui_core/gui_core_kernel_2.cpp b/dlib/gui_core/gui_core_kernel_2.cpp index e085b3cc9..721867697 100644 --- a/dlib/gui_core/gui_core_kernel_2.cpp +++ b/dlib/gui_core/gui_core_kernel_2.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net) +// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), Keita Mochizuki // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_GUI_CORE_KERNEL_2_CPp_ #define DLIB_GUI_CORE_KERNEL_2_CPp_ @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include "../assert.h" #include "../queue.h" @@ -37,6 +39,7 @@ namespace dlib { Window hwnd; Time last_click_time; + XIC xic; }; typedef sync_extension::kernel_1a>::kernel_1a @@ -44,11 +47,12 @@ namespace dlib int depth; Display* disp; + XIM xim; static Screen* screen; Atom delete_window; static Window exit_window; - static std::string clipboard; + static std::wstring clipboard; static bool core_has_been_initialized = false; static int alt_mask = 0; @@ -369,13 +373,28 @@ namespace dlib bool quit_event_loop = false; while (quit_event_loop == false) { - XEvent ev; - XNextEvent(disp,&ev); - - // get a lock on the window_table's mutex auto_mutex window_table_locker(window_table.get_mutex()); + XEvent ev; + while (XPending(disp) == 0){ + window_table.get_mutex().unlock(); + // wait until receiving X11 next event + struct pollfd pfd; + pfd.fd = ConnectionNumber(disp); + pfd.events = POLLIN | POLLPRI; + poll(&pfd, 1, -1); + + window_table.get_mutex().lock(); + } + XNextEvent(disp,&ev); + + // pass events to input method. + // if this event is needed by input method, XFilterEvent returns True + if (XFilterEvent(&ev, None) == True){ + continue; + } + // if this event is for one of the windows in the window_table // then get that window out of the table and put it into win. XAnyEvent* _ae = reinterpret_cast(&ev); @@ -398,6 +417,7 @@ namespace dlib case SelectionRequest: { + Atom a_ct = XInternAtom(disp, "COMPOUND_TEXT", False); XSelectionRequestEvent* req = reinterpret_cast(&ev.xselectionrequest); XEvent respond; @@ -409,6 +429,18 @@ namespace dlib XA_STRING, 8, PropModeReplace, + reinterpret_cast(convert_wstring_to_mbstring(clipboard).c_str()), + clipboard.size()+1); + respond.xselection.property=req->property; + } + else if (req->target == a_ct) + { + XChangeProperty (disp, + req->requestor, + req->property, + a_ct, + sizeof(wchar_t)*8, + PropModeReplace, reinterpret_cast(clipboard.c_str()), clipboard.size()+1); respond.xselection.property=req->property; @@ -494,17 +526,30 @@ namespace dlib if((e->state & scroll_lock_mask)!=0) state |= base_window::KBD_MOD_SCROLL_LOCK; - char buffer[2]; KeySym key; - XLookupString(e,buffer,2,&key,NULL); + Status status; - bool is_printable; - unsigned long result; + std::wstring wstr; + wstr.resize(2); + int len = XwcLookupString(win->x11_stuff.xic,e,&wstr[0],wstr.size(),&key,&status); + if (status == XBufferOverflow){ + wstr.resize(len); + len = XwcLookupString(win->x11_stuff.xic,e,&wstr[0],wstr.size(),&key,&status); + } + if (status == XLookupChars){ + win->on_string_put(wstr); + } - if (map_keys(key,shift,caps,result,is_printable)) - { - // signal the keyboard event - win->on_keydown(result,is_printable,state); + else if (status == XLookupKeySym || status == XLookupBoth){ + + bool is_printable; + unsigned long result; + + if (map_keys(key,shift,caps,result,is_printable)) + { + // signal the keyboard event + win->on_keydown(result,is_printable,state); + } } } break; @@ -1009,6 +1054,9 @@ namespace dlib using namespace gui_core_kernel_2_globals; try { + +/* + // causes dead-lock when using with XIM if (XInitThreads() == 0) { dlog << LFATAL << "Unable to initialize threading support."; @@ -1019,12 +1067,16 @@ namespace dlib window_table.get_mutex().unlock(); return; } +*/ - + window_table.get_mutex().lock(); disp = XOpenDisplay(NULL); + window_table.get_mutex().unlock(); if (disp == 0) { + window_table.get_mutex().lock(); disp = XOpenDisplay(":0.0"); + window_table.get_mutex().unlock(); if (disp == 0) { dlog << LFATAL << "Unable to connect to the X display."; @@ -1037,14 +1089,23 @@ namespace dlib } } + window_table.get_mutex().lock(); screen = DefaultScreenOfDisplay(disp); depth = DefaultDepthOfScreen(screen); delete_window = XInternAtom(disp,"WM_DELETE_WINDOW",1); + window_table.get_mutex().unlock(); + xim = NULL; + window_table.get_mutex().lock(); + if (setlocale( LC_CTYPE, "" ) && XSupportsLocale() && XSetLocaleModifiers("")){ + xim = XOpenIM(disp, NULL, NULL, NULL); + } + window_table.get_mutex().unlock(); // make this window just so we can send messages to it and trigger // events in the event thread XSetWindowAttributes attr; + window_table.get_mutex().lock(); exit_window = XCreateWindow( disp, DefaultRootWindow(disp), @@ -1059,6 +1120,7 @@ namespace dlib 0, &attr ); + window_table.get_mutex().unlock(); // signal that the event thread is now up and running window_table.get_mutex().lock(); @@ -1203,6 +1265,20 @@ namespace dlib void put_on_clipboard ( const std::string& str ) + { + put_on_clipboard(convert_mbstring_to_wstring(str)); + } + + void put_on_clipboard ( + const dlib::ustring& str + ) + { + put_on_clipboard(convert_utf32_to_wstring(str)); + } + + void put_on_clipboard ( + const std::wstring& str + ) { using namespace gui_core_kernel_2_globals; init_gui_core(); @@ -1234,12 +1310,31 @@ namespace dlib void get_from_clipboard ( std::string& str ) + { + std::wstring wstr; + get_from_clipboard(wstr); + str = convert_wstring_to_mbstring(wstr); + } + + void get_from_clipboard ( + dlib::ustring& str + ) + { + std::wstring wstr; + get_from_clipboard(wstr); + str = convert_wstring_to_utf32(wstr); + } + + void get_from_clipboard ( + std::wstring& str + ) { using namespace gui_core_kernel_2_globals; init_gui_core(); auto_mutex M(window_table.get_mutex()); str.clear(); unsigned char *data = 0; + wchar_t **plist = 0; Window sown; Atom type; int format, result; @@ -1248,6 +1343,7 @@ namespace dlib try { + Atom atom_ct = XInternAtom(disp, "COMPOUND_TEXT", False); sown = XGetSelectionOwner (disp, XA_PRIMARY); if (sown == exit_window) { @@ -1261,7 +1357,7 @@ namespace dlib // of the exit_window. It doesn't matter what window we put it in // so long as it is one under the control of this process and exit_window // is easy to use here so that is what I'm using. - XConvertSelection (disp, XA_PRIMARY, XA_STRING, XA_PRIMARY, + XConvertSelection (disp, XA_PRIMARY, atom_ct, XA_PRIMARY, exit_window, CurrentTime); // This will wait until we get a SelectionNotify event which should happen @@ -1283,20 +1379,23 @@ namespace dlib XFree(data); data = 0; } - if (bytes_left > 0 && type == XA_STRING) + if (bytes_left > 0 && type == atom_ct) { + XTextProperty p; result = XGetWindowProperty (disp, exit_window, XA_PRIMARY, 0,bytes_left,0, - AnyPropertyType, &type,&format, - &len, &dummy, &data); - if (result == Success && type == XA_STRING) + AnyPropertyType, &p.encoding,&p.format, + &p.nitems, &dummy, &p.value); + if (result == Success && p.encoding == atom_ct) { - str = (char*)data; + int n; + XwcTextPropertyToTextList(disp, &p, &plist, &n); + str = plist[0]; } - if (data) + if (plist) { - XFree(data); - data = 0; + XwcFreeStringList(plist); + plist = 0; } } } @@ -1305,6 +1404,11 @@ namespace dlib { if (data) XFree(data); + if (plist) + { + XwcFreeStringList(plist); + plist = 0; + } } } @@ -1421,16 +1525,31 @@ namespace dlib &attr ); + x11_stuff.xic = NULL; + if (gui_core_kernel_2_globals::xim) + { + x11_stuff.xic = XCreateIC( + gui_core_kernel_2_globals::xim, + XNInputStyle, XIMPreeditNothing | XIMStatusNothing, + XNClientWindow, x11_stuff.hwnd, + NULL + ); + } + Window temp = x11_stuff.hwnd; base_window* ttemp = this; gui_core_kernel_2_globals::window_table.add(temp,ttemp); + // query event mask required by input method + unsigned long event_xim = 0; + XGetICValues( x11_stuff.xic, XNFilterEvents, &event_xim, NULL ); + XSelectInput( gui_core_kernel_2_globals::disp, x11_stuff.hwnd, StructureNotifyMask|ExposureMask|ButtonPressMask|ButtonReleaseMask| PointerMotionMask|LeaveWindowMask|EnterWindowMask|KeyPressMask| - KeyReleaseMask| FocusChangeMask + KeyReleaseMask| FocusChangeMask | event_xim ); XSetWMProtocols( @@ -1483,6 +1602,9 @@ namespace dlib gui_core_kernel_2_globals::window_table.destroy(x11_stuff.hwnd); + XDestroyIC(x11_stuff.xic); + x11_stuff.xic = 0; + XDestroyWindow(gui_core_kernel_2_globals::disp,x11_stuff.hwnd); x11_stuff.hwnd = 0; gui_core_kernel_2_globals::window_close_signaler.broadcast(); @@ -1506,6 +1628,23 @@ namespace dlib const std::string& title_ ) { + set_title(convert_mbstring_to_wstring(title_)); + } + + void base_window:: + set_title ( + const ustring& title_ + ) + { + set_title(convert_utf32_to_wstring(title_)); + } + + void base_window:: + set_title ( + const std::wstring& title_ + ) + { + auto_mutex M(wm); DLIB_ASSERT(is_closed() == false, "\tvoid base_window::set_title" << "\n\tYou can't do this to a window that has been closed." @@ -1513,9 +1652,9 @@ namespace dlib ); // I'm pretty sure the pointer won't be modified even though // it isn't const anymore. - char *title = const_cast(title_.c_str()); + wchar_t *title = const_cast(title_.c_str()); XTextProperty property; - XStringListToTextProperty(&title,1,&property); + XwcTextListToTextProperty(gui_core_kernel_2_globals::disp,&title,1,XStdICCTextStyle, &property); XSetWMName(gui_core_kernel_2_globals::disp,x11_stuff.hwnd,&property); XFree(property.value); XFlush(gui_core_kernel_2_globals::disp); @@ -1527,6 +1666,7 @@ namespace dlib show ( ) { + auto_mutex M(wm); DLIB_ASSERT(is_closed() == false, "\tvoid base_window::show" << "\n\tYou can't do this to a window that has been closed." @@ -1553,6 +1693,7 @@ namespace dlib hide ( ) { + auto_mutex M(wm); DLIB_ASSERT(is_closed() == false, "\tvoid base_window::hide" << "\n\tYou can't do this to a window that has been closed." diff --git a/dlib/gui_core/gui_core_kernel_2.h b/dlib/gui_core/gui_core_kernel_2.h index a525a49c2..5959a41b8 100644 --- a/dlib/gui_core/gui_core_kernel_2.h +++ b/dlib/gui_core/gui_core_kernel_2.h @@ -1,4 +1,4 @@ -// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net) +// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), Keita Mochizuki // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_GUI_CORE_KERNEl_2_ #define DLIB_GUI_CORE_KERNEl_2_ @@ -21,6 +21,7 @@ #include "../binary_search_tree.h" #include #include "../pixel.h" +#include "../unicode.h" namespace dlib @@ -46,12 +47,28 @@ namespace dlib const std::string& str ); + void put_on_clipboard ( + const std::wstring& str + ); + + void put_on_clipboard ( + const dlib::ustring& str + ); + // ---------------------------------------------------------------------------------------- void get_from_clipboard ( std::string& str ); + void get_from_clipboard ( + std::wstring& str + ); + + void get_from_clipboard ( + dlib::ustring& str + ); + // ---------------------------------------------------------------------------------------- class canvas : public rectangle @@ -252,6 +269,14 @@ namespace dlib const std::string& title_ ); + void set_title ( + const std::wstring& title_ + ); + + void set_title ( + const dlib::ustring& title_ + ); + virtual void show ( ); @@ -352,6 +377,10 @@ namespace dlib unsigned long state ){} + virtual void on_string_put ( + const std::wstring &str + ){} + private: virtual void paint ( diff --git a/dlib/gui_core/gui_core_kernel_abstract.h b/dlib/gui_core/gui_core_kernel_abstract.h index c79c37b80..8aaffac70 100644 --- a/dlib/gui_core/gui_core_kernel_abstract.h +++ b/dlib/gui_core/gui_core_kernel_abstract.h @@ -1,4 +1,4 @@ -// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net) +// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), Keita Mochizuki // License: Boost Software License See LICENSE.txt for the full license. #undef DLIB_GUI_CORE_KERNEl_ABSTRACT_ #ifdef DLIB_GUI_CORE_KERNEl_ABSTRACT_ @@ -6,6 +6,7 @@ #include #include "../algs.h" #include "../geometry/rectangle_abstract.h" +#include "../unicode/unicode_abstract.h" namespace dlib { @@ -61,6 +62,10 @@ namespace dlib - dlib::thread_error !*/ + // overloads for wide character strings + void put_on_clipboard (const std::wstring& str); + void put_on_clipboard (const dlib::ustring& str); + // ---------------------------------------------------------------------------------------- void get_from_clipboard ( @@ -78,6 +83,10 @@ namespace dlib - dlib::thread_error !*/ + // overloads for wide character strings + void get_from_clipboard (std::wtring& str); + void get_from_clipboard (dlib::utring& str); + // ---------------------------------------------------------------------------------------- @@ -356,6 +365,26 @@ namespace dlib - sets the title of the window !*/ + void set_title ( + const std::wstring& title + ); + /*! + requires + - is_closed() == false + ensures + - sets the title of the window + !*/ + + void set_title ( + const dlib::ustring& title + ); + /*! + requires + - is_closed() == false + ensures + - sets the title of the window + !*/ + virtual void show ( ); /*! @@ -708,6 +737,20 @@ namespace dlib - does not change the state of mutex wm !*/ + virtual void on_string_put ( + const std::wstring &str + ){} + /*! + requires + - is_closed() == false + - mutex wm is locked + - is called when a wide/multibyte character input method determines a string + that is being input to the window. + - str == the string that is being input + ensures + - does not change the state of mutex wm + !*/ + private: virtual void paint ( diff --git a/dlib/gui_widgets/base_widgets.cpp b/dlib/gui_widgets/base_widgets.cpp index 37cc6d175..1f0868dc7 100644 --- a/dlib/gui_widgets/base_widgets.cpp +++ b/dlib/gui_widgets/base_widgets.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net) +// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), Keita Mochizuki // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_BASE_WIDGETs_CPP_ #define DLIB_BASE_WIDGETs_CPP_ diff --git a/dlib/gui_widgets/base_widgets.h b/dlib/gui_widgets/base_widgets.h index f21725af0..7d1491bbc 100644 --- a/dlib/gui_widgets/base_widgets.h +++ b/dlib/gui_widgets/base_widgets.h @@ -1,4 +1,4 @@ -// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net) +// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), Keita Mochizuki // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_BASE_WIDGETs_ @@ -16,6 +16,7 @@ #include "../image_transforms.h" #include "../array.h" #include "../smart_pointers.h" +#include "../unicode.h" #include @@ -981,6 +982,20 @@ namespace dlib void set_text ( const std::string& str ) + { + set_text(convert_mbstring_to_wstring(str)); + } + + void set_text ( + const std::wstring& str + ) + { + set_text(convert_wstring_to_utf32(str)); + } + + void set_text ( + const ustring& str + ) { auto_mutex M(m); if (!stuff) @@ -994,9 +1009,21 @@ namespace dlib const std::string text ( ) const + { + return convert_wstring_to_mbstring(wtext()); + } + + const std::wstring wtext ( + ) const + { + return convert_utf32_to_wstring(utext()); + } + + const dlib::ustring utext ( + ) const { auto_mutex M(m); - std::string temp; + dlib::ustring temp; if (stuff) { temp = stuff->win.text; @@ -1067,15 +1094,29 @@ namespace dlib { } - std::string text; + ustring text; rectangle rect_all; rectangle rect_text; const unsigned long pad; const font* mfont; - + void set_text ( const std::string& str ) + { + set_text(convert_mbstring_to_wstring(str)); + } + + void set_text ( + const std::wstring& str + ) + { + set_text(convert_wstring_to_utf32(str)); + } + + void set_text ( + const dlib::ustring& str + ) { text = str.c_str(); @@ -1227,15 +1268,11 @@ namespace dlib class menu_item_submenu : public menu_item { - public: - menu_item_submenu ( - const std::string& str, - unichar hk = 0 - ) : - text(str), - f(default_font::get_font()), - hotkey(hk) + void initialize ( + unichar hk + ) { + const dlib::ustring &str = text; if (hk != 0) { std::string::size_type pos = str.find_first_of(hk); @@ -1252,6 +1289,39 @@ namespace dlib } } } + public: + menu_item_submenu ( + const std::string& str, + unichar hk = 0 + ) : + text(convert_wstring_to_utf32(convert_mbstring_to_wstring(str))), + f(default_font::get_font()), + hotkey(hk) + { + initialize(hk); + } + + menu_item_submenu ( + const std::wstring& str, + unichar hk = 0 + ) : + text(convert_wstring_to_utf32(str)), + f(default_font::get_font()), + hotkey(hk) + { + initialize(hk); + } + + menu_item_submenu ( + const dlib::ustring& str, + unichar hk = 0 + ) : + text(str), + f(default_font::get_font()), + hotkey(hk) + { + initialize(hk); + } virtual unichar get_hot_key ( ) const { return hotkey; } @@ -1337,7 +1407,7 @@ namespace dlib } private: - std::string text; + dlib::ustring text; const font* f; member_function_pointer<>::kernel_1a action; unichar hotkey; @@ -1349,18 +1419,14 @@ namespace dlib class menu_item_text : public menu_item { - public: template - menu_item_text ( - const std::string& str, - T& object, + void initialize ( + T &object, void (T::*event_handler_)(), - unichar hk = 0 - ) : - text(str), - f(default_font::get_font()), - hotkey(hk) + unichar hk + ) { + dlib::ustring &str = text; action.set(object,event_handler_); if (hk != 0) @@ -1380,6 +1446,49 @@ namespace dlib } } + public: + template + menu_item_text ( + const std::string& str, + T& object, + void (T::*event_handler_)(), + unichar hk = 0 + ) : + text(convert_wstring_to_utf32(convert_mbstring_to_wstring(str))), + f(default_font::get_font()), + hotkey(hk) + { + initialize(object, event_handler_, hk); + } + + template + menu_item_text ( + const std::wstring& str, + T& object, + void (T::*event_handler_)(), + unichar hk = 0 + ) : + text(convert_wstring_to_utf32(str)), + f(default_font::get_font()), + hotkey(hk) + { + initialize(object, event_handler_, hk); + } + + template + menu_item_text ( + const dlib::ustring& str, + T& object, + void (T::*event_handler_)(), + unichar hk = 0 + ) : + text(str), + f(default_font::get_font()), + hotkey(hk) + { + initialize(object, event_handler_, hk); + } + virtual unichar get_hot_key ( ) const { return hotkey; } @@ -1444,7 +1553,7 @@ namespace dlib ) const { return true; } private: - std::string text; + dlib::ustring text; const font* f; member_function_pointer<>::kernel_1a action; unichar hotkey; diff --git a/dlib/gui_widgets/base_widgets_abstract.h b/dlib/gui_widgets/base_widgets_abstract.h index 5f2b5d8d0..a5db964e9 100644 --- a/dlib/gui_widgets/base_widgets_abstract.h +++ b/dlib/gui_widgets/base_widgets_abstract.h @@ -1,4 +1,4 @@ -// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net) +// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), Keita Mochizuki // License: Boost Software License See LICENSE.txt for the full license. #undef DLIB_BASE_WIDGETs_ABSTRACT_ #ifdef DLIB_BASE_WIDGETs_ABSTRACT_ @@ -907,6 +907,15 @@ namespace dlib will display on the screen when the user hovers the mouse over it !*/ + // overloads for wide character strings + void set_text ( + const std::wstring& str + ); + + void set_text ( + const dlib::ustring& str + ); + const std::string text ( ) const; /*! @@ -915,6 +924,22 @@ namespace dlib tooltip !*/ + const std::wstring wtext ( + ) const; + /*! + ensures + - returns the text that is displayed inside this + tooltip + !*/ + + const dlib::ustring utext ( + ) const; + /*! + ensures + - returns the text that is displayed inside this + tooltip + !*/ + private: // restricted functions @@ -1102,6 +1127,27 @@ namespace dlib clicked by the user. - #get_hot_key() == hotkey !*/ + + // overloads for wide charactor strings + template < + typename T + > + menu_item_text ( + const std::wstring& str, + T& object, + void (T::*on_click_handler)(), + unichar hotkey = 0 + ); + + template < + typename T + > + menu_item_text ( + const dlib::ustring& str, + T& object, + void (T::*on_click_handler)(), + unichar hotkey = 0 + ); }; // ---------------------------------------------------------------------------------------- @@ -1126,6 +1172,17 @@ namespace dlib clicked by the user. - #get_hot_key() == hotkey !*/ + + //overloads for wide charactor strings + menu_item_submenu ( + const std::wstring& str, + unichar hotkey = 0 + ); + + menu_item_submenu ( + const dlib::ustring& str, + unichar hotkey = 0 + ); }; // ---------------------------------------------------------------------------------------- diff --git a/dlib/gui_widgets/drawable.cpp b/dlib/gui_widgets/drawable.cpp index 7618b7092..8ee39485f 100644 --- a/dlib/gui_widgets/drawable.cpp +++ b/dlib/gui_widgets/drawable.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net) +// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), Keita Mochizuki // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_DRAWABLe_CPP_ #define DLIB_DRAWABLe_CPP_ @@ -330,6 +330,25 @@ namespace dlib } } +// ---------------------------------------------------------------------------------------- + + void drawable_window:: + on_string_put ( + const std::wstring &str + ) + { + ++event_id; + string_put.reset(); + while (string_put.move_next()) + { + if (string_put.element()->event_id != event_id) + { + string_put.element()->event_id = event_id; + string_put.element()->on_string_put(str); + } + } + } + // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // ----------- drawable object ---------------------------------------------------------- @@ -399,6 +418,11 @@ namespace dlib temp = this; parent.window_moved.add(temp); } + if (events & STRING_PUT) + { + temp = this; + parent.string_put.add(temp); + } parent.invalidate_rectangle(rect); } } @@ -481,6 +505,8 @@ namespace dlib parent.focus.remove(this,junk); if (events & WINDOW_MOVED) parent.window_moved.remove(this,junk); + if (events & STRING_PUT) + parent.string_put.remove(this,junk); } } diff --git a/dlib/gui_widgets/drawable.h b/dlib/gui_widgets/drawable.h index ee3e722d4..130a91736 100644 --- a/dlib/gui_widgets/drawable.h +++ b/dlib/gui_widgets/drawable.h @@ -1,4 +1,4 @@ -// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net) +// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), Keita Mochizuki // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_DRAWABLe_ @@ -149,6 +149,10 @@ namespace dlib unsigned long state ); + void on_string_put ( + const std::wstring &str + ); + void on_user_event ( void* p, int i @@ -173,6 +177,7 @@ namespace dlib set_of_drawables keyboard; set_of_drawables focus; set_of_drawables window_moved; + set_of_drawables string_put; long lastx, lasty; unsigned long event_id; @@ -201,7 +206,8 @@ namespace dlib WINDOW_RESIZED = 8, KEYBOARD_EVENTS = 16, FOCUS_EVENTS = 32, - WINDOW_MOVED = 64 + WINDOW_MOVED = 64, + STRING_PUT = 128 }; class drawable @@ -496,6 +502,10 @@ namespace dlib bool is_printable, unsigned long state ){} + + virtual void on_string_put ( + const std::wstring &str + ){} }; // ---------------------------------------------------------------------------------------- diff --git a/dlib/gui_widgets/drawable_abstract.h b/dlib/gui_widgets/drawable_abstract.h index 3adba7964..1c22c2af6 100644 --- a/dlib/gui_widgets/drawable_abstract.h +++ b/dlib/gui_widgets/drawable_abstract.h @@ -132,7 +132,8 @@ namespace dlib WINDOW_RESIZED = 8, KEYBOARD_EVENTS = 16, FOCUS_EVENTS = 32, - WINDOW_MOVED = 64 + WINDOW_MOVED = 64, + STRING_PUT = 128 }; class drawable @@ -665,6 +666,19 @@ namespace dlib - does not change the state of mutex m. !*/ + virtual void on_string_put ( + const std::wstring &str + ){} + /*! + requires + - events_are_enabled() == true + - mutex m is locked + - this is just the base_window::on_put_string() event forwarded to + this object. See the gui_core specs for the details about this event. + ensures + - does not change the state of mutex m. + !*/ + virtual void draw ( const canvas& c ) const=0; diff --git a/dlib/gui_widgets/fonts.cpp b/dlib/gui_widgets/fonts.cpp index 5b818956b..e029bef1a 100644 --- a/dlib/gui_widgets/fonts.cpp +++ b/dlib/gui_widgets/fonts.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), and Nils Labugt +// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), and Nils Labugt, Keita Mochizuki // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_FONTs_CPP_ #define DLIB_FONTs_CPP_ @@ -11,6 +11,7 @@ #include "../compress_stream.h" #include #include "../tokenizer.h" +#include "nativefont.h" namespace dlib { @@ -657,6 +658,14 @@ namespace dlib return true; } +// ---------------------------------------------------------------------------------------- + + const font* get_native_font ( + ) + { + return nativefont::native_font::get_font(); + } + // ---------------------------------------------------------------------------------------- } diff --git a/dlib/gui_widgets/fonts.h b/dlib/gui_widgets/fonts.h index 9c60bc37e..691f0e6cd 100644 --- a/dlib/gui_widgets/fonts.h +++ b/dlib/gui_widgets/fonts.h @@ -1,4 +1,4 @@ -// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), and Nils Labugt +// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), and Nils Labugt, Keita Mochizuki // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_FONTs_ @@ -475,6 +475,10 @@ namespace dlib }; +// ---------------------------------------------------------------------------------------- + + const font* get_native_font (); + // ---------------------------------------------------------------------------------------- class default_font : public font diff --git a/dlib/gui_widgets/fonts_abstract.h b/dlib/gui_widgets/fonts_abstract.h index 58f3de938..db89dfaed 100644 --- a/dlib/gui_widgets/fonts_abstract.h +++ b/dlib/gui_widgets/fonts_abstract.h @@ -1,6 +1,5 @@ -// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), and Nils Labugt +// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), Nils Labugt, Keita Mochizuki // License: Boost Software License See LICENSE.txt for the full license. - #undef DLIB_FONTs_ABSTRACT_ #ifdef DLIB_FONTs_ABSTRACT_ @@ -379,7 +378,7 @@ namespace dlib { /*! WHAT THIS OBJECT REPRESENTS - This is an implementation of the Times New Roman font. + This is an implementation of the Helvetica 12 point font. THREAD SAFETY It is safe to call get_font() and access the returned font from any @@ -478,6 +477,15 @@ namespace dlib }; +// ---------------------------------------------------------------------------------------- + + font* get_native_font ( + ); + /*! + ensures + - returns a font object that uses the local font + !*/ + // ---------------------------------------------------------------------------------------- } diff --git a/dlib/gui_widgets/nativefont.h b/dlib/gui_widgets/nativefont.h new file mode 100644 index 000000000..ddae2308c --- /dev/null +++ b/dlib/gui_widgets/nativefont.h @@ -0,0 +1,600 @@ +// Copyright (C) 2006 Keita Mochizuki +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_IGG_FONT_RENDERER_H_ +#define DLIB_IGG_FONT_RENDERER_H_ + +#include "../gui_widgets.h" +#include "../unicode.h" + +#include + +#include +#include +#include +#include + +#ifdef WIN32 +#include +#include +#else +#include +#include +#include +#include +#include +#include +#endif + +namespace nativefont +{ +// ---------------------------------------------------------------------------------------- + + namespace font_renderer + { +#if defined(WIN32) && !defined(__MINGW32__) + typedef BYTE uint8_t; + typedef WORD uint16_t; + typedef DWORD uint32_t; +#endif + typedef uint8_t byte; + + +#ifdef WIN32 + template struct input2native_trait{ + }; + template <> struct input2native_trait{ + typedef char type_t; + }; + template <> struct input2native_trait{ + typedef wchar_t type_t; + }; + template <> struct input2native_trait{ + typedef wchar_t type_t; + }; +#endif + // T : N : sizeof_source_type + template struct size2inner_trait{ + }; + template <> struct size2inner_trait<1>{ + typedef char type_t; + }; + template <> struct size2inner_trait<2>{ + typedef uint16_t type_t; + }; + template <> struct size2inner_trait<4>{ + typedef dlib::unichar type_t; + }; + + +// ---------------------------------------------------------------------------------------- + + template struct create_helper{ }; + template <> struct create_helper<1>{ + typedef char type_t; + type_t *istr; + int len; + create_helper(char *str){ + len = (int)strlen(str); + istr = str; + } + ~create_helper(){} + }; + template <> struct create_helper<2>{ + typedef wchar_t type_t; + type_t *istr; + bool allocated; + int len; + create_helper(wchar_t *str){ + allocated = false; + len = (int)wcslen(str); + istr = str; + } + create_helper(dlib::unichar *str){ + allocated = true; + len = 0; + int unicount = 0; + dlib::unichar *p = str; + while(*p){ + if (*p > 0xffff){ + len += 2; + }else{ + len++; + } + unicount++; + p++; + } + istr = new wchar_t[len+1]; + for (int i = 0, wi = 0; i < unicount; ++i){ + dlib::unichar high, low; + if (str[i] > 0xffff){ + dlib::unichar_to_surrogate_pair(str[i], high, low); + istr[wi] = (wchar_t)high, istr[wi+1] = (wchar_t)low; + wi += 2; + }else{ + istr[wi] = (wchar_t)str[i]; + wi += 1; + } + } + istr[len] = L'\0'; + // printf("unicount:%d, len:%d wcslen:%d\n", unicount, len, wcslen(istr)); + } + + ~create_helper(){ + if (allocated) delete[] istr; + } + }; + template <> struct create_helper<4>{ + typedef wchar_t type_t; + type_t *istr; + int len; + create_helper(dlib::unichar *str){ + len = (int)wcslen((wchar_t *)str); + istr = (type_t *)str; + // printf("len:%d\n", len); + } + ~create_helper(){} + }; + +// ---------------------------------------------------------------------------------------- + + class font_renderer{ + public: + + struct rgb_type{ + byte r, g, b; + rgb_type() : r(0), g(0), b(0){}; + rgb_type(byte r_, byte g_, byte b_) : r(r_), g(g_), b(b_){}; + }; + private: + + byte *image; + int width, height; + void destroy(){ + width = height = 0; + delete image; + image = 0; + } + struct vals_internal{ + int width, height; +#ifdef WIN32 + COLORREF rgb2RGB(rgb_type &rgb){ + return RGB(rgb.r, rgb.g, rgb.b); + } + HBITMAP hBmp, hBmpOld; + HDC hDCBmp; + BYTE *pixelint; + HFONT hFont, hFontOld; + HBRUSH hBrush; + int pix_width_prev, pix_height_prev; + bool first; + int ascender, descender; + int height_prev; + char attribute_prev; + + template void create(T *str, int height_want, bool italic, bool bold, bool fixed, rgb_type &background, rgb_type &foreground){ + struct inner{ + inline static BOOL GetTextExtentPoint32(HDC hDC, LPCSTR str, int len, LPSIZE lpsize){ + return ::GetTextExtentPoint32A(hDC, str, len, lpsize); + } + inline static BOOL GetTextExtentPoint32(HDC hDC, LPCWSTR str, int len, LPSIZE lpsize){ + return ::GetTextExtentPoint32W(hDC, str, len, lpsize); + } + inline static BOOL TextOut(HDC hDC, int nxstart, int nystart, LPCSTR str, int cbstr){ + return ::TextOutA(hDC, nxstart, nystart, str, cbstr); + } + inline static BOOL TextOut(HDC hDC, int nxstart, int nystart, LPCWSTR str, int cbstr){ + return ::TextOutW(hDC, nxstart, nystart, str, cbstr); + } + }; + + create_helper::type_t)> ch(str); + + if (hDCBmp == NULL){ + HWND hWnd = GetDesktopWindow(); + HDC hDC = GetDC(hWnd); + hDCBmp = CreateCompatibleDC(hDC); + ReleaseDC(hWnd, hDC); + } + SetTextColor(hDCBmp, rgb2RGB(foreground)); + SetBkColor(hDCBmp, rgb2RGB(background)); + + char attribute = (italic ? 1 : 0) | (bold ? 2 : 0) | (fixed ? 4 : 0); + if (!hFont || height_prev != height || attribute != attribute_prev){ + attribute_prev = attribute; + height_prev = height_want; + if (hFont){ + SelectObject(hDCBmp, hFontOld); + DeleteObject(hFont); + } + hFont = CreateFont(height_want, 0, 0, 0, bold ? FW_BOLD : FW_DONTCARE, italic ? TRUE : FALSE, + FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + fixed ? (FIXED_PITCH | FF_DONTCARE) : (VARIABLE_PITCH | FF_DONTCARE), NULL); + hFontOld = (HFONT)SelectObject(hDCBmp, hFont); + } + + { + SIZE sz; + inner::GetTextExtentPoint32(hDCBmp, ch.istr, ch.len, &sz); + width = ((sz.cx + 3) / 4) * 4; + height = sz.cy; + } + + if (pix_width_prev < width || pix_height_prev < height){ + if (hBmp){ + SelectObject(hDCBmp, hBmpOld); + DeleteObject(hBmp); + } + pix_width_prev = width * 2; + pix_height_prev = height * 2; + BITMAPINFO bi; + ZeroMemory(&bi, sizeof(bi)); + bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biBitCount = 24; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biWidth = pix_width_prev; + bi.bmiHeader.biHeight = -pix_height_prev; + hBmp = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void **)&pixelint, NULL, 0); + hBmpOld = (HBITMAP)SelectObject(hDCBmp, hBmp); + } + + { + HBRUSH hBrush = CreateSolidBrush(rgb2RGB(background)); + RECT rc; + rc.left = rc.top = 0; + rc.right = pix_width_prev; + rc.bottom = pix_height_prev; + FillRect(hDCBmp, &rc, hBrush); + } + + inner::TextOut(hDCBmp, 0, 0, ch.istr, ch.len); + TEXTMETRICW tm; + GetTextMetricsW(hDCBmp,&tm); + ascender = tm.tmAscent; + descender = tm.tmDescent; + } + + template vals_internal(T *str, int height_want, bool italic = false, + bool bold = false, bool fixed = false, rgb_type background = rgb_type(), rgb_type foreground = rgb_type()){ + first = true; + hFont = NULL; + hDCBmp = 0; + hBmpOld = 0; + hBmp = 0; + hDCBmp = 0; + pixelint = 0; + pix_width_prev = pix_height_prev = 0; + height_prev = -1; + attribute_prev = 0; + create(str, height_want, italic, bold, fixed, background, foreground); + first = false; + } + + inline int get_ascender(){ + return ascender; + } + + inline int get_descender(){ + return descender; + } + + inline void get_pixel(int x, int y, byte &r, byte &g, byte &b){ + byte *p = pixelint + (y * pix_width_prev + x) * 3; + r = *(p+2), g = *(p+1), b = *p; + } + + void destroy(){ + SelectObject(hDCBmp, hBmpOld); + DeleteObject(hBmp); + SelectObject(hDCBmp, hFontOld); + DeleteObject(hFont); + DeleteDC(hDCBmp); + hFont = NULL; + hDCBmp = 0; + hBmpOld = 0; + hBmp = 0; + hDCBmp = 0; + pixelint = 0; + } + ~vals_internal(){ + destroy(); + } +#else + XImage *ximg; + Display *d; + GC gc; + XFontSet fs; + Pixmap pix; + Colormap cmap; + int ascender, descender; + int pix_width_prev, pix_height_prev; + char fontset_prev[256]; + unsigned long rgb2color(rgb_type col, Display *d, Colormap &cmap){ + XColor xcol; + xcol.red = col.r * 257; + xcol.green = col.g * 257; + xcol.blue = col.b * 257; + XAllocColor(d, cmap, &xcol); + return xcol.pixel; + } + template void create(T *str, int height_want, bool italic, bool bold, bool fixed, rgb_type background, rgb_type foreground){ + struct inner{ + inline static int XTextExtents (XFontSet fs, char *str, int len, XRectangle *ink, XRectangle *logical){ + return XmbTextExtents(fs, str, len, ink, logical); + } + inline static int XTextExtents (XFontSet fs, wchar_t *str, int len, XRectangle *ink, XRectangle *logical){ + return XwcTextExtents(fs, str, len, ink, logical); + } + inline static void XDrawString(Display *d, Window w, XFontSet fs, GC gc, int x, int y, char *str, int num_bytes){ + XmbDrawString(d, w, fs, gc, x, y, str, num_bytes); + } + inline static void XDrawString(Display *d, Window w, XFontSet fs, GC gc, int x, int y, wchar_t *str, int num_bytes){ + XwcDrawString(d, w, fs, gc, x, y, str, num_bytes); + } + }; + create_helper ch((typename size2inner_trait::type_t *)str); + setlocale(LC_CTYPE, ""); + if (d == NULL){ + d = XOpenDisplay(NULL); + cmap = DefaultColormap(d, DefaultScreen(d)); + } + char fontset[256]; + { + char *p = fontset; + p += sprintf(fontset, "-*-*-%s-%c-normal--%d-*-*-*-%c", + bold ? "bold" : "medium", italic ? 'i' : 'r', height_want, fixed ? 'c' : 'p'); + if (fixed){ + sprintf(p, ",-*-*-%s-%c-normal--%d-*-*-*-m", + bold ? "bold" : "medium", italic ? 'i' : 'r', height_want); + } + } + bool equal_font; + if (strcmp(fontset, fontset_prev) == 0){ + equal_font = true; + }else{ + equal_font = false; + strcpy(fontset_prev, fontset); + } + + char **mlist; + int mcount; + char *def_str; + if (!equal_font){ + if (fs){ + XFreeFontSet(d, fs); + } + fs = XCreateFontSet(d, fontset, &mlist, &mcount, &def_str); + + XFontSetExtents *extent; + extent = XExtentsOfFontSet(fs); + ascender = -extent->max_logical_extent.y; + descender = extent->max_logical_extent.height - ascender; + XFreeStringList(mlist); + } + XRectangle ink, logical; + inner::XTextExtents (fs, ch.istr, ch.len, &ink, &logical); + width = logical.width; + height = height_want; + + if (pix == None || pix_width_prev < width || pix_height_prev < height){ + if (pix != None){ + XFreeGC(d, gc); + XFreePixmap(d, pix); + } + pix_width_prev = width * 2; + pix_height_prev = height * 2; + pix = XCreatePixmap(d, DefaultRootWindow(d), pix_width_prev, pix_height_prev, XDefaultDepth(d, DefaultScreen(d))); + gc = XCreateGC(d, pix, 0, NULL); + } + + unsigned long backcolor = rgb2color(background, d, cmap); + XSetForeground(d, gc, backcolor); + XSetBackground(d, gc, backcolor); + XFillRectangle(d, pix, gc, 0, 0, width, height); + XSetForeground(d, gc, rgb2color(foreground, d, cmap)); + inner::XDrawString(d, pix, fs, gc, 0, ascender, ch.istr, ch.len); + + if (ximg) XDestroyImage(ximg); + ximg = XGetImage(d, pix, 0, 0, width, height, AllPlanes, ZPixmap ); + } + + template vals_internal(T *str, int height_want, bool italic = false, + bool bold = false, bool fixed = false, rgb_type background = rgb_type(), rgb_type foreground = rgb_type()){ + fontset_prev[0] = '\0'; + ximg = NULL; + d = NULL; + pix = None; + fs = NULL; + ascender = descender = -1; + pix_width_prev = pix_height_prev = -1; + create(str, height_want, italic, bold, fixed, background, foreground); + } + + inline int get_ascender(){ + return ascender; + } + + inline int get_descender(){ + return descender; + } + + std::map col2rgb; + rgb_type color2rgb(unsigned long color, Display *d, Colormap &cmap){ + if (col2rgb.count(color)){ + return col2rgb[color]; + }else{ + XColor xcol; + xcol.pixel = color; + XQueryColor(d, cmap, &xcol); + rgb_type rgb_((byte)(xcol.red/257), (byte)(xcol.green/257), (byte)(xcol.blue/257)); + col2rgb[color] = rgb_; + return rgb_; + } + } + inline void get_pixel(int x, int y, byte &r, byte &g, byte &b){ + rgb_type c = color2rgb(XGetPixel(ximg,x,y), d, cmap); + r = c.r, g = c.g, b = c.b; + } + + ~vals_internal(){ + XDestroyImage(ximg); + + XFreeGC(d, gc); + XFreeFontSet(d, fs); + XFreePixmap(d, pix); + XCloseDisplay(d); + } +#endif + }; + + struct image_size_setter{ + void operator()(int &width, int &height){ + } + }; + + int ascender, descender; + vals_internal *vi; + public: + font_renderer() : image(0), width(0), height(0){ + ascender = descender = 0; + vi = NULL; + } + + template font_renderer(T *str, int height_want, bool italic = false, bool bold = false, bool fixed = false, rgb_type background = rgb_type(0,0,0), rgb_type foreground = rgb_type(255,255,255)){ + render(str, height_want, italic, bold, fixed, background, foreground); + } + + template void render(T *str, int height_want, + bool italic = false, bool bold = false, bool fixed = false, + rgb_type background = rgb_type(0,0,0), rgb_type foreground = rgb_type(255,255,255)){ + if (vi == NULL){ + vi = new vals_internal(str, height_want, italic, bold, fixed, background, foreground); + }else{ + vi->create(str, height_want, italic, bold, fixed, background, foreground); + } + width = vi->width, height = vi->height; + image = new byte[width * height * 3]; + ascender = vi->get_ascender(); + descender = vi->get_descender(); + + int h = height, w = width; + for (int j = 0, i3 = 0; j < h; ++j){ + for (int i = 0; i < w; ++i, i3 += 3){ + vi->get_pixel(i, j, image[i3], image[i3+1], image[i3+2]); + } + } + } + + ~font_renderer(){ + if (vi) delete vi; + destroy(); + } + int get_width(){ + return width; + } + int get_height(){ + return height; + } + inline int get_ascender(){ + return ascender; + } + inline int get_descender(){ + return descender; + } + + const byte *get_image(){ + return image; + } + }; + } + +// ---------------------------------------------------------------------------------------- + + class native_font : public dlib::font + { + unsigned long ascender_; + native_font(){ + setlocale(LC_CTYPE, ""); + ascender_ = 0; + get_letter((int)('x')); + } + virtual ~native_font() {} + std::map letters; + font_renderer::font_renderer fl; + public: + virtual bool has_character ( + dlib::unichar ch + )const{ + return (*this)[ch].width() > 0; + } + + static const font* get_font ( + ) + { + static native_font f; + return &f; + } + + virtual const dlib::letter& operator[] (dlib::unichar ch) const{ + return (const_cast(this))->get_letter(ch); + } + + dlib::letter& get_letter ( + dlib::unichar ch + ){ + if (letters.count(ch)){ + dlib::letter *l = letters.find(ch)->second; + return *l; + } + + dlib::unichar c[2]; + c[0] = ch; + c[1] = 0; + + fl.render(c, height(),false,false,true); + if (ascender_ == 0){ + ascender_ = fl.get_ascender(); + } + std::vector v; + const font_renderer::byte *bp = fl.get_image(); + for (int j = 0; j < fl.get_height(); ++j){ + for (int i = 0; i < fl.get_width(); ++i, bp += 3){ + if (*bp){ + v.push_back(dlib::letter::point(i,j-ascender()+1)); + } + } + } + dlib::letter *l = new dlib::letter(fl.get_width(), (unsigned long)v.size()); + + letters.insert(std::make_pair(ch,l)); + for (int i = 0; i < (int)v.size(); ++i){ + (*l)[i] = v.at(i); + } + return *l; + } + + virtual const unsigned long height ( + ) const { return 12; } + + virtual const unsigned long ascender ( + ) const { return ascender_; } + + virtual const unsigned long left_overflow ( + ) const { return 1; } + + virtual const unsigned long right_overflow ( + ) const { return 2; } + }; + +// ---------------------------------------------------------------------------------------- + +} +// history +// 2006/07/10 ver 1.10 Win32 ‚Æ X11 ‚Å‹¤’Ê‚µ‚Ä‚¢‚é•”•ª‚Ìd•¡‚𖳂­‚µ‚½ +// 2007/08/15 dlib—p‚ÉC³ +// 2007/12/16 unicode(UTF32)‚ɑΉž‚µ‚½ +// 2008/01/02 ver 2.00 dlib ver 16.1 ‚Å”CˆÓ‚̃tƒHƒ“ƒgƒNƒ‰ƒX‚ðƒAƒvƒŠƒP[ƒVƒ‡ƒ“‘¤‚Å +// Žw’è‚Å‚«‚é‚悤‚É‚È‚èAdlib‚Æ‚±‚̃Nƒ‰ƒX‚𕪗£‚µ‚Ĉµ‚¦‚é‚悤 +// ‚É‚È‚Á‚½B‚±‚Ì•ÏX‚ɇ‚킹‚ÄA–¼‘O‹óŠÔ‚ð•ÏX‚µ‚½B + +#endif // DLIB_IGG_FONT_RENDERER_H_ + diff --git a/dlib/gui_widgets/style.cpp b/dlib/gui_widgets/style.cpp index e9d6570c8..b9e19c26b 100644 --- a/dlib/gui_widgets/style.cpp +++ b/dlib/gui_widgets/style.cpp @@ -22,7 +22,7 @@ namespace dlib const font& mfont, const long lastx, const long lasty, - const std::string& name, + const ustring& name, const bool is_depressed ) const { @@ -87,7 +87,7 @@ namespace dlib rectangle button_style_default:: get_min_size ( - const std::string& name, + const ustring& name, const font& mfont ) const { @@ -112,7 +112,7 @@ namespace dlib const font& mfont, const long lastx, const long lasty, - const std::string& name, + const ustring& name, const bool is_depressed ) const { @@ -186,7 +186,7 @@ namespace dlib rectangle button_style_toolbar1:: get_min_size ( - const std::string& name, + const ustring& name, const font& mfont ) const { @@ -211,7 +211,7 @@ namespace dlib const font& mfont, const long lastx, const long lasty, - const std::string& name, + const ustring& name, const bool is_depressed ) const { @@ -268,7 +268,7 @@ namespace dlib rectangle button_style_toolbar_icon1:: get_min_size ( - const std::string& name, + const ustring& name, const font& mfont ) const { @@ -289,7 +289,7 @@ namespace dlib const font& mfont, const long lastx, const long lasty, - const std::string& name, + const ustring& name, const bool is_depressed, const bool is_checked ) const @@ -355,7 +355,7 @@ namespace dlib rectangle toggle_button_style_default:: get_min_size ( - const std::string& name, + const ustring& name, const font& mfont ) const { @@ -380,7 +380,7 @@ namespace dlib const font& mfont, const long lastx, const long lasty, - const std::string& name, + const ustring& name, const bool is_depressed, const bool is_checked ) const @@ -447,7 +447,7 @@ namespace dlib rectangle toggle_button_style_check_box:: get_min_size ( - const std::string& name, + const ustring& name, const font& mfont ) const { @@ -473,7 +473,7 @@ namespace dlib const font& mfont, const long lastx, const long lasty, - const std::string& name, + const ustring& name, const bool is_depressed, const bool is_checked ) const @@ -567,7 +567,7 @@ namespace dlib rectangle toggle_button_style_radio_button:: get_min_size ( - const std::string& name, + const ustring& name, const font& mfont ) const { diff --git a/dlib/gui_widgets/style.h b/dlib/gui_widgets/style.h index 5861ea2f0..ad70fe966 100644 --- a/dlib/gui_widgets/style.h +++ b/dlib/gui_widgets/style.h @@ -12,6 +12,7 @@ #include "../unicode.h" #include "../array2d.h" #include "../pixel.h" +#include "fonts.h" namespace dlib @@ -38,7 +39,7 @@ namespace dlib ) const { return false; } virtual rectangle get_min_size ( - const std::string& name, + const ustring& name, const font& mfont ) const = 0; @@ -50,7 +51,7 @@ namespace dlib const font& mfont, const long lastx, const long lasty, - const std::string& name, + const ustring& name, const bool is_depressed ) const = 0; }; @@ -70,12 +71,12 @@ namespace dlib const font& mfont, const long lastx, const long lasty, - const std::string& name, + const ustring& name, const bool is_depressed ) const; virtual rectangle get_min_size ( - const std::string& name, + const ustring& name, const font& mfont ) const; @@ -104,7 +105,7 @@ namespace dlib const font& mfont, const long lastx, const long lasty, - const std::string& name, + const ustring& name, const bool is_depressed ) const; @@ -112,7 +113,7 @@ namespace dlib ) const { return true; } virtual rectangle get_min_size ( - const std::string& name, + const ustring& name, const font& mfont ) const; @@ -153,7 +154,7 @@ namespace dlib const font& mfont, const long lastx, const long lasty, - const std::string& name, + const ustring& name, const bool is_depressed ) const; @@ -161,7 +162,7 @@ namespace dlib ) const { return true; } virtual rectangle get_min_size ( - const std::string& name, + const ustring& name, const font& mfont ) const; @@ -235,7 +236,7 @@ namespace dlib ) const { return false; } virtual rectangle get_min_size ( - const std::string& name, + const ustring& name, const font& mfont ) const = 0; @@ -247,7 +248,7 @@ namespace dlib const font& mfont, const long lastx, const long lasty, - const std::string& name, + const ustring& name, const bool is_depressed, const bool is_checked ) const = 0; @@ -268,13 +269,13 @@ namespace dlib const font& mfont, const long lastx, const long lasty, - const std::string& name, + const ustring& name, const bool is_depressed, const bool is_checked ) const; virtual rectangle get_min_size ( - const std::string& name, + const ustring& name, const font& mfont ) const; @@ -301,13 +302,13 @@ namespace dlib const font& mfont, const long lastx, const long lasty, - const std::string& name, + const ustring& name, const bool is_depressed, const bool is_checked ) const; virtual rectangle get_min_size ( - const std::string& name, + const ustring& name, const font& mfont ) const; @@ -326,13 +327,13 @@ namespace dlib const font& mfont, const long lastx, const long lasty, - const std::string& name, + const ustring& name, const bool is_depressed, const bool is_checked ) const; virtual rectangle get_min_size ( - const std::string& name, + const ustring& name, const font& mfont ) const; diff --git a/dlib/gui_widgets/style_abstract.h b/dlib/gui_widgets/style_abstract.h index 8791de870..70da07804 100644 --- a/dlib/gui_widgets/style_abstract.h +++ b/dlib/gui_widgets/style_abstract.h @@ -6,6 +6,7 @@ #include "../algs.h" #include "../gui_core.h" #include "widgets_abstract.h" +#include "../unicode/unicode_abstract.h" namespace dlib { @@ -42,7 +43,7 @@ namespace dlib !*/ virtual rectangle get_min_size ( - const std::string& name, + const ustring& name, const font& mfont ) const = 0; /*! @@ -61,7 +62,7 @@ namespace dlib const font& mfont, const long lastx, const long lasty, - const std::string& name, + const ustring& name, const bool is_depressed ) const = 0; /*! @@ -153,7 +154,7 @@ namespace dlib !*/ virtual rectangle get_min_size ( - const std::string& name, + const ustring& name, const font& mfont ) const = 0; /*! @@ -172,7 +173,7 @@ namespace dlib const font& mfont, const long lastx, const long lasty, - const std::string& name, + const ustring& name, const bool is_depressed, const bool is_checked ) const = 0; diff --git a/dlib/gui_widgets/widgets.cpp b/dlib/gui_widgets/widgets.cpp index d4e327c74..352403758 100644 --- a/dlib/gui_widgets/widgets.cpp +++ b/dlib/gui_widgets/widgets.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net) +// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), Keita Mochizuki // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_WIDGETs_CPP_ #define DLIB_WIDGETs_CPP_ @@ -84,6 +84,26 @@ namespace dlib btn_tooltip.set_text(text); } +// ---------------------------------------------------------------------------------------- + + void button:: + set_tooltip_text ( + const std::wstring& text + ) + { + btn_tooltip.set_text(text); + } + +// ---------------------------------------------------------------------------------------- + + void button:: + set_tooltip_text ( + const ustring& text + ) + { + btn_tooltip.set_text(text); + } + // ---------------------------------------------------------------------------------------- const std::string button:: @@ -93,6 +113,20 @@ namespace dlib return btn_tooltip.text(); } + const std::wstring button:: + tooltip_wtext ( + ) const + { + return btn_tooltip.wtext(); + } + + const dlib::ustring button:: + tooltip_utext ( + ) const + { + return btn_tooltip.utext(); + } + // ---------------------------------------------------------------------------------------- void button:: @@ -124,6 +158,22 @@ namespace dlib set_name ( const std::string& name ) + { + set_name(convert_mbstring_to_wstring(name)); + } + + void button:: + set_name ( + const std::wstring& name + ) + { + set_name(convert_wstring_to_utf32(name)); + } + + void button:: + set_name ( + const ustring& name + ) { auto_mutex M(m); name_ = name; @@ -145,9 +195,35 @@ namespace dlib ) const { auto_mutex M(m); - std::string temp = name_; + std::string temp = convert_wstring_to_mbstring(wname()); // do this to get rid of any reference counting that may be present in // the std::string implementation. + char c = temp[0]; + temp[0] = c; + return temp; + } + + const std::wstring button:: + wname ( + ) const + { + auto_mutex M(m); + std::wstring temp = convert_utf32_to_wstring(uname()); + // do this to get rid of any reference counting that may be present in + // the std::wstring implementation. + wchar_t w = temp[0]; + temp[0] = w; + return temp; + } + + const dlib::ustring button:: + uname ( + ) const + { + auto_mutex M(m); + dlib::ustring temp = name_; + // do this to get rid of any reference counting that may be present in + // the dlib::ustring implementation. temp[0] = name_[0]; return temp; } @@ -276,6 +352,22 @@ namespace dlib btn_tooltip.set_text(text); } + void toggle_button:: + set_tooltip_text ( + const std::wstring& text + ) + { + btn_tooltip.set_text(text); + } + + void toggle_button:: + set_tooltip_text ( + const dlib::ustring& text + ) + { + btn_tooltip.set_text(text); + } + // ---------------------------------------------------------------------------------------- const std::string toggle_button:: @@ -285,6 +377,20 @@ namespace dlib return btn_tooltip.text(); } + const std::wstring toggle_button:: + tooltip_wtext ( + ) const + { + return btn_tooltip.wtext(); + } + + const dlib::ustring toggle_button:: + tooltip_utext ( + ) const + { + return btn_tooltip.utext(); + } + // ---------------------------------------------------------------------------------------- void toggle_button:: @@ -316,6 +422,22 @@ namespace dlib set_name ( const std::string& name ) + { + set_name(convert_mbstring_to_wstring(name)); + } + + void toggle_button:: + set_name ( + const std::wstring& name + ) + { + set_name(convert_wstring_to_utf32(name)); + } + + void toggle_button:: + set_name ( + const dlib::ustring& name + ) { auto_mutex M(m); name_ = name; @@ -335,9 +457,23 @@ namespace dlib const std::string toggle_button:: name ( ) const + { + return convert_wstring_to_mbstring(wname()); + } + + const std::wstring toggle_button:: + wname ( + ) const + { + return convert_utf32_to_wstring(uname()); + } + + const dlib::ustring toggle_button:: + uname ( + ) const { auto_mutex M(m); - std::string temp = name_; + dlib::ustring temp = name_; // do this to get rid of any reference counting that may be present in // the std::string implementation. temp[0] = name_[0]; @@ -418,10 +554,27 @@ namespace dlib // ---------------------------------------------------------------------------------------- + void label:: set_text ( const std::string& text ) + { + set_text(convert_mbstring_to_wstring(text)); + } + + void label:: + set_text ( + const std::wstring& text + ) + { + set_text(convert_wstring_to_utf32(text)); + } + + void label:: + set_text ( + const dlib::ustring& text + ) { using namespace std; auto_mutex M(m); @@ -447,9 +600,23 @@ namespace dlib const std::string label:: text ( ) const + { + return convert_wstring_to_mbstring(wtext()); + } + + const std::wstring label:: + wtext ( + ) const + { + return convert_utf32_to_wstring(utext()); + } + + const dlib::ustring label:: + utext ( + ) const { auto_mutex M(m); - std::string temp = text_; + dlib::ustring temp = text_; // do this to get rid of any reference counting that may be present in // the std::string implementation. temp[0] = text_[0]; @@ -633,10 +800,26 @@ namespace dlib set_text ( const std::string& text ) + { + set_text(convert_mbstring_to_wstring(text)); + } + + void text_field:: + set_text ( + const std::wstring& text + ) + { + set_text(convert_wstring_to_utf32(text)); + } + + void text_field:: + set_text ( + const dlib::ustring& text + ) { DLIB_ASSERT ( text.find_first_of('\n') == std::string::npos , "\tvoid text_field::set_text()" - << "\n\ttext: " << text ); + << "\n\ttext: " << narrow(text) ); auto_mutex M(m); // do this to get rid of any reference counting that may be present in // the std::string implementation. @@ -655,11 +838,27 @@ namespace dlib const std::string text_field:: text ( ) const + { + std::string temp = convert_wstring_to_mbstring(wtext()); + return temp; + } + + const std::wstring text_field:: + wtext ( + ) const + { + std::wstring temp = convert_utf32_to_wstring(utext()); + return temp; + } + + const dlib::ustring text_field:: + utext ( + ) const { auto_mutex M(m); // do this to get rid of any reference counting that may be present in - // the std::string implementation. - std::string temp = text_.c_str(); + // the dlib::ustring implementation. + dlib::ustring temp = text_.c_str(); return temp; } @@ -807,8 +1006,9 @@ namespace dlib { // highlight the double clicked word string::size_type first, last; - first = text_.substr(0,cursor_pos).find_last_of(" \t\n"); - last = text_.find_first_of(" \t\n",cursor_pos); + const ustring ustr = convert_utf8_to_utf32(std::string(" \t\n")); + first = text_.substr(0,cursor_pos).find_last_of(ustr.c_str()); + last = text_.find_first_of(ustr.c_str(),cursor_pos); long f = static_cast(first); long l = static_cast(last); if (first == string::npos) @@ -886,6 +1086,7 @@ namespace dlib unsigned long state ) { + const ustring space_str = convert_utf8_to_utf32(std::string(" \t\n")); const bool shift = (state&base_window::KBD_MOD_SHIFT) != 0; const bool ctrl = (state&base_window::KBD_MOD_CONTROL) != 0; if (has_focus && enabled && !hidden) @@ -921,10 +1122,10 @@ namespace dlib if (ctrl) { // find the first non-whitespace to our left - std::string::size_type pos = text_.find_last_not_of(" \t\n",cursor_pos); + std::string::size_type pos = text_.find_last_not_of(space_str.c_str(),cursor_pos); if (pos != std::string::npos) { - pos = text_.find_last_of(" \n\t",pos); + pos = text_.find_last_of(space_str.c_str(),pos); if (pos != std::string::npos) new_pos = static_cast(pos); else @@ -959,10 +1160,10 @@ namespace dlib if (ctrl) { // find the first non-whitespace to our left - std::string::size_type pos = text_.find_first_not_of(" \t\n",cursor_pos); + std::string::size_type pos = text_.find_first_not_of(space_str.c_str(),cursor_pos); if (pos != std::string::npos) { - pos = text_.find_first_of(" \n\t",pos); + pos = text_.find_first_of(space_str.c_str(),pos); if (pos != std::string::npos) new_pos = static_cast(pos+1); else @@ -1003,7 +1204,7 @@ namespace dlib { if (highlight_start <= highlight_end) { - text_ = text_.substr(0,highlight_start) + static_cast(key) + + text_ = text_.substr(0,highlight_start) + static_cast(key) + text_.substr(highlight_end+1,text_.size()-highlight_end-1); move_cursor(highlight_start+1); highlight_start = 0; @@ -1012,7 +1213,7 @@ namespace dlib } else { - text_ = text_.substr(0,cursor_pos) + static_cast(key) + + text_ = text_.substr(0,cursor_pos) + static_cast(key) + text_.substr(cursor_pos,text_.size()-cursor_pos); move_cursor(cursor_pos+1); } @@ -1119,6 +1320,39 @@ namespace dlib } } +// ---------------------------------------------------------------------------------------- + + void text_field:: + on_string_put( + const std::wstring &str + ) + { + if (has_focus && enabled && !hidden){ + ustring ustr = convert_wstring_to_utf32(str); + if (highlight_start <= highlight_end) + { + text_ = text_.substr(0,highlight_start) + ustr + + text_.substr(highlight_end+1,text_.size()-highlight_end-1); + move_cursor(highlight_start+ustr.size()); + highlight_start = 0; + highlight_end = -1; + parent.invalidate_rectangle(rect); + } + else + { + text_ = text_.substr(0,cursor_pos) + ustr + + text_.substr(cursor_pos,text_.size()-cursor_pos); + move_cursor(cursor_pos+ustr.size()); + } + unsigned long height; + mfont->compute_size(text_,text_width,height,text_pos); + + // send out the text modified event + if (text_modified_handler.is_set()) + text_modified_handler(); + } + } + // ---------------------------------------------------------------------------------------- void text_field:: @@ -1339,10 +1573,26 @@ namespace dlib // ---------------------------------------------------------------------------------------- - const std::string& tabbed_display:: + const std::string tabbed_display:: tab_name ( unsigned long idx ) const + { + return convert_wstring_to_mbstring(tab_wname(idx)); + } + + const std::wstring tabbed_display:: + tab_wname ( + unsigned long idx + ) const + { + return convert_utf32_to_wstring(tab_uname(idx)); + } + + const dlib::ustring& tabbed_display:: + tab_uname ( + unsigned long idx + ) const { auto_mutex M(m); @@ -1361,6 +1611,24 @@ namespace dlib unsigned long idx, const std::string& new_name ) + { + set_tab_name(idx, convert_mbstring_to_wstring(new_name)); + } + + void tabbed_display:: + set_tab_name ( + unsigned long idx, + const std::wstring& new_name + ) + { + set_tab_name(idx, convert_wstring_to_utf32(new_name)); + } + + void tabbed_display:: + set_tab_name ( + unsigned long idx, + const dlib::ustring& new_name + ) { auto_mutex M(m); @@ -1750,6 +2018,22 @@ namespace dlib set_name ( const std::string& name ) + { + set_name(convert_mbstring_to_wstring(name)); + } + + void named_rectangle:: + set_name ( + const std::wstring& name + ) + { + set_name(convert_wstring_to_utf32(name)); + } + + void named_rectangle:: + set_name ( + const dlib::ustring& name + ) { auto_mutex M(m); name_ = name.c_str(); @@ -1764,9 +2048,23 @@ namespace dlib const std::string named_rectangle:: name ( ) const + { + return convert_wstring_to_mbstring(wname()); + } + + const std::wstring named_rectangle:: + wname ( + ) const + { + return convert_utf32_to_wstring(uname()); + } + + const dlib::ustring named_rectangle:: + uname ( + ) const { auto_mutex M(m); - return std::string(name_.c_str()); + return dlib::ustring(name_.c_str()); } // ---------------------------------------------------------------------------------------- @@ -2039,7 +2337,9 @@ namespace dlib // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- - list_box:: + namespace list_box_helper{ + template + list_box:: list_box( drawable_window& w ) : @@ -2059,7 +2359,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - list_box:: + template + list_box:: ~list_box( ) { @@ -2069,7 +2370,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: set_main_font ( const font* f ) @@ -2087,7 +2389,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: set_size ( unsigned long width_, unsigned long height_ @@ -2106,7 +2409,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - bool list_box:: + template + bool list_box:: is_selected ( unsigned long index ) const @@ -2122,7 +2426,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: select ( unsigned long index ) @@ -2139,7 +2444,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: unselect ( unsigned long index ) @@ -2155,7 +2461,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - const std::string& list_box::operator [] ( + template + const S& list_box::operator [] ( unsigned long index ) const { @@ -2169,7 +2476,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - bool list_box:: + template + bool list_box:: multiple_select_enabled ( ) const { @@ -2179,7 +2487,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: enable_multiple_select ( ) { @@ -2189,7 +2498,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: disable_multiple_select ( ) { @@ -2199,7 +2509,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - bool list_box:: + template + bool list_box:: at_start ( ) const { @@ -2209,7 +2520,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: reset ( ) const { @@ -2219,7 +2531,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - bool list_box:: + template + bool list_box:: current_element_valid ( ) const { @@ -2229,7 +2542,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - const std::string& list_box:: + template + const S &list_box:: element ( ) const { @@ -2242,7 +2556,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - const std::string& list_box:: + template + const S &list_box:: element ( ) { @@ -2255,7 +2570,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - bool list_box:: + template + bool list_box:: move_next ( ) const { @@ -2265,7 +2581,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - unsigned long list_box:: + template + unsigned long list_box:: size ( ) const { @@ -2275,7 +2592,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: draw ( const canvas& c ) const @@ -2327,7 +2645,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: hide ( ) { @@ -2339,7 +2658,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: show ( ) { @@ -2351,7 +2671,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: disable ( ) { @@ -2362,7 +2683,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: enable ( ) { @@ -2373,7 +2695,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: set_pos ( long x, long y @@ -2386,7 +2709,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: adjust_sliders ( ) { @@ -2453,7 +2777,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: sbh_handler ( ) { @@ -2463,7 +2788,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: sbv_handler ( ) { @@ -2473,7 +2799,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: on_wheel_up ( ) { @@ -2491,7 +2818,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: on_wheel_down ( ) { @@ -2509,7 +2837,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: on_mouse_down ( unsigned long btn, unsigned long state, @@ -2584,7 +2913,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - void list_box:: + template + void list_box:: set_z_order ( long order ) @@ -2596,7 +2926,8 @@ namespace dlib // ---------------------------------------------------------------------------------------- - unsigned long list_box:: + template + unsigned long list_box:: get_selected ( ) const { @@ -2611,9 +2942,13 @@ namespace dlib } return items.size(); } - // ---------------------------------------------------------------------------------------- + // making instance of template + template class list_box; + template class list_box; + template class list_box; + } } #endif // DLIB_WIDGETs_CPP_ diff --git a/dlib/gui_widgets/widgets.h b/dlib/gui_widgets/widgets.h index 210780b0c..6aa3d5da0 100644 --- a/dlib/gui_widgets/widgets.h +++ b/dlib/gui_widgets/widgets.h @@ -1,4 +1,4 @@ -// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net) +// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), Keita Mochizuki // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_WIDGETs_ @@ -63,9 +63,23 @@ namespace dlib const std::string& text ); + void set_text ( + const std::wstring& text + ); + + void set_text ( + const dlib::ustring& text + ); + const std::string text ( ) const; + const std::wstring wtext ( + ) const; + + const dlib::ustring utext ( + ) const; + void set_text_color ( const rgb_pixel color ); @@ -78,7 +92,7 @@ namespace dlib ); private: - std::string text_; + dlib::ustring text_; rgb_pixel text_color_; @@ -124,13 +138,35 @@ namespace dlib const std::string& name_ ); + void set_name ( + const std::wstring& name_ + ); + + void set_name ( + const dlib::ustring& name_ + ); + const std::string name ( ) const; + const std::wstring wname ( + ) const; + + const dlib::ustring uname ( + ) const; + void set_tooltip_text ( const std::string& text ); + void set_tooltip_text ( + const std::wstring& text + ); + + void set_tooltip_text ( + const dlib::ustring& text + ); + void set_pos( long x, long y @@ -139,6 +175,12 @@ namespace dlib const std::string tooltip_text ( ) const; + const std::wstring tooltip_wtext ( + ) const; + + const dlib::ustring tooltip_utext ( + ) const; + void set_main_font ( const font* f ); @@ -200,7 +242,7 @@ namespace dlib button(button&); // copy constructor button& operator=(button&); // assignment operator - std::string name_; + dlib::ustring name_; tooltip btn_tooltip; member_function_pointer<>::kernel_1a event_handler; @@ -260,6 +302,14 @@ namespace dlib const std::string& name ); + void set_name ( + const std::wstring& name + ); + + void set_name ( + const dlib::ustring& name + ); + void set_size ( unsigned long width_, unsigned long height_ @@ -269,15 +319,35 @@ namespace dlib const std::string& text ); + void set_tooltip_text ( + const std::wstring& text + ); + + void set_tooltip_text ( + const ustring& text + ); + const std::string tooltip_text ( ) const; + const std::wstring tooltip_wtext ( + ) const; + + const dlib::ustring tooltip_utext ( + ) const; + bool is_checked ( ) const; const std::string name ( ) const; + const std::wstring wname ( + ) const; + + const dlib::ustring uname ( + ) const; + void set_checked ( ); @@ -350,7 +420,7 @@ namespace dlib toggle_button(toggle_button&); // copy constructor toggle_button& operator=(toggle_button&); // assignment operator - std::string name_; + dlib::ustring name_; tooltip btn_tooltip; bool checked; @@ -436,7 +506,7 @@ namespace dlib text_field( drawable_window& w ) : - drawable(w,MOUSE_CLICK | KEYBOARD_EVENTS | MOUSE_MOVE), + drawable(w,MOUSE_CLICK | KEYBOARD_EVENTS | MOUSE_MOVE | STRING_PUT), text_color_(0,0,0), bg_color_(255,255,255), text_width(0), @@ -470,9 +540,23 @@ namespace dlib const std::string& text_ ); + void set_text ( + const std::wstring& text_ + ); + + void set_text ( + const dlib::ustring& text_ + ); + const std::string text ( ) const; + const std::wstring wtext ( + ) const; + + const dlib::ustring utext ( + ) const; + void set_text_color ( const rgb_pixel color ); @@ -596,7 +680,7 @@ namespace dlib - returns the rectangle that should contain the text in this widget !*/ - std::string text_; + dlib::ustring text_; rgb_pixel text_color_; rgb_pixel bg_color_; @@ -659,6 +743,10 @@ namespace dlib bool is_printable, unsigned long state ); + + void on_string_put ( + const std::wstring &str + ); }; // ---------------------------------------------------------------------------------------- @@ -753,7 +841,15 @@ namespace dlib unsigned long number_of_tabs ( ) const; - const std::string& tab_name ( + const std::string tab_name ( + unsigned long idx + ) const; + + const std::wstring tab_wname ( + unsigned long idx + ) const; + + const dlib::ustring& tab_uname ( unsigned long idx ) const; @@ -762,6 +858,16 @@ namespace dlib const std::string& new_name ); + void set_tab_name ( + unsigned long idx, + const std::wstring& new_name + ); + + void set_tab_name ( + unsigned long idx, + const dlib::ustring& new_name + ); + void set_pos ( long x, long y @@ -838,7 +944,7 @@ namespace dlib { tab_data() : width(0), group(0) {} - std::string name; + dlib::ustring name; unsigned long width; rectangle rect; widget_group* group; @@ -894,9 +1000,23 @@ namespace dlib const std::string& name ); + void set_name ( + const std::wstring& name + ); + + void set_name ( + const dlib::ustring& name + ); + const std::string name ( ) const; + const std::wstring wname ( + ) const; + + const dlib::ustring uname ( + ) const; + void wrap_around ( const rectangle& rect ); @@ -916,7 +1036,7 @@ namespace dlib void make_name_fit_in_rect ( ); - std::string name_; + dlib::ustring name_; unsigned long name_width; unsigned long name_height; @@ -1013,16 +1133,8 @@ namespace dlib { class box_win : public drawable_window { - public: - box_win ( - const std::string& title_, - const std::string& message_ - ) : - drawable_window(false), - title(title_), - message(message_), - msg(*this), - btn_ok(*this) + void initialize ( + ) { msg.set_pos(20,20); msg.set_text(message); @@ -1040,7 +1152,44 @@ namespace dlib show(); - set_title(title_); + set_title(title); + } + public: + box_win ( + const std::string& title_, + const std::string& message_ + ) : + drawable_window(false), + title(convert_mbstring_to_wstring(title_)), + message(convert_mbstring_to_wstring(message_)), + msg(*this), + btn_ok(*this) + { + initialize(); + } + box_win ( + const std::wstring& title_, + const std::wstring& message_ + ) : + drawable_window(false), + title(title_), + message(message_), + msg(*this), + btn_ok(*this) + { + initialize(); + } + box_win ( + const dlib::ustring& title_, + const dlib::ustring& message_ + ) : + drawable_window(false), + title(convert_utf32_to_wstring(title_)), + message(convert_utf32_to_wstring(message_)), + msg(*this), + btn_ok(*this) + { + initialize(); } ~box_win ( @@ -1098,8 +1247,8 @@ namespace dlib return CLOSE_WINDOW; } - const std::string title; - const std::string message; + const std::wstring title; + const std::wstring message; label msg; button btn_ok; @@ -1108,16 +1257,8 @@ namespace dlib class blocking_box_win : public drawable_window { - public: - blocking_box_win ( - const std::string& title_, - const std::string& message_ - ) : - drawable_window(false), - title(title_), - message(message_), - msg(*this), - btn_ok(*this) + void initialize ( + ) { msg.set_pos(20,20); msg.set_text(message); @@ -1134,9 +1275,48 @@ namespace dlib set_size(size.right()+20,size.bottom()+20); - set_title(title_); + set_title(title); show(); } + public: + blocking_box_win ( + const std::string& title_, + const std::string& message_ + ) : + drawable_window(false), + title(convert_mbstring_to_wstring(title_)), + message(convert_mbstring_to_wstring(message_)), + msg(*this), + btn_ok(*this) + { + initialize(); + } + + blocking_box_win ( + const std::wstring& title_, + const std::wstring& message_ + ) : + drawable_window(false), + title(title_), + message(message_), + msg(*this), + btn_ok(*this) + { + initialize(); + } + + blocking_box_win ( + const dlib::ustring& title_, + const dlib::ustring& message_ + ) : + drawable_window(false), + title(convert_utf32_to_wstring(title_)), + message(convert_utf32_to_wstring(message_)), + msg(*this), + btn_ok(*this) + { + initialize(); + } ~blocking_box_win ( ) @@ -1152,8 +1332,8 @@ namespace dlib close_window(); } - const std::string title; - const std::string message; + const std::wstring title; + const std::wstring message; label msg; button btn_ok; }; @@ -1199,8 +1379,10 @@ namespace dlib // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- + namespace list_box_helper{ + template class list_box : public drawable, - public enumerable + public enumerable { /*! INITIAL VALUE @@ -1302,7 +1484,7 @@ namespace dlib last_selected = 0; } - const std::string& operator[] ( + const S& operator[] ( unsigned long index ) const; @@ -1340,10 +1522,10 @@ namespace dlib bool current_element_valid ( ) const; - const std::string& element ( + const S& element ( ) const; - const std::string& element ( + const S& element ( ); bool move_next ( @@ -1410,9 +1592,10 @@ namespace dlib const canvas& c ) const; + template struct data { - std::string name; + SS name; bool is_selected; unsigned long width; unsigned long height; @@ -1421,7 +1604,7 @@ namespace dlib const static long pad = 2; bool ms_enabled; - array::kernel_2a_c items; + typename array >::kernel_2a_c items; member_function_pointer::kernel_1a event_handler; member_function_pointer::kernel_1a single_click_event_handler; unsigned long pos; @@ -1436,7 +1619,10 @@ namespace dlib list_box(list_box&); // copy constructor list_box& operator=(list_box&); // assignment operator }; - + } + typedef list_box_helper::list_box list_box; + typedef list_box_helper::list_box wlist_box; + typedef list_box_helper::list_box ulist_box; // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // function open_file_box() @@ -1989,6 +2175,24 @@ namespace dlib const std::string name, char underline_ch = '\0' ) + { + set_menu_name(idx, convert_mbstring_to_wstring(name), underline_ch); + } + + void set_menu_name ( + unsigned long idx, + const std::wstring name, + char underline_ch = '\0' + ) + { + set_menu_name(idx, convert_wstring_to_utf32(name), underline_ch); + } + + void set_menu_name ( + unsigned long idx, + const dlib::ustring name, + char underline_ch = '\0' + ) { DLIB_ASSERT ( idx < number_of_menus() , "\tvoid menu_bar::set_menu_name()" @@ -2005,6 +2209,20 @@ namespace dlib const std::string menu_name ( unsigned long idx ) const + { + return convert_wstring_to_mbstring(menu_wname(idx)); + } + + const std::wstring menu_wname ( + unsigned long idx + ) const + { + return convert_utf32_to_wstring(menu_uname(idx)); + } + + const dlib::ustring menu_uname ( + unsigned long idx + ) const { DLIB_ASSERT ( idx < number_of_menus() , "\tstd::string menu_bar::menu_name()" @@ -2262,8 +2480,8 @@ namespace dlib struct menu_data { - std::string name; - std::string::size_type underline_pos; + dlib::ustring name; + dlib::ustring::size_type underline_pos; popup_menu menu; rectangle rect; rectangle bgrect; @@ -2498,12 +2716,28 @@ namespace dlib unsigned long i, const std::string& label ) + { + set_node_label(i, convert_mbstring_to_wstring(label)); + } + + void set_node_label ( + unsigned long i, + const std::wstring& label + ) + { + set_node_label(i, convert_wstring_to_utf32(label)); + } + + void set_node_label ( + unsigned long i, + const dlib::ustring& label + ) { auto_mutex M(m); DLIB_ASSERT ( i < number_of_nodes() , "\tvoid directed_graph_drawer::set_node_label(i,label)" << "\n\ti: " << i - << "\n\tlabel: " << label + << "\n\tlabel: " << narrow(label) << "\n\tnumber_of_nodes(): " << number_of_nodes() ); graph_.node(i).data.name = label.c_str(); @@ -2547,7 +2781,27 @@ namespace dlib { auto_mutex M(m); DLIB_ASSERT ( i < number_of_nodes() , - "\tconst std::string directed_graph_drawer::node_label(i)" + "\tconst std::ustring directed_graph_drawer::node_label(i)" + << "\n\ti: " << i + << "\n\tnumber_of_nodes(): " << number_of_nodes() + ); + return narrow(graph_.node(i).data.name); + } + + const std::wstring node_wlabel ( + unsigned long i + ) const + { + return convert_utf32_to_wstring(node_ulabel(i)); + } + + const dlib::ustring node_ulabel ( + unsigned long i + ) const + { + auto_mutex M(m); + DLIB_ASSERT ( i < number_of_nodes() , + "\tconst std::ustring directed_graph_drawer::node_label(i)" << "\n\ti: " << i << "\n\tnumber_of_nodes(): " << number_of_nodes() ); @@ -3005,7 +3259,7 @@ namespace dlib { data() : color(0,0,0) {} vector p; - std::string name; + dlib::ustring name; rectangle str_rect; rgb_pixel color; }; @@ -3175,6 +3429,22 @@ namespace dlib unsigned long row, unsigned long col ) const + { + return convert_wstring_to_mbstring(wtext(row, col)); + } + + const std::wstring wtext ( + unsigned long row, + unsigned long col + ) const + { + return convert_utf32_to_wstring(utext(row, col)); + } + + const dlib::ustring utext ( + unsigned long row, + unsigned long col + ) const { auto_mutex M(m); DLIB_ASSERT ( row < number_of_rows() && col < number_of_columns(), @@ -3193,6 +3463,24 @@ namespace dlib unsigned long col, const std::string& str ) + { + set_text(row, col, convert_mbstring_to_wstring(str)); + } + + void set_text ( + unsigned long row, + unsigned long col, + const std::wstring& str + ) + { + set_text(row, col, convert_wstring_to_utf32(str)); + } + + void set_text ( + unsigned long row, + unsigned long col, + const dlib::ustring& str + ) { auto_mutex M(m); DLIB_ASSERT ( row < number_of_rows() && col < number_of_columns(), @@ -3771,11 +4059,11 @@ namespace dlib first(0), is_editable(true) {} - std::string text; + dlib::ustring text; rgb_pixel text_color; rgb_pixel bg_color; rectangle bg_rect; - std::string::size_type first; + dlib::ustring::size_type first; bool is_editable; }; diff --git a/dlib/gui_widgets/widgets_abstract.h b/dlib/gui_widgets/widgets_abstract.h index f38584962..bdb14fe0c 100644 --- a/dlib/gui_widgets/widgets_abstract.h +++ b/dlib/gui_widgets/widgets_abstract.h @@ -1,4 +1,4 @@ -// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net) +// Copyright (C) 2005 Davis E. King (davisking@users.sourceforge.net), Keita Mochizuki // License: Boost Software License See LICENSE.txt for the full license. #undef DLIB_WIDGETs_ABSTRACT_ @@ -204,6 +204,26 @@ namespace dlib - std::bad_alloc !*/ + void set_text ( + const std::wstring& text + ); + /*! + ensures + - #text() == text + throws + - std::bad_alloc + !*/ + + void set_text ( + const dlib::ustring& text + ); + /*! + ensures + - #text() == text + throws + - std::bad_alloc + !*/ + const std::string text ( ) const; /*! @@ -213,6 +233,24 @@ namespace dlib - std::bad_alloc !*/ + const std::wstring wtext ( + ) const; + /*! + ensures + - returns the text of this label + throws + - std::bad_alloc + !*/ + + const dlib::ustring utext ( + ) const; + /*! + ensures + - returns the text of this label + throws + - std::bad_alloc + !*/ + void set_text_color ( const rgb_pixel color ); @@ -303,6 +341,30 @@ namespace dlib - std::bad_alloc !*/ + void set_name ( + const std::wstring& name + ); + /*! + ensures + - #name() == name + - this button has been resized such that it is big enough to contain + the new name. + throws + - std::bad_alloc + !*/ + + void set_name ( + const dlib::ustring& name + ); + /*! + ensures + - #name() == name + - this button has been resized such that it is big enough to contain + the new name. + throws + - std::bad_alloc + !*/ + const std::string name ( ) const; /*! @@ -312,6 +374,24 @@ namespace dlib - std::bad_alloc !*/ + const std::wstring wname ( + ) const; + /*! + ensures + - returns the name of this button + throws + - std::bad_alloc + !*/ + + const dlib::string uname ( + ) const; + /*! + ensures + - returns the name of this button + throws + - std::bad_alloc + !*/ + void set_tooltip_text ( const std::string& text ); @@ -328,6 +408,20 @@ namespace dlib - returns the text that is displayed in the tooltip for this button !*/ + const std::wstring tooltip_wtext ( + ) const; + /*! + ensures + - returns the text that is displayed in the tooltip for this button + !*/ + + const dlib::ustring tooltip_utext ( + ) const; + /*! + ensures + - returns the text that is displayed in the tooltip for this button + !*/ + template < typename style_type > @@ -445,6 +539,30 @@ namespace dlib - std::bad_alloc !*/ + void set_name ( + const std::wstring& name + ); + /*! + ensures + - #name() == name + - this toggle_button has been resized such that it is big enough to contain + the new name. + throws + - std::bad_alloc + !*/ + + void set_name ( + const dlib::ustring& name + ); + /*! + ensures + - #name() == name + - this toggle_button has been resized such that it is big enough to contain + the new name. + throws + - std::bad_alloc + !*/ + void set_size ( unsigned long width_, unsigned long height_ @@ -469,6 +587,24 @@ namespace dlib - enables the tooltip for this toggle_button !*/ + void set_tooltip_text ( + const std::wstring& text + ); + /*! + ensures + - #tooltip_text() == text + - enables the tooltip for this toggle_button + !*/ + + void set_tooltip_text ( + const dlib::ustring& text + ); + /*! + ensures + - #tooltip_text() == text + - enables the tooltip for this toggle_button + !*/ + const std::string tooltip_text ( ) const; /*! @@ -510,6 +646,26 @@ namespace dlib - std::bad_alloc !*/ + const std::wstring wname ( + ) const; + /*! + ensures + - returns the name of this toggle_button. The name is a string + that appears to the right of the actual check box. + throws + - std::bad_alloc + !*/ + + const dlib::ustring uname ( + ) const; + /*! + ensures + - returns the name of this toggle_button. The name is a string + that appears to the right of the actual check box. + throws + - std::bad_alloc + !*/ + void set_checked ( ); /*! @@ -628,6 +784,32 @@ namespace dlib - std::bad_alloc !*/ + void set_text ( + const std::wstring& text + ); + /*! + requires + - text.find_first_of('\n') == std::wstring::npos + (i.e. there aren't any new lines in text) + ensures + - #text() == text + throws + - std::bad_alloc + !*/ + + void set_text ( + const dlib::ustring& text + ); + /*! + requires + - text.find_first_of('\n') == dlib::ustring::npos + (i.e. there aren't any new lines in text) + ensures + - #text() == text + throws + - std::bad_alloc + !*/ + const std::string text ( ) const; /*! @@ -637,6 +819,24 @@ namespace dlib - std::bad_alloc !*/ + const std::wstring wtext ( + ) const; + /*! + ensures + - returns the text of this text_field + throws + - std::bad_alloc + !*/ + + const dlib::ustring utext ( + ) const; + /*! + ensures + - returns the text of this text_field + throws + - std::bad_alloc + !*/ + void set_width ( unsigned long width_ ); @@ -871,6 +1071,26 @@ namespace dlib - returns a const reference to the name of the tab given by idx !*/ + const std::wstring& tab_wname ( + unsigned long idx + ) const; + /*! + requires + - idx < number_of_tabs() + ensures + - returns a const reference to the name of the tab given by idx + !*/ + + const dlib::ustring& tab_uname ( + unsigned long idx + ) const; + /*! + requires + - idx < number_of_tabs() + ensures + - returns a const reference to the name of the tab given by idx + !*/ + void set_tab_name ( unsigned long idx, const std::string& new_name @@ -884,6 +1104,32 @@ namespace dlib - std::bad_alloc !*/ + void set_tab_name ( + unsigned long idx, + const std::wstring& new_name + ); + /*! + requires + - idx < number_of_tabs() + ensures + - #tab_name(idx) == new_name + throws + - std::bad_alloc + !*/ + + void set_tab_name ( + unsigned long idx, + const dlib::ustring& new_name + ); + /*! + requires + - idx < number_of_tabs() + ensures + - #tab_name(idx) == new_name + throws + - std::bad_alloc + !*/ + void set_tab_group ( unsigned long idx, widget_group& group @@ -1015,6 +1261,26 @@ namespace dlib - std::bad_alloc !*/ + void set_name ( + const std::wstring& name + ); + /*! + ensures + - #name() == name + throws + - std::bad_alloc + !*/ + + void set_name ( + const dlib::ustring& name + ); + /*! + ensures + - #name() == name + throws + - std::bad_alloc + !*/ + const std::string name ( ) const; /*! @@ -1024,6 +1290,24 @@ namespace dlib - std::bad_alloc !*/ + const std::wstring wname ( + ) const; + /*! + ensures + - returns the name of this named_rectangle + throws + - std::bad_alloc + !*/ + + const dlib::ustring uname ( + ) const; + /*! + ensures + - returns the name of this named_rectangle + throws + - std::bad_alloc + !*/ + private: // restricted functions @@ -1296,6 +1580,18 @@ namespace dlib list_box& operator=(list_box&); // assignment operator }; + class wlist_box : public drawable, + public enumerable; + /*! + same as list_box except for std::wstring instead of std::string + !*/ + + class ulist_box : public drawable, + public enumerable; + /*! + same as list_box except for dlib::ustring instead of std::string + !*/ + // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // class menu_bar @@ -1376,6 +1672,26 @@ namespace dlib - returns the name of the menu with index idx !*/ + const std::wstring menu_wname ( + unsigned long idx + ) const; + /*! + requires + - idx < number_of_menus() + ensures + - returns the name of the menu with index idx + !*/ + + const dlib::ustring menu_uname ( + unsigned long idx + ) const; + /*! + requires + - idx < number_of_menus() + ensures + - returns the name of the menu with index idx + !*/ + popup_menu& menu ( unsigned long idx ); @@ -1530,6 +1846,28 @@ namespace dlib - #node_label(i) == label !*/ + void set_node_label ( + unsigned long i, + const std::wstring& label + ); + /*! + requires + - i < number_of_nodes() + ensures + - #node_label(i) == label + !*/ + + void set_node_label ( + unsigned long i, + const dlib::ustring& label + ); + /*! + requires + - i < number_of_nodes() + ensures + - #node_label(i) == label + !*/ + void set_node_color ( unsigned long i, rgb_pixel color @@ -1561,6 +1899,26 @@ namespace dlib - returns the text label for node graph_node(i) !*/ + const std::wstring node_wlabel ( + unsigned long i + ) const; + /*! + requires + - i < number_of_nodes() + ensures + - returns the text label for node graph_node(i) + !*/ + + const dlib::ustring node_ulabel ( + unsigned long i + ) const; + /*! + requires + - i < number_of_nodes() + ensures + - returns the text label for node graph_node(i) + !*/ + template < typename T > @@ -1749,6 +2107,30 @@ namespace dlib - returns the text in the given grid location !*/ + const std::wstring wtext ( + unsigned long row, + unsigned long col + ) const; + /*! + requires + - row < number_of_rows() + - col < number_of_columns() + ensures + - returns the text in the given grid location + !*/ + + const dlib::ustring utext ( + unsigned long row, + unsigned long col + ) const; + /*! + requires + - row < number_of_rows() + - col < number_of_columns() + ensures + - returns the text in the given grid location + !*/ + void set_text ( unsigned long row, unsigned long col, @@ -1762,6 +2144,32 @@ namespace dlib - #text(row,col) == str !*/ + void set_text ( + unsigned long row, + unsigned long col, + const std::wstring& str + ); + /*! + requires + - row < number_of_rows() + - col < number_of_columns() + ensures + - #text(row,col) == str + !*/ + + void set_text ( + unsigned long row, + unsigned long col, + const dlib::ustring& str + ); + /*! + requires + - row < number_of_rows() + - col < number_of_columns() + ensures + - #text(row,col) == str + !*/ + const rgb_pixel text_color ( unsigned long row, unsigned long col diff --git a/dlib/serialize.h b/dlib/serialize.h index 2d7218dbd..1e3bc2675 100644 --- a/dlib/serialize.h +++ b/dlib/serialize.h @@ -118,6 +118,7 @@ #include "interfaces/enumerable.h" #include "interfaces/map_pair.h" #include "enable_if.h" +#include "unicode.h" namespace dlib { @@ -765,6 +766,40 @@ namespace dlib if (!in) throw serialization_error("Error deserializing object of type std::wstring"); } +// ---------------------------------------------------------------------------------------- + + inline void serialize ( + const ustring& item, + std::ostream& out + ) + { + const unsigned long size = static_cast(item.size()); + try{ serialize(size,out); } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while serializing object of type ustring"); } + + for (unsigned long i = 0; i < item.size(); ++i) + serialize(item[i], out); + if (!out) throw serialization_error("Error serializing object of type ustring"); + } + + inline void deserialize ( + ustring& item, + std::istream& in + ) + { + unsigned long size; + try { deserialize(size,in); } + catch (serialization_error& e) + { throw serialization_error(e.info + "\n while deserializing object of type ustring"); } + + item.resize(size); + for (unsigned long i = 0; i < item.size(); ++i) + deserialize(item[i],in); + + if (!in) throw serialization_error("Error deserializing object of type ustring"); + } + // ---------------------------------------------------------------------------------------- template < diff --git a/dlib/string/string.h b/dlib/string/string.h index 16ad6ef95..6597c6a51 100644 --- a/dlib/string/string.h +++ b/dlib/string/string.h @@ -3,9 +3,9 @@ #ifndef DLIB_STRINg_ #define DLIB_STRINg_ +#include "../algs.h" #include #include -#include "../algs.h" #include "../error.h" #include "../assert.h" #include "string_abstract.h" @@ -227,10 +227,12 @@ namespace dlib std::string temp; temp.reserve(str.size()); std::string::size_type i; - std::basic_ostringstream sout; for (i = 0; i < str.size(); ++i) { - temp += sout.narrow(str[i],' '); + if (zero_extend_cast(str[i]) > 255) + temp += ' '; + else + temp += zero_extend_cast(str[i]); } return temp; } diff --git a/dlib/unicode/unicode.cpp b/dlib/unicode/unicode.cpp new file mode 100644 index 000000000..48dc71df0 --- /dev/null +++ b/dlib/unicode/unicode.cpp @@ -0,0 +1,175 @@ +// Copyright (C) 2008 Keita Mochizuki, Davis E. King (davisking@users.sourceforge.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_UNICODe_CPp_ +#define DLIB_UNICODe_CPp_ +#include "unicode.h" +#include +#include "../string.h" +#include + +namespace dlib +{ + +// ---------------------------------------------------------------------------------------- + + static const unichar SURROGATE_FIRST_TOP = 0xD800; + static const unichar SURROGATE_SECOND_TOP = 0xDC00; + static const unichar SURROGATE_CLEARING_MASK = 0x03FF; + static const unichar &SURROGATE_TOP = SURROGATE_FIRST_TOP; + static const unichar SURROGATE_END = 0xE000; + static const unichar SMP_TOP = 0x10000; + static const int VALID_BITS = 10; + +// ---------------------------------------------------------------------------------------- + + template bool is_surrogate(T ch) + { + return (zero_extend_cast(ch) >= SURROGATE_TOP && + zero_extend_cast(ch) < SURROGATE_END); + } + +// ---------------------------------------------------------------------------------------- + + template unichar surrogate_pair_to_unichar(T first, T second) + { + return ((first & SURROGATE_CLEARING_MASK) << VALID_BITS) | (second & SURROGATE_CLEARING_MASK) + SMP_TOP; + } + //110110 0000000000 + //110111 0000000000 + +// ---------------------------------------------------------------------------------------- + + void unichar_to_surrogate_pair(unichar input, unichar &first, unichar &second) + { + first = ((input - SMP_TOP) >> VALID_BITS) | SURROGATE_FIRST_TOP; + second = (input & SURROGATE_CLEARING_MASK) | SURROGATE_SECOND_TOP; + } + +// ---------------------------------------------------------------------------------------- + + template void wstr2ustring_t(const wchar_t *src, size_t src_len, ustring &dest); + + template <> void wstr2ustring_t<4>(const wchar_t *src, size_t src_len, ustring &dest) + { + dest.assign((const unichar *)(src)); + } + + template <> void wstr2ustring_t<2>(const wchar_t *src, size_t src_len, ustring &dest) + { + size_t wlen = 0; + for (size_t i = 0; i < src_len; i++) + { + is_surrogate(src[i]) ? i++, wlen++ : wlen++; + } + dest.resize(wlen); + for (size_t i = 0, ii = 0; ii < src_len; ++i) + { + if (is_surrogate(src[ii])) + { + dest[i] = surrogate_pair_to_unichar(src[ii], src[ii+1]); + ii += 2; + }else + { + dest[i] = zero_extend_cast(src[ii]); + ii++; + } + } + } + +// ---------------------------------------------------------------------------------------- + + const ustring convert_wstring_to_utf32(const std::wstring &src) + { + ustring dest; + wstr2ustring_t(src.c_str(), src.size(), dest); + return dest; + } + +// ---------------------------------------------------------------------------------------- + + template struct ustring2wstr + { + }; + + // for the environment of sizeof(wchar_t) == 2 (i.e. Win32) + template <> struct ustring2wstr<2> + { + wchar_t *wstr; + size_t wlen; + ustring2wstr(const ustring &src){ + wlen = 0; + for (size_t i = 0; i < src.length(); ++i) + { + if (src[i] < SMP_TOP) wlen++; + else wlen += 2; + } + wstr = new wchar_t[wlen+1]; + wstr[wlen] = L'\0'; + + size_t wi = 0; + for (size_t i = 0; i < src.length(); ++i) + { + if (src[i] < SMP_TOP) + { + wstr[wi++] = (wchar_t)src[i]; + }else + { + unichar high, low; + unichar_to_surrogate_pair(src[i], high, low); + wstr[wi++] = (wchar_t)high; + wstr[wi++] = (wchar_t)low; + } + } + } + ~ustring2wstr() + { + delete[] wstr; + } + }; + + // for the environment of sizeof(wchar_t) == 4 (i.e. Unix gcc) + template <> struct ustring2wstr<4> + { + const wchar_t *wstr; + size_t wlen; + ustring2wstr(const ustring &src){ + wstr = (const wchar_t *)(src.c_str()); + wlen = src.size(); + } + }; + +// ---------------------------------------------------------------------------------------- + + const std::wstring convert_utf32_to_wstring(const ustring &src) + { + ustring2wstr conv(src); + std::wstring dest(conv.wstr); + return dest; + } + +// ---------------------------------------------------------------------------------------- + + const std::wstring convert_mbstring_to_wstring(const std::string &src) + { + std::vector wstr(src.length()+1); + std::mbstowcs(&wstr.front(), src.c_str(), src.length()+1); + return std::wstring(&wstr.front()); + } + +// ---------------------------------------------------------------------------------------- + + const std::string convert_wstring_to_mbstring(const std::wstring &src) + { + using namespace std; + std::string str; + str.resize((src.length() + 1) * MB_CUR_MAX); + wcstombs(&str[0], src.c_str(), str.size()); + return std::string(&str[0]); + } + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_UNICODe_CPp_ + diff --git a/dlib/unicode/unicode.h b/dlib/unicode/unicode.h index 42ce04bd8..44fc71954 100644 --- a/dlib/unicode/unicode.h +++ b/dlib/unicode/unicode.h @@ -7,6 +7,8 @@ #include "../algs.h" #include "unicode_abstract.h" #include +#include + #include namespace dlib @@ -15,7 +17,94 @@ namespace dlib // ---------------------------------------------------------------------------------------- typedef uint32 unichar; + +#if defined(__GNUC__) && __GNUC__ < 4 && __GNUC_MINOR__ < 4 + struct unichar_traits + { + typedef dlib::unichar char_type; + typedef dlib::unichar int_type; + typedef std::streamoff off_type; + typedef std::streampos pos_type; + typedef std::mbstate_t state_type; + + static void assign(char_type& c1, const char_type& c2) { c1 = c2; } + static bool eq(const char_type& c1, const char_type& c2) { return c1 == c2; } + static bool lt(const char_type& c1, const char_type& c2) { return c1 < c2; } + static int compare(const char_type* s1, const char_type* s2, size_t n) + { + for (size_t i = 0; i < n; ++i) + { + if (s1[i] < s2[i]) + return -1; + else if (s1[i] > s2[i]) + return 1; + } + return 0; + } + + static size_t length(const char_type* s) + { + size_t i = 0; + while (s[i] != 0) + ++i; + return i; + } + + static const char_type* find(const char_type* s, size_t n, + const char_type& a) + { + for (size_t i = 0; i < n; ++i) + { + if (s[i] == a) + { + return s+i; + } + } + return 0; + } + + static char_type* move(char_type* s1, const char_type* s2, size_t n) + { + return static_cast(std::memmove(s1, s2, sizeof(char_type)*n)); + } + + static char_type* copy(char_type* s1, const char_type* s2, size_t n) + { + for (size_t i = 0; i < n; ++i) + s1[i] = s2[i]; + + return s1; + } + + static char_type* assign(char_type* s, size_t n, char_type a) + { + for (size_t i = 0; i < n; ++i) + s[i] = a; + + return s; + } + + + static int_type not_eof(const int_type& c) + { + if (!eq_int_type(c,eof())) + return to_int_type(c); + else + return 0; + } + + static char_type to_char_type(const int_type& c) { return static_cast(c); } + static int_type to_int_type(const char_type& c) { return zero_extend_cast(c); } + + static bool eq_int_type(const int_type& c1, const int_type& c2) { return c1 == c2; } + + static int_type eof() { return static_cast(EOF); } + }; + + typedef std::basic_string ustring; +#else typedef std::basic_string ustring; +#endif // ---------------------------------------------------------------------------------------- @@ -419,6 +508,31 @@ namespace dlib return temp; } +// ---------------------------------------------------------------------------------------- + + bool is_surrogate(unichar ch); + + unichar surrogate_pair_to_unichar(unichar first, unichar second); + + void unichar_to_surrogate_pair(unichar unicode, unichar &first, unichar &second); + + + const ustring convert_wstring_to_utf32 ( + const std::wstring &wstr + ); + + const std::wstring convert_utf32_to_wstring ( + const ustring &src + ); + + const std::wstring convert_mbstring_to_wstring ( + const std::string &src + ); + + const std::string convert_wstring_to_mbstring( + const std::wstring &src + ); + // ---------------------------------------------------------------------------------------- template @@ -490,5 +604,9 @@ namespace dlib } +#ifdef NO_MAKEFILE +#include "unicode.cpp" +#endif + #endif // DLIB_UNICODe_H_ diff --git a/dlib/unicode/unicode_abstract.h b/dlib/unicode/unicode_abstract.h index 451902242..ad5b2ec4a 100644 --- a/dlib/unicode/unicode_abstract.h +++ b/dlib/unicode/unicode_abstract.h @@ -33,6 +33,44 @@ namespace dlib - returns false !*/ + bool is_surrogate( + unichar ch + ); + /*! + ensures + - if (ch is a unicode surrogate character) then + - returns true + - else + - returns false + !*/ + + unichar surrogate_pair_to_unichar( + unichar first, + unichar second + ); + /*! + requires + - 0xD800 <= first < 0xDC00 + - 0xDC00 <= second < 0xE000 + - is_surrogate(first) == true + - is_surrogate(second) == true + ensures + - converts two surrogates into one unicode character + !*/ + + void unichar_to_surrogate_pair( + unichar ch, + unichar& first, + unichar& second + ); + /*! + requires + - ch >= 0x10000 (i.e. is not in Basic Multilingual Plane) + ensures + - surrogate_pair_to_unichar(#first,#second) == ch + (i.e. converts ch into two surrogate characters) + !*/ + // ---------------------------------------------------------------------------------------- class invalid_utf8_error : public error @@ -53,6 +91,58 @@ namespace dlib - throws invalid_utf8_error !*/ +// ---------------------------------------------------------------------------------------- + + const ustring convert_wstring_to_utf32 ( + const std::wstring &wstr + ); + /*! + requires + - wstr is a valid UTF-16 string when sizeof(wchar_t) == 2 + - wstr is a valid UTF-32 string when sizeof(wchar_t) == 4 + ensures + - converts wstr into UTF-32 string + !*/ + +// ---------------------------------------------------------------------------------------- + + const std::wstring convert_utf32_to_wstring ( + const ustring &str + ); + /*! + requires + - str is a valid UTF-32 encoded string + ensures + - converts str into wstring whose encoding is UTF-16 when sizeof(wchar_t) == 2 + - converts str into wstring whose encoding is UTF-32 when sizeof(wchar_t) == 4 + !*/ + +// ---------------------------------------------------------------------------------------- + + const std::wstring convert_mbstring_to_wstring ( + const std::string &str + ); + /*! + requires + - str is a valid multibyte string whose encoding is same as current locale setting + ensures + - converts str into wstring whose encoding is UTF-16 when sizeof(wchar_t) == 2 + - converts str into wstring whose encoding is UTF-32 when sizeof(wchar_t) == 4 + !*/ + +// ---------------------------------------------------------------------------------------- + + const std::string convert_wstring_to_mbstring ( + const std::wstring &src + ); + /*! + requires + - str is a valid wide character string string whose encoding is same as current + locale setting + ensures + - returns a multibyte encoded version of the given string + !*/ + // ---------------------------------------------------------------------------------------- template <