diff -cr qt-1.45.orig/configs/freebsd-g++-shared qt-1.45/configs/freebsd-g++-shared *** qt-1.45.orig/configs/freebsd-g++-shared Sat Feb 27 02:01:59 1999 --- qt-1.45/configs/freebsd-g++-shared Thu Jun 1 00:58:41 2000 *************** *** 26,32 **** # Linking applications SYSCONF_LINK = g++ SYSCONF_LFLAGS = ! SYSCONF_LIBS = # Link flags shared objects SYSCONF_LFLAGS_SHOBJ = -shared --- 26,32 ---- # Linking applications SYSCONF_LINK = g++ SYSCONF_LFLAGS = ! SYSCONF_LIBS = -lxpg4 # Link flags shared objects SYSCONF_LFLAGS_SHOBJ = -shared diff -cr qt-1.45.orig/configs/freebsd-g++-shared-debug qt-1.45/configs/freebsd-g++-shared-debug *** qt-1.45.orig/configs/freebsd-g++-shared-debug Sat Feb 27 02:01:59 1999 --- qt-1.45/configs/freebsd-g++-shared-debug Thu Jun 1 00:58:41 2000 *************** *** 26,32 **** # Linking applications SYSCONF_LINK = g++ SYSCONF_LFLAGS = ! SYSCONF_LIBS = # Link flags shared objects SYSCONF_LFLAGS_SHOBJ = -shared --- 26,32 ---- # Linking applications SYSCONF_LINK = g++ SYSCONF_LFLAGS = ! SYSCONF_LIBS = -lxpg4 # Link flags shared objects SYSCONF_LFLAGS_SHOBJ = -shared diff -cr qt-1.45.orig/configs/freebsd-g++-static qt-1.45/configs/freebsd-g++-static *** qt-1.45.orig/configs/freebsd-g++-static Sat Feb 27 02:01:58 1999 --- qt-1.45/configs/freebsd-g++-static Thu Jun 1 00:58:41 2000 *************** *** 26,32 **** # Linking applications SYSCONF_LINK = g++ SYSCONF_LFLAGS = ! SYSCONF_LIBS = # Link flags shared objects SYSCONF_LFLAGS_SHOBJ = -shared --- 26,32 ---- # Linking applications SYSCONF_LINK = g++ SYSCONF_LFLAGS = ! SYSCONF_LIBS = -lxpg4 # Link flags shared objects SYSCONF_LFLAGS_SHOBJ = -shared diff -cr qt-1.45.orig/configs/freebsd-g++-static-debug qt-1.45/configs/freebsd-g++-static-debug *** qt-1.45.orig/configs/freebsd-g++-static-debug Sat Feb 27 02:01:59 1999 --- qt-1.45/configs/freebsd-g++-static-debug Thu Jun 1 00:58:41 2000 *************** *** 26,32 **** # Linking applications SYSCONF_LINK = g++ SYSCONF_LFLAGS = ! SYSCONF_LIBS = # Link flags shared objects SYSCONF_LFLAGS_SHOBJ = -shared --- 26,32 ---- # Linking applications SYSCONF_LINK = g++ SYSCONF_LFLAGS = ! SYSCONF_LIBS = -lxpg4 # Link flags shared objects SYSCONF_LFLAGS_SHOBJ = -shared diff -cr qt-1.45.orig/src/kernel/qapplication_x11.cpp qt-1.45/src/kernel/qapplication_x11.cpp *** qt-1.45.orig/src/kernel/qapplication_x11.cpp Sat Nov 13 01:57:24 1999 --- qt-1.45/src/kernel/qapplication_x11.cpp Thu Jun 1 00:58:52 2000 *************** *** 20,25 **** --- 20,30 ---- ** license which allows creation of commercial/proprietary software. ** *****************************************************************************/ + /* + * X11 I18N Support Patch + * Copyright (C) 1998-2000 by Serika Kurusugawa. + * Date 1998/11/23, Last Modified 2000/01/27 + */ #define select _qt_hide_select #define gettimeofday _qt_hide_gettimeofday *************** *** 36,41 **** --- 41,47 ---- #include "qwidgetlist.h" #include "qwidgetintdict.h" #include "qbitarray.h" + #include "qptrdict.h" #include "qpainter.h" #include "qpixmapcache.h" #include "qdatetime.h" *************** *** 110,115 **** --- 116,123 ---- } #endif + #define XIM_FILTER_ALL + /***************************************************************************** Internal variables and functions *****************************************************************************/ *************** *** 118,123 **** --- 126,132 ---- static char *appFont = 0; // application font static char *appBGCol = 0; // application bg color static char *appFGCol = 0; // application fg color + static char *appLocale = 0; // application locale static char *mwGeometry = 0; // main widget geometry static char *mwTitle = 0; // main widget title static bool mwIconic = FALSE; // main widget iconified *************** *** 186,191 **** --- 195,202 ---- #if !defined(NO_XIM) static XIM xim; + XIMStyle qt_xim_style = 0; + XIMStyle qt_xim_pref_style = XIMPreeditPosition | XIMStatusNothing; #endif timeval *qt_wait_timer(); *************** *** 379,384 **** --- 390,403 ---- static const char * latin9locales[] = { "tr", "tr_TR", "turkish", 0 }; + static const char * japaneselocales[] = { + "ja", "ja_JP", "ja_JP.EUC", "ja_JP.eucJP", "ja_JP.ujis", + "ja_JP.JIS7", "ja_JP.jis7", "ja_JP.JIS", "ja_JP.ISO-2022-JP", + "ja_JP.SJIS", 0 }; + + static const char * chineselocales[] = { + "zh_CN", "zh_CN.GB2312", "zh_TW", "zh_TW.Big5", 0 }; + static bool try_locale( const char * locale[], const char * lang, QFont::CharSet encoding ) { *************** *** 441,447 **** !try_locale( latin6locales, lang, QFont::Latin5 ) && !try_locale( latin7locales, lang, QFont::Latin7 ) && !try_locale( latin8locales, lang, QFont::Latin8 ) && ! !try_locale( latin9locales, lang, QFont::Latin9 ) ) QFont::setDefaultFont( QFont( "Helvetica", 12, QFont::Normal, FALSE, QFont::Latin1 ) ); if ( lang ) // Avoid purify complaint --- 460,468 ---- !try_locale( latin6locales, lang, QFont::Latin5 ) && !try_locale( latin7locales, lang, QFont::Latin7 ) && !try_locale( latin8locales, lang, QFont::Latin8 ) && ! !try_locale( latin9locales, lang, QFont::Latin9 ) && ! !try_locale( japaneselocales, lang, QFont::Japanese ) && ! !try_locale( chineselocales, lang, QFont::Chinese ) ) QFont::setDefaultFont( QFont( "Helvetica", 12, QFont::Normal, FALSE, QFont::Latin1 ) ); if ( lang ) // Avoid purify complaint *************** *** 453,458 **** --- 474,533 ---- qt_init() - initializes Qt for X11 *****************************************************************************/ + #if !defined(NO_XIM) + + #if defined(Q_C_CALLBACKS) + extern "C" { + #endif + + static void + xim_destroy_callback(XIM current_ic, XPointer client_data, XPointer call_data) + { + xim = 0; + qt_xim_style = 0; + + QWidgetList *list = QApplication::allWidgets(); + QWidgetListIt it( *list ); + QWidget *w; + while ( (w = it.current()) ) { // for all widgets... + if ( w->isInputMethodEnabled() ) { + w->internalSetInputMethodEnabled( FALSE ); + } + ++it; + } + delete list; + } + + static void + xim_instantiate_callback(Display *display, XPointer client_data, XPointer call_data) + { + if ( !(xim = XOpenIM(appDpy, 0, 0, 0)) ) { + return; + } + + XIMCallback destroy; + destroy.callback = xim_destroy_callback; + destroy.client_data = 0; + XSetIMValues(xim, XNDestroyCallback, &destroy, 0); + + QWidgetList *list = QApplication::allWidgets(); + QWidgetListIt it( *list ); + QWidget *w; + while ( (w = it.current()) ) { // for all widgets... + if ( w->isInputMethodEnabled() ) { + w->internalSetInputMethodEnabled( TRUE ); + } + ++it; + } + delete list; + } + + #if defined(Q_C_CALLBACKS) + } + #endif + + #endif + static void qt_init_internal( int *argcptr, char **argv, Display *display ) { if ( display ) { *************** *** 504,509 **** --- 579,587 ---- } else if ( arg == "-name" ) { if ( ++i < argc ) appName = argv[i]; + } else if ( arg == "-locale" ) { + if ( ++i < argc ) + appLocale = argv[i]; } else if ( arg == "-title" ) { if ( ++i < argc ) mwTitle = argv[i]; *************** *** 539,544 **** --- 617,635 ---- // ### Should we honor any others? } } + #if !defined(NO_XIM) + } else if ( arg == "-inputstyle" ) { + if ( ++i < argc ) { + QString s = QString(argv[i]).lower(); + if ( s == "overthespot" ) { + qt_xim_pref_style = XIMPreeditPosition | XIMStatusNothing; + } else if ( s == "offthespot" ) { + qt_xim_pref_style = XIMPreeditArea | XIMStatusArea; + } else if ( s == "root" ) { + qt_xim_pref_style = XIMPreeditNothing | XIMStatusNothing; + } + } + #endif } else if ( arg == "-cmap" ) { // xv uses this name qt_cmap_option = TRUE; } *************** *** 655,667 **** QPalette pal( cg, dcg, cg ); QApplication::setPalette( pal ); } ! #if !defined(NO_XIM) ! setlocale( LC_ALL, "" ); // use correct char set mapping setlocale( LC_NUMERIC, "C" ); // make sprintf()/scanf() work if ( XSupportsLocale() && ( qstrlen(XSetLocaleModifiers( "" )) || ! qstrlen(XSetLocaleModifiers( "@im=none" ) ) ) ) ! xim = XOpenIM( appDpy, 0, 0, 0 ); else xim = 0; #endif --- 746,762 ---- QPalette pal( cg, dcg, cg ); QApplication::setPalette( pal ); } ! appLocale = setlocale( LC_ALL, appLocale ? appLocale : "" ); // use correct char set mapping setlocale( LC_NUMERIC, "C" ); // make sprintf()/scanf() work + #if !defined(NO_XIM) if ( XSupportsLocale() && ( qstrlen(XSetLocaleModifiers( "" )) || ! qstrlen(XSetLocaleModifiers( "@im=none" ) ) ) ) { ! if (XRegisterIMInstantiateCallback( appDpy, 0, 0, 0, ! xim_instantiate_callback, 0) != True) { ! xim = 0; ! } ! } else xim = 0; #endif *************** *** 706,711 **** --- 801,808 ---- #if !defined(NO_XIM) if ( xim ) { + XUnregisterIMInstantiateCallback( appDpy, 0, 0, 0, + xim_instantiate_callback, 0); // Calling XCloseIM gives a Purify FMR error // Instead we get a non-critical memory leak // XCloseIM( xim ); *************** *** 883,888 **** --- 980,994 ---- return gc; } + XIM qt_xim() // get X input method + { + #if !defined(NO_XIM) + return xim; + #else + return 0; + #endif + } + /***************************************************************************** Platform specific QApplication members *************** *** 1798,1803 **** --- 1904,1913 ---- if ( quit_now ) // quit between events return FALSE; XNextEvent( appDpy, &event ); // get next event + #if 0 + if (XFilterEvent(&event, None) == True) + return FALSE; + #endif /* 0 */ nevents++; if ( x11ProcessEvent( &event ) == 1 ) *************** *** 1867,1873 **** */ int QApplication::x11ProcessEvent( XEvent* event ) { ! if ( x11EventFilter(event) ) // send through app filter return 1; QETWidget *widget = (QETWidget*)QWidget::find( (WId)event->xany.window ); --- 1977,1983 ---- */ int QApplication::x11ProcessEvent( XEvent* event ) { ! if ( x11EventFilter(event) ) // send through app filterv return 1; QETWidget *widget = (QETWidget*)QWidget::find( (WId)event->xany.window ); *************** *** 1888,1893 **** --- 1998,2025 ---- qPRCleanup( widget ); // remove from alt mapper } + #if !defined(NO_XIM) + #ifdef XIM_FILTER_ALL + QETWidget *f = widget; + switch ( event->type ) { + case KeyPress: // keyboard event + case KeyRelease: + QWidget *g = QWidget::keyboardGrabber(); + if ( g ) + f = (QETWidget*)g; + else if ( focus_widget ) + f = (QETWidget*)focus_widget; + else if ( f ) + f = (QETWidget*)f->topLevelWidget(); + } + #if 1 + if ( XFilterEvent( (XEvent*)event, f ? f->winId() : None ) ) { + return 1; + } + #endif + #endif + #endif + if ( event->type == MappingNotify ) { // keyboard mapping changed XRefreshKeyboardMapping( &event->xmapping ); return 0; *************** *** 1984,1994 **** --- 2116,2143 ---- if ( !qApp->focus_widget || qApp->focus_widget != w ) { // short-circ if ( qApp->focus_widget ) { // Inconsistent messages from X. Force a focus out. + #if !defined(NO_XIM) + if ( xim && qApp->focus_widget->isInputMethodEnabled() ) { + QWExtra *ed = qApp->focus_widget->extraData(); + if ( ed && ed->xic ) { + XUnsetICFocus( (XIC)ed->xic ); + } + } + #endif QFocusEvent out( Event_FocusOut ); QApplication::sendEvent( qApp->focus_widget, &out ); } if ( w && (w->isFocusEnabled() || w->isTopLevel()) ) { qApp->focus_widget = w; + #if !defined(NO_XIM) + if ( xim && w->isInputMethodEnabled() ) { + QWExtra *ed = w->extraData(); + if ( ed && ed->xic ) { + // w->setActiveWindow(); // force X Focus to correct Window + XSetICFocus( (XIC)ed->xic ); + } + } + #endif QFocusEvent in( Event_FocusIn ); QApplication::sendEvent( w, &in ); } else { *************** *** 2002,2007 **** --- 2151,2167 ---- case FocusOut: // lost focus if ( focus_widget ) { + #if !defined(NO_XIM) + if ( xim && focus_widget->isInputMethodEnabled() ) { + QWExtra *ed = focus_widget->extraData(); + if ( ed && ed->xic ) { + #if 0 + /* this causes kinput2 over-the-spot crazy ... */ + XUnsetICFocus( (XIC)ed->xic ); + #endif /* 0 */ + } + } + #endif QFocusEvent out( Event_FocusOut ); QWidget *w = focus_widget; focus_widget = 0; *************** *** 2985,2990 **** --- 3145,3151 ---- static QIntDict *keyDict = 0; static QIntDict *asciiDict = 0; + static QPtrDict *textDict = 0; static void deleteKeyDicts() { *************** *** 2994,3007 **** --- 3155,3186 ---- if ( asciiDict ) delete asciiDict; asciiDict = 0; + if ( textDict ) + delete textDict; + textDict = 0; } + QString QKeyEvent::text() const + { + if ( textDict ) { + QString *str = textDict->find( (void *)this ); + if ( str ) { + return *str; + } + } + return 0; + } bool QETWidget::translateKeyEvent( const XEvent *event, bool grab ) { int type; int code = -1; + #if defined(NO_XIM) char ascii[16]; + #else + char asciiBuf[64]; + char *ascii; + #endif int count = 0; int state; KeySym key = 0; *************** *** 3011,3016 **** --- 3190,3197 ---- keyDict->setAutoDelete( FALSE ); asciiDict = new QIntDict( 13 ); asciiDict->setAutoDelete( TRUE ); + textDict = new QPtrDict( 13 ); + textDict->setAutoDelete( TRUE ); qAddPostRoutine( deleteKeyDicts ); } *************** *** 3023,3063 **** #else // Implementation for X11R5 and newer, using XIM static int composingKeycode; int keycode = event->xkey.keycode; Status status; if ( type == Event_KeyPress ) { ! if ( xim ) { QWExtra * xd = extraData(); ! if ( !xd ) { ! createExtra(); ! xd = extraData(); ! } ! if ( xd->xic == 0 ) ! xd->xic = (void*)XCreateIC( xim, XNInputStyle, ! XIMPreeditNothing+XIMStatusNothing, ! XNClientWindow, winId(), ! 0 ); if ( XFilterEvent( (XEvent*)event, winId() ) ) { composingKeycode = keycode; // ### not documented in xlib return TRUE; } ! count = XmbLookupString( (XIC)(xd->xic), &((XEvent*)event)->xkey, ! ascii, 16, &key, &status ); } else { count = XLookupString( &((XEvent*)event)->xkey, ! ascii, 16, &key, 0 ); } if ( count && !keycode ) { keycode = composingKeycode; composingKeycode = 0; } ! keyDict->replace( keycode, (void*)key ); ! if ( count < 15 ) ! ascii[count] = '\0'; ! if ( count ) ! asciiDict->replace( keycode, new QString(ascii) ); } else { key = (int)(long)keyDict->find( keycode ); if ( key ) --- 3204,3269 ---- #else // Implementation for X11R5 and newer, using XIM + #ifndef XIM_FILTER_ALL static int composingKeycode; + #endif int keycode = event->xkey.keycode; Status status; + ascii = asciiBuf; if ( type == Event_KeyPress ) { ! XIC xic = 0; ! if ( xim && isInputMethodEnabled() ) { QWExtra * xd = extraData(); ! if ( xd ) { ! xic = (XIC)(xd->xic); ! } ! } ! if ( xic ) { ! #ifndef XIM_FILTER_ALL if ( XFilterEvent( (XEvent*)event, winId() ) ) { composingKeycode = keycode; // ### not documented in xlib return TRUE; } ! #endif ! count = XmbLookupString( xic, &((XEvent*)event)->xkey, ! ascii, sizeof(asciiBuf) - 1, &key, &status ); ! if ( status == XBufferOverflow ) { ! ascii = new char[count + 1]; ! count = XmbLookupString( xic, &((XEvent*)event)->xkey, ! ascii, count, &key, &status ); ! } ! if ( status == XLookupNone ) { ! return FALSE; ! } ! // if ( status == XLookupChars ) { ! // key = 0; ! // } ! if ( (status == XLookupChars) || (status == XLookupBoth) ) { ! ! } ! if ((status == XLookupKeySym) || (status == XLookupBoth)) { ! ! } ! ascii[count] = '\0'; } else { count = XLookupString( &((XEvent*)event)->xkey, ! ascii, sizeof(asciiBuf), &key, 0 ); ! if ( count < sizeof(asciiBuf) - 1 ) ! ascii[count] = '\0'; } + #ifndef XIM_FILTER_ALL if ( count && !keycode ) { keycode = composingKeycode; composingKeycode = 0; } ! #endif ! ! if ( key ) { ! keyDict->replace( keycode, (void*)key ); ! if ( count ) ! asciiDict->replace( keycode, new QString(ascii) ); ! } } else { key = (int)(long)keyDict->find( keycode ); if ( key ) *************** *** 3068,3073 **** --- 3274,3282 ---- qstrcpy( ascii, *s ); count = qstrlen( ascii ); delete s; + } else { + ascii[0] = '\0'; + count = 0; } } #endif // !NO_XIM *************** *** 3114,3123 **** --- 3323,3346 ---- return TRUE; } #endif + #if defined(NO_XIM) QKeyEvent e( type, code, count > 0 ? ascii[0] : 0, state ); + #endif if ( popupWidgets ) { // in popup mode QWidget *popup = popupWidgets->last(); + #if defined(NO_XIM) QApplication::sendEvent( popup, &e ); // send event to popup instead + #else + if ( count > 1 ) { + QKeyEvent e( type, 0, 0, state ); + textDict->insert( &e, new QString( ascii ) ); + QApplication::sendEvent( popup, &e ); // send event to popup instead + textDict->remove( &e ); + } else { + QKeyEvent e( type, code, count > 0 ? ascii[0] : 0, state ); + QApplication::sendEvent( popup, &e ); // send event to popup instead + } + #endif if ( popupWidgets ) { // still in popup mode if ( popupGrabOk ) XAllowEvents( dpy, SyncKeyboard, CurrentTime ); *************** *** 3125,3137 **** --- 3348,3382 ---- return TRUE; } if ( type == Event_KeyPress && !grab ) { // send accel event to tlw + #if !defined(NO_XIM) + if ( count <= 1) { + #endif QKeyEvent a( Event_Accel, code, count > 0 ? ascii[0] : 0, state ); a.ignore(); QApplication::sendEvent( topLevelWidget(), &a ); if ( a.isAccepted() ) return TRUE; + #if !defined(NO_XIM) + } + #endif } + #if defined(NO_XIM) return QApplication::sendEvent( this, &e ); + #else + if ( count > 1 ) { + QKeyEvent e(type, 0, 0, state); + textDict->insert( &e, new QString( ascii ) ); + if (ascii != asciiBuf) { + delete[] ascii; + } + bool result = QApplication::sendEvent (this, &e ); + textDict->remove( &e ); + return result; + } else { + QKeyEvent e( type, code, count > 0 ? ascii[0] : 0, state ); + return QApplication::sendEvent( this, &e ); + } + #endif } diff -cr qt-1.45.orig/src/kernel/qevent.h qt-1.45/src/kernel/qevent.h *** qt-1.45.orig/src/kernel/qevent.h Sat Nov 13 01:57:25 1999 --- qt-1.45/src/kernel/qevent.h Thu Jun 1 00:58:42 2000 *************** *** 20,25 **** --- 20,30 ---- ** license which allows creation of commercial/proprietary software. ** *****************************************************************************/ + /* + * X11 I18N Support Patch + * Copyright (C) 1998-2000 by Serika Kurusugawa. + * Date 1998/11/28, Last Modified 2000/01/23 + */ #ifndef QEVENT_H #define QEVENT_H *************** *** 146,151 **** --- 151,157 ---- bool isAccepted() const { return accpt; } void accept() { accpt = TRUE; } void ignore() { accpt = FALSE; } + QString text() const; protected: ushort k, s; uchar a; diff -cr qt-1.45.orig/src/kernel/qfont.h qt-1.45/src/kernel/qfont.h *** qt-1.45.orig/src/kernel/qfont.h Sat Nov 13 01:57:26 1999 --- qt-1.45/src/kernel/qfont.h Thu Jun 1 00:58:42 2000 *************** *** 20,25 **** --- 20,30 ---- ** license which allows creation of commercial/proprietary software. ** *****************************************************************************/ + /* + * X11 I18N Support Patch + * Copyright (C) 2000 by Serika Kurusugawa. + * Date 1998/11/23, Last Modified 2000/01/23 + */ #ifndef QFONT_H #define QFONT_H *************** *** 55,61 **** Latin7, ISO_8859_7 = Latin7, Latin8, ISO_8859_8 = Latin8, Latin9, ISO_8859_9 = Latin9, ! KOI8R }; QFont(); // default font QFont( const char *family, int pointSize = 12, --- 60,66 ---- Latin7, ISO_8859_7 = Latin7, Latin8, ISO_8859_8 = Latin8, Latin9, ISO_8859_9 = Latin9, ! KOI8R, Japanese, Chinese }; QFont(); // default font QFont( const char *family, int pointSize = 12, *************** *** 96,101 **** --- 101,107 ---- bool isCopyOf( const QFont & ) const; HANDLE handle( HANDLE=0 ) const; + void * handle2( HANDLE=0 ) const; const char* rawName() const; diff -cr qt-1.45.orig/src/kernel/qfont_x11.cpp qt-1.45/src/kernel/qfont_x11.cpp *** qt-1.45.orig/src/kernel/qfont_x11.cpp Sat Nov 13 01:57:26 1999 --- qt-1.45/src/kernel/qfont_x11.cpp Thu Jun 1 00:58:42 2000 *************** *** 20,31 **** --- 20,43 ---- ** license which allows creation of commercial/proprietary software. ** *****************************************************************************/ + /* + * X11 I18N Support Patch + * Copyright (C) 1998-2000 by Serika Kurusugawa. + * Date 1998/11/23, Last Modified 2000/01/27 + */ #include "qwidget.h" #include "qpainter.h" #include "qfontdata.h" #include "qcache.h" #include "qdict.h" + #if 1 + #include "qdir.h" + #include "qfile.h" + #include "qlist.h" + #include "qregexp.h" + #include "qtextstream.h" + #endif #include #include #include *************** *** 36,41 **** --- 48,54 ---- #include #include + static const int fontFields = 14; enum FontFieldNames { // X LFD fields *************** *** 72,81 **** int fontMatchScore( char *fontName, QString &buffer, float *pointSizeDiff, int *weightDiff, bool *scalable, bool *polymorphic, ! int *resx, int *resy ); ! QString bestMatch( const char *pattern, int *score ); QString bestFamilyMember( const char *family, int *score ); QString findFont( bool *exact ); }; #undef PRIV --- 85,99 ---- int fontMatchScore( char *fontName, QString &buffer, float *pointSizeDiff, int *weightDiff, bool *scalable, bool *polymorphic, ! int *resx, int *resy, bool is16bit = FALSE ); ! QString bestMatch( const char *pattern, int *score, bool is16bit = FALSE ); QString bestFamilyMember( const char *family, int *score ); + QString bestCharsetMember( const char *charset, int *score ); + QString bestFamilyCharsetMember( const char *family, + const char *charset, + int *score ); QString findFont( bool *exact ); + QString findFontSet( bool *exact ); }; #undef PRIV *************** *** 99,104 **** --- 117,123 ---- const char *name() const; int xResolution() const; XFontStruct *fontStruct() const; + XFontSet fontSet() const; const QFontDef *spec() const; int lineWidth() const; void reset(); *************** *** 107,113 **** void computeLineWidth(); QString n; ! XFontStruct *f; QFontDef s; int lw; int xres; --- 126,132 ---- void computeLineWidth(); QString n; ! XFontSet f; QFontDef s; int lw; int xres; *************** *** 133,138 **** --- 152,180 ---- inline XFontStruct *QFontInternal::fontStruct() const { + XFontStruct **fsl; + char **fnl; + int n = XFontsOfFontSet(f, &fsl, &fnl); + if (n > 0) { + for (int i = 0; i < n; i++) { + QString fn(fnl[i]); + char *tokens[fontFields]; + if (parseXFontName(fn, tokens)) { + if (strcmp(tokens[CharsetRegistry], "iso8859") == 0) { + return fsl[i]; + } + } + } + return fsl[0]; + } + #if defined(CHECK_NULL) + warning( "QFontInternal: No font struct\n" ); + #endif + return 0; + } + + inline XFontSet QFontInternal::fontSet() const + { return f; } *************** *** 154,160 **** inline void QFontInternal::reset() { if ( f ) { ! XFreeFont( QPaintDevice::x__Display(), f ); f = 0; } } --- 196,202 ---- inline void QFontInternal::reset() { if ( f ) { ! XFreeFontSet( QPaintDevice::x__Display(), f ); f = 0; } } *************** *** 216,221 **** --- 258,268 ---- return d->fin->fontStruct(); } + XFontSet qt_get_xfontset( QFontData *d ) + { + return d->fin->fontSet(); + } + /***************************************************************************** QFont member functions *************** *** 318,323 **** --- 365,383 ---- return last; } + void *QFont::handle2( HANDLE ) const + { + static XFontSet last = 0; + if ( DIRTY_FONT ) { + load(); + } else { + if ( d->fin->fontSet() != last ) + fontCache->find( d->fin->name() ); + } + last = d->fin->fontSet(); + return last; + } + /*! Returns the name of the font within the underlying system. Using the return value of this function is usually not *************** *** 521,526 **** --- 581,593 ---- Loads the font. */ + #define DoFS(fontset) \ + XFontStruct **_fs, *fs; \ + char **_fn; \ + int _i, _n; \ + _n = XFontsOfFontSet(fontset, &_fs, &_fn); \ + for (_i = 0; (_i < _n) && (fs = _fs[_i]); _i++) + void QFont::load( HANDLE ) const { if ( !fontCache ) // not initialized *************** *** 538,544 **** if ( !match ) name = lastResortFont(); } else { ! name = PRIV->findFont( &match ); } fn = new QXFontName( name, match ); CHECK_PTR( fn ); --- 605,611 ---- if ( !match ) name = lastResortFont(); } else { ! name = PRIV->findFontSet( &match ); } fn = new QXFontName( name, match ); CHECK_PTR( fn ); *************** *** 555,574 **** fontDict->insert( d->fin->name(), d->fin ); } } ! XFontStruct *f = d->fin->f; if ( !f ) { // font not loaded ! f = XLoadQueryFont( QPaintDevice::x__Display(), n ); if ( !f ) { ! f = XLoadQueryFont( QPaintDevice::x__Display(), lastResortFont()); fn->exactMatch = FALSE; #if defined(CHECK_NULL) if ( !f ) fatal( "QFont::load: Internal error" ); #endif } ! int size = (f->max_bounds.ascent + f->max_bounds.descent) * ! f->max_bounds.width * ! (f->max_char_or_byte2 - f->min_char_or_byte2) / 8; // If we get a cache overflow, we make room for this font only if ( size > fontCache->maxCost() + reserveCost ) fontCache->setMaxCost( size + reserveCost ); --- 622,655 ---- fontDict->insert( d->fin->name(), d->fin ); } } ! XFontSet f = d->fin->f; if ( !f ) { // font not loaded ! char **missing_charset_list; ! int missing_charset_count; ! char *def_string; ! f = XCreateFontSet( QPaintDevice::x__Display(), n, ! &missing_charset_list, &missing_charset_count, ! &def_string); ! if (missing_charset_list) { ! XFreeStringList(missing_charset_list); ! } if ( !f ) { ! f = XCreateFontSet( QPaintDevice::x__Display(), lastResortFont(), ! &missing_charset_list, &missing_charset_count, ! &def_string); fn->exactMatch = FALSE; #if defined(CHECK_NULL) if ( !f ) fatal( "QFont::load: Internal error" ); #endif } ! int size = 0; ! DoFS(f) { ! size += (fs->max_bounds.ascent + fs->max_bounds.descent) * ! fs->max_bounds.width * ! (fs->max_byte1 - fs->min_byte1 + 1) * ! (fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1) / 8; ! } // If we get a cache overflow, we make room for this font only if ( size > fontCache->maxCost() + reserveCost ) fontCache->setMaxCost( size + reserveCost ); *************** *** 607,613 **** int QFont_Private::fontMatchScore( char *fontName, QString &buffer, float *pointSizeDiff, int *weightDiff, bool *scalable , bool *polymorphic, ! int *resx , int *resy ) { char *tokens[fontFields]; bool exactMatch = TRUE; --- 688,695 ---- int QFont_Private::fontMatchScore( char *fontName, QString &buffer, float *pointSizeDiff, int *weightDiff, bool *scalable , bool *polymorphic, ! int *resx , int *resy, ! bool is16bit ) { char *tokens[fontFields]; bool exactMatch = TRUE; *************** *** 621,633 **** if ( !parseXFontName( buffer, tokens ) ) return 0; // Name did not conform to X Logical Font Description ! if ( strncmp( tokens[CharsetRegistry], "ksc", 3 ) == 0 && ! isdigit( tokens[CharsetRegistry][3] ) || ! strncmp( tokens[CharsetRegistry], "jisx", 4 ) == 0 && ! isdigit( tokens[CharsetRegistry][4] ) || ! strncmp( tokens[CharsetRegistry], "gb", 2 ) == 0 && ! isdigit( tokens[CharsetRegistry][2] ) ) { ! return 0; // Dirty way of avoiding common 16 bit charsets ### } #undef IS_ZERO --- 703,720 ---- if ( !parseXFontName( buffer, tokens ) ) return 0; // Name did not conform to X Logical Font Description ! if ( !is16bit ) { ! if ( strncmp( tokens[CharsetRegistry], "ksc", 3 ) == 0 && ! isdigit( tokens[CharsetRegistry][3] ) || ! strncmp( tokens[CharsetRegistry], "jisx", 4 ) == 0 && ! isdigit( tokens[CharsetRegistry][4] ) || ! strncmp( tokens[CharsetRegistry], "big5", 4 ) == 0 || ! strncmp( tokens[CharsetRegistry], "cns", 3 ) == 0 && ! isdigit( tokens[CharsetRegistry][3] ) || ! strncmp( tokens[CharsetRegistry], "gb", 2 ) == 0 && ! isdigit( tokens[CharsetRegistry][2] ) ) { ! return 0; // Dirty way of avoiding common 16 bit charsets ### ! } } #undef IS_ZERO *************** *** 800,806 **** int weightDiff; }; ! QString QFont_Private::bestMatch( const char *pattern, int *score ) { MatchData best; MatchData bestScalable; --- 887,893 ---- int weightDiff; }; ! QString QFont_Private::bestMatch( const char *pattern, int *score, bool is16bit ) { MatchData best; MatchData bestScalable; *************** *** 819,828 **** xFontNames = getXFontNames( pattern, &count ); for( i = 0; i < count; i++ ) { sc = fontMatchScore( xFontNames[i], matchBuffer, &pointDiff, &weightDiff, ! &scalable, &polymorphic, &resx, &resy ); if ( sc > best.score || sc == best.score && pointDiff < best.pointDiff || sc == best.score && pointDiff == best.pointDiff && --- 906,920 ---- xFontNames = getXFontNames( pattern, &count ); + if ((xFontNames == 0) || (count == 0)) { + *score = 0; + return 0; + } + for( i = 0; i < count; i++ ) { sc = fontMatchScore( xFontNames[i], matchBuffer, &pointDiff, &weightDiff, ! &scalable, &polymorphic, &resx, &resy, is16bit ); if ( sc > best.score || sc == best.score && pointDiff < best.pointDiff || sc == best.score && pointDiff == best.pointDiff && *************** *** 891,896 **** --- 983,1006 ---- } + QString QFont_Private::bestCharsetMember( const char *charset, int *score ) + { + char pattern[256]; + sprintf( pattern, "-*-*-*-*-*-*-*-*-*-*-*-*-%s", charset ); + return bestMatch( pattern, score, TRUE ); + } + + + QString QFont_Private::bestFamilyCharsetMember( const char *family, + const char *charset, + int *score ) + { + char pattern[256]; + sprintf( pattern, "-*-%s-*-*-*-*-*-*-*-*-*-*-%s", family, charset ); + return bestMatch( pattern, score, TRUE ); + } + + QString QFont_Private::findFont( bool *exact ) { QString familyName = family(); *************** *** 933,938 **** --- 1043,1228 ---- } + #if 1 + class QResourceTextStream : public QTextStream + { + public: + QResourceTextStream( QIODevice *d ) : QTextStream( d ) {} + QString readLine(); + }; + + QString QResourceTextStream::readLine() + { + QString line(""); + + while ( !eof() ) { + QString s = QTextStream::readLine(); + if ( s.length() == 0 ) { + break; + } + if ( s.data()[0] == '#' ) { + continue; + } + line += s.stripWhiteSpace(); + if ( line.data()[line.length() - 1] == '\\' ) { + line.data()[line.length() - 1] = ' '; + } else { + break; + } + } + return line; + } + + class I18nFontSetEntry { + public: + QString qFontPattern; + QStrList xFontPatterns; + }; + + typedef Q_DECLARE(QListM,I18nFontSetEntry) I18nFontSetInfo; + static I18nFontSetInfo *i18nFontSetInfo = 0; + + /* + * read xlfd pattern info used for creating XFontSet. + */ + void initI18nFontSetInfo() + { + if ( !i18nFontSetInfo ) { + i18nFontSetInfo = new I18nFontSetInfo; + CHECK_PTR( i18nFontSetInfo ); + + QString home = QDir::homeDirPath(); + /* + * open $(HOME)/.qti18nrc file + */ + QFile f( home + "/.qti18nrc" ); + if ( f.open(IO_ReadOnly) ) { + QResourceTextStream t( &f ); + while ( !t.eof() ) { + QString str = t.readLine().simplifyWhiteSpace(); + /* + * parse "family xlfd, xlfd, ..." + */ + int sp = str.find( ' ' ); + if ( sp > 0 ) { + QString qfs = str.left( sp ); // family + str = str.right( str.length() - sp - 1 ); + I18nFontSetEntry *entry = new I18nFontSetEntry(); + entry->qFontPattern = qfs; + while ( str.length() > 0 ) { + QString xfs; + int cp = str.find( ',' ); + if ( cp > 0 ) { + xfs = str.left( cp ).stripWhiteSpace(); // xlfd + str = str.right( str.length() - cp - 1 ); + } else { + xfs = str.stripWhiteSpace(); // last xlfd + str = ""; + } + if ( xfs.length() > 0 ) { + entry->xFontPatterns.append( xfs ); + } + } + if ( entry->xFontPatterns.count() > 0 ) { + i18nFontSetInfo->append( entry ); + } else { + delete entry; + } + } + } + f.close(); + } + } + } + #endif /* 1 */ + + + QString QFont_Private::findFontSet( bool *exact ) + { + QString familyName = substitute( family() ); + *exact = TRUE; // assume exact match + if ( familyName.isEmpty() ) { + familyName = defaultFamily(); + *exact = FALSE; + } + + QStrList namelist; + namelist.append( findFont(exact) ); + + initI18nFontSetInfo(); + if ( i18nFontSetInfo->count() > 0 ){ + I18nFontSetEntry *entry = i18nFontSetInfo->first(); + while ( entry ) { + QRegExp r( entry->qFontPattern, FALSE, TRUE ); + if ( r.match( familyName ) >= 0 ) { + break; + } + entry = i18nFontSetInfo->next(); + } + if ( entry && (entry->xFontPatterns.count() > 0) ) { + char *ptr = entry->xFontPatterns.first(); + while ( ptr ) { + int score; + QString best = bestMatch( ptr, &score, TRUE ); + if ( score > 0 ) { + namelist.append( best ); + } + ptr = entry->xFontPatterns.next(); + } + } + } + + XOM xom = XOpenOM( QPaintDevice::x__Display(), 0, 0, 0 ); + XOMCharSetList csl; + if ( xom ) { + if ( XGetOMValues(xom, XNRequiredCharSet, &csl, NULL) == 0) { + for (int i = 0; i < csl.charset_count; i++) { + QString charset; + bool found = false; + for (char *n = namelist.first(); n != 0; n = namelist.next()) { + QString fn(n); + char *tokens[fontFields]; + if ( parseXFontName(fn, tokens) ) { + charset = tokens[CharsetRegistry]; + charset += "-"; + charset += tokens[CharsetEncoding]; + if ( stricmp( csl.charset_list[i], charset ) == 0 ) { + found = true; + break; + } + } + } + if ( !found ) { + charset = csl.charset_list[i]; + charset.lower(); + int s1, s2; + QString n1, n2; + n1 = bestFamilyCharsetMember( familyName, charset, &s1 ); + n2 = bestCharsetMember( charset, &s2 ); + if ((s1 <= 0) && (s2 <= 0)) { + #if defined(DEBUG) + warning("QFont: Could not find any font for charset %s", + (const char *)charset); + #endif + } else { + namelist.append( (s1 > s2) ? n1 : n2 ); + } + } + } + } + } + + QString name; + for (char *n = namelist.first(); n != 0; n = namelist.next()) { + if ( name.length() > 0 ) { + name += ","; + } + name += n; + } + return name; + } + + /***************************************************************************** QFontMetrics member functions *****************************************************************************/ *************** *** 980,987 **** } } #undef FS ! #define FS (type() == FontInternal ? u.f->fontStruct() : (XFontStruct*)fontStruct()) int QFontMetrics::printerAdjusted(int val) const { --- 1270,1297 ---- } } + void *QFontMetrics::fontSet() const + { + if ( type() == FontInternal ) { + return u.f->fontSet(); + } else if ( type() == Widget && u.w ) { + QFont *f = (QFont *)&u.w->font(); + f->handle(); + return f->d->fin->fontSet(); + } else if ( type() == Painter && u.p ) { + QFont *f = (QFont *)&u.p->font(); + f->handle(); + return f->d->fin->fontSet(); + } else { + #if defined(CHECK_NULL) + warning( "QFontMetrics: Invalid font metrics" ); + #endif + return 0; + } + } + #undef FS ! #define FS (type() == FontInternal ? u.f->fontSet() : (XFontSet)fontSet()) int QFontMetrics::printerAdjusted(int val) const { *************** *** 1007,1013 **** int QFontMetrics::ascent() const { ! return printerAdjusted(FS->max_bounds.ascent); } --- 1317,1329 ---- int QFontMetrics::ascent() const { ! short ascent = SHRT_MIN; // XCharStruct values are declared as short. ! DoFS(FS) { ! if (ascent < fs->max_bounds.ascent) { ! ascent = fs->max_bounds.ascent; ! } ! } ! return printerAdjusted(ascent); } *************** *** 1023,1029 **** int QFontMetrics::descent() const { ! return printerAdjusted(FS->max_bounds.descent - 1); } /*! --- 1339,1351 ---- int QFontMetrics::descent() const { ! short descent = SHRT_MIN; // XCharStruct values are declared as short. ! DoFS(FS) { ! if (descent < fs->max_bounds.descent) { ! descent = fs->max_bounds.descent; ! } ! } ! return printerAdjusted(descent - 1); } /*! *************** *** 1031,1039 **** */ bool QFontMetrics::inFont(char ch) const { ! XFontStruct *f = FS; ! return (uint)(uchar)ch >= f->min_char_or_byte2 ! && (uint)(uchar)ch <= f->max_char_or_byte2; } /*! --- 1353,1369 ---- */ bool QFontMetrics::inFont(char ch) const { ! uint byte1 = 0; ! uint byte2 = (uint)(uchar)ch; ! DoFS(FS) { ! if ((byte1 >= fs->min_byte1) && ! (byte1 <= fs->max_byte1) && ! (byte2 >= fs->min_char_or_byte2) && ! (byte2 <= fs->max_char_or_byte2)) { ! return TRUE; ! } ! } ! return FALSE; } /*! *************** *** 1050,1061 **** */ int QFontMetrics::leftBearing(char ch) const { ! XFontStruct *f = FS; ! if ( !inFont(ch) ) ! ch = f->default_char; ! XCharStruct* cs = f->per_char ! ? f->per_char + ((uchar)ch - f->min_char_or_byte2) ! : &f->max_bounds; return printerAdjusted(cs->lbearing); } --- 1380,1404 ---- */ int QFontMetrics::leftBearing(char ch) const { ! XFontStruct *xfs = 0; ! uint byte1 = 0; ! uint byte2 = (uint)(uchar)ch; ! DoFS(FS) { ! if ((byte1 >= fs->min_byte1) && ! (byte1 <= fs->max_byte1) && ! (byte2 >= fs->min_char_or_byte2) && ! (byte2 <= fs->max_char_or_byte2)) { ! xfs = fs; ! break; ! } ! } ! if (xfs == 0) { ! xfs = _fs[0]; ! ch = _fs[0]->default_char; ! } ! XCharStruct* cs = xfs->per_char ! ? xfs->per_char + (byte2 - xfs->min_char_or_byte2) ! : &xfs->max_bounds; return printerAdjusted(cs->lbearing); } *************** *** 1073,1084 **** */ int QFontMetrics::rightBearing(char ch) const { ! XFontStruct *f = FS; ! if ( !inFont(ch) ) ! ch = f->default_char; ! XCharStruct* cs = f->per_char ! ? f->per_char + ((uchar)ch - f->min_char_or_byte2) ! : &f->max_bounds; return printerAdjusted(cs->width - cs->rbearing); } --- 1416,1440 ---- */ int QFontMetrics::rightBearing(char ch) const { ! XFontStruct *xfs = 0; ! uint byte1 = 0; ! uint byte2 = (uint)(uchar)ch; ! DoFS(FS) { ! if ((byte1 >= fs->min_byte1) && ! (byte1 <= fs->max_byte1) && ! (byte2 >= fs->min_char_or_byte2) && ! (byte2 <= fs->max_char_or_byte2)) { ! xfs = fs; ! break; ! } ! } ! if (xfs == 0) { ! xfs = _fs[0]; ! ch = _fs[0]->default_char; ! } ! XCharStruct* cs = xfs->per_char ! ? xfs->per_char + (byte2 - xfs->min_char_or_byte2) ! : &xfs->max_bounds; return printerAdjusted(cs->width - cs->rbearing); } *************** *** 1092,1099 **** */ int QFontMetrics::minLeftBearing() const { ! // Don't need def->lbearing, the FS stores it. ! return printerAdjusted(FS->min_bounds.lbearing); } /*! --- 1448,1460 ---- */ int QFontMetrics::minLeftBearing() const { ! short lbearing = SHRT_MAX; // XCharStruct values are declared as short. ! DoFS(FS) { ! if (lbearing > fs->min_bounds.lbearing) { ! lbearing = fs->min_bounds.lbearing; ! } ! } ! return printerAdjusted(lbearing); } /*! *************** *** 1110,1129 **** QFontDef* def = (QFontDef*)spec(); if ( def->rbearing == SHRT_MIN ) { ! XFontStruct *f = FS; ! if ( f->per_char ) { ! XCharStruct *c = f->per_char; ! int nc = f->max_char_or_byte2 - f->min_char_or_byte2 + 1; ! int mx = c->width - c->rbearing; ! for ( int i=1; i < nc; i++ ) { ! int nmx = c[i].width - c[i].rbearing; ! if ( nmx < mx ) ! mx = nmx; } - def->rbearing = mx; - } else { - def->rbearing = f->max_bounds.width - f->max_bounds.rbearing; } } return printerAdjusted(def->rbearing); --- 1471,1498 ---- QFontDef* def = (QFontDef*)spec(); if ( def->rbearing == SHRT_MIN ) { ! short rbearing = SHRT_MAX; // XCharStruct values are declared as short. ! DoFS(FS) { ! if ( fs->per_char ) { ! XCharStruct *c = fs->per_char; ! int nc = (fs->max_byte1 - fs->min_byte1 + 1) * ! (fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1); ! int mx = c->width - c->rbearing; ! for ( int i=1; i < nc; i++ ) { ! int nmx = c[i].width - c[i].rbearing; ! if ( nmx < mx ) ! mx = nmx; ! } ! if (rbearing > mx) { ! rbearing = mx; ! } ! } else { ! if (rbearing > fs->max_bounds.width - fs->max_bounds.rbearing) { ! rbearing = fs->max_bounds.width - fs->max_bounds.rbearing; ! } } } + def->rbearing = rbearing; } return printerAdjusted(def->rbearing); *************** *** 1140,1147 **** int QFontMetrics::height() const { ! XFontStruct *f = FS; ! return printerAdjusted(f->max_bounds.ascent + f->max_bounds.descent); } /*! --- 1509,1525 ---- int QFontMetrics::height() const { ! short ascent = SHRT_MIN; // XCharStruct values are declared as short. ! short descent = SHRT_MIN; // XCharStruct values are declared as short. ! DoFS(FS) { ! if (ascent < fs->max_bounds.ascent) { ! ascent = fs->max_bounds.ascent; ! } ! if (descent < fs->max_bounds.descent) { ! descent = fs->max_bounds.descent; ! } ! } ! return printerAdjusted(ascent + descent); } /*! *************** *** 1154,1164 **** int QFontMetrics::leading() const { ! XFontStruct *f = FS; ! int l = f->ascent + f->descent - ! f->max_bounds.ascent - f->max_bounds.descent; ! if ( l > 0 ) { ! return printerAdjusted(l); } else { return 0; } --- 1532,1547 ---- int QFontMetrics::leading() const { ! short leading = SHRT_MIN; // XCharStruct values are declared as short. ! DoFS(FS) { ! int l = fs->ascent + fs->descent - ! fs->max_bounds.ascent - fs->max_bounds.descent; ! if (leading < l) { ! leading = l; ! } ! } ! if ( leading > 0 ) { ! return printerAdjusted(leading); } else { return 0; } *************** *** 1198,1209 **** int QFontMetrics::width( char ch ) const { ! XFontStruct *f = FS; ! if ( !inFont(ch) ) ! ch = f->default_char; ! XCharStruct* cs = f->per_char ! ? f->per_char + ((uchar)ch - f->min_char_or_byte2) ! : &f->max_bounds; return printerAdjusted(cs->width); } --- 1581,1605 ---- int QFontMetrics::width( char ch ) const { ! XFontStruct *xfs = 0; ! uint byte1 = 0; ! uint byte2 = (uint)(uchar)ch; ! DoFS(FS) { ! if ((byte1 >= fs->min_byte1) && ! (byte1 <= fs->max_byte1) && ! (byte2 >= fs->min_char_or_byte2) && ! (byte2 <= fs->max_char_or_byte2)) { ! xfs = fs; ! break; ! } ! } ! if (xfs == 0) { ! xfs = _fs[0]; ! ch = _fs[0]->default_char; ! } ! XCharStruct* cs = xfs->per_char ! ? xfs->per_char + (byte2 - xfs->min_char_or_byte2) ! : &xfs->max_bounds; return printerAdjusted(cs->width); } *************** *** 1226,1232 **** { if ( len < 0 ) len = strlen( str ); ! return printerAdjusted(XTextWidth( FS, str, len )); } --- 1622,1630 ---- { if ( len < 0 ) len = strlen( str ); ! // return printerAdjusted(XmbTextEscapement( FS, str, len )); ! int w = XmbTextEscapement( FS, str, len ); ! return printerAdjusted(w); } *************** *** 1254,1264 **** if ( len < 0 ) len = strlen( str ); ! XFontStruct *f = FS; ! int direction; ! int ascent; ! int descent; XCharStruct overall; bool underline; bool strikeOut; --- 1652,1661 ---- if ( len < 0 ) len = strlen( str ); ! XFontSet f = FS; XCharStruct overall; + XRectangle overall_ink; + XRectangle overall_logical; bool underline; bool strikeOut; *************** *** 1277,1294 **** underline = strikeOut = FALSE; } ! XTextExtents( f, str, len, &direction, &ascent, &descent, &overall ); ! overall.lbearing = printerAdjusted(overall.lbearing); ! overall.rbearing = printerAdjusted(overall.rbearing); ! overall.ascent = printerAdjusted(overall.ascent); ! overall.descent = printerAdjusted(overall.descent); ! overall.width = printerAdjusted(overall.width); ! ! int startX = overall.lbearing; ! int width = overall.rbearing - startX; ! ascent = overall.ascent; ! descent = overall.descent; if ( !underline && !strikeOut ) { width = overall.rbearing - startX; } else { --- 1674,1691 ---- underline = strikeOut = FALSE; } ! int w = XmbTextExtents( f, str, len, &overall_ink, &overall_logical ); ! overall.lbearing = printerAdjusted(overall_ink.x); ! overall.rbearing = printerAdjusted(overall_ink.x + overall_ink.width); ! overall.ascent = printerAdjusted(-overall_ink.y); ! overall.descent = printerAdjusted(overall_ink.y + overall_ink.height); ! overall.width = printerAdjusted(w); ! ! int startX = overall.lbearing; ! int width = overall.rbearing - startX; ! int ascent = overall.ascent; ! int descent = overall.descent; if ( !underline && !strikeOut ) { width = overall.rbearing - startX; } else { *************** *** 1325,1331 **** int QFontMetrics::maxWidth() const { ! return printerAdjusted(FS->max_bounds.width); } --- 1722,1734 ---- int QFontMetrics::maxWidth() const { ! short width = SHRT_MIN; // XCharStruct values are declared as short. ! DoFS(FS) { ! if (width < fs->max_bounds.width) { ! width = fs->max_bounds.width; ! } ! } ! return printerAdjusted(width); } *************** *** 1354,1360 **** int QFontMetrics::strikeOutPos() const { ! int pos = FS->max_bounds.ascent/3; if ( pos ) { return printerAdjusted(pos); } else { --- 1757,1769 ---- int QFontMetrics::strikeOutPos() const { ! short ascent = SHRT_MIN; // XCharStruct values are declared as short. ! DoFS(FS) { ! if (ascent < fs->max_bounds.ascent) { ! ascent = fs->max_bounds.ascent; ! } ! } ! int pos = ascent/3; if ( pos ) { return printerAdjusted(pos); } else { *************** *** 1475,1485 **** static bool fontExists( const char *fontName ) { ! char **fontNames; ! int count; ! fontNames = getXFontNames( fontName, &count ); ! XFreeFontNames( fontNames ); ! return count != 0; } --- 1884,1906 ---- static bool fontExists( const char *fontName ) { ! QString fn(fontName); ! for (int cur = 0; cur < fn.length(); ) { ! int next = fn.find(',', cur); ! if (next < 0) { ! next = fn.length(); ! } ! QString s = fn.mid(cur, next - cur); ! char **fontNames; ! int count; ! fontNames = getXFontNames( s.stripWhiteSpace(), &count ); ! XFreeFontNames( fontNames ); ! if (count == 0) { ! return FALSE; ! } ! cur = next + 1; ! } ! return TRUE; } diff -cr qt-1.45.orig/src/kernel/qfontmetrics.h qt-1.45/src/kernel/qfontmetrics.h *** qt-1.45.orig/src/kernel/qfontmetrics.h Sat Nov 13 01:57:26 1999 --- qt-1.45/src/kernel/qfontmetrics.h Thu Jun 1 00:58:42 2000 *************** *** 20,25 **** --- 20,30 ---- ** license which allows creation of commercial/proprietary software. ** *****************************************************************************/ + /* + * X11 I18N Support Patch + * Copyright (C) 1998-2000 by Serika Kurusugawa. + * Date 1998/11/23, Last Modified 2000/01/23 + */ #ifndef QFONTMETRICS_H #define QFONTMETRICS_H *************** *** 82,87 **** --- 87,93 ---- HDC hdc() const; #elif defined(_WS_X11_) void *fontStruct() const; + void *fontSet() const; int printerAdjusted(int) const; #endif diff -cr qt-1.45.orig/src/kernel/qpainter.cpp qt-1.45/src/kernel/qpainter.cpp *** qt-1.45.orig/src/kernel/qpainter.cpp Sat Nov 13 01:57:27 1999 --- qt-1.45/src/kernel/qpainter.cpp Thu Jun 1 00:58:42 2000 *************** *** 20,25 **** --- 20,30 ---- ** license which allows creation of commercial/proprietary software. ** *****************************************************************************/ + /* + * X11 I18N Support Patch + * Copyright (C) 1998 by Serika Kurusugawa. + * Date 1998/11/23, Last Modified 1999/09/30 + */ #include "qpainter.h" #include "qpaintdevicedefs.h" *************** *** 29,34 **** --- 34,42 ---- #include "qwidget.h" #include "qimage.h" #include + #if !defined(NO_XPG4) + #include + #endif /*! \class QPainter qpainter.h *************** *** 1864,1869 **** --- 1872,1878 ---- const char *p = str; const char *end = &str[len]; while ( p < end ) { + #if defined(NO_XPG4) switch ( *p++ ) { case '\n': newline = TRUE; *************** *** 1874,1880 **** --- 1883,1911 ---- case '&': shortcut = TRUE; break; + } + #else + int l = mblen( p, MB_CUR_MAX ); + if ( l < 0 ) { // error + break; + } else if ( l == 0 ) { // end of string + break; } + if ( l == 1 ) { + switch ( *p ) { + case '\n': + newline = TRUE; + break; + case '\t': + tabbing = TRUE; + break; + case '&': + shortcut = TRUE; + break; + } + } + p += l; + #endif } if ( ((tf & SingleLine) != 0 || !newline) && ((tf & ExpandTabs) == 0 || !tabbing) && *************** *** 1946,1955 **** } void qt_format_text( const QFontMetrics& fm, int x, int y, int w, int h, ! int tf, const char *str, int len, QRect *brect, ! int tabstops, int* tabarray, int tabarraylen, ! char **internal, QPainter* painter ) { if ( w <= 0 || h <= 0 ) fix_neg_rect( &x, &y, &w, &h ); --- 1977,1993 ---- } + #if defined(NO_XPG4) void qt_format_text( const QFontMetrics& fm, int x, int y, int w, int h, ! int tf, const char *str, int len, QRect *brect, ! int tabstops, int* tabarray, int tabarraylen, ! char **internal, QPainter* painter ) ! #else ! void qt_format_str( const QFontMetrics& fm, int x, int y, int w, int h, ! int tf, const char *str, int len, QRect *brect, ! int tabstops, int* tabarray, int tabarraylen, ! char **internal, QPainter* painter ) ! #endif { if ( w <= 0 || h <= 0 ) fix_neg_rect( &x, &y, &w, &h ); *************** *** 2227,2234 **** QRegion save_rgn = painter->crgn; // save the current region bool clip_on = painter->testf(QPainter::ClipOn); ! if ( len > 200 ) { ! p = new char[len]; // buffer for printable string CHECK_PTR( p ); p_alloc = TRUE; } else { --- 2265,2272 ---- QRegion save_rgn = painter->crgn; // save the current region bool clip_on = painter->testf(QPainter::ClipOn); ! if ( len >= 200 ) { ! p = new char[len + 1]; // buffer for printable string CHECK_PTR( p ); p_alloc = TRUE; } else { *************** *** 2365,2370 **** --- 2403,2931 ---- if ( code_alloc ) free( codes ); } + + #if !defined(NO_XPG4) + void qt_format_wcs( const QFontMetrics& fm, int x, int y, int w, int h, + int tf, const wchar_t *str, int len, QRect *brect, + int tabstops, int* tabarray, int tabarraylen, + char **internal, QPainter* painter ) + { + if ( w <= 0 || h <= 0 ) + fix_neg_rect( &x, &y, &w, &h ); + + struct text_info { // internal text info + char tag[4]; // contains "qptr" + int w; // width + int h; // height + int tf; // flags (alignment etc.) + int len; // text length + int maxwidth; // max text width + int nlines; // number of lines + int codelen; // length of encoding + }; + + struct wccode{ + ushort flag; + wchar_t wc; + }; + wccode codearray[200]; + int codelen = 200; + bool code_alloc = FALSE; + wccode *codes = codearray; + wccode cc; // wide character code + bool decode = internal && *internal; // decode from internal data + bool encode = internal && !*internal; // build internal data + + if ( len > 150 && !decode ) { // need to alloc code array + codelen = len + len/2; + codes = (wccode *)malloc( codelen*sizeof(wccode) ); + code_alloc = TRUE; + } + + const int BEGLINE = 0x8000; // encoding 0x8zzz, zzz=width + const int TABSTOP = 0x4000; // encoding 0x4zzz, zzz=tab pos + const int PREFIX = 0x2000; // encoding 0x20zz, zz=char + const int WIDTHBITS= 0x1fff; // bits for width encoding + const int MAXWIDTH = 0x1fff; // max width value + + wchar_t *p = (wchar_t *)str; + int nlines; // number of lines + int index; // index for codes + int begline; // index at beginning of line + int breakindex; // index where to break + int breakwidth; // width of text at breakindex + int maxwidth; // maximum width of a line + int bcwidth; // width of break char + int tabindex; // tab array index + int cw; // character width + int k; // index for p + int tw; // text width + short charwidth[255]; // character widths + memset( charwidth, -1, 255*sizeof(short) ); + + #define WCWIDTH(x) (charwidth[(x)]>=0 ? charwidth[(x)] : (charwidth[(x)]=fm.width(x))) + + bool wordbreak = (tf & WordBreak) == WordBreak; + bool expandtabs = (tf & ExpandTabs) == ExpandTabs; + bool singleline = (tf & SingleLine) == SingleLine; + bool showprefix = (tf & ShowPrefix) == ShowPrefix; + + int spacewidth = WCWIDTH( (int)' ' ); // width of space char + + nlines = 0; + index = 1; // first index contains BEGLINE + begline = breakindex = breakwidth = maxwidth = bcwidth = tabindex = 0; + k = tw = 0; + + if ( decode ) // skip encoding + k = len; + + int localTabStops = 0; // tab stops + if ( tabstops ) + localTabStops = tabstops; + else + localTabStops = fm.width('x')*8; // default to 8 times x + + while ( k < len ) { // convert string to codes + + if ( *p > 32 ) { // printable character + cc.flag = 0; + if ( *p == '&' && showprefix ) { + cc.wc = '&'; // assume ampersand + if ( k < len-1 ) { + k++; + p++; + if ( *p != '&' && *p > 32 ) { + cc.flag = PREFIX; // use prefix char + cc.wc = *p; + } + } + } else { + cc.wc = *p; + } + if ((0 <= cc.wc) && (cc.wc < 256)) { + cw = WCWIDTH( cc.wc ); + } else { + char mb[8]; // must be greater than MB_CUR_MAX + int mblen = wctomb(mb, cc.wc); + cw = fm.width(mb, mblen); + } + + } else { // not printable (except ' ') + + cc.flag = 0; + if ( *p == 32 ) { // the space character + cc.wc = ' '; + cw = spacewidth; + } else if ( *p == '\n' ) { // newline + if ( singleline ) { + cc.wc = ' '; // convert newline to space + cw = spacewidth; + } else { + cc.flag = BEGLINE; + cc.wc = 0; + cw = 0; + } + } else if ( *p == '\t' ) { // TAB character + if ( expandtabs ) { + cw = 0; + if ( tabarray ) { // use tab array + while ( tabindex < tabarraylen ) { + if ( tabarray[tabindex] > tw ) { + cw = tabarray[tabindex] - tw; + tabindex++; + break; + } + tabindex++; + } + } + if ( cw == 0 ) // use fixed tab stops + cw = localTabStops - tw%localTabStops; + cc.flag = TABSTOP | QMIN(tw+cw,MAXWIDTH); + cc.wc = 0; + } else { // convert TAB to space + cc.wc = ' '; + cw = spacewidth; + } + } else { // ignore character + k++; + p++; + continue; + } + + if ( wordbreak ) { // possible break position + breakindex = index; + breakwidth = tw; + bcwidth = cw; + } + } + + if ( wordbreak && breakindex > 0 && tw+cw > w ) { + if ( index == breakindex ) { // break at current index + cc.flag = BEGLINE; + cc.wc = 0; + cw = 0; + } else { // break at breakindex + codes[begline].flag = BEGLINE | QMIN(breakwidth,MAXWIDTH); + maxwidth = QMAX(maxwidth,breakwidth); + begline = breakindex; + nlines++; + tw -= breakwidth + bcwidth; + breakindex = tabindex = 0; + } + } + + tw += cw; // increment text width + + if ( cc.flag == BEGLINE ) { + codes[begline].flag = BEGLINE | QMIN(tw,MAXWIDTH); + maxwidth = QMAX(maxwidth,tw); + begline = index; + nlines++; + tw = 0; + breakindex = tabindex = 0; + } + codes[index++] = cc; + if ( index >= codelen - 1 ) { // grow code array + codelen *= 2; + if ( code_alloc ) { + codes = (wccode *)realloc( codes, sizeof(wccode)*codelen ); + } else { + codes = (wccode *)malloc( sizeof(wccode)*codelen ); + code_alloc = TRUE; + } + } + k++; + p++; + } + + if ( decode ) { // decode from internal data + char *data = *internal; + text_info *ti = (text_info*)data; + if ( strncmp(ti->tag,"qptr",4)!=0 || ti->w != w || ti->h != h || + ti->tf != tf || ti->len != len ) { + #if defined(CHECK_STATE) + warning( "QPainter::drawText: Internal text info is invalid" ); + #endif + return; + } + maxwidth = ti->maxwidth; // get internal values + nlines = ti->nlines; + codelen = ti->codelen; + codes = (wccode *)(data + sizeof(text_info)); + } else { + codes[begline].flag = BEGLINE | QMIN(tw,MAXWIDTH); + maxwidth = QMAX(maxwidth,tw); + nlines++; + codes[index].flag = 0; + codes[index].wc = 0; + index++; + codelen = index; + } + + if ( encode ) { // build internal data + char *data = new char[sizeof(text_info)+codelen*sizeof(wccode)]; + text_info *ti = (text_info*)data; + strncpy( ti->tag, "qptr", 4 ); // set tag + ti->w = w; // save parameters + ti->h = h; + ti->tf = tf; + ti->len = len; + ti->maxwidth = maxwidth; + ti->nlines = nlines; + ti->codelen = codelen; + memcpy( data+sizeof(text_info), codes, codelen*sizeof(wccode) ); + *internal = data; + } + + int fascent = fm.ascent(); // get font measurements + int fheight = fm.height(); + int xp, yp; + int xc; // character xp + wchar_t p_array[200]; + bool p_alloc; + + if ( (tf & AlignVCenter) == AlignVCenter ) // vertically centered text + yp = h/2 - nlines*fheight/2; + else if ( (tf & AlignBottom) == AlignBottom)// bottom aligned + yp = h - nlines*fheight; + else // top aligned + yp = 0; + maxwidth -= fm.minLeftBearing()+fm.minRightBearing(); + if ( (tf & AlignRight) == AlignRight ) { + xp = w - maxwidth; // right aligned + } else if ( (tf & AlignHCenter) == AlignHCenter ) { + xp = w/2 - maxwidth/2; // centered text + } else { + xp = 0; // left aligned + } + + #if defined(CHECK_RANGE) + int hAlignFlags = 0; + if ( (tf & AlignRight) == AlignRight ) + hAlignFlags++; + if ( (tf & AlignHCenter) == AlignHCenter ) + hAlignFlags++; + if ( (tf & AlignLeft ) == AlignLeft ) + hAlignFlags++; + + if ( hAlignFlags > 1 ) + warning("QPainter::drawText: More than one of AlignRight, AlignLeft\n" + " and AlignHCenter set in the tf parameter." + ); + + int vAlignFlags = 0; + if ( (tf & AlignTop) == AlignTop ) + vAlignFlags++; + if ( (tf & AlignVCenter) == AlignVCenter ) + vAlignFlags++; + if ( (tf & AlignBottom ) == AlignBottom ) + vAlignFlags++; + + if ( hAlignFlags > 1 ) + warning("QPainter::drawText: More than one of AlignTop, AlignBottom\n" + " and AlignVCenter set in the tf parameter." + ); + #endif // CHECK_RANGE + + QRect br( x+xp, y+yp, maxwidth, nlines*fheight ); + if ( brect ) // set bounding rect + *brect = br; + + if ( !painter || (tf & DontPrint) != 0 ) { // can't/don't print any text + if ( code_alloc ) + free( codes ); + return; + } + + // From here, we have a painter. + + QRegion save_rgn = painter->crgn; // save the current region + bool clip_on = painter->testf(QPainter::ClipOn); + + if ( len >= 200 ) { + p = new wchar_t[len + 1]; // buffer for printable string + CHECK_PTR( p ); + p_alloc = TRUE; + } else { + p = p_array; + p_alloc = FALSE; + } + + if ( br.x() >= x && br.y() >= y && br.width() < w && br.height() < h ) + tf |= DontClip; // no need to clip + + if ( (tf & DontClip) == 0 ) { // clip text + QRegion new_rgn; + QRect r( x, y, w, h ); + if ( painter->txop == TxRotShear ) { // world xform active + QPointArray a( r ); // complex region + a = painter->xForm( a ); + new_rgn = QRegion( a ); + } else { + r = painter->xForm( r ); + new_rgn = QRegion( r ); + } + if ( clip_on ) // combine with existing region + new_rgn = new_rgn.intersect( painter->crgn ); + painter->setClipRegion( new_rgn ); + } + + QBitmap *mask; + QPainter *pp; + QPixmap *pm; + + if ( (tf & GrayText) == GrayText ) { // prepare to draw gray text + // #### NOTE: will not work with too-big-to-fit unclipped text. + mask = new QBitmap( w, fheight ); + CHECK_PTR( mask ); + pp = new QPainter( mask ); + pp->setBrush( Dense4Pattern ); + pp->setBackgroundMode( TransparentMode ); + pp->setPen( color1 ); + CHECK_PTR( pp ); + pm = new QPixmap( w, fheight ); + CHECK_PTR( pm ); + } else { + mask = 0; + pp = 0; + pm = 0; + } + + yp += fascent; + + register wccode *cp = codes; + + while ( cp->flag || cp->wc ) { // finally, draw the text + + tw = cp->flag & WIDTHBITS; // text width + cp++; + + if ( tw == 0 ) { // ignore empty line + while ( (cp->flag || cp->wc) && (cp->flag & BEGLINE) != BEGLINE ) + cp++; + yp += fheight; + continue; + } + + if ( (tf & AlignRight) == AlignRight ) { + xc = w - tw + fm.minRightBearing(); + } else if ( (tf & AlignHCenter) == AlignHCenter ) { + xc = w/2 - (tw-fm.minLeftBearing()-fm.minRightBearing())/2 + - fm.minLeftBearing(); + } else { + xc = -fm.minLeftBearing(); + } + + if ( pp ) // erase pixmap if gray text + pp->fillRect( 0, 0, w, fheight, color0 ); + + int bxc = xc; // base x position (chars) + while ( TRUE ) { + k = 0; + while ( (cp->flag || cp->wc) && (cp->flag & (BEGLINE|TABSTOP)) == 0 ) { + if ( (cp->flag & PREFIX) == PREFIX ) { + int xcpos; + { + wchar_t tmp = p[k]; + p[k] = 0; + char *mb = new char[MB_CUR_MAX * k + 1]; + int mblen = wcstombs(mb, p, MB_CUR_MAX * k + 1); + xcpos = fm.width(mb, mblen); + p[k] = tmp; + delete[] mb; + } + if ((0 <= cp->wc) && (cp->wc < 256)) { + cw = WCWIDTH( cp->wc ); + } else { + char mb[8]; // must be greater than MB_CUR_MAX + int mblen = wctomb(mb, cp->wc); + cw = fm.width(mb, mblen); + } + if ( pp ) // gray text + pp->fillRect( xc+xcpos, fascent+fm.underlinePos(), + cw, fm.lineWidth(), + color1 ); + else + painter->fillRect( x+xc+xcpos, y+yp+fm.underlinePos(), + cw, fm.lineWidth(), + painter->cpen.color() ); + } + p[k++] = cp->wc; + cp++; + } + { + wchar_t tmp = p[k]; + p[k] = 0; + char *mb = new char[MB_CUR_MAX * k + 1]; + int mblen = wcstombs(mb, p, MB_CUR_MAX * k + 1); + if ( pp ) // gray text + pp->drawText( xc, fascent, mb, mblen ); + else + painter->drawText( x+xc, y+yp, mb, mblen ); // draw the text + p[k] = tmp; + delete[] mb; + } + if ( (cp->flag & TABSTOP) == TABSTOP ) { + int w = (cp->flag & WIDTHBITS); + cp++; + xc = bxc + w; + } else { // *cp == 0 || *cp == BEGLINE + break; + } + } + if ( pp ) { // gray text + pp->setPen(color0); + pp->drawRect( mask->rect() ); + pp->setPen(color1); + pm->fill( painter->cpen.color() ); + pp->end(); + pm->setMask( *mask ); + painter->drawPixmap( x, y+yp-fascent, *pm ); + pp->begin( mask ); + } + + yp += fheight; + } + + if ( pp ) { // gray text + pp->end(); + delete pp; + delete pm; + } + + if ( (tf & DontClip) == 0 ) { // restore clipping + if ( clip_on ) { // set original region + painter->setClipRegion( save_rgn ); + } else { // clipping was off + painter->crgn = save_rgn; + painter->setClipping( FALSE ); + } + } + + if ( p_alloc ) + delete [] p; + if ( code_alloc ) + free( codes ); + } + + void qt_format_mbs( const QFontMetrics& fm, int x, int y, int w, int h, + int tf, const char *str, int len, QRect *brect, + int tabstops, int* tabarray, int tabarraylen, + char **internal, QPainter* painter ) + { + wchar_t local_wcs[64]; + wchar_t *wcs = 0; + int n = len; + if (str) { + char *string; + if (len < strlen(str)) { + string = (char *)malloc(len + 1); + strncpy(string, str, len); + string[len] = '\0'; + } else { + string = (char *)str; + } + if (len < sizeof(local_wcs) / sizeof(local_wcs[0])) { + wcs = local_wcs; + } else { + wcs = (wchar_t *)malloc(sizeof(wchar_t) * (len + 1)); + } + n = mbstowcs(wcs, string, len + 1); + if (string != str) { + free(string); + } + } + #if defined(CHECK_RANGE) + if (n < 0) { + /* warning( "qt_format_mbs: mbstowcs() failed, errno %d\n", errno ); */ + return; + } + #endif + qt_format_wcs(fm, x, y, w, h, tf, wcs, n, brect, + tabstops, tabarray, tabarraylen, + internal, painter); + if ((wcs != 0) && (wcs != local_wcs)) { + free(wcs); + } + } + + void qt_format_text( const QFontMetrics& fm, int x, int y, int w, int h, + int tf, const char *str, int len, QRect *brect, + int tabstops, int* tabarray, int tabarraylen, + char **internal, QPainter* painter ) + { + if (MB_CUR_MAX == 1) { + qt_format_str(fm, x, y, w, h, tf, str, len, brect, + tabstops, tabarray, tabarraylen, + internal, painter); + } else { + qt_format_mbs(fm, x, y, w, h, tf, str, len, brect, + tabstops, tabarray, tabarraylen, + internal, painter); + } + } + #endif /* !NO_XPG4 */ /*! diff -cr qt-1.45.orig/src/kernel/qpainter.h qt-1.45/src/kernel/qpainter.h *** qt-1.45.orig/src/kernel/qpainter.h Sat Nov 13 01:57:27 1999 --- qt-1.45/src/kernel/qpainter.h Thu Jun 1 00:58:42 2000 *************** *** 20,25 **** --- 20,30 ---- ** license which allows creation of commercial/proprietary software. ** *****************************************************************************/ + /* + * X11 I18N Support Patch + * Copyright (C) 1998-2000 by Serika Kurusugawa. + * Date 1998/11/23, Last Modified 2000/01/23 + */ #ifndef QPAINTER_H #define QPAINTER_H *************** *** 311,316 **** --- 316,335 ---- int tf, const char *str, int len, QRect *brect, int tabstops, int* tabarray, int tabarraylen, char **internal, QPainter* painter ); + #if !defined(NO_XPG4) + friend void qt_format_str( const QFontMetrics& fm, int x, int y, int w, int h, + int tf, const char *str, int len, QRect *brect, + int tabstops, int* tabarray, int tabarraylen, + char **internal, QPainter* painter ); + friend void qt_format_mbs( const QFontMetrics& fm, int x, int y, int w, int h, + int tf, const char *str, int len, QRect *brect, + int tabstops, int* tabarray, int tabarraylen, + char **internal, QPainter* painter ); + friend void qt_format_wcs( const QFontMetrics& fm, int x, int y, int w, int h, + int tf, const wchar_t *str, int len, QRect *brect, + int tabstops, int* tabarray, int tabarraylen, + char **internal, QPainter* painter ); + #endif /* NO_XPG4 */ private: // Disabled copy constructor and operator= #if defined(Q_DISABLE_COPY) diff -cr qt-1.45.orig/src/kernel/qpainter_x11.cpp qt-1.45/src/kernel/qpainter_x11.cpp *** qt-1.45.orig/src/kernel/qpainter_x11.cpp Sat Nov 13 01:57:27 1999 --- qt-1.45/src/kernel/qpainter_x11.cpp Thu Jun 1 00:58:42 2000 *************** *** 20,25 **** --- 20,30 ---- ** license which allows creation of commercial/proprietary software. ** *****************************************************************************/ + /* + * X11 I18N Support Patch + * Copyright (C) 1998-2000 by Serika Kurusugawa. + * Date 1998/11/23, Last Modified 2000/01/27 + */ #include "qpainter.h" #include "qpaintdevicedefs.h" *************** *** 2511,2528 **** } } if ( bg_mode == OpaqueMode ) { // opaque fill ! extern XFontStruct *qt_get_xfontstruct( QFontData * ); ! XFontStruct *fs = qt_get_xfontstruct( cfont.d ); ! int direction; int ascent; int descent; XCharStruct overall; ! XTextExtents( fs, str, len, &direction, &ascent, &descent, ! &overall ); int fx = x; ! int fy = y - ascent; ! int fw = overall.width; ! int fh = ascent + descent; int m, n; QPointArray a(5); mat1.map( fx, fy, &m, &n ); a.setPoint( 0, m, n ); --- 2516,2534 ---- } } if ( bg_mode == OpaqueMode ) { // opaque fill ! extern XFontSet qt_get_xfontset( QFontData * ); ! XFontSet fs = qt_get_xfontset( cfont.d ); int ascent; int descent; XCharStruct overall; ! XRectangle overall_ink; ! XRectangle overall_logical; ! int w = XmbTextExtents( fs, str, len, ! &overall_ink, &overall_logical ); int fx = x; ! int fy = y + overall_ink.y; ! int fw = w; ! int fh = overall_ink.height; int m, n; QPointArray a(5); mat1.map( fx, fy, &m, &n ); a.setPoint( 0, m, n ); *************** *** 2562,2570 **** } if ( bg_mode == TransparentMode ) ! XDrawString( dpy, hd, gc, x, y, str, len ); else ! XDrawImageString( dpy, hd, gc, x, y, str, len ); if ( cfont.underline() || cfont.strikeOut() ) { QFontMetrics fm = fontMetrics(); --- 2568,2576 ---- } if ( bg_mode == TransparentMode ) ! XmbDrawString( dpy, hd,(XFontSet)cfont.handle2(), gc, x, y, str, len ); else ! XmbDrawImageString( dpy, hd, (XFontSet)cfont.handle2(), gc, x, y, str, len ); if ( cfont.underline() || cfont.strikeOut() ) { QFontMetrics fm = fontMetrics(); diff -cr qt-1.45.orig/src/kernel/qpsprinter.cpp qt-1.45/src/kernel/qpsprinter.cpp *** qt-1.45.orig/src/kernel/qpsprinter.cpp Sat Nov 13 01:57:27 1999 --- qt-1.45/src/kernel/qpsprinter.cpp Thu Jun 1 00:58:42 2000 *************** *** 43,48 **** --- 43,54 ---- #endif #include + #define EUC_JP + #ifdef EUC_JP + #include + #define KANJISCALESIZE "1.0" + #endif + // Note: this is comment-stripped and word-wrapped later. static const char *ps_header[] = { "/D {bind def} bind def", // first word MUST be shorter than 78 characters *************** *** 2095,2101 **** QString key; int cs = (int)f.charSet(); ! if ( cs == QFont::AnyCharSet ) { QIntDictIterator it( d->headerEncodings ); if ( it.current() ) cs = it.currentKey(); --- 2101,2108 ---- QString key; int cs = (int)f.charSet(); ! if ( cs == QFont::AnyCharSet || ! cs == QFont::Japanese || cs == QFont::Chinese ) { QIntDictIterator it( d->headerEncodings ); if ( it.current() ) cs = it.currentKey(); *************** *** 2142,2149 **** --- 2149,2180 ---- ++d->headerFontNumber; d->fontStream << "/F" << d->headerFontNumber << " " << f.pointSize() << fontName << " DF\n"; + #ifdef EUC_JP + QString fontNameSave = fontName; + #endif /* EUC_JP */ fontName.sprintf( "F%d", d->headerFontNumber ); d->headerFontNames.insert( key, new QString( fontName ) ); + #ifdef EUC_JP + d->fontStream << "/F" << d->headerFontNumber << "en " + << f.pointSize() << fontNameSave << " DF\n"; + d->fontStream << "/F" << (d->headerFontNumber)-1 ; + if ( strstr(ps,"Helvetica") || strstr(ps,"Bold") ) { + if ( strstr(ps,"Italic") || strstr(ps,"Oblique") ) { + d->fontStream << "jp{ GothicSlant } def\n"; + } else { + d->fontStream << "jp{ Gothic } def\n"; + } + } else { + if ( strstr(ps,"Italic") || strstr(ps,"Oblique") ) { + d->fontStream << "jp{ MinchoSlant } def\n"; + } else { + d->fontStream << "jp{ Mincho } def\n"; + } + } + d->fontStream << "/F" << d->headerFontNumber << "{ /Fno " + << d->headerFontNumber << " def /Fs " << f.pointSize() + << " def " << "F" << d->headerFontNumber << "en } def\n"; + #endif /* EUC_JP */ } else { if ( !d->headerEncodings.find( cs ) && !d->pageEncodings.find( cs ) ) { *************** *** 2438,2443 **** --- 2469,2535 ---- #endif const char * from = p[1].str; char * to = tmp; + #ifdef EUC_JP + #define isasciichar(a) (0x20 <= (char)(a) && (char)(a) <= 0x7e) + #define iseucchar(a) (0xa0 <= (unsigned char)(a) && (unsigned char)(a) <= 0xfe) + #define AsciiFlag 1 + #define KanjiFlag 2 + #define MixFlag (AsciiFlag|KanjiFlag) + int flag = 0; + for (const char *ptr = from; *ptr; ptr++) { + if (isasciichar(*ptr)) { + flag |= AsciiFlag; + } else if (iseucchar(*ptr)) { + flag |= KanjiFlag; + } + } + if ( flag == MixFlag ) { + stream << "/addoffs 0 def\n"; + } + while ( *from ) { + if ( isasciichar(*from) ) { + to = tmp; + while ( isasciichar(*from) ) { + if ( *from == '\\' || + *from == '(' || + *from == ')' ) { + *to++ = '\\'; // escape special chars + } + *to++ = *from++; + } + *to = '\0'; + stream << "(" << tmp << ")"; + if ( flag == MixFlag ) { + stream << " dup " << + XCOORD(p[0].point->x()) << " addoffs add " << + YCOORD(p[0].point->y()) << " T Astrwidth\n"; + } else { + stream << POINT(0) << "T\n"; + } + } else if ( iseucchar(*from) ) { + to = tmp; + while ( iseucchar(*from) ) { + if ( (*from & 0x7f) == '\\' || + (*from & 0x7f) == '(' || + (*from & 0x7f) == ')' ) { + *to++ = '\\'; // escape special chars + } + *to++ = *from++ & 0x7f; // EUC to JIS conv. + } + *to = '\0'; + stream << "(" << tmp << ")"; + if ( flag == MixFlag ) { + stream << " dup " << + XCOORD(p[0].point->x()) << " addoffs add " << + YCOORD(p[0].point->y()) << " Tja Kstrwidth\n"; + } else { + stream << POINT(0) << "Tja\n"; + } + } else { + from++; + } + } + #else while ( *from ) { if ( *from == '\\' || *from == '(' || *from == ')' ) *to++ = '\\'; // escape special chars *************** *** 2445,2450 **** --- 2537,2543 ---- } *to = '\0'; stream<< "(" << tmp << ")" << POINT(0) << "T\n"; + #endif /* EUC_JP */ delete [] tmp; } break; *************** *** 2597,2602 **** --- 2690,2713 ---- << tmp.dx() << ' ' << tmp.dy() << "]ST\n"; dirtyMatrix = FALSE; + #ifdef EUC_JP + QString fn; + fn += getenv("HOME"); + fn += "/.kde/.kanjifontscale"; + FILE *fp; + if ( fp = fopen(fn, "r") ) { + float fk; + fscanf(fp, "%f", &fk); + // printf("KanjiFontScaleSize Multiple:%.3f\n",fk); + stream << "/kscalesize " << tmp.m11() << ' ' + << fk << " mul def\n"; + fclose(fp); + } else { + // printf("KanjiFontScaleSize Multiple:%s\n",KANJISCALESIZE); + stream << "/kscalesize " << tmp.m11() << ' ' + << KANJISCALESIZE << " mul def\n"; + } + #endif /* EUC_JP */ } void QPSPrinter::orientationSetup() *************** *** 2659,2664 **** --- 2770,2820 ---- stream.writeRawBytes( (const char *)(d->fontBuffer->buffer().data()), d->fontBuffer->buffer().size() ); } + #ifdef EUC_JP + stream << "/Mincho{\n"; + stream << " /Ryumin-Light-H findfont kscalesize scalefont\n"; + stream << " [ Fs 0 0 Fs -1 mul 0 0] makefont\n"; + stream << "}def\n"; + stream << "/MinchoSlant{\n"; + stream << " /Ryumin-Light-H findfont kscalesize scalefont\n"; + stream << " [ Fs 0 Fs 0.2 mul Fs -1 mul 0 0] makefont\n"; + stream << "}def\n"; + stream << "/Gothic{\n"; + stream << " /GothicBBB-Medium-H findfont kscalesize scalefont\n"; + stream << " [ Fs 0 0 Fs -1 mul 0 0] makefont\n"; + stream << "}def\n"; + stream << "/GothicSlant{\n"; + stream << " /GothicBBB-Medium-H findfont kscalesize scalefont\n"; + stream << " [ Fs 0 Fs 0.2 mul Fs -1 mul 0 0] makefont\n"; + stream << "}def\n"; + stream << "/setEnglishFont{\n"; + stream << " Fno 2 eq { F2en F } if\n"; + stream << " Fno 4 eq { F4en F } if\n"; + stream << " Fno 6 eq { F6en F } if\n"; + stream << " Fno 8 eq { F8en F } if\n"; + stream << " Fno 10 eq { F10en F } if\n"; + stream << "}def\n"; + stream << "/setKanjiFont{\n"; + stream << " Fno 2 eq { F1jp F } if\n"; + stream << " Fno 4 eq { F3jp F } if\n"; + stream << " Fno 6 eq { F5jp F } if\n"; + stream << " Fno 8 eq { F7jp F } if\n"; + stream << " Fno 10 eq { F9jp F } if\n"; + stream << "}def\n"; + stream << "/Tja{\n"; + stream << " setKanjiFont\n"; + stream << " MT PCol SC show\n"; + stream << " setEnglishFont\n"; + stream << "}def\n"; + stream << "/Kstrwidth {\n"; + stream << " setKanjiFont\n"; + stream << " stringwidth pop /addoffs exch addoffs add def\n"; + stream << " setEnglishFont\n"; + stream << "}def\n"; + stream << "/Astrwidth {\n"; + stream << " stringwidth pop /addoffs exch addoffs add def\n"; + stream << "}def\n"; + #endif /* EUC_JP */ stream << "%%EndProlog\n"; stream.writeRawBytes( (const char *)(d->buffer->buffer().data()), d->buffer->buffer().size() ); diff -cr qt-1.45.orig/src/kernel/qwidget.cpp qt-1.45/src/kernel/qwidget.cpp *** qt-1.45.orig/src/kernel/qwidget.cpp Sat Nov 13 01:57:28 1999 --- qt-1.45/src/kernel/qwidget.cpp Thu Jun 1 00:58:42 2000 *************** *** 20,25 **** --- 20,30 ---- ** license which allows creation of commercial/proprietary software. ** *****************************************************************************/ + /* + * X11 I18N Support Patch + * Copyright (C) 1998-2000 by Serika Kurusugawa. + * Date 1998/11/29, Last Modified 2000/01/27 + */ #include "qobjectlist.h" #include "qobjectdict.h" *************** *** 41,46 **** --- 46,54 ---- #include #endif #endif + #if defined(_WS_X11_) && !defined(NO_XIM) + #include + #endif /*! \class QWidget qwidget.h *************** *** 609,614 **** --- 617,623 ---- winid = 0; // default attributes flags = f; focusChild = 0; + clearWFlags( WInputMethodEnabled ); extra = 0; // no extra widget info if ( !deferredMoves ) // do it only once initDeferredDicts(); *************** *** 1730,1735 **** --- 1739,1759 ---- fnt = font; fnt.handle(); // force load font fontChange( old ); + #if defined(_WS_X11_) && !defined(NO_XIM) + if ( qt_xim() && isInputMethodEnabled() ) { + QWExtra *ed = extraData(); + if ( ed && ed->xic ) { + XFontSet fontset = (XFontSet)fnt.handle2(); + XVaNestedList list; + list = XVaCreateNestedList( 0, + XNFontSet, fontset, + 0 ); + XSetICValues( (XIC)ed->xic, + XNPreeditAttributes, list, + 0 ); + } + } + #endif PropagationMode m = fontPropagation(); if ( m != NoChildren && children() ) { QObjectListIt it( *children() ); *************** *** 1997,2007 **** --- 2021,2058 ---- if ( qApp->focus_widget && qApp->focus_widget != this ) { QWidget * prev = qApp->focus_widget; qApp->focus_widget = this; + #if defined(_WS_X11_) && !defined(NO_XIM) + if ( qt_xim() && prev->isInputMethodEnabled() ) { + QWExtra *ed = prev->extraData(); + if ( ed && ed->xic ) { + XUnsetICFocus( (XIC)ed->xic ); + } + // force X Focus to correct Window + if ( prev->isActiveWindow() ) { + prev->setActiveWindow(); + } + } + #endif QFocusEvent out( Event_FocusOut ); QApplication::sendEvent( prev, &out ); } qApp->focus_widget = this; + #if defined(_WS_X11_) && !defined(NO_XIM) + if ( qt_xim() && isInputMethodEnabled() ) { + QWExtra *ed = extraData(); + if ( ed && ed->xic ) { + // force X Focus to correct Window + if ( isActiveWindow() ) { + setActiveWindow(); + } + XSetICValues( (XIC)ed->xic, + XNFocusWindow, winId(), + 0 ); + XSetICFocus( (XIC)ed->xic ); + } + } + #endif QFocusEvent in( Event_FocusIn ); QApplication::sendEvent( this, &in ); } else { *************** *** 2033,2038 **** --- 2084,2101 ---- if ( w && w->focusWidget() == this ) { // clear active focus qApp->focus_widget = 0; + #if defined(_WS_X11_) && !defined(NO_XIM) + if ( qt_xim() && w->isInputMethodEnabled() ) { + QWExtra *ed = w->extraData(); + if ( ed && ed->xic ) { + XUnsetICFocus( (XIC)ed->xic ); + } + // force X Focus to correct Window + if ( w->isActiveWindow() ) { + w->setActiveWindow(); + } + } + #endif QFocusEvent out( Event_FocusOut ); QApplication::sendEvent( w, &out ); } *************** *** 2892,2897 **** --- 2955,2979 ---- break; case Event_Resize: + #if defined(_WS_X11_) && !defined(NO_XIM) + if ( qt_xim() && isInputMethodEnabled() ) { + QWExtra *ed = extraData(); + if ( ed && ed->xic ) { + XRectangle pre_area; + pre_area.x = 0; + pre_area.y = 0; + pre_area.width = ((QResizeEvent *)e)->size().width(); + pre_area.height = ((QResizeEvent *)e)->size().height(); + XVaNestedList list; + list = XVaCreateNestedList( 0, + XNArea, &pre_area, + 0); + XSetICValues( (XIC)ed->xic, + XNPreeditAttributes, list, + 0 ); + } + } + #endif resizeEvent( (QResizeEvent*)e ); break; diff -cr qt-1.45.orig/src/kernel/qwidget.h qt-1.45/src/kernel/qwidget.h *** qt-1.45.orig/src/kernel/qwidget.h Sat Nov 13 01:57:28 1999 --- qt-1.45/src/kernel/qwidget.h Thu Jun 1 00:58:42 2000 *************** *** 20,25 **** --- 20,30 ---- ** license which allows creation of commercial/proprietary software. ** *****************************************************************************/ + /* + * X11 I18N Support Patch + * Copyright (C) 1998-2000 by Serika Kurusugawa. + * Date 1998/11/28, Last Modified 2000/01/23 + */ #ifndef QWIDGET_H #define QWIDGET_H *************** *** 176,181 **** --- 181,193 ---- void setFocusProxy( QWidget * ); QWidget * focusProxy() const; + #if defined(_WS_X11_) + bool isInputMethodEnabled() const; + bool setInputMethodEnabled( bool enable ); + bool internalSetInputMethodEnabled( bool enable ); + void setInputMethodSpotLocation( int x, int y ); + #endif + // Grab functions void grabMouse(); *************** *** 456,461 **** --- 468,478 ---- inline QWidget::FocusPolicy QWidget::focusPolicy() const { return (FocusPolicy)((testWFlags(WState_TabToFocus) ? (int)TabFocus : 0) + (testWFlags(WState_ClickToFocus)?(int)ClickFocus:0)); } + + #if defined(_WS_X11_) + inline bool QWidget::isInputMethodEnabled() const + { return testWFlags(WInputMethodEnabled); } + #endif inline bool QWidget::isUpdatesEnabled() const { return !testWFlags(WState_BlockUpdates); } diff -cr qt-1.45.orig/src/kernel/qwidget_x11.cpp qt-1.45/src/kernel/qwidget_x11.cpp *** qt-1.45.orig/src/kernel/qwidget_x11.cpp Sat Nov 13 01:57:28 1999 --- qt-1.45/src/kernel/qwidget_x11.cpp Thu Jun 1 00:58:42 2000 *************** *** 20,25 **** --- 20,30 ---- ** license which allows creation of commercial/proprietary software. ** *****************************************************************************/ + /* + * X11 I18N Support Patch + * Copyright (C) 1998 by Serika Kurusugawa. + * Date 1998/11/28, Last Modified 1999/08/02 + */ #include "qwindow.h" #include "qapplication.h" *************** *** 946,951 **** --- 951,1248 ---- /*! + \fn bool QWidget::isInputMethodEnabled() const + + Returns TRUE if the input method is enabled. + + \sa setInputMethodEnabled() + */ + + /*! + \fn void QWidget::setInputMethodEnabled( uint preedit, uint status ) + + Enable the input method. + + \sa isInputMethodEnabled() + */ + + #if defined(_WS_X11_) + #if !defined(NO_XIM) + + static XIMStyle getInputMethodStyle() + { + XIM xim = qt_xim(); + if (xim == 0) { + return 0; + } + + extern XIMStyle qt_xim_style; + extern XIMStyle qt_xim_pref_style; + + if ( qt_xim_style ) { + return qt_xim_style; + } + + XIMStyles *ximStyles; + if ( XGetIMValues( xim, XNQueryInputStyle, &ximStyles, 0 ) ) { + return FALSE; + } + XIMStyle style = 0; + for (int i = 0; i < ximStyles->count_styles; i++) { + if (ximStyles->supported_styles[i] == qt_xim_pref_style) { + style = qt_xim_pref_style; + break; + } + } + #define PreeditNothingStyle ( XIMPreeditNothing | XIMStatusNothing ) + #define PreeditNoneStyle ( XIMPreeditNone | XIMStatusNone ) + if ( ! style ) { + for (int i = 0; i < ximStyles->count_styles; i++) { + if (ximStyles->supported_styles[i] == PreeditNothingStyle) { + style = PreeditNothingStyle; + break; + } + } + } + if ( ! style ) { + for (int i = 0; i < ximStyles->count_styles; i++) { + if (ximStyles->supported_styles[i] == PreeditNoneStyle) { + style = PreeditNoneStyle; + break; + } + } + } + XFree( ximStyles ); + qt_xim_style = style; + return qt_xim_style; + } + #endif + + bool QWidget::setInputMethodEnabled( bool enable ) + { + #if defined(NO_XIM) + return FALSE; + #else + + if ( enable ) { + if ( isInputMethodEnabled() ) { + return TRUE; + } else { + setWFlags( WInputMethodEnabled ); + } + } else { + if ( isInputMethodEnabled() ) { + clearWFlags( WInputMethodEnabled ); + } else { + return TRUE; + } + } + + XIM xim = qt_xim(); + if ( xim == 0 ) { + return TRUE; + } + + XIMStyle style = getInputMethodStyle(); + if ( enable && !style ) { + return FALSE; + } + createExtra(); + if ( enable ) { + // enable input method + XRectangle pre_area; + pre_area.x = 0; + pre_area.y = 0; + pre_area.width = width(); + pre_area.height = height(); + XFontSet fontset = (XFontSet)font().handle2(); + XPoint location; + location.x = 0; + location.y = fontMetrics().ascent(); + XVaNestedList preedit_list; + XVaNestedList status_list; + preedit_list = XVaCreateNestedList( 0, + XNFontSet, fontset, + XNSpotLocation, &location, + XNArea, &pre_area, + // XNLineSpace, 16, + 0); + status_list = XVaCreateNestedList( 0, + XNFontSet, fontset, + // XNLineSpace, 16, + 0); + extra->xic = (void*)XCreateIC( xim, + XNInputStyle, style, + XNClientWindow, winId(), + // XNFocusWindow, winId(), + XNPreeditAttributes, preedit_list, + XNStatusAttributes, status_list, + 0 ); + if ( extra->xic == 0 ) { + return FALSE; + } + if ( style & XIMPreeditArea ) { + XRectangle *area; + preedit_list = XVaCreateNestedList( 0, XNAreaNeeded, &area, 0 ); + XGetICValues( (XIC)extra->xic, XNPreeditAttributes, preedit_list, 0 ); + XFree( preedit_list ); + preedit_list = XVaCreateNestedList( 0, XNArea, area, 0 ); + XSetICValues( (XIC)extra->xic, XNPreeditAttributes, preedit_list, NULL); + XFree(preedit_list); + } + if ( style & XIMStatusArea ) { + XRectangle *area; + status_list = XVaCreateNestedList( 0, XNAreaNeeded, &area, 0 ); + XGetICValues( (XIC)extra->xic, XNStatusAttributes, status_list, 0 ); + XFree( status_list ); + status_list = XVaCreateNestedList( 0, XNArea, area, 0 ); + XSetICValues( (XIC)extra->xic, XNStatusAttributes, status_list, NULL); + XFree(status_list); + } + + long xicEventMask; + if ( !XGetICValues( (XIC)extra->xic, XNFilterEvents, &xicEventMask, 0) ) { + XWindowAttributes getAttr; + XGetWindowAttributes( dpy, winId(), &getAttr ); + XSetWindowAttributes setAttr; + setAttr.event_mask = getAttr.your_event_mask | xicEventMask; + XChangeWindowAttributes( dpy, winId(), CWEventMask, &setAttr ); + } + } else { + // disable input method + if ( extra->xic != 0 ) { + XDestroyIC( (XIC)extra->xic ); + extra->xic = 0; + } + } + return TRUE; + #endif + } + + bool QWidget::internalSetInputMethodEnabled( bool enable ) + { + #if defined(NO_XIM) + return FALSE; + #else + + if ( !isInputMethodEnabled() ) { + return TRUE; + } + + createExtra(); + if ( enable ) { + // enable input method + XIM xim = qt_xim(); + if ( xim == 0 ) { + return FALSE; + } + + XIMStyle style = getInputMethodStyle(); + if ( !style ) { + return FALSE; + } + + XRectangle pre_area; + pre_area.x = 0; + pre_area.y = 0; + pre_area.width = width(); + pre_area.height = height(); + XFontSet fontset = (XFontSet)font().handle2(); + XPoint location; + location.x = 0; + location.y = fontMetrics().ascent(); + XVaNestedList preedit_list; + XVaNestedList status_list; + preedit_list = XVaCreateNestedList( 0, + XNFontSet, fontset, + XNSpotLocation, &location, + XNArea, &pre_area, + // XNLineSpace, 16, + 0); + status_list = XVaCreateNestedList( 0, + XNFontSet, fontset, + // XNLineSpace, 16, + 0); + extra->xic = (void*)XCreateIC( xim, + XNInputStyle, style, + XNClientWindow, winId(), + // XNFocusWindow, winId(), + XNPreeditAttributes, preedit_list, + XNStatusAttributes, status_list, + 0 ); + if ( extra->xic == 0 ) { + return FALSE; + } + if ( style & XIMPreeditArea ) { + XRectangle *area; + preedit_list = XVaCreateNestedList( 0, XNAreaNeeded, &area, 0 ); + XGetICValues( (XIC)extra->xic, XNPreeditAttributes, preedit_list, 0 ); + XFree( preedit_list ); + preedit_list = XVaCreateNestedList( 0, XNArea, area, 0 ); + XSetICValues( (XIC)extra->xic, XNPreeditAttributes, preedit_list, NULL); + XFree(preedit_list); + } + if ( style & XIMStatusArea ) { + XRectangle *area; + status_list = XVaCreateNestedList( 0, XNAreaNeeded, &area, 0 ); + XGetICValues( (XIC)extra->xic, XNStatusAttributes, status_list, 0 ); + XFree( status_list ); + status_list = XVaCreateNestedList( 0, XNArea, area, 0 ); + XSetICValues( (XIC)extra->xic, XNStatusAttributes, status_list, NULL); + XFree(status_list); + } + + long xicEventMask; + if ( !XGetICValues( (XIC)extra->xic, XNFilterEvents, &xicEventMask, 0) ) { + XWindowAttributes getAttr; + XGetWindowAttributes( dpy, winId(), &getAttr ); + XSetWindowAttributes setAttr; + setAttr.event_mask = getAttr.your_event_mask | xicEventMask; + XChangeWindowAttributes( dpy, winId(), CWEventMask, &setAttr ); + } + } else { + // disable input method + extra->xic = 0; + } + return TRUE; + #endif + } + + #endif + + + /*! + \fn void QWidget::setInputMethodSpotLocation( int x, int y ) + + Set spot location of the input method. + + \sa isInputMethodEnabled(), setInputMethodEnabeld() + */ + + #if defined(_WS_X11_) + void QWidget::setInputMethodSpotLocation( int x, int y ) + { + #if defined(NO_XIM) + #else + XIM xim = qt_xim(); + if (xim == 0) { + return; + } + if ( extra && extra->xic ) { + XPoint location; + XVaNestedList list; + location.x = x; + location.y = y; + list = XVaCreateNestedList( 0, XNSpotLocation, &location, 0 ); + XSetICValues( (XIC)extra->xic, XNPreeditAttributes, list, 0 ); + XFree( list ); + } + #endif + } + #endif + + + /*! Returns TRUE if the top-level widget containing this widget is the active window. *************** *** 1729,1734 **** --- 2026,2035 ---- void QWidget::deleteSysExtra() { + if ( extra->xic ) { + XDestroyIC( (XIC)extra->xic ); + extra->xic = 0; + } } /*! diff -cr qt-1.45.orig/src/kernel/qwindowdefs.h qt-1.45/src/kernel/qwindowdefs.h *** qt-1.45.orig/src/kernel/qwindowdefs.h Sat Nov 13 01:57:28 1999 --- qt-1.45/src/kernel/qwindowdefs.h Thu Jun 1 00:58:42 2000 *************** *** 21,26 **** --- 21,31 ---- ** license which allows creation of commercial/proprietary software. ** *****************************************************************************/ + /* + * X11 I18N Support Patch + * Copyright (C) 1998-2000 by Serika Kurusugawa. + * Date 1998/11/23, Last Modified 2000/01/23 + */ #ifndef QWINDOWDEFS_H #define QWINDOWDEFS_H *************** *** 161,166 **** --- 166,174 ---- typedef struct _XDisplay Display; typedef union _XEvent XEvent; typedef struct _XGC *GC; + typedef struct _XIM *XIM; + typedef struct _XIC *XIC; + typedef struct _XOC *XOC, *XFontSet; typedef struct _XRegion *Region; Q_EXPORT Display *qt_xdisplay(); *************** *** 168,173 **** --- 176,182 ---- Q_EXPORT WId qt_xrootwin(); Q_EXPORT GC qt_xget_readonly_gc( bool monochrome=FALSE ); Q_EXPORT GC qt_xget_temp_gc( bool monochrome=FALSE ); + Q_EXPORT XIM qt_xim(); #endif // _WS_X11_ *************** *** 251,256 **** --- 260,268 ---- const uint WExportFontMetrics = 0x10000000; const uint WExportFontInfo = 0x20000000; const uint WFocusSet = 0x40000000; // not used any more + #if defined(_WS_X11_) + const uint WInputMethodEnabled = 0x40000000; + #endif const uint WState_TabToFocus = 0x80000000; diff -cr qt-1.45.orig/src/tools/qglobal.h qt-1.45/src/tools/qglobal.h *** qt-1.45.orig/src/tools/qglobal.h Sat Nov 13 01:57:30 1999 --- qt-1.45/src/tools/qglobal.h Thu Jun 1 00:58:42 2000 *************** *** 20,25 **** --- 20,30 ---- ** license which allows creation of commercial/proprietary software. ** *****************************************************************************/ + /* + * X11 I18N Support Patch + * Copyright (C) 1999 by Serika Kurusugawa. + * Date 1999/09/30, Last Modified 1999/09/30 + */ #ifndef QGLOBAL_H #define QGLOBAL_H *************** *** 27,32 **** --- 32,39 ---- #define QT_VERSION 145 #define QT_VERSION_STR "1.45" + + #define QT_I18N // diff -cr qt-1.45.orig/src/widgets/qlineedit.cpp qt-1.45/src/widgets/qlineedit.cpp *** qt-1.45.orig/src/widgets/qlineedit.cpp Sat Nov 13 01:57:31 1999 --- qt-1.45/src/widgets/qlineedit.cpp Thu Jun 1 00:58:42 2000 *************** *** 20,25 **** --- 20,30 ---- ** license which allows creation of commercial/proprietary software. ** *****************************************************************************/ + /* + * X11 I18N Support Patch + * Copyright (C) 1998 by Serika Kurusugawa. + * Date 1998/11/28, Last Modified 1999/08/17 + */ #include "qlineedit.h" #include "qpainter.h" *************** *** 34,39 **** --- 39,120 ---- #include "qtimer.h" #include + #if !defined(NO_XPG4) + #include + #endif + + + + #if !defined(NO_XPG4) + /* + * マルチバイト文字列の文字の区切り目のなかで + * pos を含む pos の値を越えない最大の位置を返す。 + */ + int mbValidLeftPos( const char *string, int pos ) + { + uint length = strlen( string ); + + if ( ( pos < 0 ) || ( pos > length ) ) { + return -1; + } + if ( length == 0 ) { // work around for broken mblen() on Solaris 2.6 + return 0; + } + #if 1 + if ( MB_CUR_MAX == 1 ) { + return pos; + } + #endif + int p = 0; + do { + int l = mblen( &string[p], length - p ); + if ( l < 0 ) { + return -1; + } else if ( l == 0 ) { + return p; + } + if ( p + l > pos ) { + return p; + } + p += l; + } while ( p < length ); + return length; + } + /* + * マルチバイト文字列の文字の区切り目のなかで + * pos を含む pos の値を下回らない最小の位置を返す。 + */ + int mbValidRightPos( const char *string, int pos ) + { + uint length = strlen( string ); + + if ( ( pos < 0 ) || ( pos > length ) ) { + return -1; + } + if ( length == 0 ) { // work around for broken mblen() on Solaris 2.6 + return 0; + } + #if 1 + if ( MB_CUR_MAX == 1 ) { + return pos; + } + #endif + int p = 0; + do { + int l = mblen( &string[p], length - p ); + if ( l < 0 ) { + return -1; + } else if ( l == 0 ) { + return p; + } + if ( p + l >= pos ) { + return p + l; + } + p += l; + } while ( p < length ); + return length; + } + #endif struct QLineEditPrivate { QLineEditPrivate( QLineEdit * l ): *************** *** 107,112 **** --- 188,197 ---- { char *tmp; int dist; + #if !defined(NO_XPG4) + char *prev; + int len; + #endif if ( xPos > width ) xPos = width; *************** *** 114,123 **** --- 199,229 ---- return 0; dist = xPos; tmp = s; + #if defined(NO_XPG4) while ( *tmp && dist > 0 ) dist -= fm.width( tmp++, 1 ); if ( dist < 0 && ( xPos - dist > width || fm.width( tmp - 1, 1)/2 < -dist)) tmp--; + #else + prev = s; + len = strlen(s); + while ( *tmp && dist > 0 ) { + int l = mblen( tmp, len ); + if ( l <= 0 ) { // error( < 0) or end of string( == 0) + break; + } + dist -= fm.width( tmp, l ); + prev = tmp; + tmp += l; + len -= l; + } + if ( dist < 0 ) { + int l = mblen( prev, /*strlen(prev)*/MB_CUR_MAX ); + if ( ( xPos - dist > width ) || ( fm.width( prev, l ) / 2 < -dist ) ) { + tmp = prev; + } + } + #endif return tmp - s; } *************** *** 125,135 **** --- 231,256 ---- { if ( !s || s[0] == '\0' ) return 0; + #if defined(NO_XPG4) char *tmp = &s[strlen( s ) - 1]; do { width -= fm.width( tmp--, 1 ); } while ( tmp >=s && width >=0 ); return width < 0 ? tmp - s + 2 : 0; + #else + int cur, prev; + cur = prev = strlen( s ); + do { + prev = cur; + int p = mbValidLeftPos( s, cur - 1 ); + if ( p < 0 ) { + break; + } + width -= fm.width( &s[p], cur - p ); + cur = p; + } while ( cur >= 0 && width >= 0 ); + return width < 0 ? prev : 0; + #endif } *************** *** 163,168 **** --- 284,293 ---- setCursor( ibeamCursor ); setBackgroundMode( PaletteBase ); //setAcceptDrops( TRUE ); + #if !defined(NO_XIM) + // setInputMethodStyle( IMSDefault, IMSDefault ); + setInputMethodEnabled( TRUE ); + #endif } /*! *************** *** 309,314 **** --- 434,445 ---- if ( (int)tbuf.length() > maxLen ) { tbuf.resize( maxLen + 1 ); // include \0 tbuf[maxLen] = '\0'; + #if !defined(NO_XPG4) + m = mbValidLeftPos(tbuf, maxLen); + if ( m >= 0 ) { + tbuf[m] = '\0'; + } + #endif d->pmDirty = TRUE; } if ( offset || cursorPos ) { *************** *** 381,386 **** --- 512,521 ---- insert( t ); return; } + if ( (e->key() == 0) && (e->text().length() > 0) ) { + insert( e->text() ); + return; + } int unknown = 0; if ( e->state() & ControlButton ) { switch ( e->key() ) { *************** *** 541,547 **** --- 676,691 ---- displayText = ""; break; case Password: + #if defined(NO_XPG4) displayText.fill( '*', tbuf.length() - offset ); + #else + if ( MB_CUR_MAX == 1 ) { + displayText.fill( '*', tbuf.length() - offset ); + } else { + int l = mbstowcs(0, &tbuf[offset], 0); // get # of characters + displayText.fill( '*', l); + } + #endif break; } *************** *** 591,597 **** p.drawText( margin + 2, ypos, displayText, mark1 ); if ( mark2 != charsVisible ) { QString rest( displayText.mid( mark2, charsVisible - mark2 ) ); ! p.drawText( margin + 2 + fm.width( displayText.left( mark2) ), ypos, rest ); } } --- 735,741 ---- p.drawText( margin + 2, ypos, displayText, mark1 ); if ( mark2 != charsVisible ) { QString rest( displayText.mid( mark2, charsVisible - mark2 ) ); ! p.drawText( margin + 2 + fm.width( displayText.left( mark2 ) ), ypos, rest ); } } *************** *** 603,608 **** --- 747,755 ---- curXPos += offset > cursorPos ? -1 : // ?: for scrolling case fm.width( displayText, cursorPos - offset ) - 1; int curYPos = ypos - fm.ascent(); + #if !defined(NO_XIM) + setInputMethodSpotLocation( curXPos, ypos ); + #endif d->cursorRepaintRect.setRect( curXPos-2, curYPos, 5, fm.height() ); d->pmDirty = FALSE; } *************** *** 650,661 **** --- 797,822 ---- QFontMetrics fm = fontMetrics(); int w = width() - (frame() ? 8 : 4); int i = cursorPos; + #if defined(NO_XPG4) while ( w > 0 && i > 0 ) { i--; w -= fm.width( tbuf.at(i) ); } if ( w < 0 && i != cursorPos ) i++; + #else + int j = i; + while ( w > 0 && i > 0 ) { + j = i; + i = mbValidLeftPos( tbuf, i - 1 ); + if ( i < 0 ) { // error + break; + } + w -= fm.width( &tbuf[i], j - i ); + } + if ( w < 0 && i != cursorPos ) + i = j; + #endif offset = i; } else if ( offset ) { int i = showLastPartOffset( tbuf.data(), fontMetrics(), *************** *** 848,854 **** --- 1009,1019 ---- return; } if ( cursorPos > 0 || (!mark && hasMarkedText()) ) { + #if defined(NO_XPG4) cursorPos -= steps; + #else + cursorPos = mbValidLeftPos(tbuf, cursorPos - steps); + #endif if ( cursorPos < 0 ) cursorPos = 0; cursorOn = FALSE; *************** *** 878,884 **** --- 1043,1055 ---- int len = (int)strlen( tbuf ); if ( cursorPos < len || (!mark && hasMarkedText()) ) { int minP = QMIN( cursorPos, minMark() ); + #if defined(NO_XPG4) cursorPos += steps; + #else + cursorPos = mbValidRightPos(tbuf, cursorPos + steps); + if ( cursorPos < 0 ) // error + cursorPos = 0; + #endif if ( cursorPos > len ) cursorPos = len; cursorOn = FALSE; *************** *** 927,934 **** --- 1098,1113 ---- test.remove( minMark(), maxMark() - minMark() ); validateAndSet( test, minMark(), minMark(), minMark() ); } else if ( cursorPos != (int)strlen(tbuf) ) { + #if defined(NO_XPG4) test.remove( cursorPos, 1 ); validateAndSet( test, minMark(), minMark(), minMark() ); + #else + int len = mblen( &test[cursorPos], test.length() - cursorPos ); + if ( len > 0 ) { + test.remove( cursorPos, len ); + validateAndSet( test, minMark(), minMark(), minMark() ); + } + #endif } } *************** *** 1003,1008 **** --- 1182,1193 ---- void QLineEdit::newMark( int pos, bool copy ) { + #if !defined(NO_XPG4) + pos = mbValidLeftPos(tbuf, pos); + if ( pos < 0 ) { + return; + } + #endif if ( markDrag != pos || cursorPos != pos ) d->pmDirty = TRUE; markDrag = pos; *************** *** 1014,1030 **** --- 1199,1249 ---- void QLineEdit::markWord( int pos ) { + #if defined(NO_XPG4) int i = pos - 1; while ( i >= 0 && isprint(tbuf.at(i)) && !isspace(tbuf.at(i)) ) i--; i++; markAnchor = i; + #else + int i = pos; + int j = i; + while ( i >= 0 ) { + j = i; + i = mbValidLeftPos( tbuf, i - 1 ); + if ( i < 0 ) { + break; + } + if ( (j - i == 1) && + (/*!isprint(tbuf.at(i)) || */isspace(tbuf.at(i)) ) ) { + break; + } + } + markAnchor = j; + #endif + #if defined(NO_XPG4) int lim = tbuf.length(); i = pos; while ( i < lim && isprint(tbuf.at(i)) && !isspace(tbuf.at(i)) ) i++; markDrag = i; + #else + int lim = tbuf.length(); + i = pos; + while ( i < lim ) { + int l = mblen( &tbuf[i], lim - i ); + if ( l <= 0 ) { // error( < 0) or end of string( == 0) + break; + } + if ( (l == 1) && + (/*!isprint(tbuf.at(i)) || */isspace(tbuf.at(i)) ) ) { + break; + } + i += l; + } + markDrag = i; + #endif int maxVis = lastCharVisible(); int markBegin = minMark(); *************** *** 1359,1370 **** --- 1578,1611 ---- QString t( newText ); if ( !t.isEmpty() ) { uchar *p = (uchar *) t.data(); + #if defined(NO_XPG4) while ( *p ) { // unprintable/linefeed becomes space if ( *p < 32 ) *p = 32; p++; } + #else + uint len = t.length(); + while ( *p ) { // unprintable/linefeed becomes space + int l = mblen( (char *)p, len ); + if ( l <= 0 ) { // error( < 0) or end of string( == 0) + *p = '\0'; + break; + } + if ( (l == 1) && (*p < 32) ) { + *p = 32; + } + p += l; + len -= l; + } + #endif + } + #if !defined(NO_XPG4) + newPos = mbValidLeftPos( t, newPos ); + if ( newPos < 0 ) { // error + return FALSE; } + #endif if ( t.length() > (uint)maxLength() ) t.truncate( maxLength() ); *************** *** 1390,1396 **** minP = QMIN( minP, QMIN( cursorPos, minMark() ) ); maxP = QMAX( maxP, QMAX( cursorPos, maxMark() ) ); ! if ( tbuf == t || tbuf == t.right( tbuf.length() ) ) { int i = 0; while( i < minP && t[i] == tbuf[i] ) i++; --- 1631,1637 ---- minP = QMIN( minP, QMIN( cursorPos, minMark() ) ); maxP = QMAX( maxP, QMAX( cursorPos, maxMark() ) ); ! if ( tbuf == t || tbuf == t.right( tbuf.length() ) ) { /* !!! */ int i = 0; while( i < minP && t[i] == tbuf[i] ) i++; *************** *** 1413,1424 **** x = 0; else x = fm.width(t.mid( offset, cursorPos - offset) ); ! int margin = frame() ? 2 : 0; if ( x >= width() - margin ) { while( x >= width() - margin ) { int w = fm.width( tbuf[offset] ); x -= w; offset++; } } d->pmDirty = TRUE; --- 1654,1675 ---- x = 0; else x = fm.width(t.mid( offset, cursorPos - offset) ); ! int margin = frame() ? 8 : 4; if ( x >= width() - margin ) { while( x >= width() - margin ) { + #if defined(NO_XPG4) int w = fm.width( tbuf[offset] ); x -= w; offset++; + #else + int l = mblen( &tbuf[offset], tbuf.length() - offset ); + if ( l <= 0 ) { // error( < 0) or end of string( == 0) + break; + } + int w = fm.width( &tbuf[offset], l ); + x -= w; + offset += l; + #endif } } d->pmDirty = TRUE; *************** *** 1443,1452 **** return; uchar *p = (uchar *) t.data(); while ( *p ) { // unprintable/nl becomes space ! if ( *p < 32 ) *p = 32; ! p++; } QString test( tbuf.copy() ); --- 1694,1711 ---- return; uchar *p = (uchar *) t.data(); + uint len = t.length(); while ( *p ) { // unprintable/nl becomes space ! int l = mblen( (char *)p, len ); ! if ( l <= 0 ) { ! *p = '\0'; ! break; ! } ! if ( (l == 1) && (*p < 32) ) { *p = 32; ! } ! p += l; ! len -= l; } QString test( tbuf.copy() ); *************** *** 1476,1481 **** --- 1735,1750 ---- a = to; b = from; } + #if !defined(NO_XPG4) + a = mbValidLeftPos( tbuf, a ); + if ( a < 0 ) { // error + a = 0; + } + b = mbValidRightPos( tbuf, b ); + if ( b < 0 ) { // error + b = tbuf.length(); + } + #endif if ( offset > cursorPos ) { offset = cursorPos; *************** *** 1494,1504 **** QFontMetrics fm( fontMetrics() ); int margin = frame() ? 2 : 0; ! int x3 = fm.width( tbuf.mid( offset, cursorPos - offset ) ) + 2*margin; if ( x3 >= width() ) { while( x3 >= width() ) { x3 -= fm.width( tbuf[offset] ); offset++; } d->pmDirty = TRUE; repaint( FALSE ); --- 1763,1782 ---- QFontMetrics fm( fontMetrics() ); int margin = frame() ? 2 : 0; ! int x3 = fm.width( tbuf.mid( offset, cursorPos - offset ) ) + 2*margin + 4; if ( x3 >= width() ) { while( x3 >= width() ) { + #if defined(NO_XPG4) x3 -= fm.width( tbuf[offset] ); offset++; + #else + int l = mblen( &tbuf[offset], tbuf.length() - offset ); + if ( l <= 0 ) { // error( < 0) or end of string( == 0) + break; + } + x3 -= fm.width( &tbuf[offset], l ); + offset += l; + #endif } d->pmDirty = TRUE; repaint( FALSE ); *************** *** 1556,1561 **** --- 1834,1852 ---- void QLineEdit::setSelection( int start, int length ) { + #if !defined(NO_XPG4) + int l, r; + l = mbValidLeftPos( tbuf, start ); + if ( l < 0 ) { + l = 0; + } + r = mbValidRightPos( tbuf, start + length ); + if ( r < 0 ) { + r = tbuf.length(); + } + start = l; + length = r - l; + #endif int b, e; b = QMIN( markAnchor, markDrag ); e = QMAX( markAnchor, markDrag ); *************** *** 1574,1579 **** --- 1865,1878 ---- { if ( newPos > (int)tbuf.length() || newPos < 0 ) return; + #if !defined(NO_XPG4) + int pos = mbValidLeftPos( tbuf, newPos ); + if (pos < 0) { // error + // return; + } else { + newPos = pos; + } + #endif int b, e; b = QMIN( newPos, cursorPos ); e = QMAX( newPos, cursorPos ); diff -cr qt-1.45.orig/src/widgets/qmultilinedit.cpp qt-1.45/src/widgets/qmultilinedit.cpp *** qt-1.45.orig/src/widgets/qmultilinedit.cpp Sat Nov 13 01:57:32 1999 --- qt-1.45/src/widgets/qmultilinedit.cpp Thu Jun 1 00:58:42 2000 *************** *** 20,25 **** --- 20,30 ---- ** license which allows creation of commercial/proprietary software. ** *****************************************************************************/ + /* + * X11 I18N Support Patch + * Copyright (C) 1998 by Serika Kurusugawa. + * Date 1998/11/28, Last Modified 1999/08/17 + */ #include "qmultilinedit.h" #include "qpainter.h" *************** *** 31,36 **** --- 36,50 ---- #include "qapplication.h" #include "qtimer.h" #include + #if !defined(NO_XPG4) + #include + #endif + + + #if !defined(NO_XPG4) + extern int mbValidLeftPos( const char *string, int pos ); + extern int mbValidRightPos( const char *string, int pos ); + #endif /*! *************** *** 87,98 **** --- 101,125 ---- return 0; int tabDist = tabStopDist(fm); while ( *tmp && tmp - s < nChars ) { + #if defined(NO_XPG4) if ( *tmp == '\t') { dist = ( dist/tabDist + 1 ) * tabDist; } else { dist += fm.width( tmp, 1 ); } tmp++; + #else + int l = mblen( tmp, nChars - (tmp - s) ); + if ( l <= 0 ) { // error( < 0) or end of string( == 0) + break; + } + if ( l == 1 && *tmp == '\t') { + dist = ( dist/tabDist + 1 ) * tabDist; + } else { + dist += fm.width( tmp, l ); + } + tmp += l; + #endif } return dist; } *************** *** 101,106 **** --- 128,136 ---- int xPos, int width ) { const char *tmp; + #if !defined(NO_XPG4) + const char *prev; + #endif int dist; int tabDist; *************** *** 114,121 **** --- 144,153 ---- int distBeforeLastTab = 0; dist = 0; tmp = s; + prev = tmp; tabDist = tabStopDist(fm); while ( *tmp && dist < xPos ) { + #if defined(NO_XPG4) if ( *tmp == '\t') { distBeforeLastTab = dist; dist = (dist/tabDist + 1) * tabDist; *************** *** 123,133 **** --- 155,184 ---- dist += fm.width( tmp, 1 ); } tmp++; + #else + int l = mblen( tmp, MB_CUR_MAX ); + if ( l <= 0 ) { // error( < 0) or end of string( == 0) + break; + } + if ( l == 1 && *tmp == '\t') { + distBeforeLastTab = dist; + dist = (dist/tabDist + 1) * tabDist; + } else { + dist += fm.width( tmp, l ); + } + prev = tmp; + tmp += l; + #endif } if ( dist > xPos ) { if ( dist > width ) { + #if defined(NO_XPG4) tmp--; + #else + tmp = prev; + #endif } else { + #if defined(NO_XPG4) if ( *(tmp - 1) == '\t' ) { // dist equals a tab stop position if ( xPos - distBeforeLastTab < (dist - distBeforeLastTab)/2 ) tmp--; *************** *** 135,140 **** --- 186,201 ---- if ( fm.width(tmp - 1, 1)/2 < dist-xPos ) tmp--; } + #else + if ( (tmp - prev == 1) && + (*prev == '\t') ) { // dist equals a tab stop position + if ( xPos - distBeforeLastTab < (dist - distBeforeLastTab)/2 ) + tmp = prev; + } else { + if ( fm.width(prev, tmp - prev)/2 < dist-xPos ) + tmp = prev; + } + #endif } } return tmp - s; *************** *** 190,195 **** --- 251,260 ---- markDragY = 0; blinkTimer = 0; scrollTimer = 0; + #if !defined(NO_XIM) + // setInputMethodStyle( IMSDefault, IMSDefault ); + setInputMethodEnabled( TRUE ); + #endif } /*! \fn int QMultiLineEdit::numLines() const *************** *** 425,430 **** --- 490,501 ---- p.drawLine( cXPos - 2, cYPos + fm.height() - 2, cXPos + 2, cYPos + fm.height() - 2); } + #if !defined(NO_XIM) + int rypos; + if ( rowYPos( row, &rypos ) ) { + setInputMethodSpotLocation( cXPos, rypos + cYPos + fm.ascent() ); + } + #endif } p.end(); painter->drawPixmap( updateR.left(), updateR.top(), *buffer ); *************** *** 849,854 **** --- 920,933 ---- mlData->isHandlingEvent = FALSE; return; } + if ( (e->key() == 0) && (e->text().length() > 0) ) { + insertAt( e->text(), cursorY, cursorX ); + makeVisible(); + if ( textDirty ) + emit textChanged(); + mlData->isHandlingEvent = FALSE; + return; + } if ( e->state() & ControlButton ) { switch ( e->key() ) { case Key_A: *************** *** 1061,1070 **** --- 1140,1163 ---- } int len = 0; const char *p = txt; + #if defined(NO_XPG4) while ( *p && *p != '\n' ) { p++; len++; } + #else + while ( *p ) { + int l = mblen( p, MB_CUR_MAX ); + if ( l <= 0 ) { // error( < 0) or end of string( == 0) + break; + } + if ( l == 1 && *p == '\n' ) { + break; + } + p += l; + len += l; + } + #endif *s = new QString( len + 1 ); memmove( (*s)->data(), txt, len ); (**s)[len] = 0; *************** *** 1092,1097 **** --- 1185,1196 ---- QString *oldLine = getString( line ); ASSERT( oldLine ); + #if !defined(NO_XPG4) + col = mbValidLeftPos( *oldLine, col ); + if ( col < 0 ) { + return; + } + #endif bool cursorAfter = atEnd() || cursorY > line || cursorY == line && cursorX >= col; bool onLineAfter = cursorY == line && cursorX >= col; *************** *** 1238,1244 **** cursorX = s->length(); if ( overWrite && !wasMarkedText && cursorX < (int)s->length() ) del(); // ## Will flicker ! s->insert( cursorX, c); int w = textWidth( s ); setWidth( QMAX( maxLineWidth(), w ) ); cursorRight( FALSE ); // will repaint --- 1337,1343 ---- cursorX = s->length(); if ( overWrite && !wasMarkedText && cursorX < (int)s->length() ) del(); // ## Will flicker ! s->insert( cursorX, c ); int w = textWidth( s ); setWidth( QMAX( maxLineWidth(), w ) ); cursorRight( FALSE ); // will repaint *************** *** 1311,1318 **** --- 1410,1421 ---- if ( cursorX > ll ) cursorX = ll; cursorOn = TRUE; + #if defined(NO_XPG4) cursorX--; if ( cursorX < 0 ) { + #else + if ( cursorX <= 0 ) { + #endif int oldY = cursorY; if ( cursorY > 0 ) { cursorY--; *************** *** 1323,1328 **** --- 1426,1437 ---- } updateCell( oldY, 0, FALSE ); } + #if !defined(NO_XPG4) + else { + QString *s = getString( cursorY ); + cursorX = mbValidLeftPos( *s, cursorX - 1 ); + } + #endif if ( mark ) newMark( cursorX, cursorY, FALSE ); blinkTimer = startTimer( blinkTime ); *************** *** 1352,1359 **** --- 1461,1472 ---- } killTimer( blinkTimer ); cursorOn = TRUE; + #if defined(NO_XPG4) cursorX++; if ( cursorX > strl ) { + #else + if ( cursorX >= strl ) { + #endif int oldY = cursorY; if ( cursorY < (int) contents->count() - 1 ) { cursorY++; *************** *** 1363,1368 **** --- 1476,1487 ---- } updateCell( oldY, 0, FALSE ); } + #if !defined(NO_XPG4) + else { + QString *s = getString( cursorY ); + cursorX = mbValidRightPos( *s, cursorX + 1 ); + } + #endif if ( mark ) newMark( cursorX, cursorY, FALSE ); updateCell( cursorY, 0, FALSE ); *************** *** 1538,1544 **** --- 1657,1670 ---- removeLine( cursorY + 1 ); } else { bool recalc = textWidth( s ) == maxLineWidth(); + #if defined(NO_XPG4) s->remove( cursorX, 1 ); + #else + int l = mblen( &(*s)[cursorX], s->length() - cursorX ); + if ( l > 0 ) { + s->remove( cursorX, l ); + } + #endif updateCell( cursorY, 0, FALSE ); if ( recalc ) updateCellWidth(); *************** *** 1851,1856 **** --- 1977,1988 ---- { QString *s = getString( line ); ASSERT( s ); + #if !defined(NO_XPG4) + xIndex = mbValidLeftPos( *s, xIndex ); + if ( xIndex < 0 ) { // error + return BORDER - 1; + } + #endif xIndex = QMIN( (int)s->length(), xIndex ); QFontMetrics fm( font() ); return BORDER + textWidthWithTabs( fm, *s, xIndex ) - 1; *************** *** 1910,1918 **** --- 2042,2060 ---- uchar *p = (uchar *) t.data(); while ( *p ) { // unprintable becomes space + #if defined(NO_XPG4) if ( *p < 32 && *p != '\n' && *p != '\t' ) *p = 32; p++; + #else + int l = mblen( (char *)p, MB_CUR_MAX ); + if ( l <= 0 ) { // error( < 0) or end of string( == 0) + break; + } + if ( l == 1 && *p < 32 && *p != '\n' && *p != '\t' ) + *p = 32; + p += l; + #endif } insertAt( t, cursorY, cursorX ); markIsOn = FALSE; *************** *** 1966,1971 **** --- 2108,2121 ---- void QMultiLineEdit::newMark( int posx, int posy, bool copy ) { + #if !defined(NO_XPG4) + QString *s = getString( posy ); + ASSERT( s ); + posx = mbValidLeftPos( *s, posx ); + if ( posx < 0 ) { // error + return; + } + #endif if ( markIsOn && markDragX == posx && markDragY == posy && cursorX == posx && cursorY == posy ) return; *************** *** 1981,1987 **** /*! Marks the word at character position \a posx, \a posy. */ ! void QMultiLineEdit::markWord( int posx, int posy ) { QString *s = contents->at( posy ); ASSERT( s ); --- 2131,2137 ---- /*! Marks the word at character position \a posx, \a posy. */ ! void QMultiLineEdit::markWord( int posx, int posy ) /* not I18N yet !!! */ { QString *s = contents->at( posy ); ASSERT( s ); *************** *** 2111,2116 **** --- 2261,2275 ---- int oldY = cursorY; cursorY = QMAX( QMIN( line, numLines() - 1), 0 ); cursorX = QMAX( QMIN( col, lineLength( cursorY )), 0 ); + #if !defined(NO_XPG4) + QString *s = getString( cursorY ); + int pos = mbValidLeftPos( *s, cursorX ); + if ( pos < 0 ) { // error + // return; + } else { + cursorX = pos; + } + #endif curXPos = 0; makeVisible(); updateCell( oldY, 0, FALSE );