/****************************************************************** Copyright 1991, by FUJITSU LIMITED Modified by Digital Equipment Corporation, 1993 This demo program is modified from the demo program in the public domain of X11R5 contribution. To run this program, $ximdemo [-locale] [-display] [-Root / -Cb] [-fs] [-xrm_file] [-immodifier] To set locale: -locale To set display: -display To set root-window pre-editing as your preference choice: -Root To set on-the-spot pre-editing as your preference choice: -Cb To set your preferred base font name list: -fs To set your resource database: -xrm_file To set im modifier name: -immodifier ******************************************************************/ #include #include #include #include #include #include #include #include #define W_WIDTH 422 #define W_HEIGHT 162 #define MAXTYPE 20 #define DEFAULT_LOCALE "zh_TW.dechanyu" #define DEFAULT_FONT_NAME "-*-SCREEN-*-*-R-Normal--*-*, -*" static void CreateStatus(); static Window JxCreateTextWindow(); static int JxDestroyTextWindow(); static int JxRealizeText(); static int JxRedisplayText(); static int _JxNextLine(); static int JxWriteText(); /* Forward declarations */ typedef struct { Display *dpy; Window win; XFontSet fset; } preedcb_data; GC Jxgc_on, Jxgc_off; int Jxcx, Jxcy; int Jxcx_offset=2, Jxcy_offset=2; int Jxsfont_w, Jxwfont_w, Jxfont_height; XRectangle *Jxfont_rect; int Jxw_width, Jxw_height; #define Jxmax_line 10 int Jxsize[Jxmax_line]; char Jxbuff[Jxmax_line][128]; int Jxline_no; int Jxline_height; int sav_cx, sav_cy; int sav_w_width, w_height; int sav_size[Jxmax_line]; int sav_line_no; char preedit_buffer[12]; void save_value() { int i; sav_cx = Jxcx; sav_cy = Jxcy; sav_line_no = Jxline_no; for (i=0; i< Jxmax_line; i++) sav_size[i] = Jxsize[i]; } void restore_value() { int i; Jxcx = sav_cx; Jxcy = sav_cy; Jxline_no = sav_line_no; for (i=0; i< Jxmax_line; i++) Jxsize[i] = sav_size[i]; } int api_preedit_start_cb(ic, clientdata, calldata) XIC ic; XPointer clientdata; XPointer calldata; { int len; len = 12; /* save up the values */ save_value(); return(len); } void api_preedit_done_cb(ic, clientdata, calldata) XIC ic; XPointer clientdata; XPointer calldata; { preedcb_data *cd = (preedcb_data *)clientdata; /* restore up the values */ restore_value(); JxRedisplayText(cd->dpy, cd->win, cd->fset); /* convenient handling */ return; } void api_preedit_draw_cb( ic, clientdata, calldata) XIC ic; XPointer clientdata; XIMPreeditDrawCallbackStruct *calldata; { preedcb_data *cd = (preedcb_data *)clientdata; int count; char *reset_str; if (calldata->text) { if (calldata->text->encoding_is_wchar) { } else { count = strlen(calldata->text->string.multi_byte); if (count > 12) { reset_str = XmbResetIC(ic); /* preedit string > max preedit buffer */ XFillRectangle(cd->dpy, cd->win, Jxgc_off, Jxcx, Jxcy, Jxw_width*13, Jxfont_height); /* clear the preedit area */ restore_value(); if (reset_str) XFree(reset_str); return; } if (!calldata->chg_length) { /* insert character */ if (!calldata->chg_first) { /* insert in first character in preedit buffer */ strncpy(&preedit_buffer[0],calldata->text->string.multi_byte, count); restore_value(); } else { /* Not Yet Implemented */ } } else { /* replace character */ if (!calldata->chg_first) { /* replace from first character in preedit buffer */ strncpy(&preedit_buffer[0],calldata->text->string.multi_byte, count); restore_value(); } else { /* Not Yet Implemented */ } } XFillRectangle(cd->dpy, cd->win, Jxgc_off, Jxcx, Jxcy, Jxw_width*13, Jxfont_height); /* clear the preedit area */ JxWriteText(cd->dpy, cd->win, cd->fset, count, preedit_buffer); } } else { /* should delete preedit buffer */ /* Not yet implemented */ } return; } void api_preedit_caret_cb(ic, clientdata, calldata) XIC ic; XPointer clientdata; XIMPreeditCaretCallbackStruct *calldata; { /* Not yet implemented */ return; } main(argc, argv) int argc; char *argv[]; { Display *display; int screen; Window root, window, client; XRectangle rect, StatusArea; XEvent event; unsigned long mask; unsigned long fpixel, bpixel; int font_height; int i, n; char *base_font_name = NULL; int len = 128; char string[128]; KeySym keysym; int count; XIMStyles *im_styles; XIMStyle xim_mode=0; XIMStyle best_style = XIMPreeditCallbacks; XIM im; XIC ic; XFontSet font_set; char *locale = NULL; XVaNestedList preedit_attr, status_attr; char **missing_list; int missing_count; char *def_string; char *display_name = NULL; char *res_file = NULL; XrmDatabase rdb = NULL; XIMStyle app_supported_styles; long im_event_mask; XVaNestedList nestlist; XIMCallback ximapicb[10]; char immodifier[100]; preedcb_data preedcb_cd; static char title[30]; immodifier[0] = '\0'; for(i=1; i 0) { fprintf(stderr, "The following charsets are missing: \n"); for (i=0; icount_styles; i++) { xim_mode = im_styles->supported_styles[i]; if((xim_mode & app_supported_styles) == xim_mode) { /* if we can handle it */ n = 0; if (xim_mode & best_style) /* pick user selected style */ break; } } } if(n) { printf("warning : Unsupport InputStyle. or No IMserver.\n"); exit (0); } if (xim_mode & XIMPreeditCallbacks) { ximapicb[0].client_data = (XPointer)NULL; ximapicb[0].callback = (XIMProc)api_preedit_start_cb; ximapicb[1].client_data = (XPointer)(&preedcb_cd); ximapicb[1].callback = (XIMProc)api_preedit_done_cb; ximapicb[2].client_data = (XPointer)(&preedcb_cd); ximapicb[2].callback = (XIMProc)api_preedit_draw_cb; ximapicb[3].client_data = (XPointer)NULL; ximapicb[3].callback = (XIMProc)api_preedit_caret_cb; nestlist = XVaCreateNestedList(10, XNPreeditStartCallback, &ximapicb[0], XNPreeditDoneCallback, &ximapicb[1], XNPreeditDrawCallback, &ximapicb[2], XNPreeditCaretCallback, &ximapicb[3], NULL); } if (xim_mode & XIMPreeditCallbacks) { ic = XCreateIC(im, XNInputStyle, xim_mode, XNClientWindow, window, XNFocusWindow, client, XNPreeditAttributes, nestlist, NULL); } else { /* preedit nothing */ ic = XCreateIC(im, XNInputStyle, xim_mode, XNClientWindow, window, XNFocusWindow, client, NULL ); } if(ic == NULL) { printf("Error : XCreateIC() !\n"); XCloseIM(im); exit(0); } XGetICValues(ic, XNFilterEvents, &im_event_mask, NULL); mask = StructureNotifyMask | FocusChangeMask | ExposureMask; XSelectInput(display, window, mask); mask = ExposureMask | KeyPressMask | FocusChangeMask | im_event_mask; XSelectInput(display, client, mask); if(res_file) { static char Resouce_name[] = "*"; char *ret; ret = XSetICValues(ic, XNResourceName, Resouce_name, NULL); if(ret != NULL) printf("Error : XSetICValues() name = %s\n", ret); } XMapWindow(display, window); XMapWindow(display, client); JxRealizeText(display, client); for(;;) { XNextEvent(display, &event); if(XFilterEvent(&event, NULL) == True) continue; switch(event.type ) { case FocusIn : if(event.xany.window == window) XSetInputFocus(display, client, RevertToParent, CurrentTime); else if(event.xany.window == client) { XSetICFocus(ic); } break; case FocusOut : if(event.xany.window == client) { XUnsetICFocus(ic); } break; case Expose : if(event.xany.window == client) JxRedisplayText(display, client, font_set); break; case KeyPress : count = XmbLookupString(ic, (XKeyPressedEvent *)&event, string, len, &keysym, NULL); if( count == 1 && string[0] == (0x1F&'c')) { /* exit */ goto exit; } if( count > 0 ) { JxWriteText(display, client, font_set, count, string); } break; case MappingNotify : XRefreshKeyboardMapping( (XMappingEvent *)&event ); break; case DestroyNotify : printf("Error : DestroyEvent !\n"); break; } } exit: XDestroyIC(ic); XCloseIM(im); JxDestroyTextWindow(display, client); XDestroyWindow(display, window); XCloseDisplay(display); return(0); } static Window JxCreateTextWindow(display, window, x, y, w_width, w_height, w_bw, bpixel, fpixel, font_set, font_heightp) Display *display; int x, y, w_width, w_height, w_bw; unsigned long fpixel, bpixel; XFontSet font_set; int *font_heightp; { Window client; unsigned long mask; XGCValues gcvalues; XFontSetExtents *fset_extents; Jxw_width = w_width; Jxw_height = w_height; client = XCreateSimpleWindow(display, window, x, y, w_width, w_height, w_bw, bpixel, fpixel); mask = GCBackground | GCForeground; gcvalues.foreground = bpixel; gcvalues.background = fpixel; Jxgc_on = XCreateGC(display, window, mask, &gcvalues); gcvalues.foreground = fpixel; gcvalues.background = bpixel; Jxgc_off = XCreateGC(display, window, mask, &gcvalues); Jxsfont_w = XmbTextEscapement(font_set, "$", 1); fset_extents = XExtentsOfFontSet(font_set); Jxfont_rect = &(fset_extents->max_logical_extent); *font_heightp = Jxfont_height = Jxfont_rect->height; Jxline_height = Jxfont_height + 2; Jxwfont_w = Jxfont_rect->width; return( client ); } static int JxDestroyTextWindow(display, client) Display *display; Window client; { XFreeGC(display, Jxgc_on); XFreeGC(display, Jxgc_off); XDestroyWindow(display, client); } static int JxRealizeText(display, client) Display *display; Window client; { int i; Jxline_no = 0; for(i=0; i < Jxmax_line; i++) { Jxsize[i] = 0; Jxbuff[i][0] = 0; } Jxcx = Jxcx_offset; Jxcy = Jxcy_offset; XFillRectangle(display, client, Jxgc_on, Jxcx, Jxcy, Jxsfont_w, Jxfont_height); } static int JxRedisplayText(display, client, font_set) Display *display; Window client; XFontSet font_set; { int i, fy; for(i=0; i < Jxmax_line; i++) { fy = i * Jxline_height + Jxcy_offset - Jxfont_rect->y; if( Jxsize[i] > 0 ){ XmbDrawImageString(display, client, font_set, Jxgc_on, Jxcx_offset, fy, Jxbuff[i], Jxsize[i]); } } XFillRectangle(display, client, Jxgc_on, Jxcx, Jxcy, Jxsfont_w, Jxfont_height); } static int _JxNextLine() { Jxcx = Jxcx_offset; Jxcy += Jxline_height; Jxline_no++; if(Jxline_no >= Jxmax_line) { Jxline_no = 0; Jxcy = Jxcy_offset; } Jxsize[Jxline_no] = 0; Jxbuff[Jxline_no][0] = 0; } #define LF 0x0a #define CR 0x0d #define TAB 0x09 static int JxWriteText(display, client, font_set, len, string) Display *display; Window client; XFontSet font_set; int len; char *string; { int fy; XFillRectangle(display, client, Jxgc_off, Jxcx, Jxcy, Jxsfont_w, Jxfont_height); if(len == 1 && (string[0] == LF || string[0] == TAB || string[0] == CR)) { _JxNextLine(); XFillRectangle(display, client, Jxgc_off, 0, Jxcy, Jxw_width, Jxfont_height); } else { if(Jxcx >= (Jxw_width - Jxwfont_w) || (Jxsize[Jxline_no] + len) >= 256) { _JxNextLine(); XFillRectangle(display, client, Jxgc_off, 0, Jxcy, Jxw_width, Jxfont_height); } strncpy(&Jxbuff[Jxline_no][Jxsize[Jxline_no]], string, len); Jxsize[Jxline_no] += len; fy = -Jxfont_rect->y + Jxcy; XmbDrawImageString(display, client, font_set, Jxgc_on, Jxcx, fy, string, len); Jxcx += XmbTextEscapement(font_set, string, len); if(Jxcx >= Jxw_width) { _JxNextLine(); XFillRectangle(display, client, Jxgc_off, 0, Jxcy, Jxw_width, Jxfont_height); } } XFillRectangle(display, client, Jxgc_on, Jxcx, Jxcy, Jxsfont_w, Jxfont_height); }