diff -urN aterm-0.4.2.orig/autoconf/acconfig.h aterm-0.4.2/autoconf/acconfig.h --- aterm-0.4.2.orig/autoconf/acconfig.h Fri Sep 7 01:38:07 2001 +++ aterm-0.4.2/autoconf/acconfig.h Mon Sep 17 06:51:11 2001 @@ -27,6 +27,10 @@ * (width of 3d-look shadows and highlights) --pjh */ #undef HALFSHADOW +/* Define if you want to have XIM (X Input Method) protocol support + * This is required for multibyte characters input. */ +#undef USE_XIM + /* Define if you want KANJI support */ /* after compilation, rename executable as `kxvt' */ #undef KANJI @@ -39,6 +43,9 @@ #undef NO_XLOCALE /* Define is setlocale (defined to Xsetlocale) doesn't work */ +#undef NO_XSETLOCALE + +/* Define is plain setlocale doesn't work */ #undef NO_SETLOCALE /* Define if you want Menubar support */ diff -urN aterm-0.4.2.orig/autoconf/config.h.in aterm-0.4.2/autoconf/config.h.in --- aterm-0.4.2.orig/autoconf/config.h.in Fri Sep 7 01:38:07 2001 +++ aterm-0.4.2/autoconf/config.h.in Mon Sep 17 06:52:02 2001 @@ -77,6 +77,10 @@ * (width of 3d-look shadows and highlights) --pjh */ #undef HALFSHADOW +/* Define if you want to have XIM (X Input Method) protocol support + * This is required for multibyte characters input. */ +#undef USE_XIM + /* Define if you want KANJI support */ /* after compilation, rename executable as `kxvt' */ #undef KANJI @@ -89,6 +93,9 @@ #undef NO_XLOCALE /* Define is setlocale (defined to Xsetlocale) doesn't work */ +#undef NO_XSETLOCALE + +/* Define is plain setlocale doesn't work */ #undef NO_SETLOCALE /* Define if you want Menubar support */ diff -urN aterm-0.4.2.orig/autoconf/configure.in aterm-0.4.2/autoconf/configure.in --- aterm-0.4.2.orig/autoconf/configure.in Fri Sep 7 01:38:07 2001 +++ aterm-0.4.2/autoconf/configure.in Mon Sep 17 06:53:56 2001 @@ -94,6 +94,12 @@ AC_DEFINE(HALFSHADOW) fi]) +AC_ARG_ENABLE(xim, + [ --enable-xim enable XIM (X Input Method) protocol support], + [if test x$enableval = xyes; then + AC_DEFINE(USE_XIM) + fi]) + AC_ARG_ENABLE(kanji, [ --enable-kanji enable kanji support], [if test x$enableval = xyes; then @@ -642,6 +648,7 @@ dnl# this is a really hack test for some basic Xlocale stuff SAVETHELIBS=$LIBS LIBS="$LIBS $X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS -lX11" +CFLAGS="$CFLAGS $X_CFLAGS" AC_CACHE_CHECK(for working Xlocale, rxvt_cv_func_xlocale, [AC_TRY_RUN( [#define X_LOCALE 1 @@ -667,6 +674,14 @@ [setlocale(LC_CTYPE, "");], rxvt_cv_func_xsetlocale=yes, rxvt_cv_func_xsetlocale=no)]) if test "${rxvt_cv_func_xsetlocale}" = no; then + AC_DEFINE(NO_XSETLOCALE) +fi + +AC_CACHE_CHECK(for working plain setlocale, rxvt_cv_func_setlocale, +[AC_TRY_LINK([#include ], + [setlocale(LC_CTYPE, "");], + rxvt_cv_func_setlocale=yes, rxvt_cv_func_setlocale=no)]) +if test x${rxvt_cv_func_setlocale} = xno; then AC_DEFINE(NO_SETLOCALE) fi diff -urN aterm-0.4.2.orig/src/command.c aterm-0.4.2/src/command.c --- aterm-0.4.2.orig/src/command.c Fri Sep 7 01:38:07 2001 +++ aterm-0.4.2/src/command.c Mon Sep 17 06:47:48 2001 @@ -69,9 +69,15 @@ #ifndef NO_XLOCALE # if (XtSpecificationRelease < 6) # define NO_XLOCALE -# else -# define X_LOCALE -# include +# endif +#endif /* NO_XLOCALE */ + +#ifndef NO_XSETLOCALE +# define X_LOCALE +# include +#else +# ifndef NO_SETLOCALE +# include # endif #endif /* NO_XLOCALE */ @@ -182,7 +188,11 @@ /*{{{ defines: */ -#define KBUFSZ 8 /* size of keyboard mapping buffer */ +#ifdef USE_XIM +# define KBUFSZ 64 /* size of keyboard mapping buffer */ +#else +# define KBUFSZ 8 /* size of keyboard mapping buffer */ +#endif #define STRING_MAX 512 /* max string size for process_xterm_seq() */ #define ESC_ARGS 32 /* max # of args for esc sequences */ @@ -308,11 +318,15 @@ static Atom DndProtocol, DndSelection; #endif /* OFFIX_DND */ +#ifdef USE_XIM +static XIC Input_Context; /* input context */ +#else #ifndef NO_XLOCALE static char *rs_inputMethod = ""; /* XtNinputMethod */ static char *rs_preeditType = NULL; /* XtNpreeditType */ static XIC Input_Context; /* input context */ #endif /* NO_XLOCALE */ +#endif /* USE_XIM */ /* command input buffering */ #ifndef BUFSIZ @@ -534,7 +548,7 @@ ttydev = tty_name; # define PTYCHAR1 "pqrstuvwxyz" -# define PTYCHAR2 "0123456789abcdef" +# define PTYCHAR2 "0123456789abcdefghijklmnopqrstuvwxyz" for (c1 = PTYCHAR1; *c1; c1++) { ptydev[len - 2] = ttydev[len - 2] = *c1; for (c2 = PTYCHAR2; *c2; c2++) { @@ -1137,8 +1151,17 @@ DndSelection = XInternAtom(Xdisplay, "DndSelection", False); #endif /* OFFIX_DND */ +#ifndef NO_XLOCALE init_xlocale(); +#else + setlocale(LC_CTYPE, ""); +#endif +#ifdef USE_XIM + setTermFontSet(); + XRegisterIMInstantiateCallback(Xdisplay, NULL, NULL, NULL, IMInstantiateCallback, NULL); +#endif + /* get number of available file descriptors */ #ifdef _POSIX_VERSION num_fds = sysconf(_SC_OPEN_MAX); @@ -1204,6 +1227,7 @@ init_xlocale(void) { #ifndef NO_XLOCALE +#ifndef USE_XIM char *p, *s, buf[32], tmp[1024]; XIM xim = NULL; XIMStyle input_style = 0; @@ -1212,7 +1236,7 @@ Input_Context = NULL; -# ifndef NO_SETLOCALE +# if !defined(NO_SETLOCALE) || !defined(NO_XSETLOCALE) /* setlocale(LC_CTYPE, ""); /* XXX: should we do this? */ # endif if (rs_inputMethod == NULL || !*rs_inputMethod) { @@ -1311,6 +1335,7 @@ print_error("Failed to create input context"); XCloseIM(xim); } +#endif /* USE_XIM */ #endif /* NO_XLOCALE */ } /*}}} */ @@ -1379,22 +1404,21 @@ numlock_state = (ev->xkey.state & ModNumLockMask); /* numlock toggle */ PrivMode((!numlock_state), PrivMode_aplKP); } -#ifndef NO_XLOCALE - if (!XFilterEvent(ev, *(&ev->xkey.window))) { - if (Input_Context != NULL) { - Status status_return; - - len = XmbLookupString(Input_Context, &ev->xkey, kbuf, - sizeof(kbuf), &keysym, - &status_return); - } else { - len = XLookupString(&ev->xkey, kbuf, - sizeof(kbuf), &keysym, - &compose); - } - } else - len = 0; -#else /* NO_XLOCALE */ +#ifdef USE_XIM + len = 0; + if (Input_Context != NULL) { + Status status_return; + + kbuf[0] = '\0'; + len = XmbLookupString(Input_Context, &ev->xkey, kbuf, + sizeof(kbuf), &keysym, + &status_return); + } else { + len = XLookupString(&ev->xkey, kbuf, + sizeof(kbuf), &keysym, + &compose); + } +#else /* USE_XIM */ len = XLookupString(&ev->xkey, (char *) kbuf, sizeof(kbuf), &keysym, &compose); /* * have unmapped Latin[2-4] entries -> Latin1 @@ -1404,7 +1428,7 @@ len = 1; kbuf[0] = (keysym & 0xFF); } -#endif /* NO_XLOCALE */ +#endif /* USE_XIM */ if (len && (Options & Opt_scrollKeypress)) TermWin.view_start = 0; @@ -1977,8 +2001,12 @@ XEvent ev; refreshed = 0; +#ifdef USE_XIM + XProcessEvent(Xdisplay); +#else XNextEvent(Xdisplay, &ev); process_x_event(&ev); +#endif /* in case button actions pushed chars to cmdbuf */ if (cmdbuf_ptr < cmdbuf_endp) @@ -2050,6 +2078,9 @@ refreshed = 1; scr_refresh(refresh_type); scrollbar_show(1); +#ifdef USE_XIM + IMSendSpot(); +#endif } } } @@ -2225,7 +2256,7 @@ on_colors_changed(Color_bg); } #endif -#ifndef NO_XLOCALE +#ifdef USE_XIM if (Input_Context != NULL) XSetICFocus(Input_Context); #endif @@ -2242,7 +2273,7 @@ on_colors_changed(Color_bg); } #endif -#ifndef NO_XLOCALE +#ifdef USE_XIM if (Input_Context != NULL) XUnsetICFocus(Input_Context); #endif @@ -2720,6 +2751,9 @@ scr_refresh(refresh_type); refresh_count = refresh_limit = 0; scrollbar_show(1); +#ifdef USE_XIM + IMSendSpot(); +#endif } break; } @@ -3444,6 +3478,9 @@ } } Gr_do_graphics(cmd, nargs, args, text); +#ifdef USE_XIM + IMSendSpot(); +#endif #endif } /*}}} */ @@ -3612,6 +3649,364 @@ } +#ifdef USE_XIM +/* PROTO */ +void +setSize( XRectangle *size ) +{ + size->x = TermWin_internalBorder; + size->y = TermWin_internalBorder; + size->width = Width2Pixel (TermWin.ncol); + size->height = Height2Pixel(TermWin.nrow); + return; +} + +/* PROTO */ +void +setColor( unsigned long *fg, unsigned long *bg ) +{ + *fg = PixColors[Color_fg]; + *bg = PixColors[Color_bg]; + return; +} + +/* PROTO */ +void +IMSendSpot( void ) +{ + XPoint spot; + XVaNestedList preedit_attr; + XIMStyle input_style; + + if( Input_Context == NULL ) + return; + else { + XGetICValues(Input_Context,XNInputStyle,&input_style,NULL); + if (!(input_style & XIMPreeditPosition)) + return; + } + setPosition( &spot ); + + preedit_attr = XVaCreateNestedList( 0, XNSpotLocation, &spot, NULL ); + XSetICValues( Input_Context, XNPreeditAttributes, preedit_attr, NULL ); + XFree( preedit_attr ); + return; +} + +/* PROTO */ +void +setTermFontSet( void ) +{ + char *string; + long length, i; + + if( TermWin.fontset != NULL ){ + XFreeFontSet( Xdisplay, TermWin.fontset ); + TermWin.fontset = NULL; + } + + length = 0; + for( i = 0 ; i < NFONTS ; i ++){ + if( rs_font[ i ] ) + length += strlen( rs_font[ i ] ) + 1; +# ifdef MULTICHAR_SET + if( rs_mfont[ i ] ) + length += strlen( rs_mfont[ i ] ) + 1; +# endif + } + if( ( string = malloc( length ) ) != NULL ){ + char **missing_charsetlist, *def_string; + int missing_charsetcount; + + string[ 0 ] = '\0'; + for( i = 0 ; i < NFONTS ; i ++){ + if( rs_font[ i ] ){ + strcat( string, rs_font[ i ] ); + strcat( string, "," ); + } +# ifdef MULTICHAR_SET + if( rs_mfont[ i ] ){ + strcat( string, rs_mfont[ i ] ); + strcat( string, "," ); + } +# endif + } + length = strlen( string ); + if( length > 0 && string[ length - 1 ] == ',' ){ + string[ length - 1 ] = '\0'; + length --; + } + if( length > 0 ){ + TermWin.fontset = XCreateFontSet + ( Xdisplay, string, + &missing_charsetlist, &missing_charsetcount, &def_string ); + } + free( string ); + } else { + TermWin.fontset = NULL; + } + return; +} + +/* PROTO */ +void +setPreeditArea(XRectangle *preedit_rect, XRectangle *status_rect, XRectangle *needed_rect) +{ + preedit_rect->x = needed_rect->width + + (scrollbar_visible() && !(Options & Opt_scrollBar_right) + ? (SB_WIDTH + sb_shadow * 2) : 0); + preedit_rect->y = Height2Pixel(TermWin.nrow - 1) + + ((menuBar.state == 1) ? menuBar_TotalHeight() : 0); + + preedit_rect->width = Width2Pixel(TermWin.ncol + 1) - needed_rect->width + + (!(Options & Opt_scrollBar_right) + ? (SB_WIDTH + sb_shadow * 2) : 0); + preedit_rect->height = Height2Pixel(1); + + status_rect->x = (scrollbar_visible() && !(Options & Opt_scrollBar_right)) + ? (SB_WIDTH + sb_shadow * 2) : 0; + status_rect->y = Height2Pixel(TermWin.nrow - 1) + + ((menuBar.state == 1) ? menuBar_TotalHeight() : 0); + + status_rect->width = needed_rect->width ? needed_rect->width + : Width2Pixel(TermWin.ncol + 1); + status_rect->height = Height2Pixel(1); +} + +/* PROTO */ +void +IMDestroyCallback(XIM xim, XPointer client_data, XPointer call_data) +{ + Input_Context = NULL; + XRegisterIMInstantiateCallback(Xdisplay, NULL, NULL, NULL, IMInstantiateCallback, NULL); +} + + +/* PROTO */ +void +IMInstantiateCallback(Display *display, XPointer client_data, XPointer call_data) +{ + char *p, *s, buf[64], tmp[1024]; + char *end, *next_s; + XIM xim = NULL; + XIMStyle input_style = 0; + XIMStyles *xim_styles = NULL; + int found; + XPoint spot; + XRectangle rect, status_rect, needed_rect; + unsigned long fg, bg; + XVaNestedList preedit_attr = NULL; + XVaNestedList status_attr = NULL; + XIMCallback ximcallback; + + Input_Context = NULL; + + if (Input_Context) + return; + + ximcallback.callback = IMDestroyCallback; + ximcallback.client_data = NULL; + + if (rs_inputMethod && *rs_inputMethod) { + STRNCPY(tmp, rs_inputMethod, sizeof(tmp) - 1); + for (s = tmp; *s; s = next_s + 1) { + for (; *s && isspace(*s); s++); + if (!*s) + break; + for (end = s; (*end && (*end != ',')); end++); + for (next_s = end--; ((end >= s) && isspace(*end)); end--); + *(end + 1) = '\0'; + if (*s) { + STRCPY(buf, "@im="); + strncat(buf, s, sizeof(buf) - 4 - 1); + if ((p = XSetLocaleModifiers(buf)) != NULL && *p + && (xim = XOpenIM(Xdisplay, NULL, NULL, NULL)) != NULL) + break; + } + if (!*next_s) + break; + } + } + + /* try with XMODIFIERS env. var. */ + if (xim == NULL && (p = XSetLocaleModifiers("")) != NULL && *p) + xim = XOpenIM(Xdisplay, NULL, NULL, NULL); + + /* try with no modifiers base */ + if (xim == NULL && (p = XSetLocaleModifiers("@im=none")) != NULL && *p) + xim = XOpenIM(Xdisplay, NULL, NULL, NULL); + + if (xim == NULL) + return; + XSetIMValues(xim, XNDestroyCallback, &ximcallback, NULL); + + if (XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL) + || !xim_styles) { + print_error("input method doesn't support any style"); + XCloseIM(xim); + return; + } + STRNCPY(tmp, (rs_preeditType ? rs_preeditType + : "OverTheSpot,OffTheSpot,Root"), + sizeof(tmp) - 1); + for (found = 0, s = tmp; *s && !found; s = next_s + 1) { + unsigned short i; + + for (; *s && isspace(*s); s++); + if (!*s) + break; + for (end = s; (*end && (*end != ',')); end++); + for (next_s = end--; ((end >= s) && isspace(*end)); end--); + *(end + 1) = '\0'; + + if (!strcmp(s, "OverTheSpot")) + input_style = (XIMPreeditPosition | XIMStatusNothing); + else if (!strcmp(s, "OffTheSpot")) + input_style = (XIMPreeditArea | XIMStatusArea); + else if (!strcmp(s, "Root")) + input_style = (XIMPreeditNothing | XIMStatusNothing); + + for (i = 0; i < xim_styles->count_styles; i++) + if (input_style == xim_styles->supported_styles[i]) { + found = 1; + break; + } + } + XFree(xim_styles); + + if (found == 0) { + print_error("input method doesn't support my preedit type"); + XCloseIM(xim); + return; + } + if ((input_style != (XIMPreeditNothing | XIMStatusNothing)) + && (input_style != (XIMPreeditArea | XIMStatusArea)) + && (input_style != (XIMPreeditPosition | XIMStatusNothing))) { + print_error("This program does not support the preedit type"); + XCloseIM(xim); + return; + } + if (input_style & XIMPreeditPosition) { + setSize(&rect); + setPosition(&spot); + setColor(&fg, &bg); + + preedit_attr = XVaCreateNestedList(0, XNArea, &rect, + XNSpotLocation, &spot, + XNForeground, fg, + XNBackground, bg, + XNFontSet, TermWin.fontset, + NULL); + } else if (input_style & XIMPreeditArea) { + setColor(&fg, &bg); + + /* + * The necessary width of preedit area is unknown + * until create input context. + */ + needed_rect.width = 0; + + setPreeditArea(&rect, &status_rect, &needed_rect); + + preedit_attr = XVaCreateNestedList(0, XNArea, &rect, + XNForeground, fg, + XNBackground, bg, + XNFontSet, TermWin.fontset, + NULL); + status_attr = XVaCreateNestedList(0, XNArea, &status_rect, + XNForeground, fg, + XNBackground, bg, + XNFontSet, TermWin.fontset, + NULL); + } + Input_Context = XCreateIC(xim, XNInputStyle, input_style, + XNClientWindow, TermWin.parent, + XNFocusWindow, TermWin.parent, + XNDestroyCallback, &ximcallback, + preedit_attr ? XNPreeditAttributes : NULL, + preedit_attr, + status_attr ? XNStatusAttributes : NULL, + status_attr, + NULL); + XFree(preedit_attr); + XFree(status_attr); + if (Input_Context == NULL) { + print_error("Failed to create input context"); + XCloseIM(xim); + } + if (input_style & XIMPreeditArea) + IMSetStatusPosition(); +} + +/* PROTO */ +void +IMSetStatusPosition(void) +{ + XIMStyle input_style; + XRectangle rect, status_rect, *needed_rect; + XVaNestedList preedit_attr, status_attr; + + if (Input_Context == NULL) + return; + + XGetICValues(Input_Context, XNInputStyle, &input_style, NULL); + + if (input_style & XIMPreeditArea) { + status_attr = XVaCreateNestedList(0, XNAreaNeeded, &needed_rect, NULL); + XGetICValues(Input_Context, XNStatusAttributes, status_attr, NULL); + XFree(status_attr); + + rect.x = needed_rect->width; + if (menuBar.state == 1) { + rect.y = Height2Pixel(TermWin.nrow - 1) - menuBar_TotalHeight(); + } else { + rect.y = Height2Pixel(TermWin.nrow - 1); + } + if (Options & Opt_scrollBar_right) { + rect.width = Width2Pixel(TermWin.ncol + 1) - needed_rect->width; + } else { + rect.width = Width2Pixel(TermWin.ncol + 1) + SB_WIDTH + SHADOW * 2 - needed_rect->width; + } + rect.height = needed_rect->height; + preedit_attr = XVaCreateNestedList(0, XNArea, &rect, NULL); + + if (scrollbar_visible()) { + if (Options & Opt_scrollBar_right) { + status_rect.x = 0; + } else { + status_rect.x = SB_WIDTH + SHADOW * 2; + } + } else { + status_rect.x = 0; + } + if (menuBar.state == 1) { + status_rect.y = Height2Pixel(TermWin.nrow - 1) + menuBar_TotalHeight(); + } else { + status_rect.y = Height2Pixel(TermWin.nrow - 1); + } + status_rect.width = needed_rect->width; + status_rect.height = needed_rect->height; + status_attr = XVaCreateNestedList(0, XNArea, &status_rect, NULL); + XSetICValues(Input_Context, + XNPreeditAttributes, preedit_attr, + XNStatusAttributes, status_attr, NULL); + XFree(preedit_attr); + XFree(status_attr); + } +} + +/* PROTO */ +void +XProcessEvent( Display *display ) +{ + XEvent xev; + XNextEvent( display, &xev ); + if( !XFilterEvent( &xev, xev.xany.window ) ) + process_x_event( &xev ); + return; +} + +#endif /*}}} */ /*----------------------- end-of-file (C source) -----------------------*/ diff -urN aterm-0.4.2.orig/src/main.c aterm-0.4.2/src/main.c --- aterm-0.4.2.orig/src/main.c Fri Sep 7 01:38:07 2001 +++ aterm-0.4.2/src/main.c Mon Sep 17 06:49:41 2001 @@ -901,6 +901,9 @@ XResizeWindow(Xdisplay, TermWin.parent, width, height); resize_window1(width, height); +#ifdef USE_XIM + IMSetStatusPosition(); +#endif scr_clear(); } } @@ -1798,6 +1801,10 @@ #endif } +#ifdef USE_XIM + TermWin.fontset = NULL; +#endif + #ifdef XTERM_REVERSE_VIDEO /* this is how xterm implements reverseVideo */ if (Options & Opt_reverseVideo) { diff -urN aterm-0.4.2.orig/src/rxvt.h aterm-0.4.2/src/rxvt.h --- aterm-0.4.2.orig/src/rxvt.h Fri Sep 7 01:38:07 2001 +++ aterm-0.4.2/src/rxvt.h Mon Sep 17 06:46:01 2001 @@ -280,6 +280,9 @@ #ifdef MULTICHAR_SET XFontStruct *mfont; /* Multichar font structure */ #endif +#ifdef USE_XIM + XFontSet fontset; +#endif #if defined(BACKGROUND_IMAGE) || defined(TRANSPARENT) || defined(_MYSTYLE_) BackgroundInfo background; #endif @@ -949,6 +952,10 @@ #ifdef PRINTPIPE EXTERN const char *rs_print_pipe; #endif +#ifdef USE_XIM +EXTERN const char *rs_preeditType; +EXTERN const char *rs_inputMethod; +#endif #ifndef NO_BRIGHTCOLOR EXTERN unsigned int colorfgbg; #endif diff -urN aterm-0.4.2.orig/src/screen.c aterm-0.4.2/src/screen.c --- aterm-0.4.2.orig/src/screen.c Fri Sep 7 01:38:07 2001 +++ aterm-0.4.2/src/screen.c Mon Sep 17 06:46:01 2001 @@ -3439,3 +3439,17 @@ #endif fprintf(stderr, "%s\n", name[color]); } + +#ifdef USE_XIM +/* PROTO */ +void +setPosition(XPoint *pos) +{ + XWindowAttributes xwa ; + + XGetWindowAttributes( Xdisplay, TermWin.vt, &xwa ) ; + pos->x = Col2Pixel ( screen.cur.col ) + xwa.x; + pos->y = Height2Pixel((screen.cur.row + 1)) + xwa.y; + return ; +} +#endif diff -urN aterm-0.4.2.orig/src/xdefaults.c aterm-0.4.2/src/xdefaults.c --- aterm-0.4.2.orig/src/xdefaults.c Fri Sep 7 01:38:07 2001 +++ aterm-0.4.2/src/xdefaults.c Mon Sep 17 06:46:01 2001 @@ -276,6 +276,11 @@ STRG(rs_multichar_encoding, "multichar_encoding", "km", "mode", "multiple-character font encoding; mode = eucj | sjis | big5"), #endif /* MULTICHAR_SET */ +#ifdef USE_XIM + STRG(rs_preeditType, "preeditType", "pt", "style", + "input style of input method; style = OverTheSpot | OffTheSpot | Root"), + STRG(rs_inputMethod, "inputMethod", "im", "name", "name of input method"), +#endif /* USE_XIM */ #ifdef GREEK_SUPPORT STRG(rs_greek_keyboard, "greek_keyboard", "grk", "mode", "greek keyboard mapping; mode = iso | ibm"),