Mercurial > kinput2.yaz
diff lib/AuxPanel.c @ 0:92745d501b9a
initial import from kinput2-v3.1
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Mon, 08 Mar 2010 04:44:30 +0900 |
parents | |
children | 89750191b165 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/AuxPanel.c Mon Mar 08 04:44:30 2010 +0900 @@ -0,0 +1,606 @@ +#ifndef lint +static char *rcsid = "$Id: AuxPanel.c,v 1.23 1994/09/01 06:33:41 ishisone Exp $"; +#endif +/* + * Copyright (c) 1990 Software Research Associates, Inc. + * + * 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 + */ + +/* Copyright 1991 NEC Corporation, Tokyo, Japan. + * + * 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 NEC Corporation + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. NEC + * Corporation makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * NEC CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NEC CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Author: Akira Kon, NEC Corporation. (kon@d1.bs2.mt.nec.co.jp) + */ + +/* + $BLdBjE@(B + $B!&J8;zIA2h$,A4It=q$-D>$7=hM}$K$J$C$F$$$k!#(B + $B!&$@$l$b(B Destroy $B$r8F$s$G$/$l$J$$$N$G$A$g$C$H$4$_$,;D$k!#(B + */ + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#if XtSpecificationRelease > 4 +#include <X11/Xfuncs.h> +#endif +#include "AuxPanelP.h" +#include "ConvDisp.h" +#include "WStr.h" + +#define DEBUG_VAR debug_AuxPanel +#include "DebugPrint.h" + +static XtResource resources[] = { +#define offset(field) XtOffset(AuxPanelWidget, cpanel.field) + { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), + offset(foreground), XtRString, XtDefaultForeground }, + { XtNhorizontalSpacing, XtCSpacing, XtRDimension, sizeof(Dimension), + offset(hspace), XtRString, "6" }, + { XtNverticalSpacing, XtCSpacing, XtRDimension, sizeof(Dimension), + offset(vspace), XtRString, "4" }, + { XtNdefaultWidth, XtCDefaultWidth, XtRDimension, sizeof(Dimension), + offset(defaultwidth), XtRString, "400" }, + { XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor), + offset(cursor), XtRImmediate, (XtPointer)None }, + { XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), + offset(callback), XtRCallback, NULL }, +#undef offset +}; + +static void Initialize(), Destroy(); +static void Realize(); +static void Redisplay(); +static void Resize(); +static Boolean SetValues(); +static XtGeometryResult QueryGeometry(); +static void InsertChild(); + +static void GetInvGC(); +static void ComputeSize(); +static void Layout(); + +static void freeDisplaySegments(); +static void UpdateAuxDisplay(); + +static CompositeClassExtensionRec CompositeExtension = { + /* next_extension */ NULL, + /* record_type */ NULLQUARK, + /* version */ XtCompositeExtensionVersion, + /* record_size */ sizeof(CompositeClassExtensionRec), + /* accept_objects */ True, +}; + +AuxPanelClassRec auxPanelClassRec = { + { /* core fields */ + /* superclass */ (WidgetClass) &compositeClassRec, + /* class_name */ "AuxPanel", + /* widget_size */ sizeof(AuxPanelRec), + /* class_initialize */ NULL, + /* class_part_initialize */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ Realize, + /* 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 */ Resize, + /* expose */ Redisplay, + /* 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 */ NULL, + /* query_geometry */ QueryGeometry, + /* display_accelerator */ XtInheritDisplayAccelerator, + /* extension */ NULL + }, + { /* composite fields */ + /* geometry_manager */ NULL, + /* change_managed */ NULL, + /* insert_child */ InsertChild, + /* delete_child */ XtInheritDeleteChild, + /* extension */ (XtPointer)&CompositeExtension, + }, + { /* auxpanel fields */ + /* empty */ 0 + } +}; + +WidgetClass auxPanelWidgetClass = (WidgetClass)&auxPanelClassRec; + +/* ARGSUSED */ +static void +Initialize(req, new, args, num_args) +Widget req; +Widget new; +ArgList args; +Cardinal *num_args; +{ + AuxPanelWidget cpw = (AuxPanelWidget)new; + + TRACE(("AuxPanel:Initialize()\n")); + + cpw->cpanel.displayobj = NULL; + cpw->cpanel.dispauxsegments = NULL; + cpw->cpanel.dispauxsegmentsize = 0; + cpw->cpanel.numauxsegments = 0; + GetInvGC(cpw); +} + +static void +Destroy(w) +Widget w; +{ + AuxPanelWidget cpw = (AuxPanelWidget)w; + + TRACE(("AuxPanel:Destroy()\n")); + + freeDisplaySegments(cpw); + if (cpw->cpanel.invgc != NULL) XtReleaseGC(w, cpw->cpanel.invgc); +} + +static void +Realize(w, mask, value) +Widget w; +XtValueMask *mask; +XSetWindowAttributes *value; +{ + AuxPanelWidget cpw = (AuxPanelWidget)w; + CompositeWidgetClass super = (CompositeWidgetClass)XtClass(w)->core_class.superclass; + String params[1]; + Cardinal num_params; + + TRACE(("AuxPanel:Realize()\n")); + + if (cpw->cpanel.displayobj == NULL) { + params[0] = XtClass(w)->core_class.class_name; + num_params = 1; + XtAppErrorMsg(XtWidgetToApplicationContext(w), + "childError", "number", "WidgetError", + "%s: has no child (ConvDisplayObject)", + params, &num_params); + } + + if (cpw->cpanel.cursor != None) { + *mask |= CWCursor; + value->cursor = cpw->cpanel.cursor; + } + + (*super->core_class.realize)(w, mask, value); +} + +/* ARGSUSED */ +static void +Redisplay(w, ev, region) +Widget w; +XEvent *ev; +Region region; +{ + AuxPanelWidget cpw = (AuxPanelWidget)w; + XExposeEvent *event = (XExposeEvent *)ev; + DisplaySegment *dseg; + int cheight, hspace, vspace; + int x, i; + + TRACE(("AuxPanel:Redisplay()\n")); + + cheight = cpw->cpanel.fontheight; + hspace = cpw->cpanel.hspace; + vspace = cpw->cpanel.vspace; + + if (event->y + event->height < vspace / 2 + || cheight + vspace / 2 < event->y) + return; + + for (i = 0, x = hspace / 2, dseg = cpw->cpanel.dispauxsegments; + i < cpw->cpanel.numauxsegments ; i++, dseg++) { + if (x < event->x + event->width && event->x < x + dseg->width) { + dseg->redrawpos = 0; + } + else { + dseg->redrawpos = -1; /* $B=q$-D>$9I,MW$,$J$$(B */ + } + x += dseg->width; + } + + UpdateAuxDisplay(cpw); +} + +static void +Resize(w) +Widget w; +{ + AuxPanelWidget cpw = (AuxPanelWidget)w; + + TRACE(("AuxPanel:Resize()\n")); + + Layout(cpw, True, True); +} + +/* ARGSUSED */ +static Boolean +SetValues(cur, req, wid, args, num_args) +Widget cur; +Widget req; +Widget wid; +ArgList args; +Cardinal *num_args; +{ + AuxPanelWidget old = (AuxPanelWidget)cur; + AuxPanelWidget new = (AuxPanelWidget)wid; + Boolean redisplay = False; + + TRACE(("AuxPanel:SetValues()\n")); + + if (new->cpanel.displayobj == NULL) return False; + + if (new->cpanel.foreground != old->cpanel.foreground || + new->core.background_pixel != old->core.background_pixel) { + XtVaSetValues(new->cpanel.displayobj, + XtNforeground, new->cpanel.foreground, + XtNbackground, new->core.background_pixel, + NULL); + redisplay = True; + } + + if (new->cpanel.numauxsegments > 0 || + new->cpanel.hspace != old->cpanel.hspace || + new->cpanel.vspace != old->cpanel.vspace || + new->cpanel.defaultwidth != old->cpanel.defaultwidth) { + Layout(new, True, True); + redisplay = True; + } + + if (new->cpanel.cursor != old->cpanel.cursor && XtIsRealized(wid)) { + XDefineCursor(XtDisplay(wid), XtWindow(wid), new->cpanel.cursor); + } + + return redisplay; +} + +static XtGeometryResult +QueryGeometry(w, req, ret) +Widget w; +XtWidgetGeometry *req; +XtWidgetGeometry *ret; +{ + Dimension width, height; + Dimension owidth, oheight; + + TRACE(("AuxPanel:QueryGeometry()\n")); + + ret->request_mode = 0; + + if ((req->request_mode & (CWWidth | CWHeight)) == 0) return XtGeometryYes; + + width = (req->request_mode & CWWidth) ? req->width : w->core.width; + height = (req->request_mode & CWHeight) ? req->height : w->core.height; + + owidth = width; + oheight = height; + ComputeSize((AuxPanelWidget)w, + (req->request_mode & CWWidth) != 0, + (req->request_mode & CWHeight) != 0, + &width, &height); + ret->request_mode = CWWidth | CWHeight; + ret->width = width; + ret->height = height; + + if (width != owidth || height != oheight) return XtGeometryAlmost; + + return XtGeometryYes; +} + +static void +InsertChild(w) +Widget w; +{ + AuxPanelWidget cpw = (AuxPanelWidget)XtParent(w); + CompositeWidgetClass super = (CompositeWidgetClass)XtClass(cpw)->core_class.superclass; + String params[1]; + Cardinal num_params; + + TRACE(("AuxPanel:InsertChild()\n")); + + if (!XtIsSubclass(w, convDisplayObjectClass)) { + params[0] = XtClass(cpw)->core_class.class_name; + num_params = 1; + XtAppErrorMsg(XtWidgetToApplicationContext(w), + "childError", "class", "WidgetError", + "%s: child must be subclass of ConvDisplayObject", + params, &num_params); + } + if (cpw->composite.num_children != 0) { + params[0] = XtClass(cpw)->core_class.class_name; + num_params = 1; + XtAppErrorMsg(XtWidgetToApplicationContext(w), + "childError", "number", "WidgetError", + "%s: can only take one child", + params, &num_params); + } + + (*super->composite_class.insert_child)(w); + + cpw->cpanel.displayobj = w; + cpw->cpanel.fontheight = CDLineHeight(w, (Position *)NULL); + +#ifdef notdef + { + Pixel fg, bg; + XtVaGetValues(w, XtNforeground, &fg, XtNbackground, &bg, NULL); + GetInvGC(cpw, fg, bg); + } +#endif + + if (cpw->cpanel.numauxsegments > 0) { + Layout(cpw, cpw->core.width == 0, cpw->core.height == 0); + } +} + +static void +GetInvGC(cpw) +AuxPanelWidget cpw; +{ + XGCValues values; + + TRACE(("AuxPanel:GetInvGC()\n")); + + values.function = GXinvert; + values.plane_mask = cpw->cpanel.foreground ^ cpw->core.background_pixel; + cpw->cpanel.invgc = XtGetGC((Widget)cpw, GCFunction|GCPlaneMask, &values); +} + +/* ARGSUSED */ +static void +ComputeSize(cpw, resizex, resizey, width_inout, height_inout) +AuxPanelWidget cpw; +int resizex; +int resizey; +Dimension *width_inout; +Dimension *height_inout; +{ + int width, height; + int i, minwidth = 0; + DisplaySegment *dseg = cpw->cpanel.dispauxsegments; + + + TRACE(("AuxPanel:ComputeSize()\n")); + + if (cpw->cpanel.displayobj == NULL) return; + + width = *width_inout; + height = *height_inout; + + for (i = 0 ; i < cpw->cpanel.numauxsegments ; i++, dseg++) { + minwidth += CDStringWidth(cpw->cpanel.displayobj, &dseg->seg, 0, -1); + } + minwidth += cpw->cpanel.hspace * 2; + if (resizex) { + width = minwidth; + } else { + width = (cpw->core.width < minwidth) ? minwidth : cpw->core.width; + } + height = cpw->cpanel.fontheight + cpw->cpanel.vspace; + *width_inout = width; + *height_inout = height; +} + +static void +Layout(cpw, resizex, resizey) +AuxPanelWidget cpw; +int resizex; +int resizey; +{ + Dimension width, height; + Dimension owidth, oheight; + XtGeometryResult re; + + TRACE(("AuxPanel:Layout()\n")); + + if (cpw->cpanel.displayobj == NULL) return; + + width = cpw->core.width; + height = cpw->core.height; + ComputeSize(cpw, resizex, resizey, &width, &height); + if (width != cpw->core.width || height != cpw->core.height) { + owidth = width; + oheight = height; + re = XtMakeResizeRequest((Widget)cpw, owidth, oheight, + &width, &height); + switch (re) { + case XtGeometryYes: + /* no problem */ + break; + } + } +} + +/*- allocDisplaySegments: prepare specified number of display segments -*/ +static void +allocDisplaySegments(cpw, n) +AuxPanelWidget cpw; +Cardinal n; +{ + if (cpw->cpanel.dispauxsegmentsize > n) return; + n = ((n + 3) / 4) * 4 ; + if (cpw->cpanel.dispauxsegments == NULL) { + cpw->cpanel.dispauxsegments = + (DisplaySegment *)XtCalloc(n, sizeof(DisplaySegment)); + } else { + cpw->cpanel.dispauxsegments = + (DisplaySegment *)XtRealloc((char *)cpw->cpanel.dispauxsegments, + n * sizeof(DisplaySegment)); + bzero((char *)(cpw->cpanel.dispauxsegments + cpw->cpanel.numauxsegments), + (n - cpw->cpanel.numauxsegments) * sizeof(DisplaySegment)); + } + cpw->cpanel.dispauxsegmentsize = n; +} + +/*- freeDisplaySegments: free display segments -*/ +static void +freeDisplaySegments(cpw) +AuxPanelWidget cpw; +{ + Cardinal i; + DisplaySegment *dseg = cpw->cpanel.dispauxsegments; + + for (i = 0 ; i < cpw->cpanel.dispauxsegmentsize ; i++, dseg++) { + if (dseg->seg.data != NULL) XtFree(dseg->seg.data); + } + XtFree((char *)cpw->cpanel.dispauxsegments); + cpw->cpanel.dispauxsegments = (DisplaySegment *)0; + cpw->cpanel.dispauxsegmentsize = 0; +} + +/*- copyString: copy ICString -*/ +static void +copyString(from, to) +ICString *from; +ICString *to; +{ + if (to->data != NULL) XtFree(to->data); + *to = *from; + to->data = XtMalloc(to->nbytes); + (void)bcopy(from->data, to->data, to->nbytes); +} + +static void +UpdateAuxDisplay(cpw) +AuxPanelWidget cpw; +{ + Widget dispobj = cpw->cpanel.displayobj; + DisplaySegment *dseg; + int hspace, vspace; + int x, y; + Cardinal i; + + if (dispobj == NULL) return; + + hspace = cpw->cpanel.hspace; + vspace = cpw->cpanel.vspace; + + x = hspace / 2; + y = vspace / 2; + + for (i = 0, dseg = cpw->cpanel.dispauxsegments; + i < cpw->cpanel.numauxsegments ; i++, dseg++) { + if (dseg->redrawpos >= 0) { + int offset = 0; + int idx = dseg->redrawpos; + + if (dseg->width == 0) { + dseg->width = CDStringWidth(dispobj, &dseg->seg, 0, -1); + } + if (idx > 0) { + offset = CDStringWidth(dispobj, &dseg->seg, 0, idx); + } + CDDrawString(dispobj, (Widget)cpw, &dseg->seg, 0, -1, x + offset, y); + } + x += dseg->width; + } + return; +} + +/* + * Public Functions + */ + +/* ARGSUSED */ +void +APanelStart(w, segments, nseg, curseg, cursorpos) +Widget w; +ICString *segments; +Cardinal nseg, curseg, cursorpos; +{ + AuxPanelWidget cpw = (AuxPanelWidget)w; + Cardinal i; + DisplaySegment *dseg; + + cpw->cpanel.numauxsegments = nseg; + allocDisplaySegments(cpw, nseg); + for (i = 0, dseg = cpw->cpanel.dispauxsegments ; i < nseg ; i++, dseg++) { + copyString(segments +i, &dseg->seg); + dseg->redrawpos = 0; + dseg->width = 0; + } + Layout(cpw, True, True); + if (XtIsRealized(w)) XClearWindow(XtDisplay(w), XtWindow(w)); + return; +} + +void +APanelEnd(w) +Widget w; +{ + AuxPanelWidget cpw = (AuxPanelWidget)w; + + cpw->cpanel.numauxsegments = 0; + return; +} + +/* ARGSUSED */ +void +APanelChange(w, segments, nseg, curseg, cursorpos) +Widget w; +ICString *segments; +Cardinal nseg, curseg, cursorpos; +{ + AuxPanelWidget cpw = (AuxPanelWidget)w; + Cardinal i; + DisplaySegment *dseg; + + cpw->cpanel.numauxsegments = nseg; + allocDisplaySegments(cpw, nseg); + for (i = 0, dseg = cpw->cpanel.dispauxsegments ; i < nseg ; i++, dseg++) { + /* $BA4=q$-49$($K$J$C$F$7$^$&!#(BICCompareSegment $B$,;H$($k$J$i(B + $B;H$$$?$$$N$@$,!#(B */ + copyString(segments +i, &dseg->seg); + dseg->redrawpos = 0; + dseg->width = 0; + } + Layout(cpw, False, False); + if (XtIsRealized(w)) XClearWindow(XtDisplay(w), XtWindow(w)); + UpdateAuxDisplay(cpw); + return; +}