Mercurial > kinput2.yaz
view lib/OnConv.c @ 4:5b1d5c19f325
imported patch 06_kinput2-v3.1-wm_delete_window.patch
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Mon, 08 Mar 2010 20:07:06 +0900 |
parents | e55ccba56891 |
children |
line wrap: on
line source
#ifndef lint static char *rcsid = "$Id: OnConv.c,v 10.9 1999/05/19 08:52:42 ishisone Exp $"; #endif /* * Copyright (c) 1990 Software Research Associates, Inc. * Copyright (c) 1999 Kazuki YASUMATSU * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Software Research Associates not be * used in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. Software Research * Associates makes no representations about the suitability of this software * for any purpose. It is provided "as is" without express or implied * warranty. * * Author: Makoto Ishisone, Software Research Associates, Inc., Japan * Author: Kazuki YASUMATSU (Kazuki.Yasumatsu@fujixerox.co.jp) */ #include <X11/IntrinsicP.h> #include <X11/StringDefs.h> #include <X11/Xmu/Atoms.h> #if XtSpecificationRelease > 4 #include <X11/Xfuncs.h> #endif #include <X11/Xatom.h> #include "CachedAtom.h" #include "AsyncErr.h" #include "OnConvP.h" #include "InputConv.h" #include "ConvDisp.h" #include "CandPanel.h" #include "AuxPanel.h" #include "ICLabel.h" #define DEBUG_VAR debug_OnTheSpotConversion #include "DebugPrint.h" /*- resource table -*/ static XtResource resources[] = { #define offset(field) XtOffset(OnTheSpotConversionWidget, onthespot.field) { XtNpreeditStartCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), offset(preeditstartcallback), XtRCallback, (XtPointer)NULL }, { XtNpreeditDoneCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), offset(preeditdonecallback), XtRCallback, (XtPointer)NULL }, { XtNpreeditDrawCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), offset(preeditdrawcallback), XtRCallback, (XtPointer)NULL }, { XtNpreeditCaretCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), offset(preeditcaretcallback), XtRCallback, (XtPointer)NULL }, { XtNstatusStartCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), offset(statusstartcallback), XtRCallback, (XtPointer)NULL }, { XtNstatusDoneCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), offset(statusdonecallback), XtRCallback, (XtPointer)NULL }, { XtNstatusDrawCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList), offset(statusdrawcallback), XtRCallback, (XtPointer)NULL }, { XtNfeedbackAttributes, XtCFeedbackAttributes, XtRFeedbackAttributes, sizeof(FeedbackAttributes), offset(feedbackattrs), XtRString, (XtPointer)"U,,R,H" }, #undef offset }; /*- default translations -*/ static char translations[] = "<Key>: to-inputobj()"; /* same as superclass's */ /*- declarations of local structures -*/ typedef struct { int attrs_length; int attrs_limit; unsigned long *attrs_buffer; } AttributeBuffer; /*- declarations of static functions -*/ static void ClassInitialize(); static void Initialize(); static void Destroy(); static Boolean SetValues(); static void ConversionStartup(); static void ConversionFinish(); static void ChangeAttributes(); static void ChangeFocus(); static void StringToFeedbackAttrs(); static Widget CreateSelectionWidget(); static void UpdateText(); static void CommitText(); static void UpdateMode(); static void SelectionControl(); static void SelectionStart(); static void LocateSelectionPopup(); static void SelectionEnd(); static void SelectionSet(); static void SelectionGet(); static void SelectionMove(); static Widget CreateAuxWidget(); static void AuxControl(); static void AuxStart(); static void AuxEnd(); static void AuxChange(); static void LocateAuxPopup(); static void SelectionSelected(); static Boolean SafeGetWindowAttributes(); static void MoveShell(); static Window getToplevelWindow(); static void setTransientFor(); static void allocDisplaySegments(); static void freeDisplaySegment(); static void clearAllDisplaySegments(); static void copyString(); static void freeString(); static AttributeBuffer *allocAttributeBuffer(); static void destroyAttributeBuffer(); static void addAttributeBuffer(); static unsigned long attrToFeedback(); static void CBPreeditStart(); static void CBPreeditDone(); static void CBPreeditDraw(); static void CBPreeditCaret(); static void CBStatusStart(); static void CBStatusDone(); static void CBStatusDraw(); /*- composite-extension rec: for enabling non-widget children -*/ static CompositeClassExtensionRec CompositeExtension = { /* next_extension */ NULL, /* record_type */ NULLQUARK, /* version */ XtCompositeExtensionVersion, /* record_size */ sizeof(CompositeClassExtensionRec), /* accept_objects */ True, }; /*- onTheSpotConversionClass record -*/ OnTheSpotConversionClassRec onTheSpotConversionClassRec = { { /* core fields */ /* superclass */ (WidgetClass)&conversionControlClassRec, /* class_name */ "OnTheSpotConversion", /* widget_size */ sizeof(OnTheSpotConversionRec), /* class_initialize */ ClassInitialize, /* class_part_initialize */ NULL, /* class_inited */ FALSE, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ XtInheritRealize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ TRUE, /* compress_exposure */ TRUE, /* compress_enterleave */ TRUE, /* visible_interest */ FALSE, /* destroy */ Destroy, /* resize */ XtInheritResize, /* expose */ NULL, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ NULL, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ translations, /* query_geometry */ XtInheritQueryGeometry, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL }, { /* composite fields */ /* geometry_manager */ XtInheritGeometryManager, /* change_managed */ XtInheritChangeManaged, /* insert_child */ XtInheritInsertChild, /* delete_child */ XtInheritDeleteChild, /* extension */ (XtPointer)&CompositeExtension, }, { /* shell fields */ /* extension */ NULL }, { /* wm_shell fields */ /* extension */ NULL }, { /* vendor_shell fields */ /* extension */ NULL }, { /* transient_shell fields */ /* extension */ NULL }, { /* conversionControl fields */ /* Startup */ ConversionStartup, /* Finish */ ConversionFinish, /* ChangeAttributes */ ChangeAttributes, /* ChangeFocus */ ChangeFocus, /* TextChange */ UpdateText, /* Fix */ CommitText, /* ModeChange */ UpdateMode, /* SelectionControl */ SelectionControl, /* AuxControl */ AuxControl, }, { /* onTheSpotConversion fields */ /* empty */ 0 }, }; WidgetClass onTheSpotConversionWidgetClass = (WidgetClass)&onTheSpotConversionClassRec; /* *+ Core class method */ /*- ClassInitialize: class initializer -*/ /* ARGSUSED */ static void ClassInitialize() { /* add String -> FeedbackAttributes converter */ XtAddConverter(XtRString, XtRFeedbackAttributes, StringToFeedbackAttrs, (XtConvertArgList)NULL, (Cardinal)0); } /*- Initialize: initalize method -*/ /* ARGSUSED */ static void Initialize(req, new, args, num_args) Widget req; Widget new; ArgList args; Cardinal *num_args; { OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)new; (void)CreateSelectionWidget(ocw); (void)CreateAuxWidget(ocw); ocw->onthespot.dispsegments = NULL; ocw->onthespot.numsegments = 0; ocw->onthespot.dispsegmentsize = 0; ocw->onthespot.candlist = NULL; ocw->onthespot.numcands = 0; ocw->onthespot.selectionpoppedup = False; ocw->onthespot.auxpoppedup = False; ocw->onthespot.lastcaret = 0; ocw->onthespot.fixnotify = False; } /*- Destroy: destroy method -*/ static void Destroy(w) Widget w; { OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)w; /* $B%G%#%9%W%l%$%;%0%a%s%H$NNN0h$r2rJ|(B */ if (ocw->onthespot.dispsegments) { DisplaySegment *dsp = ocw->onthespot.dispsegments; int i; for (i = 0; i < ocw->onthespot.numsegments; i++) { freeString(&dsp[i].seg); } XtFree((char *)dsp); } } /*- SetValues: setvalues method -*/ /* ARGSUSED */ static Boolean SetValues(cur, req, new, args, num_args) Widget cur; Widget req; Widget new; ArgList args; Cardinal *num_args; { /* OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)new; */ return False; } /* *+ ConversionControl class method */ /*- ConversionStartup: class specific conversion startup -*/ static void ConversionStartup(widget, valuemask, value) Widget widget; unsigned long valuemask; ConversionAttributes *value; { OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)widget; Widget inputobj = ocw->ccontrol.inputobj; Window toplevel; TRACE(("OnTheSpot:ConversionStartup()\n")); /* $BFbIt$N%P%C%U%!$r%/%j%"$9$k(B */ clearAllDisplaySegments(ocw); /* WM_TRANSIENT_FOR $B%W%m%Q%F%#$r@5$7$/%;%C%H$9$k(B */ toplevel = getToplevelWindow(XtDisplay(widget), ocw->ccontrol.clientwindow); setTransientFor(ocw->onthespot.selectionshell, toplevel); setTransientFor(ocw->onthespot.auxshell, toplevel); /* * OnTheSpotConvesion $B$N(B widget $B<+BN$O%]%C%W%"%C%W$5$;$J$$$,!"(B * $B%P%C%/%(%s%I%?%$%W$N;~$K$O%/%i%$%"%s%H$,$3$N(B widget $B$N(B * $B%&%#%s%I%&$KBP$7$F%$%Y%s%H$rAw$k$N$G(B Realize $B$@$1$7$F$*$/(B */ if (!XtIsRealized(widget)) { Arg args[2]; XtSetArg(args[0], XtNwidth, 1); XtSetArg(args[1], XtNheight, 1); XtSetValues(widget, args, 2); XtRealizeWidget(widget); } ocw->onthespot.lastcaret = 0; ocw->onthespot.fixnotify = False; /* $B%9%F!<%?%9$r99?7$9$k(B */ UpdateMode(widget); /* $B%W%l%(%G%#%C%H$r3+;O$9$k(B */ CBPreeditStart(widget); } /*- ConversionFinish: class specific conversion finish -*/ /* ARGSUSED */ static void ConversionFinish(w) Widget w; { OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)w; Atom encoding = XA_COMPOUND_TEXT(XtDisplayOfObject(w)); int format = 8; if (!ocw->onthespot.fixnotify) { /* $B3NDj$7$F$$$J$$(B */ DisplaySegment *dseg = ocw->onthespot.dispsegments; int i, len = 0; for (i = 0; i < ocw->onthespot.numsegments; i++, dseg++) { len += dseg->seg.nchars; } if (len > 0) { /* $B%W%l%(%G%#%C%H%P%C%U%!$N>C5n(B */ unsigned long attr = 0; CBPreeditDraw(ocw, 0, 0, len, encoding, format, 0, (XPointer)"", 0, &attr); } } /* $B%W%l%(%G%#%C%H$r=*N;$9$k(B */ CBPreeditDone(w); /* $B%9%F!<%?%9$r99?7(B($B=i4|2=(B)$B$9$k(B */ CBStatusDraw(ocw, encoding, format, 0, (XPointer)"", 0); if (ocw->onthespot.selectionpoppedup) { XtPopdown(ocw->onthespot.selectionshell); ocw->onthespot.selectionpoppedup = False; } if (ocw->onthespot.auxpoppedup) { XtPopdown(ocw->onthespot.auxshell); ocw->onthespot.auxpoppedup = False; } } /*- ChangeAttributes: class specific conversion attribute change routine -*/ /* ARGSUSED */ static void ChangeAttributes(w, valuemask, value) Widget w; unsigned long valuemask; ConversionAttributes *value; { /* do nothing */ } /*- ChangeFocus: class specific conversion attribute change routine -*/ static void ChangeFocus(w, set) Widget w; int set; { if (set) { UpdateMode(w); } else { #if 0 /* $B%U%)!<%+%9$r<:$C$?>l9g$K$O2?$b$7$J$$(B */ OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)w; Atom encoding = XA_COMPOUND_TEXT(XtDisplayOfObject(w)); int format = 8; CBStatusDraw(ocw, encoding, format, 0, (XPointer)"", 0); #endif } } /* *+ resource converter */ /*- StringToFeedbackAttrs: string to feedback attiributes converter -*/ static void StringToFeedbackAttrs(args, num_args, from, to) XrmValue *args; Cardinal *num_args; XrmValue *from; XrmValue *to; { char *s = (char *)from->addr; int idx; int invalid = 0; static FeedbackAttributes fba; for (idx = 0; idx < 4; idx++) fba.feedbacks[idx] = 0; for (idx = 0; idx < 4; idx++) { int c; unsigned long fb = 0; while ((c = *s++) != ',' && c != '\0') { switch (c) { case 'R': case 'r': fb |= XIMReverse; break; case 'U': case 'u': fb |= XIMUnderline; break; case 'H': case 'h': fb |= XIMHighlight; break; case 'P': case 'p': fb |= XIMPrimary; break; case 'S': case 's': fb |= XIMSecondary; break; case 'T': case 't': fb |= XIMTertiary; break; case ' ': case '\t': break; default: invalid++; break; } } fba.feedbacks[idx] = fb; if (c == '\0') break; } if (invalid) { XtStringConversionWarning((char *)from->addr, XtRFeedbackAttributes); } to->size = sizeof(fba); to->addr = (caddr_t)&fba; } /* *+ sub-widget creation */ /*- CreateSelectionWidget: create selection widget for selecting candidates -*/ static Widget CreateSelectionWidget(ocw) OnTheSpotConversionWidget ocw; { Widget shell, sel; /* set width/height so that XtRealizeWidget() doesn't cause error */ shell = XtVaCreatePopupShell("selectionShell", transientShellWidgetClass, (Widget)ocw, XtNwidth, 1, XtNheight, 1, NULL); ocw->onthespot.selectionshell = shell; sel = XtCreateManagedWidget("selection", candidatePanelWidgetClass, shell, NULL, 0); (void)XtCreateWidget("display", ocw->ccontrol.displayobjclass, sel, NULL, 0); XtAddCallback(sel, XtNcallback, SelectionSelected, (XtPointer)ocw); XtInstallAccelerators(sel, (Widget)ocw); ocw->onthespot.selectionwidget = sel; return shell; } /*- CreateAuxWidget: create aux widget for display auxiliary data -*/ static Widget CreateAuxWidget(ocw) OnTheSpotConversionWidget ocw; { Widget shell, sel; /* set width/height so that XtRealizeWidget() doesn't cause error */ shell = XtVaCreatePopupShell("auxShell", transientShellWidgetClass, (Widget)ocw, XtNwidth, 1, XtNheight, 1, XtNallowShellResize, True, NULL); ocw->onthespot.auxshell = shell; sel = XtCreateManagedWidget("aux", auxPanelWidgetClass, shell, NULL, 0); (void)XtCreateWidget("display", ocw->ccontrol.displayobjclass, sel, NULL, 0); XtAddCallback(sel, XtNcallback, SelectionSelected, (XtPointer)ocw); XtInstallAccelerators(sel, (Widget)ocw); ocw->onthespot.auxwidget = sel; return shell; } /* *+ inputobject callback */ /*- UpdateText: update text -*/ static void UpdateText(w) Widget w; { OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)w; Widget inputobj = ocw->ccontrol.inputobj; int nnew = ICNumSegments(inputobj); int nold = ocw->onthespot.numsegments; FeedbackAttributes *fba = &ocw->onthespot.feedbackattrs; Cardinal cseg, caret; ICString *newseg; DisplaySegment *dseg; Boolean changed; int chgseg, chgoffset; int oldlen; AttributeBuffer *buffer; int i; int diff; Cardinal nsame; TRACE(("OnTheSpotConversion:UpdateText() nnew=%d\n", nnew)); ocw->onthespot.fixnotify = False; if (!ICCursorPos(inputobj, &cseg, &caret)) { cseg = nnew; caret = 0; } allocDisplaySegments(ocw, nnew); changed = False; chgseg = chgoffset = 0; oldlen = 0; buffer = allocAttributeBuffer(); for (i = 0, dseg = ocw->onthespot.dispsegments; i < nnew; i++, dseg++) { newseg = ICGetSegment(inputobj, i); if (i < cseg) { caret += newseg->nchars; } if (i >= nold) { copyString(newseg, &dseg->seg); addAttributeBuffer(buffer, inputobj, newseg, 0, fba); if (!changed) { chgseg = i; chgoffset = 0; changed = True; } } else { oldlen += dseg->seg.nchars; diff = ICCompareSegment(inputobj, newseg, &dseg->seg, &nsame); switch (diff) { case ICSame: if (changed) { addAttributeBuffer(buffer, inputobj, newseg, 0, fba); } break; case ICAttrChanged: dseg->seg.attr = newseg->attr; addAttributeBuffer(buffer, inputobj, newseg, 0, fba); if (!changed) { chgseg = i; chgoffset = 0; changed = True; } break; case ICStringChanged: freeString(&dseg->seg); copyString(newseg, &dseg->seg); if (!changed) { addAttributeBuffer(buffer, inputobj, newseg, nsame, fba); chgseg = i; chgoffset = nsame; changed = True; } else { addAttributeBuffer(buffer, inputobj, newseg, 0, fba); } break; default: /* ICAttrChanged | ICStringChanged */ freeString(&dseg->seg); copyString(newseg, &dseg->seg); addAttributeBuffer(buffer, inputobj, newseg, 0, fba); if (!changed) { chgseg = i; chgoffset = 0; changed = True; } break; } } } for (; i < nold; i++, dseg++) { oldlen += dseg->seg.nchars; if (!changed) { chgseg = i; chgoffset = 0; changed = True; } freeDisplaySegment(dseg); } ocw->onthespot.numsegments = nnew; if (!changed) { if (ocw->onthespot.lastcaret != caret) { CBPreeditCaret(ocw, caret); } } else { /* changed */ Atom encoding = ocw->ccontrol.textencoding; int format; int length; XtPointer string; if (ICGetPreeditString(inputobj, chgseg, chgoffset, &encoding, &format, &length, &string) == 0) { dseg = ocw->onthespot.dispsegments; for (i = 0; i < chgseg; i++, dseg++) { chgoffset += dseg->seg.nchars; } CBPreeditDraw(ocw, caret, chgoffset, oldlen - chgoffset, encoding, format, length, string, buffer->attrs_length, buffer->attrs_buffer); /* string $B$r(B free $B$7$F$*$/(B */ XtFree((char *)string); } } ocw->onthespot.lastcaret = caret; /* buffer $B$r(B destroy $B$7$F$*$/(B */ destroyAttributeBuffer(buffer); } /*- CommitText: commit text -*/ static void CommitText(w, arg) Widget w; CCTextCallbackArg *arg; { OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)w; DisplaySegment *dseg; int i, len; dseg = ocw->onthespot.dispsegments; len = 0; for (i = 0; i < ocw->onthespot.numsegments; i++, dseg++) { len += dseg->seg.nchars; } if (len > 0) { /* $B%W%l%(%G%#%C%H%P%C%U%!$N>C5n(B */ Atom encoding = XA_COMPOUND_TEXT(XtDisplayOfObject(w)); int format = 8; unsigned long attr = 0; CBPreeditDraw(ocw, 0, 0, len, encoding, format, 0, (XPointer)"", 0, &attr); } /* $BFbIt$N%P%C%U%!$r%/%j%"$9$k(B */ clearAllDisplaySegments(ocw); ocw->onthespot.lastcaret = 0; XtCallCallbackList((Widget)ocw, ocw->ccontrol.textcallback, (XtPointer)arg); ocw->onthespot.fixnotify = True; } /*- UpdateMode: update mode -*/ static void UpdateMode(w) Widget w; { OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)w; Widget inputobj = ocw->ccontrol.inputobj; Atom encoding = ocw->ccontrol.textencoding; int format; int length; XtPointer string; int nchars; TRACE(("OnTheSpotConversion:UpdateMode()\n")); if (ICGetStatusString(inputobj, &encoding, &format, &length, &string, &nchars) == -1) return; CBStatusDraw(ocw, encoding, format, length, string, nchars); /* string $B$r(B free $B$7$F$*$/(B */ XtFree((char *)string); } /*- SelectionControl: selection control -*/ static void SelectionControl(w, arg) Widget w; ICSelectionControlArg *arg; { OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)w; String params[1]; Cardinal num_params; switch (arg->command) { case ICSelectionStart: SelectionStart(ocw, arg->u.selection_kind); break; case ICSelectionEnd: SelectionEnd(ocw, &arg->u.current_item); break; case ICSelectionSet: SelectionSet(ocw, arg->u.current_item); break; case ICSelectionMove: SelectionMove(ocw, arg->u.dir); break; case ICSelectionGet: SelectionGet(ocw, &arg->u.current_item); break; default: params[0] = XtClass(w)->core_class.class_name; num_params = 1; XtAppWarningMsg(XtWidgetToApplicationContext(w), "parameterError", "SelectionControl", "WidgetError", "%s: unknown selection control command", params, &num_params); break; } } /*- SelectionStart: selection startup -*/ /* ARGSUSED */ static void SelectionStart(ocw, kind) OnTheSpotConversionWidget ocw; int kind; { Cardinal ncand; Atom wm_state, atom, protocols[1]; unsigned long data[2]; Display *dpy; TRACE(("OnTheSpotConversion:SelectionStart()\n")); if (ocw->onthespot.selectionpoppedup) { TRACE(("\tselection already started -- ignored\n")); return; } ocw->onthespot.candlist = ICGetItemList(ocw->ccontrol.inputobj, &ncand); ocw->onthespot.numcands = ncand; TRACE(("\tnumcands=%d\n", ocw->onthespot.numcands)); CPanelSetList(ocw->onthespot.selectionwidget, ocw->onthespot.candlist, ocw->onthespot.numcands, 0, True); LocateSelectionPopup(ocw); XtPopup(ocw->onthespot.selectionshell, XtGrabNone); ocw->onthespot.selectionpoppedup = True; /* force to be set _NET_WM_STATE_ABOVE, because the candidate window * always should be shown above anything window. */ dpy = XtDisplay ((Widget) ocw); wm_state = CachedInternAtom (dpy, "_NET_WM_STATE", True); atom = CachedInternAtom (dpy, "_NET_WM_STATE_ABOVE", True); data[0] = atom; XChangeProperty (dpy, XtWindow (ocw->onthespot.selectionshell), wm_state, XA_ATOM, 32, PropModeAppend, data, 1); protocols[0] = CachedInternAtom (dpy, "WM_DELETE_WINDOW", True); XSetWMProtocols (dpy, XtWindow (ocw->onthespot.selectionshell), protocols, 1); } /*- LocateSelectionPopup: put selection popup at an appropriate position -*/ static void LocateSelectionPopup(ocw) OnTheSpotConversionWidget ocw; { Position x, y; int clx, cly; Dimension dpyWidth, dpyHeight; Widget panel = ocw->onthespot.selectionwidget; Widget shell = ocw->onthespot.selectionshell; Window junk; int barheight = ocw->ccontrol.titlebarheight; (void)XTranslateCoordinates(XtDisplay(ocw), ocw->ccontrol.clientwindow, RootWindowOfScreen(XtScreen(ocw)), 0, 0, &clx, &cly, &junk); (void)SafeGetWindowAttributes(XtDisplay(ocw), ocw->ccontrol.clientwindow, &(ocw->ccontrol.client_attr)); x = clx; y = cly + ocw->ccontrol.client_attr.height; dpyWidth = WidthOfScreen(XtScreen(shell)); dpyHeight = HeightOfScreen(XtScreen(shell)); if (x + panel->core.width > (int)dpyWidth) x = dpyWidth - panel->core.width; if (x < 0) x = 0; #if 0 if (y + panel->core.height + barheight > (int)dpyHeight) { y = cly - panel->core.height - 8 - barheight - 20; /* XXX */ if (y < 0) y = dpyHeight - panel->core.height - barheight; } #endif if (y + panel->core.height + barheight > (int)dpyHeight) y = dpyHeight - panel->core.height - 8 - barheight - 20; /* XXX */ if (y < 0) y = 0; MoveShell(shell, x, y); } /*- SelectionEnd: selection finish -*/ static void SelectionEnd(ocw, current) OnTheSpotConversionWidget ocw; int *current; { TRACE(("OnTheSpotConversion:SelectionEnd()\n")); if (!ocw->onthespot.selectionpoppedup) { /* for safe */ TRACE(("\tnot in selection mode -- ignored\n")); return; } XtVaGetValues(ocw->onthespot.selectionwidget, XtNcurrentItem, current, NULL); XtPopdown(ocw->onthespot.selectionshell); ocw->onthespot.selectionpoppedup = False; } /*- SelectionSet: set current selection item -*/ static void SelectionSet(ocw, current) OnTheSpotConversionWidget ocw; int current; { TRACE(("OnTheSpotConversion:SelectionSet()\n")); if (!ocw->onthespot.selectionpoppedup) { /* for safe */ TRACE(("\tnot in selection mode -- ignored\n")); return; } XtVaSetValues(ocw->onthespot.selectionwidget, XtNcurrentItem, current, NULL); } /*- SelectionGet: get current selection item -*/ static void SelectionGet(ocw, current) OnTheSpotConversionWidget ocw; int *current; { TRACE(("OnTheSpotConversion:SelectionGet()\n")); if (!ocw->onthespot.selectionpoppedup) { /* for safe */ TRACE(("\tnot in selection mode -- ignored\n")); return; } XtVaGetValues(ocw->onthespot.selectionwidget, XtNcurrentItem, current, NULL); } /*- SelectionMove: move crrent selection to specified direction -*/ static void SelectionMove(ocw, dir) OnTheSpotConversionWidget ocw; int dir; { TRACE(("OnTheSpotConversion:SelectionMove()\n")); if (!ocw->onthespot.selectionpoppedup) { /* for safe */ TRACE(("\tnot in selection mode -- ignored\n")); return; } CPanelMoveCurrent(ocw->onthespot.selectionwidget, dir); } /* * Aux Callback */ static void AuxControl(w, arg) Widget w; ICAuxControlArg *arg; { OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)w; String params[1]; Cardinal num_params; switch (arg->command) { case ICAuxStart: AuxStart(ocw); break; case ICAuxEnd: AuxEnd(ocw); break; case ICAuxChange: AuxChange(ocw); break; default: params[0] = XtClass(w)->core_class.class_name; num_params = 1; XtAppWarningMsg(XtWidgetToApplicationContext(w), "parameterError", "AuxControl", "WidgetError", "%s: unknown aux control command", params, &num_params); break; } } /* ARGSUSED */ static void AuxStart(ocw) OnTheSpotConversionWidget ocw; { ICString *auxstr; Cardinal ncand, curseg, cursorpos; if (ocw->onthespot.auxpoppedup) return; /* $B%F%-%9%H%3!<%k%P%C%/$N;~$N$h$&$J=hM}$r$9$k(B $B$N$O(B AuxPanel.c $B$K$^$+$;$h$&(B */ auxstr = ICGetAuxSegments(ocw->ccontrol.inputobj, &ncand, &curseg, &cursorpos); APanelStart(ocw->onthespot.auxwidget, auxstr, ncand, curseg, cursorpos); /* $B%]%C%W%"%C%W$9$k>l=j$r7h$a$k(B */ LocateAuxPopup(ocw); XtPopup(ocw->onthespot.auxshell, XtGrabNone); ocw->onthespot.auxpoppedup = True; } /* ARGSUSED */ static void AuxEnd(ocw) OnTheSpotConversionWidget ocw; { if (!ocw->onthespot.auxpoppedup) return; /* for safe */ /* APanelEnd(ocw->onthespot.auxwidget); */ XtPopdown(ocw->onthespot.auxshell); ocw->onthespot.auxpoppedup = False; } /* ARGSUSED */ static void AuxChange(ocw) OnTheSpotConversionWidget ocw; { Cardinal ncand, curseg, cursorpos; ICString *auxstr; if (!ocw->onthespot.auxpoppedup) return; /* for safe */ auxstr = ICGetAuxSegments(ocw->ccontrol.inputobj, &ncand, &curseg, &cursorpos); APanelChange(ocw->onthespot.auxwidget, auxstr, ncand, curseg, cursorpos); } /*- LocateAuxPopup: put aux popup at an appropriate position -*/ static void LocateAuxPopup(ocw) OnTheSpotConversionWidget ocw; { Position x, y; int clx, cly; Dimension dpyWidth, dpyHeight; Widget panel = ocw->onthespot.auxwidget; Widget shell = ocw->onthespot.auxshell; Window junk; int barheight = ocw->ccontrol.titlebarheight; (void)XTranslateCoordinates(XtDisplay(ocw), ocw->ccontrol.clientwindow, RootWindowOfScreen(XtScreen(ocw)), 0, 0, &clx, &cly, &junk); (void)SafeGetWindowAttributes(XtDisplay(ocw), ocw->ccontrol.clientwindow, &(ocw->ccontrol.client_attr)); x = clx; y = cly + ocw->ccontrol.client_attr.height; dpyWidth = WidthOfScreen(XtScreen(shell)); dpyHeight = HeightOfScreen(XtScreen(shell)); if (x + panel->core.width > (int)dpyWidth) x = dpyWidth - panel->core.width; if (x < 0) x = 0; #if 0 if (y + panel->core.height + barheight > (int)dpyHeight) { y = cly - panel->core.height - 8 - barheight - 20; /* XXX */ if (y < 0) y = dpyHeight - panel->core.height - barheight; } #endif if (y + panel->core.height + barheight > (int)dpyHeight) y = dpyHeight - panel->core.height - 8 - barheight - 20; /* XXX */ if (y < 0) y = 0; MoveShell(shell, x, y); } /* *+ Selection Widget callback */ /*- SelectionSelected: selection selected callback -*/ /* ARGSUSED */ static void SelectionSelected(w, client_data, call_data) Widget w; XtPointer client_data; XtPointer call_data; { OnTheSpotConversionWidget ocw = (OnTheSpotConversionWidget)client_data; int current = (int)call_data; TRACE(("OnTheSpotConversion:SelectionSelected()\n")); XtPopdown(ocw->onthespot.selectionshell); ocw->onthespot.selectionpoppedup = False; ICSelectItem(ocw->ccontrol.inputobj, current); } /* *+ miscelaneous functions */ /*- SafeGetWindowAttributes: get window attributes -*/ static Boolean SafeGetWindowAttributes(dpy, w, attr) Display *dpy; Window w; XWindowAttributes *attr; { XAEHandle h; unsigned long errbits = 0; h = XAESetRecordErrors(dpy, &errbits); (void)XGetWindowAttributes(dpy, w, attr); XAEUnset(h); return (errbits == 0); } /*- MoveShell: move shell widget -*/ static void MoveShell(w, x, y) Widget w; Position x; Position y; { XtWidgetGeometry req; /* * calling XtMoveWidget() is NOT enough to move shell widgets. * we must use XtMakeGeometryRequest() or XtSetValues() to * invoke root-geometry-manager which modifies the size hint * appropriately. */ req.request_mode = CWX | CWY; req.x = x; req.y = y; (void)XtMakeGeometryRequest(w, &req, (XtWidgetGeometry *)NULL); } /*- getToplevelWindow: get top-level window of a given window -*/ static Window getToplevelWindow(dpy, win) Display *dpy; Window win; { Atom wm_state; Atom type; int format; unsigned long nitems, bytesafter; unsigned char *data; Window root, parent; Window *children; unsigned int nchildren; /* * find toplevel window which has WM_STATE property or if no exists, * direct subwindow of the root window. (ie I assume that if a * window manager is running, that is a ICCCM compliant one) */ wm_state = CachedInternAtom(dpy, "WM_STATE", True); for (;;) { type = None; if (wm_state != None) { data = NULL; XGetWindowProperty(dpy, win, wm_state, 0L, 0L, False, AnyPropertyType, &type, &format, &nitems, &bytesafter, &data); if (data != NULL) XtFree((char *)data); if (type != None) break; } if (!XQueryTree(dpy, win, &root, &parent, &children, &nchildren)) break; if (nchildren > 0) XtFree((char *)children); if (root == parent) break; win = parent; } return win; } /*- setTransientFor: set WM_TRANSIENT_FOR property to specified widget -*/ static void setTransientFor(w, win) Widget w; Window win; { if (!XtIsRealized(w)) XtRealizeWidget(w); XSetTransientForHint(XtDisplay(w), XtWindow(w), win); } /*- allocDisplaySegments: prepare specified number of display segments -*/ static void allocDisplaySegments(ocw, n) OnTheSpotConversionWidget ocw; Cardinal n; { if (ocw->onthespot.dispsegmentsize > n) return; n = ((n + 3) / 4) * 4 ; if (ocw->onthespot.dispsegments == NULL) { ocw->onthespot.dispsegments = (DisplaySegment *)XtMalloc(n * sizeof(DisplaySegment)); } else { ocw->onthespot.dispsegments = (DisplaySegment *)XtRealloc((char *)ocw->onthespot.dispsegments, n * sizeof(DisplaySegment)); } ocw->onthespot.dispsegmentsize = n; } /*- freeDisplaySegment: free display segment's contents -*/ static void freeDisplaySegment(dsp) DisplaySegment *dsp; { freeString(&dsp->seg); } /*- clearAllDisplaySegments: clear all display segment's -*/ static void clearAllDisplaySegments(ocw) OnTheSpotConversionWidget ocw; { DisplaySegment *dsp = ocw->onthespot.dispsegments; int i; for (i = 0; i < ocw->onthespot.numsegments; i++) { freeDisplaySegment(dsp++); } ocw->onthespot.numsegments = 0; } /*- copyString: copy ICString -*/ static void copyString(from, to) ICString *from; ICString *to; { *to = *from; to->data = XtMalloc(to->nbytes); (void)bcopy(from->data, to->data, to->nbytes); } /*- freeString: free ICString -*/ static void freeString(seg) ICString *seg; { XtFree(seg->data); seg->data = NULL; seg->nbytes = 0; } /*- allocAttributeBuffer: allocate attribute buffer -*/ static AttributeBuffer * allocAttributeBuffer() { AttributeBuffer *buffer; buffer = (AttributeBuffer *)XtMalloc(sizeof(AttributeBuffer)); buffer->attrs_length = 0; buffer->attrs_limit = 64; buffer->attrs_buffer = (unsigned long *)XtMalloc(buffer->attrs_limit * sizeof(unsigned long)); return buffer; } /*- destroyAttributeBuffer: destroy draw string buffer's contents -*/ static void destroyAttributeBuffer(buffer) AttributeBuffer *buffer; { XtFree((char *)buffer->attrs_buffer); XtFree((char *)buffer); } /*- addAttributeBuffer: add segment to draw string buffer's contents -*/ static void addAttributeBuffer(buffer, inputobj, seg, offset, fba) AttributeBuffer *buffer; Widget inputobj; ICString *seg; int offset; FeedbackAttributes *fba; { int nchars = seg->nchars - offset; unsigned long fb; int i; if (buffer->attrs_length + nchars > buffer->attrs_limit) { unsigned long *new_attrs_buffer; int new_limit = buffer->attrs_limit * 2; if (new_limit < buffer->attrs_length + nchars) new_limit = buffer->attrs_length + nchars + 8; new_attrs_buffer = (unsigned long *)XtMalloc(new_limit * sizeof(unsigned long)); bcopy(buffer->attrs_buffer, new_attrs_buffer, buffer->attrs_length * sizeof(unsigned long)); XtFree((char *)buffer->attrs_buffer); buffer->attrs_limit = new_limit; buffer->attrs_buffer = new_attrs_buffer; } fb = attrToFeedback(fba, seg->attr); for (i = 0; i < nchars; i++) { buffer->attrs_buffer[buffer->attrs_length + i] = fb; } buffer->attrs_length += nchars; } /*- attrToFeedback: ICString attribute -> XIMFeedback attribute converter -*/ static unsigned long attrToFeedback(fba, attr) FeedbackAttributes *fba; int attr; { int idx; if (attr == ICAttrNormalString) return 0; if (!(attr & ICAttrConverted)) { /* Not yet converted */ idx = FEEDBACK_NOCONV; } else if (attr & ICAttrCurrentSegment) { /* it's converted and the current segment */ idx = FEEDBACK_CURRENT; } else if (attr & ICAttrCurrentSubSegment) { /* it's converted and the current sub segment */ idx = FEEDBACK_CURRENTSUB; } else { /* converted, not current */ idx = FEEDBACK_CONV; } return fba->feedbacks[idx]; } /*- CBPreeditStart: callback preedit start -*/ static void CBPreeditStart(ocw) OnTheSpotConversionWidget ocw; { if (ocw->onthespot.preeditstartcallback == NULL || XtHasCallbacks((Widget)ocw, XtNpreeditStartCallback) != XtCallbackHasSome) { /* no callback */ return; } TRACE(("OnTheSpot:CBPreeditStart()\n")); XtCallCallbackList((Widget)ocw, ocw->onthespot.preeditstartcallback, (XtPointer)NULL); } /*- CBPreeditDone: callback preedit done -*/ static void CBPreeditDone(ocw) OnTheSpotConversionWidget ocw; { if (ocw->onthespot.preeditdonecallback == NULL || XtHasCallbacks((Widget)ocw, XtNpreeditDoneCallback) != XtCallbackHasSome) { /* no callback */ return; } TRACE(("OnTheSpot:CBPreeditDone()\n")); XtCallCallbackList((Widget)ocw, ocw->onthespot.preeditdonecallback, (XtPointer)NULL); } /*- CBPreeditDraw: callback preedit draw -*/ static void CBPreeditDraw(ocw, caret, chg_first, chg_length, encoding, format, text_length, text, attrs_length, attrs) OnTheSpotConversionWidget ocw; int caret; int chg_first; int chg_length; Atom encoding; int format; int text_length; XtPointer text; int attrs_length; unsigned long *attrs; { OCCPreeditDrawArg arg; if (ocw->onthespot.preeditdrawcallback == NULL || XtHasCallbacks((Widget)ocw, XtNpreeditDrawCallback) != XtCallbackHasSome) { /* no callback */ return; } TRACE(("OnTheSpot:CBPreeditDraw()\n")); arg.caret = caret; arg.chg_first = chg_first; arg.chg_length = chg_length; arg.encoding = encoding; arg.format = format; arg.text_length = text_length; arg.text = text; arg.attrs_length = attrs_length; arg.attrs = attrs; XtCallCallbackList((Widget)ocw, ocw->onthespot.preeditdrawcallback, (XtPointer)&arg); } /*- CBPreeditCaret: callback preedit caret -*/ static void CBPreeditCaret(ocw, caret) OnTheSpotConversionWidget ocw; int caret; { if (ocw->onthespot.preeditcaretcallback == NULL || XtHasCallbacks((Widget)ocw, XtNpreeditCaretCallback) != XtCallbackHasSome) { /* no callback */ return; } TRACE(("OnTheSpot:CBPreeditCaret()\n")); XtCallCallbackList((Widget)ocw, ocw->onthespot.preeditcaretcallback, (XtPointer)caret); } /*- CBStatusStart: callback status start -*/ static void CBStatusStart(ocw) OnTheSpotConversionWidget ocw; { if (ocw->onthespot.statusstartcallback == NULL || XtHasCallbacks((Widget)ocw, XtNstatusStartCallback) != XtCallbackHasSome) { /* no callback */ return; } TRACE(("OnTheSpot:CBStatusStart()\n")); XtCallCallbackList((Widget)ocw, ocw->onthespot.statusstartcallback, (XtPointer)NULL); } /*- CBStatusDone: callback status done -*/ static void CBStatusDone(ocw) OnTheSpotConversionWidget ocw; { if (ocw->onthespot.statusdonecallback == NULL || XtHasCallbacks((Widget)ocw, XtNstatusDoneCallback) != XtCallbackHasSome) { /* no callback */ return; } TRACE(("OnTheSpot:CBStatusDone()\n")); XtCallCallbackList((Widget)ocw, ocw->onthespot.statusdonecallback, (XtPointer)NULL); } /*- CBStatusDraw: callback status draw -*/ static void CBStatusDraw(ocw, encoding, format, length, text, nchars) OnTheSpotConversionWidget ocw; Atom encoding; int format; int length; XtPointer text; int nchars; { OCCPreeditDrawArg arg; if (ocw->onthespot.statusdrawcallback == NULL || XtHasCallbacks((Widget)ocw, XtNstatusDrawCallback) != XtCallbackHasSome) { /* no callback */ return; } TRACE(("OnTheSpot:CBStatusDraw()\n")); arg.caret = 0; /* ignored */ arg.chg_first = 0; /* ignored */ arg.chg_length = 0; /* ignored */ arg.encoding = encoding; arg.format = format; arg.text_length = length; arg.text = text; arg.attrs_length = nchars; arg.attrs = NULL; /* ignored */ XtCallCallbackList((Widget)ocw, ocw->onthespot.statusdrawcallback, (XtPointer)&arg); }