diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/AllWidgets.c | 124 | ||||
-rw-r--r-- | src/AllWidgets.h | 37 | ||||
-rw-r--r-- | src/AsciiSink.c | 693 | ||||
-rw-r--r-- | src/AsciiSink.h | 91 | ||||
-rw-r--r-- | src/AsciiSinkP.h | 118 | ||||
-rw-r--r-- | src/AsciiSrc.c | 1438 | ||||
-rw-r--r-- | src/AsciiSrc.h | 162 | ||||
-rw-r--r-- | src/AsciiSrcP.h | 163 | ||||
-rw-r--r-- | src/AsciiText.c | 347 | ||||
-rw-r--r-- | src/AsciiText.h | 151 | ||||
-rw-r--r-- | src/AsciiTextP.h | 166 | ||||
-rw-r--r-- | src/Box.c | 622 | ||||
-rw-r--r-- | src/Box.h | 98 | ||||
-rw-r--r-- | src/BoxP.h | 108 | ||||
-rw-r--r-- | src/Cardinals.h | 44 | ||||
-rw-r--r-- | src/Command.c | 629 | ||||
-rw-r--r-- | src/Command.h | 118 | ||||
-rw-r--r-- | src/CommandP.h | 143 | ||||
-rw-r--r-- | src/Dialog.c | 448 | ||||
-rw-r--r-- | src/Dialog.h | 109 | ||||
-rw-r--r-- | src/DialogP.h | 98 | ||||
-rw-r--r-- | src/Form.c | 848 | ||||
-rw-r--r-- | src/Form.h | 168 | ||||
-rw-r--r-- | src/FormP.h | 143 | ||||
-rw-r--r-- | src/Grip.c | 150 | ||||
-rw-r--r-- | src/Grip.h | 105 | ||||
-rw-r--r-- | src/GripP.h | 105 | ||||
-rw-r--r-- | src/Imakefile | 157 | ||||
-rw-r--r-- | src/Imakefrag.X11R5 | 33 | ||||
-rw-r--r-- | src/Label.c | 871 | ||||
-rw-r--r-- | src/Label.h | 131 | ||||
-rw-r--r-- | src/LabelP.h | 137 | ||||
-rw-r--r-- | src/Layout.c | 1049 | ||||
-rw-r--r-- | src/Layout.h | 94 | ||||
-rw-r--r-- | src/LayoutP.h | 232 | ||||
-rw-r--r-- | src/List.c | 1230 | ||||
-rw-r--r-- | src/List.h | 239 | ||||
-rw-r--r-- | src/ListP.h | 119 | ||||
-rw-r--r-- | src/MenuButtoP.h | 102 | ||||
-rw-r--r-- | src/MenuButton.c | 221 | ||||
-rw-r--r-- | src/MenuButton.h | 90 | ||||
-rw-r--r-- | src/MultiSink.c | 780 | ||||
-rw-r--r-- | src/MultiSink.h | 118 | ||||
-rw-r--r-- | src/MultiSinkP.h | 157 | ||||
-rw-r--r-- | src/MultiSrc.c | 1461 | ||||
-rw-r--r-- | src/MultiSrc.h | 151 | ||||
-rw-r--r-- | src/MultiSrcP.h | 194 | ||||
-rw-r--r-- | src/Paned.c | 1947 | ||||
-rw-r--r-- | src/Paned.h | 256 | ||||
-rw-r--r-- | src/PanedP.h | 193 | ||||
-rw-r--r-- | src/Panner.c | 975 | ||||
-rw-r--r-- | src/Panner.h | 108 | ||||
-rw-r--r-- | src/PannerP.h | 104 | ||||
-rw-r--r-- | src/Porthole.c | 366 | ||||
-rw-r--r-- | src/Porthole.h | 64 | ||||
-rw-r--r-- | src/PortholeP.h | 65 | ||||
-rw-r--r-- | src/README.XAW3D | 544 | ||||
-rw-r--r-- | src/Repeater.c | 278 | ||||
-rw-r--r-- | src/Repeater.h | 77 | ||||
-rw-r--r-- | src/RepeaterP.h | 82 | ||||
-rw-r--r-- | src/Reports.h | 55 | ||||
-rw-r--r-- | src/Scrollbar.c | 1169 | ||||
-rw-r--r-- | src/Scrollbar.h | 146 | ||||
-rw-r--r-- | src/ScrollbarP.h | 122 | ||||
-rw-r--r-- | src/Simple.c | 299 | ||||
-rw-r--r-- | src/Simple.h | 105 | ||||
-rw-r--r-- | src/SimpleMenP.h | 113 | ||||
-rw-r--r-- | src/SimpleMenu.c | 1673 | ||||
-rw-r--r-- | src/SimpleMenu.h | 159 | ||||
-rw-r--r-- | src/SimpleP.h | 89 | ||||
-rw-r--r-- | src/Sme.c | 246 | ||||
-rw-r--r-- | src/Sme.h | 81 | ||||
-rw-r--r-- | src/SmeBSB.c | 877 | ||||
-rw-r--r-- | src/SmeBSB.h | 111 | ||||
-rw-r--r-- | src/SmeBSBP.h | 120 | ||||
-rw-r--r-- | src/SmeLine.c | 294 | ||||
-rw-r--r-- | src/SmeLine.h | 79 | ||||
-rw-r--r-- | src/SmeLineP.h | 97 | ||||
-rw-r--r-- | src/SmeP.h | 107 | ||||
-rw-r--r-- | src/SmeThreeD.c | 596 | ||||
-rw-r--r-- | src/SmeThreeD.h | 96 | ||||
-rw-r--r-- | src/SmeThreeDP.h | 82 | ||||
-rw-r--r-- | src/StripCharP.h | 109 | ||||
-rw-r--r-- | src/StripChart.c | 556 | ||||
-rw-r--r-- | src/StripChart.h | 118 | ||||
-rw-r--r-- | src/Template.c | 94 | ||||
-rw-r--r-- | src/Template.h | 71 | ||||
-rw-r--r-- | src/TemplateP.h | 64 | ||||
-rw-r--r-- | src/Text.c | 3600 | ||||
-rw-r--r-- | src/Text.h | 310 | ||||
-rw-r--r-- | src/TextAction.c | 2327 | ||||
-rw-r--r-- | src/TextP.h | 290 | ||||
-rw-r--r-- | src/TextPop.c | 1434 | ||||
-rw-r--r-- | src/TextSink.c | 779 | ||||
-rw-r--r-- | src/TextSink.h | 317 | ||||
-rw-r--r-- | src/TextSinkP.h | 143 | ||||
-rw-r--r-- | src/TextSrc.c | 676 | ||||
-rw-r--r-- | src/TextSrc.h | 237 | ||||
-rw-r--r-- | src/TextSrcP.h | 164 | ||||
-rw-r--r-- | src/TextTr.c | 147 | ||||
-rw-r--r-- | src/ThreeD.c | 839 | ||||
-rw-r--r-- | src/ThreeD.h | 119 | ||||
-rw-r--r-- | src/ThreeDP.h | 77 | ||||
-rw-r--r-- | src/Tip.c | 718 | ||||
-rw-r--r-- | src/Tip.h | 135 | ||||
-rw-r--r-- | src/TipP.h | 76 | ||||
-rw-r--r-- | src/Toggle.c | 619 | ||||
-rw-r--r-- | src/Toggle.h | 177 | ||||
-rw-r--r-- | src/ToggleP.h | 113 | ||||
-rw-r--r-- | src/Tree.c | 1008 | ||||
-rw-r--r-- | src/Tree.h | 125 | ||||
-rw-r--r-- | src/TreeP.h | 132 | ||||
-rw-r--r-- | src/Vendor.c | 604 | ||||
-rw-r--r-- | src/VendorEP.h | 81 | ||||
-rw-r--r-- | src/Viewport.c | 1200 | ||||
-rw-r--r-- | src/Viewport.h | 124 | ||||
-rw-r--r-- | src/ViewportP.h | 108 | ||||
-rw-r--r-- | src/Xaw3dP.c | 212 | ||||
-rw-r--r-- | src/Xaw3dP.h.sed | 83 | ||||
-rw-r--r-- | src/XawI18n.c | 88 | ||||
-rw-r--r-- | src/XawI18n.h | 78 | ||||
-rw-r--r-- | src/XawIm.c | 1716 | ||||
-rw-r--r-- | src/XawImP.h | 240 | ||||
-rw-r--r-- | src/XawInit.c | 49 | ||||
-rw-r--r-- | src/XawInit.h | 31 | ||||
-rw-r--r-- | src/laygram.y | 263 | ||||
-rw-r--r-- | src/laylex.l | 127 | ||||
-rw-r--r-- | src/sharedlib.c | 192 |
128 files changed, 47537 insertions, 0 deletions
diff --git a/src/AllWidgets.c b/src/AllWidgets.c new file mode 100644 index 0000000..0dc7e16 --- /dev/null +++ b/src/AllWidgets.c @@ -0,0 +1,124 @@ +/* $XConsortium: AllWidgets.c,v 1.8 94/04/17 20:11:39 kaleb Exp $ */ + +/* + +Copyright (c) 1991, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +#include <X11/IntrinsicP.h> +#include <X11/Xmu/WidgetNode.h> + +extern WidgetClass applicationShellWidgetClass; +extern WidgetClass asciiSinkObjectClass; +extern WidgetClass asciiSrcObjectClass; +extern WidgetClass asciiTextWidgetClass; +extern WidgetClass boxWidgetClass; +extern WidgetClass commandWidgetClass; +extern WidgetClass compositeWidgetClass; +extern WidgetClass constraintWidgetClass; +extern WidgetClass coreWidgetClass; +extern WidgetClass dialogWidgetClass; +extern WidgetClass formWidgetClass; +extern WidgetClass gripWidgetClass; +extern WidgetClass labelWidgetClass; +extern WidgetClass layoutWidgetClass; +extern WidgetClass listWidgetClass; +extern WidgetClass menuButtonWidgetClass; +extern WidgetClass objectClass; +extern WidgetClass overrideShellWidgetClass; +extern WidgetClass panedWidgetClass; +extern WidgetClass pannerWidgetClass; +extern WidgetClass portholeWidgetClass; +extern WidgetClass rectObjClass; +extern WidgetClass repeaterWidgetClass; +extern WidgetClass scrollbarWidgetClass; +extern WidgetClass shellWidgetClass; +extern WidgetClass simpleMenuWidgetClass; +extern WidgetClass simpleWidgetClass; +extern WidgetClass smeBSBObjectClass; +extern WidgetClass smeLineObjectClass; +extern WidgetClass smeObjectClass; +extern WidgetClass smeThreeDObjectClass; +extern WidgetClass stripChartWidgetClass; +extern WidgetClass textSinkObjectClass; +extern WidgetClass textSrcObjectClass; +extern WidgetClass textWidgetClass; +extern WidgetClass threeDWidgetClass; +extern WidgetClass toggleWidgetClass; +extern WidgetClass topLevelShellWidgetClass; +extern WidgetClass transientShellWidgetClass; +extern WidgetClass treeWidgetClass; +extern WidgetClass vendorShellWidgetClass; +extern WidgetClass viewportWidgetClass; +extern WidgetClass wmShellWidgetClass; + +XmuWidgetNode XawWidgetArray[] = { +{ "applicationShell", &applicationShellWidgetClass }, +{ "asciiSink", &asciiSinkObjectClass }, +{ "asciiSrc", &asciiSrcObjectClass }, +{ "asciiText", &asciiTextWidgetClass }, +{ "box", &boxWidgetClass }, +{ "command", &commandWidgetClass }, +{ "composite", &compositeWidgetClass }, +{ "constraint", &constraintWidgetClass }, +{ "core", &coreWidgetClass }, +{ "dialog", &dialogWidgetClass }, +{ "form", &formWidgetClass }, +{ "grip", &gripWidgetClass }, +{ "label", &labelWidgetClass }, +{ "layout", &layoutWidgetClass }, +{ "list", &listWidgetClass }, +{ "menuButton", &menuButtonWidgetClass }, +{ "object", &objectClass }, +{ "overrideShell", &overrideShellWidgetClass }, +{ "paned", &panedWidgetClass }, +{ "panner", &pannerWidgetClass }, +{ "porthole", &portholeWidgetClass }, +{ "rect", &rectObjClass }, +{ "repeater", &repeaterWidgetClass }, +{ "scrollbar", &scrollbarWidgetClass }, +{ "shell", &shellWidgetClass }, +{ "simpleMenu", &simpleMenuWidgetClass }, +{ "simple", &simpleWidgetClass }, +{ "smeBSB", &smeBSBObjectClass }, +{ "smeLine", &smeLineObjectClass }, +{ "smeThreeD", &smeThreeDObjectClass }, +{ "sme", &smeObjectClass }, +{ "stripChart", &stripChartWidgetClass }, +{ "textSink", &textSinkObjectClass }, +{ "textSrc", &textSrcObjectClass }, +{ "text", &textWidgetClass }, +{ "threeD", &threeDWidgetClass }, +{ "toggle", &toggleWidgetClass }, +{ "topLevelShell", &topLevelShellWidgetClass }, +{ "transientShell", &transientShellWidgetClass }, +{ "tree", &treeWidgetClass }, +{ "vendorShell", &vendorShellWidgetClass }, +{ "viewport", &viewportWidgetClass }, +{ "wmShell", &wmShellWidgetClass }, +}; + +int XawWidgetCount = XtNumber(XawWidgetArray); + diff --git a/src/AllWidgets.h b/src/AllWidgets.h new file mode 100644 index 0000000..c71aa91 --- /dev/null +++ b/src/AllWidgets.h @@ -0,0 +1,37 @@ +/* + * $XConsortium: AllWidgets.h,v 1.3 94/04/17 20:11:40 jim Exp $ + * +Copyright (c) 1990 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + */ + +#ifndef _XawAllWidgets_h +#define _XawAllWidgets_h + +/* + * This file matches the generated AllWidgets.c + */ +extern XmuWidgetNode XawWidgetArray[]; +extern int XawWidgetCount; + +#endif /* _XawAllWidgets_h */ diff --git a/src/AsciiSink.c b/src/AsciiSink.c new file mode 100644 index 0000000..b427c80 --- /dev/null +++ b/src/AsciiSink.c @@ -0,0 +1,693 @@ +/* $XConsortium: AsciiSink.c,v 1.62 94/04/17 20:11:41 kaleb Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#include <stdio.h> + +#include <X11/Xatom.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/AsciiSinkP.h> +#include <X11/Xaw3d/AsciiSrcP.h> /* For source function defs. */ +#include <X11/Xaw3d/TextP.h> /* I also reach into the text widget. */ + +#ifdef GETLASTPOS +#undef GETLASTPOS /* We will use our own GETLASTPOS. */ +#endif + +#define GETLASTPOS XawTextSourceScan(source, (XawTextPosition) 0, XawstAll, XawsdRight, 1, TRUE) + +static void Initialize(), Destroy(); +static Boolean SetValues(); +static int MaxLines(), MaxHeight(); +static void SetTabs(); + +static void DisplayText(), InsertCursor(), FindPosition(); +static void FindDistance(), Resolve(), GetCursorBounds(); + +#define offset(field) XtOffsetOf(AsciiSinkRec, ascii_sink.field) + +static XtResource resources[] = { + {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *), + offset(font), XtRString, XtDefaultFont}, + {XtNecho, XtCOutput, XtRBoolean, sizeof(Boolean), + offset(echo), XtRImmediate, (XtPointer) True}, + {XtNdisplayNonprinting, XtCOutput, XtRBoolean, sizeof(Boolean), + offset(display_nonprinting), XtRImmediate, (XtPointer) True}, +}; +#undef offset + +#define SuperClass (&textSinkClassRec) +AsciiSinkClassRec asciiSinkClassRec = { + { +/* core_class fields */ + /* superclass */ (WidgetClass) SuperClass, + /* class_name */ "AsciiSink", + /* widget_size */ sizeof(AsciiSinkRec), + /* class_initialize */ XawInitializeWidgetSet, + /* class_part_initialize */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* obj1 */ NULL, + /* obj2 */ NULL, + /* obj3 */ 0, + /* resources */ resources, + /* num_resources */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* obj4 */ FALSE, + /* obj5 */ FALSE, + /* obj6 */ FALSE, + /* obj7 */ FALSE, + /* destroy */ Destroy, + /* obj8 */ NULL, + /* obj9 */ NULL, + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* obj10 */ NULL, + /* get_values_hook */ NULL, + /* obj11 */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* obj12 */ NULL, + /* obj13 */ NULL, + /* obj14 */ NULL, + /* extension */ NULL + }, +/* text_sink_class fields */ + { + /* DisplayText */ DisplayText, + /* InsertCursor */ InsertCursor, + /* ClearToBackground */ XtInheritClearToBackground, + /* FindPosition */ FindPosition, + /* FindDistance */ FindDistance, + /* Resolve */ Resolve, + /* MaxLines */ MaxLines, + /* MaxHeight */ MaxHeight, + /* SetTabs */ SetTabs, + /* GetCursorBounds */ GetCursorBounds + }, +/* ascii_sink_class fields */ + { + /* unused */ 0 + } +}; + +WidgetClass asciiSinkObjectClass = (WidgetClass)&asciiSinkClassRec; + +/* Utilities */ + +static int +CharWidth (w, x, c) +Widget w; +int x; +unsigned char c; +{ + int i, width, nonPrinting; + AsciiSinkObject sink = (AsciiSinkObject) w; + XFontStruct *font = sink->ascii_sink.font; + Position *tab; + + if ( c == XawLF ) return(0); + + if (c == XawTAB) { + /* Adjust for Left Margin. */ + x -= ((TextWidget) XtParent(w))->text.margin.left; + + if (x >= (int)XtParent(w)->core.width) return 0; + for (i = 0, tab = sink->text_sink.tabs ; + i < sink->text_sink.tab_count ; i++, tab++) { + if (x < *tab) { + if (*tab < (int)XtParent(w)->core.width) + return *tab - x; + else + return 0; + } + } + return 0; + } + + if ( (nonPrinting = (c < (unsigned char) XawSP)) ) + if (sink->ascii_sink.display_nonprinting) + c += '@'; + else { + c = XawSP; + nonPrinting = False; + } + + if (font->per_char && + (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2)) + width = font->per_char[c - font->min_char_or_byte2].width; + else + width = font->min_bounds.width; + + if (nonPrinting) + width += CharWidth(w, x, (unsigned char) '^'); + + return width; +} + +/* Function Name: PaintText + * Description: Actually paints the text into the windoe. + * Arguments: w - the text widget. + * gc - gc to paint text with. + * x, y - location to paint the text. + * buf, len - buffer and length of text to paint. + * Returns: the width of the text painted, or 0. + * + * NOTE: If this string attempts to paint past the end of the window + * then this function will return zero. + */ + +static Dimension +PaintText(w, gc, x, y, buf, len) +Widget w; +GC gc; +Position x, y; +unsigned char * buf; +int len; +{ + AsciiSinkObject sink = (AsciiSinkObject) w; + TextWidget ctx = (TextWidget) XtParent(w); + + Position max_x; + Dimension width = XTextWidth(sink->ascii_sink.font, (char *) buf, len); + max_x = (Position) ctx->core.width; + + if ( ((int) width) <= -x) /* Don't draw if we can't see it. */ + return(width); + + XDrawImageString(XtDisplay(ctx), XtWindow(ctx), gc, + (int) x, (int) y, (char *) buf, len); + if ( (((Position) width + x) > max_x) && (ctx->text.margin.right != 0) ) { + x = ctx->core.width - ctx->text.margin.right; + width = ctx->text.margin.right; + XFillRectangle(XtDisplay((Widget) ctx), XtWindow( (Widget) ctx), + sink->ascii_sink.normgc, (int) x, + (int) y - sink->ascii_sink.font->ascent, + (unsigned int) width, + (unsigned int) (sink->ascii_sink.font->ascent + + sink->ascii_sink.font->descent)); + return(0); + } + return(width); +} + +/* Sink Object Functions */ + +/* + * This function does not know about drawing more than one line of text. + */ + +static void +DisplayText(w, x, y, pos1, pos2, highlight) +Widget w; +Position x, y; +Boolean highlight; +XawTextPosition pos1, pos2; +{ + AsciiSinkObject sink = (AsciiSinkObject) w; + Widget source = XawTextGetSource(XtParent(w)); + unsigned char buf[BUFSIZ]; + + int j, k; + XawTextBlock blk; + GC gc = highlight ? sink->ascii_sink.invgc : sink->ascii_sink.normgc; + GC invgc = highlight ? sink->ascii_sink.normgc : sink->ascii_sink.invgc; + + if (!sink->ascii_sink.echo) return; + + y += sink->ascii_sink.font->ascent; + for ( j = 0 ; pos1 < pos2 ; ) { + pos1 = XawTextSourceRead(source, pos1, &blk, (int) pos2 - pos1); + for (k = 0; k < blk.length; k++) { + if (j >= BUFSIZ) { /* buffer full, dump the text. */ + x += PaintText(w, gc, x, y, buf, j); + j = 0; + } + buf[j] = blk.ptr[k]; + if (buf[j] == XawLF) /* line feeds ('\n') are not printed. */ + continue; + + else if (buf[j] == '\t') { + Position temp = 0; + Dimension width; + + if ((j != 0) && ((temp = PaintText(w, gc, x, y, buf, j)) == 0)) + return; + + x += temp; + width = CharWidth(w, x, (unsigned char) '\t'); + XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w), + invgc, (int) x, + (int) y - sink->ascii_sink.font->ascent, + (unsigned int) width, + (unsigned int) (sink->ascii_sink.font->ascent + + sink->ascii_sink.font->descent)); + x += width; + j = -1; + } + else if ( buf[j] < (unsigned char) ' ' ) { + if (sink->ascii_sink.display_nonprinting) { + buf[j + 1] = buf[j] + '@'; + buf[j] = '^'; + j++; + } + else + buf[j] = ' '; + } + j++; + } + } + if (j > 0) + (void) PaintText(w, gc, x, y, buf, j); +} + +#define insertCursor_width 6 +#define insertCursor_height 3 +static char insertCursor_bits[] = {0x0c, 0x1e, 0x33}; + +static Pixmap +CreateInsertCursor(s) +Screen *s; +{ + return (XCreateBitmapFromData (DisplayOfScreen(s), RootWindowOfScreen(s), + insertCursor_bits, insertCursor_width, insertCursor_height)); +} + +/* Function Name: GetCursorBounds + * Description: Returns the size and location of the cursor. + * Arguments: w - the text object. + * RETURNED rect - an X rectangle to return the cursor bounds in. + * Returns: none. + */ + +static void +GetCursorBounds(w, rect) +Widget w; +XRectangle * rect; +{ + AsciiSinkObject sink = (AsciiSinkObject) w; + + rect->width = (unsigned short) insertCursor_width; + rect->height = (unsigned short) insertCursor_height; + rect->x = sink->ascii_sink.cursor_x - (short) (rect->width / 2); + rect->y = sink->ascii_sink.cursor_y - (short) rect->height; +} + +/* + * The following procedure manages the "insert" cursor. + */ + +static void +InsertCursor (w, x, y, state) +Widget w; +Position x, y; +XawTextInsertState state; +{ + AsciiSinkObject sink = (AsciiSinkObject) w; + Widget text_widget = XtParent(w); + XRectangle rect; + + sink->ascii_sink.cursor_x = x; + sink->ascii_sink.cursor_y = y; + + GetCursorBounds(w, &rect); + if (state != sink->ascii_sink.laststate && XtIsRealized(text_widget)) + XCopyPlane(XtDisplay(text_widget), + sink->ascii_sink.insertCursorOn, + XtWindow(text_widget), sink->ascii_sink.xorgc, + 0, 0, (unsigned int) rect.width, (unsigned int) rect.height, + (int) rect.x, (int) rect.y, 1); + sink->ascii_sink.laststate = state; +} + +/* + * Given two positions, find the distance between them. + */ + +static void +FindDistance (w, fromPos, fromx, toPos, resWidth, resPos, resHeight) +Widget w; +XawTextPosition fromPos; /* First position. */ +int fromx; /* Horizontal location of first position. */ +XawTextPosition toPos; /* Second position. */ +int *resWidth; /* Distance between fromPos and resPos. */ +XawTextPosition *resPos; /* Actual second position used. */ +int *resHeight; /* Height required. */ +{ + AsciiSinkObject sink = (AsciiSinkObject) w; + Widget source = XawTextGetSource(XtParent(w)); + + XawTextPosition index, lastPos; + unsigned char c; + XawTextBlock blk; + + /* we may not need this */ + lastPos = GETLASTPOS; + XawTextSourceRead(source, fromPos, &blk, (int) toPos - fromPos); + *resWidth = 0; + for (index = fromPos; index != toPos && index < lastPos; index++) { + if (index - blk.firstPos >= blk.length) + XawTextSourceRead(source, index, &blk, (int) toPos - fromPos); + c = blk.ptr[index - blk.firstPos]; + *resWidth += CharWidth(w, fromx + *resWidth, c); + if (c == XawLF) { + index++; + break; + } + } + *resPos = index; + *resHeight = sink->ascii_sink.font->ascent +sink->ascii_sink.font->descent; +} + + +static void +FindPosition(w, fromPos, fromx, width, stopAtWordBreak, + resPos, resWidth, resHeight) +Widget w; +XawTextPosition fromPos; /* Starting position. */ +int fromx; /* Horizontal location of starting position.*/ +int width; /* Desired width. */ +int stopAtWordBreak; /* Whether the resulting position should be at + a word break. */ +XawTextPosition *resPos; /* Resulting position. */ +int *resWidth; /* Actual width used. */ +int *resHeight; /* Height required. */ +{ + AsciiSinkObject sink = (AsciiSinkObject) w; + Widget source = XawTextGetSource(XtParent(w)); + + XawTextPosition lastPos, index, whiteSpacePosition = 0; + int lastWidth = 0, whiteSpaceWidth = 0; + Boolean whiteSpaceSeen; + unsigned char c; + XawTextBlock blk; + + lastPos = GETLASTPOS; + + XawTextSourceRead(source, fromPos, &blk, BUFSIZ); + *resWidth = 0; + whiteSpaceSeen = FALSE; + c = 0; + for (index = fromPos; *resWidth <= width && index < lastPos; index++) { + lastWidth = *resWidth; + if (index - blk.firstPos >= blk.length) + XawTextSourceRead(source, index, &blk, BUFSIZ); + c = blk.ptr[index - blk.firstPos]; + *resWidth += CharWidth(w, fromx + *resWidth, c); + + if ((c == XawSP || c == XawTAB) && *resWidth <= width) { + whiteSpaceSeen = TRUE; + whiteSpacePosition = index; + whiteSpaceWidth = *resWidth; + } + if (c == XawLF) { + index++; + break; + } + } + if (*resWidth > width && index > fromPos) { + *resWidth = lastWidth; + index--; + if (stopAtWordBreak && whiteSpaceSeen) { + index = whiteSpacePosition + 1; + *resWidth = whiteSpaceWidth; + } + } + if (index == lastPos && c != XawLF) index = lastPos + 1; + *resPos = index; + *resHeight = sink->ascii_sink.font->ascent +sink->ascii_sink.font->descent; +} + +static void +Resolve (w, pos, fromx, width, leftPos, rightPos) +Widget w; +XawTextPosition pos; +int fromx, width; +XawTextPosition *leftPos, *rightPos; +{ + int resWidth, resHeight; + Widget source = XawTextGetSource(XtParent(w)); + + FindPosition(w, pos, fromx, width, FALSE, leftPos, &resWidth, &resHeight); + if (*leftPos > GETLASTPOS) + *leftPos = GETLASTPOS; + *rightPos = *leftPos; +} + +static void +GetGC(sink) +AsciiSinkObject sink; +{ + XtGCMask valuemask = (GCFont | + GCGraphicsExposures | GCForeground | GCBackground ); + XGCValues values; + + values.font = sink->ascii_sink.font->fid; + values.graphics_exposures = (Bool) FALSE; + + values.foreground = sink->text_sink.foreground; + values.background = sink->text_sink.background; + sink->ascii_sink.normgc = XtGetGC((Widget)sink, valuemask, &values); + + values.foreground = sink->text_sink.background; + values.background = sink->text_sink.foreground; + sink->ascii_sink.invgc = XtGetGC((Widget)sink, valuemask, &values); + + values.function = GXxor; + values.background = (unsigned long) 0L; /* (pix ^ 0) = pix */ + values.foreground = (sink->text_sink.background ^ + sink->text_sink.foreground); + valuemask = GCGraphicsExposures | GCFunction | GCForeground | GCBackground; + + sink->ascii_sink.xorgc = XtGetGC((Widget)sink, valuemask, &values); +} + + +/***** Public routines *****/ + +/* Function Name: Initialize + * Description: Initializes the TextSink Object. + * Arguments: request, new - the requested and new values for the object + * instance. + * Returns: none. + * + */ + +/* ARGSUSED */ +static void +Initialize(request, new, args, num_args) +Widget request, new; +ArgList args; +Cardinal *num_args; +{ + AsciiSinkObject sink = (AsciiSinkObject) new; + + GetGC(sink); + + sink->ascii_sink.insertCursorOn= CreateInsertCursor(XtScreenOfObject(new)); + sink->ascii_sink.laststate = XawisOff; + sink->ascii_sink.cursor_x = sink->ascii_sink.cursor_y = 0; +} + +/* Function Name: Destroy + * Description: This function cleans up when the object is + * destroyed. + * Arguments: w - the AsciiSink Object. + * Returns: none. + */ + +static void +Destroy(w) +Widget w; +{ + AsciiSinkObject sink = (AsciiSinkObject) w; + + XtReleaseGC(w, sink->ascii_sink.normgc); + XtReleaseGC(w, sink->ascii_sink.invgc); + XtReleaseGC(w, sink->ascii_sink.xorgc); + XFreePixmap(XtDisplayOfObject(w), sink->ascii_sink.insertCursorOn); +} + +/* Function Name: SetValues + * Description: Sets the values for the AsciiSink + * Arguments: current - current state of the object. + * request - what was requested. + * new - what the object will become. + * Returns: True if redisplay is needed. + */ + +/* ARGSUSED */ +static Boolean +SetValues(current, request, new, args, num_args) +Widget current, request, new; +ArgList args; +Cardinal *num_args; +{ + AsciiSinkObject w = (AsciiSinkObject) new; + AsciiSinkObject old_w = (AsciiSinkObject) current; + + if (w->ascii_sink.font != old_w->ascii_sink.font + || w->text_sink.background != old_w->text_sink.background + || w->text_sink.foreground != old_w->text_sink.foreground) { + XtReleaseGC((Widget)w, w->ascii_sink.normgc); + XtReleaseGC((Widget)w, w->ascii_sink.invgc); + XtReleaseGC((Widget)w, w->ascii_sink.xorgc); + GetGC(w); + ((TextWidget)XtParent(new))->text.redisplay_needed = True; + } else { + if ( (w->ascii_sink.echo != old_w->ascii_sink.echo) || + (w->ascii_sink.display_nonprinting != + old_w->ascii_sink.display_nonprinting) ) + ((TextWidget)XtParent(new))->text.redisplay_needed = True; + } + + return False; +} + +/* Function Name: MaxLines + * Description: Finds the Maximum number of lines that will fit in + * a given height. + * Arguments: w - the AsciiSink Object. + * height - height to fit lines into. + * Returns: the number of lines that will fit. + */ + +/* ARGSUSED */ +static int +MaxLines(w, height) +Widget w; +Dimension height; +{ + AsciiSinkObject sink = (AsciiSinkObject) w; + int font_height; + + font_height = sink->ascii_sink.font->ascent + sink->ascii_sink.font->descent; + return( ((int) height) / font_height ); +} + +/* Function Name: MaxHeight + * Description: Finds the Minium height that will contain a given number + * lines. + * Arguments: w - the AsciiSink Object. + * lines - the number of lines. + * Returns: the height. + */ + +/* ARGSUSED */ +static int +MaxHeight(w, lines) +Widget w; +int lines; +{ + AsciiSinkObject sink = (AsciiSinkObject) w; + + return(lines * (sink->ascii_sink.font->ascent + + sink->ascii_sink.font->descent)); +} + +/* Function Name: SetTabs + * Description: Sets the Tab stops. + * Arguments: w - the AsciiSink Object. + * tab_count - the number of tabs in the list. + * tabs - the text positions of the tabs. + * Returns: none + */ + +static void +SetTabs(w, tab_count, tabs) +Widget w; +int tab_count; +short *tabs; +{ + AsciiSinkObject sink = (AsciiSinkObject) w; + int i; + Atom XA_FIGURE_WIDTH; + unsigned long figure_width = 0; + XFontStruct *font = sink->ascii_sink.font; + +/* + * Find the figure width of the current font. + */ + + XA_FIGURE_WIDTH = XInternAtom(XtDisplayOfObject(w), "FIGURE_WIDTH", FALSE); + if ( (XA_FIGURE_WIDTH != None) && + ( (!XGetFontProperty(font, XA_FIGURE_WIDTH, &figure_width)) || + (figure_width == 0)) ) + if (font->per_char && font->min_char_or_byte2 <= '$' && + font->max_char_or_byte2 >= '$') + figure_width = font->per_char['$' - font->min_char_or_byte2].width; + else + figure_width = font->max_bounds.width; + + if (tab_count > sink->text_sink.tab_count) { + sink->text_sink.tabs = (Position *) + XtRealloc((char *) sink->text_sink.tabs, + (Cardinal) (tab_count * sizeof(Position))); + sink->text_sink.char_tabs = (short *) + XtRealloc((char *) sink->text_sink.char_tabs, + (Cardinal) (tab_count * sizeof(short))); + } + + for ( i = 0 ; i < tab_count ; i++ ) { + sink->text_sink.tabs[i] = tabs[i] * figure_width; + sink->text_sink.char_tabs[i] = tabs[i]; + } + + sink->text_sink.tab_count = tab_count; + +#ifndef NO_TAB_FIX + { TextWidget ctx = (TextWidget)XtParent(w); + ctx->text.redisplay_needed = True; + _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE); + } +#endif +} diff --git a/src/AsciiSink.h b/src/AsciiSink.h new file mode 100644 index 0000000..30ac68a --- /dev/null +++ b/src/AsciiSink.h @@ -0,0 +1,91 @@ +/* + * $XConsortium: AsciiSink.h,v 1.9 94/04/17 20:11:43 kaleb Exp $ + */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _XawAsciiSink_h +#define _XawAsciiSink_h + +/*********************************************************************** + * + * AsciiSink Object + * + ***********************************************************************/ + +#include <X11/Xaw3d/TextSink.h> + +/* Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + echo Output Boolean True + displayNonprinting Output Boolean True + +*/ + +#define XtCOutput "Output" + +#define XtNdisplayNonprinting "displayNonprinting" +#define XtNecho "echo" + +/* Class record constants */ + +extern WidgetClass asciiSinkObjectClass; + +typedef struct _AsciiSinkClassRec *AsciiSinkObjectClass; +typedef struct _AsciiSinkRec *AsciiSinkObject; + +/************************************************************ + * + * Public Functions. + * + ************************************************************/ + +#endif /* _XawAsciiSrc_h */ diff --git a/src/AsciiSinkP.h b/src/AsciiSinkP.h new file mode 100644 index 0000000..f6ba99f --- /dev/null +++ b/src/AsciiSinkP.h @@ -0,0 +1,118 @@ +/* +* $XConsortium: AsciiSinkP.h,v 1.4 94/04/17 20:11:44 kaleb Exp $ +*/ + + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * asciiSinkP.h - Private definitions for asciiSink object + * + */ + +#ifndef _XawAsciiSinkP_h +#define _XawAsciiSinkP_h + +/*********************************************************************** + * + * AsciiSink Object Private Data + * + ***********************************************************************/ + +#include <X11/Xaw3d/TextSinkP.h> +#include <X11/Xaw3d/AsciiSink.h> + +/************************************************************ + * + * New fields for the AsciiSink object class record. + * + ************************************************************/ + +typedef struct _AsciiSinkClassPart { + int foo; +} AsciiSinkClassPart; + +/* Full class record declaration */ + +typedef struct _AsciiSinkClassRec { + ObjectClassPart object_class; + TextSinkClassPart text_sink_class; + AsciiSinkClassPart ascii_sink_class; +} AsciiSinkClassRec; + +extern AsciiSinkClassRec asciiSinkClassRec; + +/* New fields for the AsciiSink object record */ +typedef struct { + /* public resources */ + XFontStruct *font; /* Font to draw in. */ + Boolean echo; + Boolean display_nonprinting; + + /* private state */ + GC normgc, invgc, xorgc; + Pixmap insertCursorOn; + XawTextInsertState laststate; + short cursor_x, cursor_y; /* Cursor Location. */ +} AsciiSinkPart; + +/**************************************************************** + * + * Full instance record declaration + * + ****************************************************************/ + +typedef struct _AsciiSinkRec { + ObjectPart object; + TextSinkPart text_sink; + AsciiSinkPart ascii_sink; +} AsciiSinkRec; + +#endif /* _XawAsciiSinkP_h */ + diff --git a/src/AsciiSrc.c b/src/AsciiSrc.c new file mode 100644 index 0000000..be8cdf8 --- /dev/null +++ b/src/AsciiSrc.c @@ -0,0 +1,1438 @@ +/* $XConsortium: AsciiSrc.c,v 1.65 94/04/17 20:11:45 kaleb Exp $ */ + +/* + +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +/* + * AsciiSrc.c - AsciiSrc object. (For use with the text widget). + * + */ + +#include "Xaw3dP.h" +#include <X11/IntrinsicP.h> +#include <stdio.h> +#include <ctype.h> +#include <errno.h> +#include <X11/StringDefs.h> +#include <X11/Xos.h> +#ifndef X_NOT_STDC_ENV +#include <stdlib.h> +#endif +#include <X11/Xfuncs.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/AsciiSrcP.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xmu/CharSet.h> +#ifdef XAW_INTERNATIONALIZATION +#include <X11/Xaw3d/MultiSrcP.h> +#endif + + +#if (defined(ASCII_STRING) || defined(ASCII_DISK)) +# include <X11/Xaw3d/AsciiText.h> /* for Widget Classes. */ +#endif + + +/**************************************************************** + * + * Full class record constant + * + ****************************************************************/ + +/* Private Data */ + +static int magic_value = MAGIC_VALUE; + +#define offset(field) XtOffsetOf(AsciiSrcRec, ascii_src.field) + +static XtResource resources[] = { + {XtNstring, XtCString, XtRString, sizeof (char *), + offset(string), XtRString, NULL}, + {XtNtype, XtCType, XtRAsciiType, sizeof (XawAsciiType), + offset(type), XtRImmediate, (XtPointer)XawAsciiString}, + {XtNdataCompression, XtCDataCompression, XtRBoolean, sizeof (Boolean), + offset(data_compression), XtRImmediate, (XtPointer) TRUE}, + {XtNpieceSize, XtCPieceSize, XtRInt, sizeof (XawTextPosition), + offset(piece_size), XtRImmediate, (XtPointer) BUFSIZ}, + {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), + offset(callback), XtRCallback, (XtPointer)NULL}, + {XtNuseStringInPlace, XtCUseStringInPlace, XtRBoolean, sizeof (Boolean), + offset(use_string_in_place), XtRImmediate, (XtPointer) FALSE}, + {XtNlength, XtCLength, XtRInt, sizeof (int), + offset(ascii_length), XtRInt, (XtPointer) &magic_value}, + +#ifdef ASCII_DISK + {XtNfile, XtCFile, XtRString, sizeof (String), + offset(filename), XtRString, NULL}, +#endif /* ASCII_DISK */ +}; +#undef offset + +static XawTextPosition Scan(), Search(), ReadText(); +static int ReplaceText(); +static Piece * FindPiece(), * AllocNewPiece(); +static FILE * InitStringOrFile(); +static void FreeAllPieces(), RemovePiece(), BreakPiece(), LoadPieces(); +static void RemoveOldStringOrFile(), CvtStringToAsciiType(); +static void ClassInitialize(), Initialize(), Destroy(), GetValuesHook(); +static String MyStrncpy(), StorePiecesInString(); +static Boolean SetValues(), WriteToFile(); +#ifdef X_NOT_STDC_ENV +extern int errno; +#endif + +#ifdef X_NOT_POSIX +#define Off_t long +#define Size_t unsigned int +#else +#define Off_t off_t +#define Size_t size_t +#endif + +#define superclass (&textSrcClassRec) +AsciiSrcClassRec asciiSrcClassRec = { + { +/* core_class fields */ + /* superclass */ (WidgetClass) superclass, + /* class_name */ "AsciiSrc", + /* widget_size */ sizeof(AsciiSrcRec), + /* class_initialize */ ClassInitialize, + /* class_part_initialize */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ NULL, + /* actions */ NULL, + /* num_actions */ 0, + /* resources */ resources, + /* num_resources */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ FALSE, + /* compress_exposure */ FALSE, + /* compress_enterleave */ FALSE, + /* visible_interest */ FALSE, + /* destroy */ Destroy, + /* resize */ NULL, + /* expose */ NULL, + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* set_values_almost */ NULL, + /* get_values_hook */ GetValuesHook, + /* accept_focus */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* tm_table */ NULL, + /* query_geometry */ NULL, + /* display_accelerator */ NULL, + /* extension */ NULL + }, +/* textSrc_class fields */ + { + /* Read */ ReadText, + /* Replace */ ReplaceText, + /* Scan */ Scan, + /* Search */ Search, + /* SetSelection */ XtInheritSetSelection, + /* ConvertSelection */ XtInheritConvertSelection + }, +/* asciiSrc_class fields */ + { + /* Keep the compiler happy */ '\0' + } +}; + +WidgetClass asciiSrcObjectClass = (WidgetClass)&asciiSrcClassRec; + +/************************************************************ + * + * Semi-Public Interfaces. + * + ************************************************************/ + +/* Function Name: ClassInitialize + * Description: Class Initialize routine, called only once. + * Arguments: none. + * Returns: none. + */ + +static void +ClassInitialize() +{ + XawInitializeWidgetSet(); + XtAddConverter( XtRString, XtRAsciiType, CvtStringToAsciiType, + NULL, (Cardinal) 0); +} + +/* Function Name: Initialize + * Description: Initializes the simple menu widget + * Arguments: request - the widget requested by the argument list. + * new - the new widget with both resource and non + * resource values. + * Returns: none. + */ + +/* ARGSUSED */ +static void +Initialize(request, new, args, num_args) +Widget request, new; +ArgList args; +Cardinal *num_args; +{ + AsciiSrcObject src = (AsciiSrcObject) new; + FILE * file; + +/* + * Set correct flags (override resources) depending upon widget class. + */ + + src->text_src.text_format = XawFmt8Bit; /* data format. */ + +#ifdef ASCII_DISK + if (XtIsSubclass(XtParent(new), asciiDiskWidgetClass)) { + src->ascii_src.type = XawAsciiFile; + src->ascii_src.string = src->ascii_src.filename; + } +#endif + +#ifdef ASCII_STRING + if (XtIsSubclass(XtParent(new), asciiStringWidgetClass)) { + src->ascii_src.use_string_in_place = TRUE; + src->ascii_src.type = XawAsciiString; + } +#endif + + src->ascii_src.changes = FALSE; + src->ascii_src.allocated_string = FALSE; + + file = InitStringOrFile(src, src->ascii_src.type == XawAsciiFile); + LoadPieces(src, file, NULL); + + if (file != NULL) fclose(file); +} + +/* Function Name: ReadText + * Description: This function reads the source. + * Arguments: w - the AsciiSource widget. + * pos - position of the text to retreive. + * RETURNED text - text block that will contain returned text. + * length - maximum number of characters to read. + * Returns: The number of characters read into the buffer. + */ + +static XawTextPosition +ReadText(w, pos, text, length) +Widget w; +XawTextPosition pos; +XawTextBlock *text; +int length; +{ + AsciiSrcObject src = (AsciiSrcObject) w; + XawTextPosition count, start; + Piece * piece = FindPiece(src, pos, &start); + + text->firstPos = pos; + text->ptr = piece->text + (pos - start); + count = piece->used - (pos - start); + text->length = (length > count) ? count : length; + return(pos + text->length); +} + +/* Function Name: ReplaceText. + * Description: Replaces a block of text with new text. + * Arguments: w - the AsciiSource widget. + * startPos, endPos - ends of text that will be removed. + * text - new text to be inserted into buffer at startPos. + * Returns: XawEditError or XawEditDone. + */ + +/*ARGSUSED*/ +static int +ReplaceText (w, startPos, endPos, text) +Widget w; +XawTextPosition startPos, endPos; +XawTextBlock *text; +{ + AsciiSrcObject src = (AsciiSrcObject) w; + Piece *start_piece, *end_piece, *temp_piece; + XawTextPosition start_first, end_first; + int length, firstPos; + +/* + * Editing a read only source is not allowed. + */ + + if (src->text_src.edit_mode == XawtextRead) + return(XawEditError); + + start_piece = FindPiece(src, startPos, &start_first); + end_piece = FindPiece(src, endPos, &end_first); + + src->ascii_src.changes = TRUE; /* We have changed the buffer. */ + +/* + * Remove Old Stuff. + */ + + if (start_piece != end_piece) { + temp_piece = start_piece->next; + +/* + * If empty and not the only piece then remove it. + */ + + if ( ((start_piece->used = startPos - start_first) == 0) && + !((start_piece->next == NULL) && (start_piece->prev == NULL)) ) + RemovePiece(src, start_piece); + + while (temp_piece != end_piece) { + temp_piece = temp_piece->next; + RemovePiece(src, temp_piece->prev); + } + end_piece->used -= endPos - end_first; + if (end_piece->used != 0) + MyStrncpy(end_piece->text, (end_piece->text + endPos - end_first), + (int) end_piece->used); + } + else { /* We are fully in one piece. */ + if ( (start_piece->used -= endPos - startPos) == 0) { + if ( !((start_piece->next == NULL) && (start_piece->prev == NULL)) ) + RemovePiece(src, start_piece); + } + else { + MyStrncpy(start_piece->text + (startPos - start_first), + start_piece->text + (endPos - start_first), + (int) (start_piece->used - (startPos - start_first)) ); + if ( src->ascii_src.use_string_in_place && + ((src->ascii_src.length - (endPos - startPos)) < + (src->ascii_src.piece_size - 1)) ) + start_piece->text[src->ascii_src.length - (endPos - startPos)] = '\0'; + } + } + + src->ascii_src.length += -(endPos - startPos) + text->length; + + if ( text->length != 0) { + + /* + * Put in the New Stuff. + */ + + start_piece = FindPiece(src, startPos, &start_first); + + length = text->length; + firstPos = text->firstPos; + + while (length > 0) { + char * ptr; + int fill; + + if (src->ascii_src.use_string_in_place) { + if (start_piece->used == (src->ascii_src.piece_size - 1)) { + /* + * If we are in ascii string emulation mode. Then the + * string is not allowed to grow. + */ + start_piece->used = src->ascii_src.length = + src->ascii_src.piece_size - 1; + start_piece->text[src->ascii_src.length] = '\0'; + return(XawEditError); + } + } + + + if (start_piece->used == src->ascii_src.piece_size) { + BreakPiece(src, start_piece); + start_piece = FindPiece(src, startPos, &start_first); + } + + fill = Min((int)(src->ascii_src.piece_size - start_piece->used), length); + + ptr = start_piece->text + (startPos - start_first); + MyStrncpy(ptr + fill, ptr, + (int) start_piece->used - (startPos - start_first)); + strncpy(ptr, text->ptr + firstPos, fill); + + startPos += fill; + firstPos += fill; + start_piece->used += fill; + length -= fill; + } + } + + if (src->ascii_src.use_string_in_place) + start_piece->text[start_piece->used] = '\0'; + + XtCallCallbacks(w, XtNcallback, NULL); /* Call callbacks, we have changed + the buffer. */ + + return(XawEditDone); +} + +/* Function Name: Scan + * Description: Scans the text source for the number and type + * of item specified. + * Arguments: w - the AsciiSource widget. + * position - the position to start scanning. + * type - type of thing to scan for. + * dir - direction to scan. + * count - which occurance if this thing to search for. + * include - whether or not to include the character found in + * the position that is returned. + * Returns: the position of the item found. + * + * Note: While there are only 'n' characters in the file there are n+1 + * possible cursor positions (one before the first character and + * one after the last character. + */ + +static +XawTextPosition +Scan (w, position, type, dir, count, include) +Widget w; +XawTextPosition position; +XawTextScanType type; +XawTextScanDirection dir; +int count; +Boolean include; +{ + AsciiSrcObject src = (AsciiSrcObject) w; + int inc; + Piece* piece; + XawTextPosition first, first_eol_position = 0; + char* ptr; + + if (type == XawstAll) { /* Optomize this common case. */ + if (dir == XawsdRight) + return(src->ascii_src.length); + return(0); /* else. */ + } + + if (position > src->ascii_src.length) + position = src->ascii_src.length; + + if ( dir == XawsdRight ) { + if (position == src->ascii_src.length) +/* + * Scanning right from src->ascii_src.length??? + */ + return(src->ascii_src.length); + inc = 1; + } + else { + if (position == 0) + return(0); /* Scanning left from 0??? */ + inc = -1; + position--; + } + + piece = FindPiece(src, position, &first); + +/* + * If the buffer is empty then return 0. + */ + + if ( piece->used == 0 ) return(0); + + ptr = (position - first) + piece->text; + + switch (type) { + case XawstEOL: + case XawstParagraph: + case XawstWhiteSpace: + for ( ; count > 0 ; count-- ) { + Boolean non_space = FALSE, first_eol = TRUE; + /* CONSTCOND */ + while (TRUE) { + unsigned char c = *ptr; + + ptr += inc; + position += inc; + + if (type == XawstWhiteSpace) { + if (isspace(c)) { + if (non_space) + break; + } + else + non_space = TRUE; + } + else if (type == XawstEOL) { + if (c == '\n') break; + } + else { /* XawstParagraph */ + if (first_eol) { + if (c == '\n') { + first_eol_position = position; + first_eol = FALSE; + } + } + else + if ( c == '\n') + break; + else if ( !isspace(c) ) + first_eol = TRUE; + } + + + if ( ptr < piece->text ) { + piece = piece->prev; + if (piece == NULL) /* Begining of text. */ + return(0); + ptr = piece->text + piece->used - 1; + } + else if ( ptr >= (piece->text + piece->used) ) { + piece = piece->next; + if (piece == NULL) /* End of text. */ + return(src->ascii_src.length); + ptr = piece->text; + } + } + } + if (!include) { + if ( type == XawstParagraph) + position = first_eol_position; + position -= inc; + } + break; + case XawstPositions: + position += count * inc; + break; + case XawstAll: /* handled in special code above */ + default: + break; + } + + if ( dir == XawsdLeft ) + position++; + + if (position >= src->ascii_src.length) + return(src->ascii_src.length); + if (position < 0) + return(0); + + return(position); +} + +/* Function Name: Search + * Description: Searchs the text source for the text block passed + * Arguments: w - the AsciiSource Widget. + * position - the position to start scanning. + * dir - direction to scan. + * text - the text block to search for. + * Returns: the position of the item found. + */ + +static XawTextPosition +Search(w, position, dir, text) +Widget w; +XawTextPosition position; +XawTextScanDirection dir; +XawTextBlock * text; +{ + AsciiSrcObject src = (AsciiSrcObject) w; + int inc, count = 0; + char * ptr; + Piece * piece; + char * buf; + XawTextPosition first; + + if ( dir == XawsdRight ) + inc = 1; + else { + inc = -1; + if (position == 0) + return(XawTextSearchError); /* scanning left from 0??? */ + position--; + } + + buf = XtMalloc((unsigned)sizeof(unsigned char) * text->length); + strncpy(buf, (text->ptr + text->firstPos), text->length); + piece = FindPiece(src, position, &first); + ptr = (position - first) + piece->text; + + /* CONSTCOND */ + while (TRUE) { + if (*ptr == ((dir == XawsdRight) ? *(buf + count) + : *(buf + text->length - count - 1)) ) { + if (count == (text->length - 1)) + break; + else + count++; + } + else { + if (count != 0) { + position -=inc * count; + ptr -= inc * count; + } + count = 0; + } + + ptr += inc; + position += inc; + + while ( ptr < piece->text ) { + piece = piece->prev; + if (piece == NULL) { /* Begining of text. */ + XtFree(buf); + return(XawTextSearchError); + } + ptr = piece->text + piece->used - 1; + } + + while ( ptr >= (piece->text + piece->used) ) { + piece = piece->next; + if (piece == NULL) { /* End of text. */ + XtFree(buf); + return(XawTextSearchError); + } + ptr = piece->text; + } + } + + XtFree(buf); + if (dir == XawsdLeft) + return(position); + return(position - (text->length - 1)); +} + +/* Function Name: SetValues + * Description: Sets the values for the AsciiSource. + * Arguments: current - current state of the widget. + * request - what was requested. + * new - what the widget will become. + * Returns: True if redisplay is needed. + */ + +/* ARGSUSED */ +static Boolean +SetValues(current, request, new, args, num_args) +Widget current, request, new; +ArgList args; +Cardinal * num_args; +{ + AsciiSrcObject src = (AsciiSrcObject) new; + AsciiSrcObject old_src = (AsciiSrcObject) current; + Boolean total_reset = FALSE, string_set = FALSE; + FILE * file; + int i; + + if ( old_src->ascii_src.use_string_in_place != + src->ascii_src.use_string_in_place ) { + XtAppWarning( XtWidgetToApplicationContext(new), + "AsciiSrc: The XtNuseStringInPlace resource may not be changed."); + src->ascii_src.use_string_in_place = + old_src->ascii_src.use_string_in_place; + } + + for (i = 0; i < *num_args ; i++ ) + if (streq(args[i].name, XtNstring)) { + string_set = TRUE; + break; + } + + if ( string_set || (old_src->ascii_src.type != src->ascii_src.type) ) { + RemoveOldStringOrFile(old_src, string_set); /* remove old info. */ + file = InitStringOrFile(src, string_set); /* Init new info. */ + LoadPieces(src, file, NULL); /* load new info into internal buffers. */ + if (file != NULL) fclose(file); + XawTextSetSource( XtParent(new), new, 0); /* Tell text widget + what happened. */ + total_reset = TRUE; + } + + if ( old_src->ascii_src.ascii_length != src->ascii_src.ascii_length ) + src->ascii_src.piece_size = src->ascii_src.ascii_length; + + if ( !total_reset && + (old_src->ascii_src.piece_size != src->ascii_src.piece_size) ) { + String string = StorePiecesInString(old_src); + FreeAllPieces(old_src); + LoadPieces(src, NULL, string); + XtFree(string); + } + + return(FALSE); +} + +/* Function Name: GetValuesHook + * Description: This is a get values hook routine that sets the + * values specific to the ascii source. + * Arguments: w - the AsciiSource Widget. + * args - the argument list. + * num_args - the number of args. + * Returns: none. + */ + +static void +GetValuesHook(w, args, num_args) +Widget w; +ArgList args; +Cardinal * num_args; +{ + AsciiSrcObject src = (AsciiSrcObject) w; + int i; + + if (src->ascii_src.type == XawAsciiString) { + for (i = 0; i < *num_args ; i++ ) + if (streq(args[i].name, XtNstring)) { + if (src->ascii_src.use_string_in_place) { + *((char **) args[i].value) = src->ascii_src.first_piece->text; + } + else { + if (XawAsciiSave(w)) /* If save sucessful. */ + *((char **) args[i].value) = src->ascii_src.string; + } + break; + } + } +} + +/* Function Name: Destroy + * Description: Destroys an ascii source (frees all data) + * Arguments: src - the Ascii source Widget to free. + * Returns: none. + */ + +static void +Destroy (w) +Widget w; +{ + RemoveOldStringOrFile((AsciiSrcObject) w, True); +} + +/************************************************************ + * + * Public routines + * + ************************************************************/ + +/* Function Name: XawAsciiSourceFreeString + * Description: Frees the string returned by a get values call + * on the string when the source is of type string. + * Arguments: w - the AsciiSrc widget. + * Returns: none. + */ + +void +#if NeedFunctionPrototypes +XawAsciiSourceFreeString(Widget w) +#else +XawAsciiSourceFreeString(w) +Widget w; +#endif +{ + AsciiSrcObject src = (AsciiSrcObject) w; + + /* If the src is really a multi, call the multi routine.*/ + +#ifdef XAW_INTERNATIONALIZATION + if ( XtIsSubclass( w, multiSrcObjectClass ) ) { + _XawMultiSourceFreeString( w ); + return; + } + else +#endif + if ( !XtIsSubclass( w, asciiSrcObjectClass ) ) { + XtErrorMsg("bad argument", "asciiSource", "XawError", +#ifdef XAW_INTERNATIONALIZATION + "XawAsciiSourceFreeString's parameter must be an asciiSrc or multiSrc.", +#else + "XawAsciiSourceFreeString's parameter must be an asciiSrc.", +#endif + NULL, NULL); + } + + if (src->ascii_src.allocated_string && src->ascii_src.type != XawAsciiFile) { + src->ascii_src.allocated_string = FALSE; + XtFree(src->ascii_src.string); + src->ascii_src.string = NULL; + } +} + +/* Function Name: XawAsciiSave + * Description: Saves all the pieces into a file or string as required. + * Arguments: w - the asciiSrc Widget. + * Returns: TRUE if the save was successful. + */ + +Boolean +#if NeedFunctionPrototypes +XawAsciiSave(Widget w) +#else +XawAsciiSave(w) +Widget w; +#endif +{ + AsciiSrcObject src = (AsciiSrcObject) w; + + /* If the src is really a multi, call the multi save. */ + +#ifdef XAW_INTERNATIONALIZATION + if ( XtIsSubclass( w, multiSrcObjectClass ) ) + return( _XawMultiSave( w ) ); + else +#endif + if ( !XtIsSubclass( w, asciiSrcObjectClass ) ) { + XtErrorMsg("bad argument", "asciiSource", "XawError", +#ifdef XAW_INTERNATIONALIZATION + "XawAsciiSave's parameter must be an asciiSrc or multiSrc.", +#else + "XawAsciiSave's parameter must be an asciiSrc.", +#endif + NULL, NULL); + } + +/* + * If using the string in place then there is no need to play games + * to get the internal info into a readable string. + */ + + if (src->ascii_src.use_string_in_place) + return(TRUE); + + if (src->ascii_src.type == XawAsciiFile) { + char * string; + + if (!src->ascii_src.changes) /* No changes to save. */ + return(TRUE); + + string = StorePiecesInString(src); + + if (WriteToFile(string, src->ascii_src.string) == FALSE) { + XtFree(string); + return(FALSE); + } + XtFree(string); + } + else { + if (src->ascii_src.allocated_string == TRUE) + XtFree(src->ascii_src.string); + else + src->ascii_src.allocated_string = TRUE; + + src->ascii_src.string = StorePiecesInString(src); + } + src->ascii_src.changes = FALSE; + return(TRUE); +} + +/* Function Name: XawAsciiSaveAsFile + * Description: Save the current buffer as a file. + * Arguments: w - the AsciiSrc widget. + * name - name of the file to save this file into. + * Returns: True if the save was sucessful. + */ + +Boolean +#if NeedFunctionPrototypes +XawAsciiSaveAsFile(Widget w, _Xconst char* name) +#else +XawAsciiSaveAsFile(w, name) +Widget w; +String name; +#endif +{ + AsciiSrcObject src = (AsciiSrcObject) w; + String string; + Boolean ret; + + /* If the src is really a multi, call the multi save. - */ + +#ifdef XAW_INTERNATIONALIZATION + if ( XtIsSubclass( w, multiSrcObjectClass ) ) + return( _XawMultiSaveAsFile( w, name ) ); + else +#endif + if ( !XtIsSubclass( w, asciiSrcObjectClass ) ) { + XtErrorMsg("bad argument", "asciiSource", "XawError", +#ifdef XAW_INTERNATIONALIZATION + "XawAsciiSaveAsFile's 1st parameter must be an asciiSrc or multiSrc.", +#else + "XawAsciiSaveAsFile's 1st parameter must be an asciiSrc.", +#endif + NULL, NULL); + } + + string = StorePiecesInString(src); + + ret = WriteToFile(string, name); + XtFree(string); + return(ret); +} + +/* Function Name: XawAsciiSourceChanged + * Description: Returns true if the source has changed since last saved. + * Arguments: w - the ascii source widget. + * Returns: a Boolean (see description). + */ + +Boolean +#if NeedFunctionPrototypes +XawAsciiSourceChanged(Widget w) +#else +XawAsciiSourceChanged(w) +Widget w; +#endif +{ +#ifdef XAW_INTERNATIONALIZATION + if ( XtIsSubclass( w, multiSrcObjectClass ) ) + return( ( (MultiSrcObject) w )->multi_src.changes ); +#endif + + if ( XtIsSubclass( w, asciiSrcObjectClass ) ) + return( ( (AsciiSrcObject) w)->ascii_src.changes ); + + XtErrorMsg("bad argument", "asciiSource", "XawError", +#ifdef XAW_INTERNATIONALIZATION + "XawAsciiSourceChanged parameter must be an asciiSrc or multiSrc.", +#else + "XawAsciiSourceChanged parameter must be an asciiSrc.", +#endif + NULL, NULL); + + return( True ); /* for gcc -Wall */ +} + +/************************************************************ + * + * Private Functions. + * + ************************************************************/ + +static void +RemoveOldStringOrFile(src, checkString) +AsciiSrcObject src; +Boolean checkString; +{ + FreeAllPieces(src); + + if (checkString && src->ascii_src.allocated_string) { + XtFree(src->ascii_src.string); + src->ascii_src.allocated_string = False; + src->ascii_src.string = NULL; + } +} + +/* Function Name: WriteToFile + * Description: Write the string specified to the begining of the file + * specified. + * Arguments: string - string to write. + * name - the name of the file + * Returns: returns TRUE if sucessful, FALSE otherwise. + */ + +static Boolean +WriteToFile(string, name) +String string, name; +{ + int fd; + + if ( ((fd = creat(name, 0666)) == -1 ) || + (write(fd, string, sizeof(unsigned char) * strlen(string)) == -1) ) + return(FALSE); + + if ( close(fd) == -1 ) + return(FALSE); + + return(TRUE); +} + +/* Function Name: StorePiecesInString + * Description: store the pieces in memory into a standard ascii string. + * Arguments: data - the ascii pointer data. + * Returns: none. + */ + +static String +StorePiecesInString(src) +AsciiSrcObject src; +{ + String string; + XawTextPosition first; + Piece * piece; + + string = XtMalloc((unsigned) sizeof(unsigned char) * + src->ascii_src.length + 1); + + for (first = 0, piece = src->ascii_src.first_piece ; piece != NULL; + first += piece->used, piece = piece->next) + strncpy(string + first, piece->text, piece->used); + + string[src->ascii_src.length] = '\0'; /* NULL terminate this sucker. */ + +/* + * This will refill all pieces to capacity. + */ + + if (src->ascii_src.data_compression) { + FreeAllPieces(src); + LoadPieces(src, NULL, string); + } + + return(string); +} + +/* Function Name: InitStringOrFile. + * Description: Initializes the string or file. + * Arguments: src - the AsciiSource. + * Returns: none - May exit though. + */ + +static FILE * +InitStringOrFile(src, newString) +AsciiSrcObject src; +Boolean newString; +{ + char * open_mode = NULL; + FILE * file; + char fileName[TMPSIZ]; + + if (src->ascii_src.type == XawAsciiString) { + + if (src->ascii_src.string == NULL) + src->ascii_src.length = 0; + + else if (! src->ascii_src.use_string_in_place) { + src->ascii_src.string = XtNewString(src->ascii_src.string); + src->ascii_src.allocated_string = True; + src->ascii_src.length = strlen(src->ascii_src.string); + } + + if (src->ascii_src.use_string_in_place) { + src->ascii_src.length = strlen(src->ascii_src.string); + /* In case the length resource is incorrectly set */ + if (src->ascii_src.length > src->ascii_src.ascii_length) + src->ascii_src.ascii_length = src->ascii_src.length; + + if (src->ascii_src.ascii_length == MAGIC_VALUE) + src->ascii_src.piece_size = src->ascii_src.length; + else + src->ascii_src.piece_size = src->ascii_src.ascii_length + 1; + } + + return(NULL); + } + +/* + * type is XawAsciiFile. + */ + + src->ascii_src.is_tempfile = FALSE; + + switch (src->text_src.edit_mode) { + case XawtextRead: + if (src->ascii_src.string == NULL) + XtErrorMsg("NoFile", "asciiSourceCreate", "XawError", + "Creating a read only disk widget and no file specified.", + NULL, 0); + open_mode = "r"; + break; + case XawtextAppend: + case XawtextEdit: + if (src->ascii_src.string == NULL) { + src->ascii_src.string = fileName; + (void) tmpnam(src->ascii_src.string); + src->ascii_src.is_tempfile = TRUE; + open_mode = "w"; + } else + open_mode = "r+"; + break; + default: + XtErrorMsg("badMode", "asciiSourceCreate", "XawError", + "Bad editMode for ascii source; must be Read, Append or Edit.", + NULL, NULL); + } + + /* Allocate new memory for the temp filename, because it is held in + * a stack variable, not static memory. This widget does not need + * to keep the private state field is_tempfile -- it is only accessed + * in this routine, and its former setting is unused. + */ + if (newString || src->ascii_src.is_tempfile) { + src->ascii_src.string = XtNewString(src->ascii_src.string); + src->ascii_src.allocated_string = TRUE; + } + + if (!src->ascii_src.is_tempfile) { + if ((file = fopen(src->ascii_src.string, open_mode)) != 0) { + (void) fseek(file, (Off_t)0, 2); + src->ascii_src.length = (XawTextPosition) ftell(file); + return file; + } else { + String params[2]; + Cardinal num_params = 2; + + params[0] = src->ascii_src.string; + params[1] = strerror(errno); + XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src), + "openError", "asciiSourceCreate", "XawWarning", + "Cannot open file %s; %s", params, &num_params); + } + } + src->ascii_src.length = 0; + return((FILE *)NULL); +} + +static void +LoadPieces(src, file, string) +AsciiSrcObject src; +FILE * file; +char * string; +{ + char *local_str, *ptr; + Piece * piece = NULL; + XawTextPosition left; + + if (string == NULL) { + if (src->ascii_src.type == XawAsciiFile) { + local_str = XtMalloc((unsigned) (src->ascii_src.length + 1) + * sizeof(unsigned char)); + if (src->ascii_src.length != 0) { + fseek(file, (Off_t)0, 0); + src->ascii_src.length = fread(local_str, (Size_t)sizeof(unsigned char), + (Size_t)src->ascii_src.length, file); + if (src->ascii_src.length <= 0) + XtErrorMsg("readError", "asciiSourceCreate", "XawError", + "fread returned error.", NULL, NULL); + } + local_str[src->ascii_src.length] = '\0'; + } + else + local_str = src->ascii_src.string; + } + else + local_str = string; + + if (src->ascii_src.use_string_in_place) { + piece = AllocNewPiece(src, piece); + piece->used = Min(src->ascii_src.length, src->ascii_src.piece_size); + piece->text = src->ascii_src.string; + return; + } + + ptr = local_str; + left = src->ascii_src.length; + + do { + piece = AllocNewPiece(src, piece); + + piece->text = XtMalloc((unsigned)src->ascii_src.piece_size + * sizeof(unsigned char)); + piece->used = Min(left, src->ascii_src.piece_size); + if (piece->used != 0) + strncpy(piece->text, ptr, piece->used); + + left -= piece->used; + ptr += piece->used; + } while (left > 0); + + if ( (src->ascii_src.type == XawAsciiFile) && (string == NULL) ) + XtFree(local_str); +} + +/* Function Name: AllocNewPiece + * Description: Allocates a new piece of memory. + * Arguments: src - The AsciiSrc Widget. + * prev - the piece just before this one, or NULL. + * Returns: the allocated piece. + */ + +static Piece * +AllocNewPiece(src, prev) +AsciiSrcObject src; +Piece * prev; +{ + Piece * piece = XtNew(Piece); + + if (prev == NULL) { + src->ascii_src.first_piece = piece; + piece->next = NULL; + } + else { + if (prev->next != NULL) + (prev->next)->prev = piece; + piece->next = prev->next; + prev->next = piece; + } + + piece->prev = prev; + + return(piece); +} + +/* Function Name: FreeAllPieces + * Description: Frees all the pieces + * Arguments: src - The AsciiSrc Widget. + * Returns: none. + */ + +static void +FreeAllPieces(src) +AsciiSrcObject src; +{ + Piece * next, * first = src->ascii_src.first_piece; + + if (first->prev != NULL) + (void) printf("Xaw AsciiSrc Object: possible memory leak in FreeAllPieces().\n"); + + for ( ; first != NULL ; first = next ) { + next = first->next; + RemovePiece(src, first); + } +} + +/* Function Name: RemovePiece + * Description: Removes a piece from the list. + * Arguments: + * piece - the piece to remove. + * Returns: none. + */ + +static void +RemovePiece(src, piece) +AsciiSrcObject src; +Piece * piece; +{ + if (piece->prev == NULL) + src->ascii_src.first_piece = piece->next; + else + (piece->prev)->next = piece->next; + + if (piece->next != NULL) + (piece->next)->prev = piece->prev; + + if (!src->ascii_src.use_string_in_place) + XtFree(piece->text); + + XtFree((char *)piece); +} + +/* Function Name: FindPiece + * Description: Finds the piece containing the position indicated. + * Arguments: src - The AsciiSrc Widget. + * position - the position that we are searching for. + * RETURNED first - the position of the first character in this piece. + * Returns: piece - the piece that contains this position. + */ + +static Piece * +FindPiece(src, position, first) +AsciiSrcObject src; +XawTextPosition position, *first; +{ + Piece * old_piece = NULL, * piece = src->ascii_src.first_piece; + XawTextPosition temp; + + for ( temp = 0 ; piece != NULL ; temp += piece->used, piece = piece->next ) { + *first = temp; + old_piece = piece; + + if ((temp + piece->used) > position) + return(piece); + } + return(old_piece); /* if we run off the end the return the last piece */ +} + +/* Function Name: MyStrncpy + * Description: Just like string copy, but slower and will always + * work on overlapping strings. + * Arguments: (same as strncpy) - s1, s2 - strings to copy (2->1). + * n - the number of chars to copy. + * Returns: s1. + */ + +static String +MyStrncpy(s1, s2, n) +char * s1, * s2; +int n; +{ + char buf[256]; + char* temp; + + if (n == 0) return s1; + + if (n < sizeof buf) temp = buf; + else temp = XtMalloc((unsigned)sizeof(unsigned char) * n); + + strncpy(temp, s2, n); /* Saber has a bug that causes it to generate*/ + strncpy(s1, temp, n); /* a bogus warning message here (CDP 6/32/89)*/ + + if (temp != buf) XtFree(temp); + return s1; +} + +/* Function Name: BreakPiece + * Description: Breaks a full piece into two new pieces. + * Arguments: src - The AsciiSrc Widget. + * piece - the piece to break. + * Returns: none. + */ + +#define HALF_PIECE (src->ascii_src.piece_size/2) + +static void +BreakPiece(src, piece) +AsciiSrcObject src; +Piece * piece; +{ + Piece * new = AllocNewPiece(src, piece); + + new->text = XtMalloc(src->ascii_src.piece_size * sizeof(unsigned char)); + strncpy(new->text, piece->text + HALF_PIECE, + src->ascii_src.piece_size - HALF_PIECE); + piece->used = HALF_PIECE; + new->used = src->ascii_src.piece_size - HALF_PIECE; +} + +/* ARGSUSED */ +static void +CvtStringToAsciiType(args, num_args, fromVal, toVal) +XrmValuePtr args; /* unused */ +Cardinal *num_args; /* unused */ +XrmValuePtr fromVal; +XrmValuePtr toVal; +{ + static XawAsciiType type; + static XrmQuark XtQEstring = NULLQUARK; + static XrmQuark XtQEfile; + XrmQuark q; + char lowerName[40]; + + if (XtQEstring == NULLQUARK) { + XtQEstring = XrmPermStringToQuark(XtEstring); + XtQEfile = XrmPermStringToQuark(XtEfile); + } + + if (strlen ((char*)fromVal->addr) < sizeof lowerName) { + XmuCopyISOLatin1Lowered(lowerName, (char *) fromVal->addr); + q = XrmStringToQuark(lowerName); + + if (q == XtQEstring) type = XawAsciiString; + else if (q == XtQEfile) type = XawAsciiFile; + else { + toVal->size = 0; + toVal->addr = NULL; + return; + } + toVal->size = sizeof type; + toVal->addr = (XPointer) &type; + return; + } + toVal->size = 0; + toVal->addr = NULL; +} + +#if (defined(ASCII_STRING) || defined(ASCII_DISK)) +# include <X11/Xaw3d/Cardinals.h> +#endif + +#ifdef ASCII_STRING +/************************************************************ + * + * Compatability functions. + * + ************************************************************/ + +/* Function Name: AsciiStringSourceCreate + * Description: Creates a string source. + * Arguments: parent - the widget that will own this source. + * args, num_args - the argument list. + * Returns: a pointer to the new text source. + */ + +Widget +XawStringSourceCreate(parent, args, num_args) +Widget parent; +ArgList args; +Cardinal num_args; +{ + XawTextSource src; + ArgList ascii_args; + Arg temp[2]; + + XtSetArg(temp[0], XtNtype, XawAsciiString); + XtSetArg(temp[1], XtNuseStringInPlace, TRUE); + ascii_args = XtMergeArgLists(temp, TWO, args, num_args); + + src = XtCreateWidget("genericAsciiString", asciiSrcObjectClass, parent, + ascii_args, num_args + TWO); + XtFree((char *)ascii_args); + return(src); +} + +/* + * This is hacked up to try to emulate old functionality, it + * may not work, as I have not old code to test it on. + * + * Chris D. Peterson 8/31/89. + */ + +void +XawTextSetLastPos (w, lastPos) +Widget w; +XawTextPosition lastPos; +{ + AsciiSrcObject src = (AsciiSrcObject) XawTextGetSource(w); + + src->ascii_src.piece_size = lastPos; +} +#endif /* ASCII_STRING */ + +#ifdef ASCII_DISK +/* Function Name: AsciiDiskSourceCreate + * Description: Creates a disk source. + * Arguments: parent - the widget that will own this source. + * args, num_args - the argument list. + * Returns: a pointer to the new text source. + */ + +Widget +XawDiskSourceCreate(parent, args, num_args) +Widget parent; +ArgList args; +Cardinal num_args; +{ + XawTextSource src; + ArgList ascii_args; + Arg temp[1]; + int i; + + XtSetArg(temp[0], XtNtype, XawAsciiFile); + ascii_args = XtMergeArgLists(temp, ONE, args, num_args); + num_args++; + + for (i = 0; i < num_args; i++) + if (streq(ascii_args[i].name, XtNfile) || + streq(ascii_args[i].name, XtCFile)) + ascii_args[i].name = XtNstring; + + src = XtCreateWidget("genericAsciiDisk", asciiSrcObjectClass, parent, + ascii_args, num_args); + XtFree((char *)ascii_args); + return(src); +} +#endif /* ASCII_DISK */ diff --git a/src/AsciiSrc.h b/src/AsciiSrc.h new file mode 100644 index 0000000..37fe4e4 --- /dev/null +++ b/src/AsciiSrc.h @@ -0,0 +1,162 @@ +/* $XConsortium: AsciiSrc.h,v 1.15 94/04/17 20:11:46 kaleb Exp $ */ + +/* + +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + + +/* + * AsciiSrc.h - Public Header file for Ascii Text Source. + * + * This is the public header file for the Ascii Text Source. + * It is intended to be used with the Text widget, the simplest way to use + * this text source is to use the AsciiText Object. + * + * Date: June 29, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + + +#ifndef _XawAsciiSrc_h +#define _XawAsciiSrc_h + +#include <X11/Xaw3d/TextSrc.h> + +/* Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + callback Callback Callback (none) + dataCompression DataCompression Boolean True + length Length int (internal) + pieceSize PieceSize int BUFSIZ + string String String NULL + type Type XawAsciiType XawAsciiString + useStringInPlace UseStringInPlace Boolean False + +*/ + +/* Class record constants */ + +extern WidgetClass asciiSrcObjectClass; + +typedef struct _AsciiSrcClassRec *AsciiSrcObjectClass; +typedef struct _AsciiSrcRec *AsciiSrcObject; + +/* + * Just to make people's lives a bit easier. + */ + +#define AsciiSourceObjectClass AsciiSrcObjectClass +#define AsciiSourceObject AsciiSrcObject + +/* + * Resource Definitions. + */ + +#define XtCDataCompression "DataCompression" +#define XtCPieceSize "PieceSize" +#define XtCType "Type" +#define XtCUseStringInPlace "UseStringInPlace" + +#define XtNdataCompression "dataCompression" +#define XtNpieceSize "pieceSize" +#define XtNtype "type" +#define XtNuseStringInPlace "useStringInPlace" + +#define XtRAsciiType "AsciiType" + +#define XtEstring "string" +#define XtEfile "file" + +typedef enum {XawAsciiFile, XawAsciiString} XawAsciiType; + +/************************************************************ + * + * Public routines + * + ************************************************************/ + +_XFUNCPROTOBEGIN + +/* Function Name: XawAsciiSourceFreeString + * Description: Frees the string returned by a get values call + * on the string when the source is of type string. + * Arguments: w - the AsciiSrc object. + * Returns: none. + */ + +extern void XawAsciiSourceFreeString( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +/* Function Name: XawAsciiSave + * Description: Saves all the pieces into a file or string as required. + * Arguments: w - the asciiSrc Object. + * Returns: TRUE if the save was successful. + */ + +extern Boolean XawAsciiSave( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +/* Function Name: XawAsciiSaveAsFile + * Description: Save the current buffer as a file. + * Arguments: w - the asciiSrc object. + * name - name of the file to save this file into. + * Returns: True if the save was successful. + */ + +extern Boolean XawAsciiSaveAsFile( +#if NeedFunctionPrototypes + Widget /* w */, + _Xconst char* /* name */ +#endif +); + +/* Function Name: XawAsciiSourceChanged + * Description: Returns true if the source has changed since last saved. + * Arguments: w - the asciiSource object. + * Returns: a Boolean (see description). + */ + +extern Boolean XawAsciiSourceChanged( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +_XFUNCPROTOEND + +#endif /* _XawAsciiSrc_h */ + diff --git a/src/AsciiSrcP.h b/src/AsciiSrcP.h new file mode 100644 index 0000000..dcb33ff --- /dev/null +++ b/src/AsciiSrcP.h @@ -0,0 +1,163 @@ +/* +* $XConsortium: AsciiSrcP.h,v 1.10 94/04/17 20:11:49 kaleb Exp $ +*/ + + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * AsciiSrcP.h - Private Header for Ascii Text Source. + * + * This is the private header file for the Ascii Text Source. + * It is intended to be used with the Text widget, the simplest way to use + * this text source is to use the AsciiText Object. + * + * Date: June 29, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +/* + * TextSrcP.h - Private definitions for AsciiSrc object + * + */ + +#ifndef _XawAsciiSrcP_h +#define _XawAsciiSrcP_h + +#include <X11/Xaw3d/TextSrcP.h> +#include <X11/Xaw3d/AsciiSrc.h> + +/************************************************************ + * + * Private declarations. + * + ************************************************************/ + +#ifdef L_tmpnam +#define TMPSIZ L_tmpnam +#else +#define TMPSIZ 32 /* bytes to allocate for tmpnam */ +#endif + +#define MAGIC_VALUE ((XawTextPosition) -1) /* Magic value. */ + +#define streq(a, b) ( strcmp((a), (b)) == 0 ) + +typedef struct _Piece { /* Piece of the text file of BUFSIZ allocated + characters. */ + char * text; /* The text in this buffer. */ + XawTextPosition used; /* The number of characters of this buffer + that have been used. */ + struct _Piece *prev, *next; /* linked list pointers. */ +} Piece; + +/************************************************************ + * + * New fields for the AsciiSrc object class record. + * + ************************************************************/ + +typedef struct _AsciiSrcClassPart { char foo; } AsciiSrcClassPart; + +/* Full class record declaration */ +typedef struct _AsciiSrcClassRec { + ObjectClassPart object_class; + TextSrcClassPart text_src_class; + AsciiSrcClassPart ascii_src_class; +} AsciiSrcClassRec; + +extern AsciiSrcClassRec asciiSrcClassRec; + +/* New fields for the AsciiSrc object record */ + +typedef struct _AsciiSrcPart { + + /* Resources. */ + + char *string; /* either the string, or the + file name, depending upon the type. */ + XawAsciiType type; /* either string or disk. */ + XawTextPosition piece_size; /* Size of text buffer for each piece. */ + Boolean data_compression; /* compress to minimum memory automatically + on save? */ + XtCallbackList callback; /* A callback list to call when the source is + changed. */ + Boolean use_string_in_place; /* Use the string passed in place. */ + int ascii_length; /* length field for ascii string emulation. */ + +#ifdef ASCII_DISK + String filename; /* name of file for Compatability. */ +#endif /* ASCII_DISK */ + +/* Private data. */ + + Boolean is_tempfile; /* Is this a temporary file? */ + Boolean changes; /* Has this file been edited? */ + Boolean allocated_string; /* Have I allocated the + string in ascii_src->string? */ + XawTextPosition length; /* length of file */ + Piece * first_piece; /* first piece of the text. */ +} AsciiSrcPart; + +/**************************************************************** + * + * Full instance record declaration + * + ****************************************************************/ + +typedef struct _AsciiSrcRec { + ObjectPart object; + TextSrcPart text_src; + AsciiSrcPart ascii_src; +} AsciiSrcRec; + +#endif /* _XawAsciiSrcP_h */ diff --git a/src/AsciiText.c b/src/AsciiText.c new file mode 100644 index 0000000..69bd94e --- /dev/null +++ b/src/AsciiText.c @@ -0,0 +1,347 @@ +/* $XConsortium: AsciiText.c,v 1.47 95/06/06 20:50:30 kaleb Exp $ */ + +/* + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +*/ + +/*********************************************************************** + * + * AsciiText Widget + * + ***********************************************************************/ + +/* + * AsciiText.c - Source code for AsciiText Widget. + * + * This Widget is intended to be used as a simple front end to the + * text widget with an ascii source and ascii sink attached to it. + * + * Date: June 29, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#include "Xaw3dP.h" +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/Cardinals.h> +#include <X11/Xaw3d/AsciiTextP.h> +#include <X11/Xaw3d/AsciiSrc.h> +#include <X11/Xaw3d/AsciiSink.h> +#ifdef XAW_INTERNATIONALIZATION +#include <X11/Xaw3d/MultiSrc.h> +#include <X11/Xaw3d/MultiSinkP.h> +#include <X11/Xaw3d/XawImP.h> +#endif + +#define TAB_COUNT 32 + +static void Initialize(), Destroy(); + +AsciiTextClassRec asciiTextClassRec = { + { /* core fields */ + /* superclass */ (WidgetClass) &textClassRec, + /* class_name */ "Text", + /* widget_size */ sizeof(AsciiRec), + /* class_initialize */ XawInitializeWidgetSet, + /* class_part_init */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ XtInheritRealize, + /* actions */ NULL, + /* num_actions */ 0, + /* resources */ NULL, + /* num_resource */ 0, + /* xrm_class */ NULLQUARK, + /* compress_motion */ TRUE, + /* compress_exposure*/ XtExposeGraphicsExpose | XtExposeNoExpose, + /* compress_enterleave*/ TRUE, + /* visible_interest */ FALSE, + /* destroy */ Destroy, + /* resize */ XtInheritResize, + /* expose */ XtInheritExpose, + /* set_values */ NULL, + /* set_values_hook */ NULL, + /* set_values_almost*/ XtInheritSetValuesAlmost, + /* get_values_hook */ NULL, + /* accept_focus */ XtInheritAcceptFocus, + /* version */ XtVersion, + /* callback_private */ NULL, + /* tm_table */ XtInheritTranslations, + /* query_geometry */ XtInheritQueryGeometry + }, + { /* Simple fields */ + /* change_sensitive */ XtInheritChangeSensitive + }, + { /* text fields */ + /* empty */ 0 + }, + { /* ascii fields */ + /* empty */ 0 + } +}; + +WidgetClass asciiTextWidgetClass = (WidgetClass)&asciiTextClassRec; + + +static void +Initialize(request, new, args, num_args) +Widget request, new; +ArgList args; +Cardinal *num_args; +{ + AsciiWidget w = (AsciiWidget) new; + int i; + int tabs[TAB_COUNT], tab; + +#ifdef XAW_INTERNATIONALIZATION + MultiSinkObject sink; +#endif + + /* superclass Initialize can't set the following, + * as it didn't know the source or sink when it was called */ + + if (request->core.height == DEFAULT_TEXT_HEIGHT) + new->core.height = DEFAULT_TEXT_HEIGHT; + + + /* This is the main change for internationalization. */ + +#ifdef XAW_INTERNATIONALIZATION + if ( w->simple.international == True ) { /* The multi* are international. */ + + w->text.source = XtCreateWidget( "textSource", multiSrcObjectClass, + new, args, *num_args ); + w->text.sink = XtCreateWidget( "textSink", multiSinkObjectClass, + new, args, *num_args ); + } + else +#endif + { + + w->text.source = XtCreateWidget( "textSource", asciiSrcObjectClass, + new, args, *num_args ); + w->text.sink = XtCreateWidget( "textSink", asciiSinkObjectClass, + new, args, *num_args ); + } + + if (w->core.height == DEFAULT_TEXT_HEIGHT) + w->core.height = VMargins(w) + XawTextSinkMaxHeight(w->text.sink, 1); + + for (i=0, tab=0 ; i < TAB_COUNT ; i++) + tabs[i] = (tab += 8); + + XawTextSinkSetTabs(w->text.sink, TAB_COUNT, tabs); + + XawTextDisableRedisplay(new); + XawTextEnableRedisplay(new); + + + /* If we are using a MultiSink we need to tell the input method stuff. */ + +#ifdef XAW_INTERNATIONALIZATION + if ( w->simple.international == True ) { + Arg list[4]; + Cardinal ac = 0; + + sink = (MultiSinkObject)w->text.sink; + _XawImRegister( new ); + XtSetArg (list[ac], XtNfontSet, sink->multi_sink.fontset); ac++; + XtSetArg (list[ac], XtNinsertPosition, w->text.insertPos); ac++; + XtSetArg (list[ac], XtNforeground, sink->text_sink.foreground); ac++; + XtSetArg (list[ac], XtNbackground, sink->text_sink.background); ac++; + _XawImSetValues(new, list, ac); + } +#endif +} + +static void +Destroy(w) +Widget w; +{ + /* Disconnect input method */ + +#ifdef XAW_INTERNATIONALIZATION + if ( ((AsciiWidget)w)->simple.international == True ) + _XawImUnregister( w ); +#endif + + if (w == XtParent(((AsciiWidget)w)->text.source)) + XtDestroyWidget( ((AsciiWidget)w)->text.source ); + + if (w == XtParent(((AsciiWidget)w)->text.sink)) + XtDestroyWidget( ((AsciiWidget)w)->text.sink ); +} + +#ifdef ASCII_STRING + +/************************************************************ + * + * Ascii String Compatibility Code. + * + ************************************************************/ + +AsciiStringClassRec asciiStringClassRec = { + { /* core fields */ + /* superclass */ (WidgetClass) &asciiTextClassRec, + /* class_name */ "Text", + /* widget_size */ sizeof(AsciiStringRec), + /* class_initialize */ NULL, + /* class_part_init */ NULL, + /* class_inited */ FALSE, + /* initialize */ NULL, + /* initialize_hook */ NULL, + /* realize */ XtInheritRealize, + /* actions */ NULL, + /* num_actions */ 0, + /* resources */ NULL, + /* num_ resource */ 0, + /* xrm_class */ NULLQUARK, + /* compress_motion */ TRUE, + /* compress_exposure*/ XtExposeGraphicsExpose, + /* compress_enterleave*/ TRUE, + /* visible_interest */ FALSE, + /* destroy */ NULL, + /* resize */ XtInheritResize, + /* expose */ XtInheritExpose, + /* set_values */ NULL, + /* set_values_hook */ NULL, + /* set_values_almost*/ XtInheritSetValuesAlmost, + /* get_values_hook */ NULL, + /* accept_focus */ XtInheritAcceptFocus, + /* version */ XtVersion, + /* callback_private */ NULL, + /* tm_table */ XtInheritTranslations, + /* query_geometry */ XtInheritQueryGeometry + }, + { /* Simple fields */ + /* change_sensitive */ XtInheritChangeSensitive + }, + { /* text fields */ + /* empty */ 0 + }, + { /* ascii fields */ + /* empty */ 0 + } +}; + +WidgetClass asciiStringWidgetClass = (WidgetClass)&asciiStringClassRec; + +#endif /* ASCII_STRING */ + +#ifdef ASCII_DISK + +/************************************************************ + * + * Ascii Disk Compatibility Code. + * + ************************************************************/ + +AsciiDiskClassRec asciiDiskClassRec = { + { /* core fields */ + /* superclass */ (WidgetClass) &asciiTextClassRec, + /* class_name */ "Text", + /* widget_size */ sizeof(AsciiDiskRec), + /* class_initialize */ NULL, + /* class_part_init */ NULL, + /* class_inited */ FALSE, + /* initialize */ NULL, + /* initialize_hook */ NULL, + /* realize */ XtInheritRealize, + /* actions */ NULL, + /* num_actions */ 0, + /* resources */ NULL, + /* num_ resource */ 0, + /* xrm_class */ NULLQUARK, + /* compress_motion */ TRUE, + /* compress_exposure*/ XtExposeGraphicsExpose, + /* compress_enterleave*/ TRUE, + /* visible_interest */ FALSE, + /* destroy */ NULL, + /* resize */ XtInheritResize, + /* expose */ XtInheritExpose, + /* set_values */ NULL, + /* set_values_hook */ NULL, + /* set_values_almost*/ XtInheritSetValuesAlmost, + /* get_values_hook */ NULL, + /* accept_focus */ XtInheritAcceptFocus, + /* version */ XtVersion, + /* callback_private */ NULL, + /* tm_table */ XtInheritTranslations, + /* query_geometry */ XtInheritQueryGeometry + }, + { /* Simple fields */ + /* change_sensitive */ XtInheritChangeSensitive + }, + { /* text fields */ + /* empty */ 0 + }, + { /* ascii fields */ + /* empty */ 0 + } +}; + +WidgetClass asciiDiskWidgetClass = (WidgetClass)&asciiDiskClassRec; + +#endif /* ASCII_DISK */ + + + + + + + + + + + + diff --git a/src/AsciiText.h b/src/AsciiText.h new file mode 100644 index 0000000..c2d88cd --- /dev/null +++ b/src/AsciiText.h @@ -0,0 +1,151 @@ +/* + * $XConsortium: AsciiText.h,v 1.18 94/04/17 20:11:51 kaleb Exp $ + */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/*********************************************************************** + * + * AsciiText Widget + * + ***********************************************************************/ + +/* + * AsciiText.c - Public header file for AsciiText Widget. + * + * This Widget is intended to be used as a simple front end to the + * text widget with an ascii source and ascii sink attached to it. + * + * Date: June 29, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifndef _AsciiText_h +#define _AsciiText_h + +/**************************************************************** + * + * AsciiText widgets + * + ****************************************************************/ + +#include "Xaw3dP.h" +#include <X11/Xaw3d/Text.h> /* AsciiText is a subclass of Text */ +#include <X11/Xaw3d/AsciiSrc.h> +#ifdef XAW_INTERNATIONALIZATION +#include <X11/Xaw3d/MultiSrc.h> +#endif + +/* Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + autoFill AutoFill Boolean False + background Background Pixel XtDefaultBackground + border BorderColor Pixel XtDefaultForeground + borderWidth BorderWidth Dimension 1 + bottomMargin Margin Position 2 + cursor Cursor Cursor xterm + destroyCallback Callback Pointer NULL + displayCaret Output Boolean True + displayPosition TextPosition int 0 + editType EditType XawTextEditType XawtextRead + font Font XFontStruct* Fixed + foreground Foreground Pixel Black + height Height Dimension font height + insertPosition TextPosition int 0 + international International Boolean false + leftMargin Margin Position 2 + mappedWhenManaged MappedWhenManaged Boolean True + resize Resize XawTextResizeMode XawtextResizeNever + rightMargin Margin Position 4 + scrollHorizontal Scroll XawTextScrollMode XawtextScrollNever + scrollVertical Scroll XawTextScrollMode XawtextScrollNever + selectTypes SelectTypes Pointer pos/word/line/par/all + selection Selection Pointer (empty selection) + sensitive Sensitive Boolean True + sink TextSink Widget (none) + source TextSource Widget (none) + string String String NULL + topMargin Margin Position 2 + width Width Dimension 100 + wrap Wrap XawTextWrapMode XawtextWrapNever + x Position Position 0 + y Position Position 0 + + (see also *Src.h and *Sink.h) +*/ + +/* + * Everything else we need is in StringDefs.h or Text.h + */ + +typedef struct _AsciiTextClassRec *AsciiTextWidgetClass; +typedef struct _AsciiRec *AsciiWidget; + +extern WidgetClass asciiTextWidgetClass; + +/************************************************************ + * + * Disk and String Emulation Info. + * + ************************************************************/ + +#ifdef ASCII_STRING +extern WidgetClass asciiStringWidgetClass; +#endif + +#ifdef ASCII_DISK +extern WidgetClass asciiDiskWidgetClass; +#endif + +#endif /* _AsciiText_h */ diff --git a/src/AsciiTextP.h b/src/AsciiTextP.h new file mode 100644 index 0000000..c75890c --- /dev/null +++ b/src/AsciiTextP.h @@ -0,0 +1,166 @@ +/* + * $XConsortium: AsciiTextP.h,v 1.17 94/04/17 20:11:52 kaleb Exp $ + */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/*********************************************************************** + * + * AsciiText Widget + * + ***********************************************************************/ + +/* + * AsciiText.c - Private header file for AsciiText Widget. + * + * This Widget is intended to be used as a simple front end to the + * text widget with an ascii source and ascii sink attached to it. + * + * Date: June 29, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifndef _AsciiTextP_h +#define _AsciiTextP_h + +#include "Xaw3dP.h" +#include <X11/Xaw3d/TextP.h> +#include <X11/Xaw3d/AsciiText.h> +#include <X11/Xaw3d/AsciiSrc.h> +#ifdef XAW_INTERNATIONALIZATION +#include <X11/Xaw3d/MultiSrc.h> +#endif + +typedef struct {int empty;} AsciiClassPart; + +typedef struct _AsciiTextClassRec { + CoreClassPart core_class; + SimpleClassPart simple_class; + TextClassPart text_class; + AsciiClassPart ascii_class; +} AsciiTextClassRec; + +extern AsciiTextClassRec asciiTextClassRec; + +typedef struct { char foo; /* keep compiler happy. */ } AsciiPart; + +typedef struct _AsciiRec { + CorePart core; + SimplePart simple; + TextPart text; + AsciiPart ascii; +} AsciiRec; + +/************************************************************ + * + * Ascii String Emulation widget. + * + ************************************************************/ + +#ifdef ASCII_STRING + +typedef struct {int empty;} AsciiStringClassPart; + +typedef struct _AsciiStringClassRec { + CoreClassPart core_class; + SimpleClassPart simple_class; + TextClassPart text_class; + AsciiClassPart ascii_class; + AsciiStringClassPart string_class; +} AsciiStringClassRec; + +extern AsciiStringClassRec asciiStringClassRec; + +typedef struct { char foo; /* keep compiler happy. */ } AsciiStringPart; + +typedef struct _AsciiStringRec { + CorePart core; + SimplePart simple; + TextPart text; + AsciiPart ascii; + AsciiStringPart ascii_str; +} AsciiStringRec; + +#endif /* ASCII_STRING */ + +#ifdef ASCII_DISK + +/************************************************************ + * + * Ascii Disk Emulation widget. + * + ************************************************************/ + +typedef struct {int empty;} AsciiDiskClassPart; + +typedef struct _AsciiDiskClassRec { + CoreClassPart core_class; + SimpleClassPart simple_class; + TextClassPart text_class; + AsciiClassPart ascii_class; + AsciiDiskClassPart disk_class; +} AsciiDiskClassRec; + +extern AsciiDiskClassRec asciiDiskClassRec; + +typedef struct { char foo; /* keep compiler happy. */ } AsciiDiskPart; + +typedef struct _AsciiDiskRec { + CorePart core; + SimplePart simple; + TextPart text; + AsciiPart ascii; + AsciiDiskPart ascii_disk; +} AsciiDiskRec; +#endif /* ASCII_DISK */ + +#endif /* _AsciiTextP_h */ diff --git a/src/Box.c b/src/Box.c new file mode 100644 index 0000000..640567c --- /dev/null +++ b/src/Box.c @@ -0,0 +1,622 @@ +/* $XConsortium: Box.c,v 1.49 94/04/17 20:11:54 kaleb Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + + +/* + * Box.c - Box composite widget + * + */ + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/BoxP.h> + +/**************************************************************** + * + * Box Resources + * + ****************************************************************/ + +static XtResource resources[] = { + { XtNhSpace, XtCHSpace, XtRDimension, sizeof(Dimension), + XtOffsetOf(BoxRec, box.h_space), + XtRImmediate, (XtPointer)4 }, + { XtNvSpace, XtCVSpace, XtRDimension, sizeof(Dimension), + XtOffsetOf(BoxRec, box.v_space), + XtRImmediate, (XtPointer)4 }, + { XtNorientation, XtCOrientation, XtROrientation, sizeof(XtOrientation), + XtOffsetOf(BoxRec, box.orientation), + XtRImmediate, (XtPointer)XtorientVertical }, +}; + +/**************************************************************** + * + * Full class record constant + * + ****************************************************************/ + +static void ClassInitialize(); +static void Initialize(); +static void Realize(); +static void Resize(); +static Boolean SetValues(); +static XtGeometryResult GeometryManager(); +static void ChangeManaged(); +static XtGeometryResult PreferredSize(); + +BoxClassRec boxClassRec = { + { +/* core_class fields */ + /* superclass */ (WidgetClass) &compositeClassRec, + /* class_name */ "Box", + /* widget_size */ sizeof(BoxRec), + /* class_initialize */ ClassInitialize, + /* class_part_init */ 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 */ NULL, + /* resize */ Resize, + /* 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 */ NULL, + /* query_geometry */ PreferredSize, + /* display_accelerator*/ XtInheritDisplayAccelerator, + /* extension */ NULL + },{ +/* composite_class fields */ + /* geometry_manager */ GeometryManager, + /* change_managed */ ChangeManaged, + /* insert_child */ XtInheritInsertChild, + /* delete_child */ XtInheritDeleteChild, + /* extension */ NULL + },{ +/* Box class fields */ + /* empty */ 0, + } +}; + +WidgetClass boxWidgetClass = (WidgetClass)&boxClassRec; + + +/**************************************************************** + * + * Private Routines + * + ****************************************************************/ + +/* + * + * Do a layout, either actually assigning positions, or just calculating size. + * Returns minimum width and height that will preserve the same layout. + * + */ + +static void DoLayout(bbw, width, height, reply_width, reply_height, position) + BoxWidget bbw; + Dimension width, height; + Dimension *reply_width, *reply_height; /* bounding box */ + Boolean position; /* actually reposition the windows? */ +{ + Boolean vbox = (bbw->box.orientation == XtorientVertical); + Cardinal i; + Dimension w, h; /* Width and height needed for box */ + Dimension lw, lh; /* Width and height needed for current line */ + Dimension bw, bh; /* Width and height needed for current widget */ + Dimension h_space; /* Local copy of bbw->box.h_space */ + Widget widget; /* Current widget */ + int num_mapped_children = 0; + + /* Box width and height */ + h_space = bbw->box.h_space; + + w = 0; + for (i = 0; i < bbw->composite.num_children; i++) { + if ( bbw->composite.children[i]->core.width > w ) + w = bbw->composite.children[i]->core.width; + } + w += h_space; + if ( w > width ) width = w; + h = bbw->box.v_space; + + /* Line width and height */ + lh = 0; + lw = h_space; + + for (i = 0; i < bbw->composite.num_children; i++) { + widget = bbw->composite.children[i]; + if (widget->core.managed) { + if (widget->core.mapped_when_managed) num_mapped_children++; + /* Compute widget width */ + bw = widget->core.width + 2*widget->core.border_width + h_space; + if ((Dimension)(lw + bw) > width) { + if (lw > h_space) { + /* At least one widget on this line, and + * can't fit any more. Start new line if vbox. + */ + AssignMax(w, lw); + if (vbox) { + h += lh + bbw->box.v_space; + lh = 0; + lw = h_space; + } + } + else if (!position) { + /* too narrow for this widget; we'll assume we can grow */ + DoLayout(bbw, lw + bw, height, reply_width, + reply_height, position); + return; + } + } + if (position && (lw != (Dimension)widget->core.x || h != (Dimension)widget->core.y)) { + /* It would be nice to use window gravity, but there isn't + * sufficient fine-grain control to nicely handle all + * situations (e.g. when only the height changes -- + * a common case). Explicit unmapping is a cheap hack + * to speed things up & avoid the visual jitter as + * things slide around. + * + * %%% perhaps there should be a client resource to + * control this. If so, we'll have to optimize to + * perform the moves from the correct end so we don't + * force extra exposures as children occlude each other. + */ + if (XtIsRealized(widget) && widget->core.mapped_when_managed) + XUnmapWindow( XtDisplay(widget), XtWindow(widget) ); + XtMoveWidget(widget, (int)lw, (int)h); + } + lw += bw; + bh = widget->core.height + 2*widget->core.border_width; + AssignMax(lh, bh); + } /* if managed */ + } /* for */ + + if (!vbox && width && lw > width && lh < height) { + /* reduce width if too wide and height not filled */ + Dimension sw = lw, sh = lh; + Dimension width_needed = 0; + XtOrientation orientation = bbw->box.orientation; + bbw->box.orientation = XtorientVertical; + while (sh < height && sw > width) { + width_needed = sw; + DoLayout(bbw, sw-1, height, &sw, &sh, False); + } + if (sh < height) width_needed = sw; + if (width_needed != lw) { + DoLayout(bbw,width_needed,height,reply_width,reply_height,position); + bbw->box.orientation = orientation; + return; + } + bbw->box.orientation = orientation; + } + if ( vbox && ( ( width < w ) || ( width < lw ) ) ) { + AssignMax(w, lw); + DoLayout( bbw, w, height, reply_width, reply_height, position ); + return; + } + if (position && XtIsRealized((Widget)bbw)) { + if (bbw->composite.num_children == num_mapped_children) + XMapSubwindows( XtDisplay((Widget)bbw), XtWindow((Widget)bbw) ); + else { + int i = bbw->composite.num_children; + Widget *childP = bbw->composite.children; + for (; i > 0; childP++, i--) + if (XtIsRealized(*childP) && XtIsManaged(*childP) && + (*childP)->core.mapped_when_managed) + XtMapWidget(*childP); + } + } + + /* Finish off last line */ + if (lw > h_space) { + AssignMax(w, lw); + h += lh + bbw->box.v_space; + } + + *reply_width = Max(w, 1); + *reply_height = Max(h, 1); +} + +/* + * + * Calculate preferred size, given constraining box, caching it in the widget. + * + */ + +static XtGeometryResult PreferredSize(widget, constraint, preferred) + Widget widget; + XtWidgetGeometry *constraint, *preferred; +{ + BoxWidget w = (BoxWidget)widget; + Dimension width /*, height */; + Dimension preferred_width = w->box.preferred_width; + Dimension preferred_height = w->box.preferred_height; + + constraint->request_mode &= CWWidth | CWHeight; + + if (constraint->request_mode == 0) + /* parent isn't going to change w or h, so nothing to re-compute */ + return XtGeometryYes; + + if (constraint->request_mode == w->box.last_query_mode && + (!(constraint->request_mode & CWWidth) || + constraint->width == w->box.last_query_width) && + (!(constraint->request_mode & CWHeight) || + constraint->height == w->box.last_query_height)) { + /* same query; current preferences are still valid */ + preferred->request_mode = CWWidth | CWHeight; + preferred->width = preferred_width; + preferred->height = preferred_height; + if (constraint->request_mode == (CWWidth | CWHeight) && + constraint->width == preferred_width && + constraint->height == preferred_height) + return XtGeometryYes; + else + return XtGeometryAlmost; + } + + /* else gotta do it the long way... + I have a preference for tall and narrow, so if my width is + constrained, I'll accept it; otherwise, I'll compute the minimum + width that will fit me within the height constraint */ + + w->box.last_query_mode = constraint->request_mode; + w->box.last_query_width = constraint->width; + w->box.last_query_height= constraint->height; + + if (constraint->request_mode & CWWidth) + width = constraint->width; + else /* if (constraint->request_mode & CWHeight) */ { + /* let's see if I can become any narrower */ + width = 0; + constraint->width = 65535; + } + + /* height is currently ignored by DoLayout. + height = (constraint->request_mode & CWHeight) ? constraint->height + : *preferred_height; + */ + DoLayout(w, width, (Dimension)0, + &preferred_width, &preferred_height, FALSE); + + if (constraint->request_mode & CWHeight && + preferred_height > constraint->height) { + /* find minimum width for this height */ + if (preferred_width > constraint->width) { + /* punt; over-constrained */ + } + else { + width = preferred_width; + do { /* find some width big enough to stay within this height */ + width *= 2; + if (width > constraint->width) width = constraint->width; + DoLayout(w, width, 0, &preferred_width, &preferred_height, FALSE); + } while (preferred_height > constraint->height && + width < constraint->width); + if (width != constraint->width) { + do { /* find minimum width */ + width = preferred_width; + DoLayout(w, preferred_width-1, 0, + &preferred_width, &preferred_height, FALSE); + } while (preferred_height < constraint->height); + /* one last time */ + DoLayout(w, width, 0, &preferred_width, &preferred_height, FALSE); + } + } + } + + preferred->request_mode = CWWidth | CWHeight; + preferred->width = w->box.preferred_width = preferred_width; + preferred->height = w->box.preferred_height = preferred_height; + + if (constraint->request_mode == (CWWidth|CWHeight) + && constraint->width == preferred_width + && constraint->height == preferred_height) + return XtGeometryYes; + else + return XtGeometryAlmost; + +} + +/* + * + * Actually layout the box + * + */ + +static void Resize(w) + Widget w; +{ + Dimension junk; + + DoLayout((BoxWidget)w, w->core.width, w->core.height, &junk, &junk, TRUE); + +} /* Resize */ + +/* + * + * Try to do a new layout within the current width and height; + * if that fails try to resize and do it within the box returne + * by PreferredSize. + * + * TryNewLayout just says if it's possible, and doesn't actually move the kids + */ + +static Boolean TryNewLayout(bbw) + BoxWidget bbw; +{ + Dimension preferred_width, preferred_height; + Dimension proposed_width, proposed_height; + int iterations; + + DoLayout( bbw, bbw->core.width, bbw->core.height, + &preferred_width, &preferred_height, FALSE ); + + /* at this point, preferred_width is guaranteed to not be greater + than bbw->core.width unless some child is larger, so there's no + point in re-computing another layout */ + + if ((bbw->core.width == preferred_width) && + (bbw->core.height == preferred_height)) { + /* Same size */ + return (TRUE); + } + + /* let's see if our parent will go for a new size. */ + iterations = 0; + proposed_width = preferred_width; + proposed_height = preferred_height; + do { + switch (XtMakeResizeRequest((Widget)bbw,proposed_width,proposed_height, + &proposed_width, &proposed_height)) + { + case XtGeometryYes: + return (TRUE); + + case XtGeometryNo: + if (iterations > 0) + /* protect from malicious parents who change their minds */ + DoLayout( bbw, bbw->core.width, bbw->core.height, + &preferred_width, &preferred_height, FALSE ); + if ((preferred_width <= bbw->core.width) && + (preferred_height <= bbw->core.height)) + return (TRUE); + else + return (FALSE); + + case XtGeometryAlmost: + if (proposed_height >= preferred_height && + proposed_width >= preferred_width) { + + /* + * Take it, and assume the parent knows what it is doing. + * + * The parent must accept this since it was returned in + * almost. + * + */ + (void) XtMakeResizeRequest( (Widget)bbw, + proposed_width, proposed_height, + &proposed_width, &proposed_height); + return(TRUE); + } + else if (proposed_width != preferred_width) { + /* recalc bounding box; height might change */ + DoLayout(bbw, proposed_width, 0, + &preferred_width, &preferred_height, FALSE); + proposed_height = preferred_height; + } + else { /* proposed_height != preferred_height */ + XtWidgetGeometry constraints, reply; + constraints.request_mode = CWHeight; + constraints.height = proposed_height; + (void)PreferredSize((Widget)bbw, &constraints, &reply); + proposed_width = preferred_width; + } + break; + + case XtGeometryDone: /* ??? */ + default: + break; + } + iterations++; + } while (iterations < 10); + return (FALSE); +} + +/* + * + * Geometry Manager + * + * 'reply' is unused; we say only yeay or nay, never almost. + * + */ + +/*ARGSUSED*/ +static XtGeometryResult GeometryManager(w, request, reply) + Widget w; + XtWidgetGeometry *request; + XtWidgetGeometry *reply; /* RETURN */ + +{ + Dimension width, height, borderWidth; + BoxWidget bbw; + + /* Position request always denied */ + if ((request->request_mode & CWX && request->x != w->core.x) || + (request->request_mode & CWY && request->y != w->core.y)) + return (XtGeometryNo); + + /* Size changes must see if the new size can be accomodated */ + if (request->request_mode & (CWWidth | CWHeight | CWBorderWidth)) { + + /* Make all three fields in the request valid */ + if ((request->request_mode & CWWidth) == 0) + request->width = w->core.width; + if ((request->request_mode & CWHeight) == 0) + request->height = w->core.height; + if ((request->request_mode & CWBorderWidth) == 0) + request->border_width = w->core.border_width; + + /* Save current size and set to new size */ + width = w->core.width; + height = w->core.height; + borderWidth = w->core.border_width; + w->core.width = request->width; + w->core.height = request->height; + w->core.border_width = request->border_width; + + /* Decide if new layout works: (1) new widget is smaller, + (2) new widget fits in existing Box, (3) Box can be + expanded to allow new widget to fit */ + + bbw = (BoxWidget) w->core.parent; + +/* whenever a child changes his geometry, we attempt to + * change ours to be the minimum enclosing size... + if (((request->width + request->border_width <= width + borderWidth) && + (request->height + request->border_width <= height + borderWidth)) + || bbw->box.preferred_width < bbw->core.width + || bbw->box.preferred_height < bbw->core.height + || TryNewLayout(bbw)) { + */ + if (TryNewLayout(bbw)) { + /* Fits in existing or new space, relayout */ + (*XtClass((Widget)bbw)->core_class.resize)((Widget)bbw); + return (XtGeometryYes); + } else { + /* Cannot satisfy request, change back to original geometry */ + w->core.width = width; + w->core.height = height; + w->core.border_width = borderWidth; + return (XtGeometryNo); + } + }; /* if any size changes requested */ + + /* Any stacking changes don't make a difference, so allow if that's all */ + return (XtGeometryYes); +} + +static void ChangeManaged(w) + Widget w; +{ + /* Reconfigure the box */ + (void) TryNewLayout((BoxWidget)w); + Resize(w); +} + +static void ClassInitialize() +{ + XawInitializeWidgetSet(); + XtAddConverter( XtRString, XtROrientation, XmuCvtStringToOrientation, + (XtConvertArgList)NULL, (Cardinal)0 ); +} + +/* ARGSUSED */ +static void Initialize(request, new, args, num_args) + Widget request, new; + ArgList args; + Cardinal *num_args; +{ + BoxWidget newbbw = (BoxWidget)new; + + newbbw->box.last_query_mode = CWWidth | CWHeight; + newbbw->box.last_query_width = newbbw->box.last_query_height = 0; + newbbw->box.preferred_width = Max(newbbw->box.h_space, 1); + newbbw->box.preferred_height = Max(newbbw->box.v_space, 1); + + if (newbbw->core.width == 0) + newbbw->core.width = newbbw->box.preferred_width; + + if (newbbw->core.height == 0) + newbbw->core.height = newbbw->box.preferred_height; + +} /* Initialize */ + +static void Realize(w, valueMask, attributes) + Widget w; + Mask *valueMask; + XSetWindowAttributes *attributes; +{ + attributes->bit_gravity = NorthWestGravity; + *valueMask |= CWBitGravity; + + XtCreateWindow( w, (unsigned)InputOutput, (Visual *)CopyFromParent, + *valueMask, attributes); +} /* Realize */ + +/* ARGSUSED */ +static Boolean SetValues(current, request, new, args, num_args) + Widget current, request, new; + ArgList args; + Cardinal *num_args; +{ + /* need to relayout if h_space or v_space change */ + + return False; +} diff --git a/src/Box.h b/src/Box.h new file mode 100644 index 0000000..b303c99 --- /dev/null +++ b/src/Box.h @@ -0,0 +1,98 @@ +/* +* $XConsortium: Box.h,v 1.22 94/04/17 20:11:55 rws Exp $ +*/ + + +/*********************************************************** + +Copyright (c) 1987, 1988 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _XawBox_h +#define _XawBox_h + +#include <X11/Xmu/Converters.h> + +/*********************************************************************** + * + * Box Widget (subclass of CompositeClass) + * + ***********************************************************************/ + +/* Parameters: + + Name Class RepType Default Value + ---- ----- ------- ------------- + background Background Pixel XtDefaultBackground + border BorderColor Pixel XtDefaultForeground + borderWidth BorderWidth Dimension 1 + destroyCallback Callback Pointer NULL + hSpace HSpace Dimension 4 + height Height Dimension 0 + mappedWhenManaged MappedWhenManaged Boolean True + orientation Orientation XtOrientation vertical + vSpace VSpace Dimension 4 + width Width Dimension 0 + x Position Position 0 + y Position Position 0 + +*/ + + +/* New fields */ +#ifndef _XtStringDefs_h_ +#define XtNhSpace "hSpace" +#define XtNvSpace "vSpace" +#endif + +/* Class record constants */ + +extern WidgetClass boxWidgetClass; + +typedef struct _BoxClassRec *BoxWidgetClass; +typedef struct _BoxRec *BoxWidget; + +#endif /* _XawBox_h */ diff --git a/src/BoxP.h b/src/BoxP.h new file mode 100644 index 0000000..a2c19e6 --- /dev/null +++ b/src/BoxP.h @@ -0,0 +1,108 @@ +/* +* $XConsortium: BoxP.h,v 1.18 94/04/17 20:11:56 kaleb Exp $ +*/ + + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * BoxP.h - Private definitions for Box widget + * + */ + +#ifndef _XawBoxP_h +#define _XawBoxP_h + +/*********************************************************************** + * + * Box Widget Private Data + * + ***********************************************************************/ + +#include <X11/Xaw3d/Box.h> +#include <X11/Xmu/Converters.h> + +/* New fields for the Box widget class record */ +typedef struct {int empty;} BoxClassPart; + +/* Full class record declaration */ +typedef struct _BoxClassRec { + CoreClassPart core_class; + CompositeClassPart composite_class; + BoxClassPart box_class; +} BoxClassRec; + +extern BoxClassRec boxClassRec; + +/* New fields for the Box widget record */ +typedef struct { + /* resources */ + Dimension h_space, v_space; + XtOrientation orientation; + + /* private state */ + Dimension preferred_width, preferred_height; + Dimension last_query_width, last_query_height; + XtGeometryMask last_query_mode; +} BoxPart; + + +/**************************************************************** + * + * Full instance record declaration + * + ****************************************************************/ + +typedef struct _BoxRec { + CorePart core; + CompositePart composite; + BoxPart box; +} BoxRec; + +#endif /* _XawBoxP_h */ diff --git a/src/Cardinals.h b/src/Cardinals.h new file mode 100644 index 0000000..716483f --- /dev/null +++ b/src/Cardinals.h @@ -0,0 +1,44 @@ +/* $XConsortium: Cardinals.h,v 1.6 94/04/17 20:11:57 jim Exp $ */ +/* + +Copyright (c) 1985, 1986, 1987 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +#ifndef _Cardinals_h +#define _Cardinals_h + +#define ZERO ((Cardinal)0) +#define ONE ((Cardinal)1) +#define TWO ((Cardinal)2) +#define THREE ((Cardinal)3) +#define FOUR ((Cardinal)4) +#define FIVE ((Cardinal)5) +#define SIX ((Cardinal)6) +#define SEVEN ((Cardinal)7) +#define EIGHT ((Cardinal)8) +#define NINE ((Cardinal)9) +#define TEN ((Cardinal)10) + +#endif /* _Cardinals_h */ diff --git a/src/Command.c b/src/Command.c new file mode 100644 index 0000000..5fe16b6 --- /dev/null +++ b/src/Command.c @@ -0,0 +1,629 @@ +/* $XConsortium: Command.c,v 1.79 94/04/17 20:11:58 kaleb Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * Command.c - Command button widget + */ + +#include "Xaw3dP.h" +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/CommandP.h> +#include <X11/Xmu/Converters.h> +#include <X11/extensions/shape.h> + +#define DEFAULT_HIGHLIGHT_THICKNESS 2 +#define DEFAULT_SHAPE_HIGHLIGHT 32767 + +/**************************************************************** + * + * Full class record constant + * + ****************************************************************/ + +/* Private Data */ + +static char defaultTranslations[] = + "<EnterWindow>: highlight() \n\ + <LeaveWindow>: reset() \n\ + <Btn1Down>: set() \n\ + <Btn1Up>: notify() unset() "; + +#define offset(field) XtOffsetOf(CommandRec, field) +static XtResource resources[] = { + {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), + offset(command.callbacks), XtRCallback, (XtPointer)NULL}, + {XtNhighlightThickness, XtCThickness, XtRDimension, sizeof(Dimension), + offset(command.highlight_thickness), XtRImmediate, + (XtPointer) DEFAULT_SHAPE_HIGHLIGHT}, + {XtNshapeStyle, XtCShapeStyle, XtRShapeStyle, sizeof(int), + offset(command.shape_style), XtRImmediate, (XtPointer)XawShapeRectangle}, + {XtNcornerRoundPercent, XtCCornerRoundPercent, XtRDimension, + sizeof(Dimension), offset(command.corner_round), XtRImmediate, + (XtPointer) 25}, + {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension), + XtOffsetOf(RectObjRec,rectangle.border_width), XtRImmediate, + (XtPointer) 0} +}; +#undef offset + +static Boolean SetValues(); +static void Initialize(), Redisplay(), Set(), Reset(), Notify(), Unset(); +static void Highlight(), Unhighlight(), Destroy(), PaintCommandWidget(); +static void ClassInitialize(); +static Boolean ShapeButton(); +static void Realize(), Resize(); + +static XtActionsRec actionsList[] = { + {"set", Set}, + {"notify", Notify}, + {"highlight", Highlight}, + {"reset", Reset}, + {"unset", Unset}, + {"unhighlight", Unhighlight} +}; + +#define SuperClass ((LabelWidgetClass)&labelClassRec) + +CommandClassRec commandClassRec = { + { + (WidgetClass) SuperClass, /* superclass */ + "Command", /* class_name */ + sizeof(CommandRec), /* size */ + ClassInitialize, /* class_initialize */ + NULL, /* class_part_initialize */ + FALSE, /* class_inited */ + Initialize, /* initialize */ + NULL, /* initialize_hook */ + Realize, /* realize */ + actionsList, /* actions */ + XtNumber(actionsList), /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* resource_count */ + NULLQUARK, /* xrm_class */ + FALSE, /* compress_motion */ + TRUE, /* compress_exposure */ + TRUE, /* compress_enterleave */ + FALSE, /* visible_interest */ + Destroy, /* destroy */ + Resize, /* resize */ + Redisplay, /* expose */ + SetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + defaultTranslations, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL /* extension */ + }, /* CoreClass fields initialization */ + { + XtInheritChangeSensitive /* change_sensitive */ + }, /* SimpleClass fields initialization */ + { + XtInheritXaw3dShadowDraw, /* shadowdraw */ + }, /* ThreeD Class fields initialization */ + { + 0, /* field not used */ + }, /* LabelClass fields initialization */ + { + 0, /* field not used */ + }, /* CommandClass fields initialization */ +}; + + /* for public consumption */ +WidgetClass commandWidgetClass = (WidgetClass) &commandClassRec; + +/**************************************************************** + * + * Private Procedures + * + ****************************************************************/ + +static GC +Get_GC(cbw, fg, bg) +CommandWidget cbw; +Pixel fg, bg; +{ + XGCValues values; + + values.foreground = fg; + values.background = bg; + values.font = cbw->label.font->fid; + values.cap_style = CapProjecting; + + if (cbw->command.highlight_thickness > 1 ) + values.line_width = cbw->command.highlight_thickness; + else + values.line_width = 0; + +#ifdef XAW_INTERNATIONALIZATION + if ( cbw->simple.international == True ) + return XtAllocateGC((Widget)cbw, 0, + (GCForeground|GCBackground|GCLineWidth|GCCapStyle), + &values, GCFont, 0 ); + else +#endif + return XtGetGC((Widget)cbw, + (GCForeground|GCBackground|GCFont|GCLineWidth|GCCapStyle), + &values); +} + + +/* ARGSUSED */ +static void +Initialize(request, new, args, num_args) +Widget request, new; +ArgList args; /* unused */ +Cardinal *num_args; /* unused */ +{ + CommandWidget cbw = (CommandWidget) new; + int shape_event_base, shape_error_base; + + if (cbw->command.shape_style != XawShapeRectangle + && !XShapeQueryExtension(XtDisplay(new), &shape_event_base, + &shape_error_base)) + cbw->command.shape_style = XawShapeRectangle; + if (cbw->command.highlight_thickness == DEFAULT_SHAPE_HIGHLIGHT) { + if (cbw->command.shape_style != XawShapeRectangle) + cbw->command.highlight_thickness = 0; + else + cbw->command.highlight_thickness = DEFAULT_HIGHLIGHT_THICKNESS; + } + + if (cbw->command.shape_style != XawShapeRectangle) { + cbw->threeD.shadow_width = 0; + cbw->core.border_width = 1; + } + cbw->command.shadow_width = cbw->threeD.shadow_width; + + cbw->command.normal_GC = Get_GC(cbw, cbw->label.foreground, + cbw->core.background_pixel); + cbw->command.inverse_GC = Get_GC(cbw, cbw->core.background_pixel, + cbw->label.foreground); + XtReleaseGC(new, cbw->label.normal_GC); + cbw->label.normal_GC = cbw->command.normal_GC; + + cbw->command.set = FALSE; + cbw->command.highlighted = HighlightNone; +} + +static Region +HighlightRegion(cbw) +CommandWidget cbw; +{ + static Region outerRegion = NULL, innerRegion, emptyRegion; + Dimension s = cbw->threeD.shadow_width; + XRectangle rect; + + if (cbw->command.highlight_thickness == 0 || + cbw->command.highlight_thickness > + (Dimension) ((Dimension) Min(cbw->core.width, cbw->core.height)/2)) + return(NULL); + + if (outerRegion == NULL) { + /* save time by allocating scratch regions only once. */ + outerRegion = XCreateRegion(); + innerRegion = XCreateRegion(); + emptyRegion = XCreateRegion(); + } + + rect.x = rect.y = s; + rect.width = cbw->core.width - 2 * s; + rect.height = cbw->core.height - 2 * s; + XUnionRectWithRegion( &rect, emptyRegion, outerRegion ); + rect.x = rect.y += cbw->command.highlight_thickness; + rect.width -= cbw->command.highlight_thickness * 2; + rect.height -= cbw->command.highlight_thickness * 2; + XUnionRectWithRegion( &rect, emptyRegion, innerRegion ); + XSubtractRegion( outerRegion, innerRegion, outerRegion ); + return outerRegion; +} + +/*************************** +* +* Action Procedures +* +***************************/ + +/* ARGSUSED */ +static void +Set(w,event,params,num_params) +Widget w; +XEvent *event; +String *params; /* unused */ +Cardinal *num_params; /* unused */ +{ + CommandWidget cbw = (CommandWidget)w; + + if (cbw->command.set) + return; + + cbw->command.set= TRUE; + if (XtIsRealized(w)) + PaintCommandWidget(w, event, (Region) NULL, TRUE); +} + +/* ARGSUSED */ +static void +Unset(w,event,params,num_params) +Widget w; +XEvent *event; +String *params; /* unused */ +Cardinal *num_params; +{ + CommandWidget cbw = (CommandWidget)w; + + if (!cbw->command.set) + return; + + cbw->command.set = FALSE; + if (XtIsRealized(w)) { + XClearWindow(XtDisplay(w), XtWindow(w)); + PaintCommandWidget(w, event, (Region) NULL, TRUE); + } +} + +/* ARGSUSED */ +static void +Reset(w,event,params,num_params) +Widget w; +XEvent *event; +String *params; /* unused */ +Cardinal *num_params; /* unused */ +{ + CommandWidget cbw = (CommandWidget)w; + + if (cbw->command.set) { + cbw->command.highlighted = HighlightNone; + Unset(w, event, params, num_params); + } else + Unhighlight(w, event, params, num_params); +} + +/* ARGSUSED */ +static void +Highlight(w,event,params,num_params) +Widget w; +XEvent *event; +String *params; +Cardinal *num_params; +{ + CommandWidget cbw = (CommandWidget)w; + + if ( *num_params == (Cardinal) 0) + cbw->command.highlighted = HighlightWhenUnset; + else { + if ( *num_params != (Cardinal) 1) + XtWarning("Too many parameters passed to highlight action table."); + switch (params[0][0]) { + case 'A': + case 'a': + cbw->command.highlighted = HighlightAlways; + break; + default: + cbw->command.highlighted = HighlightWhenUnset; + break; + } + } + + if (XtIsRealized(w)) + PaintCommandWidget(w, event, HighlightRegion(cbw), TRUE); +} + +/* ARGSUSED */ +static void +Unhighlight(w,event,params,num_params) +Widget w; +XEvent *event; +String *params; /* unused */ +Cardinal *num_params; /* unused */ +{ + CommandWidget cbw = (CommandWidget)w; + + cbw->command.highlighted = HighlightNone; + if (XtIsRealized(w)) + PaintCommandWidget(w, event, HighlightRegion(cbw), TRUE); +} + +/* ARGSUSED */ +static void +Notify(w,event,params,num_params) +Widget w; +XEvent *event; +String *params; /* unused */ +Cardinal *num_params; /* unused */ +{ + CommandWidget cbw = (CommandWidget)w; + + /* check to be sure state is still Set so that user can cancel + the action (e.g. by moving outside the window, in the default + bindings. + */ + if (cbw->command.set) + XtCallCallbackList(w, cbw->command.callbacks, (XtPointer) NULL); +} + +/* + * Repaint the widget window + */ + +/************************ +* +* REDISPLAY (DRAW) +* +************************/ + +/* ARGSUSED */ +static void +Redisplay(w, event, region) +Widget w; +XEvent *event; +Region region; +{ + PaintCommandWidget(w, event, region, FALSE); +} + +/* Function Name: PaintCommandWidget + * Description: Paints the command widget. + * Arguments: w - the command widget. + * region - region to paint (passed to the superclass). + * change - did it change either set or highlight state? + * Returns: none + */ + +static void +PaintCommandWidget(w, event, region, change) +Widget w; +XEvent *event; +Region region; +Boolean change; +{ + CommandWidget cbw = (CommandWidget) w; + CommandWidgetClass cwclass = (CommandWidgetClass) XtClass (w); + Boolean very_thick; + GC norm_gc, rev_gc; + Dimension s = cbw->threeD.shadow_width; + + very_thick = cbw->command.highlight_thickness > + (Dimension)((Dimension) Min(cbw->core.width, cbw->core.height)/2); + + if (cbw->command.set) { + cbw->label.normal_GC = cbw->command.inverse_GC; + XFillRectangle(XtDisplay(w), XtWindow(w), cbw->command.normal_GC, + s, s, cbw->core.width - 2 * s, cbw->core.height - 2 * s); + region = NULL; /* Force label to repaint text. */ + } + else + cbw->label.normal_GC = cbw->command.normal_GC; + + if (cbw->command.highlight_thickness <= 0) + { + (*SuperClass->core_class.expose) (w, event, region); + (*cwclass->threeD_class.shadowdraw) (w, event, region, cbw->threeD.relief, !cbw->command.set); + return; + } + +/* + * If we are set then use the same colors as if we are not highlighted. + */ + + if (cbw->command.set == (cbw->command.highlighted == HighlightNone)) { + norm_gc = cbw->command.inverse_GC; + rev_gc = cbw->command.normal_GC; + } + else { + norm_gc = cbw->command.normal_GC; + rev_gc = cbw->command.inverse_GC; + } + + if ( !( (!change && (cbw->command.highlighted == HighlightNone)) || + ((cbw->command.highlighted == HighlightWhenUnset) && + (cbw->command.set))) ) { + if (very_thick) { + cbw->label.normal_GC = norm_gc; /* Give the label the right GC. */ + XFillRectangle(XtDisplay(w),XtWindow(w), rev_gc, + s, s, cbw->core.width - 2 * s, cbw->core.height - 2 * s); + } + else { + /* wide lines are centered on the path, so indent it */ + int offset = cbw->command.highlight_thickness/2; + XDrawRectangle(XtDisplay(w),XtWindow(w), rev_gc, s + offset, s + offset, + cbw->core.width - cbw->command.highlight_thickness - 2 * s, + cbw->core.height - cbw->command.highlight_thickness - 2 * s); + } + } + (*SuperClass->core_class.expose) (w, event, region); + (*cwclass->threeD_class.shadowdraw) (w, event, region, cbw->threeD.relief, !cbw->command.set); +} + +static void +Destroy(w) +Widget w; +{ + CommandWidget cbw = (CommandWidget) w; + + /* so Label can release it */ + if (cbw->label.normal_GC == cbw->command.normal_GC) + XtReleaseGC( w, cbw->command.inverse_GC ); + else + XtReleaseGC( w, cbw->command.normal_GC ); +} + +/* + * Set specified arguments into widget + */ + +/* ARGSUSED */ +static Boolean +SetValues (current, request, new, args, num_args) +Widget current, request, new; +ArgList args; +Cardinal *num_args; +{ + CommandWidget oldcbw = (CommandWidget) current; + CommandWidget cbw = (CommandWidget) new; + Boolean redisplay = False; + + if ( oldcbw->core.sensitive != cbw->core.sensitive && !cbw->core.sensitive) { + /* about to become insensitive */ + cbw->command.set = FALSE; + cbw->command.highlighted = HighlightNone; + redisplay = TRUE; + } + + if ( (oldcbw->label.foreground != cbw->label.foreground) || + (oldcbw->core.background_pixel != cbw->core.background_pixel) || + (oldcbw->command.highlight_thickness != + cbw->command.highlight_thickness) || + (oldcbw->label.font != cbw->label.font) ) + { + if (oldcbw->label.normal_GC == oldcbw->command.normal_GC) + /* Label has release one of these */ + XtReleaseGC(new, cbw->command.inverse_GC); + else + XtReleaseGC(new, cbw->command.normal_GC); + + cbw->command.normal_GC = Get_GC(cbw, cbw->label.foreground, + cbw->core.background_pixel); + cbw->command.inverse_GC = Get_GC(cbw, cbw->core.background_pixel, + cbw->label.foreground); + XtReleaseGC(new, cbw->label.normal_GC); + cbw->label.normal_GC = (cbw->command.set + ? cbw->command.inverse_GC + : cbw->command.normal_GC); + + redisplay = True; + } + + if (cbw->threeD.shadow_width != oldcbw->threeD.shadow_width) { + cbw->command.shadow_width = cbw->threeD.shadow_width; + redisplay = True; + } + if (cbw->core.border_width != oldcbw->core.border_width) + redisplay = True; + + if ( XtIsRealized(new) + && oldcbw->command.shape_style != cbw->command.shape_style + && !ShapeButton(cbw, TRUE)) + { + cbw->command.shape_style = oldcbw->command.shape_style; + } + + if (cbw->command.shape_style != XawShapeRectangle) { + cbw->threeD.shadow_width = 0; + ShapeButton(cbw, FALSE); + redisplay = True; + } + if (cbw->command.shape_style == XawShapeRectangle) { + cbw->threeD.shadow_width = + (cbw->command.shadow_width) ? cbw->command.shadow_width : 2; + redisplay = True; + } + + return (redisplay); +} + +static void ClassInitialize() +{ + XawInitializeWidgetSet(); + XtSetTypeConverter( XtRString, XtRShapeStyle, XmuCvtStringToShapeStyle, + (XtConvertArgList)NULL, 0, XtCacheNone, (XtDestructor)NULL ); +} + + +static Boolean +ShapeButton(cbw, checkRectangular) +CommandWidget cbw; +Boolean checkRectangular; +{ + Dimension corner_size = 0; + + if ( (cbw->command.shape_style == XawShapeRoundedRectangle) ) { + corner_size = (cbw->core.width < cbw->core.height) ? cbw->core.width + : cbw->core.height; + corner_size = (int) (corner_size * cbw->command.corner_round) / 100; + } + + if (checkRectangular || cbw->command.shape_style != XawShapeRectangle) { + if (!XmuReshapeWidget((Widget) cbw, cbw->command.shape_style, + corner_size, corner_size)) { + cbw->command.shape_style = XawShapeRectangle; + return(False); + } + } + return(TRUE); +} + +static void Realize(w, valueMask, attributes) + Widget w; + Mask *valueMask; + XSetWindowAttributes *attributes; +{ + (*commandWidgetClass->core_class.superclass->core_class.realize) + (w, valueMask, attributes); + + ShapeButton( (CommandWidget) w, FALSE); +} + +static void Resize(w) + Widget w; +{ + if (XtIsRealized(w)) + ShapeButton( (CommandWidget) w, FALSE); + + (*commandWidgetClass->core_class.superclass->core_class.resize)(w); +} diff --git a/src/Command.h b/src/Command.h new file mode 100644 index 0000000..43a8ef4 --- /dev/null +++ b/src/Command.h @@ -0,0 +1,118 @@ +/* $XConsortium: Command.h,v 1.29 94/04/17 20:11:59 kaleb Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _XawCommand_h +#define _XawCommand_h + +#include <X11/Xaw3d/Label.h> + +/* Command widget resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + accelerators Accelerators AcceleratorTable NULL + ancestorSensitive AncestorSensitive Boolean True + background Background Pixel XtDefaultBackground + backgroundPixmap Pixmap Pixmap XtUnspecifiedPixmap + bitmap Pixmap Pixmap None + borderColor BorderColor Pixel XtDefaultForeground + borderPixmap Pixmap Pixmap XtUnspecifiedPixmap + borderWidth BorderWidth Dimension 1 + callback Callback XtCallbackList NULL + colormap Colormap Colormap parent's colormap + cornerRoundPercent CornerRoundPercent Dimension 25 + cursor Cursor Cursor None + cursorName Cursor String NULL + depth Depth int parent's depth + destroyCallback Callback XtCallbackList NULL + encoding Encoding UnsignedChar XawTextEncoding8bit + font Font XFontStruct* XtDefaultFont + foreground Foreground Pixel XtDefaultForeground + height Height Dimension text height + highlightThickness Thickness Dimension 0 if shaped, else 2 + insensitiveBorder Insensitive Pixmap Gray + internalHeight Height Dimension 2 + internalWidth Width Dimension 4 + justify Justify XtJustify XtJustifyCenter + label Label String NULL + leftBitmap LeftBitmap Pixmap None + mappedWhenManaged MappedWhenManaged Boolean True + pointerColor Foreground Pixel XtDefaultForeground + pointerColorBackground Background Pixel XtDefaultBackground + resize Resize Boolean True + screen Screen Screen parent's Screen + sensitive Sensitive Boolean True + shapeStyle ShapeStyle ShapeStyle Rectangle + translations Translations TranslationTable see doc or source + width Width Dimension text width + x Position Position 0 + y Position Position 0 + +*/ + +#define XtNhighlightThickness "highlightThickness" + +#define XtNshapeStyle "shapeStyle" +#define XtCShapeStyle "ShapeStyle" +#define XtRShapeStyle "ShapeStyle" +#define XtNcornerRoundPercent "cornerRoundPercent" +#define XtCCornerRoundPercent "CornerRoundPercent" + +#define XawShapeRectangle XmuShapeRectangle +#define XawShapeOval XmuShapeOval +#define XawShapeEllipse XmuShapeEllipse +#define XawShapeRoundedRectangle XmuShapeRoundedRectangle + +extern WidgetClass commandWidgetClass; + +typedef struct _CommandClassRec *CommandWidgetClass; +typedef struct _CommandRec *CommandWidget; + +#endif /* _XawCommand_h */ diff --git a/src/CommandP.h b/src/CommandP.h new file mode 100644 index 0000000..8478b43 --- /dev/null +++ b/src/CommandP.h @@ -0,0 +1,143 @@ +/* +* $XConsortium: CommandP.h,v 1.31 94/04/17 20:12:01 rws Exp $ +*/ + + +/*********************************************************** + +Copyright (c) 1987, 1988 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * CommandP.h - Private definitions for Command widget + * + */ + +#ifndef _XawCommandP_h +#define _XawCommandP_h + +#include <X11/Xaw3d/Command.h> +#include <X11/Xaw3d/LabelP.h> + +/*********************************************************************** + * + * Command Widget Private Data + * + ***********************************************************************/ + +typedef enum { + HighlightNone, /* Do not highlight. */ + HighlightWhenUnset, /* Highlight only when unset, this is + to preserve current command widget + functionality. */ + HighlightAlways /* Always highlight, lets the toggle widget + and other subclasses do the right thing. */ +} XtCommandHighlight; + +/************************************ + * + * Class structure + * + ***********************************/ + + + /* New fields for the Command widget class record */ +typedef struct _CommandClass + { + int makes_compiler_happy; /* not used */ + } CommandClassPart; + + /* Full class record declaration */ +typedef struct _CommandClassRec { + CoreClassPart core_class; + SimpleClassPart simple_class; + ThreeDClassPart threeD_class; + LabelClassPart label_class; + CommandClassPart command_class; +} CommandClassRec; + +extern CommandClassRec commandClassRec; + +/*************************************** + * + * Instance (widget) structure + * + **************************************/ + + /* New fields for the Command widget record */ +typedef struct { + /* resources */ + Dimension highlight_thickness; + XtCallbackList callbacks; + + /* private state */ + Pixmap gray_pixmap; + GC normal_GC; + GC inverse_GC; + Boolean set; + XtCommandHighlight highlighted; + Dimension shadow_width; + /* more resources */ + int shape_style; + Dimension corner_round; +} CommandPart; + + +/* XtEventsPtr eventTable;*/ + + + /* Full widget declaration */ +typedef struct _CommandRec { + CorePart core; + SimplePart simple; + ThreeDPart threeD; + LabelPart label; + CommandPart command; +} CommandRec; + +#endif /* _XawCommandP_h */ + + diff --git a/src/Dialog.c b/src/Dialog.c new file mode 100644 index 0000000..aec1ace --- /dev/null +++ b/src/Dialog.c @@ -0,0 +1,448 @@ +/* $XConsortium: Dialog.c,v 1.48 94/04/17 20:12:02 kaleb Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* NOTE: THIS IS NOT A WIDGET! Rather, this is an interface to a widget. + It implements policy, and gives a (hopefully) easier-to-use interface + than just directly making your own form. */ + + +#include <X11/IntrinsicP.h> +#include <X11/Xos.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Misc.h> + +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/AsciiText.h> +#include <X11/Xaw3d/Command.h> +#include <X11/Xaw3d/Label.h> +#include <X11/Xaw3d/DialogP.h> +#include <X11/Xaw3d/Cardinals.h> + +/* + * After we have set the string in the value widget we set the + * string to a magic value. So that when a SetValues request is made + * on the dialog value we will notice it, and reset the string. + */ + +#define MAGIC_VALUE ((char *) 3) + +#define streq(a,b) (strcmp( (a), (b) ) == 0) + +static XtResource resources[] = { + {XtNlabel, XtCLabel, XtRString, sizeof(String), + XtOffsetOf(DialogRec, dialog.label), XtRString, NULL}, + {XtNvalue, XtCValue, XtRString, sizeof(String), + XtOffsetOf(DialogRec, dialog.value), XtRString, NULL}, + {XtNicon, XtCIcon, XtRBitmap, sizeof(Pixmap), + XtOffsetOf(DialogRec, dialog.icon), XtRImmediate, 0}, +}; + +static void Initialize(), ConstraintInitialize(), CreateDialogValueWidget(), + GetValuesHook(); + +static Boolean SetValues(); + +DialogClassRec dialogClassRec = { + { /* core_class fields */ + /* superclass */ (WidgetClass) &formClassRec, + /* class_name */ "Dialog", + /* widget_size */ sizeof(DialogRec), + /* class_initialize */ XawInitializeWidgetSet, + /* class_part init */ 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 */ NULL, + /* resize */ XtInheritResize, + /* expose */ XtInheritExpose, + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* set_values_almost */ XtInheritSetValuesAlmost, + /* get_values_hook */ GetValuesHook, + /* accept_focus */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* tm_table */ NULL, + /* query_geometry */ XtInheritQueryGeometry, + /* display_accelerator*/ XtInheritDisplayAccelerator, + /* extension */ NULL + }, + { /* composite_class fields */ + /* geometry_manager */ XtInheritGeometryManager, + /* change_managed */ XtInheritChangeManaged, + /* insert_child */ XtInheritInsertChild, + /* delete_child */ XtInheritDeleteChild, + /* extension */ NULL + }, + { /* constraint_class fields */ + /* subresourses */ NULL, + /* subresource_count */ 0, + /* constraint_size */ sizeof(DialogConstraintsRec), + /* initialize */ ConstraintInitialize, + /* destroy */ NULL, + /* set_values */ NULL, + /* extension */ NULL + }, + { /* form_class fields */ + /* layout */ XtInheritLayout + }, + { /* dialog_class fields */ + /* empty */ 0 + } +}; + +WidgetClass dialogWidgetClass = (WidgetClass)&dialogClassRec; + +/* ARGSUSED */ +static void Initialize(request, new, args, num_args) +Widget request, new; +ArgList args; +Cardinal *num_args; +{ + DialogWidget dw = (DialogWidget)new; + Arg arglist[9]; + Cardinal arg_cnt = 0; + + XtSetArg(arglist[arg_cnt], XtNborderWidth, 0); arg_cnt++; + XtSetArg(arglist[arg_cnt], XtNleft, XtChainLeft); arg_cnt++; + + if (dw->dialog.icon != (Pixmap)0) { + XtSetArg(arglist[arg_cnt], XtNbitmap, dw->dialog.icon); arg_cnt++; + XtSetArg(arglist[arg_cnt], XtNright, XtChainLeft); arg_cnt++; + dw->dialog.iconW = + XtCreateManagedWidget( "icon", labelWidgetClass, + new, arglist, arg_cnt ); + arg_cnt = 2; + XtSetArg(arglist[arg_cnt], XtNfromHoriz, dw->dialog.iconW);arg_cnt++; + } else dw->dialog.iconW = (Widget)NULL; + + XtSetArg(arglist[arg_cnt], XtNlabel, dw->dialog.label); arg_cnt++; + XtSetArg(arglist[arg_cnt], XtNright, XtChainRight); arg_cnt++; + + dw->dialog.labelW = XtCreateManagedWidget( "label", labelWidgetClass, + new, arglist, arg_cnt); + + if (dw->dialog.iconW != (Widget)NULL && + (dw->dialog.labelW->core.height < dw->dialog.iconW->core.height)) { + XtSetArg( arglist[0], XtNheight, dw->dialog.iconW->core.height ); + XtSetValues( dw->dialog.labelW, arglist, ONE ); + } + if (dw->dialog.value != NULL) + CreateDialogValueWidget( (Widget) dw); + else + dw->dialog.valueW = NULL; +} + +/* ARGSUSED */ +static void ConstraintInitialize(request, new, args, num_args) +Widget request, new; +ArgList args; +Cardinal *num_args; +{ + DialogWidget dw = (DialogWidget)new->core.parent; + DialogConstraints constraint = (DialogConstraints)new->core.constraints; + + if (!XtIsSubclass(new, commandWidgetClass)) /* if not a button */ + return; /* then just use defaults */ + + constraint->form.left = constraint->form.right = XtChainLeft; + if (dw->dialog.valueW == NULL) + constraint->form.vert_base = dw->dialog.labelW; + else + constraint->form.vert_base = dw->dialog.valueW; + + if (dw->composite.num_children > 1) { + WidgetList children = dw->composite.children; + Widget *childP; + for (childP = children + dw->composite.num_children - 1; + childP >= children; childP-- ) { + if (*childP == dw->dialog.labelW || *childP == dw->dialog.valueW) + break; + if (XtIsManaged(*childP) && + XtIsSubclass(*childP, commandWidgetClass)) { + constraint->form.horiz_base = *childP; + break; + } + } + } +} + +#define ICON 0 +#define LABEL 1 +#define NUM_CHECKS 2 + +/* ARGSUSED */ +static Boolean SetValues(current, request, new, in_args, in_num_args) +Widget current, request, new; +ArgList in_args; +Cardinal *in_num_args; +{ + DialogWidget w = (DialogWidget)new; + DialogWidget old = (DialogWidget)current; + Arg args[5]; + Cardinal num_args; + int i; + Boolean checks[NUM_CHECKS]; + + for (i = 0; i < NUM_CHECKS; i++) + checks[i] = FALSE; + + for (i = 0; i < *in_num_args; i++) { + if (streq(XtNicon, in_args[i].name)) + checks[ICON] = TRUE; + if (streq(XtNlabel, in_args[i].name)) + checks[LABEL] = TRUE; + } + + if (checks[ICON]) { + if (w->dialog.icon != (Pixmap)0) { + XtSetArg( args[0], XtNbitmap, w->dialog.icon ); + if (old->dialog.iconW != (Widget)NULL) { + XtSetValues( old->dialog.iconW, args, ONE ); + } else { + XtSetArg( args[1], XtNborderWidth, 0); + XtSetArg( args[2], XtNleft, XtChainLeft); + XtSetArg( args[3], XtNright, XtChainLeft); + w->dialog.iconW = + XtCreateWidget( "icon", labelWidgetClass, + new, args, FOUR ); + ((DialogConstraints)w->dialog.labelW->core.constraints)-> + form.horiz_base = w->dialog.iconW; + XtManageChild(w->dialog.iconW); + } + } else if (old->dialog.icon != (Pixmap)0) { + ((DialogConstraints)w->dialog.labelW->core.constraints)-> + form.horiz_base = (Widget)NULL; + XtDestroyWidget(old->dialog.iconW); + w->dialog.iconW = (Widget)NULL; + } + } + + if ( checks[LABEL] ) { + num_args = 0; + XtSetArg( args[num_args], XtNlabel, w->dialog.label ); num_args++; + if (w->dialog.iconW != (Widget)NULL && + (w->dialog.labelW->core.height <= w->dialog.iconW->core.height)) { + XtSetArg(args[num_args], XtNheight, w->dialog.iconW->core.height); + num_args++; + } + XtSetValues( w->dialog.labelW, args, num_args ); + } + + if ( w->dialog.value != old->dialog.value ) { + if (w->dialog.value == NULL) /* only get here if it + wasn't NULL before. */ + XtDestroyWidget(old->dialog.valueW); + else if (old->dialog.value == NULL) { /* create a new value widget. */ + w->core.width = old->core.width; + w->core.height = old->core.height; +#ifdef notdef +/* this would be correct if Form had the same semantics on Resize + * as on MakeGeometryRequest. Unfortunately, Form botched it, so + * any subclasses will currently have to deal with the fact that + * we're about to change our real size. + */ + w->form.resize_in_layout = False; + CreateDialogValueWidget( (Widget) w); + w->core.width = w->form.preferred_width; + w->core.height = w->form.preferred_height; + w->form.resize_in_layout = True; +#else /*notdef*/ + CreateDialogValueWidget( (Widget) w); +#endif /*notdef*/ + } + else { /* Widget ok, just change string. */ + Arg args[1]; + XtSetArg(args[0], XtNstring, w->dialog.value); + XtSetValues(w->dialog.valueW, args, ONE); + w->dialog.value = MAGIC_VALUE; + } + } + return False; +} + +/* Function Name: GetValuesHook + * Description: This is a get values hook routine that gets the + * values in the dialog. + * Arguments: w - the Text Widget. + * args - the argument list. + * num_args - the number of args. + * Returns: none. + */ + +static void +GetValuesHook(w, args, num_args) +Widget w; +ArgList args; +Cardinal * num_args; +{ + Arg a[1]; + String s; + DialogWidget src = (DialogWidget) w; + int i; + + for (i=0; i < *num_args; i++) + if (streq(args[i].name, XtNvalue)) { + XtSetArg(a[0], XtNstring, &s); + XtGetValues(src->dialog.valueW, a, 1); + *((char **) args[i].value) = s; + } +} + + +/* Function Name: CreateDialogValueWidget + * Description: Creates the dialog widgets value widget. + * Arguments: w - the dialog widget. + * Returns: none. + * + * must be called only when w->dialog.value is non-nil. + */ + +static void +CreateDialogValueWidget(w) +Widget w; +{ + DialogWidget dw = (DialogWidget) w; + Arg arglist[10]; + Cardinal num_args = 0; + +#ifdef notdef + XtSetArg(arglist[num_args], XtNwidth, + dw->dialog.labelW->core.width); num_args++; /* ||| hack */ +#endif /*notdef*/ + XtSetArg(arglist[num_args], XtNstring, dw->dialog.value); num_args++; + XtSetArg(arglist[num_args], XtNresizable, True); num_args++; + XtSetArg(arglist[num_args], XtNresize, XawtextResizeBoth); num_args++; + XtSetArg(arglist[num_args], XtNeditType, XawtextEdit); num_args++; + XtSetArg(arglist[num_args], XtNfromVert, dw->dialog.labelW); num_args++; + XtSetArg(arglist[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(arglist[num_args], XtNright, XtChainRight); num_args++; + + dw->dialog.valueW = XtCreateWidget("value", asciiTextWidgetClass, + w, arglist, num_args); + + /* if the value widget is being added after buttons, + * then the buttons need new layout constraints. + */ + if (dw->composite.num_children > 1) { + WidgetList children = dw->composite.children; + Widget *childP; + for (childP = children + dw->composite.num_children - 1; + childP >= children; childP-- ) { + if (*childP == dw->dialog.labelW || *childP == dw->dialog.valueW) + continue; + if (XtIsManaged(*childP) && + XtIsSubclass(*childP, commandWidgetClass)) { + ((DialogConstraints)(*childP)->core.constraints)-> + form.vert_base = dw->dialog.valueW; + } + } + } + XtManageChild(dw->dialog.valueW); + +/* + * Value widget gets the keyboard focus. + */ + + XtSetKeyboardFocus(w, dw->dialog.valueW); + dw->dialog.value = MAGIC_VALUE; +} + + +void +#if NeedFunctionPrototypes +XawDialogAddButton(Widget dialog, _Xconst char* name, XtCallbackProc function, + XtPointer param) +#else +XawDialogAddButton(dialog, name, function, param) +Widget dialog; +String name; +XtCallbackProc function; +XtPointer param; +#endif +{ +/* + * Correct Constraints are all set in ConstraintInitialize(). + */ + Widget button; + + button = XtCreateManagedWidget( name, commandWidgetClass, dialog, + (ArgList)NULL, (Cardinal)0 ); + + if (function != NULL) /* don't add NULL callback func. */ + XtAddCallback(button, XtNcallback, function, param); +} + + +char * +#if NeedFunctionPrototypes +XawDialogGetValueString(Widget w) +#else +XawDialogGetValueString(w) +Widget w; +#endif +{ + Arg args[1]; + char * value; + + XtSetArg(args[0], XtNstring, &value); + XtGetValues( ((DialogWidget)w)->dialog.valueW, args, ONE); + return(value); +} diff --git a/src/Dialog.h b/src/Dialog.h new file mode 100644 index 0000000..74ddcfc --- /dev/null +++ b/src/Dialog.h @@ -0,0 +1,109 @@ +/* $XConsortium: Dialog.h,v 1.28 94/04/17 20:12:03 kaleb Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _XawDialog_h +#define _XawDialog_h + +#include <X11/Xaw3d/Form.h> + +/*********************************************************************** + * + * Dialog Widget + * + ***********************************************************************/ + +/* Parameters: + + Name Class RepType Default Value + ---- ----- ------- ------------- + background Background Pixel XtDefaultBackground + border BorderColor Pixel XtDefaultForeground + borderWidth BorderWidth Dimension 1 + destroyCallback Callback Pointer NULL + height Height Dimension computed at create + icon Icon Pixmap 0 + label Label String NULL + mappedWhenManaged MappedWhenManaged Boolean True + sensitive Sensitive Boolean True + value Value String NULL + width Width Dimension computed at create + x Position Position 0 + y Position Position 0 + +*/ + +#define XtCIcon "Icon" +#define XtNicon "icon" + +typedef struct _DialogClassRec *DialogWidgetClass; +typedef struct _DialogRec *DialogWidget; + +extern WidgetClass dialogWidgetClass; + +_XFUNCPROTOBEGIN + +extern void XawDialogAddButton( +#if NeedFunctionPrototypes + Widget /* dialog */, + _Xconst char* /* name */, + XtCallbackProc /* function */, + XtPointer /* client_data */ +#endif +); + +extern char *XawDialogGetValueString( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +_XFUNCPROTOEND + +#endif /* _XawDialog_h */ diff --git a/src/DialogP.h b/src/DialogP.h new file mode 100644 index 0000000..77c74f1 --- /dev/null +++ b/src/DialogP.h @@ -0,0 +1,98 @@ +/* $XConsortium: DialogP.h,v 1.13 94/04/17 20:12:05 kit Exp $ */ + + +/*********************************************************** + +Copyright (c) 1987, 1988 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* Private definitions for Dialog widget */ + +#ifndef _DialogP_h +#define _DialogP_h + +#include <X11/Xaw3d/Dialog.h> +#include <X11/Xaw3d/FormP.h> + +typedef struct {int empty;} DialogClassPart; + +typedef struct _DialogClassRec { + CoreClassPart core_class; + CompositeClassPart composite_class; + ConstraintClassPart constraint_class; + FormClassPart form_class; + DialogClassPart dialog_class; +} DialogClassRec; + +extern DialogClassRec dialogClassRec; + +typedef struct _DialogPart { + /* resources */ + String label; /* description of the dialog */ + String value; /* for the user response */ + Pixmap icon; /* icon bitmap */ + /* private data */ + Widget iconW; /* widget to display the icon */ + Widget labelW; /* widget to display description*/ + Widget valueW; /* user response TextWidget */ +} DialogPart; + +typedef struct _DialogRec { + CorePart core; + CompositePart composite; + ConstraintPart constraint; + FormPart form; + DialogPart dialog; +} DialogRec; + +typedef struct {int empty;} DialogConstraintsPart; + +typedef struct _DialogConstraintsRec { + FormConstraintsPart form; + DialogConstraintsPart dialog; +} DialogConstraintsRec, *DialogConstraints; + +#endif /* _DialogP_h */ diff --git a/src/Form.c b/src/Form.c new file mode 100644 index 0000000..c4eae4b --- /dev/null +++ b/src/Form.c @@ -0,0 +1,848 @@ +/* $XConsortium: Form.c,v 1.52 94/04/17 20:12:06 kaleb Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Converters.h> +#include <X11/Xmu/CharSet.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/FormP.h> + +/* Private Definitions */ + +static int default_value = -99999; + +#define Offset(field) XtOffsetOf(FormRec, form.field) +static XtResource resources[] = { + {XtNdefaultDistance, XtCThickness, XtRInt, sizeof(int), + Offset(default_spacing), XtRImmediate, (XtPointer)4} +}; +#undef Offset + +static XtEdgeType defEdge = XtRubber; + +#define Offset(field) XtOffsetOf(FormConstraintsRec, form.field) +static XtResource formConstraintResources[] = { + {XtNtop, XtCEdge, XtREdgeType, sizeof(XtEdgeType), + Offset(top), XtREdgeType, (XtPointer)&defEdge}, + {XtNbottom, XtCEdge, XtREdgeType, sizeof(XtEdgeType), + Offset(bottom), XtREdgeType, (XtPointer)&defEdge}, + {XtNleft, XtCEdge, XtREdgeType, sizeof(XtEdgeType), + Offset(left), XtREdgeType, (XtPointer)&defEdge}, + {XtNright, XtCEdge, XtREdgeType, sizeof(XtEdgeType), + Offset(right), XtREdgeType, (XtPointer)&defEdge}, + {XtNhorizDistance, XtCThickness, XtRInt, sizeof(int), + Offset(dx), XtRInt, (XtPointer) &default_value}, + {XtNfromHoriz, XtCWidget, XtRWidget, sizeof(Widget), + Offset(horiz_base), XtRWidget, (XtPointer)NULL}, + {XtNvertDistance, XtCThickness, XtRInt, sizeof(int), + Offset(dy), XtRInt, (XtPointer) &default_value}, + {XtNfromVert, XtCWidget, XtRWidget, sizeof(Widget), + Offset(vert_base), XtRWidget, (XtPointer)NULL}, + {XtNresizable, XtCBoolean, XtRBoolean, sizeof(Boolean), + Offset(allow_resize), XtRImmediate, (XtPointer) FALSE}, +}; +#undef Offset + +static void ClassInitialize(), ClassPartInitialize(), Initialize(), Resize(); +static void ConstraintInitialize(); +static Boolean SetValues(), ConstraintSetValues(); +static XtGeometryResult GeometryManager(), PreferredGeometry(); +static void ChangeManaged(); +static Boolean Layout(); + +static void LayoutChild(), ResizeChildren(); + +FormClassRec formClassRec = { + { /* core_class fields */ + /* superclass */ (WidgetClass) &constraintClassRec, + /* class_name */ "Form", + /* widget_size */ sizeof(FormRec), + /* class_initialize */ ClassInitialize, + /* class_part_init */ ClassPartInitialize, + /* 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 */ NULL, + /* resize */ Resize, + /* expose */ XtInheritExpose, + /* 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 */ PreferredGeometry, + /* display_accelerator*/ XtInheritDisplayAccelerator, + /* extension */ NULL + }, + { /* composite_class fields */ + /* geometry_manager */ GeometryManager, + /* change_managed */ ChangeManaged, + /* insert_child */ XtInheritInsertChild, + /* delete_child */ XtInheritDeleteChild, + /* extension */ NULL + }, + { /* constraint_class fields */ + /* subresourses */ formConstraintResources, + /* subresource_count */ XtNumber(formConstraintResources), + /* constraint_size */ sizeof(FormConstraintsRec), + /* initialize */ ConstraintInitialize, + /* destroy */ NULL, + /* set_values */ ConstraintSetValues, + /* extension */ NULL + }, + { /* form_class fields */ + /* layout */ Layout + } +}; + +WidgetClass formWidgetClass = (WidgetClass)&formClassRec; + +/**************************************************************** + * + * Private Procedures + * + ****************************************************************/ + + +static XrmQuark XtQChainLeft, XtQChainRight, XtQChainTop, + XtQChainBottom, XtQRubber; + +/* ARGSUSED */ +static void _CvtStringToEdgeType(args, num_args, fromVal, toVal) + XrmValuePtr args; /* unused */ + Cardinal *num_args; /* unused */ + XrmValuePtr fromVal; + XrmValuePtr toVal; +{ + static XtEdgeType edgeType; + XrmQuark q; + char lowerName[40]; + + if (strlen ((char*) fromVal->addr) < sizeof lowerName) { + XmuCopyISOLatin1Lowered (lowerName, (char*)fromVal->addr); + q = XrmStringToQuark(lowerName); + if (q == XtQChainLeft) edgeType = XtChainLeft; + else if (q == XtQChainRight) edgeType = XtChainRight; + else if (q == XtQChainTop) edgeType = XtChainTop; + else if (q == XtQChainBottom) edgeType = XtChainBottom; + else if (q == XtQRubber) edgeType = XtRubber; + else { + toVal->size = 0; + toVal->addr = NULL; + return; + } + toVal->size = sizeof edgeType; + toVal->addr = (XPointer) &edgeType; + return; + } + toVal->addr = NULL; + toVal->size = 0; +} + +static void ClassInitialize() +{ + static XtConvertArgRec parentCvtArgs[] = { + {XtBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.parent), + sizeof(Widget)} + }; + XawInitializeWidgetSet(); + XtQChainLeft = XrmPermStringToQuark("chainleft"); + XtQChainRight = XrmPermStringToQuark("chainright"); + XtQChainTop = XrmPermStringToQuark("chaintop"); + XtQChainBottom = XrmPermStringToQuark("chainbottom"); + XtQRubber = XrmPermStringToQuark("rubber"); + + XtAddConverter( XtRString, XtREdgeType, _CvtStringToEdgeType, + (XtConvertArgList)NULL, 0 ); + XtSetTypeConverter (XtRString, XtRWidget, XmuNewCvtStringToWidget, + parentCvtArgs, XtNumber(parentCvtArgs), XtCacheNone, + (XtDestructor)NULL); +} + +static void ClassPartInitialize(class) + WidgetClass class; +{ + FormWidgetClass c = (FormWidgetClass)class; + FormWidgetClass super = (FormWidgetClass) + c->core_class.superclass; + + if (c->form_class.layout == XtInheritLayout) + c->form_class.layout = super->form_class.layout; +} + +/* ARGSUSED */ +static void Initialize(request, new, args, num_args) + Widget request, new; + ArgList args; + Cardinal *num_args; +{ + FormWidget fw = (FormWidget)new; + + fw->form.old_width = fw->core.width; + fw->form.old_height = fw->core.height; + fw->form.no_refigure = False; + fw->form.needs_relayout = False; + fw->form.resize_in_layout = True; + fw->form.resize_is_no_op = False; +} + +/* Function Name: ChangeFormGeometry + * Description: Ask the parent to change the form widget's geometry. + * Arguments: w - the Form widget. + * query_only - TRUE if this is only a query. + * width, height - the new width and height. + * ret_width, ret_height - the actual size the form is allowed + * to resize to. + * Returns: TRUE of children may always be resized. + */ + +static Boolean +ChangeFormGeometry(w, query_only, width, height, ret_width, ret_height) +Widget w; +Boolean query_only; +Dimension width, height; +Dimension *ret_width, *ret_height; +{ + FormWidget fw = (FormWidget) w; + Boolean always_resize_children; + XtGeometryResult result; + XtWidgetGeometry request, return_request; + + /* + * If we are already at the desired size then there is no need + * to ask our parent of we can change size. + */ + + if ( (width == fw->core.width) && (height == fw->core.height) ) + return(TRUE); + + request.width = width; + request.height = height; + request.request_mode = CWWidth | CWHeight; + if (query_only) + request.request_mode |= XtCWQueryOnly; + + /* + * Do no invoke the resize rules if our size changes here. + */ + + fw->form.resize_is_no_op = TRUE; + + result = XtMakeGeometryRequest(w, &request, &return_request); + if (result == XtGeometryAlmost) { + request = return_request; + (void) XtMakeGeometryRequest(w, &request, &return_request); + always_resize_children = FALSE; + } + else + always_resize_children = (result == XtGeometryYes); + + fw->form.resize_is_no_op = FALSE; + + if (ret_width != NULL) + *ret_width = request.width; + if (ret_height != NULL) + *ret_height = request.height; + + return(always_resize_children); +} + +/* Function Name: Layout + * Description: Moves all the children around. + * Arguments: fw - the Form widget. + * width, height - ** UNUSED **. + * force_relayout - will force the children to be + * moved, even if some go past the edge + * of the form. + * Returns: True if the children are allowed to move from their + * current locations to the new ones. + */ + +/* ARGSUSED */ +static Boolean Layout(fw, width, height, force_relayout) + FormWidget fw; + Dimension width, height; + Boolean force_relayout; +{ + int num_children = fw->composite.num_children; + WidgetList children = fw->composite.children; + Widget *childP; + Dimension maxx, maxy; + Boolean ret_val; + + for (childP = children; childP - children < num_children; childP++) { + FormConstraints form = (FormConstraints)(*childP)->core.constraints; + form->form.layout_state = LayoutPending; + } + + maxx = maxy = 1; + for (childP = children; childP - children < num_children; childP++) { + if (XtIsManaged(*childP)) { + FormConstraints form; + Position x, y; + + form = (FormConstraints)(*childP)->core.constraints; + + LayoutChild(*childP); + + x = form->form.new_x + (*childP)->core.width + + ((*childP)->core.border_width << 1); + if (x > (int)maxx) + maxx = x; + + y = form->form.new_y + (*childP)->core.height + + ((*childP)->core.border_width << 1); + if (y > (int)maxy) + maxy = y; + } + } + + fw->form.preferred_width = (maxx += fw->form.default_spacing); + fw->form.preferred_height = (maxy += fw->form.default_spacing); + + if (fw->form.resize_in_layout) { + Boolean always_resize_children; + + always_resize_children = + ChangeFormGeometry( (Widget) fw, FALSE, maxx, maxy, + (Dimension *)NULL, (Dimension *)NULL); + + fw->form.old_width = fw->core.width; + fw->form.old_height = fw->core.height; + + ret_val = (always_resize_children || ( (fw->core.width >= maxx) && + (fw->core.height >= maxy))); + + if (force_relayout) + ret_val = TRUE; + + if (ret_val) + ResizeChildren((Widget) fw); + } + else + ret_val = False; + + fw->form.needs_relayout = False; + return ret_val; +} + +/* Function Name: ResizeChildren + * Description: Resizes all children to new_x and new_y. + * Arguments: w - the form widget. + * Returns: none. + */ + +static void ResizeChildren(w) +Widget w; +{ + FormWidget fw = (FormWidget) w; + int num_children = fw->composite.num_children; + WidgetList children = fw->composite.children; + Widget *childP; + + for (childP = children; childP - children < num_children; childP++) { + FormConstraints form; + + if (!XtIsManaged(*childP)) + continue; + + form = (FormConstraints)(*childP)->core.constraints; + if (fw->form.no_refigure) { +/* + * I am changing the widget wrapper w/o modifing the window. This is + * risky, but I can get away with it since I am the parent of this + * widget, and he must ask me for any geometry changes. + * + * The window will be updated when no_refigure is set back to False. + */ + (*childP)->core.x = form->form.new_x; + (*childP)->core.y = form->form.new_y; + } + else + XtMoveWidget(*childP, form->form.new_x, form->form.new_y); + } +} + + +static void LayoutChild(w) + Widget w; +{ + FormConstraints form = (FormConstraints)w->core.constraints; + Widget ref; + + switch (form->form.layout_state) { + + case LayoutPending: + form->form.layout_state = LayoutInProgress; + break; + + case LayoutDone: + return; + + case LayoutInProgress: + { + String subs[2]; + Cardinal num_subs = 2; + subs[0] = w->core.name; + subs[1] = w->core.parent->core.name; + XtAppWarningMsg(XtWidgetToApplicationContext(w), + "constraintLoop","xawFormLayout","XawToolkitError", + "constraint loop detected while laying out child '%s' in FormWidget '%s'", + subs, &num_subs); + return; + } + } + + form->form.new_x = form->form.dx; + form->form.new_y = form->form.dy; + if ((ref = form->form.horiz_base) != (Widget)NULL) { + FormConstraints ref_form = (FormConstraints) ref->core.constraints; + + LayoutChild(ref); + form->form.new_x += (ref_form->form.new_x + + ref->core.width + (ref->core.border_width << 1)); + } + if ((ref = form->form.vert_base) != (Widget)NULL) { + FormConstraints ref_form = (FormConstraints) ref->core.constraints; + + LayoutChild(ref); + form->form.new_y += (ref_form->form.new_y + + ref->core.height + (ref->core.border_width << 1)); + } + + form->form.layout_state = LayoutDone; +} + + +static Position TransformCoord(loc, old, new, type) + Position loc; + Dimension old, new; + XtEdgeType type; +{ + if (type == XtRubber) { + if ( ((int) old) > 0) + loc = (int)(loc * new) / (int)old; + } + else if (type == XtChainBottom || type == XtChainRight) + loc += (Position)new - (Position)old; + + /* I don't see any problem with returning values less than zero. */ + + return (loc); +} + +static void Resize(w) + Widget w; +{ + FormWidget fw = (FormWidget)w; + WidgetList children = fw->composite.children; + int num_children = fw->composite.num_children; + Widget *childP; + Position x, y; + Dimension width, height; + + if (!fw->form.resize_is_no_op) + for (childP = children; childP - children < num_children; childP++) { + FormConstraints form= (FormConstraints)(*childP)->core.constraints; + if (!XtIsManaged(*childP)) continue; + x = TransformCoord( (*childP)->core.x, fw->form.old_width, + fw->core.width, form->form.left ); + y = TransformCoord( (*childP)->core.y, fw->form.old_height, + fw->core.height, form->form.top ); + + form->form.virtual_width = + TransformCoord((Position)((*childP)->core.x + + form->form.virtual_width + + 2 * (*childP)->core.border_width), + fw->form.old_width, fw->core.width, + form->form.right ) + - (x + 2 * (*childP)->core.border_width); + + form->form.virtual_height = + TransformCoord((Position)((*childP)->core.y + + form->form.virtual_height + + 2 * (*childP)->core.border_width), + fw->form.old_height, fw->core.height, + form->form.bottom ) + - ( y + 2 * (*childP)->core.border_width); + + width = (Dimension) + (form->form.virtual_width < 1) ? 1 : form->form.virtual_width; + height = (Dimension) + (form->form.virtual_height < 1) ? 1 : form->form.virtual_height; + + XtConfigureWidget(*childP,x,y, (Dimension)width, (Dimension)height, + (*childP)->core.border_width ); + } + + fw->form.old_width = fw->core.width; + fw->form.old_height = fw->core.height; +} + +/* + * I don't want to even think about what ``Almost'' would mean - Chris. + */ + +/* ARGSUSED */ +static XtGeometryResult GeometryManager(w, request, reply) + Widget w; + XtWidgetGeometry *request; + XtWidgetGeometry *reply; /* RETURN */ +{ + Dimension old_width, old_height; + FormWidget fw = (FormWidget) XtParent(w); + FormConstraints form = (FormConstraints) w->core.constraints; + XtWidgetGeometry allowed; + XtGeometryResult ret_val; + + if ((request->request_mode & ~(XtCWQueryOnly | CWWidth | CWHeight)) || + !form->form.allow_resize) { + + /* If GeometryManager is invoked during a SetValues call on a child + * then it is necessary to compute a new layout if ConstraintSetValues + * allowed any constraint changes. */ + + if (fw->form.needs_relayout) + (*((FormWidgetClass)fw->core.widget_class)->form_class.layout) + (fw, 0, 0, True); + return(XtGeometryNo); + } + + if (request->request_mode & CWWidth) + allowed.width = request->width; + else + allowed.width = w->core.width; + + if (request->request_mode & CWHeight) + allowed.height = request->height; + else + allowed.height = w->core.height; + + if (allowed.width == w->core.width && allowed.height == w->core.height) { + + /* If GeometryManager is invoked during a SetValues call on a child + * then it is necessary to compute a new layout if ConstraintSetValues + * allowed any constraint changes. */ + + if (fw->form.needs_relayout) + (*((FormWidgetClass)fw->core.widget_class)->form_class.layout) + (fw, 0, 0, True); + return(XtGeometryNo); + } + + /* + * Remember the old size, and then set the size to the requested size. + */ + + old_width = w->core.width; + old_height = w->core.height; + w->core.width = allowed.width; + w->core.height = allowed.height; + + if (request->request_mode & XtCWQueryOnly) { + Boolean always_resize_children; + Dimension ret_width, ret_height; + + fw->form.resize_in_layout = FALSE; + + (*((FormWidgetClass)fw->core.widget_class)->form_class.layout) + ( fw, w->core.width, w->core.height, + FALSE ); + + /* + * Reset the size of this child back to what it used to be. + */ + + w->core.width = old_width; + w->core.height = old_height; + + fw->form.resize_in_layout = TRUE; + + always_resize_children = ChangeFormGeometry(w, TRUE, + fw->form.preferred_width, + fw->form.preferred_height, + &ret_width, &ret_height); + + if (always_resize_children || + ((ret_width >= fw->form.preferred_width) && + (ret_height >= fw->form.preferred_height))) + { + ret_val = XtGeometryYes; + } + else + ret_val = XtGeometryNo; + } + else { + if ((*((FormWidgetClass)fw->core.widget_class)->form_class.layout) + ( fw, w->core.width, w->core.height, + FALSE)) + { + form->form.virtual_width = w->core.width; /* reset virtual */ + form->form.virtual_height = w->core.height; /* width and height. */ + if (fw->form.no_refigure) { +/* + * I am changing the widget wrapper w/o modifing the window. This is + * risky, but I can get away with it since I am the parent of this + * widget, and he must ask me for any geometry changes. + * + * The window will be updated when no_refigure is set back to False. + */ + form->form.deferred_resize = True; + ret_val = XtGeometryDone; + } + else + ret_val = XtGeometryYes; + } + else { + w->core.width = old_width; + w->core.height = old_height; + ret_val = XtGeometryNo; + } + } + + return(ret_val); +} + + +/* ARGSUSED */ +static Boolean SetValues(current, request, new, args, num_args) + Widget current, request, new; + ArgList args; + Cardinal *num_args; +{ + return( FALSE ); +} + + +/* ARGSUSED */ +static void ConstraintInitialize(request, new, args, num_args) + Widget request, new; + ArgList args; + Cardinal *num_args; +{ + FormConstraints form = (FormConstraints)new->core.constraints; + FormWidget fw = (FormWidget)new->core.parent; + + form->form.virtual_width = (int) new->core.width; + form->form.virtual_height = (int) new->core.height; + + if (form->form.dx == default_value) + form->form.dx = fw->form.default_spacing; + + if (form->form.dy == default_value) + form->form.dy = fw->form.default_spacing; + + form->form.deferred_resize = False; +} + +/*ARGSUSED*/ +static Boolean ConstraintSetValues(current, request, new, args, num_args) + Widget current, request, new; + ArgList args; + Cardinal *num_args; +{ + FormConstraints cfc = (FormConstraints) current->core.constraints; + FormConstraints nfc = (FormConstraints) new->core.constraints; + + if (cfc->form.top != nfc->form.top || + cfc->form.bottom != nfc->form.bottom || + cfc->form.left != nfc->form.left || + cfc->form.right != nfc->form.right || + cfc->form.dx != nfc->form.dx || + cfc->form.dy != nfc->form.dy || + cfc->form.horiz_base != nfc->form.horiz_base || + cfc->form.vert_base != nfc->form.vert_base) { + + FormWidget fp = (FormWidget) XtParent(new); + + /* If there are no subclass ConstraintSetValues procedures remaining + * to be invoked, and if there is no geometry request about to be + * made, then invoke the new layout now; else defer it. */ + + if (XtClass(XtParent(new)) == formWidgetClass && + current->core.x == new->core.x && + current->core.y == new->core.y && + current->core.width == new->core.width && + current->core.height == new->core.height && + current->core.border_width == new->core.border_width) + Layout(fp, 0, 0, True); + else fp->form.needs_relayout = True; + } + return( FALSE ); +} + +static void ChangeManaged(w) + Widget w; +{ + FormWidget fw = (FormWidget)w; + FormConstraints form; + WidgetList children, childP; + int num_children = fw->composite.num_children; + Widget child; + + /* + * Reset virtual width and height for all children. + */ + + for (children = childP = fw->composite.children ; + childP - children < num_children; childP++) { + child = *childP; + if (XtIsManaged(child)) { + form = (FormConstraints)child->core.constraints; + +/* + * If the size is one (1) then we must not change the virtual sizes, as + * they contain useful information. If someone actually wants a widget of + * width or height one (1) in a form widget he will lose, can't win them all. + * + * Chris D. Peterson 2/9/89. + */ + + if ( child->core.width != 1) + form->form.virtual_width = (int) child->core.width; + if ( child->core.height != 1) + form->form.virtual_height = (int) child->core.height; + } + } + (*((FormWidgetClass)w->core.widget_class)->form_class.layout) + ((FormWidget) w, w->core.width, + w->core.height, TRUE); +} + + +static XtGeometryResult PreferredGeometry( widget, request, reply ) + Widget widget; + XtWidgetGeometry *request, *reply; +{ + FormWidget w = (FormWidget)widget; + + reply->width = w->form.preferred_width; + reply->height = w->form.preferred_height; + reply->request_mode = CWWidth | CWHeight; + if ( request->request_mode & (CWWidth | CWHeight) == + (CWWidth | CWHeight) + && request->width == reply->width + && request->height == reply->height) + return XtGeometryYes; + else if (reply->width == w->core.width && reply->height == w->core.height) + return XtGeometryNo; + else + return XtGeometryAlmost; +} + + +/********************************************************************** + * + * Public routines + * + **********************************************************************/ + +/* + * Set or reset figuring (ignored if not realized) + */ + +void +#if NeedFunctionPrototypes +XawFormDoLayout(Widget w, +#if NeedWidePrototypes + int doit) +#else + Boolean doit) +#endif +#else +XawFormDoLayout(w, doit) +Widget w; +Boolean doit; +#endif +{ + Widget *childP; + FormWidget fw = (FormWidget)w; + int num_children = fw->composite.num_children; + WidgetList children = fw->composite.children; + + if ( ((fw->form.no_refigure = !doit) == TRUE) || !XtIsRealized(w) ) + return; + + for (childP = children; childP - children < num_children; childP++) { + Widget w = *childP; + if (XtIsManaged(w)) { + FormConstraints form = (FormConstraints)w->core.constraints; + + /* + * Xt Configure widget is too smart, and optimizes out + * my changes. + */ + + XMoveResizeWindow(XtDisplay(w), XtWindow(w), + w->core.x, w->core.y, + w->core.width, w->core.height); + + if (form->form.deferred_resize && + XtClass(w)->core_class.resize != (XtWidgetProc) NULL) { + (*(XtClass(w)->core_class.resize))(w); + form->form.deferred_resize = False; + } + } + } +} diff --git a/src/Form.h b/src/Form.h new file mode 100644 index 0000000..f4c9b5c --- /dev/null +++ b/src/Form.h @@ -0,0 +1,168 @@ +/* $XConsortium: Form.h,v 1.30 94/04/17 20:12:08 kaleb Exp $ */ + + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _XawForm_h +#define _XawForm_h + +#include <X11/Constraint.h> + +/*********************************************************************** + * + * Form Widget + * + ***********************************************************************/ + +/* Parameters: + + Name Class RepType Default Value + ---- ----- ------- ------------- + background Background Pixel XtDefaultBackground + border BorderColor Pixel XtDefaultForeground + borderWidth BorderWidth Dimension 1 + defaultDistance Thickness int 4 + destroyCallback Callback Pointer NULL + height Height Dimension computed at realize + mappedWhenManaged MappedWhenManaged Boolean True + sensitive Sensitive Boolean True + width Width Dimension computed at realize + x Position Position 0 + y Position Position 0 + +*/ + +/* Constraint parameters: + + Name Class RepType Default Value + ---- ----- ------- ------------- + bottom Edge XtEdgeType XtRubber + fromHoriz Widget Widget (left edge of form) + fromVert Widget Widget (top of form) + horizDistance Thickness int defaultDistance + left Edge XtEdgeType XtRubber + resizable Boolean Boolean False + right Edge XtEdgeType XtRubber + top Edge XtEdgeType XtRubber + vertDistance Thickness int defaultDistance + +*/ + + +#ifndef _XtStringDefs_h_ +#define XtNtop "top" +#define XtRWidget "Widget" +#endif + +#define XtNdefaultDistance "defaultDistance" +#define XtNbottom "bottom" +#define XtNleft "left" +#define XtNright "right" +#define XtNfromHoriz "fromHoriz" +#define XtNfromVert "fromVert" +#define XtNhorizDistance "horizDistance" +#define XtNvertDistance "vertDistance" +#define XtNresizable "resizable" + +#define XtCEdge "Edge" +#define XtCWidget "Widget" + +#ifndef _XawEdgeType_e +#define _XawEdgeType_e +typedef enum { + XawChainTop, /* Keep this edge a constant distance from + the top of the form */ + XawChainBottom, /* Keep this edge a constant distance from + the bottom of the form */ + XawChainLeft, /* Keep this edge a constant distance from + the left of the form */ + XawChainRight, /* Keep this edge a constant distance from + the right of the form */ + XawRubber /* Keep this edge a proportional distance + from the edges of the form*/ +} XawEdgeType; +#endif /* _XawEdgeType_e */ + +/* + * Unfortunatly I missed this definition for R4, so I cannot + * protect it with XAW_BC, it looks like this particular problem is + * one that we will have to live with for a while. + * + * Chris D. Peterson - 3/23/90. + */ + +#define XtEdgeType XawEdgeType + +#define XtChainTop XawChainTop +#define XtChainBottom XawChainBottom +#define XtChainLeft XawChainLeft +#define XtChainRight XawChainRight +#define XtRubber XawRubber + +typedef struct _FormClassRec *FormWidgetClass; +typedef struct _FormRec *FormWidget; + +extern WidgetClass formWidgetClass; + +_XFUNCPROTOBEGIN + +extern void XawFormDoLayout( +#if NeedFunctionPrototypes + Widget /* w */, +#if NeedWidePrototypes + /* Boolean */ int /* do_layout */ +#else + Boolean /* do_layout */ +#endif +#endif +); + +_XFUNCPROTOEND + +#endif /* _XawForm_h */ diff --git a/src/FormP.h b/src/FormP.h new file mode 100644 index 0000000..9314015 --- /dev/null +++ b/src/FormP.h @@ -0,0 +1,143 @@ +/* $XConsortium: FormP.h,v 1.22 94/04/17 20:12:09 kaleb Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* Form widget private definitions */ + +#ifndef _XawFormP_h +#define _XawFormP_h + +#include <X11/Xaw3d/Form.h> + +#define XtREdgeType "EdgeType" + +typedef enum {LayoutPending, LayoutInProgress, LayoutDone} LayoutState; +#define XtInheritLayout ((Boolean (*)())_XtInherit) + +typedef struct { + Boolean (*layout)(/* FormWidget, Dimension, Dimension */); +} FormClassPart; + +/* + * Layout( + * FormWidget w - the widget whose children are to be configured + * Dimension w, h - bounding box of layout to be calculated + * + * Stores preferred geometry in w->form.preferred_{width,height}. + * If w->form.resize_in_layout is True, then a geometry request + * may be made for the preferred bounding box if necessary. + * + * Returns True if a geometry request was granted, False otherwise. + */ + +typedef struct _FormClassRec { + CoreClassPart core_class; + CompositeClassPart composite_class; + ConstraintClassPart constraint_class; + FormClassPart form_class; +} FormClassRec; + +extern FormClassRec formClassRec; + +typedef struct _FormPart { + /* resources */ + int default_spacing; /* default distance between children */ + /* private state */ + Dimension old_width, old_height; /* last known dimensions */ + int no_refigure; /* no re-layout while > 0 */ + Boolean needs_relayout; /* next time no_refigure == 0 */ + Boolean resize_in_layout; /* should layout() do geom request? */ + Dimension preferred_width, preferred_height; /* cached from layout */ + Boolean resize_is_no_op; /* Causes resize to take not action. */ +} FormPart; + +typedef struct _FormRec { + CorePart core; + CompositePart composite; + ConstraintPart constraint; + FormPart form; +} FormRec; + +typedef struct _FormConstraintsPart { +/* + * Constraint Resources. + */ + XtEdgeType top, bottom, /* where to drag edge on resize */ + left, right; + int dx; /* desired horiz offset */ + int dy; /* desired vertical offset */ + Widget horiz_base; /* measure dx from here if non-null */ + Widget vert_base; /* measure dy from here if non-null */ + Boolean allow_resize; /* TRUE if child may request resize */ + +/* + * Private contstraint resources. + */ + +/* + * What the size of this child would be if we did not impose the + * constraint the width and height must be greater than zero (0). + */ + short virtual_width, virtual_height; + +/* + * Temporary Storage for children's new possible possition. + */ + + Position new_x, new_y; + + LayoutState layout_state; /* temporary layout state */ + Boolean deferred_resize; /* was resized while no_refigure is set */ +} FormConstraintsPart; + +typedef struct _FormConstraintsRec { + FormConstraintsPart form; +} FormConstraintsRec, *FormConstraints; + +#endif /* _XawFormP_h */ diff --git a/src/Grip.c b/src/Grip.c new file mode 100644 index 0000000..17c4fc0 --- /dev/null +++ b/src/Grip.c @@ -0,0 +1,150 @@ +/* $XConsortium: Grip.c,v 1.33 94/04/17 20:12:10 kaleb Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * Grip.c - Grip Widget (Used by Paned Widget) + * + */ +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/GripP.h> + +static XtResource resources[] = { + {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension), + XtOffsetOf(GripRec, core.width), XtRImmediate, + (XtPointer) DEFAULT_GRIP_SIZE}, + {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension), + XtOffsetOf(GripRec, core.height), XtRImmediate, + (XtPointer) DEFAULT_GRIP_SIZE}, + {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), + XtOffsetOf(GripRec, core.background_pixel), XtRString, + XtDefaultForeground}, + {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension), + XtOffsetOf(GripRec, core.border_width), XtRImmediate, (XtPointer)0}, + {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), + XtOffsetOf(GripRec, grip.grip_action), XtRCallback, NULL}, +}; + +static void GripAction( /* Widget, XEvent*, String*, Cardinal */ ); + +static XtActionsRec actionsList[] = +{ + {"GripAction", GripAction}, +}; + +#define SuperClass (&threeDClassRec) + +GripClassRec gripClassRec = { + { +/* core class fields */ + /* superclass */ (WidgetClass) SuperClass, + /* class name */ "Grip", + /* size */ sizeof(GripRec), + /* class initialize */ XawInitializeWidgetSet, + /* class_part_init */ NULL, + /* class_inited */ FALSE, + /* initialize */ NULL, + /* initialize_hook */ NULL, + /* realize */ XtInheritRealize, + /* actions */ actionsList, + /* num_actions */ XtNumber(actionsList), + /* resources */ resources, + /* resource_count */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ TRUE, + /* compress_exposure */ TRUE, + /* compress_enterleave*/ TRUE, + /* visible_interest */ FALSE, + /* destroy */ NULL, + /* resize */ NULL, + /* expose */ XtInheritExpose, + /* set_values */ NULL, + /* 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 */ XtInheritQueryGeometry, + /* display_accelerator*/ XtInheritDisplayAccelerator, + /* extension */ NULL + }, +/* Simple class fields initialization */ + { + /* change_sensitive */ XtInheritChangeSensitive + }, +/* ThreeD class fields initialization */ + { + /* shadowdraw */ 0 /* inherited expose method knows how */ + }, +/* Grip class fields initialization */ + { + /* not used */ 0 + } +}; + +WidgetClass gripWidgetClass = (WidgetClass) &gripClassRec; + +static void GripAction( widget, event, params, num_params ) + Widget widget; + XEvent *event; + String *params; + Cardinal *num_params; +{ + XawGripCallDataRec call_data; + + call_data.event = event; + call_data.params = params; + call_data.num_params = *num_params; + + XtCallCallbacks( widget, XtNcallback, (XtPointer)&call_data ); +} diff --git a/src/Grip.h b/src/Grip.h new file mode 100644 index 0000000..440c1f0 --- /dev/null +++ b/src/Grip.h @@ -0,0 +1,105 @@ +/* $XConsortium: Grip.h,v 1.19 94/04/17 20:12:11 converse Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * Grip.h - Public Definitions for Grip widget (used by VPane Widget) + * + */ + +#ifndef _XawGrip_h +#define _XawGrip_h + +#include <X11/Xaw3d/Simple.h> + +/*************************************************************************** + * + * Grip Widget + * + **************************************************************************/ + +/* Parameters: + + Name Class RepType Default Value + ---- ----- ------- ------------- + foreground Foreground Pixel XtDefaultForeground + border BorderColor Pixel XtDefaultForeground + borderWidth BorderWidth Dimension 0 + callback Callback Pointer GripAction + cursor Cursor Cursor None + cursorName Cursor String NULL + destroyCallback Callback Pointer NULL + height Height Dimension 8 + mappedWhenManaged MappedWhenManaged Boolean True + pointerColor Foreground Pixel XtDefaultForeground + pointerColorBackground Background Pixel XtDefaultBackground + sensitive Sensitive Boolean True + width Width Dimension 8 + x Position Position 0 + y Position Position 0 + +*/ + +#define XtNgripTranslations "gripTranslations" + +typedef struct _XawGripCallData { + XEvent *event; /* the event causing the GripAction */ + String *params; /* the TranslationTable params */ + Cardinal num_params; /* count of params */ +} XawGripCallDataRec, *XawGripCallData, + GripCallDataRec, *GripCallData; /* supported for R4 compatibility */ + +/* Class Record Constant */ + +extern WidgetClass gripWidgetClass; + +typedef struct _GripClassRec *GripWidgetClass; +typedef struct _GripRec *GripWidget; + +#endif /* _XawGrip_h */ diff --git a/src/GripP.h b/src/GripP.h new file mode 100644 index 0000000..1fc3ae6 --- /dev/null +++ b/src/GripP.h @@ -0,0 +1,105 @@ +/* +* $XConsortium: GripP.h,v 1.15 94/04/17 20:12:11 kit Exp $ +*/ + + +/*********************************************************** + +Copyright (c) 1987, 1988 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * GripP.h - Private definitions for Grip widget (Used by VPane Widget) + * + */ + +#ifndef _XawGripP_h +#define _XawGripP_h + +#include <X11/Xaw3d/Grip.h> +#include <X11/Xaw3d/ThreeDP.h> + +/***************************************************************************** + * + * Grip Widget Private Data + * + *****************************************************************************/ + +#define DEFAULT_GRIP_SIZE 8 + +/* New fields for the Grip widget class record */ +typedef struct {int empty;} GripClassPart; + +/* Full Class record declaration */ +typedef struct _GripClassRec { + CoreClassPart core_class; + SimpleClassPart simple_class; + ThreeDClassPart threeD_class; + GripClassPart grip_class; +} GripClassRec; + +extern GripClassRec gripClassRec; + +/* New fields for the Grip widget record */ +typedef struct { + XtCallbackList grip_action; +} GripPart; + +/***************************************************************************** + * + * Full instance record declaration + * + ****************************************************************************/ + +typedef struct _GripRec { + CorePart core; + SimplePart simple; + ThreeDPart threeD; + GripPart grip; +} GripRec; + +#endif /* _XawGripP_h */ + diff --git a/src/Imakefile b/src/Imakefile new file mode 100644 index 0000000..81e9a0a --- /dev/null +++ b/src/Imakefile @@ -0,0 +1,157 @@ +#ifndef XCOMM +#define XCOMM # +#endif + +XCOMM Build options. Have you read the README.XAW3D file yet? +XCOMM +XCOMM For color pixmaps, define MULTIPLANE_PIXMAPS: +#undef MULTIPLANE_PIXMAPS +XCOMM For grayed stipple shadows, define GRAY_BLKWHT_STIPPLES: +#define GRAY_BLKWHT_STIPPLES +XCOMM For scrollbars with arrows, define ARROW_SCROLLBARS: +#undef ARROW_SCROLLBARS + +#define DoNormalLib NormalLibXaw +#define DoSharedLib SharedLibXaw +#define DoDebugLib DebugLibXaw +#define DoProfileLib ProfileLibXaw +#define HasSharedData YES +#define LibName Xaw3d +#define SoRev SOXAWREV +#define IncSubdir X11 +#define IncSubSubdir Xaw3d + +XCOMM When building outside an X11 source tree: +XCOMM EXTRA_INCLUDES = -I. + +#ifdef SharedXawReqs +REQUIREDLIBS = SharedXawReqs +#endif + +LINTLIBS = $(LINTXLIB) $(LINTXTOOL) + +BASE_HDRS = AllWidgets.h AsciiSink.h AsciiSinkP.h AsciiSrc.h AsciiSrcP.h \ + AsciiText.h AsciiTextP.h Box.h BoxP.h Cardinals.h Command.h \ + CommandP.h Dialog.h DialogP.h Form.h FormP.h Grip.h GripP.h \ + Label.h LabelP.h Layout.h LayoutP.h List.h ListP.h MenuButton.h \ + MenuButtoP.h Paned.h PanedP.h Panner.h PannerP.h Porthole.h \ + PortholeP.h Repeater.h RepeaterP.h Reports.h Scrollbar.h \ + ScrollbarP.h Simple.h SimpleP.h SimpleMenu.h SimpleMenP.h Sme.h \ + SmeP.h SmeBSB.h SmeBSBP.h SmeLine.h SmeLineP.h SmeThreeD.h \ + SmeThreeDP.h StripChart.h StripCharP.h Template.c Template.h \ + TemplateP.h Text.h TextP.h TextSink.h TextSinkP.h TextSrc.h \ + TextSrcP.h ThreeD.h ThreeDP.h Tip.h TipP.h Toggle.h ToggleP.h \ + Tree.h TreeP.h Viewport.h ViewportP.h Xaw3dP.h XawInit.h + +I18N_HDRS = MultiSrc.h MultiSrcP.h MultiSink.h MultiSinkP.h VendorEP.h \ + XawImP.h + +BASE_SRCS = AllWidgets.c AsciiSink.c AsciiSrc.c AsciiText.c Box.c \ + Command.c Dialog.c Form.c Grip.c Label.c Layout.c List.c \ + MenuButton.c Paned.c Panner.c Porthole.c Repeater.c Scrollbar.c \ + Simple.c SimpleMenu.c Sme.c SmeBSB.c SmeLine.c SmeThreeD.c \ + StripChart.c Text.c TextSink.c TextSrc.c TextAction.c TextPop.c \ + TextTr.c ThreeD.c Tip.c Toggle.c Tree.c Vendor.c Viewport.c \ + Xaw3dP.c XawInit.c sharedlib.c laygram.c laylex.c + +I18N_SRCS = MultiSrc.c MultiSink.c XawIm.c XawI18n.c + +#if SharedDataSeparation +UNSHAREDOBJS = AllWidgets.o sharedlib.o +#endif + +BASE_OBJS = AllWidgets.o AsciiSink.o AsciiSrc.o AsciiText.o Box.o \ + Command.o Dialog.o Form.o Grip.o Label.o Layout.o List.o \ + MenuButton.o Paned.o Panner.o Porthole.o Repeater.o Scrollbar.o \ + Simple.o SimpleMenu.o Sme.o SmeBSB.o SmeLine.o SmeThreeD.o \ + StripChart.o Text.o TextSink.o TextSrc.o TextAction.o TextPop.o \ + TextTr.o ThreeD.o Tip.o Toggle.o Tree.o Vendor.o Viewport.o \ + Xaw3dP.o XawInit.o laygram.o laylex.o + +I18N_OBJS = MultiSrc.o MultiSink.o XawIm.o XawI18n.o + +#ifdef XawI18nDefines +#define INTERNATIONALIZATION +HEADERS = $(BASE_HDRS) $(I18N_HDRS) +SRCS = $(BASE_SRCS) $(I18N_SRCS) +OBJS = $(BASE_OBJS) $(I18N_OBJS) +#else +#undef INTERNATIONALIZATION +HEADERS = $(BASE_HDRS) +SRCS = $(BASE_SRCS) +OBJS = $(BASE_OBJS) +#endif + +#include <Library.tmpl> + +#if DoSharedLib && SharedDataSeparation +SpecialCObjectRule(sharedlib.o,NullParameter,$(SHLIBDEF)) +#endif + +XCOMM At least one X11R5 distribution needs this: +XCOMM #include "Imakefrag.X11R5" + +#ifdef LexCmd +LEX = LexCmd +#endif +#ifdef YaccCmd +YACC = YaccCmd +#endif + +#ifdef INTERNATIONALIZATION +XAW_INTERNATIONALIZATION = \ + -e 's/\/\* I18n support \*\//\#define XAW_INTERNATIONALIZATION/' +#else +XAW_INTERNATIONALIZATION = \ + -e 's/\/\* I18n support \*\//\#undef XAW_INTERNATIONALIZATION/' +#endif +#ifdef MULTIPLANE_PIXMAPS +XAW_MULTIPLANE_PIXMAPS = \ + -e 's/\/\* XPM support \*\//\#define XAW_MULTIPLANE_PIXMAPS/' +#else +XAW_MULTIPLANE_PIXMAPS = \ + -e 's/\/\* XPM support \*\//\#undef XAW_MULTIPLANE_PIXMAPS/' +#endif +#ifdef GRAY_BLKWHT_STIPPLES +XAW_GRAY_BLKWHT_STIPPLES = \ + -e 's/\/\* gray stipples \*\//\#define XAW_GRAY_BLKWHT_STIPPLES/' +#else +XAW_GRAY_BLKWHT_STIPPLES = \ + -e 's/\/\* gray stipples \*\//\#undef XAW_GRAY_BLKWHT_STIPPLES/' +#endif +#ifdef ARROW_SCROLLBARS +XAW_ARROW_SCROLLBARS = \ + -e 's/\/\* arrow scrollbars \*\//\#define XAW_ARROW_SCROLLBARS/' +#else +XAW_ARROW_SCROLLBARS = \ + -e 's/\/\* arrow scrollbars \*\//\#undef XAW_ARROW_SCROLLBARS/' +#endif + +depend:: laygram.c laygram.h laylex.c Xaw3dP.h + +clean:: + $(RM) laygram.c laygram.h laylex.c Xaw3dP.h + +distclean:: + LibCleanDir(X11) + +laygram.c: laygram.y + $(YACC) -d laygram.y + sed -e 's/yy/LayYY/g' y.tab.c > laygram.c + sed -e 's/yy/LayYY/g' y.tab.h > laygram.h + $(RM) y.tab.c y.tab.h + +laylex.c: laylex.l + $(LEX) laylex.l + sed -e 's/yy/LayYY/g' lex.yy.c > laylex.c + $(RM) lex.yy.c + +Xaw3dP.h: Xaw3dP.h.sed + sed $(XAW_INTERNATIONALIZATION) $(XAW_MULTIPLANE_PIXMAPS) \ + $(XAW_GRAY_BLKWHT_STIPPLES) $(XAW_ARROW_SCROLLBARS) \ + Xaw3dP.h.sed > Xaw3dP.h + +$(OBJS): Xaw3dP.h + +DependTarget() + diff --git a/src/Imakefrag.X11R5 b/src/Imakefrag.X11R5 new file mode 100644 index 0000000..6c26ddc --- /dev/null +++ b/src/Imakefrag.X11R5 @@ -0,0 +1,33 @@ +XCOMM make rules for X11R5 ------------------------------- + +#if DoSharedLib +#if DoNormalLib +SharedLibraryTarget(Xaw3d,$(SOXAWREV),$(OBJS),shared,..) +#else +SharedLibraryTarget(Xaw3d,$(SOXAWREV),$(OBJS),.,.) +#endif +SharedLibraryDataTarget(Xaw3d,$(SOXAWREV),$(UNSHAREDOBJS)) +InstallSharedLibrary(Xaw3d,$(SOXAWREV),$(USRLIBDIR)) +InstallSharedLibraryData(Xaw3d,$(SOXAWREV),$(USRLIBDIR)) +#endif +#if DoNormalLib +NormalLibraryTarget(Xaw3d,$(OBJS)) +InstallLibrary(Xaw3d,$(USRLIBDIR)) +#endif +#if DoProfileLib +ProfiledLibraryTarget(Xaw3d,$(OBJS)) +InstallLibrary(Xaw3d_p,$(USRLIBDIR)) +#endif +#if DoDebugLib +DebuggedLibraryTarget(Xaw3d,$(OBJS)) +InstallLibrary(Xaw3d_d,$(USRLIBDIR)) +#endif + +LintLibraryTarget(Xaw3d,$(SRCS)) +InstallLintLibrary(Xaw3d,$(LINTLIBDIR)) + +BuildIncludes($(HEADERS),Xaw3d,..) + +InstallMultiple($(HEADERS),$(INCDIR)/Xaw3d) + +XCOMM end make rules for X11R5 --------------------------- diff --git a/src/Label.c b/src/Label.c new file mode 100644 index 0000000..5fd2e32 --- /dev/null +++ b/src/Label.c @@ -0,0 +1,871 @@ +/* $XConsortium: Label.c,v 1.97 94/04/17 20:12:12 kaleb Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * Label.c - Label widget + * + */ + +#include "Xaw3dP.h" +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xos.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/LabelP.h> +#include <X11/Xmu/Converters.h> +#include <X11/Xmu/Drawing.h> +#include <stdio.h> +#include <ctype.h> + +/* needed for abs() */ +#ifndef X_NOT_STDC_ENV +#include <stdlib.h> +#else +int abs(); +#endif + +#define streq(a,b) (strcmp( (a), (b) ) == 0) + +#define MULTI_LINE_LABEL 32767 + +#ifdef CRAY +#define WORD64 +#endif + +/**************************************************************** + * + * Full class record constant + * + ****************************************************************/ + +/* Private Data */ + +#define offset(field) XtOffsetOf(LabelRec, field) +static XtResource resources[] = { + {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), + offset(label.foreground), XtRString, XtDefaultForeground}, + {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *), + offset(label.font),XtRString, XtDefaultFont}, +#ifdef XAW_INTERNATIONALIZATION + {XtNfontSet, XtCFontSet, XtRFontSet, sizeof(XFontSet ), + offset(label.fontset),XtRString, XtDefaultFontSet}, +#endif + {XtNlabel, XtCLabel, XtRString, sizeof(String), + offset(label.label), XtRString, NULL}, + {XtNencoding, XtCEncoding, XtRUnsignedChar, sizeof(unsigned char), + offset(label.encoding), XtRImmediate, (XtPointer)XawTextEncoding8bit}, + {XtNjustify, XtCJustify, XtRJustify, sizeof(XtJustify), + offset(label.justify), XtRImmediate, (XtPointer)XtJustifyCenter}, + {XtNinternalWidth, XtCWidth, XtRDimension, sizeof(Dimension), + offset(label.internal_width), XtRImmediate, (XtPointer)4}, + {XtNinternalHeight, XtCHeight, XtRDimension, sizeof(Dimension), + offset(label.internal_height), XtRImmediate, (XtPointer)2}, + {XtNleftBitmap, XtCLeftBitmap, XtRBitmap, sizeof(Pixmap), + offset(label.left_bitmap), XtRImmediate, (XtPointer) None}, + {XtNbitmap, XtCPixmap, XtRBitmap, sizeof(Pixmap), + offset(label.pixmap), XtRImmediate, (XtPointer)None}, + {XtNresize, XtCResize, XtRBoolean, sizeof(Boolean), + offset(label.resize), XtRImmediate, (XtPointer)True}, + {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension), + XtOffsetOf(RectObjRec,rectangle.border_width), XtRImmediate, + (XtPointer)1} +}; +#undef offset + +static void Initialize(); +static void Resize(); +static void Redisplay(); +static Boolean SetValues(); +static void ClassInitialize(); +static void Destroy(); +static XtGeometryResult QueryGeometry(); + +LabelClassRec labelClassRec = { + { +/* core_class fields */ + /* superclass */ (WidgetClass) &threeDClassRec, + /* class_name */ "Label", + /* widget_size */ sizeof(LabelRec), + /* 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 */ 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 + }, +/* Simple class fields initialization */ + { + /* change_sensitive */ XtInheritChangeSensitive + }, +/* ThreeD class fields initialization */ + { + /* shadowdraw */ XtInheritXaw3dShadowDraw + }, +/* Label class fields initialization */ + { + /* ignore */ 0 + } +}; + +WidgetClass labelWidgetClass = (WidgetClass)&labelClassRec; + +/**************************************************************** + * + * Private Procedures + * + ****************************************************************/ + +static void ClassInitialize() +{ + XawInitializeWidgetSet(); + XtAddConverter( XtRString, XtRJustify, XmuCvtStringToJustify, + (XtConvertArgList)NULL, 0 ); +} + +#ifndef WORD64 + +#define TXT16 XChar2b + +#else + +#define TXT16 char + +static XChar2b *buf2b; +static int buf2blen = 0; + +_XawLabelWidth16(fs, str, n) + XFontStruct *fs; + char *str; + int n; +{ + int i; + XChar2b *ptr; + + if (n > buf2blen) { + buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b)); + buf2blen = n; + } + for (ptr = buf2b, i = n; --i >= 0; ptr++) { + ptr->byte1 = *str++; + ptr->byte2 = *str++; + } + return XTextWidth16(fs, buf2b, n); +} + +_XawLabelDraw16(dpy, d, gc, x, y, str, n) + Display *dpy; + Drawable d; + GC gc; + int x, y; + char *str; + int n; +{ + int i; + XChar2b *ptr; + + if (n > buf2blen) { + buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b)); + buf2blen = n; + } + for (ptr = buf2b, i = n; --i >= 0; ptr++) { + ptr->byte1 = *str++; + ptr->byte2 = *str++; + } + XDrawString16(dpy, d, gc, x, y, buf2b, n); +} + +#define XTextWidth16 _XawLabelWidth16 +#define XDrawString16 _XawLabelDraw16 + +#endif /* WORD64 */ + +/* + * Calculate width and height of displayed text in pixels + */ + +static void SetTextWidthAndHeight(lw) + LabelWidget lw; +{ + XFontStruct *fs = lw->label.font; + + char *nl; + + if (lw->label.pixmap != None) { + Window root; + int x, y; + unsigned int width, height, bw, depth; + + if (XGetGeometry(XtDisplay(lw), lw->label.pixmap, &root, &x, &y, + &width, &height, &bw, &depth)) { + lw->label.label_height = height; + lw->label.label_width = width; + lw->label.depth = depth; + return; + } + } +#ifdef XAW_INTERNATIONALIZATION + if ( lw->simple.international == True ) { + XFontSet fset = lw->label.fontset; + XFontSetExtents *ext = XExtentsOfFontSet(fset); + + lw->label.label_height = ext->max_ink_extent.height; + if (lw->label.label == NULL) { + lw->label.label_len = 0; + lw->label.label_width = 0; + } + else if ((nl = index(lw->label.label, '\n')) != NULL) { + char *label; + lw->label.label_len = MULTI_LINE_LABEL; + lw->label.label_width = 0; + for (label = lw->label.label; nl != NULL; nl = index(label, '\n')) { + int width = XmbTextEscapement(fset, label, (int)(nl - label)); + + if (width > (int)lw->label.label_width) + lw->label.label_width = width; + label = nl + 1; + if (*label) + lw->label.label_height += + ext->max_ink_extent.height; + } + if (*label) { + int width = XmbTextEscapement(fset, label, strlen(label)); + + if (width > (int) lw->label.label_width) + lw->label.label_width = width; + } + } else { + lw->label.label_len = strlen(lw->label.label); + lw->label.label_width = + XmbTextEscapement(fset, lw->label.label, (int) lw->label.label_len); + } + + } else +#endif + { + lw->label.label_height = fs->max_bounds.ascent + fs->max_bounds.descent; + if (lw->label.label == NULL) { + lw->label.label_len = 0; + lw->label.label_width = 0; + } + else if ((nl = index(lw->label.label, '\n')) != NULL) { + char *label; + lw->label.label_len = MULTI_LINE_LABEL; + lw->label.label_width = 0; + for (label = lw->label.label; nl != NULL; nl = index(label, '\n')) { + int width; + + if (lw->label.encoding) + width = XTextWidth16(fs, (TXT16*)label, (int)(nl - label)/2); + else + width = XTextWidth(fs, label, (int)(nl - label)); + if (width > (int)lw->label.label_width) + lw->label.label_width = width; + label = nl + 1; + if (*label) + lw->label.label_height += + fs->max_bounds.ascent + fs->max_bounds.descent; + } + if (*label) { + int width = XTextWidth(fs, label, strlen(label)); + + if (lw->label.encoding) + width = XTextWidth16(fs, (TXT16*)label, (int)strlen(label)/2); + else + width = XTextWidth(fs, label, strlen(label)); + if (width > (int) lw->label.label_width) + lw->label.label_width = width; + } + } else { + lw->label.label_len = strlen(lw->label.label); + if (lw->label.encoding) + lw->label.label_width = + XTextWidth16(fs, (TXT16*)lw->label.label, + (int) lw->label.label_len/2); + else + lw->label.label_width = + XTextWidth(fs, lw->label.label, (int) lw->label.label_len); + } + + } +} + +static void GetnormalGC(lw) + LabelWidget lw; +{ + XGCValues values; + + values.foreground = lw->label.foreground; + values.background = lw->core.background_pixel; + values.font = lw->label.font->fid; + values.graphics_exposures = False; + +#ifdef XAW_INTERNATIONALIZATION + if ( lw->simple.international == True ) + /* Since Xmb/wcDrawString eats the font, I must use XtAllocateGC. */ + lw->label.normal_GC = XtAllocateGC( + (Widget)lw, 0, + (unsigned) GCForeground | GCBackground | GCGraphicsExposures, + &values, GCFont, 0 ); + else +#endif + lw->label.normal_GC = XtGetGC( + (Widget)lw, + (unsigned) GCForeground | GCBackground | GCFont | GCGraphicsExposures, + &values); +} + +static void GetgrayGC(lw) + LabelWidget lw; +{ + XGCValues values; + + values.foreground = lw->label.foreground; + values.background = lw->core.background_pixel; + values.font = lw->label.font->fid; + values.fill_style = FillTiled; + values.tile = XmuCreateStippledPixmap(XtScreen((Widget)lw), + lw->label.foreground, + lw->core.background_pixel, + lw->core.depth); + values.graphics_exposures = False; + + lw->label.stipple = values.tile; +#ifdef XAW_INTERNATIONALIZATION + if ( lw->simple.international == True ) + /* Since Xmb/wcDrawString eats the font, I must use XtAllocateGC. */ + lw->label.gray_GC = XtAllocateGC((Widget)lw, 0, + (unsigned) GCForeground | GCBackground | + GCTile | GCFillStyle | + GCGraphicsExposures, + &values, GCFont, 0); + else +#endif + lw->label.gray_GC = XtGetGC((Widget)lw, + (unsigned) GCForeground | GCBackground | + GCFont | GCTile | GCFillStyle | + GCGraphicsExposures, + &values); +} + +static void compute_bitmap_offsets (lw) + LabelWidget lw; +{ + if (lw->label.lbm_height != 0) + lw->label.lbm_y = (lw->core.height - lw->label.lbm_height) / 2; + else + lw->label.lbm_y = 0; +} + +static void set_bitmap_info (lw) + LabelWidget lw; +{ + Window root; + int x, y; + unsigned int bw; + + if (lw->label.pixmap || !(lw->label.left_bitmap && + XGetGeometry (XtDisplay(lw), lw->label.left_bitmap, &root, &x, &y, + &lw->label.lbm_width, &lw->label.lbm_height, + &bw, &lw->label.depth))) { + lw->label.lbm_width = lw->label.lbm_height = 0; + } + compute_bitmap_offsets (lw); +} + +/* ARGSUSED */ +static void Initialize(request, new, args, num_args) + Widget request, new; + ArgList args; + Cardinal *num_args; +{ + extern WidgetClass commandWidgetClass; + LabelWidget lw = (LabelWidget) new; + + /* disable shadows if we're not a subclass of Command */ + if (!XtIsSubclass(new, commandWidgetClass)) + lw->threeD.shadow_width = 0; + + if (lw->label.label == NULL) + lw->label.label = XtNewString(lw->core.name); + else + lw->label.label = XtNewString(lw->label.label); + + GetnormalGC(lw); + GetgrayGC(lw); + + SetTextWidthAndHeight(lw); /* label.label or label.pixmap */ + + if (lw->core.height == 0) + lw->core.height = lw->label.label_height + + 2 * lw->label.internal_height; + + set_bitmap_info(lw); /* req's core.height, sets label.lbm_* */ + + if (lw->label.lbm_height > lw->label.label_height) + lw->core.height = lw->label.lbm_height + + 2 * lw->label.internal_height; + + if (lw->core.width == 0) + lw->core.width = lw->label.label_width + + 2 * lw->label.internal_width + + LEFT_OFFSET(lw); /* req's label.lbm_width */ + + lw->label.label_x = lw->label.label_y = 0; + (*XtClass(new)->core_class.resize) ((Widget)lw); + + lw->label.stippled = lw->label.left_stippled = None; +} /* Initialize */ + +/* + * Repaint the widget window + */ + +/* ARGSUSED */ +static void Redisplay(gw, event, region) + Widget gw; + XEvent *event; + Region region; +{ + extern WidgetClass commandWidgetClass; + LabelWidget w = (LabelWidget) gw; + LabelWidgetClass lwclass = (LabelWidgetClass) XtClass (gw); + Pixmap pm; + GC gc; + + /* + * Don't draw shadows if Command is going to redraw them. + * The shadow draw method is region aware, but since 99% of + * all labels don't have shadows, we'll check for a shadow + * before we incur the function call overhead. + */ + if (!XtIsSubclass (gw, commandWidgetClass) && w->threeD.shadow_width > 0) + (*lwclass->threeD_class.shadowdraw) (gw, event, region, + w->threeD.relief, True); + + /* + * now we'll see if we need to draw the rest of the label + */ + if (region != NULL) { + int x = w->label.label_x; + unsigned int width = w->label.label_width; + if (w->label.lbm_width) { + if (w->label.label_x > (x = w->label.internal_width)) + width += w->label.label_x - x; + } + if (XRectInRegion(region, x, w->label.label_y, + width, w->label.label_height) == RectangleOut){ + return; + } + } + + gc = XtIsSensitive(gw) ? w->label.normal_GC : w->label.gray_GC; +#ifdef notdef + if (region != NULL) + XSetRegion(XtDisplay(gw), gc, region); +#endif /*notdef*/ + + if (w->label.pixmap == None) { + int len = w->label.label_len; + char *label = w->label.label; + Position y = w->label.label_y + w->label.font->max_bounds.ascent; + Position ksy = w->label.label_y; + + /* display left bitmap */ + if (w->label.left_bitmap && w->label.lbm_width != 0) { + pm = w->label.left_bitmap; +#ifdef XAW_MULTIPLANE_PIXMAPS + if (!XtIsSensitive(gw)) { + if (w->label.left_stippled == None) + w->label.left_stippled = stipplePixmap(gw, + w->label.left_bitmap, w->core.colormap, + w->core.background_pixel, w->label.depth); + if (w->label.left_stippled != None) + pm = w->label.left_stippled; + } +#endif + + if (w->label.depth == 1) + XCopyPlane(XtDisplay(gw), pm, XtWindow(gw), gc, 0, 0, + w->label.lbm_width, w->label.lbm_height, + (int) w->label.internal_width, + (int) w->label.lbm_y, + (unsigned long) 1L); + else + XCopyArea(XtDisplay(gw), pm, XtWindow(gw), gc, 0, 0, + w->label.lbm_width, w->label.lbm_height, + (int) w->label.internal_width, + (int) w->label.lbm_y); + } + +#ifdef XAW_INTERNATIONALIZATION + if ( w->simple.international == True ) { + + XFontSetExtents *ext = XExtentsOfFontSet(w->label.fontset); + + ksy += abs(ext->max_ink_extent.y); + + if (len == MULTI_LINE_LABEL) { + char *nl; + while ((nl = index(label, '\n')) != NULL) { + XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset, gc, + w->label.label_x, ksy, label, (int)(nl - label)); + ksy += ext->max_ink_extent.height; + label = nl + 1; + } + len = strlen(label); + } + if (len) + XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset, gc, + w->label.label_x, ksy, label, len); + + } else +#endif + { /* international false, so use R5 routine */ + + if (len == MULTI_LINE_LABEL) { + char *nl; + while ((nl = index(label, '\n')) != NULL) { + if (w->label.encoding) + XDrawString16(XtDisplay(gw), XtWindow(gw), gc, + w->label.label_x, y, + (TXT16*)label, (int)(nl - label)/2); + else + XDrawString(XtDisplay(gw), XtWindow(gw), gc, + w->label.label_x, y, label, (int)(nl - label)); + y += w->label.font->max_bounds.ascent + + w->label.font->max_bounds.descent; + label = nl + 1; + } + len = strlen(label); + } + if (len) { + if (w->label.encoding) + XDrawString16(XtDisplay(gw), XtWindow(gw), gc, + w->label.label_x, y, (TXT16*)label, len/2); + else + XDrawString(XtDisplay(gw), XtWindow(gw), gc, + w->label.label_x, y, label, len); + } + + } /* endif international */ + + } else { + pm = w->label.pixmap; +#ifdef XAW_MULTIPLANE_PIXMAPS + if (!XtIsSensitive(gw)) { + if (w->label.stippled == None) + w->label.stippled = stipplePixmap(gw, + w->label.pixmap, w->core.colormap, + w->core.background_pixel, w->label.depth); + if (w->label.stippled != None) + pm = w->label.stippled; + } +#endif + + if (w->label.depth == 1) + XCopyPlane(XtDisplay(gw), pm, XtWindow(gw), gc, 0, 0, + w->label.label_width, w->label.label_height, + w->label.label_x, w->label.label_y, + 1L); + else + XCopyArea(XtDisplay(gw), pm, XtWindow(gw), gc, 0, 0, + w->label.label_width, w->label.label_height, + w->label.label_x, w->label.label_y); + } + +#ifdef notdef + if (region != NULL) + XSetClipMask(XtDisplay(gw), gc, (Pixmap)None); +#endif /* notdef */ +} + +static void _Reposition(lw, width, height, dx, dy) + LabelWidget lw; + Dimension width, height; + Position *dx, *dy; +{ + Position newPos; + Position leftedge = lw->label.internal_width + LEFT_OFFSET(lw); + + switch (lw->label.justify) { + case XtJustifyLeft: + newPos = leftedge; + break; + case XtJustifyRight: + newPos = width - lw->label.label_width - lw->label.internal_width; + break; + case XtJustifyCenter: + default: + newPos = (int)(width - lw->label.label_width) / 2; + break; + } + + if (newPos < (Position)leftedge) + newPos = leftedge; + *dx = newPos - lw->label.label_x; + lw->label.label_x = newPos; + + *dy = (newPos = (int)(height - lw->label.label_height) / 2) + - lw->label.label_y; + lw->label.label_y = newPos; + + lw->label.lbm_y = (height - lw->label.lbm_height) / 2; + + return; +} + +static void Resize(w) + Widget w; +{ + LabelWidget lw = (LabelWidget)w; + Position dx, dy; + + _Reposition(lw, w->core.width, w->core.height, &dx, &dy); + compute_bitmap_offsets (lw); +} + +/* + * Set specified arguments into widget + */ + +#define PIXMAP 0 +#define WIDTH 1 +#define HEIGHT 2 +#define NUM_CHECKS 3 + +static Boolean SetValues(current, request, new, args, num_args) + Widget current, request, new; + ArgList args; + Cardinal *num_args; +{ + LabelWidget curlw = (LabelWidget) current; + LabelWidget reqlw = (LabelWidget) request; + LabelWidget newlw = (LabelWidget) new; + int i; + Boolean was_resized = False, redisplay = False, checks[NUM_CHECKS]; + + for (i = 0; i < NUM_CHECKS; i++) + checks[i] = FALSE; + for (i = 0; i < *num_args; i++) { + if (streq(XtNbitmap, args[i].name)) + checks[PIXMAP] = TRUE; + if (streq(XtNwidth, args[i].name)) + checks[WIDTH] = TRUE; + if (streq(XtNheight, args[i].name)) + checks[HEIGHT] = TRUE; + } + + if (newlw->label.label == NULL) + newlw->label.label = newlw->core.name; + if (curlw->label.label != newlw->label.label) { + if (curlw->label.label != curlw->core.name) + XtFree((char *)curlw->label.label); + if (newlw->label.label != newlw->core.name) + newlw->label.label = XtNewString(newlw->label.label); + was_resized = True; + } + + if (was_resized || checks[PIXMAP] || + curlw->label.font != newlw->label.font || +#ifdef XAW_INTERNATIONALIZATION + (curlw->simple.international && + curlw->label.fontset != newlw->label.fontset) || +#endif + curlw->label.encoding != newlw->label.encoding || + curlw->label.justify != newlw->label.justify) { + SetTextWidthAndHeight(newlw); /* label.label or label.pixmap */ + was_resized = True; + } + + if (curlw->label.left_bitmap != newlw->label.left_bitmap || + curlw->label.internal_width != newlw->label.internal_width || + curlw->label.internal_height != newlw->label.internal_height) + was_resized = True; + + /* recalculate the window size if something has changed. */ + if (newlw->label.resize && was_resized) { + if (curlw->core.height == reqlw->core.height && !checks[HEIGHT]) + newlw->core.height = newlw->label.label_height + + 2 * newlw->label.internal_height; + + set_bitmap_info (newlw); /* req's core.height, sets label.lbm_* */ + + if (newlw->label.lbm_height > newlw->label.label_height) + newlw->core.height = newlw->label.lbm_height + + 2 * newlw->label.internal_height; + + if (curlw->core.width == reqlw->core.width && !checks[WIDTH]) + newlw->core.width = newlw->label.label_width + + 2 * newlw->label.internal_width + + LEFT_OFFSET(newlw); /* req's label.lbm_width */ + } + + /* enforce minimum dimensions */ + if (newlw->label.resize) { + if (checks[HEIGHT]) { + if (newlw->label.label_height > newlw->label.lbm_height) + i = newlw->label.label_height + + 2 * newlw->label.internal_height; + else + i = newlw->label.lbm_height + 2 * newlw->label.internal_height; + if (i > newlw->core.height) + newlw->core.height = i; + } + if (checks[WIDTH]) { + i = newlw->label.label_width + 2 * newlw->label.internal_width + + LEFT_OFFSET(newlw); /* req's label.lbm_width */ + if (i > newlw->core.width) + newlw->core.width = i; + } + } + + if (curlw->core.background_pixel != newlw->core.background_pixel || + curlw->label.foreground != newlw->label.foreground || + curlw->label.font->fid != newlw->label.font->fid) { + /* the fontset is not in the GC - no new GC if fontset changes */ + XtReleaseGC(new, curlw->label.normal_GC); + XtReleaseGC(new, curlw->label.gray_GC); + XmuReleaseStippledPixmap( XtScreen(current), curlw->label.stipple ); + GetnormalGC(newlw); + GetgrayGC(newlw); + redisplay = True; + } + +#ifdef XAW_MULTIPLANE_PIXMAPS + if (curlw->label.pixmap != newlw->label.pixmap) + { + newlw->label.stippled = None; + if (curlw->label.stippled != None) + XFreePixmap(XtDisplay(current), curlw->label.stippled); + } + if (curlw->label.left_bitmap != newlw->label.left_bitmap) + { + newlw->label.left_stippled = None; + if (curlw->label.left_stippled != None) + XFreePixmap(XtDisplay(current), curlw->label.left_stippled); + } +#endif + + if (was_resized) { + Position dx, dy; + + /* Resize() will be called if geometry changes succeed */ + _Reposition(newlw, curlw->core.width, curlw->core.height, &dx, &dy); + } + + return was_resized || redisplay || + XtIsSensitive(current) != XtIsSensitive(new); +} + +static void Destroy(w) + Widget w; +{ + LabelWidget lw = (LabelWidget)w; + + if ( lw->label.label != lw->core.name ) + XtFree( lw->label.label ); + XtReleaseGC( w, lw->label.normal_GC ); + XtReleaseGC( w, lw->label.gray_GC); +#ifdef XAW_MULTIPLANE_PIXMAPS + if (lw->label.stippled != None) + XFreePixmap(XtDisplay(w), lw->label.stippled); + if (lw->label.left_stippled != None) + XFreePixmap(XtDisplay(w), lw->label.left_stippled); +#endif + XmuReleaseStippledPixmap( XtScreen(w), lw->label.stipple ); +} + + +static XtGeometryResult QueryGeometry(w, intended, preferred) + Widget w; + XtWidgetGeometry *intended, *preferred; +{ + LabelWidget lw = (LabelWidget)w; + + preferred->request_mode = CWWidth | CWHeight; + preferred->width = (lw->label.label_width + + 2 * lw->label.internal_width + + LEFT_OFFSET(lw)); + preferred->height = lw->label.label_height + + 2 * lw->label.internal_height; + if ( ((intended->request_mode & (CWWidth | CWHeight)) + == (CWWidth | CWHeight)) && + intended->width == preferred->width && + intended->height == preferred->height) + return XtGeometryYes; + else if (preferred->width == w->core.width && + preferred->height == w->core.height) + return XtGeometryNo; + else + return XtGeometryAlmost; +} diff --git a/src/Label.h b/src/Label.h new file mode 100644 index 0000000..fda186f --- /dev/null +++ b/src/Label.h @@ -0,0 +1,131 @@ +/* $XConsortium: Label.h,v 1.34 94/04/17 20:12:13 rws Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _XawLabel_h +#define _XawLabel_h + +/*********************************************************************** + * + * Label Widget + * + ***********************************************************************/ + +#include "Xaw3dP.h" +#include <X11/Xaw3d/Simple.h> + +/* Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + background Background Pixel XtDefaultBackground + bitmap Pixmap Pixmap None + border BorderColor Pixel XtDefaultForeground + borderWidth BorderWidth Dimension 1 + cursor Cursor Cursor None + cursorName Cursor String NULL + destroyCallback Callback XtCallbackList NULL + encoding Encoding unsigned char XawTextEncoding8bit + font Font XFontStruct* XtDefaultFont + foreground Foreground Pixel XtDefaultForeground + height Height Dimension text height + insensitiveBorder Insensitive Pixmap Gray + internalHeight Height Dimension 2 + internalWidth Width Dimension 4 + justify Justify XtJustify XtJustifyCenter + label Label String NULL + leftBitmap LeftBitmap Pixmap None + mappedWhenManaged MappedWhenManaged Boolean True + pointerColor Foreground Pixel XtDefaultForeground + pointerColorBackground Background Pixel XtDefaultBackground + resize Resize Boolean True + sensitive Sensitive Boolean True + width Width Dimension text width + x Position Position 0 + y Position Position 0 + +*/ + +#define XawTextEncoding8bit 0 +#define XawTextEncodingChar2b 1 + +#define XtNleftBitmap "leftBitmap" +#define XtCLeftBitmap "LeftBitmap" +#define XtNencoding "encoding" +#define XtCEncoding "Encoding" + +#ifdef XAW_INTERNATIONALIZATION +#ifndef XtNfontSet +#define XtNfontSet "fontSet" +#endif +#ifndef XtCFontSet +#define XtCFontSet "FontSet" +#endif +#endif + +#ifndef _XtStringDefs_h_ +#define XtNbitmap "bitmap" +#define XtNforeground "foreground" +#define XtNlabel "label" +#define XtNfont "font" +#define XtNinternalWidth "internalWidth" +#define XtNinternalHeight "internalHeight" +#define XtNresize "resize" +#define XtCResize "Resize" +#define XtCBitmap "Bitmap" +#endif + +/* Class record constants */ + +extern WidgetClass labelWidgetClass; + +typedef struct _LabelClassRec *LabelWidgetClass; +typedef struct _LabelRec *LabelWidget; + +#endif /* _XawLabel_h */ diff --git a/src/LabelP.h b/src/LabelP.h new file mode 100644 index 0000000..e56a004 --- /dev/null +++ b/src/LabelP.h @@ -0,0 +1,137 @@ +/* +* $XConsortium: LabelP.h,v 1.29 94/04/17 20:12:14 kaleb Exp $ +*/ + + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * LabelP.h - Private definitions for Label widget + * + */ + +#ifndef _XawLabelP_h +#define _XawLabelP_h + +/*********************************************************************** + * + * Label Widget Private Data + * + ***********************************************************************/ + +#include "Xaw3dP.h" +#include <X11/Xaw3d/Label.h> +#include <X11/Xaw3d/ThreeDP.h> + +/* New fields for the Label widget class record */ + +typedef struct {int foo;} LabelClassPart; + +/* Full class record declaration */ +typedef struct _LabelClassRec { + CoreClassPart core_class; + SimpleClassPart simple_class; + ThreeDClassPart threeD_class; + LabelClassPart label_class; +} LabelClassRec; + +extern LabelClassRec labelClassRec; + +/* New fields for the Label widget record */ +typedef struct { + /* resources */ + Pixel foreground; + XFontStruct *font; +#ifdef XAW_INTERNATIONALIZATION + XFontSet fontset; +#endif + char *label; + XtJustify justify; + Dimension internal_width; + Dimension internal_height; + Pixmap pixmap; + Boolean resize; + unsigned char encoding; + Pixmap left_bitmap; + + /* private state */ + GC normal_GC; + GC gray_GC; + Pixmap stipple; + Pixmap stippled; /* insensitive pixmap */ + Pixmap left_stippled; /* ditto */ + Position label_x; + Position label_y; + Dimension label_width; + Dimension label_height; + Dimension label_len; + int lbm_y; /* where in label */ + unsigned int lbm_width, lbm_height; /* size of pixmap */ + unsigned int depth; /* depth of pixmaps */ +} LabelPart; + + +/**************************************************************** + * + * Full instance record declaration + * + ****************************************************************/ + +typedef struct _LabelRec { + CorePart core; + SimplePart simple; + ThreeDPart threeD; + LabelPart label; +} LabelRec; + +#define LEFT_OFFSET(lw) ((lw)->label.left_bitmap && (lw)->label.pixmap == None \ + ? (lw)->label.lbm_width + (lw)->label.internal_width \ + : 0) + +#endif /* _XawLabelP_h */ diff --git a/src/Layout.c b/src/Layout.c new file mode 100644 index 0000000..44d391a --- /dev/null +++ b/src/Layout.c @@ -0,0 +1,1049 @@ +/* + * $XConsortium: Layout.c,v 1.1 91/09/13 18:51:44 keith Exp $ + * + * Copyright 1991 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. + * 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 TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, MIT X Consortium + */ + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> + +#include <X11/Xmu/Misc.h> +#include <X11/Xmu/Converters.h> + +#ifdef MOTIF +# include <Xm/XmP.h> +#endif + +#if defined(LAYOUT) +# include "LayoutP.h" +#else +# include <X11/Xaw3d/LayoutP.h> +#endif + +#include <ctype.h> +#include <stdio.h> + +#undef DEBUG +#ifdef DEBUG +static char *DBUG_currentproc, *DBUG_lastproc; +static int DBUG_level = 0; +# define DBUG_ENTER(s) \ + {DBUG_lastproc=DBUG_currentproc;DBUG_currentproc=s;\ + fprintf(stderr,"begin: (%d) %s\n",++DBUG_level,s);} +# define DBUG_VOID_RETURN \ + {fprintf(stderr,"end: (%d) %s\n",DBUG_level--,DBUG_currentproc); \ + DBUG_currentproc=DBUG_lastproc;return;} +# define DBUG_RETURN(f,v) \ + {fprintf(stderr,"return (%d) %s (",DBUG_level--,DBUG_currentproc); \ + fprintf(stderr,(f),(v)); \ + fprintf(stderr,")\n"); DBUG_currentproc=DBUG_lastproc;return (v);} +# define DBUG_PRINT(f,s) \ + {fprintf(stderr," (%d) %s:",DBUG_level, DBUG_currentproc); \ + fprintf(stderr,f,s);fprintf(stderr,"\n");} +#else +# define DBUG_ENTER(s) +# define DBUG_VOID_RETURN return +# define DBUG_PRINT(f,s) +# define DBUG_RETURN(f,v) return(v) +#endif + +/***************************************************************************** + * + * Full instance record declaration + * + ****************************************************************************/ + +#define offset(field) XtOffsetOf(LayoutRec, layout.field) + +static XtResource resources[] = { + {XtNlayout, XtCLayout, XtRLayout, sizeof (BoxPtr), + offset(layout), XtRLayout, NULL }, + {XtNdebug, XtCBoolean, XtRBoolean, sizeof(Boolean), + offset(debug), XtRImmediate, (XtPointer) FALSE}, +}; + +#undef offset + +static void ClassInitialize(), Initialize(); +static void Resize(); +static Boolean SetValues(); +static XtGeometryResult GeometryManager(); +static void ChangeManaged(); +static void InsertChild(); +static XtGeometryResult QueryGeometry (); +static void GetDesiredSize (); +#ifdef MOTIF +static void Redisplay (); +#endif + +static void LayoutLayout (); +static void LayoutGetNaturalSize (); +static void LayoutFreeLayout (); + +extern void LayYYsetsource(), LayYYsetdest(); +extern int LayYYparse(); + +#ifdef MOTIF +#define SuperClass ((ConstraintWidgetClass)&xmManagerClassRec) +#else +#define SuperClass ((ConstraintWidgetClass)&constraintClassRec) +#endif + +LayoutClassRec layoutClassRec = { + { +/* core class fields */ + /* superclass */ (WidgetClass) SuperClass, + /* class name */ "Layout", + /* size */ sizeof(LayoutRec), + /* class_initialize */ ClassInitialize, + /* class_part init */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ XtInheritRealize, + /* actions */ NULL, + /* num_actions */ 0, + /* resources */ resources, + /* resource_count */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ FALSE, + /* compress_exposure */ 0, + /* compress_enterleave*/ FALSE, + /* visible_interest */ FALSE, + /* destroy */ NULL, + /* resize */ Resize, +#ifdef MOTIF + /* expose */ Redisplay, +#else + /* expose */ NULL, +#endif + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* set_values_almost */ XtInheritSetValuesAlmost, + /* get_values_hook */ NULL, + /* accept_focus */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, +#ifdef MOTIF + /* tm_table */ XtInheritTranslations, +#else + /* tm_table */ NULL, +#endif + /* query_geometry */ QueryGeometry, + /* display_accelerator*/ XtInheritDisplayAccelerator, + /* extension */ NULL + }, { +/* composite class fields */ + /* geometry_manager */ GeometryManager, + /* change_managed */ ChangeManaged, + /* insert_child */ InsertChild, + /* delete_child */ XtInheritDeleteChild, + /* extension */ NULL + }, { +/* constraint class fields */ + /* subresources */ NULL, + /* subresource_count */ 0, + /* constraint_size */ sizeof(LayoutConstraintsRec), + /* initialize */ NULL, + /* destroy */ NULL, + /* set_values */ NULL, + /* extension */ NULL + }, +#ifdef MOTIF + { + /* manager class */ + XtInheritTranslations, /* translations */ + NULL, /* syn resources */ + 0, /* num syn_resources */ + NULL, /* get_cont_resources */ + 0, /* num_get_cont_resources */ + XmInheritParentProcess, /* parent_process */ + NULL, /* extension */ + }, +#endif + { /* layout_class fields */ + 0 + } +}; + +WidgetClass layoutWidgetClass = (WidgetClass) &layoutClassRec; + +#define ForAllChildren(pw, childP) \ + for ( (childP) = (pw)->composite.children ; \ + (childP) < (pw)->composite.children + (pw)->composite.num_children ; \ + (childP)++ ) if (!XtIsManaged(*childP)) ; else + +/************************************************************ + * + * Semi-public routines. + * + ************************************************************/ + +/* Function Name: ClassInitialize + * Description: The Layout widgets class initialization proc. + * Arguments: none. + * Returns: none. + */ + +/*ARGSUSED*/ +static Boolean +CvtStringToLayout (dpy, args, num_args, from, to, converter_data) + Display *dpy; + XrmValue *args; + Cardinal *num_args; + XrmValue *from, *to; + XtPointer *converter_data; +{ + static BoxPtr tmp; + + LayYYsetsource ((char *) from->addr); + if (!to->addr) to->addr = (XtPointer)&tmp; + LayYYsetdest ((BoxPtr *) to->addr); + to->size = sizeof (BoxPtr *); + return LayYYparse() ? FALSE : TRUE; +} + +/*ARGSUSED*/ +static void +DisposeLayout (app, to, data, args, num_args) + XtAppContext app; + XrmValue *to; + XtPointer data; + XrmValuePtr args; + Cardinal *num_args; +{ + LayoutFreeLayout (* (LayoutPtr *) to->addr); +} + +static void +ClassInitialize() +{ + XtSetTypeConverter ( XtRString, XtRLayout, CvtStringToLayout, + (XtConvertArgList)NULL, (Cardinal)0, XtCacheNone, + DisposeLayout ); +} + +#ifdef MOTIF +static void Redisplay ( gw, event, region ) +Widget gw; +XEvent *event; +Region region; +{ + /* + * If the Layout widget is visible, redraw gadgets. + */ + + if ( XtIsRealized ( gw ) && gw->core.visible ) + { + _XmRedisplayGadgets ( gw, event, region ); + } + /* ChangeManaged(gw);*/ +} +#endif + +/*ARGSUSED*/ +static XtGeometryResult GeometryManager(child, request, reply) + Widget child; + XtWidgetGeometry *request, *reply; +{ + LayoutWidget w = (LayoutWidget) XtParent(child); + SubInfoPtr p = SubInfo(child); + int bw; + Bool changed, bwChanged; + + bw = p->naturalBw; + changed = FALSE; + bwChanged = FALSE; + if (request->request_mode & CWBorderWidth && + request->border_width != child->core.border_width) + { + p->naturalBw = bw; + bw = request->border_width; + changed = TRUE; + bwChanged = TRUE; + } + if (bwChanged || ((request->request_mode & CWWidth) && + request->width != child->core.width)) + { + p->naturalSize[LayoutHorizontal] = request->width + bw * 2; + changed = TRUE; + } + if (bwChanged || ((request->request_mode & CWHeight) && + request->height != child->core.height)) + { + p->naturalSize[LayoutVertical] = request->height + bw * 2; + changed = TRUE; + } + if (changed) + LayoutLayout (w, TRUE); + return XtGeometryDone; +} + +/* ARGSUSED */ +static void Initialize(request, new, args, num_args) +Widget request, new; +ArgList args; +Cardinal *num_args; +{ +/* LayoutWidget w = (LayoutWidget)new; */ +} + +static void ChangeManaged(gw) + Widget gw; +{ + LayoutWidget w = (LayoutWidget) gw; + Widget *children; + + DBUG_ENTER("changeManaged"); + + ForAllChildren (w, children) + GetDesiredSize (*children); + LayoutLayout ((LayoutWidget) w, TRUE); +#ifdef MOTIF + _XmNavigChangeManaged ( gw ); +#endif + DBUG_VOID_RETURN; +} + +static void +GetDesiredSize (child) + Widget child; +{ + XtWidgetGeometry desired; + SubInfoPtr p; + + XtQueryGeometry (child, (XtWidgetGeometry *) NULL, &desired); + p = SubInfo (child); + p->naturalBw = desired.border_width; + p->naturalSize[LayoutHorizontal] = desired.width + desired.border_width * 2; + p->naturalSize[LayoutVertical] = desired.height + desired.border_width * 2; +} + +static void InsertChild (child) + Widget child; +{ + (*SuperClass->composite_class.insert_child) (child); + GetDesiredSize (child); +} + +static void +Resize(gw) + Widget gw; +{ + LayoutLayout ((LayoutWidget) gw, FALSE); +} + +/* ARGSUSED */ +static Boolean +SetValues(gold, greq, gnew, args, num_args) + Widget gold, greq, gnew; + ArgList args; + Cardinal *num_args; +{ + LayoutWidget old = (LayoutWidget) gold, + new = (LayoutWidget) gnew; + + if (old->layout.layout != new->layout.layout) + LayoutLayout (new, TRUE); + return FALSE; +} /* SetValues */ + +static XtGeometryResult +QueryGeometry (gw, request, prefered_return) + Widget gw; + XtWidgetGeometry *request, *prefered_return; +{ + LayoutWidget w = (LayoutWidget) gw; + XtGeometryResult result; + XtWidgetGeometry prefered_size; + + if (request && !(request->request_mode & (CWWidth|CWHeight))) + return XtGeometryYes; + LayoutGetNaturalSize (w, &prefered_size.width, &prefered_size.height); + prefered_return->request_mode = 0; + result = XtGeometryYes; + if (!request) { + prefered_return->width = prefered_size.width; + prefered_return->height= prefered_size.height; + if (prefered_size.width != w->core.width) { + prefered_return->request_mode |= CWWidth; + result = XtGeometryAlmost; + } + if (prefered_size.height != w->core.height) { + prefered_return->request_mode |= CWHeight; + result = XtGeometryAlmost; + } + } else { + if (request->request_mode & CWWidth) { + if (prefered_size.width > request->width) + { + if (prefered_size.width == w->core.width) + result = XtGeometryNo; + else if (result != XtGeometryNo) { + result = XtGeometryAlmost; + prefered_return->request_mode |= CWWidth; + prefered_return->width = prefered_size.width; + } + } + } + if (request->request_mode & CWHeight) { + if (prefered_size.height > request->height) + { + if (prefered_size.height == w->core.height) + result = XtGeometryNo; + else if (result != XtGeometryNo) { + result = XtGeometryAlmost; + prefered_return->request_mode |= CWHeight; + prefered_return->height = prefered_size.height; + } + } + } + } + return result; +} + +/* + * Layout section. Exports LayoutGetNaturalSize and + * LayoutLayout to above section + */ + +static void +PrintGlue (g) + GlueRec g; +{ + if (g.order == 0 || g.value != 1.0) + (void) printf ("%g", g.value); + if (g.order > 0) + { + (void) printf ("%s", " inf"); + if (g.order > 1) + (void) printf (" %d", g.order); + } +} + +static void +PrintDirection (dir) + LayoutDirection dir; +{ + switch (dir) { + case LayoutHorizontal: + (void) printf ("%s", "horizontal"); + break; + case LayoutVertical: + (void) printf ("%s", "vertical"); + break; + default: + (void) printf ("Unknown layout direction %d\n", dir); + break; + + } +} + +static void +TabTo(level) + int level; +{ + while (level--) + (void) printf ("%s", " "); +} + +static void +PrintBox (box, level) + BoxPtr box; + int level; +{ + BoxPtr child; + + TabTo (level); + (void) printf ("%s", "< "); + (void) printf ("%s", " + "); + PrintGlue (box->params.stretch[LayoutHorizontal]); + (void) printf ("%s", " - "); + PrintGlue (box->params.shrink[LayoutHorizontal]); + (void) printf ("%s", " * "); + (void) printf ("%s", " + "); + PrintGlue (box->params.stretch[LayoutVertical]); + (void) printf ("%s", " - "); + PrintGlue (box->params.shrink[LayoutVertical]); + (void) printf ("%s", " >"); + (void) printf (" size: %d x %d", box->size[0], box->size[1]); + (void) printf (" natural: %d x %d ", box->natural[0], box->natural[1]); + switch (box->type) { + case BoxBox: + PrintDirection (box->u.box.dir); + (void) printf ("%s\n", ""); + for (child = box->u.box.firstChild; child; child = child->nextSibling) + PrintBox (child, level+1); + break; + case WidgetBox: + (void) printf (" %s\n", XrmQuarkToString (box->u.widget.quark)); + break; + case GlueBox: + (void) printf ("%s\n", " glue"); + break; + case VariableBox: + (void) printf (" variable %s\n", XrmQuarkToString (box->u.variable.quark)); + break; + } +} + +static ExprPtr +LookupVariable (child, quark) + BoxPtr child; + XrmQuark quark; +{ + BoxPtr parent, box; + + DBUG_ENTER("LookupVariable"); + DBUG_PRINT("name = <%s>",XrmQuarkToString(quark)); + DBUG_PRINT("child = %p",child); + while ((parent = child->parent)) + { + for (box = parent->u.box.firstChild; + box != child; + box = box->nextSibling) + { + if (box->type == VariableBox && box->u.variable.quark == quark) + DBUG_RETURN("%p", box->u.variable.expr); + } + child = parent; + } + DBUG_RETURN("failure -> %d",0); +} + +static double +Evaluate (l, box, expr, natural) + LayoutWidget l; + BoxPtr box; + ExprPtr expr; + double natural; +{ + double left, right, down; + Widget widget; + SubInfoPtr info; + + DBUG_PRINT("Evaluate %d", expr->type); + switch (expr->type) { + case Constant: + return expr->u.constant; + case Binary: + left = Evaluate (l, box, expr->u.binary.left, natural); + right = Evaluate (l, box, expr->u.binary.right, natural); + switch (expr->u.binary.op) { + case Plus: + return left + right; + case Minus: + return left - right; + case Times: + return left * right; + case Divide: + return left / right; + case Percent: + return right * left / 100.0; + } + case Unary: + down = Evaluate (l, box, expr->u.unary.down, natural); + switch (expr->u.unary.op) { + case Percent: + return natural * down / 100.0; + case Minus: + return -down; + case Plus: + case Times: + case Divide: + break; + } + case Width: + widget = QuarkToWidget (l, expr->u.width); + if (!widget) + return 0; + info = SubInfo (widget); + return info->naturalSize[LayoutHorizontal]; + case Height: + widget = QuarkToWidget (l, expr->u.height); + if (!widget) + return 0; + info = SubInfo (widget); + return info->naturalSize[LayoutVertical]; + case Variable: + { + /* in the original code there was no nexpr, + expr was overwritten by LookupVariable and + the expression "expr->u.variable" to obtain the + variable name for the errormessage cause a segmentation + violation */ + ExprPtr nexpr; + nexpr = LookupVariable (box, expr->u.variable); + if (!nexpr) + { + char buf[256]; + (void) sprintf (buf, "Layout: undefined variable %s\n", + XrmQuarkToString (expr->u.variable)); + XtError (buf); + return 0.0; + } + return Evaluate (l, box, nexpr, natural); + } + } + return 0.0; +} + +static void +DisposeExpr (expr) + ExprPtr expr; +{ + if (!expr) + return; + switch (expr->type) { + case Constant: + break; + case Binary: + DisposeExpr (expr->u.binary.left); + DisposeExpr (expr->u.binary.right); + break; + case Unary: + DisposeExpr (expr->u.unary.down); + break; + case Width: + case Height: + case Variable: + break; + } + Dispose (expr); +} + +#define CheckGlue(l, box, glue, n) { \ + if (glue.expr) \ + glue.value = Evaluate (l, box, glue.expr, n); \ + if (glue.order == 0 && glue.value == 0) \ + glue.order = -1; \ + else if (glue.order == -1 && glue.value != 0) \ + glue.order = 0; \ +} + +#define DoStretch(l, box, dir) \ + CheckGlue (l, box, box->params.stretch[dir], (double) box->natural[dir]); + +#define DoShrink(l, box, dir) \ + CheckGlue (l, box, box->params.shrink[dir], (double) box->natural[dir]) + +/* compute the natural sizes of a box */ +static void +ComputeNaturalSizes (l, box, dir) + LayoutWidget l; + BoxPtr box; + LayoutDirection dir; +{ + BoxPtr child; + Widget w; + SubInfoPtr info; + int minStretchOrder, minShrinkOrder; + LayoutDirection thisDir; + + DBUG_ENTER("ComputeNaturalSizes"); + DBUG_PRINT("box->type=%d",box->type); + switch (box->type) { + case WidgetBox: + w = box->u.widget.widget = QuarkToWidget (l, box->u.widget.quark); + if (!w) + { + box->natural[LayoutHorizontal] = 0; + box->natural[LayoutVertical] = 0; + } + else + { + info = SubInfo (w); + box->natural[LayoutHorizontal] = info->naturalSize[LayoutHorizontal]; + box->natural[LayoutVertical] = info->naturalSize[LayoutVertical]; + } + DoStretch (l, box, dir); + DoShrink (l, box, dir); + DoStretch (l, box, !dir); + DoShrink (l, box, !dir); + break; + case GlueBox: + box->natural[dir] = Evaluate (l, box, box->u.glue.expr, 0.0); + box->natural[!dir] = 0; + DoStretch (l, box, dir); + DoShrink (l, box, dir); + break; + case BoxBox: + thisDir = box->u.box.dir; + box->natural[0] = 0; + box->natural[1] = 0; + minStretchOrder = 100000; + minShrinkOrder = 100000; + ZeroGlue (box->params.shrink[thisDir]); + ZeroGlue (box->params.stretch[thisDir]); + box->params.shrink[!thisDir].order = 100000; + box->params.stretch[!thisDir].order = 100000; + for (child = box->u.box.firstChild; child; child = child->nextSibling) + { + ComputeNaturalSizes (l, child, thisDir); + /* + * along box axis: + * normal size += child normal size + * shrink += child shrink + * stretch += child stretch + */ + box->natural[thisDir] += child->natural[thisDir]; + AddGlue (box->params.shrink[thisDir], + box->params.shrink[thisDir], + child->params.shrink[thisDir]); + AddGlue (box->params.stretch[thisDir], + box->params.stretch[thisDir], + child->params.stretch[thisDir]); + /* + * normal to box axis: + * normal size = maximum child normal size of minimum shrink order + * shrink = difference between normal size and minimum shrink + * stretch = minimum child stretch + */ + if (box->natural[!thisDir] >= child->natural[!thisDir]) + { + if (child->params.stretch[!thisDir].order < minShrinkOrder) + { + box->natural[!thisDir] = child->natural[!thisDir]; + minStretchOrder = child->params.stretch[!thisDir].order; + if (child->params.shrink[!thisDir].order < minShrinkOrder) + minShrinkOrder = child->params.shrink[!thisDir].order; + } + } + else + { + if (child->params.shrink[!thisDir].order <= minStretchOrder) + { + box->natural[!thisDir] = child->natural[!thisDir]; + minShrinkOrder = child->params.shrink[!thisDir].order; + if (child->params.stretch[!thisDir].order < minStretchOrder) + minStretchOrder = child->params.stretch[!thisDir].order; + } + } + MinGlue (box->params.stretch[!thisDir], + box->params.stretch[!thisDir], + child->params.stretch[!thisDir]); + MinGlue (box->params.shrink[!thisDir], + box->params.shrink[!thisDir], + child->params.shrink[!thisDir]); + } + if (box->params.shrink[!thisDir].order <= 0) + { + int minSize; + int largestMinSize; + + largestMinSize = 0; + for (child = box->u.box.firstChild; child; child = child->nextSibling) + { + if (child->params.shrink[!thisDir].order <= 0) + { + minSize = child->natural[!thisDir] - + child->params.shrink[!thisDir].value; + if (minSize > largestMinSize) + largestMinSize = minSize; + } + } + box->params.shrink[!thisDir].value = box->natural[!thisDir] - + largestMinSize; + if (box->params.shrink[!thisDir].value == 0) + box->params.shrink[!thisDir].order = -1; + else + box->params.shrink[!thisDir].order = 0; + } + break; + case VariableBox: + break; + } + DBUG_VOID_RETURN; +} + +/* given the boxs geometry, set the geometry of the pieces */ + +#define GluePart(a,b,dist) ((a) ? ((int) (((a) * (dist)) / (b) + \ + ((dist >= 0) ? 0.5 : -0.5))) : 0) + +static Bool +ComputeSizes (box) + BoxPtr box; +{ + LayoutDirection dir; + BoxPtr child; + GlueRec stretch; + GlueRec shrink; + GlueRec totalGlue[2]; + double remainingGlue; + GluePtr glue; + int size; + int totalSizes; + int totalChange[2]; + int change; + int remainingChange; + Bool shrinking; + Bool happy; + int i; + int maxGlue; + + dir = box->u.box.dir; + size = box->size[dir]; + + stretch = box->params.stretch[dir]; + shrink = box->params.shrink[dir]; + + /* pick the correct adjustment parameters based on the change direction */ + + totalChange[0] = size - box->natural[dir]; + + shrinking = totalChange[0] < 0; + + totalChange[1] = 0; + totalGlue[1].order = 100000; + totalGlue[1].value = 0; + maxGlue = 1; + if (shrinking) + { + totalGlue[0] = shrink; + /* for first-order infinites, shrink it to zero and then + * shrink the zero-orders + */ + if (shrink.order == 1) { + totalSizes = 0; + remainingGlue = 0; + for (child = box->u.box.firstChild; + child; + child = child->nextSibling) + { + switch (child->params.shrink[dir].order) { + case 0: + remainingGlue += child->params.shrink[dir].value; + break; + case 1: + totalSizes += child->natural[dir]; + break; + } + } + if (totalSizes < -totalChange[0]) + { + totalGlue[1] = shrink; + totalGlue[0].order = 0; + totalGlue[0].value = remainingGlue; + totalChange[1] = -totalSizes; + totalChange[0] = totalChange[0] - totalChange[1]; + maxGlue = 2; + } + } + if (totalGlue[0].order <= 0 && + totalChange[0] > totalGlue[0].value) + { + totalChange[0] = totalGlue[0].value; + } + } + else + totalGlue[0] = stretch; + + /* adjust each box */ + totalSizes = 0; + remainingGlue = totalGlue[0].value + totalGlue[1].value; + remainingChange = totalChange[0] + totalChange[1]; + happy = True; + for (child = box->u.box.firstChild; child; child = child->nextSibling) + { + /* never add glue or stretch to a VariableBox! */ + if (child->type == VariableBox) continue; + + if (shrinking) + glue = &child->params.shrink[dir]; + else + glue = &child->params.stretch[dir]; + + child->size[dir] = child->natural[dir]; + for (i = 0; i < maxGlue; i++) + { + if (glue->order == totalGlue[i].order) + { + remainingGlue -= glue->value; + if (remainingGlue <= 0) + change = remainingChange; + else + change = GluePart (glue->value, + totalGlue[i].value, + totalChange[i]); + child->size[dir] += change; + remainingChange -= change; + } + } + child->size[!dir] = box->size[!dir]; + totalSizes += child->size[dir]; + if (child->type == BoxBox) + if (!ComputeSizes (child)) + happy = False; + } + return totalSizes == box->size[dir] && happy; +} + +static void +SetSizes (box, x, y) + BoxPtr box; + Position x, y; +{ + BoxPtr child; + int width, height; + int bw; + Widget w; + SubInfoPtr info; + + switch (box->type) { + case WidgetBox: + w = box->u.widget.widget; + if (w) + { + info = SubInfo(w); + /* info = (SubInfoPtr) w->core.constraints; */ + width = box->size[LayoutHorizontal]; + height = box->size[LayoutVertical]; + bw = info->naturalBw; + width -= bw * 2; + height -= bw * 2; + /* Widgets which grow too small are placed off screen */ + if (width <= 0 || height <= 0) + { + width = 1; + height = 1; + bw = 0; + x = -1; + y = -1; + } + XtConfigureWidget (w, x, y, + (Dimension)width, (Dimension)height, + (Dimension)bw); + } + break; + case BoxBox: + for (child = box->u.box.firstChild; child; child = child->nextSibling) + { + SetSizes (child, x, y); + if (box->u.box.dir == LayoutHorizontal) + x += child->size[LayoutHorizontal]; + else + y += child->size[LayoutVertical]; + } + break; + case GlueBox: + case VariableBox: + break; + } +} + +static void +LayoutFreeLayout (box) + BoxPtr box; +{ + BoxPtr child, next; + + switch (box->type) { + case BoxBox: + for (child = box->u.box.firstChild; child; child = next) + { + next = child->nextSibling; + LayoutFreeLayout (child); + } + break; + case GlueBox: + DisposeExpr (box->u.glue.expr); + break; + case WidgetBox: + case VariableBox: + default: + break; + } + DisposeExpr (box->params.stretch[LayoutHorizontal].expr); + DisposeExpr (box->params.shrink[LayoutHorizontal].expr); + DisposeExpr (box->params.stretch[LayoutVertical].expr); + DisposeExpr (box->params.shrink[LayoutVertical].expr); + Dispose (box); +} + + +static void +LayoutGetNaturalSize (l, widthp, heightp) + LayoutWidget l; + Dimension *widthp, *heightp; +{ + BoxPtr box; + + DBUG_ENTER("LayoutGetNaturalSize"); + box = l->layout.layout; + if (box) + { + ComputeNaturalSizes (l, box, LayoutHorizontal); + *widthp = box->natural[LayoutHorizontal]; + *heightp = box->natural[LayoutVertical]; + } + else + { + *widthp = 0; + *heightp = 0; + } + DBUG_VOID_RETURN; +} + +static void +LayoutLayout (l, attemptResize) + LayoutWidget l; + Bool attemptResize; +{ + BoxPtr box; + Dimension width, height; + Dimension prefered_width, prefered_height; + + DBUG_ENTER("LayoutLayout"); + box = l->layout.layout; + if (!box) + return; + LayoutGetNaturalSize (l, &prefered_width, &prefered_height); + if (l->core.width == 0 || l->core.height == 0) + { + l->core.width = prefered_width; + l->core.height = prefered_height; + } + box->size[LayoutHorizontal] = l->core.width; + box->size[LayoutVertical] = l->core.height; + if (!ComputeSizes (box) && attemptResize) + { + XtMakeResizeRequest ((Widget) l, + prefered_width, prefered_height, + &width, &height); + if (width != box->size[LayoutHorizontal] || + height != box->size[LayoutVertical]) + { + box->size[LayoutHorizontal] = width; + box->size[LayoutVertical] = height; + ComputeSizes (box); + } + } + if (l->layout.debug) + { + PrintBox (box, 0); + fflush (stdout); + } + SetSizes (box, 0, 0); + DBUG_VOID_RETURN; +} + diff --git a/src/Layout.h b/src/Layout.h new file mode 100644 index 0000000..7d9e636 --- /dev/null +++ b/src/Layout.h @@ -0,0 +1,94 @@ +/* + * $XConsortium: Layout.h,v 1.2 92/01/22 18:03:05 keith Exp $ + * + * Copyright 1991 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. + * 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 TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, MIT X Consortium + */ + + +#ifndef _XawLayout_h +#define _XawLayout_h + +#include <X11/Constraint.h> +#include <X11/Xfuncproto.h> + +/**************************************************************** + * + * Layout Widget (SubClass of CompositeClass) + * + ****************************************************************/ + +/* RESOURCES: + + Name Class RepType Default Value + ---- ----- ------- ------------- + background Background Pixel XtDefaultBackground + border BorderColor Pixel XtDefaultForeground + borderWidth BorderWidth Dimension 1 + cursor Cursor Cursor None + destroyCallback Callback Pointer NULL + height Height Dimension 0 + mappedWhenManaged MappedWhenManaged Boolean True + sensitive Sensitive Boolean True + width Width Dimension 0 + x Position Position 0 + y Position Position 0 + layout Layout Layout NULL + +*/ + +/* + * Syntax of layout resource + * + * *layout:\ + * <widget-name>.<edge>,<widget-name>.<edge>: distance + stretch-factor\n\ + * ... + * where the null widget-name is taken to be the Layout widget + * + * e.g: + * + * *label-1.hStretch: 0 + * *label-2.vStretch: 1 + * *layout:\ + * .left, label-1.left: 10 + 0\n\ + * label-1.right, label-2.left: 10 + 1\n\ + * label-2.right, .right: 10 + 0 + * + * This layout causes label-1 to be set 10 pixels from the left edge + * and be whatever size the label widget requests, while label-2 will + * be set 10 pixels from the right edge, and take up half of the remaining + * space to 10 pixels from the right edge of label-1. + */ + +/* New Fields */ +#define XtNlayout "layout" +#define XtCLayout "Layout" +#define XtRLayout "Layout" +#define XtNdebug "debug" + +/* Class record constant */ + +extern WidgetClass layoutWidgetClass; + +typedef struct _LayoutClassRec *LayoutWidgetClass; +typedef struct _LayoutRec *LayoutWidget; + +#endif /* _Layout_h */ diff --git a/src/LayoutP.h b/src/LayoutP.h new file mode 100644 index 0000000..ae1f2c6 --- /dev/null +++ b/src/LayoutP.h @@ -0,0 +1,232 @@ +/* + * $XConsortium: LayoutP.h,v 1.2 92/01/22 18:03:08 keith Exp $ + * + * Copyright 1991 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. + * 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 TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Keith Packard, MIT X Consortium + */ + +#ifndef _XawLayoutP_h +#define _XawLayoutP_h + +#if defined(LAYOUT) +# include "Layout.h" +#else +# include <X11/Xaw3d/Layout.h> +#endif + +#include <X11/ConstrainP.h> + +#ifdef MOTIF +# include "Xm/ManagerP.h" +#endif + +#define GlueEqual(a,b) ((a).order == (b).order && (a).value == (b).value) + +#define AddGlue(r,a,b) if (a.order == b.order) { \ + r.order = a.order; \ + r.value = a.value + b.value; \ + } else { \ + if (a.order > b.order) \ + r = a; \ + else \ + r = b; \ + } + +#define MinGlue(r,a,b) if (a.order == b.order) { \ + r.order = a.order; \ + if (a.value > b.value) \ + r.value = b.value; \ + else \ + r.value = a.value; \ + } else { \ + if (a.order > b.order) \ + r = b; \ + else \ + r = a; \ + } + +#define SubGlue(r,a,b) if (a.order == b.order) { \ + r.order = a.order; \ + r.value = a.value - b.value; \ + } else { \ + if (a.order > b.order) \ + r = a; \ + else { \ + r.order = b.order; \ + r.value = -b.value; \ + } \ + } + +#define ZeroGlue(g) ((g).value = 0, (g).order = 0, (g).expr = 0) +#define IsZeroGlue(g) ((g).value == 0) + +#define QuarkToWidget(l,q) XtNameToWidget((Widget) l, \ + (char *) XrmQuarkToString(q)); + +typedef enum _BoxType { BoxBox, WidgetBox, GlueBox, VariableBox } BoxType; + +typedef enum _LayoutDirection { + LayoutHorizontal = 0, LayoutVertical = 1 +} LayoutDirection; + +typedef enum _Operator { + Plus, Minus, Times, Divide, Percent +} Operator; + +typedef enum _ExprType { + Constant, + Binary, + Unary, + Width, + Height, + Variable +} ExprType; + +typedef struct _Expr *ExprPtr; + +typedef struct _Expr { + ExprType type; + union { + double constant; + struct { + Operator op; + ExprPtr left, right; + } binary; + struct { + Operator op; + ExprPtr down; + } unary; + XrmQuark width; + XrmQuark height; + XrmQuark variable; + } u; +} ExprRec; + +typedef struct _Glue { + int order; + double value; + ExprPtr expr; +} GlueRec, *GluePtr; + +typedef struct _BoxParams { + GlueRec stretch[2]; + GlueRec shrink[2]; +} BoxParamsRec, *BoxParamsPtr; + +typedef struct _Box *BoxPtr; + +typedef BoxPtr LayoutPtr; + +typedef struct _Box { + BoxPtr nextSibling; + BoxPtr parent; + BoxParamsRec params; + int size[2]; + int natural[2]; + BoxType type; + union { + struct { + BoxPtr firstChild; + LayoutDirection dir; + } box; + struct { + XrmQuark quark; + Widget widget; + } widget; + struct { + ExprPtr expr; + } glue; + struct { + XrmQuark quark; + ExprPtr expr; + } variable; + } u; +} LBoxRec; /* this conflicted with Box's BoxRec, besides, it's not used anywhere */ + +typedef struct _SubInfo { + int naturalSize[2]; + int naturalBw; +} SubInfoRec, *SubInfoPtr; + +/* #define New(t) (t *) malloc(sizeof (t)) */ +#define New(t) (t *) XtCalloc(1,sizeof (t)) +#define Dispose(p) XtFree((char *) p) +#define Some(t,n) (t*) XtMalloc(sizeof(t) * n) +#define More(p,t,n) ((p)? (t *) XtRealloc((char *) p, sizeof(t)*n):Some(t,n) + +/********************************************************************* + * + * Layout Widget Private Data + * + *********************************************************************/ + +/* New fields for the Layout widget class record */ + +typedef struct _LayoutClassPart { + int foo; /* keep compiler happy. */ +} LayoutClassPart; + +/* Full Class record declaration */ +typedef struct _LayoutClassRec { + CoreClassPart core_class; + CompositeClassPart composite_class; + ConstraintClassPart constraint_class; +#ifdef MOTIF + XmManagerClassPart manager_class; +#endif + LayoutClassPart layout_class; +} LayoutClassRec; + +extern LayoutClassRec layoutClassRec; + +typedef struct _LayoutConstraintsRec { +#ifdef MOTIF + XmManagerConstraintPart manager; +#endif + SubInfoRec layout; +} LayoutConstraintsRec, *LayoutConstraints; + +#define SubInfo(w) (&(((LayoutConstraints) (w)->core.constraints)->layout)) + +/* New Fields for the Layout widget record */ + +typedef struct { + /* resources */ + LayoutPtr layout; + Boolean debug; +} LayoutPart; + +/************************************************************************** + * + * Full instance record declaration + * + **************************************************************************/ + +typedef struct _LayoutRec { + CorePart core; + CompositePart composite; + ConstraintPart constraint; +#ifdef MOTIF + XmManagerPart manager; +#endif + LayoutPart layout; +} LayoutRec; +#endif diff --git a/src/List.c b/src/List.c new file mode 100644 index 0000000..aea8720 --- /dev/null +++ b/src/List.c @@ -0,0 +1,1230 @@ +/* $XConsortium: List.c,v 1.39 94/04/17 20:12:15 kaleb Exp $ */ + +/* +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. +*/ + +/* + * List.c - List widget + * + * This is a List widget. It allows the user to select an item in a list and + * notifies the application through a callback function. + * + * Created: 8/13/88 + * By: Chris D. Peterson + * MIT X Consortium + */ + +#include "Xaw3dP.h" +#include <stdio.h> +#include <ctype.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Drawing.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/ListP.h> + +/* These added so widget knows whether its height, width are user selected. +I also added the freedoms member of the list widget part. */ + +#define HeightLock 1 +#define WidthLock 2 +#define LongestLock 4 + +#define HeightFree( w ) !(((ListWidget)(w))->list.freedoms & HeightLock ) +#define WidthFree( w ) !(((ListWidget)(w))->list.freedoms & WidthLock ) +#define LongestFree( w ) !(((ListWidget)(w))->list.freedoms & LongestLock ) + +/* + * Default Translation table. + */ + +static char defaultTranslations[] = + "<Btn1Down>: Set()\n\ + <Btn1Up>: Notify()"; + +/**************************************************************** + * + * Full class record constant + * + ****************************************************************/ + +/* Private Data */ + +#define offset(field) XtOffset(ListWidget, field) + +static XtResource resources[] = { + {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), + offset(list.foreground), XtRString, XtDefaultForeground}, + {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor), + offset(simple.cursor), XtRString, "left_ptr"}, + {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *), + offset(list.font),XtRString, XtDefaultFont}, +#ifdef XAW_INTERNATIONALIZATION + {XtNfontSet, XtCFontSet, XtRFontSet, sizeof(XFontSet ), + offset(list.fontset),XtRString, XtDefaultFontSet}, +#endif + {XtNlist, XtCList, XtRPointer, sizeof(char **), + offset(list.list), XtRString, NULL}, + {XtNdefaultColumns, XtCColumns, XtRInt, sizeof(int), + offset(list.default_cols), XtRImmediate, (XtPointer)2}, + {XtNlongest, XtCLongest, XtRInt, sizeof(int), + offset(list.longest), XtRImmediate, (XtPointer)0}, + {XtNnumberStrings, XtCNumberStrings, XtRInt, sizeof(int), + offset(list.nitems), XtRImmediate, (XtPointer)0}, + {XtNpasteBuffer, XtCBoolean, XtRBoolean, sizeof(Boolean), + offset(list.paste), XtRImmediate, (XtPointer) False}, + {XtNforceColumns, XtCColumns, XtRBoolean, sizeof(Boolean), + offset(list.force_cols), XtRImmediate, (XtPointer) False}, + {XtNverticalList, XtCBoolean, XtRBoolean, sizeof(Boolean), + offset(list.vertical_cols), XtRImmediate, (XtPointer) False}, + {XtNinternalWidth, XtCWidth, XtRDimension, sizeof(Dimension), + offset(list.internal_width), XtRImmediate, (XtPointer)2}, + {XtNinternalHeight, XtCHeight, XtRDimension, sizeof(Dimension), + offset(list.internal_height), XtRImmediate, (XtPointer)2}, + {XtNcolumnSpacing, XtCSpacing, XtRDimension, sizeof(Dimension), + offset(list.column_space), XtRImmediate, (XtPointer)6}, + {XtNrowSpacing, XtCSpacing, XtRDimension, sizeof(Dimension), + offset(list.row_space), XtRImmediate, (XtPointer)2}, + {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), + offset(list.callback), XtRCallback, NULL}, +}; + +static void Initialize(); +static void ChangeSize(); +static void Resize(); +static void Redisplay(); +static void Destroy(); +static Boolean Layout(); +static XtGeometryResult PreferredGeom(); +static Boolean SetValues(); +static void Notify(), Set(), Unset(); + +static XtActionsRec actions[] = { + {"Notify", Notify}, + {"Set", Set}, + {"Unset", Unset}, +}; + +ListClassRec listClassRec = { + { +/* core_class fields */ + /* superclass */ (WidgetClass) &simpleClassRec, + /* class_name */ "List", + /* widget_size */ sizeof(ListRec), + /* class_initialize */ XawInitializeWidgetSet, + /* class_part_initialize */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ XtInheritRealize, + /* actions */ actions, + /* num_actions */ XtNumber(actions), + /* resources */ resources, + /* num_resources */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ TRUE, + /* compress_exposure */ FALSE, + /* 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 */ defaultTranslations, + /* query_geometry */ PreferredGeom, + }, +/* Simple class fields initialization */ + { + /* change_sensitive */ XtInheritChangeSensitive + }, +/* List class fields initialization */ + { + /* not used */ 0 + }, +}; + +WidgetClass listWidgetClass = (WidgetClass)&listClassRec; + +/**************************************************************** + * + * Private Procedures + * + ****************************************************************/ + +static void GetGCs(w) +Widget w; +{ + XGCValues values; + ListWidget lw = (ListWidget) w; + + values.foreground = lw->list.foreground; + values.font = lw->list.font->fid; + +#ifdef XAW_INTERNATIONALIZATION + if ( lw->simple.international == True ) + lw->list.normgc = XtAllocateGC( w, 0, (unsigned) GCForeground, + &values, GCFont, 0 ); + else +#endif + lw->list.normgc = XtGetGC( w, (unsigned) GCForeground | GCFont, + &values); + + values.foreground = lw->core.background_pixel; + +#ifdef XAW_INTERNATIONALIZATION + if ( lw->simple.international == True ) + lw->list.revgc = XtAllocateGC( w, 0, (unsigned) GCForeground, + &values, GCFont, 0 ); + else +#endif + lw->list.revgc = XtGetGC( w, (unsigned) GCForeground | GCFont, + &values); + + values.tile = XmuCreateStippledPixmap(XtScreen(w), + lw->list.foreground, + lw->core.background_pixel, + lw->core.depth); + values.fill_style = FillTiled; + +#ifdef XAW_INTERNATIONALIZATION + if ( lw->simple.international == True ) + lw->list.graygc = XtAllocateGC( w, 0, (unsigned) GCTile | GCFillStyle, + &values, GCFont, 0 ); + else +#endif + lw->list.graygc = XtGetGC( w, (unsigned) GCFont | GCTile | GCFillStyle, + &values); +} + + +/* CalculatedValues() + * + * does routine checks/computations that must be done after data changes + * but won't hurt if accidently called + * + * These calculations were needed in SetValues. They were in ResetList. + * ResetList called ChangeSize, which made an XtGeometryRequest. You + * MAY NOT change your geometry from within a SetValues. (Xt man, + * sect. 9.7.2) So, I factored these changes out. */ + +static void CalculatedValues( w ) +Widget w; +{ + int i, len; + + ListWidget lw = (ListWidget) w; + + /* If list is NULL then the list will just be the name of the widget. */ + + if (lw->list.list == NULL) { + lw->list.list = &(lw->core.name); + lw->list.nitems = 1; + } + + /* Get number of items. */ + + if (lw->list.nitems == 0) + for ( ; lw->list.list[lw->list.nitems] != NULL ; lw->list.nitems++); + + /* Get column width. */ + + if ( LongestFree( lw ) ) { + + lw->list.longest = 0; /* so it will accumulate real longest below */ + + for ( i = 0 ; i < lw->list.nitems; i++) { +#ifdef XAW_INTERNATIONALIZATION + if ( lw->simple.international == True ) + len = XmbTextEscapement(lw->list.fontset, lw->list.list[i], + strlen(lw->list.list[i])); + else +#endif + len = XTextWidth(lw->list.font, lw->list.list[i], + strlen(lw->list.list[i])); + if (len > lw->list.longest) + lw->list.longest = len; + } + } + + lw->list.col_width = lw->list.longest + lw->list.column_space; +} + +/* Function Name: ResetList + * Description: Resets the new list when important things change. + * Arguments: w - the widget. + * changex, changey - allow the height or width to change? + * + * Returns: TRUE if width or height have been changed + */ + +static void +ResetList( w, changex, changey ) +Widget w; +Boolean changex, changey; +{ + Dimension width = w->core.width; + Dimension height = w->core.height; + + CalculatedValues( w ); + + if( Layout( w, changex, changey, &width, &height ) ) + ChangeSize( w, width, height ); +} + +/* Function Name: ChangeSize. + * Description: Laysout the widget. + * Arguments: w - the widget to try change the size of. + * Returns: none. + */ + +static void +ChangeSize(w, width, height) +Widget w; +Dimension width, height; +{ + XtWidgetGeometry request, reply; + + request.request_mode = CWWidth | CWHeight; + request.width = width; + request.height = height; + + switch ( XtMakeGeometryRequest(w, &request, &reply) ) { + case XtGeometryYes: + break; + case XtGeometryNo: + break; + case XtGeometryAlmost: + Layout(w, (request.height != reply.height), + (request.width != reply.width), + &(reply.width), &(reply.height)); + request = reply; + switch (XtMakeGeometryRequest(w, &request, &reply) ) { + case XtGeometryYes: + case XtGeometryNo: + break; + case XtGeometryAlmost: + request = reply; + Layout(w, FALSE, FALSE, &(request.width), &(request.height)); + request.request_mode = CWWidth | CWHeight; + XtMakeGeometryRequest(w, &request, &reply); + break; + default: + XtAppWarning(XtWidgetToApplicationContext(w), + "List Widget: Unknown geometry return."); + break; + } + break; + default: + XtAppWarning(XtWidgetToApplicationContext(w), + "List Widget: Unknown geometry return."); + break; + } +} + +/* Function Name: Initialize + * Description: Function that initilizes the widget instance. + * Arguments: junk - NOT USED. + * new - the new widget. + * Returns: none + */ + +/* ARGSUSED */ +static void +Initialize(junk, new, args, num_args) +Widget junk, new; +ArgList args; +Cardinal *num_args; +{ + ListWidget lw = (ListWidget) new; + +/* + * Initialize all private resources. + */ + + /* record for posterity if we are free */ + lw->list.freedoms = (lw->core.width != 0) * WidthLock + + (lw->core.height != 0) * HeightLock + + (lw->list.longest != 0) * LongestLock; + + GetGCs(new); + + /* Set row height. based on font or fontset */ + +#ifdef XAW_INTERNATIONALIZATION + if (lw->simple.international == True ) + lw->list.row_height = + XExtentsOfFontSet(lw->list.fontset)->max_ink_extent.height + + lw->list.row_space; + else +#endif + lw->list.row_height = lw->list.font->max_bounds.ascent + + lw->list.font->max_bounds.descent + + lw->list.row_space; + + ResetList( new, WidthFree( lw ), HeightFree( lw ) ); + + lw->list.highlight = lw->list.is_highlighted = NO_HIGHLIGHT; + +} /* Initialize */ + +/* Function Name: CvtToItem + * Description: Converts Xcoord to item number of item containing that + * point. + * Arguments: w - the list widget. + * xloc, yloc - x location, and y location. + * Returns: the item number. + */ + +static int +CvtToItem(w, xloc, yloc, item) +Widget w; +int xloc, yloc; +int *item; +{ + int one, another; + ListWidget lw = (ListWidget) w; + int ret_val = OKAY; + + if (lw->list.vertical_cols) { + one = lw->list.nrows * ((xloc - (int) lw->list.internal_width) + / lw->list.col_width); + another = (yloc - (int) lw->list.internal_height) + / lw->list.row_height; + /* If out of range, return minimum possible value. */ + if (another >= lw->list.nrows) { + another = lw->list.nrows - 1; + ret_val = OUT_OF_RANGE; + } + } + else { + one = (lw->list.ncols * ((yloc - (int) lw->list.internal_height) + / lw->list.row_height)) ; + /* If in right margin handle things right. */ + another = (xloc - (int) lw->list.internal_width) / lw->list.col_width; + if (another >= lw->list.ncols) { + another = lw->list.ncols - 1; + ret_val = OUT_OF_RANGE; + } + } + if ((xloc < 0) || (yloc < 0)) + ret_val = OUT_OF_RANGE; + if (one < 0) one = 0; + if (another < 0) another = 0; + *item = one + another; + if (*item >= lw->list.nitems) return(OUT_OF_RANGE); + return(ret_val); +} + +/* Function Name: FindCornerItems. + * Description: Find the corners of the rectangle in item space. + * Arguments: w - the list widget. + * event - the event structure that has the rectangle it it. + * ul_ret, lr_ret - the corners ** RETURNED **. + * Returns: none. + */ + +static void +FindCornerItems(w, event, ul_ret, lr_ret) +Widget w; +XEvent * event; +int *ul_ret, *lr_ret; +{ + int xloc, yloc; + + xloc = event->xexpose.x; + yloc = event->xexpose.y; + CvtToItem(w, xloc, yloc, ul_ret); + xloc += event->xexpose.width; + yloc += event->xexpose.height; + CvtToItem(w, xloc, yloc, lr_ret); +} + +/* Function Name: ItemInRectangle + * Description: returns TRUE if the item passed is in the given rectangle. + * Arguments: w - the list widget. + * ul, lr - corners of the rectangle in item space. + * item - item to check. + * Returns: TRUE if the item passed is in the given rectangle. + */ + +static Boolean +ItemInRectangle(w, ul, lr, item) +Widget w; +int ul, lr, item; +{ + ListWidget lw = (ListWidget) w; + int mod_item; + int things; + + if (item < ul || item > lr) + return(FALSE); + if (lw->list.vertical_cols) + things = lw->list.nrows; + else + things = lw->list.ncols; + + mod_item = item % things; + if ( (mod_item >= ul % things) && (mod_item <= lr % things ) ) + return(TRUE); + return(FALSE); +} + + +/* HighlightBackground() + * + * Paints the color of the background for the given item. It performs + * clipping to the interior of internal_width/height by hand, as its a + * simple calculation and probably much faster than using Xlib and a clip mask. + * + * x, y - ul corner of the area item occupies. + * gc - the gc to use to paint this rectangle */ + +static void +HighlightBackground( w, x, y, gc ) +Widget w; +int x, y; +GC gc; +{ + ListWidget lw = (ListWidget) w; + + /* easy to clip the rectangle by hand and probably alot faster than Xlib */ + + Dimension width = lw->list.col_width; + Dimension height = lw->list.row_height; + Dimension frame_limited_width = w->core.width - lw->list.internal_width - x; + Dimension frame_limited_height= w->core.height- lw->list.internal_height- y; + + /* Clip the rectangle width and height to the edge of the drawable area */ + + if ( width > frame_limited_width ) + width = frame_limited_width; + if ( height> frame_limited_height) + height = frame_limited_height; + + /* Clip the rectangle x and y to the edge of the drawable area */ + + if ( x < lw->list.internal_width ) { + width = width - ( lw->list.internal_width - x ); + x = lw->list.internal_width; + } + if ( y < lw->list.internal_height) { + height = height - ( lw->list.internal_height - x ); + y = lw->list.internal_height; + } + XFillRectangle( XtDisplay( w ), XtWindow( w ), gc, x, y, + width, height ); +} + + +/* ClipToShadowInteriorAndLongest() + * + * Converts the passed gc so that any drawing done with that GC will not + * write in the empty margin (specified by internal_width/height) (which also + * prevents erasing the shadow. It also clips against the value longest. + * If the user doesn't set longest, this has no effect (as longest is the + * maximum of all item lengths). If the user does specify, say, 80 pixel + * columns, though, this prevents items from overwriting other items. */ + +static void ClipToShadowInteriorAndLongest(lw, gc_p, x) + ListWidget lw; + GC* gc_p; + Dimension x; +{ + XRectangle rect; + + rect.x = x; + rect.y = lw->list.internal_height; + rect.height = lw->core.height - lw->list.internal_height * 2; + rect.width = lw->core.width - lw->list.internal_width - x; + if ( rect.width > lw->list.longest ) + rect.width = lw->list.longest; + + XSetClipRectangles( XtDisplay((Widget)lw),*gc_p,0,0,&rect,1,YXBanded ); +} + + +/* PaintItemName() + * + * paints the name of the item in the appropriate location. + * w - the list widget. + * item - the item to draw. + * + * NOTE: no action taken on an unrealized widget. */ + +static void +PaintItemName(w, item) +Widget w; +int item; +{ + char * str; + GC gc; + int x, y, str_y; + ListWidget lw = (ListWidget) w; +#ifdef XAW_INTERNATIONALIZATION + XFontSetExtents *ext = XExtentsOfFontSet(lw->list.fontset); +#endif + + if (!XtIsRealized(w)) return; /* Just in case... */ + + if (lw->list.vertical_cols) { + x = lw->list.col_width * (item / lw->list.nrows) + + lw->list.internal_width; + y = lw->list.row_height * (item % lw->list.nrows) + + lw->list.internal_height; + } + else { + x = lw->list.col_width * (item % lw->list.ncols) + + lw->list.internal_width; + y = lw->list.row_height * (item / lw->list.ncols) + + lw->list.internal_height; + } + +#ifdef XAW_INTERNATIONALIZATION + if ( lw->simple.international == True ) + str_y = y + abs(ext->max_ink_extent.y); + else +#endif + str_y = y + lw->list.font->max_bounds.ascent; + + if (item == lw->list.is_highlighted) { + if (item == lw->list.highlight) { + gc = lw->list.revgc; + HighlightBackground(w, x, y, lw->list.normgc); + } + else { + if (XtIsSensitive(w)) + gc = lw->list.normgc; + else + gc = lw->list.graygc; + HighlightBackground(w, x, y, lw->list.revgc); + lw->list.is_highlighted = NO_HIGHLIGHT; + } + } + else { + if (item == lw->list.highlight) { + gc = lw->list.revgc; + HighlightBackground(w, x, y, lw->list.normgc); + lw->list.is_highlighted = item; + } + else { + if (XtIsSensitive(w)) + gc = lw->list.normgc; + else + gc = lw->list.graygc; + } + } + + /* List's overall width contains the same number of inter-column + column_space's as columns. There should thus be a half + column_width margin on each side of each column. + The row case is symmetric. */ + + x += lw->list.column_space / 2; + str_y += lw->list.row_space / 2; + + str = lw->list.list[item]; /* draw it */ + + ClipToShadowInteriorAndLongest( lw, &gc, x ); + +#ifdef XAW_INTERNATIONALIZATION + if ( lw->simple.international == True ) + XmbDrawString( XtDisplay( w ), XtWindow( w ), lw->list.fontset, + gc, x, str_y, str, strlen( str ) ); + else +#endif + XDrawString( XtDisplay( w ), XtWindow( w ), + gc, x, str_y, str, strlen( str ) ); + + XSetClipMask( XtDisplay( w ), gc, None ); +} + + +/* Redisplay() + * + * Repaints the widget window on expose events. + * w - the list widget. + * event - the expose event for this repaint. + * junk - not used, unless three-d patch enabled. */ + +/* ARGSUSED */ +static void +Redisplay(w, event, junk) +Widget w; +XEvent *event; +Region junk; +{ + int item; /* an item to work with. */ + int ul_item, lr_item; /* corners of items we need to paint. */ + ListWidget lw = (ListWidget) w; + + if (event == NULL) { /* repaint all. */ + ul_item = 0; + lr_item = lw->list.nrows * lw->list.ncols - 1; + XClearWindow(XtDisplay(w), XtWindow(w)); + } + else + FindCornerItems(w, event, &ul_item, &lr_item); + + for (item = ul_item; (item <= lr_item && item < lw->list.nitems) ; item++) + if (ItemInRectangle(w, ul_item, lr_item, item)) + PaintItemName(w, item); +} + + +/* PreferredGeom() + * + * This tells the parent what size we would like to be + * given certain constraints. + * w - the widget. + * intended - what the parent intends to do with us. + * requested - what we want to happen. */ + +static XtGeometryResult +PreferredGeom(w, intended, requested) +Widget w; +XtWidgetGeometry *intended, *requested; +{ + Dimension new_width, new_height; + Boolean change, width_req, height_req; + + width_req = intended->request_mode & CWWidth; + height_req = intended->request_mode & CWHeight; + + if (width_req) + new_width = intended->width; + else + new_width = w->core.width; + + if (height_req) + new_height = intended->height; + else + new_height = w->core.height; + + requested->request_mode = 0; + +/* + * We only care about our height and width. + */ + + if ( !width_req && !height_req) + return(XtGeometryYes); + + change = Layout(w, !width_req, !height_req, &new_width, &new_height); + + requested->request_mode |= CWWidth; + requested->width = new_width; + requested->request_mode |= CWHeight; + requested->height = new_height; + + if (change) + return(XtGeometryAlmost); + return(XtGeometryYes); +} + + +/* Resize() + * + * resizes the widget, by changing the number of rows and columns. */ + +static void +Resize(w) + Widget w; +{ + Dimension width, height; + + width = w->core.width; + height = w->core.height; + + if (Layout(w, FALSE, FALSE, &width, &height)) + XtAppWarning(XtWidgetToApplicationContext(w), + "List Widget: Size changed when it shouldn't have when resising."); +} + + +/* Layout() + * + * lays out the item in the list. + * w - the widget. + * xfree, yfree - TRUE if we are free to resize the widget in + * this direction. + * width, height- the is the current width and height that we are going + * we are going to layout the list widget to, + * depending on xfree and yfree of course. + * + * RETURNS: TRUE if width or height have been changed. */ + +static Boolean +Layout(w, xfree, yfree, width, height) +Widget w; +Boolean xfree, yfree; +Dimension *width, *height; +{ + ListWidget lw = (ListWidget) w; + Boolean change = FALSE; + +/* + * If force columns is set then always use number of columns specified + * by default_cols. + */ + + if (lw->list.force_cols) { + lw->list.ncols = lw->list.default_cols; + if (lw->list.ncols <= 0) lw->list.ncols = 1; + /* 12/3 = 4 and 10/3 = 4, but 9/3 = 3 */ + lw->list.nrows = ( ( lw->list.nitems - 1) / lw->list.ncols) + 1 ; + if (xfree) { /* If allowed resize width. */ + + /* this counts the same number + of inter-column column_space 's as columns. There should thus be a + half column_space margin on each side of each column...*/ + + *width = lw->list.ncols * lw->list.col_width + + 2 * lw->list.internal_width; + change = TRUE; + } + if (yfree) { /* If allowed resize height. */ + *height = (lw->list.nrows * lw->list.row_height) + + 2 * lw->list.internal_height; + change = TRUE; + } + return(change); + } + +/* + * If both width and height are free to change the use default_cols + * to determine the number columns and set new width and height to + * just fit the window. + */ + + if (xfree && yfree) { + lw->list.ncols = lw->list.default_cols; + if (lw->list.ncols <= 0) lw->list.ncols = 1; + lw->list.nrows = ( ( lw->list.nitems - 1) / lw->list.ncols) + 1 ; + *width = lw->list.ncols * lw->list.col_width + + 2 * lw->list.internal_width; + *height = (lw->list.nrows * lw->list.row_height) + + 2 * lw->list.internal_height; + change = TRUE; + } +/* + * If the width is fixed then use it to determine the number of columns. + * If the height is free to move (width still fixed) then resize the height + * of the widget to fit the current list exactly. + */ + else if (!xfree) { + lw->list.ncols = ( (int)(*width - 2 * lw->list.internal_width) + / (int)lw->list.col_width); + if (lw->list.ncols <= 0) lw->list.ncols = 1; + lw->list.nrows = ( ( lw->list.nitems - 1) / lw->list.ncols) + 1 ; + if ( yfree ) { + *height = (lw->list.nrows * lw->list.row_height) + + 2 * lw->list.internal_height; + change = TRUE; + } + } +/* + * The last case is xfree and !yfree we use the height to determine + * the number of rows and then set the width to just fit the resulting + * number of columns. + */ + else if (!yfree) { /* xfree must be TRUE. */ + lw->list.nrows = (int)(*height - 2 * lw->list.internal_height) + / (int)lw->list.row_height; + if (lw->list.nrows <= 0) lw->list.nrows = 1; + lw->list.ncols = (( lw->list.nitems - 1 ) / lw->list.nrows) + 1; + *width = lw->list.ncols * lw->list.col_width + + 2 * lw->list.internal_width; + change = TRUE; + } + return(change); +} + + +/* Notify() - ACTION + * + * Notifies the user that a button has been pressed, and + * calls the callback; if the XtNpasteBuffer resource is true + * then the name of the item is also put in CUT_BUFFER0. */ + +/* ARGSUSED */ +static void +Notify(w, event, params, num_params) +Widget w; +XEvent * event; +String * params; +Cardinal *num_params; +{ + ListWidget lw = ( ListWidget ) w; + int item, item_len; + XawListReturnStruct ret_value; + +/* + * Find item and if out of range then unhighlight and return. + * + * If the current item is unhighlighted then the user has aborted the + * notify, so unhighlight and return. + */ + + if ( ((CvtToItem(w, event->xbutton.x, event->xbutton.y, &item)) + == OUT_OF_RANGE) || (lw->list.highlight != item) ) { + XawListUnhighlight(w); + return; + } + + item_len = strlen(lw->list.list[item]); + + if ( lw->list.paste ) /* if XtNpasteBuffer set then paste it. */ + XStoreBytes(XtDisplay(w), lw->list.list[item], item_len); + +/* + * Call Callback function. + */ + + ret_value.string = lw->list.list[item]; + ret_value.list_index = item; + + XtCallCallbacks( w, XtNcallback, (XtPointer) &ret_value); +} + + +/* Unset() - ACTION + * + * unhighlights the current element. */ + +/* ARGSUSED */ +static void +Unset(w, event, params, num_params) +Widget w; +XEvent * event; +String * params; +Cardinal *num_params; +{ + XawListUnhighlight(w); +} + + +/* Set() - ACTION + * + * Highlights the current element. */ + +/* ARGSUSED */ +static void +Set(w, event, params, num_params) +Widget w; +XEvent * event; +String * params; +Cardinal *num_params; +{ + int item; + ListWidget lw = (ListWidget) w; + + if ( (CvtToItem(w, event->xbutton.x, event->xbutton.y, &item)) + == OUT_OF_RANGE) + XawListUnhighlight(w); /* Unhighlight current item. */ + else if ( lw->list.is_highlighted != item ) /* If this item is not */ + XawListHighlight(w, item); /* highlighted then do it. */ +} + +/* + * Set specified arguments into widget + */ + +static Boolean +SetValues(current, request, new, args, num_args) +Widget current, request, new; +ArgList args; +Cardinal *num_args; +{ + ListWidget cl = (ListWidget) current; + ListWidget rl = (ListWidget) request; + ListWidget nl = (ListWidget) new; + Boolean redraw = FALSE; +#ifdef XAW_INTERNATIONALIZATION + XFontSetExtents *ext = XExtentsOfFontSet(nl->list.fontset); +#endif + + /* If the request height/width is different, lock it. Unless its 0. If */ + /* neither new nor 0, leave it as it was. Not in R5. */ + if ( nl->core.width != cl->core.width ) + nl->list.freedoms |= WidthLock; + if ( nl->core.width == 0 ) + nl->list.freedoms &= ~WidthLock; + + if ( nl->core.height != cl->core.height ) + nl->list.freedoms |= HeightLock; + if ( nl->core.height == 0 ) + nl->list.freedoms &= ~HeightLock; + + if ( nl->list.longest != cl->list.longest ) + nl->list.freedoms |= LongestLock; + if ( nl->list.longest == 0 ) + nl->list.freedoms &= ~LongestLock; + + /* _DONT_ check for fontset here - it's not in GC.*/ + + if ( (cl->list.foreground != nl->list.foreground) || + (cl->core.background_pixel != nl->core.background_pixel) || + (cl->list.font != nl->list.font) ) { + XGCValues values; + XGetGCValues(XtDisplay(current), cl->list.graygc, GCTile, &values); + XmuReleaseStippledPixmap(XtScreen(current), values.tile); + XtReleaseGC(current, cl->list.graygc); + XtReleaseGC(current, cl->list.revgc); + XtReleaseGC(current, cl->list.normgc); + GetGCs(new); + redraw = TRUE; + } + + if ( cl->list.font != nl->list.font ) { +#ifdef XAW_INTERNATIONALIZATION + if ( cl->simple.international == False ) +#endif + nl->list.row_height = nl->list.font->max_bounds.ascent + + nl->list.font->max_bounds.descent + + nl->list.row_space; + } +#ifdef XAW_INTERNATIONALIZATION + else if ( ( cl->list.fontset != nl->list.fontset ) && + ( cl->simple.international == True ) ) + nl->list.row_height = ext->max_ink_extent.height + nl->list.row_space; + + /* ...If the above two font(set) change checkers above both failed, check + if row_space was altered. If one of the above passed, row_height will + already have been re-calculated. */ + + else +#endif + if ( cl->list.row_space != nl->list.row_space ) { +#ifdef XAW_INTERNATIONALIZATION + if (cl->simple.international == True ) + nl->list.row_height = ext->max_ink_extent.height + nl->list.row_space; + else +#endif + nl->list.row_height = nl->list.font->max_bounds.ascent + + nl->list.font->max_bounds.descent + + nl->list.row_space; + } + + if ((cl->core.width != nl->core.width) || + (cl->core.height != nl->core.height) || + (cl->list.internal_width != nl->list.internal_width) || + (cl->list.internal_height != nl->list.internal_height) || + (cl->list.column_space != nl->list.column_space) || + (cl->list.row_space != nl->list.row_space) || + (cl->list.default_cols != nl->list.default_cols) || + ( (cl->list.force_cols != nl->list.force_cols) && + (rl->list.force_cols != nl->list.ncols) ) || + (cl->list.vertical_cols != nl->list.vertical_cols) || + (cl->list.longest != nl->list.longest) || + (cl->list.nitems != nl->list.nitems) || + (cl->list.font != nl->list.font) || + /* Equiv. fontsets might have different values, but the same fonts, so the + next comparison is sloppy but not dangerous. */ +#ifdef XAW_INTERNATIONALIZATION + (cl->list.fontset != nl->list.fontset) || +#endif + (cl->list.list != nl->list.list) ) { + + CalculatedValues( new ); + Layout( new, WidthFree( nl ), HeightFree( nl ), + &nl->core.width, &nl->core.height ); + redraw = TRUE; + } + + if (cl->list.list != nl->list.list) + nl->list.is_highlighted = nl->list.highlight = NO_HIGHLIGHT; + + if ((cl->core.sensitive != nl->core.sensitive) || + (cl->core.ancestor_sensitive != nl->core.ancestor_sensitive)) { + nl->list.highlight = NO_HIGHLIGHT; + redraw = TRUE; + } + + if (!XtIsRealized(current)) + return(FALSE); + + return(redraw); +} + +static void Destroy(w) + Widget w; +{ + ListWidget lw = (ListWidget) w; + XGCValues values; + + XGetGCValues(XtDisplay(w), lw->list.graygc, GCTile, &values); + XmuReleaseStippledPixmap(XtScreen(w), values.tile); + XtReleaseGC(w, lw->list.graygc); + XtReleaseGC(w, lw->list.revgc); + XtReleaseGC(w, lw->list.normgc); +} + +/* Exported Functions */ + +/* Function Name: XawListChange. + * Description: Changes the list being used and shown. + * Arguments: w - the list widget. + * list - the new list. + * nitems - the number of items in the list. + * longest - the length (in Pixels) of the longest element + * in the list. + * resize - if TRUE the the list widget will + * try to resize itself. + * Returns: none. + * NOTE: If nitems of longest are <= 0 then they will be calculated. + * If nitems is <= 0 then the list needs to be NULL terminated. + */ + +void +#if NeedFunctionPrototypes +XawListChange(Widget w, char ** list, int nitems, int longest, +#if NeedWidePrototypes + int resize_it) +#else + Boolean resize_it) +#endif +#else +XawListChange(w, list, nitems, longest, resize_it) +Widget w; +char ** list; +int nitems, longest; +Boolean resize_it; +#endif +{ + ListWidget lw = (ListWidget) w; + Dimension new_width = w->core.width; + Dimension new_height = w->core.height; + + lw->list.list = list; + + if ( nitems <= 0 ) nitems = 0; + lw->list.nitems = nitems; + if ( longest <= 0 ) longest = 0; + + /* If the user passes 0 meaning "calculate it", it must be free */ + if ( longest != 0 ) + lw->list.freedoms |= LongestLock; + else /* the user's word is god. */ + lw->list.freedoms &= ~LongestLock; + + if ( resize_it ) + lw->list.freedoms &= ~WidthLock & ~HeightLock; + /* else - still resize if its not locked */ + + lw->list.longest = longest; + + CalculatedValues( w ); + + if( Layout( w, WidthFree( w ), HeightFree( w ), + &new_width, &new_height ) ) + ChangeSize( w, new_width, new_height ); + + lw->list.is_highlighted = lw->list.highlight = NO_HIGHLIGHT; + if ( XtIsRealized( w ) ) + Redisplay( w, (XEvent *)NULL, (Region)NULL ); +} + +/* Function Name: XawListUnhighlight + * Description: unlights the current highlighted element. + * Arguments: w - the widget. + * Returns: none. + */ + +void +#if NeedFunctionPrototypes +XawListUnhighlight(Widget w) +#else +XawListUnhighlight(w) +Widget w; +#endif +{ + ListWidget lw = ( ListWidget ) w; + + lw->list.highlight = NO_HIGHLIGHT; + if (lw->list.is_highlighted != NO_HIGHLIGHT) + PaintItemName(w, lw->list.is_highlighted); /* unhighlight this one. */ +} + +/* Function Name: XawListHighlight + * Description: Highlights the given item. + * Arguments: w - the list widget. + * item - the item to hightlight. + * Returns: none. + */ + +void +#if NeedFunctionPrototypes +XawListHighlight(Widget w, int item) +#else +XawListHighlight(w, item) +Widget w; +int item; +#endif +{ + ListWidget lw = ( ListWidget ) w; + + if (XtIsSensitive(w)) { + lw->list.highlight = item; + if (lw->list.is_highlighted != NO_HIGHLIGHT) + PaintItemName(w, lw->list.is_highlighted); /* Unhighlight. */ + PaintItemName(w, item); /* HIGHLIGHT this one. */ + } +} + +/* Function Name: XawListShowCurrent + * Description: returns the currently highlighted object. + * Arguments: w - the list widget. + * Returns: the info about the currently highlighted object. + */ + +XawListReturnStruct * +#if NeedFunctionPrototypes +XawListShowCurrent(Widget w) +#else +XawListShowCurrent(w) +Widget w; +#endif +{ + ListWidget lw = ( ListWidget ) w; + XawListReturnStruct * ret_val; + + ret_val = (XawListReturnStruct *) + XtMalloc (sizeof (XawListReturnStruct));/* SPARE MALLOC OK */ + + ret_val->list_index = lw->list.highlight; + if (ret_val->list_index == XAW_LIST_NONE) + ret_val->string = ""; + else + ret_val->string = lw->list.list[ ret_val->list_index ]; + + return(ret_val); +} + diff --git a/src/List.h b/src/List.h new file mode 100644 index 0000000..a3d0abc --- /dev/null +++ b/src/List.h @@ -0,0 +1,239 @@ +/* $XConsortium: List.h,v 1.22 94/04/17 20:12:17 kaleb Exp $ */ + +/* +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. +*/ + +/* This is the List widget, it is useful to display a list, without the + * overhead of having a widget for each item in the list. It allows + * the user to select an item in a list and notifies the application through + * a callback function. + * + * Created: 8/13/88 + * By: Chris D. Peterson + * MIT X Consortium + */ + +#ifndef _XawList_h +#define _XawList_h + +/*********************************************************************** + * + * List Widget + * + ***********************************************************************/ + +#include "Xaw3dP.h" +#include <X11/Xaw3d/Simple.h> + +/* Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + background Background Pixel XtDefaultBackground + border BorderColor Pixel XtDefaultForeground + borderWidth BorderWidth Dimension 1 + callback Callback XtCallbackList NULL **6 + columnSpacing Spacing Dimension 6 + cursor Cursor Cursor left_ptr + cursorName Cursor String NULL + defaultColumns Columns int 2 **5 + destroyCallback Callback Pointer NULL + font Font XFontStruct* XtDefaultFont + forceColumns Columns Boolean False **5 + foreground Foreground Pixel XtDefaultForeground + height Height Dimension 0 **1 + insensitiveBorder Insensitive Pixmap Gray + internalHeight Height Dimension 2 + internalWidth Width Dimension 4 + list List String * NULL **2 + longest Longest int 0 **3 **4 + mappedWhenManaged MappedWhenManaged Boolean True + numberStrings NumberStrings int 0 **4 + pasteBuffer Boolean Boolean False + pointerColor Foreground Pixel XtDefaultForeground + pointerColorBackground Background Pixel XtDefaultBackground + rowSpacing Spacing Dimension 4 + sensitive Sensitive Boolean True + verticalList Boolean Boolean False + width Width Dimension 0 **1 + x Position Position 0 + y Position Position 0 + + **1 - If the Width or Height of the list widget is zero (0) then the value + is set to the minimum size necessay to fit the entire list. + + If both Width and Height are zero then they are adjusted to fit the + entire list that is created width the number of default columns + specified in the defaultColumns resource. + + **2 - This is an array of strings the specify elements of the list. + This resource must be specified. + (What good is a list widget without a list?? :-) + + **3 - Longest is the length of the widest string in pixels. + + **4 - If either of these values are zero (0) then the list widget calculates + the correct value. + + (This allows you to make startup faster if you already have + this information calculated) + + NOTE: If the numberStrings value is zero the list must + be NULL terminated. + + **5 - By setting the List.Columns resource you can force the application to + have a given number of columns. + + **6 - This returns the name and index of the item selected in an + XawListReturnStruct that is pointed to by the client_data + in the CallbackProc. + +*/ + + +/* + * Value returned when there are no highlighted objects. + */ + +#define XAW_LIST_NONE -1 + +#define XtCList "List" +#define XtCSpacing "Spacing" +#define XtCColumns "Columns" +#define XtCLongest "Longest" +#define XtCNumberStrings "NumberStrings" + +#define XtNcursor "cursor" +#define XtNcolumnSpacing "columnSpacing" +#define XtNdefaultColumns "defaultColumns" +#define XtNforceColumns "forceColumns" +#define XtNlist "list" +#define XtNlongest "longest" +#define XtNnumberStrings "numberStrings" +#define XtNpasteBuffer "pasteBuffer" +#define XtNrowSpacing "rowSpacing" +#define XtNverticalList "verticalList" + +#ifdef XAW_INTERNATIONALIZATION +#ifndef XtNfontSet +#define XtNfontSet "fontSet" +#endif +#ifndef XtCFontSet +#define XtCFontSet "FontSet" +#endif +#endif + +/* Class record constants */ + +extern WidgetClass listWidgetClass; + +typedef struct _ListClassRec *ListWidgetClass; +typedef struct _ListRec *ListWidget; + +/* The list return structure. */ + +typedef struct _XawListReturnStruct { + String string; + int list_index; +} XawListReturnStruct; + +/****************************************************************** + * + * Exported Functions + * + *****************************************************************/ + +_XFUNCPROTOBEGIN + +/* Function Name: XawListChange. + * Description: Changes the list being used and shown. + * Arguments: w - the list widget. + * list - the new list. + * nitems - the number of items in the list. + * longest - the length (in Pixels) of the longest element + * in the list. + * resize - if TRUE the the list widget will + * try to resize itself. + * Returns: none. + * NOTE: If nitems of longest are <= 0 then they will be caluculated. + * If nitems is <= 0 then the list needs to be NULL terminated. + */ + +extern void XawListChange( +#if NeedFunctionPrototypes + Widget /* w */, + String* /* list */, + int /* nitems */, + int /* longest */, +#if NeedWidePrototypes + /* Boolean */ int /* resize */ +#else + Boolean /* resize */ +#endif +#endif +); + +/* Function Name: XawListUnhighlight + * Description: unlights the current highlighted element. + * Arguments: w - the widget. + * Returns: none. + */ + +extern void XawListUnhighlight( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +/* Function Name: XawListHighlight + * Description: Highlights the given item. + * Arguments: w - the list widget. + * item - the item to highlight. + * Returns: none. + */ + +extern void XawListHighlight( +#if NeedFunctionPrototypes + Widget /* w */, + int /* item */ +#endif +); + + +/* Function Name: XawListShowCurrent + * Description: returns the currently highlighted object. + * Arguments: w - the list widget. + * Returns: the info about the currently highlighted object. + */ + +extern XawListReturnStruct * XawListShowCurrent( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +_XFUNCPROTOEND + +#endif /* _XawList_h */ diff --git a/src/ListP.h b/src/ListP.h new file mode 100644 index 0000000..592ef4c --- /dev/null +++ b/src/ListP.h @@ -0,0 +1,119 @@ +/* $XConsortium: ListP.h,v 1.14 94/04/17 20:12:17 kaleb Exp $ */ + +/* +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. +*/ + + +/* + * ListP.h - Private definitions for List widget + * + * This is a List widget. It allows the user to select an item in a list and + * notifies the application through a callback function. + * + * Created: 8/13/88 + * By: Chris D. Peterson + * MIT - Project Athena + */ + +#ifndef _XawListP_h +#define _XawListP_h + +/*********************************************************************** + * + * List Widget Private Data + * + ***********************************************************************/ + +#include "Xaw3dP.h" +#include <X11/Xaw3d/SimpleP.h> +#include <X11/Xaw3d/List.h> + +#define NO_HIGHLIGHT XAW_LIST_NONE +#define OUT_OF_RANGE -1 +#define OKAY 0 + +/* New fields for the List widget class record */ + +typedef struct {int foo;} ListClassPart; + +/* Full class record declaration */ +typedef struct _ListClassRec { + CoreClassPart core_class; + SimpleClassPart simple_class; + ListClassPart list_class; +} ListClassRec; + +extern ListClassRec listClassRec; + +/* New fields for the List widget record */ +typedef struct { + /* resources */ + Pixel foreground; + Dimension internal_width, /* if not 3d, user sets directly. */ + internal_height, + column_space, /* half of *_space is add on top/bot/left of*/ + row_space; /* each item's text bounding box. half added to longest for right */ + int default_cols; + Boolean force_cols, + paste, + vertical_cols; + int longest; /* in pixels */ + int nitems; /* number of items in the list. */ + XFontStruct *font; +#ifdef XAW_INTERNATIONALIZATION + XFontSet fontset; /* Sheeran, Omron KK, 93/03/05 */ +#endif + String * list; /* for i18n, always in multibyte format */ + XtCallbackList callback; + + /* private state */ + int is_highlighted, /* set to the item currently highlighted. */ + highlight, /* set to the item that should be highlighted.*/ + col_width, /* width of each column. */ + row_height, /* height of each row. */ + nrows, /* number of rows in the list. */ + ncols; /* number of columns in the list. */ + GC normgc, /* a couple of GC's. */ + revgc, + graygc; /* used when inactive. */ + + int freedoms; /* flags for resizing height and width */ + +} ListPart; + + +/**************************************************************** + * + * Full instance record declaration + * + ****************************************************************/ + +typedef struct _ListRec { + CorePart core; + SimplePart simple; + ListPart list; +} ListRec; + +#endif /* _XawListP_h */ diff --git a/src/MenuButtoP.h b/src/MenuButtoP.h new file mode 100644 index 0000000..df2f9dd --- /dev/null +++ b/src/MenuButtoP.h @@ -0,0 +1,102 @@ +/* $XConsortium: MenuButtoP.h,v 1.8 94/04/17 20:12:18 converse Exp $ + * +Copyright (c) 1989 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + */ + +/*********************************************************************** + * + * MenuButton Widget + * + ***********************************************************************/ + +/* + * MenuButtonP.h - Private Header file for MenuButton widget. + * + * This is the private header file for the Athena MenuButton widget. + * It is intended to provide an easy method of activating pulldown menus. + * + * Date: May 2, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifndef _XawMenuButtonP_h +#define _XawMenuButtonP_h + +#include <X11/Xaw3d/MenuButton.h> +#include <X11/Xaw3d/CommandP.h> + +/************************************ + * + * Class structure + * + ***********************************/ + + + /* New fields for the MenuButton widget class record */ +typedef struct _MenuButtonClass +{ + int makes_compiler_happy; /* not used */ +} MenuButtonClassPart; + + /* Full class record declaration */ +typedef struct _MenuButtonClassRec { + CoreClassPart core_class; + SimpleClassPart simple_class; + ThreeDClassPart threeD_class; + LabelClassPart label_class; + CommandClassPart command_class; + MenuButtonClassPart menuButton_class; +} MenuButtonClassRec; + +extern MenuButtonClassRec menuButtonClassRec; + +/*************************************** + * + * Instance (widget) structure + * + **************************************/ + + /* New fields for the MenuButton widget record */ +typedef struct { + /* resources */ + String menu_name; + +} MenuButtonPart; + + /* Full widget declaration */ +typedef struct _MenuButtonRec { + CorePart core; + SimplePart simple; + ThreeDPart threeD; + LabelPart label; + CommandPart command; + MenuButtonPart menu_button; +} MenuButtonRec; + +#endif /* _XawMenuButtonP_h */ + + diff --git a/src/MenuButton.c b/src/MenuButton.c new file mode 100644 index 0000000..b96a027 --- /dev/null +++ b/src/MenuButton.c @@ -0,0 +1,221 @@ +/* $XConsortium: MenuButton.c,v 1.21 95/06/26 20:35:12 kaleb Exp $ */ + +/* +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + */ + + +/*********************************************************************** + * + * MenuButton Widget + * + ***********************************************************************/ + +/* + * MenuButton.c - Source code for MenuButton widget. + * + * This is the source code for the Athena MenuButton widget. + * It is intended to provide an easy method of activating pulldown menus. + * + * Date: May 2, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> + +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/MenuButtoP.h> + +static void ClassInitialize(); +static void PopupMenu(); + +#define superclass ((CommandWidgetClass)&commandClassRec) + +static char defaultTranslations[] = +"<EnterWindow>: highlight()\n\ + <LeaveWindow>: reset()\n\ + Any<BtnDown>: reset() PopupMenu()"; + +/**************************************************************** + * + * Full class record constant + * + ****************************************************************/ + +/* Private Data */ + +#define offset(field) XtOffsetOf(MenuButtonRec, field) +static XtResource resources[] = { + { + XtNmenuName, XtCMenuName, XtRString, sizeof(String), + offset(menu_button.menu_name), XtRString, (XtPointer)"menu"}, +}; +#undef offset + +static XtActionsRec actionsList[] = +{ + {"PopupMenu", PopupMenu} +}; + +MenuButtonClassRec menuButtonClassRec = { + { + (WidgetClass) superclass, /* superclass */ + "MenuButton", /* class_name */ + sizeof(MenuButtonRec), /* size */ + ClassInitialize, /* class_initialize */ + NULL, /* class_part_initialize */ + FALSE, /* class_inited */ + NULL, /* initialize */ + NULL, /* initialize_hook */ + XtInheritRealize, /* realize */ + actionsList, /* actions */ + XtNumber(actionsList), /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* resource_count */ + NULLQUARK, /* xrm_class */ + FALSE, /* compress_motion */ + TRUE, /* compress_exposure */ + TRUE, /* compress_enterleave */ + FALSE, /* visible_interest */ + NULL, /* destroy */ + XtInheritResize, /* resize */ + XtInheritExpose, /* expose */ + NULL, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + defaultTranslations, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL /* extension */ + }, /* CoreClass fields initialization */ + { + XtInheritChangeSensitive /* change_sensitive */ + }, /* SimpleClass fields initialization */ + { + XtInheritXaw3dShadowDraw, /* shadowdraw */ + }, /* ThreeDClass fields initialization */ + { + 0, /* field not used */ + }, /* LabelClass fields initialization */ + { + 0, /* field not used */ + }, /* CommandClass fields initialization */ + { + 0, /* field not used */ + } /* MenuButtonClass fields initialization */ +}; + + /* for public consumption */ +WidgetClass menuButtonWidgetClass = (WidgetClass) &menuButtonClassRec; + +/**************************************************************** + * + * Private Procedures + * + ****************************************************************/ + +static void ClassInitialize() +{ + XawInitializeWidgetSet(); + XtRegisterGrabAction(PopupMenu, True, + (unsigned int)(ButtonPressMask | ButtonReleaseMask), + GrabModeAsync, GrabModeAsync); +} + +/* ARGSUSED */ +static void +PopupMenu(w, event, params, num_params) +Widget w; +XEvent * event; +String * params; +Cardinal * num_params; +{ + MenuButtonWidget mbw = (MenuButtonWidget) w; + Widget menu = NULL, temp; + Arg arglist[2]; + Cardinal num_args; + int menu_x, menu_y, menu_width, menu_height, button_height; + Position button_x, button_y; + + temp = w; + while(temp != NULL) { + menu = XtNameToWidget(temp, mbw->menu_button.menu_name); + if (menu == NULL) + temp = XtParent(temp); + else + break; + } + + if (menu == NULL) { + char error_buf[BUFSIZ]; + (void) sprintf(error_buf, "MenuButton: %s %s.", + "Could not find menu widget named", mbw->menu_button.menu_name); + XtAppWarning(XtWidgetToApplicationContext(w), error_buf); + return; + } + if (!XtIsRealized(menu)) + XtRealizeWidget(menu); + + menu_width = menu->core.width + 2 * menu->core.border_width; + button_height = w->core.height + 2 * w->core.border_width; + menu_height = menu->core.height + 2 * menu->core.border_width; + + XtTranslateCoords(w, 0, 0, &button_x, &button_y); + menu_x = button_x; + menu_y = button_y + button_height; + + if (menu_x >= 0) { + int scr_width = WidthOfScreen(XtScreen(menu)); + if (menu_x + menu_width > scr_width) + menu_x = scr_width - menu_width; + } + if (menu_x < 0) + menu_x = 0; + + if (menu_y >= 0) { + int scr_height = HeightOfScreen(XtScreen(menu)); + if (menu_y + menu_height > scr_height) + menu_y = scr_height - menu_height; + } + if (menu_y < 0) + menu_y = 0; + + num_args = 0; + XtSetArg(arglist[num_args], XtNx, menu_x); num_args++; + XtSetArg(arglist[num_args], XtNy, menu_y); num_args++; + XtSetValues(menu, arglist, num_args); + + XtPopupSpringLoaded(menu); +} + diff --git a/src/MenuButton.h b/src/MenuButton.h new file mode 100644 index 0000000..c9ee0df --- /dev/null +++ b/src/MenuButton.h @@ -0,0 +1,90 @@ +/* + * $XConsortium: MenuButton.h,v 1.9 94/04/17 20:12:21 kaleb Exp $ + * +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + */ + +/*********************************************************************** + * + * MenuButton Widget + * + ***********************************************************************/ + +/* + * MenuButton.h - Public Header file for MenuButton widget. + * + * This is the public header file for the Athena MenuButton widget. + * It is intended to provide an easy method of activating pulldown menus. + * + * Date: May 2, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifndef _XawMenuButton_h +#define _XawMenuButton_h + +#include <X11/Xaw3d/Command.h> + +/* Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + background Background Pixel XtDefaultBackground + bitmap Pixmap Pixmap None + border BorderColor Pixel XtDefaultForeground + borderWidth BorderWidth Dimension 1 + callback Callback Pointer NULL + cursor Cursor Cursor None + destroyCallback Callback Pointer NULL + font Font XFontStruct* XtDefaultFont + foreground Foreground Pixel XtDefaultForeground + height Height Dimension text height + highlightThickness Thickness Dimension 2 + insensitiveBorder Insensitive Pixmap Gray + internalHeight Height Dimension 2 + internalWidth Width Dimension 4 + justify Justify XtJustify XtJustifyCenter + label Label String NULL + mappedWhenManaged MappedWhenManaged Boolean True + menuName MenuName String "menu" + resize Resize Boolean True + sensitive Sensitive Boolean True + width Width Dimension text width + x Position Position 0 + y Position Position 0 + +*/ + +#define XtNmenuName "menuName" +#define XtCMenuName "MenuName" + +extern WidgetClass menuButtonWidgetClass; + +typedef struct _MenuButtonClassRec *MenuButtonWidgetClass; +typedef struct _MenuButtonRec *MenuButtonWidget; + +#endif /* _XawMenuButton_h */ diff --git a/src/MultiSink.c b/src/MultiSink.c new file mode 100644 index 0000000..12ef85c --- /dev/null +++ b/src/MultiSink.c @@ -0,0 +1,780 @@ +/* $XConsortium: MultiSink.c,v 1.6 95/01/23 18:34:46 kaleb Exp $ */ + +/* + * Copyright 1991 by OMRON Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 OMRON not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. OMRON makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OMRON 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: Li Yuhong OMRON Corporation + */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xatom.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/MultiSinkP.h> +#include <X11/Xaw3d/MultiSrcP.h> +#include <X11/Xaw3d/TextP.h> +#include "XawI18n.h" +#include <stdio.h> +#include <ctype.h> + +#ifdef GETLASTPOS +#undef GETLASTPOS /* We will use our own GETLASTPOS. */ +#endif + +#define GETLASTPOS XawTextSourceScan(source, (XawTextPosition) 0, XawstAll, XawsdRight, 1, TRUE) + +static void Initialize(), Destroy(); +static Boolean SetValues(); +static int MaxLines(), MaxHeight(); +static void SetTabs(); + +static void DisplayText(), InsertCursor(), FindPosition(); +static void FindDistance(), Resolve(), GetCursorBounds(); + +#define offset(field) XtOffsetOf(MultiSinkRec, multi_sink.field) + +static XtResource resources[] = { + {XtNfontSet, XtCFontSet, XtRFontSet, sizeof (XFontSet), + offset(fontset), XtRString, XtDefaultFontSet}, + {XtNecho, XtCOutput, XtRBoolean, sizeof(Boolean), + offset(echo), XtRImmediate, (XtPointer) True}, + {XtNdisplayNonprinting, XtCOutput, XtRBoolean, sizeof(Boolean), + offset(display_nonprinting), XtRImmediate, (XtPointer) True}, +}; +#undef offset + +#define SuperClass (&textSinkClassRec) +MultiSinkClassRec multiSinkClassRec = { + { /* core_class fields */ + /* superclass */ (WidgetClass) SuperClass, + /* class_name */ "MultiSink", + /* widget_size */ sizeof(MultiSinkRec), + /* class_initialize */ XawInitializeWidgetSet, + /* class_part_initialize */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* obj1 */ NULL, + /* obj2 */ NULL, + /* obj3 */ 0, + /* resources */ resources, + /* num_resources */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* obj4 */ FALSE, + /* obj5 */ FALSE, + /* obj6 */ FALSE, + /* obj7 */ FALSE, + /* destroy */ Destroy, + /* obj8 */ NULL, + /* obj9 */ NULL, + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* obj10 */ NULL, + /* get_values_hook */ NULL, + /* obj11 */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* obj12 */ NULL, + /* obj13 */ NULL, + /* obj14 */ NULL, + /* extension */ NULL + }, + { /* text_sink_class fields */ + /* DisplayText */ DisplayText, + /* InsertCursor */ InsertCursor, + /* ClearToBackground */ XtInheritClearToBackground, + /* FindPosition */ FindPosition, + /* FindDistance */ FindDistance, + /* Resolve */ Resolve, + /* MaxLines */ MaxLines, + /* MaxHeight */ MaxHeight, + /* SetTabs */ SetTabs, + /* GetCursorBounds */ GetCursorBounds + }, + { /* multi_sink_class fields */ + /* unused */ 0 + } +}; + +WidgetClass multiSinkObjectClass = (WidgetClass)&multiSinkClassRec; + +/* Utilities */ + +static int +#if NeedFunctionPrototypes +CharWidth ( + Widget w, + int x, + wchar_t c) +#else +CharWidth (w, x, c) + Widget w; + int x; + wchar_t c; +#endif +{ + int i, width; + MultiSinkObject sink = (MultiSinkObject) w; + XFontSet fontset = sink->multi_sink.fontset; + Position *tab; + + if ( c == _Xaw_atowc(XawLF) ) return(0); + + if (c == _Xaw_atowc(XawTAB)) { + /* Adjust for Left Margin. */ + x -= ((TextWidget) XtParent(w))->text.margin.left; + + if (x >= (int)XtParent(w)->core.width) return 0; + for (i = 0, tab = sink->text_sink.tabs ; + i < sink->text_sink.tab_count ; i++, tab++) { + if (x < *tab) { + if (*tab < (int)XtParent(w)->core.width) + return *tab - x; + else + return 0; + } + } + return 0; + } + + if (XwcTextEscapement (fontset, &c, 1) == 0) + if (sink->multi_sink.display_nonprinting) + c = _Xaw_atowc('@'); + else { + c = _Xaw_atowc(XawSP); + } + + /* + * if more efficiency(suppose one column is one ASCII char) + + width = XwcGetColumn(fontset->font_charset, fontset->num_of_fonts, c) * + fontset->font_struct_list[0]->min_bounds.width; + * + * WARNING: Very Slower!!! + * + * Li Yuhong. + */ + + width = XwcTextEscapement(fontset, &c, 1); + + return width; +} + +/* Function Name: PaintText + * Description: Actually paints the text into the windoe. + * Arguments: w - the text widget. + * gc - gc to paint text with. + * x, y - location to paint the text. + * buf, len - buffer and length of text to paint. + * Returns: the width of the text painted, or 0. + * + * NOTE: If this string attempts to paint past the end of the window + * then this function will return zero. + */ + +static Dimension +PaintText(w, gc, x, y, buf, len) + Widget w; + GC gc; + Position x, y; + wchar_t* buf; + int len; +{ + MultiSinkObject sink = (MultiSinkObject) w; + TextWidget ctx = (TextWidget) XtParent(w); + + XFontSet fontset = sink->multi_sink.fontset; + Position max_x; + Dimension width = XwcTextEscapement(fontset, buf, len); + XFontSetExtents *ext = XExtentsOfFontSet(fontset); + max_x = (Position) ctx->core.width; + + if ( ((int) width) <= -x) /* Don't draw if we can't see it. */ + return(width); + + XwcDrawImageString(XtDisplay(ctx), XtWindow(ctx), fontset, gc, + (int) x, (int) y, buf, len); + if ( (((Position) width + x) > max_x) && (ctx->text.margin.right != 0) ) { + x = ctx->core.width - ctx->text.margin.right; + width = ctx->text.margin.right; + XFillRectangle(XtDisplay((Widget) ctx), XtWindow( (Widget) ctx), + sink->multi_sink.normgc, (int) x, + (int) y - abs(ext->max_logical_extent.y), + (unsigned int) width, + (unsigned int) ext->max_logical_extent.height); + return(0); + } + return(width); +} + +/* Sink Object Functions */ + +/* + * This function does not know about drawing more than one line of text. + */ + +static void +DisplayText(w, x, y, pos1, pos2, highlight) + Widget w; + Position x, y; + Boolean highlight; + XawTextPosition pos1, pos2; +{ + MultiSinkObject sink = (MultiSinkObject) w; + Widget source = XawTextGetSource(XtParent(w)); + wchar_t buf[BUFSIZ]; + XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset); + + int j, k; + XawTextBlock blk; + GC gc = highlight ? sink->multi_sink.invgc : sink->multi_sink.normgc; + GC invgc = highlight ? sink->multi_sink.normgc : sink->multi_sink.invgc; + + if (!sink->multi_sink.echo) return; + + y += abs(ext->max_logical_extent.y); + for ( j = 0 ; pos1 < pos2 ; ) { + pos1 = XawTextSourceRead(source, pos1, &blk, (int) pos2 - pos1); + for (k = 0; k < blk.length; k++) { + if (j >= BUFSIZ) { /* buffer full, dump the text. */ + x += PaintText(w, gc, x, y, buf, j); + j = 0; + } + buf[j] = ((wchar_t *)blk.ptr)[k]; + if (buf[j] == _Xaw_atowc(XawLF)) + continue; + + else if (buf[j] == _Xaw_atowc(XawTAB)) { + Position temp = 0; + Dimension width; + + if ((j != 0) && ((temp = PaintText(w, gc, x, y, buf, j)) == 0)) + return; + + x += temp; + width = CharWidth(w, x, _Xaw_atowc(XawTAB)); + XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w), + invgc, (int) x, + (int) y - abs(ext->max_logical_extent.y), + (unsigned int)width, + (unsigned int)ext->max_logical_extent.height); + x += width; + j = -1; + } + else if (XwcTextEscapement (sink->multi_sink.fontset, &buf[j], 1) == 0) { + if (sink->multi_sink.display_nonprinting) + buf[j] = _Xaw_atowc('@'); + else + buf[j] = _Xaw_atowc(' '); + } + j++; + } + } + if (j > 0) + (void) PaintText(w, gc, x, y, buf, j); +} + +#define insertCursor_width 6 +#define insertCursor_height 3 +static char insertCursor_bits[] = {0x0c, 0x1e, 0x33}; + +static Pixmap +CreateInsertCursor(s) + Screen *s; +{ + return (XCreateBitmapFromData (DisplayOfScreen(s), RootWindowOfScreen(s), + insertCursor_bits, insertCursor_width, insertCursor_height)); +} + +/* Function Name: GetCursorBounds + * Description: Returns the size and location of the cursor. + * Arguments: w - the text object. + * RETURNED rect - an X rectangle to return the cursor bounds in. + * Returns: none. + */ + +static void +GetCursorBounds(w, rect) + Widget w; + XRectangle * rect; +{ + MultiSinkObject sink = (MultiSinkObject) w; + + rect->width = (unsigned short) insertCursor_width; + rect->height = (unsigned short) insertCursor_height; + rect->x = sink->multi_sink.cursor_x - (short) (rect->width / 2); + rect->y = sink->multi_sink.cursor_y - (short) rect->height; +} + +/* + * The following procedure manages the "insert" cursor. + */ + +static void +InsertCursor (w, x, y, state) + Widget w; + Position x, y; + XawTextInsertState state; +{ + MultiSinkObject sink = (MultiSinkObject) w; + Widget text_widget = XtParent(w); + XRectangle rect; + + sink->multi_sink.cursor_x = x; + sink->multi_sink.cursor_y = y; + + GetCursorBounds(w, &rect); + if (state != sink->multi_sink.laststate && XtIsRealized(text_widget)) + XCopyPlane(XtDisplay(text_widget), + sink->multi_sink.insertCursorOn, + XtWindow(text_widget), sink->multi_sink.xorgc, + 0, 0, (unsigned int) rect.width, (unsigned int) rect.height, + (int) rect.x, (int) rect.y, 1); + sink->multi_sink.laststate = state; +} + +/* + * Given two positions, find the distance between them. + */ + +static void +FindDistance (w, fromPos, fromx, toPos, resWidth, resPos, resHeight) + Widget w; + XawTextPosition fromPos; /* First position. */ + int fromx; /* Horizontal location of first position. */ + XawTextPosition toPos; /* Second position. */ + int* resWidth; /* Distance between fromPos and resPos. */ + XawTextPosition* resPos; /* Actual second position used. */ + int* resHeight; /* Height required. */ +{ + MultiSinkObject sink = (MultiSinkObject) w; + Widget source = XawTextGetSource(XtParent(w)); + + XawTextPosition index, lastPos; + wchar_t c; + XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset); + XawTextBlock blk; + + /* we may not need this */ + lastPos = GETLASTPOS; + XawTextSourceRead(source, fromPos, &blk, (int) toPos - fromPos); + *resWidth = 0; + for (index = fromPos; index != toPos && index < lastPos; index++) { + if (index - blk.firstPos >= blk.length) + XawTextSourceRead(source, index, &blk, (int) toPos - fromPos); + c = ((wchar_t *)blk.ptr)[index - blk.firstPos]; + *resWidth += CharWidth(w, fromx + *resWidth, c); + if (c == _Xaw_atowc(XawLF)) { + index++; + break; + } + } + *resPos = index; + *resHeight = ext->max_logical_extent.height; +} + + +static void +FindPosition(w, fromPos, fromx, width, stopAtWordBreak, resPos, resWidth, resHeight) + Widget w; + XawTextPosition fromPos; /* Starting position. */ + int fromx; /* Horizontal location of starting position.*/ + int width; /* Desired width. */ + int stopAtWordBreak; /* Whether the resulting position should be at + a word break. */ + XawTextPosition *resPos; /* Resulting position. */ + int* resWidth; /* Actual width used. */ + int* resHeight; /* Height required. */ +{ + MultiSinkObject sink = (MultiSinkObject) w; + Widget source = XawTextGetSource(XtParent(w)); + + XawTextPosition lastPos, index, whiteSpacePosition = 0; + int lastWidth = 0, whiteSpaceWidth = 0; + Boolean whiteSpaceSeen; + wchar_t c; + XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset); + XawTextBlock blk; + + lastPos = GETLASTPOS; + + XawTextSourceRead(source, fromPos, &blk, BUFSIZ); + *resWidth = 0; + whiteSpaceSeen = FALSE; + c = 0; + for (index = fromPos; *resWidth <= width && index < lastPos; index++) { + lastWidth = *resWidth; + if (index - blk.firstPos >= blk.length) + XawTextSourceRead(source, index, &blk, BUFSIZ); + c = ((wchar_t *)blk.ptr)[index - blk.firstPos]; + *resWidth += CharWidth(w, fromx + *resWidth, c); + + if ((c == _Xaw_atowc(XawSP) || c == _Xaw_atowc(XawTAB)) && + *resWidth <= width) { + whiteSpaceSeen = TRUE; + whiteSpacePosition = index; + whiteSpaceWidth = *resWidth; + } + if (c == _Xaw_atowc(XawLF)) { + index++; + break; + } + } + if (*resWidth > width && index > fromPos) { + *resWidth = lastWidth; + index--; + if (stopAtWordBreak && whiteSpaceSeen) { + index = whiteSpacePosition + 1; + *resWidth = whiteSpaceWidth; + } + } + if (index == lastPos && c != _Xaw_atowc(XawLF)) index = lastPos + 1; + *resPos = index; + *resHeight = ext->max_logical_extent.height; +} + +static void +Resolve (w, pos, fromx, width, leftPos, rightPos) + Widget w; + XawTextPosition pos; + int fromx, width; + XawTextPosition *leftPos, *rightPos; +{ + int resWidth, resHeight; + Widget source = XawTextGetSource(XtParent(w)); + + FindPosition(w, pos, fromx, width, FALSE, leftPos, &resWidth, &resHeight); + if (*leftPos > GETLASTPOS) + *leftPos = GETLASTPOS; + *rightPos = *leftPos; +} + +static void +GetGC(sink) + MultiSinkObject sink; +{ + XtGCMask valuemask = (GCGraphicsExposures | GCForeground | GCBackground ); + XGCValues values; + + values.graphics_exposures = (Bool) FALSE; + + values.foreground = sink->text_sink.foreground; + values.background = sink->text_sink.background; + + sink->multi_sink.normgc = XtAllocateGC( (Widget)sink, 0, valuemask, &values, GCFont, 0 ); + + values.foreground = sink->text_sink.background; + values.background = sink->text_sink.foreground; + sink->multi_sink.invgc = XtAllocateGC( (Widget)sink, 0, valuemask, &values, GCFont, 0 ); + + values.function = GXxor; + values.background = (unsigned long) 0L; /* (pix ^ 0) = pix */ + values.foreground = (sink->text_sink.background ^ + sink->text_sink.foreground); + valuemask = GCGraphicsExposures | GCFunction | GCForeground | GCBackground; + + /* if this GC is not used for fontset rendering then AllocateGC aint needed. Dont hurt tho.*/ + sink->multi_sink.xorgc = XtAllocateGC( (Widget)sink, 0, valuemask, &values, GCFont, 0 ); +} + + +/***** Public routines *****/ + +/* Function Name: Initialize + * Description: Initializes the TextSink Object. + * Arguments: request, new - the requested and new values for the object + * instance. + * Returns: none. + * + */ + +/* ARGSUSED */ +static void +Initialize(request, new, args, num_args) + Widget request, new; + ArgList args; + Cardinal* num_args; +{ + MultiSinkObject sink = (MultiSinkObject) new; + + GetGC(sink); + + sink->multi_sink.insertCursorOn= CreateInsertCursor(XtScreenOfObject(new)); + sink->multi_sink.laststate = XawisOff; + sink->multi_sink.cursor_x = sink->multi_sink.cursor_y = 0; +} + +/* Function Name: Destroy + * Description: This function cleans up when the object is + * destroyed. + * Arguments: w - the MultiSink Object. + * Returns: none. + */ + +static void +Destroy(w) + Widget w; +{ + MultiSinkObject sink = (MultiSinkObject) w; + + XtReleaseGC(w, sink->multi_sink.normgc); + XtReleaseGC(w, sink->multi_sink.invgc); + XtReleaseGC(w, sink->multi_sink.xorgc); + + XFreePixmap(XtDisplayOfObject(w), sink->multi_sink.insertCursorOn); +} + +/* Function Name: SetValues + * Description: Sets the values for the MultiSink + * Arguments: current - current state of the object. + * request - what was requested. + * new - what the object will become. + * Returns: True if redisplay is needed. + */ + +/* ARGSUSED */ +static Boolean +SetValues(current, request, new, args, num_args) + Widget current, request, new; + ArgList args; + Cardinal* num_args; +{ + MultiSinkObject w = (MultiSinkObject) new; + MultiSinkObject old_w = (MultiSinkObject) current; + + /* Font set is not in the GC! Do not make a new GC when font set changes! */ + + if ( w->multi_sink.fontset != old_w->multi_sink.fontset ) { + ((TextWidget)XtParent(new))->text.redisplay_needed = True; +#ifndef NO_TAB_FIX + SetTabs( w, w->text_sink.tab_count, w->text_sink.char_tabs ); +#endif + } + + if ( w->text_sink.background != old_w->text_sink.background || + w->text_sink.foreground != old_w->text_sink.foreground ) { + + XtReleaseGC((Widget)w, w->multi_sink.normgc); + XtReleaseGC((Widget)w, w->multi_sink.invgc); + XtReleaseGC((Widget)w, w->multi_sink.xorgc); + GetGC(w); + ((TextWidget)XtParent(new))->text.redisplay_needed = True; + } else { + if ( (w->multi_sink.echo != old_w->multi_sink.echo) || + (w->multi_sink.display_nonprinting != + old_w->multi_sink.display_nonprinting) ) + ((TextWidget)XtParent(new))->text.redisplay_needed = True; + } + + return False; +} + +/* Function Name: MaxLines + * Description: Finds the Maximum number of lines that will fit in + * a given height. + * Arguments: w - the MultiSink Object. + * height - height to fit lines into. + * Returns: the number of lines that will fit. + */ + +/* ARGSUSED */ +static int +MaxLines(w, height) + Widget w; + Dimension height; +{ + MultiSinkObject sink = (MultiSinkObject) w; + int font_height; + XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset); + + font_height = ext->max_logical_extent.height; + return( ((int) height) / font_height ); +} + +/* Function Name: MaxHeight + * Description: Finds the Minium height that will contain a given number + * lines. + * Arguments: w - the MultiSink Object. + * lines - the number of lines. + * Returns: the height. + */ + +/* ARGSUSED */ +static int +#if NeedFunctionPrototypes +MaxHeight( + Widget w, + int lines ) +#else +MaxHeight( w, lines ) + Widget w; + int lines; +#endif +{ + MultiSinkObject sink = (MultiSinkObject) w; + XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset); + + return(lines * ext->max_logical_extent.height); +} + +/* Function Name: SetTabs + * Description: Sets the Tab stops. + * Arguments: w - the MultiSink Object. + * tab_count - the number of tabs in the list. + * tabs - the text positions of the tabs. + * Returns: none + */ + +static void +#if NeedFunctionPrototypes +SetTabs( + Widget w, + int tab_count, + short* tabs ) +#else +SetTabs( w, tab_count, tabs ) + Widget w; + int tab_count; + short* tabs; +#endif +{ + MultiSinkObject sink = (MultiSinkObject) w; + int i; + Atom XA_FIGURE_WIDTH; + unsigned long figure_width = 0; + XFontStruct *font; + + /* + * Bug: + * Suppose the first font of fontset stores the unit of column. + * + * By Li Yuhong, Mar. 14, 1991 + */ + { XFontStruct **f_list; + char **f_name; + + (void) XFontsOfFontSet(sink->multi_sink.fontset, &f_list, &f_name); + font = f_list[0]; + } + +/* + * Find the figure width of the current font. + */ + + XA_FIGURE_WIDTH = XInternAtom(XtDisplayOfObject(w), "FIGURE_WIDTH", FALSE); + if ( (XA_FIGURE_WIDTH != None) && + ( (!XGetFontProperty(font, XA_FIGURE_WIDTH, &figure_width)) || + (figure_width == 0)) ) + if (font->per_char && font->min_char_or_byte2 <= '$' && + font->max_char_or_byte2 >= '$') + figure_width = font->per_char['$' - font->min_char_or_byte2].width; + else + figure_width = font->max_bounds.width; + + if (tab_count > sink->text_sink.tab_count) { + sink->text_sink.tabs = (Position *) + XtRealloc((char *) sink->text_sink.tabs, + (Cardinal) (tab_count * sizeof(Position))); + sink->text_sink.char_tabs = (short *) + XtRealloc((char *) sink->text_sink.char_tabs, + (Cardinal) (tab_count * sizeof(short))); + } + + for ( i = 0 ; i < tab_count ; i++ ) { + sink->text_sink.tabs[i] = tabs[i] * figure_width; + sink->text_sink.char_tabs[i] = tabs[i]; + } + + sink->text_sink.tab_count = tab_count; + +#ifndef NO_TAB_FIX + ((TextWidget)XtParent(w))->text.redisplay_needed = True; +#endif +} + +void +#if NeedFunctionPrototypes +_XawMultiSinkPosToXY( + Widget w, + XawTextPosition pos, + Position *x, + Position *y ) +#else +_XawMultiSinkPosToXY( w, pos, x, y ) + Widget w; + XawTextPosition pos; + Position *x, *y; +#endif +{ + MultiSinkObject sink = (MultiSinkObject) ((TextWidget)w)->text.sink; + XFontSetExtents *ext = XExtentsOfFontSet( sink->multi_sink.fontset ); + + _XawTextPosToXY( w, pos, x, y ); + *y += abs( ext->max_logical_extent.y ); +} diff --git a/src/MultiSink.h b/src/MultiSink.h new file mode 100644 index 0000000..9cb7300 --- /dev/null +++ b/src/MultiSink.h @@ -0,0 +1,118 @@ +/* $XConsortium: MultiSink.h,v 1.2 94/04/17 20:12:23 kaleb Exp $ */ + +/* + * Copyright 1991 by OMRON Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 OMRON is not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OMRON makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OMRON 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: Li Yuhong OMRON Corporation + */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _XawMultiSink_h +#define _XawMultiSink_h + +/*********************************************************************** + * + * MultiSink Object + * + ***********************************************************************/ + +#include <X11/Xaw3d/TextSink.h> + +/* Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + echo Output Boolean True + displayNonprinting Output Boolean True + fontSet FontSet XFontSet XtDefaultFontSet + +*/ + +#define XtCOutput "Output" + +#define XtNdisplayNonprinting "displayNonprinting" +#define XtNecho "echo" + +#ifndef XtNfontSet /*Sheeran, Omron KK, 93/03/04*/ +#define XtNfontSet "fontSet" +#endif + +#ifndef XtCFontSet /*Sheeran, Omron KK, 93/03/04*/ +#define XtCFontSet "FontSet" +#endif + +/* Class record constants */ + +extern WidgetClass multiSinkObjectClass; + +typedef struct _MultiSinkClassRec *MultiSinkObjectClass; +typedef struct _MultiSinkRec *MultiSinkObject; + + +#endif /* _XawMultiSrc_h */ +/* DON'T ADD STUFF AFTER THIS #endif */ diff --git a/src/MultiSinkP.h b/src/MultiSinkP.h new file mode 100644 index 0000000..1e13914 --- /dev/null +++ b/src/MultiSinkP.h @@ -0,0 +1,157 @@ +/* $XConsortium: MultiSinkP.h,v 1.2 94/04/17 20:12:24 kaleb Exp $ */ + +/* + * Copyright 1991 by OMRON Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 OMRON not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OMRON make no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OMRON 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: Li Yuhong OMRON Corporation + */ + + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * multiSinkP.h - Private definitions for multiSink object + * + */ + +#ifndef _XawMultiSinkP_h +#define _XawMultiSinkP_h + +/*********************************************************************** + * + * MultiSink Object Private Data + * + ***********************************************************************/ + +#include <X11/Xaw3d/TextSinkP.h> +#include <X11/Xaw3d/MultiSink.h> + +/************************************************************ + * + * New fields for the MultiSink object class record. + * + ************************************************************/ + +typedef struct _MultiSinkClassPart { + int foo; +} MultiSinkClassPart; + +/* Full class record declaration */ + +typedef struct _MultiSinkClassRec { + ObjectClassPart object_class; + TextSinkClassPart text_sink_class; + MultiSinkClassPart multi_sink_class; +} MultiSinkClassRec; + +extern MultiSinkClassRec multiSinkClassRec; + +/* New fields for the MultiSink object record */ +typedef struct { + /* public resources */ + Boolean echo; + Boolean display_nonprinting; + + /* private state */ + GC normgc, invgc, xorgc; + Pixmap insertCursorOn; + XawTextInsertState laststate; + short cursor_x, cursor_y; /* Cursor Location. */ + XFontSet fontset; /* font set to draw */ +} MultiSinkPart; + +/**************************************************************** + * + * Full instance record declaration + * + ****************************************************************/ + +typedef struct _MultiSinkRec { + ObjectPart object; + TextSinkPart text_sink; + MultiSinkPart multi_sink; +} MultiSinkRec; + + +/******************************************** + * + * Semi-private functions + * for use by other Xaw modules only + * + *******************************************/ + +extern void _XawMultiSinkPosToXY( +#if NeedFunctionPrototypes + Widget /* w */, + XawTextPosition /* pos */, + Position * /* x */, + Position * /*y */ +#endif +); + +#endif /* _XawMultiSinkP_h */ + diff --git a/src/MultiSrc.c b/src/MultiSrc.c new file mode 100644 index 0000000..05a6530 --- /dev/null +++ b/src/MultiSrc.c @@ -0,0 +1,1461 @@ +/* $XConsortium: MultiSrc.c,v 1.8 95/01/24 22:29:08 kaleb Exp $ */ + +/* + * Copyright 1991 by OMRON Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 OMRON not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OMRON makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OMRON 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. + * + * Authors: Chris Peterson MIT X Consortium + * Li Yuhong OMRON Corporation + * Frank Sheeran OMRON Corporation + * + * Much code taken from X11R3 String and Disk Sources. + */ + +/* + +Copyright (c) 1991, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +/* + * MultiSrc.c - MultiSrc object. (For use with the text widget). + * + */ + +#include "Xaw3dP.h" +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xfuncs.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/MultiSrcP.h> +#include <X11/Xaw3d/XawImP.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xmu/CharSet.h> +#include "XawI18n.h" +#include <X11/Xos.h> +#include <stdio.h> +#include <ctype.h> +#include <errno.h> + +/**************************************************************** + * + * Full class record constant + * + ****************************************************************/ + +/* Private Data */ + +static int magic_value = MAGIC_VALUE; + +#define offset(field) XtOffsetOf(MultiSrcRec, multi_src.field) + +static XtResource resources[] = { + {XtNstring, XtCString, XtRString, sizeof (XtPointer), + offset(string), XtRPointer, NULL}, + {XtNtype, XtCType, XtRMultiType, sizeof (XawAsciiType), + offset(type), XtRImmediate, (XtPointer)XawAsciiString}, + /* not used. */ + {XtNdataCompression, XtCDataCompression, XtRBoolean, sizeof (Boolean), + offset(data_compression), XtRImmediate, (XtPointer) FALSE}, + {XtNpieceSize, XtCPieceSize, XtRInt, sizeof (XawTextPosition), + offset(piece_size), XtRImmediate, (XtPointer) BUFSIZ}, + {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), + offset(callback), XtRCallback, (XtPointer)NULL}, + {XtNuseStringInPlace, XtCUseStringInPlace, XtRBoolean, sizeof (Boolean), + offset(use_string_in_place), XtRImmediate, (XtPointer) FALSE}, + {XtNlength, XtCLength, XtRInt, sizeof (int), + offset(multi_length), XtRInt, (XtPointer) &magic_value}, + +}; +#undef offset + +static XawTextPosition Scan(), Search(), ReadText(); +static int ReplaceText(); +static MultiPiece * FindPiece(), * AllocNewPiece(); +static FILE * InitStringOrFile(); +static void FreeAllPieces(), RemovePiece(), BreakPiece(), LoadPieces(); +static void RemoveOldStringOrFile(), CvtStringToMultiType(); +static void ClassInitialize(), Initialize(), Destroy(), GetValuesHook(); +static String StorePiecesInString(); +static Boolean SetValues(), WriteToFile(); + +#define MyWStrncpy( t,s,wcnt ) (void) memmove( (t), (s), (wcnt)*sizeof(wchar_t)) + +#ifndef MyWStrncpy +static void (MyWStrncpy)(); +#endif + +extern char *tmpnam(); +#ifdef X_NOT_STDC_ENV +extern int errno; +#endif + +#ifdef X_NOT_POSIX +#define Off_t long +#define Size_t unsigned int +#else +#define Off_t off_t +#define Size_t size_t +#endif + +extern wchar_t* _XawTextMBToWC(); +extern char *_XawTextWCToMB(); + +#define superclass (&textSrcClassRec) +MultiSrcClassRec multiSrcClassRec = { + { /* object_class fields */ + /* superclass */ (WidgetClass) superclass, + /* class_name */ "MultiSrc", + /* widget_size */ sizeof(MultiSrcRec), + /* class_initialize */ ClassInitialize, + /* class_part_initialize */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* pad */ NULL, + /* pad */ NULL, + /* pad */ 0, + /* resources */ resources, + /* num_resources */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* pad */ FALSE, + /* pad */ FALSE, + /* pad */ FALSE, + /* pad */ FALSE, + /* destroy */ Destroy, + /* pad */ NULL, + /* pad */ NULL, + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* pad */ NULL, + /* get_values_hook */ GetValuesHook, + /* pad */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* pad */ NULL, + /* pad */ NULL, + /* pad */ NULL, + /* extension */ NULL + }, + { /* textSrc_class fields */ + /* Read */ ReadText, + /* Replace */ ReplaceText, + /* Scan */ Scan, + /* Search */ Search, + /* SetSelection */ XtInheritSetSelection, + /* ConvertSelection */ XtInheritConvertSelection + }, + { /* multiSrc_class fields */ + /* Keep the compiler happy */ '\0' + } +}; + +WidgetClass multiSrcObjectClass = (WidgetClass)&multiSrcClassRec; + +/************************************************************ + * + * Semi-Public Interfaces. + * + ************************************************************/ + +/* Function Name: ClassInitialize + * Description: Class Initialize routine, called only once. + * Arguments: none. + * Returns: none. + */ + +static void +ClassInitialize() +{ + XawInitializeWidgetSet(); + XtAddConverter( XtRString, XtRMultiType, CvtStringToMultiType, + NULL, (Cardinal) 0); +} + +/* Function Name: Initialize + * Description: Initializes the simple menu widget + * Arguments: request - the widget requested by the argument list. + * new - the new widget with both resource and non + * resource values. + * Returns: none. + */ + +/* ARGSUSED */ +static void +Initialize(request, new, args, num_args) + Widget request, new; + ArgList args; + Cardinal* num_args; +{ + MultiSrcObject src = (MultiSrcObject) new; + FILE * file; + +/* + * Set correct flags (override resources) depending upon widget class. + */ + + src->multi_src.changes = FALSE; + src->multi_src.allocated_string = FALSE; + + file = InitStringOrFile(src, src->multi_src.type == XawAsciiFile); + LoadPieces(src, file, NULL); + + if (file != NULL) fclose(file); + src->text_src.text_format = XawFmtWide; + +} + +/* Function Name: ReadText + * Description: This function reads the source. + * Arguments: w - the MultiSource widget. + * pos - position of the text to retreive. + * RETURNED text - text block that will contain returned text. + * length - maximum number of characters to read. + * Returns: The number of characters read into the buffer. + */ + +static XawTextPosition +ReadText(w, pos, text, length) + Widget w; + XawTextPosition pos; + XawTextBlock* text; + int length; +{ + MultiSrcObject src = (MultiSrcObject) w; + XawTextPosition count, start; + MultiPiece * piece = FindPiece(src, pos, &start); + + text->format = XawFmtWide; + text->firstPos = pos; + text->ptr = (char *)(piece->text + (pos - start)); + count = piece->used - (pos - start); + text->length = (length > count) ? count : length; + return(pos + text->length); +} + +/* Function Name: ReplaceText. + * Description: Replaces a block of text with new text. + * Arguments: w - the MultiSource widget. + * startPos, endPos - ends of text that will be removed. + * text - new text to be inserted into buffer at startPos. + * Returns: XawEditError or XawEditDone. + */ + +/*ARGSUSED*/ +static int +ReplaceText( w, startPos, endPos, u_text_p) + Widget w; + XawTextPosition startPos, endPos; + XawTextBlock* u_text_p; +{ + MultiSrcObject src = (MultiSrcObject) w; + MultiPiece *start_piece, *end_piece, *temp_piece; + XawTextPosition start_first, end_first; + int length, firstPos; + wchar_t *wptr; + Boolean local_artificial_block = False; + XawTextBlock text; + + /* STEP 1: The user handed me a text block called `u_text' that may be + * in either FMTWIDE or FMT8BIT (ie MB.) Later code needs the block + * `text' to hold FMTWIDE. So, this copies `u_text' to `text', and if + * `u_text' was MB, I knock it up to WIDE. */ + + if ( u_text_p->length == 0 ) /* if so, the block contents never ref'd. */ + text.length = 0; + + else if ( u_text_p->format == XawFmtWide) { + local_artificial_block = False; /* ie, don't have to free it ourselves*/ + text.firstPos = u_text_p->firstPos; + text.length = u_text_p->length; + text.ptr = u_text_p->ptr; + /* text.format is unneeded */ + + } else { + /* WARNING! u_text->firstPos and length are in units of CHAR, not CHARACTERS! */ + + local_artificial_block = True; /* ie, have to free it ourselves */ + text.firstPos = 0; + text.length = u_text_p->length; /* _XawTextMBToWC converts this to wchar len. */ + + text.ptr = (char*)_XawTextMBToWC( XtDisplay(XtParent(w)), + &(u_text_p->ptr[u_text_p->firstPos]), &(text.length) ); + + /* I assert the following assignment is not needed - since Step 4 + depends on length, it has no need of a terminating NULL. I think + the ASCII-version has the same needless NULL. */ + /*((wchar_t*)text.ptr)[ text.length ] = NULL;*/ + } + + + /* STEP 2: some initialization... */ + + if (src->text_src.edit_mode == XawtextRead) + return(XawEditError); + + start_piece = FindPiece(src, startPos, &start_first); + end_piece = FindPiece(src, endPos, &end_first); + + + /* STEP 3: remove the empty pieces... */ + + if (start_piece != end_piece) { + temp_piece = start_piece->next; + + /* If empty and not the only piece then remove it. */ + + if ( ((start_piece->used = startPos - start_first) == 0) && + !((start_piece->next == NULL) && (start_piece->prev == NULL)) ) + RemovePiece(src, start_piece); + + while (temp_piece != end_piece) { + temp_piece = temp_piece->next; + RemovePiece(src, temp_piece->prev); + } + end_piece->used -= endPos - end_first; + if (end_piece->used != 0) + MyWStrncpy(end_piece->text, (end_piece->text + endPos - end_first), + (int) end_piece->used); + } + else { /* We are fully in one piece. */ + if ( (start_piece->used -= endPos - startPos) == 0) { + if ( !((start_piece->next == NULL) && (start_piece->prev == NULL)) ) + RemovePiece(src, start_piece); + } + else { + MyWStrncpy(start_piece->text + (startPos - start_first), + start_piece->text + (endPos - start_first), + (int) (start_piece->used - (startPos - start_first)) ); + if ( src->multi_src.use_string_in_place && + ((src->multi_src.length - (endPos - startPos)) < + (src->multi_src.piece_size - 1)) ) + start_piece->text[src->multi_src.length - (endPos - startPos)] = (wchar_t)0; + } + } + + src->multi_src.length += text.length -(endPos - startPos); + /*((TextWidget)src->object.parent)->text.lastPos = src->multi_src.length;*/ + + + + /* STEP 4: insert the new stuff */ + + if ( text.length != 0) { + + start_piece = FindPiece(src, startPos, &start_first); + + length = text.length; + firstPos = text.firstPos; + + while (length > 0) { + wchar_t* ptr; + int fill; + + if (src->multi_src.use_string_in_place) { + if (start_piece->used == (src->multi_src.piece_size - 1)) { + /* + * The string is used in place, then the string + * is not allowed to grow. + */ + start_piece->used = src->multi_src.length = + src->multi_src.piece_size - 1; + /*((TextWidget)src->object.parent)->text.lastPos = src->multi_src.length;*/ + + + start_piece->text[src->multi_src.length] = (wchar_t)0; + return(XawEditError); + } + } + + + if (start_piece->used == src->multi_src.piece_size) { + BreakPiece(src, start_piece); + start_piece = FindPiece(src, startPos, &start_first); + } + + fill = Min((int)(src->multi_src.piece_size - start_piece->used), length); + + ptr = start_piece->text + (startPos - start_first); + MyWStrncpy(ptr + fill, ptr, + (int) start_piece->used - (startPos - start_first)); + wptr =(wchar_t *)text.ptr; + (void)wcsncpy(ptr, wptr + firstPos, fill); + + startPos += fill; + firstPos += fill; + start_piece->used += fill; + length -= fill; + } + } + + if ( local_artificial_block == True ) + + /* In other words, text is not the u_text that the user handed me but + one I made myself. I only care, because I need to free the string. */ + + XFree( text.ptr ); + + if (src->multi_src.use_string_in_place) + start_piece->text[start_piece->used] = (wchar_t)0; + + src->multi_src.changes = TRUE; + + XtCallCallbacks(w, XtNcallback, NULL); + + return(XawEditDone); +} + +/* Function Name: Scan + * Description: Scans the text source for the number and type + * of item specified. + * Arguments: w - the MultiSource widget. + * position - the position to start scanning. + * type - type of thing to scan for. + * dir - direction to scan. + * count - which occurance if this thing to search for. + * include - whether or not to include the character found in + * the position that is returned. + * Returns: the position of the item found. + * + * Note: While there are only 'n' characters in the file there are n+1 + * possible cursor positions (one before the first character and + * one after the last character. + */ + +static +XawTextPosition +Scan( w, position, type, dir, count, include ) + Widget w; + XawTextPosition position; + XawTextScanType type; + XawTextScanDirection dir; + int count; + Boolean include; +{ + MultiSrcObject src = (MultiSrcObject) w; + int inc; + MultiPiece * piece; + XawTextPosition first, first_eol_position = 0; + wchar_t * ptr; + + if (type == XawstAll) { /* Optimize this common case. */ + if (dir == XawsdRight) + return(src->multi_src.length); + return(0); /* else. */ + } + + + /* STEP 1: basic sanity checks */ + + if (position > src->multi_src.length) + position = src->multi_src.length; + + + if ( dir == XawsdRight ) { + if (position == src->multi_src.length) + return(src->multi_src.length); + inc = 1; + } + else { + if (position == 0) + return(0); + inc = -1; + position--; + } + + piece = FindPiece(src, position, &first); + + if ( piece->used == 0 ) return(0); /* i.e., buffer is empty. */ + + ptr = (position - first) + piece->text; + + switch (type) { + case XawstEOL: + case XawstParagraph: + case XawstWhiteSpace: + for ( ; count > 0 ; count-- ) { + Boolean non_space = FALSE, first_eol = TRUE; + /* CONSTCOND */ + while (TRUE) { + wchar_t c = *ptr; + + ptr += inc; + position += inc; + + if (type == XawstWhiteSpace) { + if (iswspace(c)) { + if (non_space) + break; + } + else + non_space = TRUE; + } + else if (type == XawstEOL) { + if (c == _Xaw_atowc(XawLF)) break; + } + else { /* XawstParagraph */ + if (first_eol) { + if (c == _Xaw_atowc(XawLF)) { + first_eol_position = position; + first_eol = FALSE; + } + } + else + if ( c == _Xaw_atowc(XawLF)) + break; + else if ( !iswspace(c) ) + first_eol = TRUE; + } + + + if ( ptr < piece->text ) { + piece = piece->prev; + if (piece == NULL) /* Begining of text. */ + return(0); + ptr = piece->text + piece->used - 1; + } + else if ( ptr >= (piece->text + piece->used) ) { + piece = piece->next; + if (piece == NULL) /* End of text. */ + return(src->multi_src.length); + ptr = piece->text; + } + } + } + if (!include) { + if ( type == XawstParagraph) + position = first_eol_position; + position -= inc; + } + break; + case XawstPositions: + position += count * inc; + break; + case XawstAll: /* handled in special code above */ + default: + break; + } + + if ( dir == XawsdLeft ) + position++; + + if (position >= src->multi_src.length) + return(src->multi_src.length); + if (position < 0) + return(0); + + return(position); +} + +/* Function Name: Search + * Description: Searchs the text source for the text block passed + * Arguments: w - the MultiSource Widget. + * position - the position to start scanning. + * dir - direction to scan. + * text - the text block to search for. + * Returns: the position of the item found. + */ + +static XawTextPosition +Search(w, position, dir, text ) + Widget w; + XawTextPosition position; + XawTextScanDirection dir; + XawTextBlock* text; +{ + MultiSrcObject src = (MultiSrcObject) w; + int inc, count = 0; + wchar_t * ptr; + wchar_t* wtarget; + int wtarget_len; + Display * d = XtDisplay(XtParent(w)); + MultiPiece * piece; + wchar_t* buf; + XawTextPosition first; + + + /* STEP 1: First, a brief sanity check. */ + + if ( dir == XawsdRight ) + inc = 1; + else { + inc = -1; + if (position == 0) + return(XawTextSearchError); /* scanning left from 0??? */ + position--; + } + + + /* STEP 2: Ensure I have a local wide string.. */ + + /* Since this widget stores 32bit chars, I check here to see if + I'm being passed a string claiming to be 8bit chars (ie, MB text.) + If that is the case, naturally I convert to 32bit format. */ + + /*if the block was FMT8BIT, length will convert to REAL wchar count below */ + wtarget_len = text->length; + + if ( text->format == XawFmtWide ) + wtarget = &( ((wchar_t*)text->ptr) [text->firstPos] ); + else + { + /* The following converts wtarget_len from byte len to wchar count */ + wtarget = _XawTextMBToWC( d, &text->ptr[ text->firstPos ], &wtarget_len ); + } + + /* OK, I can now assert that wtarget holds wide characters, wtarget_len + holds an accurate count of those characters, and that firstPos has been + effectively factored out of the following computations. */ + + + /* STEP 3: SEARCH! */ + + buf = (wchar_t *)XtMalloc((unsigned)sizeof(wchar_t) * wtarget_len ); + (void)wcsncpy(buf, wtarget, wtarget_len ); + piece = FindPiece(src, position, &first); + ptr = (position - first) + piece->text; + + /* CONSTCOND */ + while (TRUE) { + if (*ptr == ((dir == XawsdRight) ? *(buf + count) + : *(buf + wtarget_len - count - 1)) ) { + if (count == (text->length - 1)) + break; + else + count++; + } + else { + if (count != 0) { + position -=inc * count; + ptr -= inc * count; + } + count = 0; + } + + ptr += inc; + position += inc; + + while ( ptr < piece->text ) { + piece = piece->prev; + if (piece == NULL) { /* Begining of text. */ + XtFree((char *)buf); + return(XawTextSearchError); + } + ptr = piece->text + piece->used - 1; + } + + while ( ptr >= (piece->text + piece->used) ) { + piece = piece->next; + if (piece == NULL) { /* End of text. */ + XtFree((char *)buf); + return(XawTextSearchError); + } + ptr = piece->text; + } + } + + XtFree( (char *) buf ); + if (dir == XawsdLeft) + return( position ); + return( position - ( wtarget_len - 1 ) ); +} + +/* Function Name: SetValues + * Description: Sets the values for the MultiSource. + * Arguments: current - current state of the widget. + * request - what was requested. + * new - what the widget will become. + * Returns: True if redisplay is needed. + */ + +/* ARGSUSED */ +static Boolean +SetValues(current, request, new, args, num_args) + Widget current, request, new; + ArgList args; + Cardinal* num_args; +{ + MultiSrcObject src = (MultiSrcObject) new; + MultiSrcObject old_src = (MultiSrcObject) current; + XtAppContext app_con = XtWidgetToApplicationContext(new); + Boolean total_reset = FALSE, string_set = FALSE; + FILE * file; + int i; + + if ( old_src->multi_src.use_string_in_place != + src->multi_src.use_string_in_place ) { + XtAppWarning( app_con, + "MultiSrc: The XtNuseStringInPlace resources may not be changed."); + src->multi_src.use_string_in_place = + old_src->multi_src.use_string_in_place; + } + + for (i = 0; i < *num_args ; i++ ) + if (streq(args[i].name, XtNstring)) { + string_set = TRUE; + break; + } + + if ( string_set || (old_src->multi_src.type != src->multi_src.type) ) { + RemoveOldStringOrFile(old_src, string_set); + file = InitStringOrFile(src, string_set); + + /* Load pieces does this logic for us, but it shouldn't. Its messy.*/ + /*if (old_src->multi_src.type == XawAsciiString) + LoadPieces(src, NULL, src->multi_src.string); + else*/ + LoadPieces(src, file, NULL); + if (file != NULL) fclose(file); + XawTextSetSource( XtParent(new), new, 0); /* Tell text widget + what happened. */ + total_reset = TRUE; + } + + if ( old_src->multi_src.multi_length != src->multi_src.multi_length ) + src->multi_src.piece_size = src->multi_src.multi_length; + + if ( !total_reset && (old_src->multi_src.piece_size + != src->multi_src.piece_size) ) { + String mb_string = StorePiecesInString( old_src ); + + if ( mb_string != 0 ) { + FreeAllPieces( old_src ); + LoadPieces( src, NULL, mb_string ); + XtFree( mb_string ); + } else { + /* If the buffer holds bad chars, don't touch it... */ + XtAppWarningMsg( app_con, + "convertError", "multiSource", "XawError", + XtName( XtParent( (Widget) old_src ) ), NULL, NULL ); + XtAppWarningMsg( app_con, + "convertError", "multiSource", "XawError", + "Non-character code(s) in buffer.", NULL, NULL ); + } + } + + return(FALSE); +} + +/* Function Name: GetValuesHook + * Description: This is a get values hook routine that sets the + * values specific to the multi source. + * Arguments: w - the MultiSource Widget. + * args - the argument list. + * num_args - the number of args. + * Returns: none. + */ + +static void +GetValuesHook(w, args, num_args) + Widget w; + ArgList args; + Cardinal* num_args; +{ + MultiSrcObject src = (MultiSrcObject) w; + int i; + + if (src->multi_src.type == XawAsciiString) { + for (i = 0; i < *num_args ; i++ ) + if (streq(args[i].name, XtNstring)) { + if (src->multi_src.use_string_in_place) { + *((char **) args[i].value) = (char *) + src->multi_src.first_piece->text; + } + else { + if (_XawMultiSave(w)) /* If save sucessful. */ + *((char **) args[i].value) = src->multi_src.string; + } + break; + } + } +} + +/* Function Name: Destroy + * Description: Destroys an multi source (frees all data) + * Arguments: src - the Multi source Widget to free. + * Returns: none. + */ + +static void +Destroy (w) + Widget w; +{ + RemoveOldStringOrFile((MultiSrcObject) w, True); +} + +/************************************************************ + * + * Public routines + * + ************************************************************/ + +/* Function Name: XawMultiSourceFreeString + * Description: Frees the string returned by a get values call + * on the string when the source is of type string. + * Arguments: w - the MultiSrc widget. + * Returns: none. + * + * The public interface is XawAsciiSourceFreeString! + */ + +void +#if NeedFunctionPrototypes +_XawMultiSourceFreeString( + Widget w) +#else +_XawMultiSourceFreeString(w) + Widget w; +#endif +{ + MultiSrcObject src = (MultiSrcObject) w; + +/*if (src->multi_src.allocated_string&& src->multi_src.type != XawAsciiFile) {*/ + /* ASSERT: src->multi_src.allocated_string -> we MUST free .string! */ + if ( src->multi_src.allocated_string ) { + XtFree(src->multi_src.string); + src->multi_src.allocated_string = FALSE; + src->multi_src.string = NULL; + } +} + +/* Function Name: _XawMultiSave + * Description: Saves all the pieces into a file or string as required. + * Arguments: w - the multiSrc Widget. + * Returns: TRUE if the save was successful. + * + * The public interface is XawAsciiSave(w)! + */ + +Boolean +#if NeedFunctionPrototypes +_XawMultiSave( + Widget w) +#else +_XawMultiSave(w) + Widget w; +#endif +{ + MultiSrcObject src = (MultiSrcObject) w; + XtAppContext app_con = XtWidgetToApplicationContext(w); + char * mb_string; + +/* + * If using the string in place then there is no need to play games + * to get the internal info into a readable string. + */ + + if (src->multi_src.use_string_in_place) + return(TRUE); + + if (src->multi_src.type == XawAsciiFile) { + + if (!src->multi_src.changes) /* No changes to save. */ + return(TRUE); + + mb_string = StorePiecesInString( src ); + + if ( mb_string != 0 ) { + if ( WriteToFile( mb_string, src->multi_src.string ) == FALSE ) { + XtFree( mb_string ); + return( FALSE ); + } + XtFree( mb_string ); + src->multi_src.changes = FALSE; + return( TRUE ); + } else { + /* If the buffer holds bad chars, don't touch it... */ + XtAppWarningMsg( app_con, + "convertError", "multiSource", "XawError", + "Due to illegal characters, file not saved.", NULL, NULL); + return( FALSE ); + } + } + else { + + /* THIS FUNCTIONALITY IS UNDOCUMENTED, probably UNNEEDED? The manual + says this routine's only function is to save files to disk. -Sheeran */ + + mb_string = StorePiecesInString( src ); + + if ( mb_string == 0 ) { + /* If the buffer holds bad chars, don't touch it... */ + XtAppWarningMsg( app_con, + "convertError", "multiSource", "XawError", + XtName( XtParent( (Widget) src ) ), NULL, NULL); + return( FALSE ); + } + + /* assert: mb_string holds good characters so the buffer is fine */ + if (src->multi_src.allocated_string == TRUE) + XtFree(src->multi_src.string); + else + src->multi_src.allocated_string = TRUE; + + src->multi_src.string = mb_string; + } + src->multi_src.changes = FALSE; + return(TRUE); +} + +/* Function Name: XawMultiSaveAsFile + * Description: Save the current buffer as a file. + * Arguments: w - the MultiSrc widget. + * name - name of the file to save this file into. + * Returns: True if the save was sucessful. + * + * The public interface is XawAsciiSaveAsFile! + */ + +Boolean +#if NeedFunctionPrototypes +_XawMultiSaveAsFile( + Widget w, + _Xconst char* name) +#else +_XawMultiSaveAsFile(w, name) + Widget w; + String name; +#endif +{ + MultiSrcObject src = (MultiSrcObject) w; + String mb_string; + Boolean ret; + + mb_string = StorePiecesInString( src ); + + if ( mb_string != 0 ) { + ret = WriteToFile( mb_string, name ); + XtFree( mb_string ); + return( ret ); + } + + /* otherwise there was a conversion error. So print widget name too. */ + XtAppWarningMsg( XtWidgetToApplicationContext(w), + "convertError", "multiSource", "XawError", + XtName( XtParent( (Widget) src ) ), NULL, NULL); + return( False ); +} + +/************************************************************ + * + * Private Functions. + * + ************************************************************/ + +static void +RemoveOldStringOrFile(src, checkString) + MultiSrcObject src; + Boolean checkString; +{ + FreeAllPieces(src); + + if (checkString && src->multi_src.allocated_string) { + XtFree(src->multi_src.string); + src->multi_src.allocated_string = False; + src->multi_src.string = NULL; + } +} + +/* Function Name: WriteToFile + * Description: Write the string specified to the begining of the file + * specified. + * Arguments: string - string to write. + * name - the name of the file + * Returns: returns TRUE if sucessful, FALSE otherwise. + */ + +static Boolean +WriteToFile(string, name) + String string, name; +{ + int fd; + + if ( ((fd = creat(name, 0666)) == -1 ) || + (write(fd, string, sizeof(unsigned char) * strlen(string)) == -1) ) + return(FALSE); + + if ( close(fd) == -1 ) + return(FALSE); + + return(TRUE); +} + + +/* Function Name: StorePiecesInString + * Description: store the pieces in memory into a char string. + * Arguments: src - the multiSrc to gather data from + * Returns: char *mb_string. Caller must free. + * or 0: conversion error. Caller must panic! + */ + +static String +StorePiecesInString(src) + MultiSrcObject src; +{ + wchar_t* wc_string; + char *mb_string; + int char_count = src->multi_src.length; + XawTextPosition first; + MultiPiece * piece; + + /* I believe the char_count + 1 and the NULL termination are unneeded! FS*/ + + wc_string = (wchar_t*) XtMalloc((unsigned)(char_count + 1) * sizeof(wchar_t)); + + for (first = 0, piece = src->multi_src.first_piece ; piece != NULL; + first += piece->used, piece = piece->next) + (void) wcsncpy( wc_string + first, piece->text, piece->used ); + + wc_string[ char_count ] = (wchar_t)0; /* NULL terminate this sucker. */ + + + /* This will refill all pieces to capacity. */ + + if ( src->multi_src.data_compression ) { + FreeAllPieces( src ); + LoadPieces( src, NULL, (char *)wc_string ); + } + + /* Lastly, convert it to a MB format and send it back. */ + + mb_string = _XawTextWCToMB( XtDisplayOfObject( (Widget)src ), + wc_string, &char_count ); + + /* NOTE THAT mb_string MAY BE ZERO IF THE CONVERSION FAILED. */ + XtFree( (char*) wc_string ); + return( mb_string ); +} + + +/* Function Name: InitStringOrFile. + * Description: Initializes the string or file. + * Arguments: src - the MultiSource. + * Returns: none - May exit though. + */ + +static FILE * +InitStringOrFile(src, newString) + MultiSrcObject src; + Boolean newString; +{ + char * open_mode = NULL; + FILE * file; + char fileName[TMPSIZ]; + Display *d = XtDisplayOfObject((Widget)src); + + if (src->multi_src.type == XawAsciiString) { + + if (src->multi_src.string == NULL) + src->multi_src.length = 0; + + else if (! src->multi_src.use_string_in_place) { + int length; + String temp = XtNewString(src->multi_src.string); + if ( src->multi_src.allocated_string ) + XtFree( src->multi_src.string ); + src->multi_src.allocated_string = True; + src->multi_src.string = temp; + + length = strlen(src->multi_src.string); + + /* Wasteful, throwing away the WC string, but need side effect! */ + (void) _XawTextMBToWC(d, src->multi_src.string, &length); + src->multi_src.length = (XawTextPosition) length; + } else { + src->multi_src.length = strlen(src->multi_src.string); + /* In case the length resource is incorrectly set */ + if (src->multi_src.length > src->multi_src.multi_length) + src->multi_src.multi_length = src->multi_src.length; + + if (src->multi_src.multi_length == MAGIC_VALUE) + src->multi_src.piece_size = src->multi_src.length; + else + src->multi_src.piece_size = src->multi_src.multi_length + 1; + } + + /*((TextWidget)src->object.parent)->text.lastPos = src->multi_src.length;*/ + return(NULL); + } + +/* + * type is XawAsciiFile. + */ + + src->multi_src.is_tempfile = FALSE; + + switch (src->text_src.edit_mode) { + case XawtextRead: + if (src->multi_src.string == NULL) + XtErrorMsg("NoFile", "multiSourceCreate", "XawError", + "Creating a read only disk widget and no file specified.", + NULL, 0); + open_mode = "r"; + break; + case XawtextAppend: + case XawtextEdit: + if (src->multi_src.string == NULL) { + + if ( src->multi_src.allocated_string ) + XtFree( src->multi_src.string ); + src->multi_src.allocated_string = False; + src->multi_src.string = fileName; + + (void) tmpnam(src->multi_src.string); + src->multi_src.is_tempfile = TRUE; + open_mode = "w"; + } else + open_mode = "r+"; + break; + default: + XtErrorMsg("badMode", "multiSourceCreate", "XawError", + "Bad editMode for multi source; must be Read, Append or Edit.", + NULL, NULL); + } + + /* Allocate new memory for the temp filename, because it is held in + * a stack memory buffer. We must verify that all routines that set + * .string first check .allocated_string and free it - plumbing Sheeran. + */ + if (newString || src->multi_src.is_tempfile) { + if ( src->multi_src.allocated_string ) + src->multi_src.string = XtNewString(src->multi_src.string); + src->multi_src.allocated_string = TRUE; + } + + if (!src->multi_src.is_tempfile) { + if ((file = fopen(src->multi_src.string, open_mode)) != 0) { + (void) fseek(file, (Off_t)0, 2); + src->multi_src.length = ftell (file); + return file; + } else { + String params[2]; + Cardinal num_params = 2; + + params[0] = src->multi_src.string; + params[1] = strerror(errno); + XtAppWarningMsg(XtWidgetToApplicationContext((Widget)src), + "openError", "multiSourceCreate", "XawWarning", + "Cannot open file %s; %s", params, &num_params); + } + } + src->multi_src.length = 0; + return((FILE *)NULL); +#undef StrLen +} + +/* LoadPieces: This routine takes either the MB contents of open file `file' or the +MB contents of string or the MB contents of src->multi_src.string and places +them in Pieces in WC format. + +CAUTION: You must have src->multi_src.length set to file length bytes +when src->multi_src.type == XawAsciiFile. src->multi_src.length must be +the length of the parameter string if string is non-NULL. */ + +static void +LoadPieces(src, file, string) + MultiSrcObject src; + FILE* file; + char* string; +{ + Display *d = XtDisplayOfObject((Widget)src); + wchar_t* local_str, *ptr; + MultiPiece* piece = NULL; + XawTextPosition left; + int bytes = sizeof(wchar_t); + char* temp_mb_holder = NULL; + + /* + * This is tricky - the _XawTextMBtoWC converter uses its 3rd arg + * in as MB length, out as WC length. We want local_length to be + * WC count. + */ + int local_length = src->multi_src.length; + + if (string != NULL) { + /* + * ASSERT: IF our caller passed a non-null string, THEN + * src->multi_src.length is currently string's * byte count, + * AND string is in a MB format. + */ + local_str = _XawTextMBToWC(d, (char *)string, &local_length); + src->multi_src.length = (XawTextPosition) local_length; + } else if (src->multi_src.type != XawAsciiFile) { + /* + * here, we are not changing the contents, just reloading, + * so don't change len... + */ + local_length = src->multi_src.string ? + strlen( src->multi_src.string ) : 0; + local_str = _XawTextMBToWC( d, (char*)src->multi_src.string, &local_length ); + } else { + if (src->multi_src.length != 0) { + temp_mb_holder = + XtMalloc((unsigned)(src->multi_src.length + 1) * sizeof(unsigned char)); + fseek(file, (Off_t)0, 0); + src->multi_src.length = fread (temp_mb_holder, + (Size_t)sizeof(unsigned char), + (Size_t)src->multi_src.length, file); + if (src->multi_src.length <= 0) + XtAppErrorMsg( XtWidgetToApplicationContext ((Widget) src), + "readError", "multiSource", "XawError", + "fread returned error.", NULL, NULL); + local_length = src->multi_src.length; + local_str = _XawTextMBToWC(d, temp_mb_holder, &local_length); + src->multi_src.length = local_length; + + if ( local_str == 0 ) { + String params[2]; + Cardinal num_params; + static char err_text[] = + "<<< FILE CONTENTS NOT REPRESENTABLE IN THIS LOCALE >>>"; + + params[0] = XtName(XtParent((Widget)src)); + params[1] = src->multi_src.string; + num_params = 2; + + XtAppWarningMsg( XtWidgetToApplicationContext((Widget)src), + "readLocaleError", "multiSource", "XawError", + "%s: The file `%s' contains characters not representable in this locale.", + params, &num_params); + src->multi_src.length = sizeof err_text; + local_length = src->multi_src.length; + local_str = _XawTextMBToWC(d, err_text, &local_length); + src->multi_src.length = local_length; + } + } else { /*ASSERT that since following while loop looks at local_length + this isn't needed. Sheeran, Omron KK, 1993/07/15 + temp_mb_holder[src->multi_src.length] = '\0';*/ + local_str = (wchar_t*)temp_mb_holder; + } + } + + if (src->multi_src.use_string_in_place) { + piece = AllocNewPiece(src, piece); + piece->used = Min(src->multi_src.length, src->multi_src.piece_size); + piece->text = (wchar_t*)src->multi_src.string; + return; + } + + ptr = local_str; + left = local_length; + + do { + piece = AllocNewPiece(src, piece); + + piece->text = (wchar_t*)XtMalloc(src->multi_src.piece_size * bytes); + piece->used = Min(left, src->multi_src.piece_size); + if (piece->used != 0) + (void) wcsncpy(piece->text, ptr, piece->used); + + left -= piece->used; + ptr += piece->used; + } while (left > 0); + + if ( temp_mb_holder ) + XtFree( (char*) temp_mb_holder ); +} + + +/* Function Name: AllocNewPiece + * Description: Allocates a new piece of memory. + * Arguments: src - The MultiSrc Widget. + * prev - the piece just before this one, or NULL. + * Returns: the allocated piece. + */ + +static MultiPiece * +AllocNewPiece(src, prev) + MultiSrcObject src; + MultiPiece * prev; +{ + MultiPiece * piece = XtNew(MultiPiece); + + if (prev == NULL) { + src->multi_src.first_piece = piece; + piece->next = NULL; + } + else { + if (prev->next != NULL) + (prev->next)->prev = piece; + piece->next = prev->next; + prev->next = piece; + } + + piece->prev = prev; + + return(piece); +} + +/* Function Name: FreeAllPieces + * Description: Frees all the pieces + * Arguments: src - The MultiSrc Widget. + * Returns: none. + */ + +static void +FreeAllPieces(src) + MultiSrcObject src; +{ + MultiPiece * next, * first = src->multi_src.first_piece; + + if (first->prev != NULL) + printf("Xaw MultiSrc Object: possible memory leak in FreeAllPieces().\n"); + + for ( ; first != NULL ; first = next ) { + next = first->next; + RemovePiece(src, first); + } +} + +/* Function Name: RemovePiece + * Description: Removes a piece from the list. + * Arguments: + * piece - the piece to remove. + * Returns: none. + */ + +static void +RemovePiece(src, piece) + MultiSrcObject src; + MultiPiece* piece; +{ + if (piece->prev == NULL) + src->multi_src.first_piece = piece->next; + else + (piece->prev)->next = piece->next; + + if (piece->next != NULL) + (piece->next)->prev = piece->prev; + + if (!src->multi_src.use_string_in_place) + XtFree((char *)piece->text); + + XtFree((char *)piece); +} + +/* Function Name: FindPiece + * Description: Finds the piece containing the position indicated. + * Arguments: src - The MultiSrc Widget. + * position - the position that we are searching for. + * RETURNED first - the position of the first character in this piece. + * Returns: piece - the piece that contains this position. + */ + +static MultiPiece * +FindPiece(src, position, first) + MultiSrcObject src; + XawTextPosition position, *first; +{ + MultiPiece * old_piece = NULL, * piece = src->multi_src.first_piece; + XawTextPosition temp; + + for ( temp = 0 ; piece != NULL ; temp += piece->used, piece = piece->next ) { + *first = temp; + old_piece = piece; + + if ((temp + piece->used) > position) + return(piece); + } + return(old_piece); /* if we run off the end the return the last piece */ +} + +/* Function Name: BreakPiece + * Description: Breaks a full piece into two new pieces. + * Arguments: src - The MultiSrc Widget. + * piece - the piece to break. + * Returns: none. + */ + +#define HALF_PIECE (src->multi_src.piece_size/2) + +static void +BreakPiece(src, piece) + MultiSrcObject src; + MultiPiece* piece; +{ + MultiPiece * new = AllocNewPiece(src, piece); + + new->text = (wchar_t*)XtMalloc(src->multi_src.piece_size * sizeof(wchar_t)); + (void) wcsncpy(new->text, piece->text + HALF_PIECE, + src->multi_src.piece_size - HALF_PIECE); + piece->used = HALF_PIECE; + new->used = src->multi_src.piece_size - HALF_PIECE; +} + +/* Convert string "XawAsciiString" and "XawAsciiFile" to quarks. */ + +/* ARGSUSED */ +static void +CvtStringToMultiType(args, num_args, fromVal, toVal) + XrmValuePtr args; /* unused */ + Cardinal* num_args; /* unused */ + XrmValuePtr fromVal; + XrmValuePtr toVal; +{ + static XawAsciiType type; + static XrmQuark XtQEstring = NULLQUARK; + static XrmQuark XtQEfile; + XrmQuark q; + char lowerName[40]; + + if (XtQEstring == NULLQUARK) { + XtQEstring = XrmPermStringToQuark(XtEstring); + XtQEfile = XrmPermStringToQuark(XtEfile); + } + + if (strlen ((char*) fromVal->addr) < sizeof lowerName) { + XmuCopyISOLatin1Lowered(lowerName, (char *) fromVal->addr); + q = XrmStringToQuark(lowerName); + + if (q == XtQEstring) type = XawAsciiString; + else if (q == XtQEfile) type = XawAsciiFile; + else { + toVal->size = 0; + toVal->addr = NULL; + return; + } + toVal->size = sizeof type; + toVal->addr = (XPointer) &type; + return; + } + toVal->size = 0; + toVal->addr = NULL; +} diff --git a/src/MultiSrc.h b/src/MultiSrc.h new file mode 100644 index 0000000..be01857 --- /dev/null +++ b/src/MultiSrc.h @@ -0,0 +1,151 @@ +/* $XConsortium: MultiSrc.h,v 1.2 94/04/17 20:12:26 kaleb Exp $ */ + +/* + * Copyright 1991 by OMRON Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 OMRON not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OMRON makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OMRON 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: Li Yuhong OMRON Corporation + */ + +/* + +Copyright (c) 1989, 1991, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +/* + * This file was modified from AsciiSrc.h. + * + * By Li Yuhong, Sept. 18, 1990 + */ + +#ifndef _XawMultiSrc_h +#define _XawMultiSrc_h + +#include <X11/Xaw3d/TextSrc.h> +/*Xfuncproto.h included by Intrinsic.h*/ + +/* Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + callback Callback Callback (none) + dataCompression DataCompression Boolean True + length Length int (internal) + pieceSize PieceSize int BUFSIZ + string String String NULL + type Type XawAsciiType XawAsciiString + useStringInPlace UseStringInPlace Boolean False + +*/ + +/* Class record constants */ + +extern WidgetClass multiSrcObjectClass; + +typedef struct _MultiSrcClassRec *MultiSrcObjectClass; +typedef struct _MultiSrcRec *MultiSrcObject; + +/* + * Just to make people's lives a bit easier. + */ + +#define MultiSourceObjectClass MultiSrcObjectClass +#define MultiSourceObject MultiSrcObject + +/* + * Resource Definitions. + */ + +#define XtCDataCompression "DataCompression" +#define XtCPieceSize "PieceSize" +#define XtCType "Type" +#define XtCUseStringInPlace "UseStringInPlace" + +#define XtNdataCompression "dataCompression" +#define XtNpieceSize "pieceSize" +#define XtNtype "type" +#define XtNuseStringInPlace "useStringInPlace" + +#define XtRMultiType "MultiType" + +#define XtEstring "string" +#define XtEfile "file" + +/************************************************************ + * + * THESE ROUTINES ARE NOT PUBLIC: Source should call + * + * the AsciiSrc API which currently forwards requests here. + * + * future versions (like theres going to be an R7 Xaw!) may + * + * eliminate this file or at least these functions entirely. + * + ************************************************************/ + +_XFUNCPROTOBEGIN + + +extern void XawMultiSourceFreeString( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +extern Boolean _XawMultiSave( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +extern Boolean _XawMultiSaveAsFile( +#if NeedFunctionPrototypes + Widget /* w */, + _Xconst char* /* name */ +#endif +); + + +_XFUNCPROTOEND + +#endif /* _XawMultiSrc_h - Don't add anything after this line. */ + diff --git a/src/MultiSrcP.h b/src/MultiSrcP.h new file mode 100644 index 0000000..6996361 --- /dev/null +++ b/src/MultiSrcP.h @@ -0,0 +1,194 @@ +/* $XConsortium: MultiSrcP.h,v 1.2 94/04/17 20:12:27 kaleb Exp $ */ + +/* + * Copyright 1991 by OMRON Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 OMRON not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. OMRON make no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * OMRON DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OMRON 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: Li Yuhong OMRON Corporation + */ + + +/*********************************************************** + +Copyright (c) 1987, 1988, 1991, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * MultiSrcP.h - Private Header for Multi Text Source. + * + * This is the private header file for the Multi Text Source. + * It is intended to be used with the Text widget, the simplest way to use + * this text source is to use the MultiText Object. + * + * Date: June 29, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +/* + * TextSrcP.h - Private definitions for MultiSrc object + * + */ + +/* + * This file was changed from AsciiSrcP.h. + * + * By Li Yuhong, Sept. 18, 1990 + */ + +#ifndef _XawMultiSrcP_h +#define _XawMultiSrcP_h + +#include <X11/Xaw3d/TextSrcP.h> +#include <X11/Xaw3d/MultiSrc.h> + +/************************************************************ + * + * Private declarations. + * + ************************************************************/ + +#ifdef L_tmpnam +#define TMPSIZ L_tmpnam +#else +#define TMPSIZ 32 /* bytes to allocate for tmpnam */ +#endif + +#define MAGIC_VALUE ((XawTextPosition) -1) /* Magic value. */ + +#define streq(a, b) ( strcmp((a), (b)) == 0 ) + +typedef struct _MultiPiece { /* Piece of the text file of BUFSIZ allocated + characters. */ + wchar_t* text; /* The text in this buffer. */ + XawTextPosition used; /* The number of characters of this buffer + that have been used. */ + struct _MultiPiece *prev, *next; /* linked list pointers. */ +} MultiPiece; + +/************************************************************ + * + * New fields for the MultiSrc object class record. + * + ************************************************************/ + +typedef struct _MultiSrcClassPart { char foo; } MultiSrcClassPart; + +/* Full class record declaration */ +typedef struct _MultiSrcClassRec { + ObjectClassPart object_class; + TextSrcClassPart text_src_class; + MultiSrcClassPart multi_src_class; +} MultiSrcClassRec; + +extern MultiSrcClassRec multiSrcClassRec; + +/* New fields for the MultiSrc object record */ + +typedef struct _MultiSrcPart { + + /* Resources. */ + + XIC ic; /* for X Input Method. */ + XtPointer string; /* either the string, or the file name, depend- + ing upon the `type'. ALWAYS IN MB FORMAT. */ + XawAsciiType type; /* either string or disk. */ + XawTextPosition piece_size; /* Size of text buffer for each piece. */ + Boolean data_compression; /* compress to minimum memory automatically + on save? */ + XtCallbackList callback; /* A callback list to call when the source is + changed. */ + Boolean use_string_in_place; /* Use the string passed in place. */ + int multi_length; /* length field for multi string emulation. */ + +/* Private data. */ + + Boolean is_tempfile; /* Is this a temporary file? */ + Boolean changes; /* Has this file been edited? */ + Boolean allocated_string; /* Have I allocated the + string in multi_src->string? */ + XawTextPosition length; /* length of file - IN CHARACTERS, NOT BYTES. */ + MultiPiece * first_piece; /* first piece of the text. */ +} MultiSrcPart; + +/**************************************************************** + * + * Full instance record declaration + * + ****************************************************************/ + +typedef struct _MultiSrcRec { + ObjectPart object; + TextSrcPart text_src; + MultiSrcPart multi_src; +} MultiSrcRec; + +#if NeedFunctionPrototypes +extern void _XawMultiSourceFreeString( Widget ); +#else +extern void _XawMultiSourceFreeString(); +#endif + +#endif /* _XawMultiSrcP_h --- Don't add anything after this line. */ diff --git a/src/Paned.c b/src/Paned.c new file mode 100644 index 0000000..babd492 --- /dev/null +++ b/src/Paned.c @@ -0,0 +1,1947 @@ +/* $XConsortium: Paned.c,v 1.27 94/04/17 20:12:28 kaleb Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * Paned.c - Paned Composite Widget. + * + * Updated and significantly modified from the Athena VPaned Widget. + * + * Date: March 1, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#include "Xaw3dP.h" +#include <X11/IntrinsicP.h> +#include <X11/cursorfont.h> +#include <X11/StringDefs.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xmu/Converters.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/Grip.h> +#include <X11/Xaw3d/PanedP.h> +#include <ctype.h> + +/* I don't know why Paned.c calls _XawImCallVendorShellExtResize, but... */ +#ifdef XAW_INTERNATIONALIZATION +#include <X11/Xaw3d/XawImP.h> +#endif + +typedef enum {UpLeftPane = 'U', LowRightPane = 'L', + ThisBorderOnly = 'T', AnyPane = 'A' } Direction; + +#define NO_INDEX -100 +#define IS_GRIP NULL + +#define PaneInfo(w) ((Pane)(w)->core.constraints) +#define HasGrip(w) (PaneInfo(w)->grip != NULL) +#define IsPane(w) ((w)->core.widget_class != gripWidgetClass) +#define PaneIndex(w) (PaneInfo(w)->position) +#define IsVert(w) ( (w)->paned.orientation == XtorientVertical ) + +#define ForAllPanes(pw, childP) \ + for ( (childP) = (pw)->composite.children ; \ + (childP) < (pw)->composite.children + (pw)->paned.num_panes ; \ + (childP)++ ) + +#define ForAllChildren(pw, childP) \ + for ( (childP) = (pw)->composite.children ; \ + (childP) < (pw)->composite.children + (pw)->composite.num_children ; \ + (childP)++ ) + +/***************************************************************************** + * + * Full instance record declaration + * + ****************************************************************************/ + +static char defGripTranslations[] = + "<Btn1Down>: GripAction(Start, UpLeftPane) \n\ + <Btn2Down>: GripAction(Start, ThisBorderOnly) \n\ + <Btn3Down>: GripAction(Start, LowRightPane) \n\ + <Btn1Motion>: GripAction(Move, UpLeft) \n\ + <Btn2Motion>: GripAction(Move, ThisBorder) \n\ + <Btn3Motion>: GripAction(Move, LowRight) \n\ + Any<BtnUp>: GripAction(Commit)"; + +#define offset(field) XtOffsetOf(PanedRec, paned.field) + +static XtResource resources[] = { + {XtNinternalBorderColor, XtCBorderColor, XtRPixel, sizeof(Pixel), + offset(internal_bp), XtRString, + (XtPointer) XtDefaultForeground}, + {XtNinternalBorderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension), + offset(internal_bw), XtRImmediate, (XtPointer) 1}, + {XtNgripIndent, XtCGripIndent, XtRPosition, sizeof(Position), + offset(grip_indent), XtRImmediate, (XtPointer) 10}, + {XtNrefigureMode, XtCBoolean, XtRBoolean, sizeof(Boolean), + offset(refiguremode), XtRImmediate, (XtPointer) TRUE}, + {XtNgripTranslations, XtCTranslations, XtRTranslationTable, + sizeof(XtTranslations), + offset(grip_translations), XtRString, (XtPointer)defGripTranslations}, + {XtNorientation, XtCOrientation, XtROrientation, sizeof(XtOrientation), + offset(orientation), XtRImmediate, (XtPointer) XtorientVertical}, + + /* Cursors - both horiz and vertical have to work. */ + + {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor), + offset(cursor), XtRImmediate, None}, + {XtNgripCursor, XtCCursor, XtRCursor, sizeof(Cursor), + offset(grip_cursor), XtRImmediate, None}, + {XtNverticalGripCursor, XtCCursor, XtRCursor, sizeof(Cursor), + offset(v_grip_cursor), XtRString, "sb_v_double_arrow"}, + {XtNhorizontalGripCursor, XtCCursor, XtRCursor, sizeof(Cursor), + offset(h_grip_cursor), XtRString, "sb_h_double_arrow"}, + + {XtNbetweenCursor, XtCCursor, XtRCursor, sizeof(Cursor), + offset(adjust_this_cursor), XtRString, None}, + {XtNverticalBetweenCursor, XtCCursor, XtRCursor, sizeof(Cursor), + offset(v_adjust_this_cursor), XtRString, "sb_left_arrow"}, + {XtNhorizontalBetweenCursor, XtCCursor, XtRCursor, sizeof(Cursor), + offset(h_adjust_this_cursor), XtRString, "sb_up_arrow"}, + + {XtNupperCursor, XtCCursor, XtRCursor, sizeof(Cursor), + offset(adjust_upper_cursor), XtRString, "sb_up_arrow"}, + {XtNlowerCursor, XtCCursor, XtRCursor, sizeof(Cursor), + offset(adjust_lower_cursor), XtRString, "sb_down_arrow"}, + {XtNleftCursor, XtCCursor, XtRCursor, sizeof(Cursor), + offset(adjust_left_cursor), XtRString, "sb_left_arrow"}, + {XtNrightCursor, XtCCursor, XtRCursor, sizeof(Cursor), + offset(adjust_right_cursor), XtRString, "sb_right_arrow"}, +}; + +#undef offset + +#define offset(field) XtOffsetOf(PanedConstraintsRec, paned.field) + +static XtResource subresources[] = { + {XtNallowResize, XtCBoolean, XtRBoolean, sizeof(Boolean), + offset(allow_resize), XtRImmediate, (XtPointer) FALSE}, + {XtNposition, XtCPosition, XtRInt, sizeof(int), + offset(position), XtRImmediate, (XtPointer) 0}, + {XtNmin, XtCMin, XtRDimension, sizeof(Dimension), + offset(min), XtRImmediate, (XtPointer) PANED_GRIP_SIZE}, + {XtNmax, XtCMax, XtRDimension, sizeof(Dimension), + offset(max), XtRImmediate, (XtPointer) ~0}, + {XtNpreferredPaneSize, XtCPreferredPaneSize, XtRDimension, + sizeof(Dimension), offset(preferred_size), + XtRImmediate, (XtPointer) PANED_ASK_CHILD}, + {XtNresizeToPreferred, XtCBoolean, XtRBoolean, sizeof(Boolean), + offset(resize_to_pref), XtRImmediate, (XtPointer) FALSE}, + {XtNskipAdjust, XtCBoolean, XtRBoolean, sizeof(Boolean), + offset(skip_adjust), XtRImmediate, (XtPointer) FALSE}, + {XtNshowGrip, XtCShowGrip, XtRBoolean, sizeof(Boolean), + offset(show_grip), XtRImmediate, (XtPointer) TRUE}, +}; + +#undef offset + +static void ClassInitialize(), Initialize(); +static void Realize(), Resize(); +static void Redisplay(); +static void GetGCs(), ReleaseGCs(); +static void RefigureLocationsAndCommit(); +static Boolean SetValues(); +static XtGeometryResult GeometryManager(); +static void ChangeManaged(); +static void InsertChild(); +static void DeleteChild(); +static Boolean PaneSetValues(); +static Dimension PaneSize(), GetRequestInfo(); +static Boolean SatisfiesRule1(), SatisfiesRule2(), SatisfiesRule3(); + +static void PushPaneStack(); +static void GetPaneStack(); +static Boolean PopPaneStack(); +static void ClearPaneStack(); + +#define SuperClass ((ConstraintWidgetClass)&constraintClassRec) + +PanedClassRec panedClassRec = { + { +/* core class fields */ + /* superclass */ (WidgetClass) SuperClass, + /* class name */ "Paned", + /* size */ sizeof(PanedRec), + /* class_initialize */ ClassInitialize, + /* class_part init */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ Realize, + /* actions */ NULL, + /* num_actions */ 0, + /* resources */ resources, + /* resource_count */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ TRUE, + /* compress_exposure */ TRUE, + /* compress_enterleave*/ TRUE, + /* visible_interest */ FALSE, + /* destroy */ ReleaseGCs, + /* 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 */ XtInheritQueryGeometry, + /* display_accelerator*/ XtInheritDisplayAccelerator, + /* extension */ NULL + }, { +/* composite class fields */ + /* geometry_manager */ GeometryManager, + /* change_managed */ ChangeManaged, + /* insert_child */ InsertChild, + /* delete_child */ DeleteChild, + /* extension */ NULL + }, { +/* constraint class fields */ + /* subresources */ subresources, + /* subresource_count */ XtNumber(subresources), + /* constraint_size */ sizeof(PanedConstraintsRec), + /* initialize */ NULL, + /* destroy */ NULL, + /* set_values */ PaneSetValues, + /* extension */ NULL + } +}; + +WidgetClass panedWidgetClass = (WidgetClass) &panedClassRec; + +/* For compatibility. */ +WidgetClass vPanedWidgetClass = (WidgetClass) &panedClassRec; + +/*********************************************************** + * + * Private Functions. + * + ************************************************************/ + +/* Function Name: AdjustPanedSize + * Description: Adjusts the size of the pane. + * Arguments: pw - the paned widget to adjust. + * off_size - the new off_size to use. + * result_ret - result of query ** RETURNED ** + * on_size_ret - the new on_size ** RETURNED ** + * off_size_ret - the new off_size ** RETURNED ** + * Returns: the amount of change in size. + */ + +static void +AdjustPanedSize(pw, off_size, result_ret, on_size_ret, off_size_ret) +PanedWidget pw; +Dimension off_size; +XtGeometryResult * result_ret; +Dimension * on_size_ret, * off_size_ret; +{ + Dimension old_size = PaneSize( (Widget) pw, IsVert(pw)); + Dimension newsize = 0; + Widget * childP; + XtWidgetGeometry request, reply; + request.request_mode = CWWidth | CWHeight; + + ForAllPanes(pw, childP) { + int size = Max(PaneInfo(*childP)->size, (int)PaneInfo(*childP)->min); + AssignMin(size, (int) PaneInfo(*childP)->max); + newsize += size + pw->paned.internal_bw; + } + newsize -= pw->paned.internal_bw; + + if (newsize < 1) newsize = 1; + + if ( IsVert(pw) ) { + request.width = off_size; + request.height = newsize; + } + else { + request.width = newsize; + request.height = off_size; + } + + if (result_ret != NULL) { + request.request_mode |= XtCWQueryOnly; + + *result_ret = XtMakeGeometryRequest( (Widget) pw, &request, &reply ); +#ifdef XAW_INTERNATIONALIZATION + _XawImCallVendorShellExtResize( (Widget) pw ); +#endif + + if ( (newsize == old_size) || (*result_ret == XtGeometryNo) ) { + *on_size_ret = old_size; + *off_size_ret = off_size; + return; + } + if (*result_ret != XtGeometryAlmost) { + *on_size_ret = GetRequestInfo( &request, IsVert(pw) ); + *off_size_ret = GetRequestInfo( &request, !IsVert(pw) ); + return; + } + *on_size_ret = GetRequestInfo( &reply, IsVert(pw) ); + *off_size_ret = GetRequestInfo( &reply, !IsVert(pw) ); + return; + } + + if (newsize == old_size) return; + + if (XtMakeGeometryRequest( (Widget) pw, + &request, &reply) == XtGeometryAlmost) + XtMakeGeometryRequest( (Widget) pw, &reply, &request); +} + +/* Function Name: PaneSize + * Description: returns the width or height of the pane depending + * upon the orientation we are using. + * Arguments: w - and widget. + * vertical - TRUE if this is vertically oriented pane. + * Returns: the size requested + * + * vertical - return height + * !vertical - return width + */ + +static Dimension +PaneSize(w, vertical) +Widget w; +Boolean vertical; +{ + if (vertical) return (w->core.height); + return (w->core.width); +} + +/* Function Name: GetRequestInfo + * Description: returns request information. + * Arguments: geo_struct - a geometry struct to get information out of. + * vert - TRUE if this is a vertical paned widget. + * Returns: the request information. + */ + +static Dimension +GetRequestInfo(geo_struct, vert) +XtWidgetGeometry * geo_struct; +Boolean vert; +{ + if ( vert ) return ( (Dimension) geo_struct->height); + return ( (Dimension) geo_struct->width); +} + +/* Function Name: ChoosePaneToResize. + * Description: This function chooses a pane to resize. + * They are chosen using the following rules: + * + * 1) size < max && size > min + * 2) skip adjust == FALSE + * 3) widget not its prefered height && + * this change will bring it closer && + * The user has not resized this pane. + * + * If no widgets are found that fits all the rules then + * rule #3 is broken. + * If there are still no widgets found than + * rule #2 is broken. + * Rule #1 is never broken. + * If no widgets are found then NULL is returned. + * + * Arguments: pw - the paned widget. + * paneindex - the index of the current pane. + * dir - direction to search first. + * shrink - TRUE if we need to shrink a pane, FALSE otherwise. + * Returns: pane to resize or NULL. + */ + +static Pane +ChoosePaneToResize(pw, paneindex, dir, shrink) +PanedWidget pw; +int paneindex; +Direction dir; +Boolean shrink; +{ + Widget *childP; + int rules = 3; + Direction _dir = dir; + int _index = paneindex; + + if ( (paneindex == NO_INDEX) || (dir == AnyPane) ) { /* Use defaults. */ + _dir = LowRightPane; /* Go up. - really. */ + _index = pw->paned.num_panes - 1; /* Start the last pane, and work + backwards. */ + } + childP = pw->composite.children + _index; + + /* CONSTCOND */ + while(TRUE) { + Pane pane = PaneInfo(*childP); + + if ( (rules < 3 || SatisfiesRule3(pane, shrink)) && + (rules < 2 || SatisfiesRule2(pane)) && + (SatisfiesRule1(pane, shrink)) && + ((paneindex != PaneIndex(*childP)) || (dir == AnyPane)) ) + return(pane); + +/* + * This is counter-intuitive, but if we are resizing the pane + * above the grip we want to choose a pane below the grip to lose, + * and visa-versa. + */ + + if (_dir == LowRightPane) --childP; else ++childP; + +/* + * If we have come to and edge then reduce the rule set, and try again. + * If we are reduced the rules to none, then return NULL. + */ + + if ( (childP - pw->composite.children < 0) || + (childP - pw->composite.children >= pw->paned.num_panes) ) { + if (--rules < 1) /* less strict rules. */ + return(NULL); + childP = pw->composite.children + _index; + } + } +} + +/* Function Name: StatisfiesRule1 + * Description: check for to see if this pane satisfies rule 1. + * Arguments: pane - the pane to check. + * shrink -TRUE if we want to shrink this pane, FALSE otherwise + * Returns: TRUE if the rule is satisfied. + */ + +static Boolean +SatisfiesRule1(pane, shrink) +Pane pane; +Boolean shrink; +{ + return( (shrink && (pane->size != pane->min)) || + (!shrink && (pane->size != pane->max)) ); +} + +/* Function Name: StatisfiesRule2 + * Description: check for to see if this pane satisfies rule 2. + * Arguments: pane - the pane to check. + * Returns: TRUE if the rule is satisfied. + */ + +static Boolean +SatisfiesRule2(pane) +Pane pane; +{ + return(!pane->skip_adjust || pane->paned_adjusted_me); +} + +/* Function Name: StatisfiesRule3 + * Description: check for to see if this pane satisfies rule 3. + * Arguments: pane - the pane to check. + * shrink -TRUE if we want to shrink this pane, FALSE otherwise + * Returns: TRUE if the rule is satisfied. + */ + +static Boolean +SatisfiesRule3(pane, shrink) +Pane pane; +Boolean shrink; +{ + return ( pane->paned_adjusted_me && + ( (shrink && ((int)pane->wp_size <= pane->size)) || + (!shrink && ((int)pane->wp_size >= pane->size))) ); +} + +/* Function Name: LoopAndRefigureChildren. + * Description: if we are resizing either the UpleftPane or LowRight Pane + * loop through all the children to see if any will allow us + * to resize them. + * Arguments: pw - the paned widget. + * paneindex - the number of the pane border we are moving. + * dir - the pane to move (either UpLeftPane or LowRightPane). + * sizeused - current amount of space used. + * THIS VALUE IS USED AND RETURNED. + * Returns: none. + */ + +static void +LoopAndRefigureChildren(pw, paneindex, dir, sizeused) +PanedWidget pw; +int paneindex, *sizeused; +Direction dir; +{ + int pane_size = (int) PaneSize( (Widget) pw, IsVert(pw)); + Boolean shrink = (*sizeused > pane_size); + + if (dir == LowRightPane) paneindex++; + + while (*sizeused != pane_size) { /* While all panes do not fit properly. */ +/* + * Choose a pane to resize. + * First look on the Pane Stack, and then go hunting for another one. + * If we fail to find a pane to resize then give up. + */ + Pane pane; + int start_size; + Dimension old; + Boolean rule3_ok = FALSE, from_stack = TRUE; + + GetPaneStack(pw, shrink, &pane, &start_size); + if (pane == NULL) { + pane = ChoosePaneToResize(pw, paneindex, dir, shrink); + if (pane == NULL) + return; /* no one to resize, give up. */ + + rule3_ok = SatisfiesRule3(pane, shrink); + from_stack = FALSE; + PushPaneStack(pw, pane); + } + + +/* + * Try to resize this pane so that all panes will fit, take min and max + * into account. + */ + old = pane->size; + pane->size += pane_size - *sizeused; + + if (from_stack) { + if (shrink) { + AssignMax(pane->size, start_size); + } /* don't remove these braces. */ + else + AssignMin(pane->size, start_size); + + if (pane->size == start_size) (void) PopPaneStack(pw); + } + else if (rule3_ok) { + if (shrink) { + AssignMax(pane->size, (int) pane->wp_size); + } /* don't remove these braces. */ + else + AssignMin(pane->size, (int) pane->wp_size); + } + + pane->paned_adjusted_me = (pane->size != pane->wp_size); + AssignMax(pane->size, (int) pane->min); + AssignMin(pane->size, (int) pane->max); + *sizeused += (pane->size - old); + } +} + +/* Function Name: RefigureLocations + * Description: refigures all locations of children. + * Arguments: pw - the paned widget. + * paneindex - child to start refiguring at. + * dir - direction to move from child. + * Returns: none. + * + * There are special arguments to paneindex and dir, they are: + * paneindex - NO_INDEX. + * dir - AnyPane. + * + * If either of these is true then all panes may be resized and + * the choosing of panes procedes in reverse order starting with the + * last child. + */ + +static void +RefigureLocations(pw, paneindex, dir) +PanedWidget pw; +int paneindex; +Direction dir; +{ + Widget *childP; + int pane_size = (int) PaneSize( (Widget) pw, IsVert(pw) ); + int sizeused = 0; + Position loc = 0; + + if (pw->paned.num_panes == 0 || !pw->paned.refiguremode) return; + +/* + * Get an initial estimate of the size we will use. + */ + + ForAllPanes(pw, childP) { + Pane pane = PaneInfo(*childP); + AssignMax(pane->size, (int) pane->min); + AssignMin(pane->size, (int) pane->max); + sizeused += (int) pane->size + (int) pw->paned.internal_bw; + } + sizeused -= (int) pw->paned.internal_bw; + + if ( (dir != ThisBorderOnly) && (sizeused != pane_size) ) + LoopAndRefigureChildren(pw, paneindex, dir, &sizeused); + +/* + * If we still are not the right size, then tell the pane that + * wanted to resize that it can't. + */ + + + if ( (paneindex != NO_INDEX) && (dir != AnyPane) ) { + Pane pane = PaneInfo(*(pw->composite.children + paneindex)); + Dimension old = pane->size; + + pane->size += pane_size - sizeused; + AssignMax(pane->size, (int) pane->min); + AssignMin(pane->size, (int) pane->max); + sizeused += pane->size - old; + } + +/* + * It is possible that the panes will not fit inside the vpaned widget, but + * we have tried out best. + * + * Assign each pane a location. + */ + + ForAllPanes(pw, childP) { + PaneInfo(*childP)->delta = loc; + loc += PaneInfo(*childP)->size + pw->paned.internal_bw; + } +} + +/* Function Name: CommitNewLocations + * Description: Commits all of the previously figured locations. + * Arguments: pw - the paned widget. + * Returns: none. + */ + +static void +CommitNewLocations(pw) +PanedWidget pw; +{ + Widget *childP; + XWindowChanges changes; + + changes.stack_mode = Above; + + ForAllPanes(pw, childP) { + Pane pane = PaneInfo(*childP); + Widget grip = pane->grip; /* may be NULL. */ + + if (IsVert(pw)) { + XtMoveWidget(*childP, (Position) 0, pane->delta); + XtResizeWidget(*childP, pw->core.width, (Dimension) pane->size, + (Dimension) 0); + + if (HasGrip(*childP)) { /* Move and Display the Grip */ + changes.x = pw->core.width - pw->paned.grip_indent - + grip->core.width - grip->core.border_width*2; + changes.y = (*childP)->core.y + (*childP)->core.height - + grip->core.height/2 - grip->core.border_width + + pw->paned.internal_bw/2; + } + } + else { + XtMoveWidget(*childP, pane->delta, (Position) 0); + XtResizeWidget(*childP, (Dimension) pane->size, pw->core.height, + (Dimension) 0); + + + if (HasGrip(*childP)) { /* Move and Display the Grip */ + changes.x = (*childP)->core.x + (*childP)->core.width - + grip->core.width/2 - grip->core.border_width + + pw->paned.internal_bw/2; + changes.y = pw->core.height - pw->paned.grip_indent - + grip->core.height - grip->core.border_width*2; + } + } + +/* + * This should match XtMoveWidget, except that we're also insuring the + * grip is Raised in the same request. + */ + + if (HasGrip(*childP)) { + grip->core.x = changes.x; + grip->core.y = changes.y; + + if (XtIsRealized(pane->grip)) + XConfigureWindow( XtDisplay(pane->grip), XtWindow(pane->grip), + CWX | CWY | CWStackMode, &changes ); + } + } + ClearPaneStack(pw); +} + +/* Function Name: RefigureLocationsAndCommit + * Description: Refigures all locations in a paned widget and + * commits them immediately. + * Arguments: pw - the paned widget. + * Returns: none + * + * This function does nothing if any of the following are true. + * o refiguremode is false. + * o The widget is unrealized. + * o There are no panes is the paned widget. + * + * NOTE: This is the resize Procedure for the Paned widget. + */ + +static void +RefigureLocationsAndCommit(w) +Widget w; +{ + PanedWidget pw = (PanedWidget) w; + if (pw->paned.refiguremode && XtIsRealized( (Widget) pw) && + pw->paned.num_panes > 0 ) { + RefigureLocations(pw, NO_INDEX, AnyPane); + CommitNewLocations(pw); + } +} + +/* Function Name: _DrawRect + * Description: Draws a rectangle in the proper orientation. + * Arguments: pw - the paned widget. + * gc - gc to used for the draw. + * on_olc, off_loc - location of upper left corner of rect. + * on_size, off_size - size of rectangle. + * Returns: none + */ + +static void +_DrawRect(pw, gc, on_loc, off_loc, on_size, off_size) +PanedWidget pw; +GC gc; +int on_loc, off_loc; +unsigned int on_size, off_size; +{ + if (IsVert(pw)) + XFillRectangle(XtDisplay(pw), XtWindow(pw), gc, + off_loc, on_loc, off_size, on_size); + else + XFillRectangle(XtDisplay(pw), XtWindow(pw), gc, + on_loc, off_loc, on_size, off_size); +} + +/* Function Name: _DrawInternalBorders + * Description: Draws the internal borders into the paned widget. + * Arguments: pw - the paned widget. + * gc - the GC to use to draw the borders. + * Returns: none. + */ + +static void +_DrawInternalBorders(pw, gc) +PanedWidget pw; +GC gc; +{ + Widget *childP; + int on_loc, off_loc; + unsigned int on_size, off_size; + +/* + * This is an optimization. Do not paint the internal borders if + * they are the same color as the background. + */ + + if (pw->core.background_pixel == pw->paned.internal_bp) + return; + + off_loc = 0; + off_size = (unsigned int) PaneSize( (Widget) pw, !IsVert(pw) ); + on_size = (unsigned int) pw->paned.internal_bw; + + ForAllPanes(pw, childP) { + on_loc = IsVert(pw) ? (*childP)->core.y : (*childP)->core.x; + on_loc -= (int) on_size; + + _DrawRect( pw, gc, on_loc, off_loc, on_size, off_size); + } +} + +/* + * This allows good reuse of code, as well as descriptive function names. + */ + +#define DrawInternalBorders(pw) _DrawInternalBorders((pw), (pw)->paned.normgc); +#define EraseInternalBorders(pw) _DrawInternalBorders((pw), (pw)->paned.invgc); + +/* Function Name: _DrawTrackLines + * Description: Draws the lines that animate the pane borders when the + * grips are moved. + * Arguments: pw - the Paned widget. + * erase - if True then just erase track lines, else + * draw them in. + * Returns: none. + */ + +static void +_DrawTrackLines(pw, erase) +PanedWidget pw; +Boolean erase; +{ + Widget *childP; + Pane pane; + int on_loc, off_loc; + unsigned int on_size, off_size; + + off_loc = 0; + off_size = PaneSize( (Widget) pw, !IsVert(pw)); + + ForAllPanes(pw, childP) { + pane = PaneInfo(*childP); + if ( erase || (pane->olddelta != pane->delta) ) { + on_size = pw->paned.internal_bw; + if (!erase) { + on_loc = PaneInfo(*childP)->olddelta - (int) on_size; + + _DrawRect( pw, pw->paned.flipgc, + on_loc, off_loc, on_size, off_size); + } + + on_loc = PaneInfo(*childP)->delta - (int) on_size; + + _DrawRect(pw, pw->paned.flipgc, + on_loc, off_loc, on_size, off_size); + + pane->olddelta = pane->delta; + } + } +} + +/* + * This allows good reuse of code, as well as descriptive function names. + */ + +#define DrawTrackLines(pw) _DrawTrackLines((pw), FALSE); +#define EraseTrackLines(pw) _DrawTrackLines((pw), TRUE); + +/* Function Name: GetEventLocation + * Description: Converts and event to an x and y location. + * Arguments: pw - the paned widget. + * event - a pointer to an event. + * Returns: if this is a vertical pane then (y) else (x). + */ + +static int +GetEventLocation(pw, event) +PanedWidget pw; +XEvent *event; +{ + int x, y; + + switch (event->xany.type) { + case ButtonPress: + case ButtonRelease: + x = event->xbutton.x_root; + y = event->xbutton.y_root; + break; + case KeyPress: + case KeyRelease: + x = event->xkey.x_root; + y = event->xkey.y_root; + break; + case MotionNotify: + x = event->xmotion.x_root; + y = event->xmotion.y_root; + break; + default: + x = pw->paned.start_loc; + y = pw->paned.start_loc; + } + if (IsVert(pw)) + return(y); + return(x); +} + +/* Function Name: StartGripAdjustment + * Description: Starts the grip adjustment procedure. + * Arguments: pw - the paned widget. + * grip - the grip widget selected. + * dir - the direction that we are to be moving. + * Returns: none. + */ + +static void +StartGripAdjustment(pw, grip, dir) +PanedWidget pw; +Widget grip; +Direction dir; +{ + Widget *childP; + Cursor cursor; + + pw->paned.whichadd = pw->paned.whichsub = (Widget) NULL; + + if (dir == ThisBorderOnly || dir == UpLeftPane) + pw->paned.whichadd = pw->composite.children[PaneIndex(grip)]; + if (dir == ThisBorderOnly || dir == LowRightPane) + pw->paned.whichsub = pw->composite.children[PaneIndex(grip) + 1]; + +/* + * Change the cursor. + */ + + if (XtIsRealized(grip)) { + if ( IsVert(pw) ) { + if (dir == UpLeftPane) + cursor = pw->paned.adjust_upper_cursor; + else if (dir == LowRightPane) + cursor = pw->paned.adjust_lower_cursor; + else { + if ( pw->paned.adjust_this_cursor == None) + cursor = pw->paned.v_adjust_this_cursor; + else + cursor = pw->paned.adjust_this_cursor; + } + } + else { + if (dir == UpLeftPane) + cursor = pw->paned.adjust_left_cursor; + else if (dir == LowRightPane) + cursor = pw->paned.adjust_right_cursor; + else { + if (pw->paned.adjust_this_cursor == None) + cursor = pw->paned.h_adjust_this_cursor; + else + cursor = pw->paned.adjust_this_cursor; + } + } + + XDefineCursor(XtDisplay(grip), XtWindow(grip), cursor); + } + + EraseInternalBorders(pw); + ForAllPanes(pw, childP) + PaneInfo(*childP)->olddelta = -99; +} + +/* Function Name: MoveGripAdjustment + * Description: This routine moves all panes around when a grip is moved. + * Arguments: pw - the paned widget. + * grip - the grip that we are moving. + * dir - the direction the pane we are interested is w.r.t the + * grip. + * loc - location of pointer in proper direction. + * Returns: none. + */ + +static void +MoveGripAdjustment(pw, grip, dir, loc) +PanedWidget pw; +Widget grip; +Direction dir; +int loc; +{ + int diff, add_size = 0, sub_size = 0; + + diff = loc - pw->paned.start_loc; + + if (pw->paned.whichadd) + add_size = PaneSize(pw->paned.whichadd, IsVert(pw) ) + diff; + + if (pw->paned.whichsub) + sub_size = PaneSize(pw->paned.whichsub, IsVert(pw) ) - diff; + +/* + * If moving this border only then do not allow either of the borders + * to go beyond the min or max size allowed. + */ + + if ( (dir == ThisBorderOnly) ) { + int old_add_size = add_size, old_sub_size; + + AssignMax(add_size, (int) PaneInfo(pw->paned.whichadd)->min); + AssignMin(add_size, (int) PaneInfo(pw->paned.whichadd)->max); + if (add_size != old_add_size) + sub_size += old_add_size - add_size; + + old_sub_size = sub_size; + AssignMax(sub_size, (int) PaneInfo(pw->paned.whichsub)->min); + AssignMin(sub_size, (int) PaneInfo(pw->paned.whichsub)->max); + if (sub_size != old_sub_size) return; /* Abort to current sizes. */ + } + + if (add_size != 0) + PaneInfo(pw->paned.whichadd)->size = add_size; + if (sub_size != 0) + PaneInfo(pw->paned.whichsub)->size = sub_size; + RefigureLocations(pw, PaneIndex(grip), dir); + DrawTrackLines(pw); +} + +/* Function Name: CommitGripAdjustment + * Description: Commits the grip adjustment. + * Arguments: pw - the paned widget. + * Returns: none + */ + +static void +CommitGripAdjustment(pw) +PanedWidget pw; +{ + EraseTrackLines(pw); + CommitNewLocations(pw); + DrawInternalBorders(pw); + +/* + * Since the user selected this size then use it as the preferred size. + */ + + if (pw->paned.whichadd) { + Pane pane = PaneInfo(pw->paned.whichadd); + pane->wp_size = pane->size; + } + if (pw->paned.whichsub) { + Pane pane = PaneInfo(pw->paned.whichsub); + pane->wp_size = pane->size; + } +} + +/* Function Name: HandleGrip + * Description: Handles the grip manipulations. + * Arguments: grip - the grip widget that has been moved. + * junk - ** NOT USED ** + * call_data - data passed to us from the grip widget. + * Returns: none. + */ + +/* ARGSUSED */ +static void +HandleGrip(grip, junk, callData) +Widget grip; +XtPointer junk, callData; +{ + XawGripCallData call_data = (XawGripCallData)callData; + PanedWidget pw = (PanedWidget) XtParent(grip); + int loc; + char action_type; + Cursor cursor; + Direction direction = 0; + Arg arglist[1]; + + action_type = *call_data->params[0]; + + if (call_data->num_params == 0 || + (action_type == 'C' && call_data->num_params != 1) || + (action_type != 'C' && call_data->num_params != 2)) + XtError( "Paned GripAction has been passed incorrect parameters." ); + + if (islower(action_type)) action_type = toupper(action_type); + + loc = GetEventLocation(pw, (XEvent *) (call_data->event)); + + if (action_type != 'C') { + if ( isupper(*call_data->params[1]) ) + direction = (Direction) *call_data->params[1]; + else + direction = (Direction) toupper(*call_data->params[1]); + } + + switch (action_type) { + case 'S': /* Start adjustment */ + pw->paned.resize_children_to_pref = FALSE; + StartGripAdjustment(pw, grip, direction); + pw->paned.start_loc = loc; + break; + + case 'M': + MoveGripAdjustment(pw, grip, direction, loc); + break; + + case 'C': + XtSetArg(arglist[0], XtNcursor, &cursor); + XtGetValues(grip, arglist, (Cardinal) 1); + XDefineCursor(XtDisplay(grip), XtWindow(grip), cursor); + CommitGripAdjustment(pw); + break; + + default: + XtError( "Paned GripAction(); 1st parameter invalid" ); + } +} + +/* Function Name: ResortChildren + * Description: Resorts the children so that all managed children + * are first. + * Arguments: pw - the paned widget. + * Returns: none. + */ + +static void +ResortChildren(pw) +PanedWidget pw; +{ + Widget * unmanagedP, * childP; + + unmanagedP = NULL; + ForAllChildren(pw, childP) { + if (!IsPane(*childP) || !XtIsManaged(*childP)) { + /* + * We only keep track of the first unmanaged pane. + */ + if (unmanagedP == NULL) + unmanagedP = childP; + } + else { /* must be a managed pane */ + /* + * If an earlier widget was not a managed pane, then swap + */ + if (unmanagedP != NULL) { + Widget child = *unmanagedP; + *unmanagedP = *childP; + *childP = child; + childP = unmanagedP; /* easiest to just back-track */ + unmanagedP = NULL; /* in case there is another managed */ + } + } + } +} + +/* Function Name: ManageAndUnmanageGrips + * Description: This function manages and unmanages the grips so that + * the managed state of each grip matches that of its pane. + * Arguments: pw - the paned widget. + * Returns: none. + */ + +static void +ManageAndUnmanageGrips(pw) +PanedWidget pw; +{ + WidgetList managed_grips, unmanaged_grips; + Widget *managedP, *unmanagedP, *childP; + Cardinal alloc_size; + + alloc_size = (Cardinal) sizeof(Widget) * pw->composite.num_children / 2; + managedP = managed_grips = (WidgetList) XtMalloc(alloc_size); + unmanagedP = unmanaged_grips = (WidgetList) XtMalloc(alloc_size); + + ForAllChildren(pw, childP) + if (IsPane(*childP) && HasGrip(*childP)) + if ( XtIsManaged(*childP) ) + *managedP++ = PaneInfo(*childP)->grip; + else + *unmanagedP++ = PaneInfo(*childP)->grip; + + if (managedP != managed_grips) { + *unmanagedP++ = *--managedP; /* Last grip is never managed */ + XtManageChildren( managed_grips, (Cardinal)(managedP - managed_grips) ); + } + + if (unmanagedP != unmanaged_grips) + XtUnmanageChildren( unmanaged_grips, + (Cardinal)(unmanagedP - unmanaged_grips) ); + + XtFree((char *)managed_grips); + XtFree((char *)unmanaged_grips); +} + +/* Function Name: CreateGrip + * Description: Creates a grip widget. + * Arguments: child - the child that wants a grip to be created for it. + * Returns: none. + */ + +static void +CreateGrip(child) +Widget child; +{ + PanedWidget pw = (PanedWidget) XtParent(child); + Arg arglist[2]; + Cardinal num_args = 0; + Cursor cursor; + + XtSetArg(arglist[num_args], XtNtranslations, pw->paned.grip_translations); + num_args++; + if ( (cursor = pw->paned.grip_cursor) == None ) + if (IsVert(pw)) + cursor = pw->paned.v_grip_cursor; + else + cursor = pw->paned.h_grip_cursor; + + XtSetArg(arglist[num_args], XtNcursor, cursor); + num_args++; + PaneInfo(child)->grip = XtCreateWidget("grip", gripWidgetClass, (Widget)pw, + arglist, num_args); + + XtAddCallback(PaneInfo(child)->grip, XtNcallback, + HandleGrip, (XtPointer) child); +} + +/* Function Name: GetGCs + * Description: Gets new GC's. + * Arguments: w - the paned widget. + * Returns: none. + */ + +static void +GetGCs(w) +Widget w; +{ + PanedWidget pw = (PanedWidget) w; + XtGCMask valuemask; + XGCValues values; + +/* + * Draw pane borders in internal border color. + */ + + values.foreground = pw->paned.internal_bp; + valuemask = GCForeground; + pw->paned.normgc = XtGetGC(w, valuemask, &values); + +/* + * Erase pane borders with background color. + */ + + values.foreground = pw->core.background_pixel; + valuemask = GCForeground; + pw->paned.invgc = XtGetGC(w, valuemask, &values); + +/* + * Draw Track lines (animate pane borders) in internal border color ^ bg color. + */ + + values.function = GXinvert; + values.plane_mask = pw->paned.internal_bp ^ pw->core.background_pixel; + values.subwindow_mode = IncludeInferiors; + valuemask = GCPlaneMask | GCFunction | GCSubwindowMode; + pw->paned.flipgc = XtGetGC(w, valuemask, &values); +} + +/* Function Name: SetChildrenPrefSizes. + * Description: Sets the preferred sizes of the children. + * Arguments: pw - the paned widget. + * Returns: none. + */ + +static void +SetChildrenPrefSizes(pw, off_size) +PanedWidget pw; +Dimension off_size; +{ + Widget * childP; + Boolean vert = IsVert(pw); + XtWidgetGeometry request, reply; + + ForAllPanes(pw, childP) + if ( pw->paned.resize_children_to_pref || + (PaneInfo(*childP)->size == 0) || + (PaneInfo(*childP)->resize_to_pref) ) { + + if (PaneInfo(*childP)->preferred_size != PANED_ASK_CHILD) + PaneInfo(*childP)->wp_size=PaneInfo(*childP)->preferred_size; + else { + if( vert ) { + request.request_mode = CWWidth; + request.width = off_size; + } + else { + request.request_mode = CWHeight; + request.height = off_size; + } + + if ((XtQueryGeometry( *childP, &request, &reply ) + == XtGeometryAlmost) && + (reply.request_mode = (vert ? CWHeight : CWWidth))) + PaneInfo(*childP)->wp_size = GetRequestInfo(&reply, vert); + else + PaneInfo(*childP)->wp_size = PaneSize(*childP, vert); + } + + PaneInfo(*childP)->size = PaneInfo(*childP)->wp_size; + } +} + +/* Function Name: ChangeAllGripCursors + * Description: Changes all the grip cursors. + * Arguments: pw - the paned widget. + * Returns: none + */ + +static void +ChangeAllGripCursors(pw) +PanedWidget pw; +{ + Widget * childP; + + ForAllPanes(pw, childP) { + Arg arglist[1]; + Cursor cursor; + + if ( (cursor = pw->paned.grip_cursor) == None ) + if ( IsVert(pw) ) + cursor = pw->paned.v_grip_cursor; + else + cursor = pw->paned.h_grip_cursor; + + if (HasGrip (*childP)) { + XtSetArg(arglist[0], XtNcursor, cursor); + XtSetValues(PaneInfo(*childP)->grip, arglist, (Cardinal) 1); + } + } +} + +/************************************************************ + * + * Stack Manipulation routines (Private). + * + ************************************************************/ + +/* Function Name: PushPaneStack + * Description: Pushes a value onto the pane stack. + * Arguments: pw - the paned widget. + * pane - the pane that we are pushing. + * Returns: none. + */ + +static void +PushPaneStack(pw, pane) +PanedWidget pw; +Pane pane; +{ + PaneStack * stack = (PaneStack *) XtMalloc(sizeof(PaneStack)); + + stack->next = pw->paned.stack; + stack->pane = pane; + stack->start_size = pane->size; + + pw->paned.stack = stack; +} + +/* Function Name: GetPaneStack + * Description: Gets the top value from the pane stack. + * Arguments: pw - the paned widget. + * shrink - TRUE if we want to shrink this pane, + * FALSE otherwise. + * ** RETURNED ** pane - the pane that we are popping. + * ** RETURNED ** start_size - the size that this pane started at. + * Returns: none. + */ + +static void +GetPaneStack(pw, shrink, pane, start_size) +PanedWidget pw; +Boolean shrink; +Pane * pane; +int * start_size; +{ + if (pw->paned.stack == NULL) { + *pane = NULL; + return; + } + + *pane = pw->paned.stack->pane; + *start_size = pw->paned.stack->start_size; + + if (shrink != ((*pane)->size > *start_size)) *pane = NULL; +} + +/* Function Name: PopPaneStack + * Description: Pops the top item off the pane stack. + * Arguments: pw - the paned widget. + * Returns: TRUE if this is not the last element on the stack. + */ + +static Boolean +PopPaneStack(pw) +PanedWidget pw; +{ + PaneStack * stack = pw->paned.stack; + + if (stack == NULL) return(FALSE); + + pw->paned.stack = stack->next; + XtFree((char*)stack); + + if (pw->paned.stack == NULL) return(FALSE); + return(TRUE); +} + +/* Function Name: ClearPaneStack + * Description: removes all entries from the pane stack. + * Arguments: pw - the paned widget. + * Returns: none + */ + +static void +ClearPaneStack(pw) +PanedWidget pw; +{ + while(PopPaneStack(pw)); +} + +/************************************************************ + * + * Semi-public routines. + * + ************************************************************/ + +/* Function Name: ClassInitialize + * Description: The Paned widgets class initialization proc. + * Arguments: none. + * Returns: none. + */ + +static void +ClassInitialize() +{ + XawInitializeWidgetSet(); + XtAddConverter( XtRString, XtROrientation, XmuCvtStringToOrientation, + (XtConvertArgList)NULL, (Cardinal)0 ); +} + +/* The Geometry Manager only allows changes after Realize if + * allow_resize is True in the constraints record. + * + * For vertically paned widgets: + * + * It only allows height changes, but offers the requested height + * as a compromise if both width and height changes were requested. + * + * For horizontal widgets the converse is true. + * As all good Geometry Managers should, we will return No if the + * request will have no effect; i.e. when the requestor is already + * of the desired geometry. + */ + +static XtGeometryResult GeometryManager(w, request, reply) +Widget w; +XtWidgetGeometry *request, *reply; +{ + PanedWidget pw = (PanedWidget) XtParent(w); + XtGeometryMask mask = request->request_mode; + Dimension old_size, old_wpsize, old_paned_size; + Pane pane = PaneInfo(w); + Boolean vert = IsVert(pw); + Dimension on_size, off_size; + XtGeometryResult result; + Boolean almost = FALSE; + +/* + * If any of the following is true, disallow the geometry change. + * + * o The paned widget is realized and allow_resize is false for the pane. + * o The child did not ask to change the on_size. + * o The request is not a width or height request. + * o The requested size is the same as the current size. + */ + + if ( (XtIsRealized((Widget)pw) && !pane->allow_resize) || + !(mask & ((vert) ? CWHeight : CWWidth)) || + (mask & ~(CWWidth | CWHeight)) || + (GetRequestInfo(request, vert) == PaneSize(w, vert)) ) { + return XtGeometryNo; + } + + old_paned_size = PaneSize( (Widget) pw, vert); + old_wpsize = pane->wp_size; + old_size = pane->size; + + pane->wp_size = pane->size = GetRequestInfo(request, vert); + + AdjustPanedSize(pw, PaneSize((Widget) pw, !vert), &result, &on_size, + &off_size); + +/* + * Fool the Refigure Locations proc to thinking that we are + * a different on_size; + */ + + if (result != XtGeometryNo) + if (vert) + pw->core.height = on_size; + else + pw->core.width = on_size; + + RefigureLocations(pw, PaneIndex(w), AnyPane); + +/* + * Set up reply struct and reset core on_size. + */ + + if (vert) { + pw->core.height = old_paned_size; + reply->height = pane->size; + reply->width = off_size; + } + else { + pw->core.width = old_paned_size; + reply->height = off_size; + reply->width = pane->size; + } + +/* + * IF either of the following is true. + * + * o There was a "off_size" request and the new "off_size" is different + * from that requested. + * o There was no "off_size" request and the new "off_size" is different + * + * o The "on_size" we will allow is different from that requested. + * + * THEN: set almost + */ + + if ( !((vert ? CWWidth : CWHeight) & mask)) + if (vert) + request->width = w->core.width; + else + request->height = w->core.height; + + almost = GetRequestInfo(request, !vert) != GetRequestInfo(reply, !vert); + almost |= (GetRequestInfo(request, vert) != GetRequestInfo(reply, vert)); + + if ( (mask & XtCWQueryOnly) || almost ) { + pane->wp_size = old_wpsize; + pane->size = old_size; + RefigureLocations(pw, PaneIndex(w), AnyPane); + reply->request_mode = CWWidth | CWHeight; + if (almost) return XtGeometryAlmost; + } + else { + AdjustPanedSize(pw, PaneSize((Widget) pw, !vert), + (XtGeometryResult *)NULL, + (Dimension *)NULL, (Dimension *)NULL); + CommitNewLocations( pw ); /* layout already refigured. */ + } + return XtGeometryDone; +} + +/* ARGSUSED */ +static void Initialize(request, new, args, num_args) +Widget request, new; +ArgList args; +Cardinal *num_args; +{ + PanedWidget pw = (PanedWidget)new; + + GetGCs( (Widget) pw); + + pw->paned.recursively_called = False; + pw->paned.stack = NULL; + pw->paned.resize_children_to_pref = TRUE; + pw->paned.num_panes = 0; +} + +static void +Realize(w, valueMask, attributes) +Widget w; +Mask *valueMask; +XSetWindowAttributes *attributes; +{ + PanedWidget pw = (PanedWidget) w; + Widget * childP; + + if ((attributes->cursor = (pw)->paned.cursor) != None) + *valueMask |= CWCursor; + + (*SuperClass->core_class.realize) (w, valueMask, attributes); + +/* + * Before we commit the new locations we need to realize all the panes and + * their grips. + */ + + ForAllPanes(pw, childP) { + XtRealizeWidget( *childP ); + if (HasGrip (*childP)) + XtRealizeWidget( PaneInfo(*childP)->grip ); + } + + RefigureLocationsAndCommit(w); + pw->paned.resize_children_to_pref = FALSE; +} /* Realize */ + +static void +ReleaseGCs(w) +Widget w; +{ + PanedWidget pw = (PanedWidget)w; + + XtReleaseGC( w, pw->paned.normgc ); + XtReleaseGC( w, pw->paned.invgc ); + XtReleaseGC( w, pw->paned.flipgc ); +} + +static void InsertChild(w) +Widget w; +{ + Pane pane = PaneInfo(w); + + /* insert the child widget in the composite children list with the */ + /* superclass insert_child routine. */ + (*SuperClass->composite_class.insert_child)(w); + + if (!IsPane(w)) return; + + /* ||| Panes will be added in the order they are created, temporarily */ + + if ( pane->show_grip == TRUE ) { + CreateGrip(w); + if (pane->min == PANED_GRIP_SIZE) + pane->min = PaneSize(pane->grip, IsVert((PanedWidget) XtParent(w))); + } + else { + if (pane->min == PANED_GRIP_SIZE) + pane->min = 1; + pane->grip = NULL; + } + + pane->size = 0; + pane->paned_adjusted_me = FALSE; + +} /* InsertChild */ + +static void DeleteChild(w) +Widget w; +{ + /* remove the subwidget info and destroy the grip */ + + if ( IsPane(w) && HasGrip(w) ) XtDestroyWidget(PaneInfo(w)->grip); + + /* delete the child widget in the composite children list with the */ + /* superclass delete_child routine. */ + (*SuperClass->composite_class.delete_child) (w); + +} /* DeleteChild */ + +static void ChangeManaged(w) + Widget w; +{ + PanedWidget pw = (PanedWidget)w; + Boolean vert = IsVert(pw); + Dimension size; + Widget *childP; + + if (pw->paned.recursively_called++) return; + +/* + * If the size is zero then set it to the size of the widest or tallest pane. + */ + + if ( (size = PaneSize( (Widget) pw, !vert )) == 0) { + size = 1; + ForAllChildren(pw, childP) + if ( XtIsManaged(*childP) && (PaneSize( *childP, !vert ) > size) ) + size = PaneSize( *childP, !vert ); + } + + ManageAndUnmanageGrips(pw); + pw->paned.recursively_called = False; + ResortChildren(pw); + + pw->paned.num_panes = 0; + ForAllChildren(pw, childP) + if ( IsPane(*childP) ) + if ( XtIsManaged(*childP) ) { + Pane pane = PaneInfo(*childP); + if (HasGrip(*childP)) + PaneInfo(pane->grip)->position = pw->paned.num_panes; + pane->position = pw->paned.num_panes; /*TEMPORY -CDP 3/89 */ + pw->paned.num_panes++; + } + else + break; /* This list is already sorted. */ + + SetChildrenPrefSizes( (PanedWidget) w, size); + +/* + * ForAllPanes can now be used. + */ + + if ( PaneSize((Widget) pw, vert) == 0 ) + AdjustPanedSize(pw, size, (XtGeometryResult *)NULL, + (Dimension *)NULL, (Dimension *)NULL); + + if (XtIsRealized( (Widget) pw)) + RefigureLocationsAndCommit( (Widget) pw); + +} /* ChangeManaged */ + +/* Function Name: Resize + * Description: The paned widget's resize proc. + * Arguments: w - the paned widget. + * Returns: none. + */ + +static void +Resize(w) +Widget w; +{ + SetChildrenPrefSizes( (PanedWidget) w, + PaneSize(w, !IsVert((PanedWidget) w)) ); + RefigureLocationsAndCommit(w); +} + +/* ARGSUSED */ +static void +Redisplay(w, event, region) +Widget w; +XEvent * event; /* unused. */ +Region region; /* unused. */ +{ + DrawInternalBorders( (PanedWidget) w); +} + +/* ARGSUSED */ +static Boolean +SetValues(old, request, new, args, num_args) +Widget old, request, new; +ArgList args; +Cardinal *num_args; +{ + PanedWidget old_pw = (PanedWidget) old; + PanedWidget new_pw = (PanedWidget) new; + Boolean redisplay = FALSE; + + if ( (old_pw->paned.cursor != new_pw->paned.cursor) && XtIsRealized(new)) + XDefineCursor(XtDisplay(new), XtWindow(new), new_pw->paned.cursor); + + if ( (old_pw->paned.internal_bp != new_pw->paned.internal_bp) || + (old_pw->core.background_pixel != new_pw->core.background_pixel) ) { + ReleaseGCs(old); + GetGCs(new); + redisplay = TRUE; + } + + if ( (old_pw->paned.grip_cursor != new_pw->paned.grip_cursor) || + (old_pw->paned.v_grip_cursor != new_pw->paned.v_grip_cursor) || + (old_pw->paned.h_grip_cursor != new_pw->paned.h_grip_cursor) ) { + ChangeAllGripCursors(new_pw); + } + + if ( IsVert(old_pw) != IsVert(new_pw)) { +/* + * We are fooling the paned widget into thinking that is needs to + * fully refigure everything, which is what we want. + */ + if (IsVert(new_pw)) + new_pw->core.width = 0; + else + new_pw->core.height = 0; + + new_pw->paned.resize_children_to_pref = TRUE; + ChangeManaged(new); /* Seems weird, but does the right thing. */ + new_pw->paned.resize_children_to_pref = FALSE; + if (new_pw->paned.grip_cursor == None) + ChangeAllGripCursors(new_pw); + return(TRUE); + } + + if (old_pw->paned.internal_bw != new_pw->paned.internal_bw) { + AdjustPanedSize( new_pw, PaneSize(new, !IsVert(old_pw)), + (XtGeometryResult *)NULL, + (Dimension *)NULL, (Dimension *)NULL); + RefigureLocationsAndCommit(new); + return(TRUE); /* We have done a full configuration, return.*/ + } + + if ( (old_pw->paned.grip_indent != new_pw->paned.grip_indent) && + (XtIsRealized(new)) ) { + CommitNewLocations(new_pw); + redisplay = TRUE; + } + + return (redisplay); +} /* SetValues */ + + +/* ARGSUSED */ +static Boolean +PaneSetValues(old, request, new, args, num_args) +Widget old, request, new; +ArgList args; +Cardinal *num_args; +{ + Pane old_pane = PaneInfo(old); + Pane new_pane = PaneInfo(new); + Boolean redisplay = FALSE; + + /* Check for new min and max. */ + + if (old_pane->min != new_pane->min || old_pane->max != new_pane->max) + XawPanedSetMinMax(new, (int)new_pane->min, (int)new_pane->max); + + /* Check for change in XtNshowGrip. */ + + if (old_pane->show_grip != new_pane->show_grip) + if (new_pane->show_grip == TRUE) { + CreateGrip(new); + if (XtIsRealized(XtParent(new))) { + if (XtIsManaged(new)) /* if paned is unrealized this will + happen automatically at realize time.*/ + XtManageChild(PaneInfo(new)->grip); /* manage the grip. */ + XtRealizeWidget(PaneInfo(new)->grip); /* realize the grip. */ + CommitNewLocations( (PanedWidget) XtParent(new) ); + } + } + else if ( HasGrip(old) ) { + XtDestroyWidget( old_pane->grip ); + new_pane->grip = NULL; + redisplay = TRUE; + } + + /* ||| need to look at position changes */ + + return(redisplay); +} + +/************************************************************ + * + * Public routines. + * + ************************************************************/ + +/* Function Name: XawPanedSetMinMax + * Description: Sets the min and max size for a pane. + * Arguments: widget - the widget that is a child of the Paned widget. + * min, max - the new min and max size for the pane. + * Returns: none. + */ + +void +#if NeedFunctionPrototypes +XawPanedSetMinMax(Widget widget, int min, int max) +#else +XawPanedSetMinMax(widget, min, max) +Widget widget; +int min, max; +#endif +{ + Pane pane = PaneInfo(widget); + + pane->min = min; + pane->max = max; + RefigureLocationsAndCommit( widget->core.parent ); +} + +/* Function Name: XawPanedGetMinMax + * Description: Gets the min and max size for a pane. + * Arguments: widget - the widget that is a child of the Paned widget. + ** RETURNED ** min, max - the current min and max size for the pane. + * Returns: none. + */ + +void +#if NeedFunctionPrototypes +XawPanedGetMinMax(Widget widget, int *min, int *max) +#else +XawPanedGetMinMax(widget, min, max) +Widget widget; +int *min, *max; +#endif +{ + Pane pane = PaneInfo(widget); + + *min = pane->min; + *max = pane->max; +} + +/* Function Name: XawPanedSetRefigureMode + * Description: Allows a flag to be set the will inhibit + * the paned widgets relayout routine. + * Arguments: w - the paned widget. + * mode - if FALSE then inhibit refigure. + * Returns: none. + */ + +void +#if NeedFunctionPrototypes +XawPanedSetRefigureMode(Widget w, +#if NeedWidePrototypes + int mode) +#else + Boolean mode) +#endif +#else +XawPanedSetRefigureMode(w, mode) +Widget w; +Boolean mode; +#endif +{ + ((PanedWidget) w)->paned.refiguremode = mode; + RefigureLocationsAndCommit( w ); +} + +/* Function Name: XawPanedGetNumSub + * Description: Returns the number of panes in the paned widget. + * Arguments: w - the paned widget. + * Returns: the number of panes in the paned widget. + */ + +int +#if NeedFunctionPrototypes +XawPanedGetNumSub(Widget w) +#else +XawPanedGetNumSub(w) +Widget w; +#endif +{ + return ((PanedWidget)w)->paned.num_panes; +} + +/* Function Name: XawPanedAllowResize + * Description: Allows a flag to be set that determines if the paned + * widget will allow geometry requests from this child + * Arguments: widget - a child of the paned widget. + * Returns: none. + */ + +void +#if NeedFunctionPrototypes +XawPanedAllowResize(Widget widget, +#if NeedWidePrototypes + int allow_resize) +#else + Boolean allow_resize) +#endif +#else +XawPanedAllowResize(widget, allow_resize) +Widget widget; +Boolean allow_resize; +#endif +{ + PaneInfo(widget)->allow_resize = allow_resize; +} diff --git a/src/Paned.h b/src/Paned.h new file mode 100644 index 0000000..6b37346 --- /dev/null +++ b/src/Paned.h @@ -0,0 +1,256 @@ +/* +* $XConsortium: Paned.h,v 1.15 94/04/17 20:12:29 kaleb Exp $ +*/ + + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * Paned.h - Paned Composite Widget's public header file. + * + * Updated and significantly modifided from the Athena VPaned Widget. + * + * Date: March 1, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifndef _XawPaned_h +#define _XawPaned_h + +#include <X11/Constraint.h> +#include <X11/Xmu/Converters.h> + +/**************************************************************** + * + * Vertical Paned Widget (SubClass of CompositeClass) + * + ****************************************************************/ + +/* RESOURCES: + + Name Class RepType Default Value + ---- ----- ------- ------------- + background Background Pixel XtDefaultBackground + betweenCursor Cursor Cursor ** + border BorderColor Pixel XtDefaultForeground + borderWidth BorderWidth Dimension 1 + cursor Cursor Cursor None + destroyCallback Callback Pointer NULL + height Height Dimension 0 + gripIndent GripIndent Position 16 + gripCursor Cursor Cursor ** + horizontalGripCursol Cursor Cursor sb_h_double_arrow + horizontalBetweencursor Cursor Cursor sb_up_arrow + internalBorderColor BorderColor Pixel XtDefaultForeground + internalBorderWidth BorderWidth Position 1 + leftCursor Cursor Cursor sb_left_arrow + lowerCursor Cursor Cursor sb_down_arrow + mappedWhenManaged MappedWhenManaged Boolean True + orientation Orientation XtOrientation XtorientVertical + refigureMode Boolean Boolean On + rightCursor Cursor Cursor sb_right_arrow + sensitive Sensitive Boolean True + upperCursor Cursor Cursor sb_up_arrow + verticalBetweenCursor Cursor Cursor sb_left_arrow + verticalGripCursor Cursor Cursor sb_v_double_arrow + width Width Dimension 0 + x Position Position 0 + y Position Position 0 + +** These resources now are set to the vertical or horizontal cursor + depending upon orientation, by default. If a value is specified here + then that cursor will be used reguardless of orientation. + + +CONSTRAINT RESOURCES: + + Name Class RepType Default Value + ---- ----- ------- ------------- + allowResize Boolean Boolean False + max Max Dimension unlimited + min Min Dimension Grip Size + preferredPaneSize PerferredPaneSize Dimension PANED_ASK_CHILD + resizeToPreferred Boolean Boolean False + showGrip ShowGrip Boolean True + skipAdjust Boolean Boolean False + +*/ + +#define PANED_ASK_CHILD 0 +#define PANED_GRIP_SIZE 0 + +/* New Fields */ +#define XtNallowResize "allowResize" +#define XtNbetweenCursor "betweenCursor" +#define XtNverticalBetweenCursor "verticalBetweenCursor" +#define XtNhorizontalBetweenCursor "horizontalBetweenCursor" +#define XtNgripCursor "gripCursor" +#define XtNgripIndent "gripIndent" +#define XtNhorizontalGripCursor "horizontalGripCursor" +#define XtNinternalBorderColor "internalBorderColor" +#define XtNinternalBorderWidth "internalBorderWidth" +#define XtNleftCursor "leftCursor" +#define XtNlowerCursor "lowerCursor" +#define XtNrefigureMode "refigureMode" +#define XtNposition "position" +#define XtNmin "min" +#define XtNmax "max" +#define XtNpreferredPaneSize "preferredPaneSize" +#define XtNresizeToPreferred "resizeToPreferred" +#define XtNrightCursor "rightCursor" +#define XtNshowGrip "showGrip" +#define XtNskipAdjust "skipAdjust" +#define XtNupperCursor "upperCursor" +#define XtNverticalGripCursor "verticalGripCursor" + +#define XtCGripIndent "GripIndent" +#define XtCMin "Min" +#define XtCMax "Max" +#define XtCPreferredPaneSize "PreferredPaneSize" +#define XtCShowGrip "ShowGrip" + +/* Class record constant */ +extern WidgetClass panedWidgetClass; + +typedef struct _PanedClassRec *PanedWidgetClass; +typedef struct _PanedRec *PanedWidget; + +/************************************************************ + * + * Public Procedures + * + ************************************************************/ + +_XFUNCPROTOBEGIN + +/* Function Name: XawPanedSetMinMax + * Description: Sets the min and max size for a pane. + * Arguments: widget - the widget that is a child of the Paned widget. + * min, max - the new min and max size for the pane. + * Returns: none. + */ + +extern void XawPanedSetMinMax( +#if NeedFunctionPrototypes + Widget /* w */, + int /* min */, + int /* max */ +#endif +); + +/* Function Name: XawPanedGetMinMax + * Description: Gets the min and max size for a pane. + * Arguments: widget - the widget that is a child of the Paned widget. + ** RETURNED ** min, max - the current min and max size for the pane. + * Returns: none. + */ + +extern void XawPanedGetMinMax( +#if NeedFunctionPrototypes + Widget /* w */, + int * /* min_return */, + int * /* max_return */ +#endif +); + +/* Function Name: XawPanedSetRefigureMode + * Description: Allows a flag to be set the will inhibit + * the paned widgets relayout routine. + * Arguments: w - the paned widget. + * mode - if FALSE then inhibit refigure. + * Returns: none. + */ + +extern void XawPanedSetRefigureMode( +#if NeedFunctionPrototypes + Widget /* w */, +#if NeedWidePrototypes + /* Boolean */ int /* mode */ +#else + Boolean /* mode */ +#endif +#endif +); + +/* Function Name: XawPanedGetNumSub + * Description: Returns the number of panes in the paned widget. + * Arguments: w - the paned widget. + * Returns: the number of panes in the paned widget. + */ + +extern int XawPanedGetNumSub( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +/* Function Name: XawPanedAllowResize + * Description: Allows a flag to be set that determines if the paned + * widget will allow geometry requests from this child + * Arguments: widget - a child of the paned widget. + * Returns: none. + */ + +extern void XawPanedAllowResize( +#if NeedFunctionPrototypes + Widget /* w */, +#if NeedWidePrototypes + /* Boolean */ int /* allow_resize */ +#else + Boolean /* allow_resize */ +#endif +#endif +); + +_XFUNCPROTOEND + +#endif /* _XawPaned_h */ diff --git a/src/PanedP.h b/src/PanedP.h new file mode 100644 index 0000000..57c410b --- /dev/null +++ b/src/PanedP.h @@ -0,0 +1,193 @@ +/*********************************************************** + + $XConsortium: PanedP.h,v 1.6 94/04/17 20:12:30 gildea Exp $ + + +Copyright (c) 1987, 1988 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * PanedP.h - Paned Composite Widget's private header file. + * + * Updated and significantly modified from the Athena VPaned Widget. + * + * Date: March 1, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifndef _XawPanedP_h +#define _XawPanedP_h + +#include <X11/Xaw3d/Paned.h> + +/********************************************************************* + * + * Paned Widget Private Data + * + *********************************************************************/ + +/* New fields for the Paned widget class record */ + +typedef struct _PanedClassPart { + int foo; /* keep compiler happy. */ +} PanedClassPart; + +/* Full Class record declaration */ +typedef struct _PanedClassRec { + CoreClassPart core_class; + CompositeClassPart composite_class; + ConstraintClassPart constraint_class; + PanedClassPart paned_class; +} PanedClassRec; + +extern PanedClassRec panedClassRec; + +/* Paned constraint record */ +typedef struct _PanedConstraintsPart { + /* Resources. */ + Dimension min; /* Minimum height */ + Dimension max; /* Maximum height */ + Boolean allow_resize; /* TRUE iff child resize requests are ok */ + Boolean show_grip; /* TRUE iff child will have grip below it, + when it is not the bottom pane. */ + Boolean skip_adjust; /* TRUE iff child's height should not be */ + /* changed without explicit user action. */ + int position; /* position location in Paned (relative to + other children) ** NIY ** */ + Dimension preferred_size; /* The Preferred size of the pane. + Iff this is zero then ask child for size.*/ + Boolean resize_to_pref; /* resize this pane to its preferred size + on a resize or change managed after + realize. */ + + /* Private state. */ + Position delta; /* Desired Location */ + Position olddelta; /* The last value of dy. */ + Boolean paned_adjusted_me; /* Has the vpaned adjusted this widget w/o + user interaction to make things fit? */ + Dimension wp_size; /* widget's preferred size */ + int size; /* the size the widget will actually get. */ + Widget grip; /* The grip for this child */ + +} PanedConstraintsPart, *Pane; + +typedef struct _PanedConstraintsRec { + PanedConstraintsPart paned; +} PanedConstraintsRec, *PanedConstraints; + +/* + * The Pane Stack Structure. + */ + +typedef struct _PaneStack { + struct _PaneStack * next; /* The next element on the stack. */ + Pane pane; /* The pane in this element on the stack. */ + int start_size; /* The size of this element when it was pushed + onto the stack. */ +} PaneStack; + +/* New Fields for the Paned widget record */ +typedef struct { + /* resources */ + Position grip_indent; /* Location of grips (offset + from right margin) */ + Boolean refiguremode; /* Whether to refigure changes + right now */ + XtTranslations grip_translations; /* grip translation table */ + Pixel internal_bp; /* color of internal borders. */ + Dimension internal_bw; /* internal border width. */ + XtOrientation orientation; /* Orientation of paned widget. */ + + Cursor cursor; /* Cursor for paned window */ + Cursor grip_cursor; /* inactive grip cursor */ + Cursor v_grip_cursor; /* inactive vert grip cursor */ + Cursor h_grip_cursor; /* inactive horiz grip cursor */ + Cursor adjust_this_cursor; /* active grip cursor: T */ + Cursor v_adjust_this_cursor; /* active vert grip cursor: T */ + Cursor h_adjust_this_cursor; /* active horiz grip cursor: T */ + + /* vertical. */ + Cursor adjust_upper_cursor; /* active grip cursor: U */ + Cursor adjust_lower_cursor; /* active grip cursor: D */ + + /* horizontal. */ + Cursor adjust_left_cursor; /* active grip cursor: U */ + Cursor adjust_right_cursor; /* active grip cursor: D */ + + /* private */ + Boolean recursively_called; /* for ChangeManaged */ + Boolean resize_children_to_pref; /* override constrain resources + and resize all children to + preferred size. */ + int start_loc; /* mouse origin when adjusting */ + Widget whichadd; /* Which pane to add changes to */ + Widget whichsub; /* Which pane to sub changes from */ + GC normgc; /* GC to use when drawing borders */ + GC invgc; /* GC to use when erasing borders */ + GC flipgc; /* GC to use when animating + borders */ + int num_panes; /* count of managed panes */ + PaneStack * stack; /* The pane stack for this widget.*/ +} PanedPart; + +/************************************************************************** + * + * Full instance record declaration + * + **************************************************************************/ + +typedef struct _PanedRec { + CorePart core; + CompositePart composite; + ConstraintPart constraint; + PanedPart paned; +} PanedRec; + +#endif /* _XawPanedP_h */ +/* DON'T ADD STUFF AFTER THIS #endif */ diff --git a/src/Panner.c b/src/Panner.c new file mode 100644 index 0000000..2d2f482 --- /dev/null +++ b/src/Panner.c @@ -0,0 +1,975 @@ +/* + * $XConsortium: Panner.c,v 1.52 95/01/10 14:31:26 kaleb Exp $ + * +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + * Author: Jim Fulton, MIT X Consortium + */ + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> /* for XtN and XtC defines */ +#include <X11/Xmu/CharSet.h> /* for XmuCompareISOLatin1() */ +#include <X11/Xaw3d/XawInit.h> /* for XawInitializeWidgetSet */ +#include <X11/Xaw3d/PannerP.h> /* us */ +#include <X11/Xos.h> +#include <X11/Xmu/Misc.h> /* for Min */ +#include <X11/Xmu/Drawing.h> +#include <ctype.h> /* for isascii() etc. */ +#include <math.h> /* for atof() */ + +extern Bool XmuDistinguishablePixels(); /* not defined in any Xmu headers */ + +#if defined(ISC) && __STDC__ && !defined(ISC30) +extern double atof(char *); +#endif + + +#if XtVersion >= 11006 +static char defaultTranslations[] = + "<Btn1Down>: start() \n\ + <Btn1Motion>: move() \n\ + <Btn1Up>: notify() stop() \n\ + <Btn2Down>: abort() \n\ + :<Key>KP_Enter: set(rubberband,toggle) \n\ + <Key>space: page(+1p,+1p) \n\ + <Key>Delete: page(-1p,-1p) \n\ + :<Key>KP_Delete: page(-1p,-1p) \n\ + <Key>BackSpace: page(-1p,-1p) \n\ + <Key>Left: page(-.5p,+0) \n\ + :<Key>KP_Left: page(-.5p,+0) \n\ + <Key>Right: page(+.5p,+0) \n\ + :<Key>KP_Right: page(+.5p,+0) \n\ + <Key>Up: page(+0,-.5p) \n\ + :<Key>KP_Up: page(+0,-.5p) \n\ + <Key>Down: page(+0,+.5p) \n\ + :<Key>KP_Down: page(+0,+.5p) \n\ + <Key>Home: page(0,0) \n\ + :<Key>KP_Home: page(0,0)"; +#else +static char defaultTranslations[] = + "<Btn1Down>: start() \n\ + <Btn1Motion>: move() \n\ + <Btn1Up>: notify() stop() \n\ + <Btn2Down>: abort() \n\ + <Key>KP_Enter: set(rubberband,toggle) \n\ + <Key>space: page(+1p,+1p) \n\ + <Key>Delete: page(-1p,-1p) \n\ + <Key>BackSpace: page(-1p,-1p) \n\ + <Key>Left: page(-.5p,+0) \n\ + <Key>Right: page(+.5p,+0) \n\ + <Key>Up: page(+0,-.5p) \n\ + <Key>Down: page(+0,+.5p) \n\ + <Key>Home: page(0,0)"; +#endif + + +static void ActionStart(), ActionStop(), ActionAbort(), ActionMove(); +static void ActionPage(), ActionNotify(), ActionSet(); + +static XtActionsRec actions[] = { + { "start", ActionStart }, /* start tmp graphics */ + { "stop", ActionStop }, /* stop tmp graphics */ + { "abort", ActionAbort }, /* punt */ + { "move", ActionMove }, /* move tmp graphics on Motion event */ + { "page", ActionPage }, /* page around usually from keyboard */ + { "notify", ActionNotify }, /* callback new position */ + { "set", ActionSet }, /* set various parameters */ +}; + + +/* + * resources for the panner + */ +static XtResource resources[] = { +#define poff(field) XtOffsetOf(PannerRec, panner.field) + { XtNallowOff, XtCAllowOff, XtRBoolean, sizeof(Boolean), + poff(allow_off), XtRImmediate, (XtPointer) FALSE }, + { XtNresize, XtCResize, XtRBoolean, sizeof(Boolean), + poff(resize_to_pref), XtRImmediate, (XtPointer) TRUE }, + { XtNreportCallback, XtCReportCallback, XtRCallback, sizeof(XtPointer), + poff(report_callbacks), XtRCallback, (XtPointer) NULL }, + { XtNdefaultScale, XtCDefaultScale, XtRDimension, sizeof(Dimension), + poff(default_scale), XtRImmediate, (XtPointer) PANNER_DEFAULT_SCALE }, + { XtNrubberBand, XtCRubberBand, XtRBoolean, sizeof(Boolean), + poff(rubber_band), XtRImmediate, (XtPointer) FALSE }, + { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), + poff(foreground), XtRString, (XtPointer) XtDefaultBackground }, + { XtNinternalSpace, XtCInternalSpace, XtRDimension, sizeof(Dimension), + poff(internal_border), XtRImmediate, (XtPointer) 4 }, + { XtNlineWidth, XtCLineWidth, XtRDimension, sizeof(Dimension), + poff(line_width), XtRImmediate, (XtPointer) 0 }, + { XtNcanvasWidth, XtCCanvasWidth, XtRDimension, sizeof(Dimension), + poff(canvas_width), XtRImmediate, (XtPointer) 0 }, + { XtNcanvasHeight, XtCCanvasHeight, XtRDimension, sizeof(Dimension), + poff(canvas_height), XtRImmediate, (XtPointer) 0 }, + { XtNsliderX, XtCSliderX, XtRPosition, sizeof(Position), + poff(slider_x), XtRImmediate, (XtPointer) 0 }, + { XtNsliderY, XtCSliderY, XtRPosition, sizeof(Position), + poff(slider_y), XtRImmediate, (XtPointer) 0 }, + { XtNsliderWidth, XtCSliderWidth, XtRDimension, sizeof(Dimension), + poff(slider_width), XtRImmediate, (XtPointer) 0 }, + { XtNsliderHeight, XtCSliderHeight, XtRDimension, sizeof(Dimension), + poff(slider_height), XtRImmediate, (XtPointer) 0 }, + { XtNshadowColor, XtCShadowColor, XtRPixel, sizeof(Pixel), + poff(shadow_color), XtRString, (XtPointer) XtDefaultForeground }, + { XtNshadowThickness, XtCShadowThickness, XtRDimension, sizeof(Dimension), + poff(shadow_thickness), XtRImmediate, (XtPointer) 2 }, + { XtNbackgroundStipple, XtCBackgroundStipple, XtRString, sizeof(String), + poff(stipple_name), XtRImmediate, (XtPointer) NULL }, +#undef poff +}; + + +/* + * widget class methods used below + */ +static void Initialize(); /* create gc's */ +static void Realize(); /* create window */ +static void Destroy(); /* clean up widget */ +static void Resize(); /* need to rescale ourselves */ +static void Redisplay(); /* draw ourselves */ +static Boolean SetValues(); /* set all of the resources */ +static void SetValuesAlmost(); /* deal with failed setval geom req */ +static XtGeometryResult QueryGeometry(); /* say how big we would like to be */ + +PannerClassRec pannerClassRec = { + { /* core fields */ + /* superclass */ (WidgetClass) &simpleClassRec, + /* class_name */ "Panner", + /* widget_size */ sizeof(PannerRec), + /* class_initialize */ XawInitializeWidgetSet, + /* class_part_initialize */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ Realize, + /* actions */ actions, + /* num_actions */ XtNumber(actions), + /* 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 */ SetValuesAlmost, + /* get_values_hook */ NULL, + /* accept_focus */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* tm_table */ defaultTranslations, + /* query_geometry */ QueryGeometry, + /* display_accelerator */ XtInheritDisplayAccelerator, + /* extension */ NULL + }, + { /* simple fields */ + /* change_sensitive */ XtInheritChangeSensitive + }, + { /* panner fields */ + /* ignore */ 0 + } +}; + +WidgetClass pannerWidgetClass = (WidgetClass) &pannerClassRec; + + +/***************************************************************************** + * * + * panner utility routines * + * * + *****************************************************************************/ + +static void reset_shadow_gc (pw) /* used when resources change */ + PannerWidget pw; +{ + XtGCMask valuemask = GCForeground; + XGCValues values; + unsigned long pixels[3]; + + if (pw->panner.shadow_gc) XtReleaseGC ((Widget) pw, pw->panner.shadow_gc); + + pixels[0] = pw->panner.foreground; + pixels[1] = pw->core.background_pixel; + pixels[2] = pw->panner.shadow_color; + if (!pw->panner.stipple_name && + !XmuDistinguishablePixels (XtDisplay (pw), pw->core.colormap, + pixels, 3) && + XmuDistinguishablePixels (XtDisplay (pw), pw->core.colormap, + pixels, 2)) + { + valuemask = GCTile | GCFillStyle; + values.fill_style = FillTiled; + values.tile = XmuCreateStippledPixmap(XtScreen((Widget)pw), + pw->panner.foreground, + pw->core.background_pixel, + pw->core.depth); + } + else + { + if (!pw->panner.line_width && + !XmuDistinguishablePixels (XtDisplay (pw), pw->core.colormap, + pixels, 2)) + pw->panner.line_width = 1; + valuemask = GCForeground; + values.foreground = pw->panner.shadow_color; + } + if (pw->panner.line_width > 0) { + values.line_width = pw->panner.line_width; + valuemask |= GCLineWidth; + } + + pw->panner.shadow_gc = XtGetGC ((Widget) pw, valuemask, &values); +} + +static void reset_slider_gc (pw) /* used when resources change */ + PannerWidget pw; +{ + XtGCMask valuemask = GCForeground; + XGCValues values; + + if (pw->panner.slider_gc) XtReleaseGC ((Widget) pw, pw->panner.slider_gc); + + values.foreground = pw->panner.foreground; + + pw->panner.slider_gc = XtGetGC ((Widget) pw, valuemask, &values); +} + +static void reset_xor_gc (pw) /* used when resources change */ + PannerWidget pw; +{ + if (pw->panner.xor_gc) XtReleaseGC ((Widget) pw, pw->panner.xor_gc); + + if (pw->panner.rubber_band) { + XtGCMask valuemask = (GCForeground | GCFunction); + XGCValues values; + Pixel tmp; + + tmp = ((pw->panner.foreground == pw->core.background_pixel) ? + pw->panner.shadow_color : pw->panner.foreground); + values.foreground = tmp ^ pw->core.background_pixel; + values.function = GXxor; + if (pw->panner.line_width > 0) { + valuemask |= GCLineWidth; + values.line_width = pw->panner.line_width; + } + pw->panner.xor_gc = XtGetGC ((Widget) pw, valuemask, &values); + } else { + pw->panner.xor_gc = NULL; + } +} + + +static void check_knob (pw, knob) + PannerWidget pw; + Boolean knob; +{ + Position pad = pw->panner.internal_border * 2; + Position maxx = (((Position) pw->core.width) - pad - + ((Position) pw->panner.knob_width)); + Position maxy = (((Position) pw->core.height) - pad - + ((Position) pw->panner.knob_height)); + Position *x = (knob ? &pw->panner.knob_x : &pw->panner.tmp.x); + Position *y = (knob ? &pw->panner.knob_y : &pw->panner.tmp.y); + + /* + * note that positions are already normalized (i.e. internal_border + * has been subtracted out) + */ + if (*x < 0) *x = 0; + if (*x > maxx) *x = maxx; + + if (*y < 0) *y = 0; + if (*y > maxy) *y = maxy; + + if (knob) { + pw->panner.slider_x = (Position) (((double) pw->panner.knob_x) / + pw->panner.haspect + 0.5); + pw->panner.slider_y = (Position) (((double) pw->panner.knob_y) / + pw->panner.vaspect + 0.5); + pw->panner.last_x = pw->panner.last_y = PANNER_OUTOFRANGE; + } +} + + +static void move_shadow (pw) + PannerWidget pw; +{ + if (pw->panner.shadow_thickness > 0) { + int lw = pw->panner.shadow_thickness + pw->panner.line_width * 2; + int pad = pw->panner.internal_border; + + if ((int)pw->panner.knob_height > lw && (int)pw->panner.knob_width > lw) { + XRectangle *r = pw->panner.shadow_rects; + r->x = (short) (pw->panner.knob_x + pad + pw->panner.knob_width); + r->y = (short) (pw->panner.knob_y + pad + lw); + r->width = pw->panner.shadow_thickness; + r->height = (unsigned short) (pw->panner.knob_height - lw); + r++; + r->x = (short) (pw->panner.knob_x + pad + lw); + r->y = (short) (pw->panner.knob_y + pad + pw->panner.knob_height); + r->width = (unsigned short) (pw->panner.knob_width - lw + + pw->panner.shadow_thickness); + r->height = pw->panner.shadow_thickness; + pw->panner.shadow_valid = TRUE; + return; + } + } + pw->panner.shadow_valid = FALSE; +} + +static void scale_knob (pw, location, size) /* set knob size and/or loc */ + PannerWidget pw; + Boolean location, size; +{ + if (location) { + pw->panner.knob_x = (Position) PANNER_HSCALE (pw, pw->panner.slider_x); + pw->panner.knob_y = (Position) PANNER_VSCALE (pw, pw->panner.slider_y); + } + if (size) { + Dimension width, height; + + if (pw->panner.slider_width < 1) { + pw->panner.slider_width = pw->panner.canvas_width; + } + if (pw->panner.slider_height < 1) { + pw->panner.slider_height = pw->panner.canvas_height; + } + width = Min (pw->panner.slider_width, pw->panner.canvas_width); + height = Min (pw->panner.slider_height, pw->panner.canvas_height); + + pw->panner.knob_width = (Dimension) PANNER_HSCALE (pw, width); + pw->panner.knob_height = (Dimension) PANNER_VSCALE (pw, height); + } + if (!pw->panner.allow_off) check_knob (pw, TRUE); + move_shadow (pw); +} + +static void rescale (pw) + PannerWidget pw; +{ + int hpad = pw->panner.internal_border * 2; + int vpad = hpad; + + if (pw->panner.canvas_width < 1) + pw->panner.canvas_width = pw->core.width; + if (pw->panner.canvas_height < 1) + pw->panner.canvas_height = pw->core.height; + + if ((int)pw->core.width <= hpad) hpad = 0; + if ((int)pw->core.height <= vpad) vpad = 0; + + pw->panner.haspect = ((double) pw->core.width - hpad) / + (double) pw->panner.canvas_width; + pw->panner.vaspect = ((double) pw->core.height - vpad) / + (double) pw->panner.canvas_height; + scale_knob (pw, TRUE, TRUE); +} + + +static void get_default_size (pw, wp, hp) + PannerWidget pw; + Dimension *wp, *hp; +{ + Dimension pad = pw->panner.internal_border * 2; + *wp = PANNER_DSCALE (pw, pw->panner.canvas_width) + pad; + *hp = PANNER_DSCALE (pw, pw->panner.canvas_height) + pad; +} + +static Boolean get_event_xy (pw, event, x, y) + PannerWidget pw; + XEvent *event; + int *x, *y; +{ + int pad = pw->panner.internal_border; + + switch (event->type) { + case ButtonPress: + case ButtonRelease: + *x = event->xbutton.x - pad; + *y = event->xbutton.y - pad; + return TRUE; + + case KeyPress: + case KeyRelease: + *x = event->xkey.x - pad; + *y = event->xkey.y - pad; + return TRUE; + + case EnterNotify: + case LeaveNotify: + *x = event->xcrossing.x - pad; + *y = event->xcrossing.y - pad; + return TRUE; + + case MotionNotify: + *x = event->xmotion.x - pad; + *y = event->xmotion.y - pad; + return TRUE; + } + + return FALSE; +} + +static int parse_page_string (s, pagesize, canvassize, relative) + char *s; + int pagesize, canvassize; + Boolean *relative; +{ + char *cp; + double val = 1.0; + Boolean rel = FALSE; + + /* + * syntax: spaces [+-] number spaces [pc\0] spaces + */ + + for (; isascii(*s) && isspace(*s); s++) ; /* skip white space */ + + if (*s == '+' || *s == '-') { /* deal with signs */ + rel = TRUE; + if (*s == '-') val = -1.0; + s++; + } + if (!*s) { /* if null then return nothing */ + *relative = TRUE; + return 0; + } + + /* skip over numbers */ + for (cp = s; isascii(*s) && (isdigit(*s) || *s == '.'); s++) ; + val *= atof (cp); + + /* skip blanks */ + for (; isascii(*s) && isspace(*s); s++) ; + + if (*s) { /* if units */ + switch (s[0]) { + case 'p': case 'P': + val *= (double) pagesize; + break; + + case 'c': case 'C': + val *= (double) canvassize; + break; + } + } + *relative = rel; + return ((int) val); +} + + +#define DRAW_TMP(pw) \ +{ \ + XDrawRectangle (XtDisplay(pw), XtWindow(pw), \ + pw->panner.xor_gc, \ + (int) (pw->panner.tmp.x + pw->panner.internal_border), \ + (int) (pw->panner.tmp.y + pw->panner.internal_border), \ + (unsigned int) (pw->panner.knob_width - 1), \ + (unsigned int) (pw->panner.knob_height - 1)); \ + pw->panner.tmp.showing = !pw->panner.tmp.showing; \ +} + +#define UNDRAW_TMP(pw) \ +{ \ + if (pw->panner.tmp.showing) DRAW_TMP(pw); \ +} + +#define BACKGROUND_STIPPLE(pw) \ + XmuLocatePixmapFile (pw->core.screen, pw->panner.stipple_name, \ + pw->panner.shadow_color, pw->core.background_pixel, \ + pw->core.depth, NULL, 0, NULL, NULL, NULL, NULL) + +#define PIXMAP_OKAY(pm) ((pm) != None && (pm) != XtUnspecifiedPixmap) + + +/***************************************************************************** + * * + * panner class methods * + * * + *****************************************************************************/ + + +/*ARGSUSED*/ +static void Initialize (greq, gnew, args, num_args) + Widget greq, gnew; + ArgList args; + Cardinal *num_args; +{ + PannerWidget req = (PannerWidget) greq, new = (PannerWidget) gnew; + Dimension defwidth, defheight; + + if (req->panner.canvas_width < 1) new->panner.canvas_width = 1; + if (req->panner.canvas_height < 1) new->panner.canvas_height = 1; + if (req->panner.default_scale < 1) + new->panner.default_scale = PANNER_DEFAULT_SCALE; + + get_default_size (req, &defwidth, &defheight); + if (req->core.width < 1) new->core.width = defwidth; + if (req->core.height < 1) new->core.height = defheight; + + new->panner.shadow_gc = NULL; + reset_shadow_gc (new); /* shadowColor */ + new->panner.slider_gc = NULL; + reset_slider_gc (new); /* foreground */ + new->panner.xor_gc = NULL; + reset_xor_gc (new); /* foreground ^ background */ + + rescale (new); /* does a position check */ + new->panner.shadow_valid = FALSE; + new->panner.tmp.doing = FALSE; + new->panner.tmp.showing = FALSE; +} + + +static void Realize (gw, valuemaskp, attr) + Widget gw; + XtValueMask *valuemaskp; + XSetWindowAttributes *attr; +{ + PannerWidget pw = (PannerWidget) gw; + Pixmap pm = XtUnspecifiedPixmap; + Boolean gotpm = FALSE; + + if (pw->core.background_pixmap == XtUnspecifiedPixmap) { + if (pw->panner.stipple_name) pm = BACKGROUND_STIPPLE (pw); + + if (PIXMAP_OKAY(pm)) { + attr->background_pixmap = pm; + *valuemaskp |= CWBackPixmap; + *valuemaskp &= ~CWBackPixel; + gotpm = TRUE; + } + } + (*pannerWidgetClass->core_class.superclass->core_class.realize) + (gw, valuemaskp, attr); + + if (gotpm) XFreePixmap (XtDisplay(gw), pm); +} + + +static void Destroy (gw) + Widget gw; +{ + PannerWidget pw = (PannerWidget) gw; + + XtReleaseGC (gw, pw->panner.shadow_gc); + XtReleaseGC (gw, pw->panner.slider_gc); + XtReleaseGC (gw, pw->panner.xor_gc); +} + + +static void Resize (gw) + Widget gw; +{ + rescale ((PannerWidget) gw); +} + + +/* ARGSUSED */ +static void Redisplay (gw, event, region) + Widget gw; + XEvent *event; + Region region; +{ + PannerWidget pw = (PannerWidget) gw; + Display *dpy = XtDisplay(gw); + Window w = XtWindow(gw); + int pad = pw->panner.internal_border; + Dimension lw = pw->panner.line_width; + Dimension extra = pw->panner.shadow_thickness + lw * 2; + int kx = pw->panner.knob_x + pad, ky = pw->panner.knob_y + pad; + + pw->panner.tmp.showing = FALSE; + XClearArea (XtDisplay(pw), XtWindow(pw), + (int) pw->panner.last_x - ((int) lw) + pad, + (int) pw->panner.last_y - ((int) lw) + pad, + (unsigned int) (pw->panner.knob_width + extra), + (unsigned int) (pw->panner.knob_height + extra), + False); + pw->panner.last_x = pw->panner.knob_x; + pw->panner.last_y = pw->panner.knob_y; + + XFillRectangle (dpy, w, pw->panner.slider_gc, kx, ky, + pw->panner.knob_width - 1, pw->panner.knob_height - 1); + + if (lw) + { + XDrawRectangle (dpy, w, pw->panner.shadow_gc, kx, ky, + (unsigned int) (pw->panner.knob_width - 1), + (unsigned int) (pw->panner.knob_height - 1)); + } + + if (pw->panner.shadow_valid) { + XFillRectangles (dpy, w, pw->panner.shadow_gc, + pw->panner.shadow_rects, 2); + } + if (pw->panner.tmp.doing && pw->panner.rubber_band) DRAW_TMP (pw); +} + + +/* ARGSUSED */ +static Boolean SetValues (gcur, greq, gnew, args, num_args) + Widget gcur, greq, gnew; + ArgList args; + Cardinal *num_args; +{ + PannerWidget cur = (PannerWidget) gcur; + PannerWidget new = (PannerWidget) gnew; + Boolean redisplay = FALSE; + + if (cur->panner.foreground != new->panner.foreground) { + reset_slider_gc (new); + if (cur->panner.foreground != cur->core.background_pixel) + reset_xor_gc (new); + redisplay = TRUE; + } else if (cur->panner.line_width != new->panner.line_width || + cur->core.background_pixel != new->core.background_pixel) { + reset_xor_gc (new); + redisplay = TRUE; + } + if (cur->panner.shadow_color != new->panner.shadow_color) { + reset_shadow_gc (new); + if (cur->panner.foreground == cur->core.background_pixel) + reset_xor_gc (new); + redisplay = TRUE; + } + if (cur->panner.shadow_thickness != new->panner.shadow_thickness) { + move_shadow (new); + redisplay = TRUE; + } + if (cur->panner.rubber_band != new->panner.rubber_band) { + reset_xor_gc (new); + if (new->panner.tmp.doing) redisplay = TRUE; + } + + if ((cur->panner.stipple_name != new->panner.stipple_name || + cur->panner.shadow_color != new->panner.shadow_color || + cur->core.background_pixel != new->core.background_pixel) && + XtIsRealized(gnew)) { + Pixmap pm = (new->panner.stipple_name ? BACKGROUND_STIPPLE (new) + : XtUnspecifiedPixmap); + + if (PIXMAP_OKAY(pm)) { + XSetWindowBackgroundPixmap (XtDisplay (new), XtWindow(new), pm); + XFreePixmap (XtDisplay (new), pm); + } else { + XSetWindowBackground (XtDisplay (new), XtWindow(new), + new->core.background_pixel); + } + redisplay = TRUE; + } + + if (new->panner.resize_to_pref && + (cur->panner.canvas_width != new->panner.canvas_width || + cur->panner.canvas_height != new->panner.canvas_height || + cur->panner.resize_to_pref != new->panner.resize_to_pref)) { + get_default_size (new, &new->core.width, &new->core.height); + redisplay = TRUE; + } else if (cur->panner.canvas_width != new->panner.canvas_width || + cur->panner.canvas_height != new->panner.canvas_height || + cur->panner.internal_border != new->panner.internal_border) { + rescale (new); /* does a scale_knob as well */ + redisplay = TRUE; + } else { + Boolean loc = (cur->panner.slider_x != new->panner.slider_x || + cur->panner.slider_y != new->panner.slider_y); + Boolean siz = (cur->panner.slider_width != new->panner.slider_width || + cur->panner.slider_height != new->panner.slider_height); + if (loc || siz || + (cur->panner.allow_off != new->panner.allow_off && + new->panner.allow_off)) { + scale_knob (new, loc, siz); + redisplay = TRUE; + } + } + + return redisplay; +} + +static void SetValuesAlmost (gold, gnew, req, reply) + Widget gold, gnew; + XtWidgetGeometry *req, *reply; +{ + if (reply->request_mode == 0) { /* got turned down, so cope */ + Resize (gnew); + } + (*pannerWidgetClass->core_class.superclass->core_class.set_values_almost) + (gold, gnew, req, reply); +} + +static XtGeometryResult QueryGeometry (gw, intended, pref) + Widget gw; + XtWidgetGeometry *intended, *pref; +{ + PannerWidget pw = (PannerWidget) gw; + + pref->request_mode = (CWWidth | CWHeight); + get_default_size (pw, &pref->width, &pref->height); + + if (((intended->request_mode & (CWWidth | CWHeight)) == + (CWWidth | CWHeight)) && + intended->width == pref->width && + intended->height == pref->height) + return XtGeometryYes; + else if (pref->width == pw->core.width && pref->height == pw->core.height) + return XtGeometryNo; + else + return XtGeometryAlmost; +} + + +/***************************************************************************** + * * + * panner action procs * + * * + *****************************************************************************/ + +/* ARGSUSED */ +static void ActionStart (gw, event, params, num_params) + Widget gw; + XEvent *event; + String *params; /* unused */ + Cardinal *num_params; /* unused */ +{ + PannerWidget pw = (PannerWidget) gw; + int x, y; + + if (!get_event_xy (pw, event, &x, &y)) { + XBell (XtDisplay(gw), 0); /* should do error message */ + return; + } + + pw->panner.tmp.doing = TRUE; + pw->panner.tmp.startx = pw->panner.knob_x; + pw->panner.tmp.starty = pw->panner.knob_y; + pw->panner.tmp.dx = (((Position) x) - pw->panner.knob_x); + pw->panner.tmp.dy = (((Position) y) - pw->panner.knob_y); + pw->panner.tmp.x = pw->panner.knob_x; + pw->panner.tmp.y = pw->panner.knob_y; + if (pw->panner.rubber_band) DRAW_TMP (pw); +} + +/* ARGSUSED */ +static void ActionStop (gw, event, params, num_params) + Widget gw; + XEvent *event; + String *params; /* unused */ + Cardinal *num_params; /* unused */ +{ + PannerWidget pw = (PannerWidget) gw; + int x, y; + + if (get_event_xy (pw, event, &x, &y)) { + pw->panner.tmp.x = ((Position) x) - pw->panner.tmp.dx; + pw->panner.tmp.y = ((Position) y) - pw->panner.tmp.dy; + if (!pw->panner.allow_off) check_knob (pw, FALSE); + } + if (pw->panner.rubber_band) UNDRAW_TMP (pw); + pw->panner.tmp.doing = FALSE; +} + +/* ARGSUSED */ +static void ActionAbort (gw, event, params, num_params) + Widget gw; + XEvent *event; + String *params; /* unused */ + Cardinal *num_params; /* unused */ +{ + PannerWidget pw = (PannerWidget) gw; + + if (!pw->panner.tmp.doing) return; + + if (pw->panner.rubber_band) UNDRAW_TMP (pw); + + if (!pw->panner.rubber_band) { /* restore old position */ + pw->panner.tmp.x = pw->panner.tmp.startx; + pw->panner.tmp.y = pw->panner.tmp.starty; + ActionNotify (gw, event, params, num_params); + } + pw->panner.tmp.doing = FALSE; +} + + +/* ARGSUSED */ +static void ActionMove (gw, event, params, num_params) + Widget gw; + XEvent *event; /* must be a motion event */ + String *params; /* unused */ + Cardinal *num_params; /* unused */ +{ + PannerWidget pw = (PannerWidget) gw; + int x, y; + + if (!pw->panner.tmp.doing) return; + + if (!get_event_xy (pw, event, &x, &y)) { + XBell (XtDisplay(gw), 0); /* should do error message */ + return; + } + + if (pw->panner.rubber_band) UNDRAW_TMP (pw); + pw->panner.tmp.x = ((Position) x) - pw->panner.tmp.dx; + pw->panner.tmp.y = ((Position) y) - pw->panner.tmp.dy; + + if (!pw->panner.rubber_band) { + ActionNotify (gw, event, params, num_params); /* does a check */ + } else { + if (!pw->panner.allow_off) check_knob (pw, FALSE); + DRAW_TMP (pw); + } +} + + +/* ARGSUSED */ +static void ActionPage (gw, event, params, num_params) + Widget gw; + XEvent *event; /* unused */ + String *params; + Cardinal *num_params; /* unused */ +{ + PannerWidget pw = (PannerWidget) gw; + Cardinal zero = 0; + Boolean isin = pw->panner.tmp.doing; + int x, y; + Boolean relx, rely; + int pad = pw->panner.internal_border * 2; + + if (*num_params != 2) { + XBell (XtDisplay(gw), 0); + return; + } + + x = parse_page_string (params[0], (int) pw->panner.knob_width, + ((int) pw->core.width) - pad, &relx); + y = parse_page_string (params[1], (int) pw->panner.knob_height, + ((int) pw->core.height) - pad, &rely); + + if (relx) x += pw->panner.knob_x; + if (rely) y += pw->panner.knob_y; + + if (isin) { /* if in, then use move */ + XEvent ev; + ev.xbutton.type = ButtonPress; + ev.xbutton.x = x; + ev.xbutton.y = y; + ActionMove (gw, &ev, (String *) NULL, &zero); + } else { /* else just do it */ + pw->panner.tmp.doing = TRUE; + pw->panner.tmp.x = x; + pw->panner.tmp.y = y; + ActionNotify (gw, event, (String *) NULL, &zero); + pw->panner.tmp.doing = FALSE; + } +} + + +/* ARGSUSED */ +static void ActionNotify (gw, event, params, num_params) + Widget gw; + XEvent *event; /* unused */ + String *params; /* unused */ + Cardinal *num_params; /* unused */ +{ + PannerWidget pw = (PannerWidget) gw; + + if (!pw->panner.tmp.doing) return; + + if (!pw->panner.allow_off) check_knob (pw, FALSE); + pw->panner.knob_x = pw->panner.tmp.x; + pw->panner.knob_y = pw->panner.tmp.y; + move_shadow (pw); + + pw->panner.slider_x = (Position) (((double) pw->panner.knob_x) / + pw->panner.haspect + 0.5); + pw->panner.slider_y = (Position) (((double) pw->panner.knob_y) / + pw->panner.vaspect + 0.5); + if (!pw->panner.allow_off) { + Position tmp; + + if (pw->panner.slider_x > + (tmp = (((Position) pw->panner.canvas_width) - + ((Position) pw->panner.slider_width)))) + pw->panner.slider_x = tmp; + if (pw->panner.slider_x < 0) pw->panner.slider_x = 0; + if (pw->panner.slider_y > + (tmp = (((Position) pw->panner.canvas_height) - + ((Position) pw->panner.slider_height)))) + pw->panner.slider_y = tmp; + if (pw->panner.slider_y < 0) pw->panner.slider_y = 0; + } + + if (pw->panner.last_x != pw->panner.knob_x || + pw->panner.last_y != pw->panner.knob_y) { + XawPannerReport rep; + + Redisplay (gw, (XEvent*) NULL, (Region) NULL); + rep.changed = (XawPRSliderX | XawPRSliderY); + rep.slider_x = pw->panner.slider_x; + rep.slider_y = pw->panner.slider_y; + rep.slider_width = pw->panner.slider_width; + rep.slider_height = pw->panner.slider_height; + rep.canvas_width = pw->panner.canvas_width; + rep.canvas_height = pw->panner.canvas_height; + XtCallCallbackList (gw, pw->panner.report_callbacks, (XtPointer) &rep); + } +} + +/* ARGSUSED */ +static void ActionSet (gw, event, params, num_params) + Widget gw; + XEvent *event; /* unused */ + String *params; + Cardinal *num_params; +{ + PannerWidget pw = (PannerWidget) gw; + Boolean rb; + + if (*num_params < 2 || + XmuCompareISOLatin1 (params[0], "rubberband") != 0) { + XBell (XtDisplay(gw), 0); + return; + } + + if (XmuCompareISOLatin1 (params[1], "on") == 0) { + rb = TRUE; + } else if (XmuCompareISOLatin1 (params[1], "off") == 0) { + rb = FALSE; + } else if (XmuCompareISOLatin1 (params[1], "toggle") == 0) { + rb = !pw->panner.rubber_band; + } else { + XBell (XtDisplay(gw), 0); + return; + } + + if (rb != pw->panner.rubber_band) { + Arg args[1]; + XtSetArg (args[0], XtNrubberBand, rb); + XtSetValues (gw, args, (Cardinal) 1); + } +} diff --git a/src/Panner.h b/src/Panner.h new file mode 100644 index 0000000..ed0cdfe --- /dev/null +++ b/src/Panner.h @@ -0,0 +1,108 @@ +/* + * $XConsortium: Panner.h,v 1.22 94/04/17 20:12:32 rws Exp $ + * +Copyright (c) 1989 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + * Author: Jim Fulton, MIT X Consortium + */ + +#ifndef _XawPanner_h +#define _XawPanner_h + +#include <X11/Xaw3d/Reports.h> + +/***************************************************************************** + * + * Panner Widget (subclass of Simple) + * + * This widget is used to represent navigation in a 2d coordinate system. + * + * Parameters: + * + * Name Class Type Default + * ---- ----- ---- ------- + * + * allowOff AllowOff Boolean FALSE + * background Background Pixel XtDefaultBackground + * backgroundStipple BackgroundStipple String NULL + * canvasWidth CanvasWidth Dimension 0 + * canvasHeight CanvasHeight Dimension 0 + * defaultScale DefaultScale Dimension 8 percent + * foreground Foreground Pixel XtDefaultBackground + * internalSpace InternalSpace Dimension 4 + * lineWidth LineWidth Dimension 0 + * reportCallback ReportCallback XtCallbackList NULL + * resize Resize Boolean TRUE + * rubberBand RubberBand Boolean FALSE + * shadowColor ShadowColor Pixel XtDefaultForeground + * shadowThickness ShadowThickness Dimension 2 + * sliderX SliderX Position 0 + * sliderY SliderY Position 0 + * sliderWidth SliderWidth Dimension 0 + * sliderHeight SliderHeight Dimension 0 + * + *****************************************************************************/ + + /* new instance and class names */ +#ifndef _XtStringDefs_h_ +#define XtNresize "resize" +#define XtCResize "Resize" +#endif + +#define XtNallowOff "allowOff" +#define XtCAllowOff "AllowOff" +#define XtNbackgroundStipple "backgroundStipple" +#define XtCBackgroundStipple "BackgroundStipple" +#define XtNdefaultScale "defaultScale" +#define XtCDefaultScale "DefaultScale" +#define XtNcanvasWidth "canvasWidth" +#define XtCCanvasWidth "CanvasWidth" +#define XtNcanvasHeight "canvasHeight" +#define XtCCanvasHeight "CanvasHeight" +#define XtNinternalSpace "internalSpace" +#define XtCInternalSpace "InternalSpace" +#define XtNlineWidth "lineWidth" +#define XtCLineWidth "LineWidth" +#define XtNrubberBand "rubberBand" +#define XtCRubberBand "RubberBand" +#define XtNshadowThickness "shadowThickness" +#define XtCShadowThickness "ShadowThickness" +#define XtNshadowColor "shadowColor" +#define XtCShadowColor "ShadowColor" +#define XtNsliderX "sliderX" +#define XtCSliderX "SliderX" +#define XtNsliderY "sliderY" +#define XtCSliderY "SliderY" +#define XtNsliderWidth "sliderWidth" +#define XtCSliderWidth "SliderWidth" +#define XtNsliderHeight "sliderHeight" +#define XtCSliderHeight "SliderHeight" + + /* external declarations */ +extern WidgetClass pannerWidgetClass; + +typedef struct _PannerClassRec *PannerWidgetClass; +typedef struct _PannerRec *PannerWidget; + +#endif /* _XawPanner_h */ diff --git a/src/PannerP.h b/src/PannerP.h new file mode 100644 index 0000000..2662929 --- /dev/null +++ b/src/PannerP.h @@ -0,0 +1,104 @@ +/* + * $XConsortium: PannerP.h,v 1.19 94/04/17 20:12:33 jim Exp $ + * +Copyright (c) 1989 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + * Author: Jim Fulton, MIT X Consortium + */ + +#ifndef _XawPannerP_h +#define _XawPannerP_h + +#include <X11/Xaw3d/Panner.h> +#include <X11/Xaw3d/SimpleP.h> /* parent */ + +typedef struct { /* new fields in widget class */ + int dummy; +} PannerClassPart; + +typedef struct _PannerClassRec { /* Panner widget class */ + CoreClassPart core_class; + SimpleClassPart simple_class; + PannerClassPart panner_class; +} PannerClassRec; + +typedef struct { /* new fields in widget */ + /* resources... */ + XtCallbackList report_callbacks; /* callback/Callback */ + Boolean allow_off; /* allowOff/AllowOff */ + Boolean resize_to_pref; /* resizeToPreferred/Boolean */ + Pixel foreground; /* foreground/Foreground */ + Pixel shadow_color; /* shadowColor/ShadowColor */ + Dimension shadow_thickness; /* shadowThickness/ShadowThickness */ + Dimension default_scale; /* defaultScale/DefaultScale */ + Dimension line_width; /* lineWidth/LineWidth */ + Dimension canvas_width; /* canvasWidth/CanvasWidth */ + Dimension canvas_height; /* canvasHeight/CanvasHeight */ + Position slider_x; /* sliderX/SliderX */ + Position slider_y; /* sliderY/SliderY */ + Dimension slider_width; /* sliderWidth/SliderWidth */ + Dimension slider_height; /* sliderHeight/SliderHeight */ + Dimension internal_border; /* internalBorderWidth/BorderWidth */ + String stipple_name; /* backgroundStipple/BackgroundStipple */ + /* private data... */ + GC slider_gc; /* background of slider */ + GC shadow_gc; /* edge of slider and shadow */ + GC xor_gc; /* for doing XOR tmp graphics */ + double haspect, vaspect; /* aspect ratio of core to canvas */ + Boolean rubber_band; /* true = rubber band, false = move */ + struct { + Boolean doing; /* tmp graphics in progress */ + Boolean showing; /* true if tmp graphics displayed */ + Position startx, starty; /* initial position of slider */ + Position dx, dy; /* offset loc for tmp graphics */ + Position x, y; /* location for tmp graphics */ + } tmp; + Position knob_x, knob_y; /* real upper left of knob in canvas */ + Dimension knob_width, knob_height; /* real size of knob in canvas */ + Boolean shadow_valid; /* true if rects are valid */ + XRectangle shadow_rects[2]; /* location of shadows */ + Position last_x, last_y; /* previous location of knob */ +} PannerPart; + +typedef struct _PannerRec { + CorePart core; + SimplePart simple; + PannerPart panner; +} PannerRec; + +#define PANNER_HSCALE(pw,val) ((pw)->panner.haspect * ((double) (val))) +#define PANNER_VSCALE(pw,val) ((pw)->panner.vaspect * ((double) (val))) + +#define PANNER_DSCALE(pw,val) (Dimension) \ + ((((unsigned long) (val)) * (unsigned long) pw->panner.default_scale) / 100L) +#define PANNER_DEFAULT_SCALE 8 /* percent */ + +#define PANNER_OUTOFRANGE -30000 + +/* + * external declarations + */ +extern PannerClassRec pannerClassRec; + +#endif /* _XawPannerP_h */ diff --git a/src/Porthole.c b/src/Porthole.c new file mode 100644 index 0000000..56ea9a8 --- /dev/null +++ b/src/Porthole.c @@ -0,0 +1,366 @@ +/* + * $XConsortium: Porthole.c,v 1.16 94/04/17 20:12:34 kaleb Exp $ + * +Copyright (c) 1990, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + * Author: Jim Fulton, MIT X Consortium + * + * This widget is a trivial clipping widget. It is typically used with a + * panner or scrollbar to navigate. + */ + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> /* get XtN and XtC defines */ +#include <X11/Xaw3d/XawInit.h> /* get Xaw initialize stuff */ +#include <X11/Xaw3d/PortholeP.h> /* get porthole structs */ +#include <X11/Xmu/Misc.h> /* for MAX */ + + +/* + * resources for the porthole + */ +static XtResource resources[] = { +#define poff(field) XtOffsetOf(PortholeRec, porthole.field) + { XtNreportCallback, XtCReportCallback, XtRCallback, sizeof(XtPointer), + poff(report_callbacks), XtRCallback, (XtPointer) NULL }, +#undef poff +}; + + +/* + * widget class methods used below + */ +static void Realize(); /* set gravity and upcall */ +static void Resize(); /* report new size */ +static XtGeometryResult GeometryManager(); /* deal with child requests */ +static void ChangeManaged(); /* somebody added a new widget */ +static XtGeometryResult QueryGeometry(); /* say how big would like to be */ + +PortholeClassRec portholeClassRec = { + { /* core fields */ + /* superclass */ (WidgetClass) &compositeClassRec, + /* class_name */ "Porthole", + /* widget_size */ sizeof(PortholeRec), + /* class_initialize */ XawInitializeWidgetSet, + /* class_part_initialize */ NULL, + /* class_inited */ FALSE, + /* initialize */ NULL, + /* 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 */ NULL, + /* resize */ Resize, + /* expose */ NULL, + /* set_values */ NULL, + /* 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 */ GeometryManager, + /* change_managed */ ChangeManaged, + /* insert_child */ XtInheritInsertChild, + /* delete_child */ XtInheritDeleteChild, + /* extension */ NULL + }, + { /* porthole fields */ + /* ignore */ 0 + } +}; + +WidgetClass portholeWidgetClass = (WidgetClass) &portholeClassRec; + + +/***************************************************************************** + * * + * utility routines * + * * + *****************************************************************************/ + +static Widget find_child (pw) + PortholeWidget pw; +{ + Widget *children; + int i; + + /* + * Find the managed child on which we should operate. Ignore multiple + * managed children. + */ + for (i = 0, children = pw->composite.children; + i < pw->composite.num_children; i++, children++) { + if (XtIsManaged(*children)) return *children; + } + + return (Widget) NULL; +} + +static void SendReport (pw, changed) + PortholeWidget pw; + unsigned int changed; +{ + Widget child = find_child (pw); + + if (pw->porthole.report_callbacks && child) { + XawPannerReport prep; + + prep.changed = changed; + prep.slider_x = -child->core.x; /* porthole is "inner" */ + prep.slider_y = -child->core.y; /* child is outer since it is larger */ + prep.slider_width = pw->core.width; + prep.slider_height = pw->core.height; + prep.canvas_width = child->core.width; + prep.canvas_height = child->core.height; + XtCallCallbackList ((Widget)pw, pw->porthole.report_callbacks, + (XtPointer) &prep); + } +} + + +static void layout_child (pw, child, geomp, xp, yp, widthp, heightp) + PortholeWidget pw; + Widget child; + XtWidgetGeometry *geomp; + Position *xp, *yp; + Dimension *widthp, *heightp; +{ + Position minx, miny; + + *xp = child->core.x; /* default to current values */ + *yp = child->core.y; + *widthp = child->core.width; + *heightp = child->core.height; + if (geomp) { /* mix in any requested changes */ + if (geomp->request_mode & CWX) *xp = geomp->x; + if (geomp->request_mode & CWY) *yp = geomp->y; + if (geomp->request_mode & CWWidth) *widthp = geomp->width; + if (geomp->request_mode & CWHeight) *heightp = geomp->height; + } + + /* + * Make sure that the child is at least as large as the porthole; there + * is no maximum size. + */ + if (*widthp < pw->core.width) *widthp = pw->core.width; + if (*heightp < pw->core.height) *heightp = pw->core.height; + + /* + * Make sure that the child is still on the screen. Note that this must + * be done *after* the size computation so that we know where to put it. + */ + minx = ((Position) pw->core.width) - ((Position) *widthp); + miny = ((Position) pw->core.height) - ((Position) *heightp); + + if (*xp < minx) *xp = minx; /* keep at lower right corner */ + if (*yp < miny) *yp = miny; + + if (*xp > 0) *xp = 0; /* keep at upper left corner */ + if (*yp > 0) *yp = 0; +} + + + +/***************************************************************************** + * * + * Porthole Widget Class Methods * + * * + *****************************************************************************/ + + +static void Realize (gw, valueMask, attributes) + Widget gw; + Mask *valueMask; + XSetWindowAttributes *attributes; +{ + attributes->bit_gravity = NorthWestGravity; + *valueMask |= CWBitGravity; + + if (gw->core.width < 1) gw->core.width = 1; + if (gw->core.height < 1) gw->core.height = 1; + (*portholeWidgetClass->core_class.superclass->core_class.realize) + (gw, valueMask, attributes); +} + + +static void Resize (gw) + Widget gw; +{ + PortholeWidget pw = (PortholeWidget) gw; + Widget child = find_child (pw); + + /* + * If we have a child, we need to make sure that it is at least as big + * as we are and in the right place. + */ + if (child) { + Position x, y; + Dimension width, height; + + layout_child (pw, child, (XtWidgetGeometry *)NULL, + &x, &y, &width, &height); + XtConfigureWidget (child, x, y, width, height, (Dimension) 0); + } + + SendReport (pw, (unsigned int) (XawPRCanvasWidth | XawPRCanvasHeight)); +} + + +static XtGeometryResult QueryGeometry (gw, intended, preferred) + Widget gw; + XtWidgetGeometry *intended, *preferred; +{ + PortholeWidget pw = (PortholeWidget) gw; + Widget child = find_child (pw); + + if (child) { +#define SIZEONLY (CWWidth | CWHeight) + preferred->request_mode = SIZEONLY; + preferred->width = child->core.width; + preferred->height = child->core.height; + + if (((intended->request_mode & SIZEONLY) == SIZEONLY) && + intended->width == preferred->width && + intended->height == preferred->height) + return XtGeometryYes; + else if (preferred->width == pw->core.width && + preferred->height == pw->core.height) + return XtGeometryNo; + else + return XtGeometryAlmost; +#undef SIZEONLY + } + return XtGeometryNo; +} + + +static XtGeometryResult GeometryManager (w, req, reply) + Widget w; + XtWidgetGeometry *req, *reply; +{ + PortholeWidget pw = (PortholeWidget) w->core.parent; + Widget child = find_child (pw); + Boolean okay = TRUE; + + if (child != w) return XtGeometryNo; /* unknown child */ + + *reply = *req; /* assume we'll grant everything */ + + if ((req->request_mode & CWBorderWidth) && req->border_width != 0) { + reply->border_width = 0; /* require border width of 0 */ + okay = FALSE; + } + + layout_child (pw, child, req, &reply->x, &reply->y, + &reply->width, &reply->height); + + if ((req->request_mode & CWX) && req->x != reply->x) okay = FALSE; + if ((req->request_mode & CWY) && req->x != reply->x) okay = FALSE; + if ((req->request_mode & CWWidth) && req->width != reply->width) + okay = FALSE; + if ((req->request_mode & CWHeight) && req->height != reply->height) + okay = FALSE; + + + /* + * If we failed on anything, simply return without touching widget + */ + if (!okay) return XtGeometryAlmost; + + /* + * If not just doing a query, update widget and send report. Note that + * we will often set fields that weren't requested because we want to keep + * the child visible. + */ + if (!(req->request_mode & XtCWQueryOnly)) { + unsigned int changed = 0; + + if (child->core.x != reply->x) { + changed |= XawPRSliderX; + child->core.x = reply->x; + } + if (child->core.y != reply->y) { + changed |= XawPRSliderY; + child->core.y = reply->y; + } + if (child->core.width != reply->width) { + changed |= XawPRSliderWidth; + child->core.width = reply->width; + } + if (child->core.height != reply->height) { + changed |= XawPRSliderHeight; + child->core.height = reply->height; + } + if (changed) SendReport (pw, changed); + } + + return XtGeometryYes; /* success! */ +} + + +static void ChangeManaged (gw) + Widget gw; +{ + PortholeWidget pw = (PortholeWidget) gw; + Widget child = find_child (pw); /* ignore extra children */ + + if (child) { + if (!XtIsRealized (gw)) { + XtWidgetGeometry geom, retgeom; + + geom.request_mode = 0; + if (pw->core.width == 0) { + geom.width = child->core.width; + geom.request_mode |= CWWidth; + } + if (pw->core.height == 0) { + geom.height = child->core.height; + geom.request_mode |= CWHeight; + } + if (geom.request_mode && + XtMakeGeometryRequest (gw, &geom, &retgeom) == XtGeometryAlmost) { + (void) XtMakeGeometryRequest (gw, &retgeom, (XtWidgetGeometry *)NULL); + } + } + + XtResizeWidget (child, Max (child->core.width, pw->core.width), + Max (child->core.height, pw->core.height), 0); + + SendReport (pw, (unsigned int) XawPRAll); + } +} diff --git a/src/Porthole.h b/src/Porthole.h new file mode 100644 index 0000000..18cac79 --- /dev/null +++ b/src/Porthole.h @@ -0,0 +1,64 @@ +/* + * $XConsortium: Porthole.h,v 1.2 94/04/17 20:12:35 jim Exp $ + * +Copyright (c) 1990 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + * Author: Jim Fulton, MIT X Consortium + */ + +#ifndef _XawPorthole_h +#define _XawPorthole_h + +#include <X11/Xaw3d/Reports.h> + +/***************************************************************************** + * + * Porthole Widget (subclass of Composite) + * + * This widget is similar to a viewport without scrollbars. Child movement + * is done by external panners or scrollbars. + * + * Parameters: + * + * Name Class Type Default + * ---- ----- ---- ------- + * + * background Background Pixel XtDefaultBackground + * border BorderColor Pixel XtDefaultForeground + * borderWidth BorderWidth Dimension 1 + * height Height Dimension 0 + * reportCallback ReportCallback Pointer NULL + * width Width Dimension 0 + * x Position Position 0 + * y Position Position 0 + * + *****************************************************************************/ + + /* external declarations */ + +extern WidgetClass portholeWidgetClass; +typedef struct _PortholeClassRec *PortholeWidgetClass; +typedef struct _PortholeRec *PortholeWidget; + +#endif /* _XawPorthole_h */ diff --git a/src/PortholeP.h b/src/PortholeP.h new file mode 100644 index 0000000..2c1d586 --- /dev/null +++ b/src/PortholeP.h @@ -0,0 +1,65 @@ +/* + * $XConsortium: PortholeP.h,v 1.3 94/04/17 20:12:36 kaleb Exp $ + * +Copyright (c) 1990, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + * Author: Jim Fulton, MIT X Consortium + */ + +#ifndef _XawPortholeP_h +#define _XawPortholeP_h + +#include <X11/Xaw3d/Porthole.h> + +typedef struct { /* new fields in widget class */ + int dummy; +} PortholeClassPart; + +typedef struct _PortholeClassRec { /* Porthole widget class */ + CoreClassPart core_class; + CompositeClassPart composite_class; + PortholeClassPart porthole_class; +} PortholeClassRec; + + +typedef struct { /* new fields in widget */ + /* resources... */ + XtCallbackList report_callbacks; /* callback/Callback */ + /* private data... */ +} PortholePart; + +typedef struct _PortholeRec { + CorePart core; + CompositePart composite; + PortholePart porthole; +} PortholeRec; + + +/* + * external declarations + */ +extern PortholeClassRec portholeClassRec; + + +#endif /* _XawPortholeP_h */ diff --git a/src/README.XAW3D b/src/README.XAW3D new file mode 100644 index 0000000..f77be1b --- /dev/null +++ b/src/README.XAW3D @@ -0,0 +1,544 @@ + + The Three-D Athena Toolkit (Xaw3d) + ---------------------------------- + + This is Release 1.5E of the Xaw3d toolkit (dated March 8, 2003), an + update that fixes some bugs, and adds many features. There were no + public releases of 1.5A through 1.5D. + + I am not Kaleb Keithley. Kaleb has moved on, and no longer supports + Xaw3d; it's my baby now. This distribution is not a fork - it is the + latest update of the One True Xaw3d. + + While not as insistant as Kaleb was, I do suggest you include this + file, as is, with any product that includes Xaw3d, in whole or in + part, in any form. This file is the authoritative documentation for + Xaw3d. + + If you discover bugs not already known, do not contact Kaleb; he's had + no part in this effort. Feel free to contact me; I'll try to respond + in kind. If you're new to the Athena toolkit, understand that it is + highly configurable, and some resources will interact (or not) with + undesirable results. Some of these are bugs, but many are just the + nature of the beast. + + D. J. Hawkey Jr. + _________________________________________________________________ + + Usage: + ------ + + This release of Xaw3d is based on X.Org's X11R6.3 Athena toolkit, with + bits and pieces thrown in from other sources. It is intended to be a + general-purpose replacement for the Athena (Xaw) toolkit. + + In general, you should be able to link almost any Athena-based + application to this Xaw3d Athena toolkit, for a three-dimensional + appearance on most of the widgets. On systems with shared libraries, + you might be able replace your shared libXaw.* with libXaw3d.* to + obtain the appearance without even relinking, but the odds of this + working is slim, and not recommended. + + Applications written for Xaw3d might have to test the library for a + particular feature (see the "Xaw3d build options" section below). To + accomodate this, a private header is installed which reflects the + library's capabilities. Xaw3dP.h contains four definitions that may be + used for this purpose. For example: + + #define XAW_INTERNATIONALIZATION + #define XAW_MULTIPLANE_PIXMAPS + #define XAW_GRAY_BLKWHT_STIPPLES + #undef XAW_ARROW_SCROLLBARS + + Xaw3dP.h need not be included by the application source, as the public + headers that reference any 3D features include this header. The + default configuration is set up to match the capabilities of X.Org's + Xaw toolkit. + + The use of most shadow resources should be intuitive enough, and may + be set or read conventionally (e.g., resource files, editres, + programatically, etc.). The userData resource may be used to "hang" + application-specific data on a widget, but this is accessable to + programs only. Other resources and less-than-obvious features are + documented throughout this file. + + The default resource values present a not-as-pretty-as-it-could-be + appearance, due to stippled shadows (as opposed to allocated colors) + in order to conserve colormap space, and by allowing non-rectangular + pushbuttons, which are not shadowed. To specify otherwise, set these + resources: + + *beNiceToColormap: False + *shapeStyle: Rectangle + + You might also want to remove the borders from some widgets: + + *Text.borderWidth: 0 + *SimpleMenu.borderWidth: 0 + *Paned.internalBorderWidth: 0 + + To revert to reverse-video highlighting in menus: + + *SmeBSB.shadowWidth: 0 + + Note that shadows "grow outward" in the SimpleMenu and Text widgets, + increasing these widgets' sizes, "grow inward" in the Viewport and + Scrollbar widgets, decreasing the size of the clip widget and thumb, + respectively, and "grow inward" in the Label (and superclasses of) and + SmeBSB widgets, encroaching on their label parts. Fat shadows will + probably mean some futzing with size or margin resources for a proper + appearance. + _________________________________________________________________ + + Xaw3d build requirements: + ------------------------- + + Many header files have changed since Release 1.5. This means that any + installed Xaw3d headers must be removed before building this + distribution, to see that these source files include these header + files. Renaming the directory that the existing headers live in is + sufficient. + + Xaw3d build options: + -------------------- + + Like Xaw, the default Xaw3d does not accomodate multi-plane pixmaps. + However, at the top of this distribution's Imakefile are the lines: + + XCOMM For color pixmaps, define MULTIPLANE_PIXMAPS: + #undef MULTIPLANE_PIXMAPS + + If you want color pixmaps, and have Arnaud Le Hors's XPM library + installed, change the "#undef" to "#define". You may then specify + either XPM or XBM files for any Xaw3d bitmap resource, whether by + resource files, with editres, programmatically, etc.. And yes, the + transparency of XPM files is honored. + + Note that this enables the use of structures and functions in the XPM + library; the XPM library include file (xpm.h) must be available when + building Xaw3d, and the XPM library must then be linked to any and all + applications that use Xaw3d. This makes Xaw3d dependant on the XPM + library, so think twice about it. + + The default stippled shadows used when the beNiceToColormap resource + is True work well enough, except for widgets that have black or white + backgrounds. So, at the top of this distribution's Imakefile, are the + lines: + + XCOMM For grayed stipple shadows, define GRAY_BLKWHT_STIPPLES: + #define GRAY_BLKWHT_STIPPLES + + This makes Xaw3d allocate a gray colorcell, and use it in stippled + shadows when 1) widgets have black or white backgrounds and 2) the + beNiceToColormap resource is True and 3) the display allows it. This + option was disabled in previous Xaw3d releases. + + The default Xaw3d does not use arrow scrollbars. At the top of this + distribution's Imakefile are the lines: + + XCOMM For scrollbars with arrows, define ARROW_SCROLLBARS: + #undef ARROW_SCROLLBARS + + If you want arrow-style scrollbars, change the "#undef" to "#define". + Note that the Scrollbar widget's translations and actions will change + accordingly. + + Building Xaw3d within an X11 source tree: + ----------------------------------------- + + This distribution expects a configured X11R6.[1-6] source tree (by + "configured", I mean that the imake infrastructure has been built). + You can use the source from X.Org, XFree86, or the X Project Team. + + Change to the directory containing /xc, and issue these commands: + + # gunzip -c Xaw3d-1.5E.tar.gz | tar -xpf - + # cd xc/lib/Xaw3d + # ../../config/imake/imake -I../../config/cf \ + -DTOPDIR=../.. -DCURDIR=lib/Xaw3d + # make includes; make depend; make; make install + + The Imakefile uses the Xaw symbols in /xc/config/cf, so if you have + debug, shared, profile, etc. libraries specified for Xaw, Xaw3d will + have them as well. + + Building Xaw3d without an X11 source tree: + ------------------------------------------ + + Near the top of this distribution's Imakefile are the lines: + + XCOMM When building outside an X11 source tree: + XCOMM EXTRA_INCLUDES = -I. + + Uncomment the second line by deleting the "XCOMM ". Then, while still + in /xc/lib/Xaw3d, issue these commands: + + # mkdir X11; cd X11; ln -fs .. Xaw3d; cd .. + # xmkmf; make depend; make; make install + + If this works for you, great. If not, well, happy hacking. + + Building Xaw3d under X11R5: + --------------------------- + + I don't know that Xaw3d will build within an X11R5 source tree, so try + the "Building Xaw3d without an X11 source tree" instructions. If the + "make" command results in nothing being built, find these lines about + half-way into this distribution's Imakefile: + + XCOMM At least one X11R5 distribution needs this: + XCOMM #include "Imakefrag.X11R5" + + Uncomment the second line by deleting the "XCOMM ", and re-issue the + "xmkmf; make depend; make; make install" commands. This line will + insert the quoted file into the Makefile, and is for when the imake + configuration files don't create the appropriate rules. + + Xaw3d and Internationalization: + ------------------------------- + + The Imakefile depends on a conventional system-wide definition for + including or omitting I18n support (i.e., "XawI18nDefines"). If the + Imakefile erroneously disables support for I18n (see the generated + Xaw3dP.h file), I can only suggest searching your imake configuration + files for a definition that enables support for "wide characters" (try + `egrep 'WCHAR|WCTYPE|XMBTOWC|ISW_FUNCS' *`), and then, about half-way + into this distribution's Imakefile, find these lines: + + #ifdef XawI18nDefines + #define INTERNATIONALIZATION + HEADERS = $(BASE_HDRS) $(I18N_HDRS) + SRCS = $(BASE_SRCS) $(I18N_SRCS) + OBJS = $(BASE_OBJS) $(I18N_OBJS) + ... + + Change the label in the first line to the label of the definition you + found. If no suitable definition is found, and I18n really is + supported, it's likely implemented in such a way that Xaw3d probably + won't include I18n support without some hacking at the Imakefile or + Makefile. + _________________________________________________________________ + + New in 1.5A: + ------------ + + The SimpleMenu widget now supports scrolling through entries too + numerous to fit on the screen, with a new resource supporting a scroll + jump value. The record variable is simple_menu.jump_val, resourced as + XtNjumpScroll, and classed as XtCJumpScroll. Adapted from an early + neXtaw toolkit. + + Added 3D support to the SimpleMenu, Text, and Viewport widgets. + + Four minor changes in ThreeD.c and SmeThreeD.c to have the widgets use + the app's colormap, rather than the screen's default, for those apps + that create their own. + + Added the deletion of laygram.h to the Imakefile. + + Created Xaw3dP.c, for functions shared by other modules that have no + other appropriate home. + + A new directory containing sample resource files for a few apps. See + the README.AD file in that directory. + + New in 1.5B: + ------------ + + Made Imakefile a bit more friendly to build options. Makefile now + defines the build options in Xaw3dP.h during the build. + + Added to the key translation tables in Panner.c and TextTr.c, and some + rules to Imakefile, to make this distribution X11R5 compliant. Tested + on exactly one X11R5 system; your mileage may vary. + + Made internationalization support conditional, for systems lacking or + broken. Tested on exactly two systems, one with and one without; your + mileage may vary. + + New in 1.5C: + ------------ + + Enabled multi-plane pixmap support with a new Xt resource type + converter. The "Xaw3d build options" section has more information. + + Added private Pixmap resources to the Label and SmeBSB widgets for + stippled copies of the public Pixmap resources (record variables + label.stippled, label.right_stippled, sme_bsb.left_stippled, and + sme_bsb.right_stippled, respectively). Insensitive pixmaps are now + rendered properly. + + New in 1.5D: + ------------ + + Added two resources to the SimpleMenu widget for setting margins. The + SmeBSB widgets have a tighter relationship with their parent and + siblings; menus and their entries now respond properly to changes in + themselves or their parent. See the section "The SimpleMenu widget and + margins" below for a detailed explanation. + + New in 1.5E: + ------------ + + Enabled a new resource in the ThreeD widget to specify one of five + shadow types. The record variable is threeD.relief (the record part is + transparent), resourced as XtNRelief and classed as XtCRelief. It + accepts as values XtReliefNone, XtReliefRaised, XtReliefSunken, + XtReliefRidge, and XtReliefGroove. Note that the Text, SimpleMenu, + Scrollbar, and Viewport widgets ignore this resource, and display only + raised or sunken shadows. Built on the unfinished work of an early + neXtaw toolkit. + + Added support for sub-menus in the SimpleMenu widget. Inspired by the + xfig application, adapted from XFree86's X11R6.6 "Xaw7" toolkit, and + made better than both. See the section "The SimpleMenu widget and + sub-menus" below for usage. + + Added a resource to the SmeBSB widget to specify an underlined + character in the label. The record variable is sme_bsb.underline, + resourced as XtNunderline, and classed as XtCUnderline. It accepts an + integer as an index to the character; a value less than zero or + greater than or equal to the label length inhibits underlining. + Adapted from a recent distribution of the xfig application. + + Made the SmeThreeD widget sensitive to the GRAY_BLKWHT_STIPPLES build + option (see the "Xaw3d build options" section for what this is and + does). + + Added support for "tooltips". Inspired by the xfig application and + adapted from XFree86's X11R6.6 "Xaw7" toolkit. See the section "The + Tip widget" below for usage. + + Fixed some geometry and positioning bugs in the Label widget. It's + internalHeight and internalWidth resources are now used to enforce a + minimum size when it's resize resource is True. The Label (and + superclasses of) widget now resizes properly to changes in label parts + and internal margins (subject to any constraints placed on the + widgets, of course). + + Swapped the top and bottom colors in the stippled pixmap shadows. + + Fixed a shadow drawing bug in the Command widget, when the shape is + changed. + + Fixed the shadow state bug in the SmeBSB widget. + + Dropped support for Linux shared a.out libraries. + _________________________________________________________________ + + Bugs and deficiencies: + ---------------------- + + You may not be be able to replace shared libXaw.* libraries with + libXaw3d.* libraries on systems with SVR3-style shared libraries. + + The lexer in the Layout widget doesn't work well when a program that + uses the Layout widget is linked with GNU's malloc(). This is a + problem on older releases of Linux, where the libc malloc() is is GNU + malloc(). It's also a problem on older releases of FreeBSD if + "ExtraLibraries -lgnumalloc" is specified in imake's FreeBSD.cf + configuration file (this may be a problem on other BSDs too, but I + don't know this as fact). The solution under FreeBSD is to delete the + "ExtraLibraries" line(s) in the vendor.cf configuration file, or edit + the Makefile to not link with "-lgnumalloc". I don't have a solution + for older Linux distributions, nor do I have the time (or inclination) + to figure one out. If you discover a fix, you're more than welcome to + send it in. + + The samples in Layout.h are wrong and don't work. Example programs + written by Keith Packard that use the Layout widget are available at + ftp://ftp.x.org/R5contrib/. + + If an application subclasses Athena's Simple or Sme classes, or + subclasses thereof, there is a high probability that Xaw3d isn't + source compatible. Sorry, I have no plans (or ideas) on how to fix + this. + + Xaw3d pixel allocation may not behave well when beNiceToColormap is + False and the colormap (default or application) is full. + + Non-rectangular Command widgets are not rendered with shadows. + + All geometry management routines should fully account for shadow + widths, but some don't, and it can show. + + A few bugs and ambiguities in the Athena toolkit from which this + distribution is derived have been resolved. While trying to be true to + Athena documentation, these changes may make Xaw3d behave oddly for + some applications. Nothing that can't be fixed by tweaking the + appropriate resources, I'll wager. + + A comment that appears in the xterm source: + ------------------------------------------- + + * + * ...There be serious and nasty dragons here. + * + + xterm is, well, xterm. The auto-scroll with arrow-style scrollbars + won't work in xterm because it relies on timeouts. xterm, perhaps for + speed, circumvents XtAppNextEvent() by using XNextEvent() to get its X + events, with the unfortunate side effect of completely ignoring "other + sources", like timeouts. At this time there is no patch to fix the + X11R6 xterm, but there is a patch for the X11R5 xterm at + ftp://ftp.x.org/contrib/widgets/Xaw3d/R5/; it shouldn't be too hard to + integrate it into the X11R6 sources. + _________________________________________________________________ + + The SimpleMenu widget and margins: + ---------------------------------- + + Two resources have been added to the SimpleMenu widget for margin + management. The record variables are simple_menu.left_whitespace and + simple_menu.right_whitespace, resourced as XtNleftWhitespace and + XtNrightWhitespace, and classed as - yup - XtCLeftWhitespace and + XtCRightWhitespace. They can be also be referenced together by the + class XtCHorizontalWhitespace. + + To illustrate, the leftMargin resource can be different values in each + SmeBSB widget, and SimpleMenu will oblige. If a pixmap wider than the + margin is specified in any SmeBSB widget, the result is less than + desirable (refer to ORA X, Vol 5 Sec 6, SmeBSB.*Bitmap and + SmeBSB.*Margin). Set the leftWhitespace resource in the parent + SimpleMenu widget, and SimpleMenu will set all children SmeBSB + leftMargins to that value. Specify a pixmap of any width for any + SmeBSB child, and SimpleMenu will separate the elements (menu edge, + pixmap, and text) of all SmeBSB children with that minimum distance as + it vertically aligns their text elements. + + The SimpleMenu widget now resizes not only to the above, but also to + changes in these SmeBSB traits: Labels and fonts, pixmaps, and + margins. + + Implementation notes: The SimpleMenu *Whitespace resources override + and replace the values of SmeBSB *Margin resources. To nullify this + behavior, a *Whitespace resource must first be set to zero, and the + corresponding *Margin resources then set appropriately. The *Margin + resources remain unchanged in and of themselves; they behave just as + always when the *Whitespace resources are not used. + + The SimpleMenu widget and sub-menus: + ------------------------------------ + + Resources have been added to the SimpleMenu and SmeBSB widgets to + support sub-menus. The record variables are simple_menu.sub_menu and + simple_menu.state (neither are public), and sme_bsb.menu_name, which + is resourced as XtNmenuName, and classed as XtCMenuName. It's the + latter resource that is used by an application, and by default it is + NULL; menus behave as they always have. When this resource is set to a + menu name, the parent SimpleMenu widget will use the SmeBSB widget as + the entry point to a child SimpleMenu widget, managing it's visibility + and location. No constraints are placed on focus or the pointer. + Consider this code fragment: + + /* create a menu button */ + opsbutton = XtCreateManagedWidget("ops", menuButtonWidgetClass, + parent, NULL, 0); + + /* create a menu for the button */ + opsmenu = XtCreatePopupShell("opsMenu", simpleMenuWidgetClass, + opsbutton, NULL, 0); + XtSetArg(args[0], XtNmenuName, "fileMenu"); + XtSetArg(args[1], XtNrightBitmap, rightArrow); + filebutton = XtCreateManagedWidget("file", smeBSBObjectClass, + opsmenu, args, 2); + XtSetArg(args[0], XtNmenuName, "pageMenu"); + XtSetArg(args[1], XtNrightBitmap, rightArrow); + pagebutton = XtCreateManagedWidget("page", smeBSBObjectClass, + opsmenu, args, 2); + quitbutton = XtCreateManagedWidget("quit", smeBSBObjectClass, + opsmenu, NULL, 0); + + /* create a sub-menu for the first menu item */ + filemenu = XtCreatePopupShell("fileMenu", simpleMenuWidgetClass, + opsmenu, NULL, 0); + openbutton = XtCreateManagedWidget("open", smeBSBObjectClass, + filemenu, NULL, 0); + printbutton = XtCreateManagedWidget("print", smeBSBObjectClass, + filemenu, NULL, 0); + + /* create a sub-menu for the second menu item */ + pagemenu = XtCreatePopupShell("pageMenu", simpleMenuWidgetClass, + opsmenu, NULL, 0); + prevbutton = XtCreateManagedWidget("prev", smeBSBObjectClass, + pagemenu, NULL, 0); + nextbutton = XtCreateManagedWidget("next", smeBSBObjectClass, + pagemenu, NULL, 0); + + The SimpleMenu widget named "opsMenu" will inherit the SimpleMenu + widgets named "fileMenu" and "pageMenu" as children sub-menus. It will + position the first sub-menu next to the SmeBSB widget named "file", + and the second next to the SmeBSB widget named "page". A sub-menu will + be mapped (or unmapped) when the pointer enters (or leaves) the + superior SmeBSB widget. Note that a sub-menu's parent must be the + superior SimpleMenu widget, not the superior SmeBSB widget. The other + resources of SmeBSB widgets are unaffected by the menuName resource. + + The Tip widget: + --------------- + + This Tip widget is not compatable with XFree86's "Xaw7" Tip widget. I + couldn't grok how it links the specified widgets to a Tip widget, nor + how their labels are set. Perhaps it's all done with an "Xaw7" + DisplayList, I don't know. So, this XawTipEnable() function requires a + second parameter, to set the label: + + /* create a menu button */ + opsbutton = XtCreateManagedWidget("ops", menuButtonWidgetClass, + parent, NULL, 0); + + /* add a tooltip */ + XawTipEnable(opsbutton, "Application functions"); + + ... + + /* for some reason, disable the tooltip */ + XawTipDisable(opsbutton); + + The XawTipEnable() function creates a Tip widget (one per screen, as + required), and links the specified widget and label to the correct Tip + widget. Nothing else is required of the application; Tip widgets + manage themselves. The XawTipDisable() function removes the timeout + and event handler, and unmaps the Tip window if necessary, but does + not destroy the widget or its linked list. + + Note that the labels of Tip widgets are set individually, but the + font, colors, margins, etc., can only be set globally, for all Tip + widget instances. For example, a resource file might contain: + + *Tip.font: 7x13bold + *Tip.background: yellow + *Tip.foreground: blue + *Tip.borderColor: blue + + Note also that the *Margin resources of XFree86's "Xaw7" Tip widget + are not in this Tip widget; they have been reduced to internalHeight + and internalWidth resources, like those of the Label widget. + _________________________________________________________________ + + Authors and contributors, in alphabetical order: + ------------------------------------------------ + + Uri Blumenthal <uri@watson.ibm.com> + Dimitrios P. Bouras <dbouras@hol.gr> + David Flanagan <david@ora.com> + D. J. Hawkey Jr. <hawkeyd@visi.com>, current maintainer + Achille Hui <eillihca@drizzle.stanford.edu> + Kaleb S. Keithley <kaleb@keithley.org>, developed and maintained Xaw3d + Alfredo Kojima + Gustaf Neumann <neumann@mohegan.wi-inf.uni-essen.de> + Keith Packard <keithp@ncd.com> + Mark Rawling <mwr@mel.dit.csiro.au> + Heiko Schroeder <heiko@pool.informatik.rwth-aachen.de> + Mike Schulze <mike@cs.curtin.edu.au> + Brian V. Smith <bvsmith@lbl.gov> + Malcolm Strickland <chuck-strickland@orl.mmc.com> + Frank Terhaar-Yonkers <fty@bizarre.trpnc.epa.gov> + Tim Theisen <tim@cs.wisc.edu> + Mitch Trachtenberg <mitch@mta.com> + Jerry Whelan <guru@stasi.bradley.edu> + Robert Withrow <witr@rwwa.com> + Jamie Zawinski <jwz@netscape.com> + + And, of course, all the people at X.Org and XFree86. + diff --git a/src/Repeater.c b/src/Repeater.c new file mode 100644 index 0000000..1467f63 --- /dev/null +++ b/src/Repeater.c @@ -0,0 +1,278 @@ +/* + * $XConsortium: Repeater.c,v 1.11 94/04/17 20:12:37 kaleb Exp $ + * +Copyright (c) 1990, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + * Author: Jim Fulton, MIT X Consortium + * + * This widget is used for press-and-hold style buttons. + */ + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> /* for XtN and XtC defines */ +#include <X11/Xaw3d/XawInit.h> /* for XawInitializeWidgetSet() */ +#include <X11/Xaw3d/RepeaterP.h> /* us */ + +static void tic(); /* clock timeout */ + +#define DO_CALLBACK(rw) \ + XtCallCallbackList ((Widget) rw, rw->command.callbacks, (XtPointer)NULL) + + +#define ADD_TIMEOUT(rw,delay) \ + XtAppAddTimeOut (XtWidgetToApplicationContext ((Widget) rw), \ + (unsigned long) delay, tic, (XtPointer) rw) + +#define CLEAR_TIMEOUT(rw) \ + if ((rw)->repeater.timer) { \ + XtRemoveTimeOut ((rw)->repeater.timer); \ + (rw)->repeater.timer = 0; \ + } + + +/* + * Translations to give user interface of press-notify...-release_or_leave + */ +static char defaultTranslations[] = + "<EnterWindow>: highlight() \n\ + <LeaveWindow>: unhighlight() \n\ + <Btn1Down>: set() start() \n\ + <Btn1Up>: stop() unset() "; + + +/* + * Actions added by this widget + */ +static void ActionStart(), ActionStop(); + +static XtActionsRec actions[] = { + { "start", ActionStart }, /* trigger timers */ + { "stop", ActionStop }, /* clear timers */ +}; + + +/* + * New resources added by this widget + */ +static XtResource resources[] = { +#define off(field) XtOffsetOf(RepeaterRec, repeater.field) + { XtNdecay, XtCDecay, XtRInt, sizeof (int), + off(decay), XtRImmediate, (XtPointer) REP_DEF_DECAY }, + { XtNinitialDelay, XtCDelay, XtRInt, sizeof (int), + off(initial_delay), XtRImmediate, (XtPointer) REP_DEF_INITIAL_DELAY }, + { XtNminimumDelay, XtCMinimumDelay, XtRInt, sizeof (int), + off(minimum_delay), XtRImmediate, (XtPointer) REP_DEF_MINIMUM_DELAY }, + { XtNrepeatDelay, XtCDelay, XtRInt, sizeof (int), + off(repeat_delay), XtRImmediate, (XtPointer) REP_DEF_REPEAT_DELAY }, + { XtNflash, XtCBoolean, XtRBoolean, sizeof (Boolean), + off(flash), XtRImmediate, (XtPointer) FALSE }, + { XtNstartCallback, XtCStartCallback, XtRCallback, sizeof (XtPointer), + off(start_callbacks), XtRImmediate, (XtPointer) NULL }, + { XtNstopCallback, XtCStopCallback, XtRCallback, sizeof (XtPointer), + off(stop_callbacks), XtRImmediate, (XtPointer) NULL }, +#undef off +}; + + +/* + * Class Methods + */ + +static void Initialize(); /* setup private data */ +static void Destroy(); /* clear timers */ +static Boolean SetValues(); /* set resources */ + +RepeaterClassRec repeaterClassRec = { + { /* core fields */ + /* superclass */ (WidgetClass) &commandClassRec, + /* class_name */ "Repeater", + /* widget_size */ sizeof(RepeaterRec), + /* class_initialize */ XawInitializeWidgetSet, + /* class_part_initialize */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ XtInheritRealize, + /* actions */ actions, + /* num_actions */ XtNumber(actions), + /* 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 */ XtInheritExpose, + /* 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 */ defaultTranslations, + /* query_geometry */ XtInheritQueryGeometry, + /* display_accelerator */ XtInheritDisplayAccelerator, + /* extension */ NULL + }, + { /* simple fields */ + /* change_sensitive */ XtInheritChangeSensitive + }, + { /* threeD fields */ + /* shadowdraw */ XtInheritXaw3dShadowDraw + }, + { /* label fields */ + /* ignore */ 0 + }, + { /* command fields */ + /* ignore */ 0 + }, + { /* repeater fields */ + /* ignore */ 0 + } +}; + +WidgetClass repeaterWidgetClass = (WidgetClass) &repeaterClassRec; + + +/***************************************************************************** + * * + * repeater utility routines * + * * + *****************************************************************************/ + +/* ARGSUSED */ +static void tic (client_data, id) + XtPointer client_data; + XtIntervalId *id; +{ + RepeaterWidget rw = (RepeaterWidget) client_data; + + rw->repeater.timer = 0; /* timer is removed */ + if (rw->repeater.flash) { + XtExposeProc expose; + expose = repeaterWidgetClass->core_class.superclass->core_class.expose; + XClearWindow (XtDisplay((Widget) rw), XtWindow((Widget) rw)); + rw->command.set = FALSE; + (*expose) ((Widget) rw, (XEvent *) NULL, (Region) NULL); + XClearWindow (XtDisplay((Widget) rw), XtWindow((Widget) rw)); + rw->command.set = TRUE; + (*expose) ((Widget) rw, (XEvent *) NULL, (Region) NULL); + } + DO_CALLBACK (rw); + + rw->repeater.timer = ADD_TIMEOUT (rw, rw->repeater.next_delay); + + /* decrement delay time, but clamp */ + if (rw->repeater.decay) { + rw->repeater.next_delay -= rw->repeater.decay; + if (rw->repeater.next_delay < rw->repeater.minimum_delay) + rw->repeater.next_delay = rw->repeater.minimum_delay; + } +} + + +/***************************************************************************** + * * + * repeater class methods * + * * + *****************************************************************************/ + +/* ARGSUSED */ +static void Initialize (greq, gnew, args, num_args) + Widget greq, gnew; + ArgList args; + Cardinal *num_args; +{ + RepeaterWidget new = (RepeaterWidget) gnew; + + if (new->repeater.minimum_delay < 0) new->repeater.minimum_delay = 0; + new->repeater.timer = (XtIntervalId) 0; +} + +static void Destroy (gw) + Widget gw; +{ + CLEAR_TIMEOUT ((RepeaterWidget) gw); +} + +/* ARGSUSED */ +static Boolean SetValues (gcur, greq, gnew, args, num_args) + Widget gcur, greq, gnew; + ArgList args; + Cardinal *num_args; +{ + RepeaterWidget cur = (RepeaterWidget) gcur; + RepeaterWidget new = (RepeaterWidget) gnew; + Boolean redisplay = FALSE; + + if (cur->repeater.minimum_delay != new->repeater.minimum_delay) { + if (new->repeater.next_delay < new->repeater.minimum_delay) + new->repeater.next_delay = new->repeater.minimum_delay; + } + + return redisplay; +} + +/***************************************************************************** + * * + * repeater action procs * + * * + *****************************************************************************/ + +/* ARGSUSED */ +static void ActionStart (gw, event, params, num_params) + Widget gw; + XEvent *event; + String *params; /* unused */ + Cardinal *num_params; /* unused */ +{ + RepeaterWidget rw = (RepeaterWidget) gw; + + CLEAR_TIMEOUT (rw); + if (rw->repeater.start_callbacks) + XtCallCallbackList (gw, rw->repeater.start_callbacks, (XtPointer)NULL); + + DO_CALLBACK (rw); + rw->repeater.timer = ADD_TIMEOUT (rw, rw->repeater.initial_delay); + rw->repeater.next_delay = rw->repeater.repeat_delay; +} + + +/* ARGSUSED */ +static void ActionStop (gw, event, params, num_params) + Widget gw; + XEvent *event; + String *params; /* unused */ + Cardinal *num_params; /* unused */ +{ + RepeaterWidget rw = (RepeaterWidget) gw; + + CLEAR_TIMEOUT ((RepeaterWidget) gw); + if (rw->repeater.stop_callbacks) + XtCallCallbackList (gw, rw->repeater.stop_callbacks, (XtPointer)NULL); +} + diff --git a/src/Repeater.h b/src/Repeater.h new file mode 100644 index 0000000..efc07cb --- /dev/null +++ b/src/Repeater.h @@ -0,0 +1,77 @@ +/* + * $XConsortium: Repeater.h,v 1.4 94/04/17 20:12:38 jim Exp $ + * +Copyright (c) 1989 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + * Author: Jim Fulton, MIT X Consortium + */ + +#ifndef _XawRepeater_h +#define _XawRepeater_h + +#include <X11/Xaw3d/Command.h> + +/***************************************************************************** + * + * Repeater Widget (subclass of Command) + * + * This widget is a push button that repeatedly fires when held down. + * + * Parameters: + * + * Name Class Type Default + * ---- ----- ---- ------- + * + * decay Decay int 5 milliseconds + * flash Boolean Boolean FALSE + * initialDelay Delay int 200 milliseconds + * minimumDelay MinimumDelay int 10 milliseconds + * repeatDelay Delay int 50 milliseconds + * startCallback StartCallback XtCallbackList NULL + * stopCallback StopCallback XtCallbackList NULL + * + *****************************************************************************/ + + /* new instance and class names */ +#define XtNdecay "decay" +#define XtCDecay "Decay" +#define XtNinitialDelay "initialDelay" +#define XtCDelay "Delay" +#define XtNminimumDelay "minimumDelay" +#define XtCMinimumDelay "MinimumDelay" +#define XtNrepeatDelay "repeatDelay" +#define XtNflash "flash" +#define XtNstartCallback "startCallback" +#define XtCStartCallback "StartCallback" +#define XtNstopCallback "stopCallback" +#define XtCStopCallback "StopCallback" + + + /* external declarations */ +extern WidgetClass repeaterWidgetClass; + +typedef struct _RepeaterClassRec *RepeaterWidgetClass; +typedef struct _RepeaterRec *RepeaterWidget; + +#endif /* _XawRepeater_h */ diff --git a/src/RepeaterP.h b/src/RepeaterP.h new file mode 100644 index 0000000..4cd0e75 --- /dev/null +++ b/src/RepeaterP.h @@ -0,0 +1,82 @@ +/* + * $XConsortium: RepeaterP.h,v 1.4 94/04/17 20:12:39 jim Exp $ + * +Copyright (c) 1989 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + * Author: Jim Fulton, MIT X Consortium + */ + +#ifndef _XawRepeaterP_h +#define _XawRepeaterP_h + +#include <X11/Xaw3d/CommandP.h> +#include <X11/Xaw3d/Repeater.h> + +typedef struct { /* new fields in widget class */ + int dummy; +} RepeaterClassPart; + +typedef struct _RepeaterClassRec { /* Repeater widget class */ + CoreClassPart core_class; + SimpleClassPart simple_class; + ThreeDClassPart threeD_class; + LabelClassPart label_class; + CommandClassPart command_class; + RepeaterClassPart repeater_class; +} RepeaterClassRec; + +typedef struct { /* new fields in widget */ + /* resources... */ + int initial_delay; /* initialDelay/Delay */ + int repeat_delay; /* repeatDelay/Delay */ + int minimum_delay; /* minimumDelay/MinimumDelay */ + int decay; /* decay to minimum delay */ + Boolean flash; /* flash/Boolean */ + XtCallbackList start_callbacks; /* startCallback/StartCallback */ + XtCallbackList stop_callbacks; /* stopCallback/StopCallback */ + /* private data... */ + int next_delay; /* next amount for timer */ + XtIntervalId timer; /* timer that will fire */ +} RepeaterPart; + +typedef struct _RepeaterRec { + CorePart core; + SimplePart simple; + ThreeDPart threeD; + LabelPart label; + CommandPart command; + RepeaterPart repeater; +} RepeaterRec; + +#define REP_DEF_DECAY 5 /* milliseconds */ +#define REP_DEF_INITIAL_DELAY 200 /* milliseconds */ +#define REP_DEF_MINIMUM_DELAY 10 /* milliseconds */ +#define REP_DEF_REPEAT_DELAY 50 /* milliseconds */ + +/* + * external declarations + */ +extern RepeaterClassRec repeaterClassRec; + +#endif /* _XawRepeaterP_h */ diff --git a/src/Reports.h b/src/Reports.h new file mode 100644 index 0000000..0b193c9 --- /dev/null +++ b/src/Reports.h @@ -0,0 +1,55 @@ +/* + * $XConsortium: Reports.h,v 1.4 94/04/17 20:12:39 jim Exp $ + * +Copyright (c) 1990 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + */ + +#ifndef _Xaw_Reports_h +#define _Xaw_Reports_h + +/* + * XawPannerReport - this structure is used by the reportCallback of the + * Panner, Porthole, Viewport, and Scrollbar widgets to report its position. + * All fields must be filled in, although the changed field may be used as + * a hint as to which fields have been altered since the last report. + */ +typedef struct { + unsigned int changed; /* mask, see below */ + Position slider_x, slider_y; /* location of slider within outer */ + Dimension slider_width, slider_height; /* size of slider */ + Dimension canvas_width, canvas_height; /* size of canvas */ +} XawPannerReport; + +#define XawPRSliderX (1 << 0) +#define XawPRSliderY (1 << 1) +#define XawPRSliderWidth (1 << 2) +#define XawPRSliderHeight (1 << 3) +#define XawPRCanvasWidth (1 << 4) +#define XawPRCanvasHeight (1 << 5) +#define XawPRAll (63) /* union of above */ + +#define XtNreportCallback "reportCallback" +#define XtCReportCallback "reportCallback" + +#endif /* _Xaw_Reports_h */ diff --git a/src/Scrollbar.c b/src/Scrollbar.c new file mode 100644 index 0000000..c105688 --- /dev/null +++ b/src/Scrollbar.c @@ -0,0 +1,1169 @@ + +/* MODIFIED ATHENA SCROLLBAR (USING ARROWHEADS AT ENDS OF TRAVEL) */ +/* Modifications Copyright 1992 by Mitch Trachtenberg */ +/* Rights, permissions, and disclaimer of warranty are as in the */ +/* DEC and MIT notice below. */ +/* $XConsortium: Scrollbar.c,v 1.70 91/10/16 21:39:40 eswu Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* ScrollBar.c */ +/* created by weissman, Mon Jul 7 13:20:03 1986 */ +/* converted by swick, Thu Aug 27 1987 */ + +#include "Xaw3dP.h" + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> + +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/ScrollbarP.h> + +#include <X11/Xmu/Drawing.h> + +/* Private definitions. */ + +#ifdef XAW_ARROW_SCROLLBARS +static char defaultTranslations[] = + "<Btn1Down>: NotifyScroll()\n\ + <Btn2Down>: MoveThumb() NotifyThumb() \n\ + <Btn3Down>: NotifyScroll()\n\ + <Btn1Motion>: HandleThumb() \n\ + <Btn3Motion>: HandleThumb() \n\ + <Btn2Motion>: MoveThumb() NotifyThumb() \n\ + <BtnUp>: EndScroll()"; +#else +static char defaultTranslations[] = + "<Btn1Down>: StartScroll(Forward) \n\ + <Btn2Down>: StartScroll(Continuous) MoveThumb() NotifyThumb() \n\ + <Btn3Down>: StartScroll(Backward) \n\ + <Btn2Motion>: MoveThumb() NotifyThumb() \n\ + <BtnUp>: NotifyScroll(Proportional) EndScroll()"; +#ifdef bogusScrollKeys + /* examples */ + "<KeyPress>f: StartScroll(Forward) NotifyScroll(FullLength) EndScroll()" + "<KeyPress>b: StartScroll(Backward) NotifyScroll(FullLength) EndScroll()" +#endif +#endif + +static float floatZero = 0.0; + +#define Offset(field) XtOffsetOf(ScrollbarRec, field) + +static XtResource resources[] = { +#ifdef XAW_ARROW_SCROLLBARS +/* {XtNscrollCursor, XtCCursor, XtRCursor, sizeof(Cursor), + Offset(scrollbar.cursor), XtRString, "crosshair"},*/ +#else + {XtNscrollVCursor, XtCCursor, XtRCursor, sizeof(Cursor), + Offset(scrollbar.verCursor), XtRString, "sb_v_double_arrow"}, + {XtNscrollHCursor, XtCCursor, XtRCursor, sizeof(Cursor), + Offset(scrollbar.horCursor), XtRString, "sb_h_double_arrow"}, + {XtNscrollUCursor, XtCCursor, XtRCursor, sizeof(Cursor), + Offset(scrollbar.upCursor), XtRString, "sb_up_arrow"}, + {XtNscrollDCursor, XtCCursor, XtRCursor, sizeof(Cursor), + Offset(scrollbar.downCursor), XtRString, "sb_down_arrow"}, + {XtNscrollLCursor, XtCCursor, XtRCursor, sizeof(Cursor), + Offset(scrollbar.leftCursor), XtRString, "sb_left_arrow"}, + {XtNscrollRCursor, XtCCursor, XtRCursor, sizeof(Cursor), + Offset(scrollbar.rightCursor), XtRString, "sb_right_arrow"}, +#endif + {XtNlength, XtCLength, XtRDimension, sizeof(Dimension), + Offset(scrollbar.length), XtRImmediate, (XtPointer) 1}, + {XtNthickness, XtCThickness, XtRDimension, sizeof(Dimension), + Offset(scrollbar.thickness), XtRImmediate, (XtPointer) 14}, + {XtNorientation, XtCOrientation, XtROrientation, sizeof(XtOrientation), + Offset(scrollbar.orientation), XtRImmediate, (XtPointer) XtorientVertical}, + {XtNscrollProc, XtCCallback, XtRCallback, sizeof(XtPointer), + Offset(scrollbar.scrollProc), XtRCallback, NULL}, + {XtNthumbProc, XtCCallback, XtRCallback, sizeof(XtPointer), + Offset(scrollbar.thumbProc), XtRCallback, NULL}, + {XtNjumpProc, XtCCallback, XtRCallback, sizeof(XtPointer), + Offset(scrollbar.jumpProc), XtRCallback, NULL}, + {XtNthumb, XtCThumb, XtRBitmap, sizeof(Pixmap), + Offset(scrollbar.thumb), XtRImmediate, (XtPointer) XtUnspecifiedPixmap}, + {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), + Offset(scrollbar.foreground), XtRString, XtDefaultForeground}, + {XtNshown, XtCShown, XtRFloat, sizeof(float), + Offset(scrollbar.shown), XtRFloat, (XtPointer)&floatZero}, + {XtNtopOfThumb, XtCTopOfThumb, XtRFloat, sizeof(float), + Offset(scrollbar.top), XtRFloat, (XtPointer)&floatZero}, + {XtNpickTop, XtCPickTop, XtRBoolean, sizeof(Boolean), + Offset(scrollbar.pick_top), XtRBoolean, (XtPointer) False}, + {XtNminimumThumb, XtCMinimumThumb, XtRDimension, sizeof(Dimension), + Offset(scrollbar.min_thumb), XtRImmediate, (XtPointer) 7} +}; +#undef Offset + +static void ClassInitialize(); +static void Initialize(); +static void Destroy(); +static void Realize(); +static void Resize(); +static void Redisplay(); +static Boolean SetValues(); + +#ifdef XAW_ARROW_SCROLLBARS +static void HandleThumb(); +#else +static void StartScroll(); +#endif +static void MoveThumb(); +static void NotifyThumb(); +static void NotifyScroll(); +static void EndScroll(); + +static XtActionsRec actions[] = { +#ifdef XAW_ARROW_SCROLLBARS + {"HandleThumb", HandleThumb}, +#else + {"StartScroll", StartScroll}, +#endif + {"MoveThumb", MoveThumb}, + {"NotifyThumb", NotifyThumb}, + {"NotifyScroll", NotifyScroll}, + {"EndScroll", EndScroll} +}; + + +ScrollbarClassRec scrollbarClassRec = { + { /* core fields */ + /* superclass */ (WidgetClass) &threeDClassRec, + /* class_name */ "Scrollbar", + /* size */ sizeof(ScrollbarRec), + /* class_initialize */ ClassInitialize, + /* class_part_init */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ Realize, + /* actions */ actions, + /* num_actions */ XtNumber(actions), + /* 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 */ defaultTranslations, + /* query_geometry */ XtInheritQueryGeometry, + /* display_accelerator*/ XtInheritDisplayAccelerator, + /* extension */ NULL + }, + { /* simple fields */ + /* change_sensitive */ XtInheritChangeSensitive + }, + { /* threeD fields */ + /* shadowdraw */ XtInheritXaw3dShadowDraw /*,*/ + /* shadowboxdraw */ /*XtInheritXaw3dShadowBoxDraw*/ + }, + { /* scrollbar fields */ + /* ignore */ 0 + } + +}; + +WidgetClass scrollbarWidgetClass = (WidgetClass)&scrollbarClassRec; + +#define NoButton -1 +#define PICKLENGTH(widget, x, y) \ + ((widget->scrollbar.orientation == XtorientHorizontal) ? x : y) +#define MIN(x,y) ((x) < (y) ? (x) : (y)) +#define MAX(x,y) ((x) > (y) ? (x) : (y)) + +static void ClassInitialize() +{ + XawInitializeWidgetSet(); + XtAddConverter( XtRString, XtROrientation, XmuCvtStringToOrientation, + (XtConvertArgList)NULL, (Cardinal)0 ); +} + +#ifdef XAW_ARROW_SCROLLBARS +/* CHECKIT #define MARGIN(sbw) (sbw)->scrollbar.thickness + (sbw)->threeD.shadow_width */ +#define MARGIN(sbw) (sbw)->scrollbar.thickness +#else +#define MARGIN(sbw) (sbw)->threeD.shadow_width +#endif + +/* + The original Xaw Scrollbar's FillArea *really* relied on the fact that the + server was going to clip at the window boundaries; so the logic was really + rather sloppy. To avoid drawing over the shadows and the arrows requires + some extra care... Hope I didn't make any mistakes. +*/ +static void FillArea (sbw, top, bottom, fill) + ScrollbarWidget sbw; + Position top, bottom; + int fill; +{ + int tlen = bottom - top; /* length of thumb in pixels */ + int sw, margin, floor; + int lx, ly, lw, lh; + + if (bottom <= 0 || bottom <= top) + return; + if ((sw = sbw->threeD.shadow_width) < 0) + sw = 0; + margin = MARGIN (sbw); + floor = sbw->scrollbar.length - margin; + + if (sbw->scrollbar.orientation == XtorientHorizontal) { + lx = ((top < margin) ? margin : top); + ly = sw; + lw = ((bottom > floor) ? floor - top : tlen); +/* CHECKIT lw = (((top + tlen) > floor) ? floor - top : tlen); */ + lh = sbw->core.height - 2 * sw; + } else { + lx = sw; + ly = ((top < margin) ? margin : top); + lw = sbw->core.width - 2 * sw; +/* CHECKIT lh = (((top + tlen) > floor) ? floor - top : tlen); */ + lh = ((bottom > floor) ? floor - top : tlen); + } + if (lh <= 0 || lw <= 0) return; + if (fill) { + XFillRectangle(XtDisplay((Widget) sbw), XtWindow((Widget) sbw), + sbw->scrollbar.gc, + lx, ly, (unsigned int) lw, (unsigned int) lh); + } else { + XClearArea (XtDisplay((Widget) sbw), XtWindow((Widget) sbw), + lx, ly, (unsigned int) lw, (unsigned int) lh, + FALSE); + } +} + +/* Paint the thumb in the area specified by sbw->top and + sbw->shown. The old area is erased. The painting and + erasing is done cleverly so that no flickering will occur. */ + +static void PaintThumb (sbw, event) + ScrollbarWidget sbw; + XEvent *event; +{ + Dimension s = sbw->threeD.shadow_width; + Position oldtop = sbw->scrollbar.topLoc; + Position oldbot = oldtop + sbw->scrollbar.shownLength; + Dimension margin = MARGIN (sbw); + Dimension tzl = sbw->scrollbar.length - margin - margin; + Position newtop, newbot; + Position floor = sbw->scrollbar.length - margin; + + newtop = margin + (int)(tzl * sbw->scrollbar.top); + newbot = newtop + (int)(tzl * sbw->scrollbar.shown); + if (sbw->scrollbar.shown < 1.) newbot++; + if (newbot < newtop + (int)sbw->scrollbar.min_thumb + + 2 * (int)sbw->threeD.shadow_width) + newbot = newtop + sbw->scrollbar.min_thumb + + 2 * sbw->threeD.shadow_width; + if ( newbot >= floor ) { + newtop = floor-(newbot-newtop)+1; + newbot = floor; + } + + sbw->scrollbar.topLoc = newtop; + sbw->scrollbar.shownLength = newbot - newtop; + if (XtIsRealized ((Widget) sbw)) { + /* 3D thumb wanted ? + */ + if (s) + { + if (newtop < oldtop) FillArea(sbw, oldtop, oldtop + s, 0); + if (newtop > oldtop) FillArea(sbw, oldtop, MIN(newtop, oldbot), 0); + if (newbot < oldbot) FillArea(sbw, MAX(newbot, oldtop), oldbot, 0); + if (newbot > oldbot) FillArea(sbw, oldbot - s, oldbot, 0); + + if (sbw->scrollbar.orientation == XtorientHorizontal) + { + _ShadowSurroundedBox((Widget)sbw, (ThreeDWidget)sbw, + newtop, s, newbot, sbw->core.height - s, + sbw->threeD.relief, TRUE); + } + else + { + _ShadowSurroundedBox((Widget)sbw, (ThreeDWidget)sbw, + s, newtop, sbw->core.width - s, newbot, + sbw->threeD.relief, TRUE); + } + } + else + { + /* + Note to Mitch: FillArea is (now) correctly implemented to + not draw over shadows or the arrows. Therefore setting clipmasks + doesn't seem to be necessary. Correct me if I'm wrong! + */ + if (newtop < oldtop) FillArea(sbw, newtop, MIN(newbot, oldtop), 1); + if (newtop > oldtop) FillArea(sbw, oldtop, MIN(newtop, oldbot), 0); + if (newbot < oldbot) FillArea(sbw, MAX(newbot, oldtop), oldbot, 0); + if (newbot > oldbot) FillArea(sbw, MAX(newtop, oldbot), newbot, 1); + } + } +} + +#ifdef XAW_ARROW_SCROLLBARS +static void PaintArrows (sbw) + ScrollbarWidget sbw; +{ + XPoint pt[20]; + Dimension s = sbw->threeD.shadow_width; + Dimension t = sbw->scrollbar.thickness; + Dimension l = sbw->scrollbar.length; + Dimension tms = t - s, lms = l - s; + Dimension tm1 = t - 1; + Dimension lmt = l - t; + Dimension lp1 = lmt + 1; + Dimension sm1 = s - 1; + Dimension t2 = t / 2; + Dimension sa30 = (Dimension)(1.732 * s ); /* cotangent of 30 deg */ + Display *dpy = XtDisplay (sbw); + Window win = XtWindow (sbw); + GC top = sbw->threeD.top_shadow_GC; + GC bot = sbw->threeD.bot_shadow_GC; + + + if (XtIsRealized ((Widget) sbw)) { + /* 3D arrows? + */ + if (s) { + /* upper/right arrow */ + pt[0].x = sm1; pt[0].y = tm1; + pt[1].x = t2; pt[1].y = sm1; + pt[2].x = t2; pt[2].y = s + sa30; + pt[3].x = sm1 + sa30; pt[3].y = tms - 1; + + pt[4].x = sm1; pt[4].y = tm1; + pt[5].x = tms; pt[5].y = tm1; + pt[6].x = t2; pt[6].y = sm1; + pt[7].x = t2; pt[7].y = s + sa30; + pt[8].x = tms - sa30; pt[8].y = tms - 1; + pt[9].x = sm1 + sa30; pt[9].y = tms - 1; + + /* lower/left arrow */ + pt[10].x = tms; pt[10].y = lp1; + pt[11].x = s; pt[11].y = lp1; + pt[12].x = t2; pt[12].y = lms; + pt[13].x = t2; pt[13].y = lms - sa30; + pt[14].x = s + sa30; pt[14].y = lmt + s + 1; + pt[15].x = tms - sa30; pt[15].y = lmt + s + 1; + + pt[16].x = tms; pt[16].y = lp1; + pt[17].x = t2; pt[17].y = lms; + pt[18].x = t2; pt[18].y = lms - sa30; + pt[19].x = tms - sa30; pt[19].y = lmt + s + 1; + + /* horizontal arrows require that x and y coordinates be swapped */ + if (sbw->scrollbar.orientation == XtorientHorizontal) { + int n; + int swap; + for (n = 0; n < 20; n++) { + swap = pt[n].x; + pt[n].x = pt[n].y; + pt[n].y = swap; + } + } + XFillPolygon (dpy, win, top, pt, 4, Complex, CoordModeOrigin); + XFillPolygon (dpy, win, bot, pt + 4, 6, Complex, CoordModeOrigin); + XFillPolygon (dpy, win, top, pt + 10, 6, Complex, CoordModeOrigin); + XFillPolygon (dpy, win, bot, pt + 16, 4, Complex, CoordModeOrigin); + + } else { + pt[0].x = 0; pt[0].y = tm1; + pt[1].x = t; pt[1].y = tm1; + pt[2].x = t2; pt[2].y = 0; + + pt[3].x = 0; pt[3].y = lp1; + pt[4].x = t; pt[4].y = lp1; + pt[5].x = t2; pt[5].y = l; + + /* horizontal arrows require that x and y coordinates be swapped */ + if (sbw->scrollbar.orientation == XtorientHorizontal) { + int n; + int swap; + for (n = 0; n < 6; n++) { + swap = pt[n].x; + pt[n].x = pt[n].y; + pt[n].y = swap; + } + } + /* draw the up/left arrow */ + XFillPolygon (dpy, win, sbw->scrollbar.gc, + pt, 3, + Convex, CoordModeOrigin); + /* draw the down/right arrow */ + XFillPolygon (dpy, win, sbw->scrollbar.gc, + pt+3, 3, + Convex, CoordModeOrigin); + } + } +} +#endif + +/* Function Name: Destroy + * Description: Called as the scrollbar is going away... + * Arguments: w - the scrollbar. + * Returns: nonw + */ +static void Destroy (w) + Widget w; +{ + ScrollbarWidget sbw = (ScrollbarWidget) w; +#ifdef XAW_ARROW_SCROLLBARS + if(sbw->scrollbar.timer_id != (XtIntervalId) 0) + XtRemoveTimeOut (sbw->scrollbar.timer_id); +#endif + XtReleaseGC (w, sbw->scrollbar.gc); +} + +/* Function Name: CreateGC + * Description: Creates the GC. + * Arguments: w - the scrollbar widget. + * Returns: none. + */ + +static void CreateGC (w) + Widget w; +{ + ScrollbarWidget sbw = (ScrollbarWidget) w; + XGCValues gcValues; + XtGCMask mask; + unsigned int depth = 1; + + if (sbw->scrollbar.thumb == XtUnspecifiedPixmap) { + sbw->scrollbar.thumb = XmuCreateStippledPixmap (XtScreen(w), + (Pixel) 1, (Pixel) 0, depth); + } else if (sbw->scrollbar.thumb != None) { + Window root; + int x, y; + unsigned int width, height, bw; + if (XGetGeometry (XtDisplay(w), sbw->scrollbar.thumb, &root, &x, &y, + &width, &height, &bw, &depth) == 0) { + XtAppError (XtWidgetToApplicationContext (w), + "Scrollbar Widget: Could not get geometry of thumb pixmap."); + } + } + + gcValues.foreground = sbw->scrollbar.foreground; + gcValues.background = sbw->core.background_pixel; + mask = GCForeground | GCBackground; + + if (sbw->scrollbar.thumb != None) { + if (depth == 1) { + gcValues.fill_style = FillOpaqueStippled; + gcValues.stipple = sbw->scrollbar.thumb; + mask |= GCFillStyle | GCStipple; + } + else { + gcValues.fill_style = FillTiled; + gcValues.tile = sbw->scrollbar.thumb; + mask |= GCFillStyle | GCTile; + } + } + /* the creation should be non-caching, because */ + /* we now set and clear clip masks on the gc returned */ + sbw->scrollbar.gc = XtGetGC (w, mask, &gcValues); +} + +static void SetDimensions (sbw) + ScrollbarWidget sbw; +{ + if (sbw->scrollbar.orientation == XtorientVertical) { + sbw->scrollbar.length = sbw->core.height; + sbw->scrollbar.thickness = sbw->core.width; + } else { + sbw->scrollbar.length = sbw->core.width; + sbw->scrollbar.thickness = sbw->core.height; + } +} + +/* ARGSUSED */ +static void Initialize( request, new, args, num_args ) + Widget request; /* what the client asked for */ + Widget new; /* what we're going to give him */ + ArgList args; + Cardinal *num_args; +{ + ScrollbarWidget sbw = (ScrollbarWidget) new; + + CreateGC (new); + + if (sbw->core.width == 0) + sbw->core.width = (sbw->scrollbar.orientation == XtorientVertical) + ? sbw->scrollbar.thickness : sbw->scrollbar.length; + + if (sbw->core.height == 0) + sbw->core.height = (sbw->scrollbar.orientation == XtorientHorizontal) + ? sbw->scrollbar.thickness : sbw->scrollbar.length; + + SetDimensions (sbw); +#ifdef XAW_ARROW_SCROLLBARS + sbw->scrollbar.scroll_mode = 0; + sbw->scrollbar.timer_id = (XtIntervalId)0; +#else + sbw->scrollbar.direction = 0; +#endif + sbw->scrollbar.topLoc = 0; + sbw->scrollbar.shownLength = sbw->scrollbar.min_thumb; +} + +static void Realize (w, valueMask, attributes) + Widget w; + Mask *valueMask; + XSetWindowAttributes *attributes; +{ + ScrollbarWidget sbw = (ScrollbarWidget) w; +#ifdef XAW_ARROW_SCROLLBARS + if(sbw->simple.cursor_name == NULL) + XtVaSetValues(w, XtNcursorName, "crosshair", NULL); + /* dont set the cursor of the window to anything */ + *valueMask &= ~CWCursor; +#else + sbw->scrollbar.inactiveCursor = + (sbw->scrollbar.orientation == XtorientVertical) + ? sbw->scrollbar.verCursor + : sbw->scrollbar.horCursor; + + XtVaSetValues (w, XtNcursor, sbw->scrollbar.inactiveCursor, NULL); +#endif + /* + * The Simple widget actually stuffs the value in the valuemask. + */ + + (*scrollbarWidgetClass->core_class.superclass->core_class.realize) + (w, valueMask, attributes); +} + +/* ARGSUSED */ +static Boolean SetValues (current, request, desired, args, num_args) + Widget current, /* what I am */ + request, /* what he wants me to be */ + desired; /* what I will become */ + ArgList args; + Cardinal *num_args; +{ + ScrollbarWidget sbw = (ScrollbarWidget) current; + ScrollbarWidget dsbw = (ScrollbarWidget) desired; + Boolean redraw = FALSE; + +/* + * If these values are outside the acceptable range ignore them... + */ + + if (dsbw->scrollbar.top < 0.0 || dsbw->scrollbar.top > 1.0) + dsbw->scrollbar.top = sbw->scrollbar.top; + + if (dsbw->scrollbar.shown < 0.0 || dsbw->scrollbar.shown > 1.0) + dsbw->scrollbar.shown = sbw->scrollbar.shown; + +/* + * Change colors and stuff... + */ + if (XtIsRealized (desired)) { + if (sbw->scrollbar.foreground != dsbw->scrollbar.foreground || + sbw->core.background_pixel != dsbw->core.background_pixel || + sbw->scrollbar.thumb != dsbw->scrollbar.thumb) { + XtReleaseGC (desired, sbw->scrollbar.gc); + CreateGC (desired); + redraw = TRUE; + } + if (sbw->scrollbar.top != dsbw->scrollbar.top || + sbw->scrollbar.shown != dsbw->scrollbar.shown) + redraw = TRUE; + } + return redraw; +} + +static void Resize (w) + Widget w; +{ + /* ForgetGravity has taken care of background, but thumb may + * have to move as a result of the new size. */ + SetDimensions ((ScrollbarWidget) w); + Redisplay (w, (XEvent*) NULL, (Region)NULL); +} + + +/* ARGSUSED */ +static void Redisplay (w, event, region) + Widget w; + XEvent *event; + Region region; +{ + ScrollbarWidget sbw = (ScrollbarWidget) w; + ScrollbarWidgetClass swclass = (ScrollbarWidgetClass) XtClass (w); + int x, y; + unsigned int width, height; + + (*swclass->threeD_class.shadowdraw) (w, event, region, sbw->threeD.relief, FALSE); + + if (sbw->scrollbar.orientation == XtorientHorizontal) { + x = sbw->scrollbar.topLoc; + y = 1; + width = sbw->scrollbar.shownLength; + height = sbw->core.height - 2; + } else { + x = 1; + y = sbw->scrollbar.topLoc; + width = sbw->core.width - 2; + height = sbw->scrollbar.shownLength; + } + if (region == NULL || + XRectInRegion (region, x, y, width, height) != RectangleOut) { + /* Forces entire thumb to be painted. */ + sbw->scrollbar.topLoc = -(sbw->scrollbar.length + 1); + PaintThumb (sbw, event); + } +#ifdef XAW_ARROW_SCROLLBARS + /* we'd like to be region aware here!!!! */ + PaintArrows (sbw); +#endif + +} + + +static Boolean CompareEvents (oldEvent, newEvent) + XEvent *oldEvent, *newEvent; +{ +#define Check(field) if (newEvent->field != oldEvent->field) return False; + + Check(xany.display); + Check(xany.type); + Check(xany.window); + + switch (newEvent->type) { + case MotionNotify: + Check(xmotion.state); + break; + case ButtonPress: + case ButtonRelease: + Check(xbutton.state); + Check(xbutton.button); + break; + case KeyPress: + case KeyRelease: + Check(xkey.state); + Check(xkey.keycode); + break; + case EnterNotify: + case LeaveNotify: + Check(xcrossing.mode); + Check(xcrossing.detail); + Check(xcrossing.state); + break; + } +#undef Check + + return True; +} + +struct EventData { + XEvent *oldEvent; + int count; +}; + +static Bool PeekNotifyEvent (dpy, event, args) + Display *dpy; + XEvent *event; + char *args; +{ + struct EventData *eventData = (struct EventData*)args; + + return ((++eventData->count == QLength(dpy)) /* since PeekIf blocks */ + || CompareEvents(event, eventData->oldEvent)); +} + + +static Boolean LookAhead (w, event) + Widget w; + XEvent *event; +{ + XEvent newEvent; + struct EventData eventData; + + if (QLength (XtDisplay (w)) == 0) return False; + + eventData.count = 0; + eventData.oldEvent = event; + + XPeekIfEvent (XtDisplay (w), &newEvent, PeekNotifyEvent, (char*)&eventData); + + return CompareEvents (event, &newEvent); +} + + +static void ExtractPosition (event, x, y) + XEvent *event; + Position *x, *y; /* RETURN */ +{ + switch( event->type ) { + case MotionNotify: + *x = event->xmotion.x; + *y = event->xmotion.y; + break; + case ButtonPress: + case ButtonRelease: + *x = event->xbutton.x; + *y = event->xbutton.y; + break; + case KeyPress: + case KeyRelease: + *x = event->xkey.x; + *y = event->xkey.y; + break; + case EnterNotify: + case LeaveNotify: + *x = event->xcrossing.x; + *y = event->xcrossing.y; + break; + default: + *x = 0; *y = 0; + } +} + +#ifdef XAW_ARROW_SCROLLBARS +/* ARGSUSED */ +static void HandleThumb (w, event, params, num_params) + Widget w; + XEvent *event; + String *params; /* unused */ + Cardinal *num_params; /* unused */ +{ + Position x,y; + ScrollbarWidget sbw = (ScrollbarWidget) w; + + ExtractPosition( event, &x, &y ); + /* if the motion event puts the pointer in thumb, call Move and Notify */ + /* also call Move and Notify if we're already in continuous scroll mode */ + if (sbw->scrollbar.scroll_mode == 2 || + (PICKLENGTH (sbw,x,y) >= sbw->scrollbar.topLoc && + PICKLENGTH (sbw,x,y) <= sbw->scrollbar.topLoc + sbw->scrollbar.shownLength)){ + XtCallActionProc(w, "MoveThumb", event, params, *num_params); + XtCallActionProc(w, "NotifyThumb", event, params, *num_params); + } +} + +static void RepeatNotify (client_data, idp) + XtPointer client_data; + XtIntervalId *idp; +{ +#define A_FEW_PIXELS 5 + ScrollbarWidget sbw = (ScrollbarWidget) client_data; + int call_data; + if (sbw->scrollbar.scroll_mode != 1 && sbw->scrollbar.scroll_mode != 3) { + sbw->scrollbar.timer_id = (XtIntervalId) 0; + return; + } + call_data = MAX (A_FEW_PIXELS, sbw->scrollbar.length / 20); + if (sbw->scrollbar.scroll_mode == 1) + call_data = -call_data; + XtCallCallbacks((Widget)sbw, XtNscrollProc, (XtPointer) call_data); + sbw->scrollbar.timer_id = + XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)sbw), + (unsigned long) 150, + RepeatNotify, + client_data); +} + +#else /* XAW_ARROW_SCROLLBARS */ +/* ARGSUSED */ +static void StartScroll (w, event, params, num_params ) + Widget w; + XEvent *event; + String *params; /* direction: Back|Forward|Smooth */ + Cardinal *num_params; /* we only support 1 */ +{ + ScrollbarWidget sbw = (ScrollbarWidget) w; + Cursor cursor; + char direction; + + if (sbw->scrollbar.direction != 0) return; /* if we're already scrolling */ + if (*num_params > 0) + direction = *params[0]; + else + direction = 'C'; + + sbw->scrollbar.direction = direction; + + switch (direction) { + case 'B': + case 'b': + cursor = (sbw->scrollbar.orientation == XtorientVertical) + ? sbw->scrollbar.downCursor + : sbw->scrollbar.rightCursor; + break; + case 'F': + case 'f': + cursor = (sbw->scrollbar.orientation == XtorientVertical) + ? sbw->scrollbar.upCursor + : sbw->scrollbar.leftCursor; + break; + case 'C': + case 'c': + cursor = (sbw->scrollbar.orientation == XtorientVertical) + ? sbw->scrollbar.rightCursor + : sbw->scrollbar.upCursor; + break; + default: + return; /* invalid invocation */ + } + XtVaSetValues (w, XtNcursor, cursor, NULL); + XFlush (XtDisplay (w)); +} +#endif /* XAW_ARROW_SCROLLBARS */ + +/* + * Make sure the first number is within the range specified by the other + * two numbers. + */ + +#ifndef XAW_ARROW_SCROLLBARS +static int InRange(num, small, big) + int num, small, big; +{ + return (num < small) ? small : ((num > big) ? big : num); +} +#endif + +/* + * Same as above, but for floating numbers. + */ + +static float FloatInRange(num, small, big) + float num, small, big; +{ + return (num < small) ? small : ((num > big) ? big : num); +} + + +#ifdef XAW_ARROW_SCROLLBARS +static void NotifyScroll (w, event, params, num_params) + Widget w; + XEvent *event; + String *params; + Cardinal *num_params; +{ + ScrollbarWidget sbw = (ScrollbarWidget) w; + int call_data; + Position x, y; + + if (sbw->scrollbar.scroll_mode == 2 /* if scroll continuous */ + || LookAhead (w, event)) + return; + + ExtractPosition (event, &x, &y); + + if (PICKLENGTH (sbw,x,y) < sbw->scrollbar.thickness) { + /* handle first arrow zone */ + call_data = -MAX (A_FEW_PIXELS, sbw->scrollbar.length / 20); + XtCallCallbacks (w, XtNscrollProc, (XtPointer)(call_data)); + /* establish autoscroll */ + sbw->scrollbar.timer_id = + XtAppAddTimeOut (XtWidgetToApplicationContext (w), + (unsigned long) 300, RepeatNotify, (XtPointer)w); + sbw->scrollbar.scroll_mode = 1; + } else if (PICKLENGTH (sbw,x,y) > sbw->scrollbar.length - sbw->scrollbar.thickness) { + /* handle last arrow zone */ + call_data = MAX (A_FEW_PIXELS, sbw->scrollbar.length / 20); + XtCallCallbacks (w, XtNscrollProc, (XtPointer)(call_data)); + /* establish autoscroll */ + sbw->scrollbar.timer_id = + XtAppAddTimeOut (XtWidgetToApplicationContext (w), + (unsigned long) 300, RepeatNotify, (XtPointer)w); + sbw->scrollbar.scroll_mode = 3; + } else if (PICKLENGTH (sbw, x, y) < sbw->scrollbar.topLoc) { + /* handle zone "above" the thumb */ + call_data = - sbw->scrollbar.length; + XtCallCallbacks (w, XtNscrollProc, (XtPointer)(call_data)); + } else if (PICKLENGTH (sbw, x, y) > sbw->scrollbar.topLoc + sbw->scrollbar.shownLength) { + /* handle zone "below" the thumb */ + call_data = sbw->scrollbar.length; + XtCallCallbacks (w, XtNscrollProc, (XtPointer)(call_data)); + } else + { + /* handle the thumb in the motion notify action */ + } + return; +} +#else /* XAW_ARROW_SCROLLBARS */ +static void NotifyScroll (w, event, params, num_params) + Widget w; + XEvent *event; + String *params; /* style: Proportional|FullLength */ + Cardinal *num_params; /* we only support 1 */ +{ + ScrollbarWidget sbw = (ScrollbarWidget) w; + int call_data; + char style; + Position x, y; + + if (sbw->scrollbar.direction == 0) return; /* if no StartScroll */ + if (LookAhead (w, event)) return; + if (*num_params > 0) + style = *params[0]; + else + style = 'P'; + + switch (style) { + case 'P': /* Proportional */ + case 'p': + ExtractPosition (event, &x, &y); + call_data = + InRange (PICKLENGTH (sbw, x, y), 0, (int) sbw->scrollbar.length); + break; + + case 'F': /* FullLength */ + case 'f': + call_data = sbw->scrollbar.length; + break; + } + switch (sbw->scrollbar.direction) { + case 'B': + case 'b': + call_data = -call_data; + /* fall through */ + + case 'F': + case 'f': + XtCallCallbacks (w, XtNscrollProc, (XtPointer)call_data); + break; + + case 'C': + case 'c': + /* NotifyThumb has already called the thumbProc(s) */ + break; + } +} +#endif /* XAW_ARROW_SCROLLBARS */ + +/* ARGSUSED */ +static void EndScroll(w, event, params, num_params ) + Widget w; + XEvent *event; /* unused */ + String *params; /* unused */ + Cardinal *num_params; /* unused */ +{ + ScrollbarWidget sbw = (ScrollbarWidget) w; + +#ifdef XAW_ARROW_SCROLLBARS + sbw->scrollbar.scroll_mode = 0; + /* no need to remove any autoscroll timeout; it will no-op */ + /* because the scroll_mode is 0 */ + /* but be sure to remove timeout in destroy proc */ +#else + XtVaSetValues (w, XtNcursor, sbw->scrollbar.inactiveCursor, NULL); + XFlush (XtDisplay (w)); + sbw->scrollbar.direction = 0; +#endif +} + +static float FractionLoc (sbw, x, y) + ScrollbarWidget sbw; + int x, y; +{ + float result; + int margin; + float height, width; + + margin = MARGIN (sbw); + x -= margin; + y -= margin; + height = sbw->core.height - 2 * margin; + width = sbw->core.width - 2 * margin; + result = PICKLENGTH (sbw, x / width, y / height); + return FloatInRange(result, 0.0, 1.0); +} + + +static void MoveThumb (w, event, params, num_params) + Widget w; + XEvent *event; + String *params; /* unused */ + Cardinal *num_params; /* unused */ +{ + ScrollbarWidget sbw = (ScrollbarWidget) w; + Position x, y; + float loc, t, s; + +#ifndef XAW_ARROW_SCROLLBARS + if (sbw->scrollbar.direction == 0) return; /* if no StartScroll */ +#endif + + if (LookAhead (w, event)) return; + + if (!event->xmotion.same_screen) return; + + ExtractPosition (event, &x, &y); + loc = FractionLoc (sbw, x, y); + t = sbw->scrollbar.top; + s = sbw->scrollbar.shown; +#ifdef XAW_ARROW_SCROLLBARS + if (sbw->scrollbar.scroll_mode != 2 ) + /* initialize picked position */ + sbw->scrollbar.picked = (FloatInRange( loc, t, t + s ) - t); +#else + sbw->scrollbar.picked = 0.5 * s; +#endif + if (sbw->scrollbar.pick_top) + sbw->scrollbar.top = loc; + else { + sbw->scrollbar.top = loc - sbw->scrollbar.picked; + if (sbw->scrollbar.top < 0.0) sbw->scrollbar.top = 0.0; + } + +#if 0 + /* this breaks many text-line scrolls */ + if (sbw->scrollbar.top + sbw->scrollbar.shown > 1.0) + sbw->scrollbar.top = 1.0 - sbw->scrollbar.shown; +#endif +#ifdef XAW_ARROW_SCROLLBARS + sbw->scrollbar.scroll_mode = 2; /* indicate continuous scroll */ +#endif + PaintThumb (sbw, event); + XFlush (XtDisplay (w)); /* re-draw it before Notifying */ +} + + +/* ARGSUSED */ +static void NotifyThumb (w, event, params, num_params ) + Widget w; + XEvent *event; + String *params; /* unused */ + Cardinal *num_params; /* unused */ +{ + register ScrollbarWidget sbw = (ScrollbarWidget) w; + float top = sbw->scrollbar.top; + +#ifndef XAW_ARROW_SCROLLBARS + if (sbw->scrollbar.direction == 0) return; /* if no StartScroll */ +#endif + + if (LookAhead (w, event)) return; + + /* thumbProc is not pretty, but is necessary for backwards + compatibility on those architectures for which it work{s,ed}; + the intent is to pass a (truncated) float by value. */ +/* #ifdef XAW_ARROW_SCROLLBARS */ + /* This corrects for rounding errors: If the thumb is moved to the end of + the scrollable area sometimes the last line/column is not displayed. + This can happen when the integer number of the top line or leftmost + column to be be displayed is calculated from the float value + sbw->scrollbar.top. The numerical error of this rounding problem is + very small. We therefore add a small value which then forces the + next line/column (the correct one) to be used. Since we can expect + that the resolution of display screens will not be higher then + 10000 text lines/columns we add 1/10000 to the top position. The + intermediate variable `top' is used to avoid erroneous summing up + corrections (can this happen at all?). If the arrows are not displayed + there is no problem since in this case there is always a constant + integer number of pixels the thumb must be moved in order to scroll + to the next line/column. */ + /* Removed the dependancy on scrollbar arrows. Xterm as distributed in + X11R6.6 by The XFree86 Project wants this correction, with or without + the arrows. */ + top += 0.0001; +/* #endif */ + XtCallCallbacks (w, XtNthumbProc, *(XtPointer*)&top); + XtCallCallbacks (w, XtNjumpProc, (XtPointer)&top); +} + + + +/************************************************************ + * + * Public routines. + * + ************************************************************/ + +/* Set the scroll bar to the given location. */ + +#if NeedFunctionPrototypes +void XawScrollbarSetThumb (Widget w, +#if NeedWidePrototypes + double top, double shown) +#else + float top, float shown) +#endif +#else +void XawScrollbarSetThumb (w, top, shown) + Widget w; + float top, shown; +#endif +{ + ScrollbarWidget sbw = (ScrollbarWidget) w; + +#ifdef WIERD + fprintf(stderr,"< XawScrollbarSetThumb w=%p, top=%f, shown=%f\n", + w,top,shown); +#endif + +#ifdef XAW_ARROW_SCROLLBARS + if (sbw->scrollbar.scroll_mode == (char) 2) return; /* if still thumbing */ +#else + if (sbw->scrollbar.direction == 'c') return; /* if still thumbing */ +#endif + + sbw->scrollbar.top = (top > 1.0) ? 1.0 : + (top >= 0.0) ? top : sbw->scrollbar.top; + + sbw->scrollbar.shown = (shown > 1.0) ? 1.0 : + (shown >= 0.0) ? shown : sbw->scrollbar.shown; + + PaintThumb (sbw, NULL); +} + diff --git a/src/Scrollbar.h b/src/Scrollbar.h new file mode 100644 index 0000000..2821018 --- /dev/null +++ b/src/Scrollbar.h @@ -0,0 +1,146 @@ +/* $XConsortium: Scrollbar.h,v 1.7 91/07/26 21:59:31 converse Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _Scrollbar_h +#define _Scrollbar_h + +/**************************************************************** + * + * Scrollbar Widget + * + ****************************************************************/ + +#include <X11/Xmu/Converters.h> +#include <X11/Xfuncproto.h> + +/* Scrollbar resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + accelerators Accelerators AcceleratorTable NULL + ancestorSensitive AncestorSensitive Boolean True + background Background Pixel XtDefaultBackground + backgroundPixmap Pixmap Pixmap XtUnspecifiedPixmap + borderColor BorderColor Pixel XtDefaultForeground + borderPixmap Pixmap Pixmap XtUnspecifiedPixmap + borderWidth BorderWidth Dimension 1 + colormap Colormap Colormap parent's colormap + cursor Cursor Cursor None + cursorName Cursor String NULL + depth Depth int parent's depth + destroyCallback Callback XtCallbackList NULL + foreground Foreground Pixel XtDefaultForeground + height Height Dimension length or thickness + insensitiveBorder Insensitive Pixmap GreyPixmap + jumpProc Callback XtCallbackList NULL + length Length Dimension 1 + mappedWhenManaged MappedWhenManaged Boolean True + minimumThumb MinimumThumb Dimension 7 + orientation Orientation XtOrientation XtorientVertical + pointerColor Foreground Pixel XtDefaultForeground + pointerColorBackground Background Pixel XtDefaultBackground + screen Screen Screen parent's screen + scrollDCursor Cursor Cursor XC_sb_down_arrow + scrollHCursor Cursor Cursor XC_sb_h_double_arrow + scrollLCursor Cursor Cursor XC_sb_left_arrow + scrollProc Callback XtCallbackList NULL + scrollRCursor Cursor Cursor XC_sb_right_arrow + scrollUCursor Cursor Cursor XC_sb_up_arrow + scrollVCursor Cursor Cursor XC_sb_v_double_arrow + sensitive Sensitive Boolean True + shown Shown Float 0.0 + thickness Thickness Dimension 14 + thumb Thumb Bitmap GreyPixmap + thumbProc Callback XtCallbackList NULL + topOfThumb TopOfThumb Float 0.0 + pickTop PickTop Boolean False + translations Translations TranslationTable see source or doc + width Width Dimension thickness or length + x Position Position 0 + y Position Position 0 + +*/ + +/* + * Most things we need are in StringDefs.h + */ + +#define XtCMinimumThumb "MinimumThumb" +#define XtCShown "Shown" +#define XtCTopOfThumb "TopOfThumb" +#define XtCPickTop "PickTop" + +#define XtNminimumThumb "minimumThumb" +#define XtNtopOfThumb "topOfThumb" +#define XtNpickTop "pickTop" + +typedef struct _ScrollbarRec *ScrollbarWidget; +typedef struct _ScrollbarClassRec *ScrollbarWidgetClass; + +extern WidgetClass scrollbarWidgetClass; + +_XFUNCPROTOBEGIN + +extern void XawScrollbarSetThumb( +#if NeedFunctionPrototypes + Widget /* scrollbar */, +#if NeedWidePrototypes + /* float */ double /* top */, + /* float */ double /* shown */ +#else + float /* top */, + float /* shown */ +#endif +#endif +); + +_XFUNCPROTOEND + +#endif /* _Scrollbar_h */ diff --git a/src/ScrollbarP.h b/src/ScrollbarP.h new file mode 100644 index 0000000..d4c8b72 --- /dev/null +++ b/src/ScrollbarP.h @@ -0,0 +1,122 @@ +/* MODIFIED ATHENA SCROLLBAR (USING ARROWHEADS AT ENDS OF TRAVEL) */ +/* Modifications Copyright 1992 by Mitch Trachtenberg */ +/* Rights, permissions, and disclaimer of warranty are as in the */ +/* DEC and MIT notice below. See usage warning in .c file. */ + +/* + * $XConsortium: ScrollbarP.h,v 1.2 90/04/11 17:33:53 jim Exp $ + */ + +/*********************************************************** + +Copyright (c) 1987, 1988 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _ScrollbarP_h +#define _ScrollbarP_h + +#include "Xaw3dP.h" +#include <X11/Xaw3d/Scrollbar.h> +#include <X11/Xaw3d/ThreeDP.h> + +typedef struct { + /* public */ + Pixel foreground; /* thumb foreground color */ + XtOrientation orientation; /* horizontal or vertical */ + XtCallbackList scrollProc; /* proportional scroll */ + XtCallbackList thumbProc; /* jump (to position) scroll */ + XtCallbackList jumpProc; /* same as thumbProc but pass data by ref */ + Pixmap thumb; /* thumb color */ +#ifndef XAW_ARROW_SCROLLBARS + Cursor upCursor; /* scroll up cursor */ + Cursor downCursor; /* scroll down cursor */ + Cursor leftCursor; /* scroll left cursor */ + Cursor rightCursor; /* scroll right cursor */ + Cursor verCursor; /* scroll vertical cursor */ + Cursor horCursor; /* scroll horizontal cursor */ +#endif + float top; /* What percent is above the win's top */ + float shown; /* What percent is shown in the win */ + Dimension length; /* either height or width */ + Dimension thickness; /* either width or height */ + Dimension min_thumb; /* minium size for the thumb. */ + float picked; /* How much of the thumb is picked * + * when scrolling starts */ + + /* private */ +#ifdef XAW_ARROW_SCROLLBARS + XtIntervalId timer_id; /* autorepeat timer; remove on destruction */ + char scroll_mode; /* 0:none 1:up/back 2:track 3:down/forward */ +#else + Cursor inactiveCursor; /* the normal cursor for scrollbar */ + char direction; /* a scroll has started; which direction */ +#endif + GC gc; /* a (shared) gc */ + Position topLoc; /* Pixel that corresponds to top */ + Dimension shownLength; /* Num pixels corresponding to shown */ + Boolean pick_top; /* pick thumb at top or anywhere*/ + +} ScrollbarPart; + +typedef struct _ScrollbarRec { + CorePart core; + SimplePart simple; + ThreeDPart threeD; + ScrollbarPart scrollbar; +} ScrollbarRec; + +typedef struct {int empty;} ScrollbarClassPart; + +typedef struct _ScrollbarClassRec { + CoreClassPart core_class; + SimpleClassPart simple_class; + ThreeDClassPart threeD_class; + ScrollbarClassPart scrollbar_class; +} ScrollbarClassRec; + +extern ScrollbarClassRec scrollbarClassRec; + +#endif /* _ScrollbarP_h */ diff --git a/src/Simple.c b/src/Simple.c new file mode 100644 index 0000000..29cbbc8 --- /dev/null +++ b/src/Simple.c @@ -0,0 +1,299 @@ +/* $XConsortium: Simple.c,v 1.36 94/04/17 20:12:43 kaleb Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#include "Xaw3dP.h" +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/SimpleP.h> +#include <X11/Xmu/Drawing.h> + +#define offset(field) XtOffsetOf(SimpleRec, simple.field) + +static XtResource resources[] = { + {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor), + offset(cursor), XtRImmediate, (XtPointer) None}, + {XtNinsensitiveBorder, XtCInsensitive, XtRPixmap, sizeof(Pixmap), + offset(insensitive_border), XtRImmediate, (XtPointer) NULL}, + {XtNpointerColor, XtCForeground, XtRPixel, sizeof(Pixel), + offset(pointer_fg), XtRString, XtDefaultForeground}, + {XtNpointerColorBackground, XtCBackground, XtRPixel, sizeof(Pixel), + offset(pointer_bg), XtRString, XtDefaultBackground}, + {XtNcursorName, XtCCursor, XtRString, sizeof(String), + offset(cursor_name), XtRString, NULL}, +#ifdef XAW_INTERNATIONALIZATION + {XtNinternational, XtCInternational, XtRBoolean, sizeof(Boolean), + offset(international), XtRImmediate, (XtPointer) FALSE}, +#endif +#undef offset +}; + +static void ClassPartInitialize(), ClassInitialize(),Realize(),ConvertCursor(); +static Boolean SetValues(), ChangeSensitive(); + +SimpleClassRec simpleClassRec = { + { /* core fields */ + /* superclass */ (WidgetClass) &widgetClassRec, + /* class_name */ "Simple", + /* widget_size */ sizeof(SimpleRec), + /* class_initialize */ ClassInitialize, + /* class_part_initialize */ ClassPartInitialize, + /* class_inited */ FALSE, + /* initialize */ NULL, + /* 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 */ NULL, + /* resize */ NULL, + /* 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 */ NULL, + /* query_geometry */ XtInheritQueryGeometry, + /* display_accelerator */ XtInheritDisplayAccelerator, + /* extension */ NULL + }, + { /* simple fields */ + /* change_sensitive */ ChangeSensitive + } +}; + +WidgetClass simpleWidgetClass = (WidgetClass)&simpleClassRec; + +static void ClassInitialize() +{ + static XtConvertArgRec convertArg[] = { + {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.screen), + sizeof(Screen *)}, + {XtResourceString, (XtPointer) XtNpointerColor, sizeof(Pixel)}, + {XtResourceString, (XtPointer) XtNpointerColorBackground, + sizeof(Pixel)}, + {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.colormap), + sizeof(Colormap)} + }; + + XawInitializeWidgetSet(); + XtSetTypeConverter( XtRString, XtRColorCursor, XmuCvtStringToColorCursor, + convertArg, XtNumber(convertArg), + XtCacheByDisplay, (XtDestructor)NULL); +} + +static void ClassPartInitialize(class) + WidgetClass class; +{ + SimpleWidgetClass c = (SimpleWidgetClass) class; + SimpleWidgetClass super = (SimpleWidgetClass) + c->core_class.superclass; + + if (c->simple_class.change_sensitive == NULL) { + char buf[BUFSIZ]; + + (void) sprintf(buf, + "%s Widget: The Simple Widget class method 'change_sensitive' is undefined.\nA function must be defined or inherited.", + c->core_class.class_name); + XtWarning(buf); + c->simple_class.change_sensitive = ChangeSensitive; + } + + if (c->simple_class.change_sensitive == XtInheritChangeSensitive) + c->simple_class.change_sensitive = super->simple_class.change_sensitive; +} + +static void Realize(w, valueMask, attributes) + Widget w; + Mask *valueMask; + XSetWindowAttributes *attributes; +{ + Pixmap border_pixmap = 0; + if (!XtIsSensitive(w)) { + /* change border to gray; have to remember the old one, + * so XtDestroyWidget deletes the proper one */ + if (((SimpleWidget)w)->simple.insensitive_border == None) + ((SimpleWidget)w)->simple.insensitive_border = + XmuCreateStippledPixmap(XtScreen(w), + w->core.border_pixel, + w->core.background_pixel, + w->core.depth); + border_pixmap = w->core.border_pixmap; + attributes->border_pixmap = + w->core.border_pixmap = ((SimpleWidget)w)->simple.insensitive_border; + + *valueMask |= CWBorderPixmap; + *valueMask &= ~CWBorderPixel; + } + + ConvertCursor(w); + + if ((attributes->cursor = ((SimpleWidget)w)->simple.cursor) != None) + *valueMask |= CWCursor; + + XtCreateWindow( w, (unsigned int)InputOutput, (Visual *)CopyFromParent, + *valueMask, attributes ); + + if (!XtIsSensitive(w)) + w->core.border_pixmap = border_pixmap; +} + +/* Function Name: ConvertCursor + * Description: Converts a name to a new cursor. + * Arguments: w - the simple widget. + * Returns: none. + */ + +static void +ConvertCursor(w) +Widget w; +{ + SimpleWidget simple = (SimpleWidget) w; + XrmValue from, to; + Cursor cursor; + + if (simple->simple.cursor_name == NULL) + return; + + from.addr = (XPointer) simple->simple.cursor_name; + from.size = strlen((char *) from.addr) + 1; + + to.size = sizeof(Cursor); + to.addr = (XPointer) &cursor; + + if (XtConvertAndStore(w, XtRString, &from, XtRColorCursor, &to)) { + if ( cursor != None) + simple->simple.cursor = cursor; + } + else { + XtAppErrorMsg(XtWidgetToApplicationContext(w), + "convertFailed","ConvertCursor","XawError", + "Simple: ConvertCursor failed.", + (String *)NULL, (Cardinal *)NULL); + } +} + + +/* ARGSUSED */ +static Boolean SetValues(current, request, new, args, num_args) + Widget current, request, new; + ArgList args; + Cardinal *num_args; +{ + SimpleWidget s_old = (SimpleWidget) current; + SimpleWidget s_new = (SimpleWidget) new; + Boolean new_cursor = FALSE; + + /* this disables user changes after creation*/ +#ifdef XAW_INTERNATIONALIZATION + s_new->simple.international = s_old->simple.international; +#endif + + if ( XtIsSensitive(current) != XtIsSensitive(new) ) + (*((SimpleWidgetClass)XtClass(new))-> + simple_class.change_sensitive) ( new ); + + if (s_old->simple.cursor != s_new->simple.cursor) { + new_cursor = TRUE; + } + +/* + * We are not handling the string cursor_name correctly here. + */ + + if ( (s_old->simple.pointer_fg != s_new->simple.pointer_fg) || + (s_old->simple.pointer_bg != s_new->simple.pointer_bg) || + (s_old->simple.cursor_name != s_new->simple.cursor_name) ) { + ConvertCursor(new); + new_cursor = TRUE; + } + + if (new_cursor && XtIsRealized(new)) + XDefineCursor(XtDisplay(new), XtWindow(new), s_new->simple.cursor); + + return False; +} + + +static Boolean ChangeSensitive(w) + Widget w; +{ + if (XtIsRealized(w)) { + if (XtIsSensitive(w)) + if (w->core.border_pixmap != XtUnspecifiedPixmap) + XSetWindowBorderPixmap( XtDisplay(w), XtWindow(w), + w->core.border_pixmap ); + else + XSetWindowBorder( XtDisplay(w), XtWindow(w), + w->core.border_pixel ); + else { + if (((SimpleWidget)w)->simple.insensitive_border == None) + ((SimpleWidget)w)->simple.insensitive_border = + XmuCreateStippledPixmap(XtScreen(w), + w->core.border_pixel, + w->core.background_pixel, + w->core.depth); + XSetWindowBorderPixmap( XtDisplay(w), XtWindow(w), + ((SimpleWidget)w)-> + simple.insensitive_border ); + } + } + return False; +} diff --git a/src/Simple.h b/src/Simple.h new file mode 100644 index 0000000..7be83b1 --- /dev/null +++ b/src/Simple.h @@ -0,0 +1,105 @@ +/* $XConsortium: Simple.h,v 1.14 94/04/17 20:12:44 rws Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _Simple_h +#define _Simple_h + +#include "Xaw3dP.h" +#include <X11/Xmu/Converters.h> + +/**************************************************************** + * + * Simple widgets + * + ****************************************************************/ + +/* Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + background Background Pixel XtDefaultBackground + border BorderColor Pixel XtDefaultForeground + borderWidth BorderWidth Dimension 1 + cursor Cursor Cursor None + cursorName Cursor String NULL + destroyCallback Callback Pointer NULL + height Height Dimension 0 + insensitiveBorder Insensitive Pixmap Gray + mappedWhenManaged MappedWhenManaged Boolean True + pointerColor Foreground Pixel XtDefaultForeground + pointerColorBackground Background Pixel XtDefaultBackground + sensitive Sensitive Boolean True + width Width Dimension 0 + x Position Position 0 + y Position Position 0 + +*/ + +#define XtNcursor "cursor" +#define XtNcursorName "cursorName" +#define XtNinsensitiveBorder "insensitiveBorder" + +#define XtCInsensitive "Insensitive" + +#ifdef XAW_INTERNATIONALIZATION +#ifndef XtCInternational +#define XtCInternational "International" +#endif +#ifndef XtNinternational +#define XtNinternational "international" +#endif +#endif + +typedef struct _SimpleClassRec *SimpleWidgetClass; +typedef struct _SimpleRec *SimpleWidget; + +extern WidgetClass simpleWidgetClass; + +#endif /* _Simple_h */ diff --git a/src/SimpleMenP.h b/src/SimpleMenP.h new file mode 100644 index 0000000..4ecb187 --- /dev/null +++ b/src/SimpleMenP.h @@ -0,0 +1,113 @@ +/* + * $XConsortium: SimpleMenP.h,v 1.14 94/04/17 20:12:44 kaleb Exp $ + * +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + */ + +/* + * SimpleMenuP.h - Private Header file for SimpleMenu widget. + * + * Date: April 3, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifndef _SimpleMenuP_h +#define _SimpleMenuP_h + +#include <X11/Xaw3d/SimpleMenu.h> +#include <X11/Xaw3d/SmeP.h> +#include <X11/ShellP.h> + +typedef struct { + XtPointer extension; /* For future needs. */ +} SimpleMenuClassPart; + +typedef struct _SimpleMenuClassRec { + CoreClassPart core_class; + CompositeClassPart composite_class; + ShellClassPart shell_class; + OverrideShellClassPart override_shell_class; + SimpleMenuClassPart simpleMenu_class; +} SimpleMenuClassRec; + +extern SimpleMenuClassRec simpleMenuClassRec; + +typedef struct _SimpleMenuPart { + + /* resources */ + + String label_string; /* The string for the label or NULL. */ + SmeObject label; /* If label_string is non-NULL then this is + the label widget. */ + WidgetClass label_class; /* Widget Class of the menu label object. */ + + Dimension top_margin; /* Top and bottom margins. */ + Dimension bottom_margin; + Dimension left_whitespace; /* Space between BSB elements */ + Dimension right_whitespace; + Dimension row_height; /* height of each row (menu entry) */ + + Cursor cursor; /* The menu's cursor. */ + SmeObject popup_entry; /* The entry to position the cursor on for + when using XawPositionSimpleMenu. */ + Boolean menu_on_screen; /* Force the menus to be fully on the screen.*/ + int backing_store; /* What type of backing store to use. */ + + /* private state */ + + Boolean recursive_set_values; /* contain a possible infinite loop. */ + + Boolean menu_width; /* If true then force width to remain + core.width */ + Boolean menu_height; /* Just like menu_width, but for height. */ + + SmeObject entry_set; /* The entry that is currently set or + highlighted. */ + + Widget threeD; /* 3d drawing stuff */ + + SmeObject *first_entry; /* the first entry */ + SmeObject *current_first; /* the first entry displayed */ + Dimension last_y; + int first_y; /* Dimension doesn't do negatives! */ + int jump_val; /* number of entries to scroll by */ + Boolean too_tall; /* menu doesn't fit on screen */ + Boolean didnt_fit; /* if some entry didn't fit in the menu */ + Widget sub_menu; /* submenu of active SmeBSB object */ + unsigned char state; +} SimpleMenuPart; + +typedef struct _SimpleMenuRec { + CorePart core; + CompositePart composite; + ShellPart shell; + OverrideShellPart override; + SimpleMenuPart simple_menu; +} SimpleMenuRec; + +#endif /* _SimpleMenuP_h */ diff --git a/src/SimpleMenu.c b/src/SimpleMenu.c new file mode 100644 index 0000000..87a3170 --- /dev/null +++ b/src/SimpleMenu.c @@ -0,0 +1,1673 @@ +/* $XConsortium: SimpleMenu.c,v 1.44 94/04/17 20:12:45 kaleb Exp $ */ + +/* +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + */ + +/* + * SimpleMenu.c - Source code file for SimpleMenu widget. + * + * Date: April 3, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#include <stdio.h> +#include <limits.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> + +#include "Xaw3dP.h" +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/SimpleMenP.h> +#include <X11/Xaw3d/SmeBSBP.h> +#include <X11/Xaw3d/SmeLine.h> +#include <X11/Xaw3d/Cardinals.h> +#include <X11/Xaw3d/ThreeDP.h> + +#include <X11/Xmu/Initer.h> +#include <X11/Xmu/CharSet.h> + +#define streq(a, b) ( strcmp((a), (b)) == 0 ) + +#define offset(field) XtOffsetOf(SimpleMenuRec, simple_menu.field) + +static XtResource resources[] = { + +/* + * Label Resources. + */ + + {XtNlabel, XtCLabel, XtRString, sizeof(String), + offset(label_string), XtRString, NULL}, + {XtNlabelClass, XtCLabelClass, XtRPointer, sizeof(WidgetClass), + offset(label_class), XtRImmediate, (XtPointer) NULL}, + +/* + * Layout Resources. + */ + + {XtNrowHeight, XtCRowHeight, XtRDimension, sizeof(Dimension), + offset(row_height), XtRImmediate, (XtPointer) 0}, + {XtNtopMargin, XtCVerticalMargins, XtRDimension, sizeof(Dimension), + offset(top_margin), XtRImmediate, (XtPointer) 0}, + {XtNbottomMargin, XtCVerticalMargins, XtRDimension, sizeof(Dimension), + offset(bottom_margin), XtRImmediate, (XtPointer) 0}, + {XtNleftWhitespace, XtCHorizontalWhitespace, XtRDimension, sizeof(Dimension), + offset(left_whitespace), XtRImmediate, (XtPointer) 0}, + {XtNrightWhitespace, XtCHorizontalWhitespace, XtRDimension, sizeof(Dimension), + offset(right_whitespace), XtRImmediate, (XtPointer) 0}, + +/* + * Misc. Resources + */ + + { XtNallowShellResize, XtCAllowShellResize, XtRBoolean, sizeof(Boolean), + XtOffsetOf(SimpleMenuRec, shell.allow_shell_resize), + XtRImmediate, (XtPointer) TRUE }, + {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor), + offset(cursor), XtRImmediate, (XtPointer) None}, + {XtNmenuOnScreen, XtCMenuOnScreen, XtRBoolean, sizeof(Boolean), + offset(menu_on_screen), XtRImmediate, (XtPointer) TRUE}, + {XtNpopupOnEntry, XtCPopupOnEntry, XtRWidget, sizeof(Widget), + offset(popup_entry), XtRWidget, NULL}, + {XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int), + offset(backing_store), + XtRImmediate, (XtPointer) (Always + WhenMapped + NotUseful)}, + {XtNjumpScroll, XtCJumpScroll, XtRInt, sizeof(int), + offset(jump_val), XtRImmediate, (XtPointer)1}, +}; +#undef offset + +static char defaultTranslations[] = + "<EnterWindow>: highlight() \n\ + <LeaveWindow>: unhighlight() \n\ + <BtnMotion>: highlight() \n\ + <BtnUp>: notify() unhighlight() popdown()"; + +/* + * Semi Public function definitions. + */ + +static void Redisplay(), Realize(), Resize(), ChangeManaged(); +static void Initialize(), ClassInitialize(), ClassPartInitialize(); +static Boolean SetValues(), SetValuesHook(); +static XtGeometryResult GeometryManager(); +static void PopupCB(), PopupSubMenu(), PopdownSubMenu(); + +/* + * Action Routine Definitions + */ + +static void Highlight(), Unhighlight(), Notify(), PositionMenuAction(); +static void Popdown(); + +/* + * Private Function Definitions. + */ + +static void MakeSetValuesRequest(), CreateLabel(), Layout(); +static void AddPositionAction(), PositionMenu(), ChangeCursorOnGrab(); +static void SetMarginWidths(); +static Dimension GetMenuWidth(), GetMenuHeight(); +static Widget FindMenu(); +static SmeObject GetEventEntry(); +static void MoveMenu(); + +static XtActionsRec actionsList[] = +{ + {"notify", Notify}, + {"highlight", Highlight}, + {"unhighlight", Unhighlight}, + {"popdown", Popdown} +}; + +static CompositeClassExtensionRec extension_rec = { + /* next_extension */ NULL, + /* record_type */ NULLQUARK, + /* version */ XtCompositeExtensionVersion, + /* record_size */ sizeof(CompositeClassExtensionRec), + /* accepts_objects */ TRUE, +}; + +#define superclass (&overrideShellClassRec) + +SimpleMenuClassRec simpleMenuClassRec = { + { + /* superclass */ (WidgetClass) superclass, + /* class_name */ "SimpleMenu", + /* size */ sizeof(SimpleMenuRec), + /* class_initialize */ ClassInitialize, + /* class_part_initialize*/ ClassPartInitialize, + /* Class init'ed */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ Realize, + /* actions */ actionsList, + /* num_actions */ XtNumber(actionsList), + /* resources */ resources, + /* resource_count */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ TRUE, + /* compress_exposure */ TRUE, + /* compress_enterleave*/ TRUE, + /* visible_interest */ FALSE, + /* destroy */ NULL, + /* resize */ Resize, + /* expose */ Redisplay, + /* set_values */ SetValues, + /* set_values_hook */ SetValuesHook, + /* set_values_almost */ XtInheritSetValuesAlmost, + /* get_values_hook */ NULL, + /* accept_focus */ NULL, + /* intrinsics version */ XtVersion, + /* callback offsets */ NULL, + /* tm_table */ defaultTranslations, + /* query_geometry */ NULL, + /* display_accelerator*/ NULL, + /* extension */ NULL + },{ + /* geometry_manager */ GeometryManager, + /* change_managed */ ChangeManaged, + /* insert_child */ XtInheritInsertChild, + /* delete_child */ XtInheritDeleteChild, + /* extension */ NULL + },{ + /* Shell extension */ NULL + },{ + /* Override extension */ NULL + },{ + /* Simple Menu extension*/ NULL + } +}; + +WidgetClass simpleMenuWidgetClass = (WidgetClass)&simpleMenuClassRec; + +#define SMW_ARROW_SIZE 8 +#define SMW_UNMAPPING 0x01 +#define SMW_POPLEFT 0x02 + +#define ForAllChildren(smw, childP) \ + for ((childP) = (SmeObject *) (smw)->composite.children; \ + (childP) < (SmeObject *) ((smw)->composite.children + \ + (smw)->composite.num_children); \ + (childP)++) + +/************************************************************ + * + * Semi-Public Functions. + * + ************************************************************/ + +/* Function Name: ClassInitialize + * Description: Class Initialize routine, called only once. + * Arguments: none. + * Returns: none. + */ + +static void +ClassInitialize() +{ + XawInitializeWidgetSet(); + XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore, + (XtConvertArgList)NULL, (Cardinal)0 ); + XmuAddInitializer( AddPositionAction, NULL); +} + +/* Function Name: ClassInitialize + * Description: Class Part Initialize routine, called for every + * subclass. Makes sure that the subclasses pick up + * the extension record. + * Arguments: wc - the widget class of the subclass. + * Returns: none. + */ + +static void +ClassPartInitialize(wc) +WidgetClass wc; +{ + SimpleMenuWidgetClass smwc = (SimpleMenuWidgetClass) wc; + +/* + * Make sure that our subclass gets the extension rec too. + */ + + extension_rec.next_extension = smwc->composite_class.extension; + smwc->composite_class.extension = (XtPointer) &extension_rec; +} + +/* Function Name: Initialize + * Description: Initializes the simple menu widget + * Arguments: request - the widget requested by the argument list. + * new - the new widget with both resource and non + * resource values. + * Returns: none. + */ + +/* ARGSUSED */ +static void +Initialize(request, new, args, num_args) +Widget request, new; +ArgList args; +Cardinal *num_args; +{ + SimpleMenuWidget smw = (SimpleMenuWidget) new; + + XmuCallInitializers(XtWidgetToApplicationContext(new)); + + smw->simple_menu.label = NULL; + smw->simple_menu.entry_set = NULL; + smw->simple_menu.recursive_set_values = FALSE; + smw->simple_menu.first_entry = NULL; + smw->simple_menu.current_first = NULL; + smw->simple_menu.first_y = 0; + smw->simple_menu.too_tall = FALSE; + smw->simple_menu.sub_menu = NULL; + smw->simple_menu.state = 0; + + XtAddCallback(new, XtNpopupCallback, PopupCB, NULL); + + if (smw->simple_menu.label_class == NULL) + smw->simple_menu.label_class = smeBSBObjectClass; + + if (smw->simple_menu.label_string != NULL) + CreateLabel(new); + + /* GetMenuHeight() needs this */ + smw->simple_menu.threeD = XtVaCreateWidget("threeD", threeDWidgetClass, + new, + XtNx, 0, XtNy, 0, XtNwidth, /* dummy */ 10, XtNheight, /* dummy */ 10, + NULL); + + smw->simple_menu.menu_width = TRUE; + + if (smw->core.width == 0) { + smw->simple_menu.menu_width = FALSE; + smw->core.width = GetMenuWidth(new, (Widget)NULL); + } + + smw->simple_menu.menu_height = TRUE; + + if (smw->core.height == 0) { + smw->simple_menu.menu_height = FALSE; + smw->core.height = GetMenuHeight(new); + } + + /* add a popup_callback routine for changing the cursor */ + XtAddCallback(new, XtNpopupCallback, ChangeCursorOnGrab, (XtPointer)NULL); +} + +/* Function Name: Redisplay + * Description: Redisplays the contents of the widget. + * Arguments: w - the simple menu widget. + * event - the X event that caused this redisplay. + * region - the region the needs to be repainted. + * Returns: none. + */ + +/* ARGSUSED */ +static void +Redisplay(w, event, region) +Widget w; +XEvent * event; +Region region; +{ + SimpleMenuWidget smw = (SimpleMenuWidget)w; + SmeObject *entry; + SmeObjectClass class; + ThreeDWidget tdw = (ThreeDWidget)smw->simple_menu.threeD; + RectObjPart old_pos; + int y, max_y, new_y, dy, s = tdw->threeD.shadow_width; + Boolean can_paint; + XPoint point[3]; + + if (region == NULL) + XClearWindow(XtDisplay(w), XtWindow(w)); + + if (XtIsRealized((Widget)smw)) + _ShadowSurroundedBox((Widget)smw, tdw, + 0, 0, smw->core.width, smw->core.height, + tdw->threeD.relief, True); + + smw->simple_menu.didnt_fit = False; + y = 0; + max_y = HeightOfScreen(XtScreen(w)) - s; + new_y = -(*(SmeObject *)(smw)->composite.children)->rectangle.y; + can_paint = False; + + /* check and paint each of the entries - including the label */ + ForAllChildren(smw, entry) + { + if (!XtIsManaged((Widget)*entry)) continue; + + if (smw->simple_menu.first_entry == NULL) + { + smw->simple_menu.first_entry = entry; + smw->simple_menu.current_first = entry; + } + + if (smw->simple_menu.too_tall) + { + dy = 0; + + if (entry == (smw->simple_menu.current_first)) + { + new_y = (*entry)->rectangle.y - 1; + + if (smw->simple_menu.current_first != smw->simple_menu.first_entry) + { + point[0].x = (*entry)->rectangle.width / 2; + point[0].y = s + 1; + point[1].x = (*entry)->rectangle.width / 2 - SMW_ARROW_SIZE / 2; + point[1].y = s + SMW_ARROW_SIZE; + point[2].x = (*entry)->rectangle.width / 2 + SMW_ARROW_SIZE / 2; + point[2].y = s + SMW_ARROW_SIZE; + XFillPolygon(XtDisplay(w), smw->core.window, + tdw->threeD.bot_shadow_GC, point, 3, Convex, + CoordModeOrigin); + + new_y -= SMW_ARROW_SIZE; + dy = SMW_ARROW_SIZE; + } + + smw->simple_menu.first_y = new_y; + can_paint = True; + } + else if (!can_paint) + continue; + + old_pos = (*entry)->rectangle; + (*entry)->rectangle.y -= new_y; + + if ((*entry)->rectangle.y + (*entry)->rectangle.height + dy > max_y) + { + smw->simple_menu.last_y = (*entry)->rectangle.y; + point[0].x = (*entry)->rectangle.width / 2; + point[0].y = max_y - 1; + point[1].x = (*entry)->rectangle.width / 2 - SMW_ARROW_SIZE / 2; + point[1].y = max_y - SMW_ARROW_SIZE; + point[2].x = (*entry)->rectangle.width / 2 + SMW_ARROW_SIZE / 2; + point[2].y = max_y - SMW_ARROW_SIZE; + XFillPolygon(XtDisplay(w), smw->core.window, + tdw->threeD.bot_shadow_GC, point, 3, Convex, + CoordModeOrigin); + + smw->simple_menu.didnt_fit = True; + (*entry)->rectangle = old_pos; + break; + } + } + + /* + if (region != NULL) + switch (XRectInRegion(region, + (int)(*entry)->rectangle.x, (int)(*entry)->rectangle.y, + (unsigned int)(*entry)->rectangle.width, + (unsigned int)(*entry)->rectangle.height)) + { + case RectangleIn: + case RectanglePart: + break; + default: + continue; + } + */ + + class = (SmeObjectClass)(*entry)->object.widget_class; + + if (class->rect_class.expose != NULL) + (class->rect_class.expose)((Widget)*entry, NULL, NULL); + + if (smw->simple_menu.too_tall) (*entry)->rectangle = old_pos; + + y += (*entry)->rectangle.height; + } +} + +/* Function Name: Realize + * Description: Realizes the widget. + * Arguments: w - the simple menu widget. + * mask - value mask for the window to create. + * attrs - attributes for the window to create. + * Returns: none + */ + +static void +Realize(w, mask, attrs) +Widget w; +XtValueMask * mask; +XSetWindowAttributes * attrs; +{ + SimpleMenuWidget smw = (SimpleMenuWidget) w; + + attrs->cursor = smw->simple_menu.cursor; + *mask |= CWCursor; + if ((smw->simple_menu.backing_store == Always) || + (smw->simple_menu.backing_store == NotUseful) || + (smw->simple_menu.backing_store == WhenMapped) ) { + *mask |= CWBackingStore; + attrs->backing_store = smw->simple_menu.backing_store; + } + else + *mask &= ~CWBackingStore; + + /* check if the menu is too big */ + if (smw->core.height >= HeightOfScreen(XtScreen(w))) { + smw->simple_menu.too_tall = TRUE; + smw->core.height = HeightOfScreen(XtScreen(w)); + } + + (*superclass->core_class.realize) (w, mask, attrs); +} + +/* Function Name: Resize + * Description: Handle the menu being resized. + * Arguments: w - the simple menu widget or any of its object children. + * Returns: none. + */ + +static void +Resize(w) +Widget w; +{ + /* + * The sole purpose of this function is to force an initial + * layout by handling a call from some child widget. Ick. + */ + + if (XtIsSubclass(w, smeBSBObjectClass)) + { + Widget parent = XtParent(w); + + if (!XtIsRealized(parent)) + XtRealizeWidget(parent); + + Layout(w, (Dimension *)NULL, (Dimension *)NULL); + } +} + +/* Function Name: SetValues + * Description: Relayout the menu when one of the resources is changed. + * Arguments: current - current state of the widget. + * request - what was requested. + * new - what the widget will become. + * Returns: none + */ + +/* ARGSUSED */ +static Boolean +SetValues(current, request, new, args, num_args) +Widget current, request, new; +ArgList args; +Cardinal *num_args; +{ + SimpleMenuWidget smw_old = (SimpleMenuWidget) current; + SimpleMenuWidget smw_new = (SimpleMenuWidget) new; + Boolean ret_val = FALSE, layout = FALSE; + + if (!XtIsRealized(current)) return(FALSE); + + if (!smw_new->simple_menu.recursive_set_values) { + if (smw_new->core.width != smw_old->core.width) { + smw_new->simple_menu.menu_width = (smw_new->core.width != 0); + layout = TRUE; + } + if (smw_new->core.height != smw_old->core.height) { + smw_new->simple_menu.menu_height = (smw_new->core.height != 0); + layout = TRUE; + } + } + + if (smw_old->simple_menu.cursor != smw_new->simple_menu.cursor) + XDefineCursor(XtDisplay(new), + XtWindow(new), smw_new->simple_menu.cursor); + + if (smw_old->simple_menu.label_string !=smw_new->simple_menu.label_string) + if (smw_new->simple_menu.label_string == NULL) /* Destroy. */ + XtDestroyWidget((Widget) smw_old->simple_menu.label); + else if (smw_old->simple_menu.label_string == NULL) /* Create. */ + CreateLabel(new); + else { /* Change. */ + Arg arglist[1]; + + XtSetArg(arglist[0], XtNlabel, smw_new->simple_menu.label_string); + XtSetValues((Widget) smw_new->simple_menu.label, arglist, ONE); + } + + if (smw_old->simple_menu.label_class != smw_new->simple_menu.label_class) + XtAppWarning(XtWidgetToApplicationContext(new), + "No Dynamic class change of the SimpleMenu Label."); + + if ((smw_old->simple_menu.top_margin != smw_new->simple_menu.top_margin) || + (smw_old->simple_menu.bottom_margin != + smw_new->simple_menu.bottom_margin) /* filler................. */ ) { + layout = TRUE; + ret_val = TRUE; + } + + if (smw_old->simple_menu.left_whitespace != smw_new->simple_menu.left_whitespace) { + layout = TRUE; + ret_val = TRUE; + } + + if (smw_old->simple_menu.right_whitespace != smw_new->simple_menu.right_whitespace) { + layout = TRUE; + ret_val = TRUE; + } + + if (layout) + Layout(new, (Dimension *)NULL, (Dimension *)NULL); + + return(ret_val); +} + +/* Function Name: SetValuesHook + * Description: To handle a special case, this is passed the + * actual arguments. + * Arguments: w - the menu widget. + * arglist - the argument list passed to XtSetValues. + * num_args - the number of args. + * Returns: none + */ + +/* + * If the user actually passed a width and height to the widget + * then this MUST be used, rather than our newly calculated width and + * height. + */ + +static Boolean +SetValuesHook(w, arglist, num_args) +Widget w; +ArgList arglist; +Cardinal *num_args; +{ + Cardinal i; + Dimension width, height; + + width = w->core.width; + height = w->core.height; + + for ( i = 0 ; i < *num_args ; i++) { + if ( streq(arglist[i].name, XtNwidth) ) + width = (Dimension) arglist[i].value; + if ( streq(arglist[i].name, XtNheight) ) + height = (Dimension) arglist[i].value; + } + + if ((width != w->core.width) || (height != w->core.height)) + MakeSetValuesRequest(w, width, height); + return(FALSE); +} + +/************************************************************ + * + * Geometry Management routines. + * + ************************************************************/ + +/* Function Name: GeometryManager + * Description: This is the SimpleMenu Widget's Geometry Manager. + * Arguments: w - the Menu Entry making the request. + * request - requested new geometry. + * reply - the allowed geometry. + * Returns: XtGeometry{Yes, No, Almost}. + */ + +static XtGeometryResult +GeometryManager(w, request, reply) +Widget w; +XtWidgetGeometry * request, * reply; +{ + SimpleMenuWidget smw = (SimpleMenuWidget) XtParent(w); + SmeObject entry = (SmeObject) w; + XtGeometryMask mode = request->request_mode; + XtGeometryResult answer; + Dimension old_height, old_width; + + if ( !(mode & CWWidth) && !(mode & CWHeight) ) + return(XtGeometryNo); + + reply->width = request->width; + reply->height = request->height; + + old_width = entry->rectangle.width; + old_height = entry->rectangle.height; + + Layout(w, &(reply->width), &(reply->height) ); + +/* + * Since we are an override shell and have no parent there is no one to + * ask to see if this geom change is okay, so I am just going to assume + * we can do whatever we want. If you subclass be very careful with this + * assumption, it could bite you. + * + * Chris D. Peterson - Sept. 1989. + */ + + if ( (reply->width == request->width) && + (reply->height == request->height) ) { + + if ( mode & XtCWQueryOnly ) { + entry->rectangle.width = old_width; + entry->rectangle.height = old_height; + } + else { + /* Actually perform the layout */ + Layout(( Widget) smw, (Dimension *)NULL, (Dimension *)NULL); + } + answer = XtGeometryDone; + } + else { + entry->rectangle.width = old_width; + entry->rectangle.height = old_height; + + if ( ((reply->width == request->width) && !(mode & CWHeight)) || + ((reply->height == request->height) && !(mode & CWWidth)) || + ((reply->width == request->width) && + (reply->height == request->height)) ) + answer = XtGeometryNo; + else { + answer = XtGeometryAlmost; + reply->request_mode = 0; + if (reply->width != request->width) + reply->request_mode |= CWWidth; + if (reply->height != request->height) + reply->request_mode |= CWHeight; + } + } + return(answer); +} + +/* Function Name: ChangeManaged + * Description: called whenever a new child is managed. + * Arguments: w - the simple menu widget. + * Returns: none. + */ + +static void +ChangeManaged(w) +Widget w; +{ + Layout(w, (Dimension *)NULL, (Dimension *)NULL); +} + +/************************************************************ + * + * Global Action Routines. + * + * These actions routines will be added to the application's + * global action list. + * + ************************************************************/ + +/* Function Name: PositionMenuAction + * Description: Positions the simple menu widget. + * Arguments: w - a widget (no the simple menu widget.) + * event - the event that caused this action. + * params, num_params - parameters passed to the routine. + * we expect the name of the menu here. + * Returns: none + */ + +/* ARGSUSED */ +static void +PositionMenuAction(w, event, params, num_params) +Widget w; +XEvent * event; +String * params; +Cardinal * num_params; +{ + Widget menu; + XPoint loc; + + if (*num_params != 1) { + char error_buf[BUFSIZ]; + (void) sprintf(error_buf, "%s %s", + "Xaw - SimpleMenuWidget: position menu action expects only one", + "parameter which is the name of the menu."); + XtAppWarning(XtWidgetToApplicationContext(w), error_buf); + return; + } + + if ( (menu = FindMenu(w, params[0])) == NULL) { + char error_buf[BUFSIZ]; + (void) sprintf(error_buf, "%s '%s'", + "Xaw - SimpleMenuWidget: could not find menu named: ", params[0]); + XtAppWarning(XtWidgetToApplicationContext(w), error_buf); + return; + } + + switch (event->type) { + case ButtonPress: + case ButtonRelease: + loc.x = event->xbutton.x_root; + loc.y = event->xbutton.y_root; + PositionMenu(menu, &loc); + break; + case EnterNotify: + case LeaveNotify: + loc.x = event->xcrossing.x_root; + loc.y = event->xcrossing.y_root; + PositionMenu(menu, &loc); + break; + case MotionNotify: + loc.x = event->xmotion.x_root; + loc.y = event->xmotion.y_root; + PositionMenu(menu, &loc); + break; + default: + PositionMenu(menu, (XPoint *)NULL); + break; + } +} + +/************************************************************ + * + * Widget Action Routines. + * + ************************************************************/ + +/* Function Name: Unhighlight + * Description: Unhighlights current entry. + * Arguments: w - the simple menu widget. + * event - the event that caused this action. + * params, num_params - ** NOT USED ** + * Returns: none + */ + +/* ARGSUSED */ +static void +Unhighlight(w, event, params, num_params) +Widget w; +XEvent * event; +String * params; +Cardinal * num_params; +{ + SimpleMenuWidget smw = (SimpleMenuWidget) w; + SimpleMenuWidget sub = (SimpleMenuWidget) smw->simple_menu.sub_menu; + SmeObject entry = smw->simple_menu.entry_set; + SmeObjectClass class; + int old_pos; + + if (entry == NULL || entry == GetEventEntry(w, event)) { + smw->simple_menu.entry_set = NULL; + PopdownSubMenu(smw); + return; + } + + if (event->xcrossing.y < 0 || event->xcrossing.y >= (int)smw->core.height) + PopdownSubMenu(smw); + else if (sub && + ((event->xcrossing.x < 0 && + !(sub->simple_menu.state & SMW_POPLEFT)) || + (event->xcrossing.x >= (int)smw->core.width && + (sub->simple_menu.state & SMW_POPLEFT)))) + PopdownSubMenu(smw); + + smw->simple_menu.entry_set = NULL; + class = (SmeObjectClass) entry->object.widget_class; + + /* backup, then restore, original entry position */ + old_pos = entry->rectangle.y; + entry->rectangle.y -= smw->simple_menu.first_y; + + (class->sme_class.unhighlight) ((Widget) entry); + + entry->rectangle.y = old_pos; +} + +/* Function Name: Highlight + * Description: Highlights current entry. + * Arguments: w - the simple menu widget. + * event - the event that caused this action. + * params, num_params - ** NOT USED ** + * Returns: none + */ + +/* ARGSUSED */ +static void +Highlight(w, event, params, num_params) +Widget w; +XEvent * event; +String * params; +Cardinal * num_params; +{ + SimpleMenuWidget smw = (SimpleMenuWidget) w; + SmeObject entry; + SmeObjectClass class; + int old_pos; + + if (!XtIsSensitive(w)) return; + + entry = GetEventEntry(w, event); + if (entry == smw->simple_menu.entry_set) + return; + + PopdownSubMenu(smw); + Unhighlight(w, event, params, num_params); + + if (entry == NULL) + return; + if (!XtIsSensitive((Widget) entry)) { + smw->simple_menu.entry_set = NULL; + return; + } + + if (!(smw->simple_menu.state & SMW_UNMAPPING)) { + smw->simple_menu.entry_set = entry; + class = (SmeObjectClass) entry->object.widget_class; + + /* backup, then restore, original entry position */ + old_pos = entry->rectangle.y; + entry->rectangle.y -= smw->simple_menu.first_y; + + (class->sme_class.highlight) ((Widget) entry); + if (XtIsSubclass((Widget)entry, smeBSBObjectClass)) + PopupSubMenu(smw); + + entry->rectangle.y = old_pos; + } +} + +/* Function Name: Notify + * Description: Notify user of current entry. + * Arguments: w - the simple menu widget. + * event - the event that caused this action. + * params, num_params - ** NOT USED ** + * Returns: none + */ + +/* ARGSUSED */ +static void +Notify(w, event, params, num_params) +Widget w; +XEvent * event; +String * params; +Cardinal * num_params; +{ + SimpleMenuWidget smw = (SimpleMenuWidget) w; + SmeObject entry = smw->simple_menu.entry_set; + SmeObjectClass class; + + if ( (entry == NULL) || !XtIsSensitive((Widget) entry ) ) return; + + class = (SmeObjectClass) entry->object.widget_class; + (class->sme_class.notify)( (Widget) entry ); +} + +/************************************************************ + * + * Public Functions. + * + ************************************************************/ + +/* Function Name: XawSimpleMenuAddGlobalActions + * Description: adds the global actions to the simple menu widget. + * Arguments: app_con - the appcontext. + * Returns: none. + */ + +void +#if NeedFunctionPrototypes +XawSimpleMenuAddGlobalActions(XtAppContext app_con) +#else +XawSimpleMenuAddGlobalActions(app_con) +XtAppContext app_con; +#endif +{ + XtInitializeWidgetClass(simpleMenuWidgetClass); + XmuCallInitializers( app_con ); +} + + +/* Function Name: XawSimpleMenuGetActiveEntry + * Description: Gets the currently active (set) entry. + * Arguments: w - the smw widget. + * Returns: the currently set entry or NULL if none is set. + */ + +Widget +#if NeedFunctionPrototypes +XawSimpleMenuGetActiveEntry(Widget w) +#else +XawSimpleMenuGetActiveEntry(w) +Widget w; +#endif +{ + SimpleMenuWidget smw = (SimpleMenuWidget) w; + + return( (Widget) smw->simple_menu.entry_set); +} + +/* Function Name: XawSimpleMenuClearActiveEntry + * Description: Unsets the currently active (set) entry. + * Arguments: w - the smw widget. + * Returns: none. + */ + +void +#if NeedFunctionPrototypes +XawSimpleMenuClearActiveEntry(Widget w) +#else +XawSimpleMenuClearActiveEntry(w) +Widget w; +#endif +{ + SimpleMenuWidget smw = (SimpleMenuWidget) w; + + smw->simple_menu.entry_set = NULL; +} + +/************************************************************ + * + * Private Functions. + * + ************************************************************/ + +/* Function Name: CreateLabel + * Description: Creates a the menu label. + * Arguments: w - the smw widget. + * Returns: none. + * + * Creates the label object and makes sure it is the first child in + * in the list. + */ + +static void +CreateLabel(w) +Widget w; +{ + SimpleMenuWidget smw = (SimpleMenuWidget) w; + Widget * child, * next_child; + int i; + Arg args[2]; + + if ( (smw->simple_menu.label_string == NULL) || + (smw->simple_menu.label != NULL) ) { + char error_buf[BUFSIZ]; + + (void) sprintf(error_buf, "Xaw Simple Menu Widget: %s or %s, %s", + "label string is NULL", "label already exists", + "no label is being created."); + XtAppWarning(XtWidgetToApplicationContext(w), error_buf); + return; + } + + XtSetArg(args[0], XtNlabel, smw->simple_menu.label_string); + XtSetArg(args[1], XtNjustify, XtJustifyCenter); + smw->simple_menu.label = (SmeObject) + XtCreateManagedWidget("menuLabel", + smw->simple_menu.label_class, w, + args, TWO); + + next_child = NULL; + for (child = smw->composite.children + smw->composite.num_children, + i = smw->composite.num_children ; i > 0 ; i--, child--) { + if (next_child != NULL) + *next_child = *child; + next_child = child; + } + *child = (Widget) smw->simple_menu.label; +} + +/* Function Name: Layout + * Description: lays the menu entries out all nice and neat. + * Arguments: w - See below (+++) + * width_ret, height_ret - The returned width and + * height values. + * Returns: none. + * + * if width == NULL || height == NULL then it assumes the you do not care + * about the return values, and just want a relayout. + * + * if this is not the case then it will set width_ret and height_ret + * to be width and height that the child would get if it were layed out + * at this time. + * + * +++ "w" can be the simple menu widget or any of its object children. + */ + +static void +Layout(w, width_ret, height_ret) +Widget w; +Dimension *width_ret, *height_ret; +{ + SmeObject current_entry, *entry; + SimpleMenuWidget smw; + ThreeDWidget tdw; + Dimension width, height; + Boolean do_layout = (height_ret == NULL || width_ret == NULL); + Boolean allow_change_size; + height = 0; + + if (XtIsSubclass(w, simpleMenuWidgetClass)) + { + smw = (SimpleMenuWidget)w; + current_entry = NULL; + } + else + { + smw = (SimpleMenuWidget)XtParent(w); + current_entry = (SmeObject)w; + } + tdw = (ThreeDWidget)smw->simple_menu.threeD; + + do_layout |= (current_entry != NULL); + allow_change_size = + (!XtIsRealized((Widget)smw) || smw->shell.allow_shell_resize); + + if (smw->simple_menu.menu_height) + height = smw->core.height; + else if (do_layout) + { + height = smw->simple_menu.top_margin + tdw->threeD.shadow_width; + + ForAllChildren(smw, entry) + { + if (!XtIsManaged((Widget)*entry)) continue; + + if (smw->simple_menu.row_height != 0 && + *entry != smw->simple_menu.label) + (*entry)->rectangle.height = smw->simple_menu.row_height; + + (*entry)->rectangle.y = height; + (*entry)->rectangle.x = 0; + height += (*entry)->rectangle.height; + } + + height += smw->simple_menu.bottom_margin + tdw->threeD.shadow_width; + } + else if (smw->simple_menu.row_height != 0 && + current_entry != smw->simple_menu.label) + { + height = smw->simple_menu.row_height * smw->composite.num_children; + height += tdw->threeD.shadow_width * 2; + } + + if (smw->simple_menu.menu_width) + width = smw->core.width; + else if (allow_change_size) + { + SetMarginWidths((Widget)smw); + + width = GetMenuWidth((Widget)smw, (Widget)NULL); + } + else + width = smw->core.width; + + if (do_layout) + { + ForAllChildren(smw, entry) + if (XtIsManaged((Widget)*entry)) + (*entry)->rectangle.width = width; + + if (allow_change_size) + MakeSetValuesRequest((Widget) smw, width, height); + } + else + { + *width_ret = width; + if (height != 0) *height_ret = height; + } +} + +/* Function Name: AddPositionAction + * Description: Adds the XawPositionSimpleMenu action to the global + * action list for this appcon. + * Arguments: app_con - the application context for this app. + * data - NOT USED. + * Returns: none. + */ + +/* ARGSUSED */ +static void +AddPositionAction(app_con, data) +XtAppContext app_con; +XPointer data; +{ + static XtActionsRec pos_action[] = { + { "XawPositionSimpleMenu", PositionMenuAction }, + }; + + XtAppAddActions(app_con, pos_action, XtNumber(pos_action)); +} + +/* Function Name: FindMenu + * Description: Find the menu give a name and reference widget. + * Arguments: widget - reference widget. + * name - the menu widget's name. + * Returns: the menu widget or NULL. + */ + +static Widget +FindMenu(widget, name) +Widget widget; +String name; +{ + Widget w, menu; + + for ( w = widget ; w != NULL ; w = XtParent(w) ) + if ( (menu = XtNameToWidget(w, name)) != NULL ) + return(menu); + return(NULL); +} + +/* Function Name: PositionMenu + * Description: Places the menu + * Arguments: w - the simple menu widget. + * location - a pointer the the position or NULL. + * Returns: none. + */ + +static void +PositionMenu(w, location) +Widget w; +XPoint * location; +{ + SimpleMenuWidget smw = (SimpleMenuWidget) w; + SmeObject entry; + XPoint t_point; + + if (location == NULL) { + Window junk1, junk2; + int root_x, root_y, junkX, junkY; + unsigned int junkM; + + location = &t_point; + if (XQueryPointer(XtDisplay(w), XtWindow(w), &junk1, &junk2, + &root_x, &root_y, &junkX, &junkY, &junkM) == FALSE) { + char error_buf[BUFSIZ]; + (void) sprintf(error_buf, "%s %s", "Xaw Simple Menu Widget:", + "Could not find location of mouse pointer"); + XtAppWarning(XtWidgetToApplicationContext(w), error_buf); + return; + } + location->x = (short) root_x; + location->y = (short) root_y; + } + + /* + * The width will not be correct unless it is realized. + */ + + XtRealizeWidget(w); + + location->x -= (Position) w->core.width/2; + + if (smw->simple_menu.popup_entry == NULL) + entry = smw->simple_menu.label; + else + entry = smw->simple_menu.popup_entry; + + if (entry != NULL) + location->y -= entry->rectangle.y + entry->rectangle.height/2; + + MoveMenu(w, (Position) location->x, (Position) location->y); +} + +/* Function Name: MoveMenu + * Description: Actually moves the menu, may force it to + * to be fully visable if menu_on_screen is TRUE. + * Arguments: w - the simple menu widget. + * x, y - the current location of the widget. + * Returns: none + */ + +static void +MoveMenu(w, x, y) +Widget w; +Position x, y; +{ + SimpleMenuWidget smw = (SimpleMenuWidget) w; + Arg arglist[2]; + + if (smw->simple_menu.menu_on_screen) { + int width = w->core.width + 2 * w->core.border_width; + int height = w->core.height + 2 * w->core.border_width; + + if (x >= 0) { + int scr_width = WidthOfScreen(XtScreen(w)); + if (x + width > scr_width) + x = scr_width - width; + } + if (x < 0) + x = 0; + + if (y >= 0) { + int scr_height = HeightOfScreen(XtScreen(w)); + if (y + height > scr_height) + y = scr_height - height; + } + if (y < 0) + y = 0; + } + + XtSetArg(arglist[0], XtNx, x); + XtSetArg(arglist[1], XtNy, y); + XtSetValues(w, arglist, TWO); +} + +/* Function Name: ChangeCursorOnGrab + * Description: Changes the cursor on the active grab to the one + * specified in out resource list. + * Arguments: w - the widget. + * junk, garbage - ** NOT USED **. + * Returns: None. + */ + +/* ARGSUSED */ +static void +ChangeCursorOnGrab(w, junk, garbage) +Widget w; +XtPointer junk, garbage; +{ + SimpleMenuWidget smw = (SimpleMenuWidget) w; + + /* + * The event mask here is what is currently in the MIT implementation. + * There really needs to be a way to get the value of the mask out + * of the toolkit (CDP 5/26/89). + */ + + XChangeActivePointerGrab(XtDisplay(w), ButtonPressMask|ButtonReleaseMask, + smw->simple_menu.cursor, + XtLastTimestampProcessed(XtDisplay(w))); +} + +/* Function Name: MakeSetValuesRequest + * Description: Makes a (possibly recursive) call to SetValues, + * I take great pains to not go into an infinite loop. + * Arguments: w - the simple menu widget. + * width, height - the size of the ask for. + * Returns: none + */ + +static void +MakeSetValuesRequest(w, width, height) +Widget w; +Dimension width, height; +{ + SimpleMenuWidget smw = (SimpleMenuWidget) w; + + if ( !smw->simple_menu.recursive_set_values ) { + if ( (smw->core.width != width) || (smw->core.height != height) ) { + Arg arglist[2]; + + smw->simple_menu.recursive_set_values = TRUE; + XtSetArg(arglist[0], XtNwidth, width); + XtSetArg(arglist[1], XtNheight, height); + XtSetValues(w, arglist, TWO); + } + else if (XtIsRealized( (Widget) smw)) + Redisplay((Widget) smw, (XEvent *) NULL, (Region) NULL); + } + smw->simple_menu.recursive_set_values = FALSE; +} + +/* + * Function Name: SetMarginWidths() + * Description: Set new margin values for all menu children. + * Arguments: w - the simple menu widget + * w_ent - the current menu entry + */ +static void +SetMarginWidths(w) +Widget w; +{ + SimpleMenuWidget smw = (SimpleMenuWidget)w; + SmeObject *entry; + SmeBSBObject bsb_entry; + Dimension l_mrgn, l_bmw, r_mrgn, r_bmw; + + if (smw->simple_menu.left_whitespace || smw->simple_menu.right_whitespace) + { + /* determine the widest bitmaps */ + l_bmw = r_bmw = (Dimension)0; + ForAllChildren(smw, entry) + { + if (!XtIsManaged((Widget)*entry)) continue; + if (*entry == smw->simple_menu.label) continue; + if (XtIsSubclass((Widget)*entry, smeLineObjectClass)) + continue; + + bsb_entry = (SmeBSBObject)&((*entry)->object); + if (bsb_entry->sme_bsb.left_bitmap_width > l_bmw) + l_bmw = bsb_entry->sme_bsb.left_bitmap_width; + if (bsb_entry->sme_bsb.right_bitmap_width > r_bmw) + r_bmw = bsb_entry->sme_bsb.right_bitmap_width; + } + + /* set the margin values */ + if (smw->simple_menu.left_whitespace) + l_mrgn = l_bmw + + (smw->simple_menu.left_whitespace * ((l_bmw) ? 2 : 1)); + if (smw->simple_menu.right_whitespace) + r_mrgn = r_bmw + + (smw->simple_menu.right_whitespace * ((r_bmw) ? 2 : 1)); + + /* make all the margins uniform */ + ForAllChildren(smw, entry) + { + if (!XtIsManaged((Widget)*entry)) continue; + if (*entry == smw->simple_menu.label) continue; + if (XtIsSubclass((Widget)*entry, smeLineObjectClass)) + continue; + + bsb_entry = (SmeBSBObject)&((*entry)->object); + if (smw->simple_menu.left_whitespace) + bsb_entry->sme_bsb.left_margin = l_mrgn; + if (smw->simple_menu.right_whitespace) + bsb_entry->sme_bsb.right_margin = r_mrgn; + } + } +} + +/* Function Name: GetMenuWidth + * Description: Sets the width to the widest entry in pixels. + * Arguments: w - the simple menu widget. + * w_ent - the current menu entry. + * Returns: width of menu. + */ + +static Dimension +GetMenuWidth(w, w_ent) +Widget w, w_ent; +{ + SmeObject cur_entry = (SmeObject) w_ent; + SimpleMenuWidget smw = (SimpleMenuWidget) w; + Dimension width, widest = (Dimension) 0; + SmeObject * entry; + + if ( smw->simple_menu.menu_width ) + return(smw->core.width); + + ForAllChildren(smw, entry) { + XtWidgetGeometry preferred; + + if (!XtIsManaged( (Widget) *entry)) continue; + + if (*entry != cur_entry) { + XtQueryGeometry((Widget) *entry, (XtWidgetGeometry *)NULL, &preferred); + + if (preferred.request_mode & CWWidth) + width = preferred.width; + else + width = (*entry)->rectangle.width; + } + else + width = (*entry)->rectangle.width; + + if ( width > widest ) + widest = width; + } + + return(widest); +} + +/* Function Name: GetMenuHeight + * Description: Sets the height to all the entries in pixels. + * Arguments: w - the simple menu widget. + * Returns: height of menu. + */ + +static Dimension +GetMenuHeight(w) +Widget w; +{ + SimpleMenuWidget smw = (SimpleMenuWidget) w; + ThreeDWidget tdw = (ThreeDWidget) smw->simple_menu.threeD; + SmeObject * entry; + Dimension height; + + if (smw->simple_menu.menu_height) + return(smw->core.height); + + height = smw->simple_menu.top_margin + smw->simple_menu.bottom_margin; + height += tdw->threeD.shadow_width * 2; + + if (smw->simple_menu.row_height == 0) { + ForAllChildren(smw, entry) + if (XtIsManaged ((Widget) *entry)) + height += (*entry)->rectangle.height; + } else + height += smw->simple_menu.row_height * smw->composite.num_children; + + return(height); +} + +/* Function Name: GetEventEntry + * Description: Gets an entry given an event that has X and Y coords. + * Arguments: w - the simple menu widget. + * event - the event. + * Returns: the entry that this point is in. + */ + +static SmeObject +GetEventEntry(w, event) +Widget w; +XEvent * event; +{ + Position x_loc = 0, y_loc = 0; + SimpleMenuWidget smw = (SimpleMenuWidget)w; + SmeObject *entry; + static XPoint last_pos; + XPoint pos; + int s = ((ThreeDWidget)smw->simple_menu.threeD)->threeD.shadow_width; + + switch (event->type) { + case MotionNotify: + x_loc = event->xmotion.x; + y_loc = event->xmotion.y; + pos.y = event->xmotion.y_root; + break; + case EnterNotify: + case LeaveNotify: + x_loc = event->xcrossing.x; + y_loc = event->xcrossing.y; + pos.y = event->xcrossing.y_root; + break; + case ButtonPress: + case ButtonRelease: + x_loc = event->xbutton.x; + y_loc = event->xbutton.y; + pos.y = event->xbutton.y_root; + break; + default: + XtAppError(XtWidgetToApplicationContext(w), + "Unknown event type in GetEventEntry()."); + break; + } + + if (x_loc < 0 || x_loc >= (int)smw->core.width) + return NULL; + else if (smw->simple_menu.too_tall) { + if (pos.y >= smw->simple_menu.last_y && smw->simple_menu.didnt_fit) { + if (last_pos.y && pos.y < last_pos.y) { + last_pos.y = pos.y; + return NULL; + } + smw->simple_menu.current_first += smw->simple_menu.jump_val; + Redisplay(w, (XEvent *)NULL, (Region)NULL); + last_pos.y = pos.y; + return NULL; + } else if (pos.y <= s + SMW_ARROW_SIZE && + smw->simple_menu.first_entry != smw->simple_menu.current_first) + { + if (pos.y && (!last_pos.y || pos.y > last_pos.y)) { + last_pos.y = pos.y; + return NULL; + } + smw->simple_menu.current_first -= smw->simple_menu.jump_val; + Redisplay(w, (XEvent *)NULL, (Region)NULL); + last_pos.y = pos.y; + return NULL; + } + else + last_pos.y = 0; + } else if (y_loc < 0 || y_loc >= (int)smw->core.height) + return NULL; + + ForAllChildren(smw, entry) { + int tmp_y; + + if (!XtIsManaged((Widget)*entry)) continue; + + tmp_y = (*entry)->rectangle.y - smw->simple_menu.first_y; + if (tmp_y < y_loc && tmp_y + (int)(*entry)->rectangle.height > y_loc) { + if (*entry == smw->simple_menu.label) + return NULL; /* cannot select the label */ + else + return *entry; + } + } + + return NULL; +} + +/*ARGSUSED*/ +static void +PopupCB(w, client_data, call_data) +Widget w; +XtPointer client_data, call_data; +{ + SimpleMenuWidget smw = (SimpleMenuWidget)w; + + smw->simple_menu.state &= ~SMW_UNMAPPING; +} + +static void +PopupSubMenu(smw) +SimpleMenuWidget smw; +{ + Widget menu; + SmeBSBObject entry = (SmeBSBObject)smw->simple_menu.entry_set; + Position menu_x, menu_y; + Bool popleft; + Arg args[2]; + + if (entry->sme_bsb.menu_name == NULL) + return; + + if ((menu = FindMenu((Widget)smw, entry->sme_bsb.menu_name)) == NULL) + return; + + smw->simple_menu.sub_menu = menu; + + if (!XtIsRealized(menu)) + XtRealizeWidget(menu); + + popleft = (smw->simple_menu.state & SMW_POPLEFT) != 0; + + if (popleft) + XtTranslateCoords((Widget)smw, -(int)XtWidth(menu), + XtY(entry) - XtBorderWidth(menu), &menu_x, &menu_y); + else + XtTranslateCoords((Widget)smw, XtWidth(smw), XtY(entry) + - XtBorderWidth(menu), &menu_x, &menu_y); + + if (!popleft && menu_x >= 0) { + int scr_width = WidthOfScreen(XtScreen(menu)); + + if (menu_x + XtWidth(menu) > scr_width) { + menu_x -= XtWidth(menu) + XtWidth(smw); + popleft = True; + } + } + else if (popleft && menu_x < 0) { + menu_x = 0; + popleft = False; + } + + if (menu_y >= 0) { + ThreeDWidget tdw = + (ThreeDWidget)((SimpleMenuWidget)menu)->simple_menu.threeD; + int scr_height = HeightOfScreen(XtScreen(menu)); + + if (menu_y + XtHeight(menu) > scr_height) + menu_y = scr_height - XtHeight(menu) - XtBorderWidth(menu); + + menu_y -= tdw->threeD.shadow_width; + } + if (menu_y < 0) + menu_y = 0; + + XtSetArg(args[0], XtNx, menu_x); + XtSetArg(args[1], XtNy, menu_y); + XtSetValues(menu, args, TWO); + + if (popleft) + ((SimpleMenuWidget)menu)->simple_menu.state |= SMW_POPLEFT; + else + ((SimpleMenuWidget)menu)->simple_menu.state &= ~SMW_POPLEFT; + + XtPopup(menu, XtGrabNone); +} + +static void +Popdown(w, event, params, num_params) +Widget w; +XEvent *event; +String *params; +Cardinal *num_params; +{ + SimpleMenuWidget smw = (SimpleMenuWidget)w; + + while (XtParent(w) && + XtIsSubclass(XtParent(w), simpleMenuWidgetClass)) { + if (((SimpleMenuWidget)XtParent(w))->simple_menu.sub_menu == (Widget)w) + { + w = XtParent(w); + smw = (SimpleMenuWidget)w; + smw->simple_menu.entry_set = NULL; + } + else + break; + } + + smw->simple_menu.state |= SMW_UNMAPPING; + PopdownSubMenu(smw); + + XtCallActionProc(w, "XtMenuPopdown", event, params, *num_params); +} + +static void +PopdownSubMenu(smw) +SimpleMenuWidget smw; +{ + SimpleMenuWidget menu = (SimpleMenuWidget)smw->simple_menu.sub_menu; + + if (!menu) return; + + menu->simple_menu.state &= ~SMW_POPLEFT; + menu->simple_menu.state |= SMW_UNMAPPING; + PopdownSubMenu(menu); + + XtPopdown((Widget)menu); + + smw->simple_menu.sub_menu = NULL; +} + diff --git a/src/SimpleMenu.h b/src/SimpleMenu.h new file mode 100644 index 0000000..9e4c45c --- /dev/null +++ b/src/SimpleMenu.h @@ -0,0 +1,159 @@ +/* + * $XConsortium: SimpleMenu.h,v 1.22 94/04/17 20:12:47 kaleb Exp $ + * +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + * Author: Chris D. Peterson, MIT X Consortium + */ + +/* + * SimpleMenu.h - Public Header file for SimpleMenu widget. + * + * This is the public header file for the Athena SimpleMenu widget. + * It is intended to provide one pane pulldown and popup menus within + * the framework of the X Toolkit. As the name implies it is a first and + * by no means complete implementation of menu code. It does not attempt to + * fill the needs of all applications, but does allow a resource oriented + * interface to menus. + * + * Date: April 3, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifndef _SimpleMenu_h +#define _SimpleMenu_h + +#include <X11/Shell.h> +#include <X11/Xmu/Converters.h> + +/**************************************************************** + * + * SimpleMenu widget + * + ****************************************************************/ + +/* SimpleMenu Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + background Background Pixel XtDefaultBackground + backgroundPixmap BackgroundPixmap Pixmap None + borderColor BorderColor Pixel XtDefaultForeground + borderPixmap BorderPixmap Pixmap None + borderWidth BorderWidth Dimension 1 + bottomMargin VerticalMargins Dimension VerticalSpace + columnWidth ColumnWidth Dimension Width of widest text + cursor Cursor Cursor None + destroyCallback Callback Pointer NULL + height Height Dimension 0 + label Label String NULL (No label) + labelClass LabelClass Pointer smeBSBObjectClass + mappedWhenManaged MappedWhenManaged Boolean True + rowHeight RowHeight Dimension Height of Font + sensitive Sensitive Boolean True + topMargin VerticalMargins Dimension VerticalSpace + width Width Dimension 0 + x Position Position 0n + y Position Position 0 + +*/ + +typedef struct _SimpleMenuClassRec* SimpleMenuWidgetClass; +typedef struct _SimpleMenuRec* SimpleMenuWidget; + +extern WidgetClass simpleMenuWidgetClass; + +#define XtNcursor "cursor" +#define XtNbottomMargin "bottomMargin" +#define XtNcolumnWidth "columnWidth" +#define XtNlabelClass "labelClass" +#define XtNmenuOnScreen "menuOnScreen" +#define XtNpopupOnEntry "popupOnEntry" +#define XtNrowHeight "rowHeight" +#define XtNtopMargin "topMargin" +#define XtNjumpScroll "jumpScroll" +#define XtNleftWhitespace "leftWhitespace" +#define XtNrightWhitespace "rightWhitespace" + +#define XtCColumnWidth "ColumnWidth" +#define XtCLabelClass "LabelClass" +#define XtCMenuOnScreen "MenuOnScreen" +#define XtCPopupOnEntry "PopupOnEntry" +#define XtCRowHeight "RowHeight" +#define XtCVerticalMargins "VerticalMargins" +#define XtCJumpScroll "JumpScroll" +#define XtCLeftWhitespace "LeftWhitespace" +#define XtCRightWhitespace "RightWhitespace" +#define XtCHorizontalWhitespace "HorizontalWhitespace" + +/************************************************************ + * + * Public Functions. + * + ************************************************************/ + +_XFUNCPROTOBEGIN + +/* Function Name: XawSimpleMenuAddGlobalActions + * Description: adds the global actions to the simple menu widget. + * Arguments: app_con - the appcontext. + * Returns: none. + */ + +extern void XawSimpleMenuAddGlobalActions( +#if NeedFunctionPrototypes + XtAppContext /* app_con */ +#endif +); + +/* Function Name: XawSimpleMenuGetActiveEntry + * Description: Gets the currently active (set) entry. + * Arguments: w - the smw widget. + * Returns: the currently set entry or NULL if none is set. + */ + +extern Widget XawSimpleMenuGetActiveEntry( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +/* Function Name: XawSimpleMenuClearActiveEntry + * Description: Unsets the currently active (set) entry. + * Arguments: w - the smw widget. + * Returns: none. + */ + +extern void XawSimpleMenuClearActiveEntry( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +_XFUNCPROTOEND + +#endif /* _SimpleMenu_h */ diff --git a/src/SimpleP.h b/src/SimpleP.h new file mode 100644 index 0000000..ce7d744 --- /dev/null +++ b/src/SimpleP.h @@ -0,0 +1,89 @@ +/*********************************************************** + + $XConsortium: SimpleP.h,v 1.12 94/04/17 20:12:47 kaleb Exp $ + + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _SimpleP_h +#define _SimpleP_h + +#include "Xaw3dP.h" +#include <X11/Xaw3d/Simple.h> + +typedef struct { + Boolean (*change_sensitive)(/* widget */); +} SimpleClassPart; + +#define XtInheritChangeSensitive ((Boolean (*)())_XtInherit) + +typedef struct _SimpleClassRec { + CoreClassPart core_class; + SimpleClassPart simple_class; +} SimpleClassRec; + +extern SimpleClassRec simpleClassRec; + +typedef struct { + /* resources */ + Cursor cursor; + Pixmap insensitive_border; + String cursor_name; /* cursor specified by name. */ + + Pixel pointer_fg, pointer_bg; /* Pointer colors. */ +#ifdef XAW_INTERNATIONALIZATION + Boolean international; +#endif + /* private state */ +} SimplePart; + +typedef struct _SimpleRec { + CorePart core; + SimplePart simple; +} SimpleRec; + +#endif /* _SimpleP_h */ diff --git a/src/Sme.c b/src/Sme.c new file mode 100644 index 0000000..f3b34dd --- /dev/null +++ b/src/Sme.c @@ -0,0 +1,246 @@ +/* $XConsortium: Sme.c,v 1.12 94/04/17 20:12:48 kaleb Exp $ */ + +/* +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + */ + +/* + * Sme.c - Source code for the generic menu entry + * + * Date: September 26, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#include "Xaw3dP.h" +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/SmeP.h> +#include <X11/Xaw3d/Cardinals.h> + +#define offset(field) XtOffsetOf(SmeRec, sme.field) +static XtResource resources[] = { + {XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer), + offset(callbacks), XtRCallback, (XtPointer)NULL}, +#ifdef XAW_INTERNATIONALIZATION + {XtNinternational, XtCInternational, XtRBoolean, sizeof(Boolean), + offset(international), XtRImmediate, (XtPointer) FALSE}, +#endif +}; +#undef offset + +/* + * Semi Public function definitions. + */ + +static void Unhighlight(), Highlight(), Notify(), ClassPartInitialize(); +static void Initialize(); +static XtGeometryResult QueryGeometry(); + +#define SUPERCLASS (&rectObjClassRec) + +SmeClassRec smeClassRec = { + { + /* superclass */ (WidgetClass) SUPERCLASS, + /* class_name */ "Sme", + /* size */ sizeof(SmeRec), + /* class_initialize */ XawInitializeWidgetSet, + /* class_part_initialize*/ ClassPartInitialize, + /* Class init'ed */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ NULL, + /* actions */ NULL, + /* num_actions */ ZERO, + /* resources */ resources, + /* resource_count */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ FALSE, + /* compress_exposure */ FALSE, + /* compress_enterleave*/ FALSE, + /* visible_interest */ FALSE, + /* destroy */ NULL, + /* resize */ NULL, + /* expose */ NULL, + /* set_values */ NULL, + /* set_values_hook */ NULL, + /* set_values_almost */ XtInheritSetValuesAlmost, + /* get_values_hook */ NULL, + /* accept_focus */ NULL, + /* intrinsics version */ XtVersion, + /* callback offsets */ NULL, + /* tm_table */ NULL, + /* query_geometry */ QueryGeometry, + /* display_accelerator*/ NULL, + /* extension */ NULL + },{ + /* Simple Menu Entry Fields */ + + /* highlight */ Highlight, + /* unhighlight */ Unhighlight, + /* notify */ Notify, + /* extension */ NULL + } +}; + +WidgetClass smeObjectClass = (WidgetClass) &smeClassRec; + +/************************************************************ + * + * Semi-Public Functions. + * + ************************************************************/ + +/* Function Name: ClassPartInitialize + * Description: handles inheritance of class functions. + * Arguments: class - the widget classs of this widget. + * Returns: none. + */ + +static void +ClassPartInitialize(class) +WidgetClass class; +{ + SmeObjectClass m_ent, superC; + + m_ent = (SmeObjectClass) class; + superC = (SmeObjectClass) m_ent->rect_class.superclass; + +/* + * We don't need to check for null super since we'll get to TextSink + * eventually. + */ + + if (m_ent->sme_class.highlight == XtInheritHighlight) + m_ent->sme_class.highlight = superC->sme_class.highlight; + + if (m_ent->sme_class.unhighlight == XtInheritUnhighlight) + m_ent->sme_class.unhighlight = superC->sme_class.unhighlight; + + if (m_ent->sme_class.notify == XtInheritNotify) + m_ent->sme_class.notify = superC->sme_class.notify; +} + +/* Function Name: Initialize + * Description: Initializes the simple menu widget + * Arguments: request - the widget requested by the argument list. + * new - the new widget with both resource and non + * resource values. + * Returns: none. + * + * MENU ENTRIES CANNOT HAVE BORDERS. + */ + +/* ARGSUSED */ +static void +Initialize(request, new, args, num_args) +Widget request, new; +ArgList args; +Cardinal *num_args; +{ + SmeObject entry = (SmeObject) new; + + entry->rectangle.border_width = 0; +} + +/* Function Name: Highlight + * Description: The default highlight proceedure for menu entries. + * Arguments: w - the menu entry. + * Returns: none. + */ + +/* ARGSUSED */ +static void +Highlight(w) +Widget w; +{ +/* This space intentionally left blank. */ +} + +/* Function Name: Unhighlight + * Description: The default unhighlight proceedure for menu entries. + * Arguments: w - the menu entry. + * Returns: none. + */ + +/* ARGSUSED */ +static void +Unhighlight(w) +Widget w; +{ +/* This space intentionally left blank. */ +} + +/* Function Name: Notify + * Description: calls the callback proceedures for this entry. + * Arguments: w - the menu entry. + * Returns: none. + */ + +static void +Notify(w) +Widget w; +{ + XtCallCallbacks(w, XtNcallback, (XtPointer)NULL); +} + +/* Function Name: QueryGeometry. + * Description: Returns the preferred geometry for this widget. + * Arguments: w - the menu entry object. + * itended, return - the intended and return geometry info. + * Returns: A Geometry Result. + * + * See the Intrinsics manual for details on what this function is for. + * + * I just return the height and a width of 1. + */ + +static XtGeometryResult +QueryGeometry(w, intended, return_val) +Widget w; +XtWidgetGeometry *intended, *return_val; +{ + SmeObject entry = (SmeObject) w; + Dimension width; + XtGeometryResult ret_val = XtGeometryYes; + XtGeometryMask mode = intended->request_mode; + + width = 1; /* we can be really small. */ + + if ( ((mode & CWWidth) && (intended->width != width)) || + !(mode & CWWidth) ) { + return_val->request_mode |= CWWidth; + return_val->width = width; + mode = return_val->request_mode; + + if ( (mode & CWWidth) && (width == entry->rectangle.width) ) + return(XtGeometryNo); + return(XtGeometryAlmost); + } + return(ret_val); +} diff --git a/src/Sme.h b/src/Sme.h new file mode 100644 index 0000000..709b105 --- /dev/null +++ b/src/Sme.h @@ -0,0 +1,81 @@ +/* + * $XConsortium: Sme.h,v 1.6 94/04/17 20:12:48 kaleb Exp $ + * +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + */ + +/* + * Sme.h - Public Header file for Sme object. + * + * This is the public header file for the Athena Sme object. + * It is intended to be used with the simple menu widget. + * + * Date: April 3, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifndef _Sme_h +#define _Sme_h + +#include "Xaw3dP.h" +#include <X11/RectObj.h> + +/**************************************************************** + * + * Sme Object + * + ****************************************************************/ + +/* Simple Menu Entry Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + callback Callback Pointer NULL + destroyCallback Callback Pointer NULL + height Height Dimension 0 + sensitive Sensitive Boolean True + width Width Dimension 0 + x Position Position 0n + y Position Position 0 + +*/ + +#ifdef XAW_INTERNATIONALIZATION +#ifndef XtCInternational +#define XtCInternational "International" +#endif +#ifndef XtNinternational +#define XtNinternational "international" +#endif +#endif + +typedef struct _SmeClassRec* SmeObjectClass; +typedef struct _SmeRec* SmeObject; + +extern WidgetClass smeObjectClass; + +#endif /* _Sme_h */ diff --git a/src/SmeBSB.c b/src/SmeBSB.c new file mode 100644 index 0000000..63bdc49 --- /dev/null +++ b/src/SmeBSB.c @@ -0,0 +1,877 @@ +/* $XConsortium: SmeBSB.c,v 1.19 94/04/17 20:12:49 kaleb Exp $ */ + +/* +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + */ + +/* + * Portions Copyright (c) 2003 Brian V. Smith + * Rights, permissions, and disclaimer per the above X Consortium license. + */ + +/* + * SmeBSB.c - Source code file for BSB Menu Entry object. + * + * Date: September 26, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#include "Xaw3dP.h" +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xos.h> +#include <X11/Xmu/Drawing.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/ThreeDP.h> +#include <X11/Xaw3d/SimpleMenP.h> +#include <X11/Xaw3d/SmeBSBP.h> +#include <X11/Xaw3d/Cardinals.h> +#include <stdio.h> + +/* needed for abs() */ +#ifndef X_NOT_STDC_ENV +#include <stdlib.h> +#else +extern int abs(); +#endif + +#define offset(field) XtOffsetOf(SmeBSBRec, sme_bsb.field) + +static XtResource resources[] = { + {XtNlabel, XtCLabel, XtRString, sizeof(String), + offset(label), XtRString, NULL}, + {XtNvertSpace, XtCVertSpace, XtRInt, sizeof(int), + offset(vert_space), XtRImmediate, (XtPointer) 25}, + {XtNleftBitmap, XtCLeftBitmap, XtRBitmap, sizeof(Pixmap), + offset(left_bitmap), XtRImmediate, (XtPointer)None}, + {XtNjustify, XtCJustify, XtRJustify, sizeof(XtJustify), + offset(justify), XtRImmediate, (XtPointer) XtJustifyLeft}, + {XtNrightBitmap, XtCRightBitmap, XtRBitmap, sizeof(Pixmap), + offset(right_bitmap), XtRImmediate, (XtPointer)None}, + {XtNleftMargin, XtCHorizontalMargins, XtRDimension, sizeof(Dimension), + offset(left_margin), XtRImmediate, (XtPointer) 4}, + {XtNrightMargin, XtCHorizontalMargins, XtRDimension, sizeof(Dimension), + offset(right_margin), XtRImmediate, (XtPointer) 4}, + {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), + offset(foreground), XtRString, XtDefaultForeground}, + {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *), + offset(font), XtRString, XtDefaultFont}, +#ifdef XAW_INTERNATIONALIZATION + {XtNfontSet, XtCFontSet, XtRFontSet, sizeof(XFontSet ), + offset(fontset),XtRString, XtDefaultFontSet}, +#endif + {XtNmenuName, XtCMenuName, XtRString, sizeof(String), + offset(menu_name), XtRImmediate, (XtPointer) NULL}, + {XtNunderline, XtCIndex, XtRInt, sizeof(int), + offset(underline), XtRImmediate, (XtPointer) -1}, +}; +#undef offset + +/* + * Semi Public function definitions. + */ + +static void Redisplay(), Destroy(), Initialize(); +static void Highlight(), Unhighlight(); +static void ClassInitialize(); +static Boolean SetValues(); +static XtGeometryResult QueryGeometry(); + +/* + * Private Function Definitions. + */ + +static void GetDefaultSize(), DrawBitmaps(), GetBitmapInfo(); +static void CreateGCs(), DestroyGCs(), FlipColors(); + +#define superclass (&smeThreeDClassRec) +SmeBSBClassRec smeBSBClassRec = { + { + /* superclass */ (WidgetClass) superclass, + /* class_name */ "SmeBSB", + /* size */ sizeof(SmeBSBRec), + /* class_initializer */ ClassInitialize, + /* class_part_initialize*/ NULL, + /* Class init'ed */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ NULL, + /* actions */ NULL, + /* num_actions */ ZERO, + /* resources */ resources, + /* resource_count */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ FALSE, + /* compress_exposure */ FALSE, + /* compress_enterleave*/ FALSE, + /* visible_interest */ FALSE, + /* destroy */ Destroy, + /* resize */ NULL, + /* expose */ Redisplay, + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* set_values_almost */ XtInheritSetValuesAlmost, + /* get_values_hook */ NULL, + /* accept_focus */ NULL, + /* intrinsics version */ XtVersion, + /* callback offsets */ NULL, + /* tm_table */ NULL, + /* query_geometry */ QueryGeometry, + /* display_accelerator*/ NULL, + /* extension */ NULL + },{ + /* SimpleMenuClass Fields */ + /* highlight */ Highlight, + /* unhighlight */ Unhighlight, + /* notify */ XtInheritNotify, + /* extension */ NULL + }, { + /* ThreeDClass Fields */ + /* shadowdraw */ XtInheritXawSme3dShadowDraw + }, { + /* BSBClass Fields */ + /* extension */ NULL + } +}; + +WidgetClass smeBSBObjectClass = (WidgetClass) &smeBSBClassRec; + +/************************************************************ + * + * Semi-Public Functions. + * + ************************************************************/ + +/* Function Name: ClassInitialize + * Description: Initializes the SmeBSBObject. + * Arguments: none. + * Returns: none. + */ + +static void +ClassInitialize() +{ + XawInitializeWidgetSet(); + XtAddConverter( XtRString, XtRJustify, XmuCvtStringToJustify, + (XtConvertArgList)NULL, (Cardinal)0 ); +} + +/* Function Name: Initialize + * Description: Initializes the simple menu widget + * Arguments: request - the widget requested by the argument list. + * new - the new widget with both resource and non + * resource values. + * Returns: none. + */ + +/* ARGSUSED */ +static void +Initialize(request, new, args, num_args) +Widget request, new; +ArgList args; +Cardinal *num_args; +{ + SmeBSBObject entry = (SmeBSBObject) new; + + if (entry->sme_bsb.label == NULL) + entry->sme_bsb.label = XtName(new); + else + entry->sme_bsb.label = XtNewString( entry->sme_bsb.label ); + + CreateGCs(new); + + GetBitmapInfo(new, TRUE); /* Left Bitmap Info */ + GetBitmapInfo(new, FALSE); /* Right Bitmap Info */ + + entry->sme_bsb.left_stippled = entry->sme_bsb.right_stippled = None; + + GetDefaultSize(new, &(entry->rectangle.width), &(entry->rectangle.height)); +} + +/* Function Name: Destroy + * Description: Called at destroy time, cleans up. + * Arguments: w - the simple menu widget. + * Returns: none. + */ + +static void +Destroy(w) +Widget w; +{ + SmeBSBObject entry = (SmeBSBObject) w; + + DestroyGCs(w); +#ifdef XAW_MULTIPLANE_PIXMAPS + if (entry->sme_bsb.left_stippled != None) + XFreePixmap(XtDisplayOfObject(w), entry->sme_bsb.left_stippled); + if (entry->sme_bsb.right_stippled != None) + XFreePixmap(XtDisplayOfObject(w), entry->sme_bsb.right_stippled); +#endif + if (entry->sme_bsb.label != XtName(w)) + XtFree(entry->sme_bsb.label); +} + +/* Function Name: Redisplay + * Description: Redisplays the contents of the widget. + * Arguments: w - the simple menu widget. + * event - the X event that caused this redisplay. + * region - the region the needs to be repainted. + * Returns: none. + */ + +/* ARGSUSED */ +static void +Redisplay(w, event, region) +Widget w; +XEvent * event; +Region region; +{ + GC gc; + SmeBSBObject entry = (SmeBSBObject) w; + Dimension s = entry->sme_threeD.shadow_width; + int font_ascent = 0, font_descent = 0, y_loc; +#ifdef XAW_INTERNATIONALIZATION + int fontset_ascent = 0, fontset_descent = 0; + XFontSetExtents *ext = XExtentsOfFontSet(entry->sme_bsb.fontset); +#endif + + entry->sme_bsb.set_values_area_cleared = FALSE; +#ifdef XAW_INTERNATIONALIZATION + if ( entry->sme.international == True ) { + fontset_ascent = abs(ext->max_ink_extent.y); + fontset_descent = ext->max_ink_extent.height - fontset_ascent; + } + else +#endif + { /*else, compute size from font like R5*/ + font_ascent = entry->sme_bsb.font->max_bounds.ascent; + font_descent = entry->sme_bsb.font->max_bounds.descent; + } + y_loc = entry->rectangle.y; + + if (XtIsSensitive(w) && XtIsSensitive( XtParent(w) ) ) { + if ( w == XawSimpleMenuGetActiveEntry(XtParent(w)) ) { + XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w), + entry->sme_bsb.norm_gc, s, y_loc + s, + (unsigned int) entry->rectangle.width - 2 * s, + (unsigned int) entry->rectangle.height - 2 * s); + gc = entry->sme_bsb.rev_gc; + } + else + gc = entry->sme_bsb.norm_gc; + } + else + gc = entry->sme_bsb.norm_gray_gc; + + if (entry->sme_bsb.label != NULL) { + int x_loc = entry->sme_bsb.left_margin; + int len = strlen(entry->sme_bsb.label); + int width, t_width; + char * label = entry->sme_bsb.label; + + switch(entry->sme_bsb.justify) { + case XtJustifyCenter: +#ifdef XAW_INTERNATIONALIZATION + if ( entry->sme.international == True ) + t_width = XmbTextEscapement(entry->sme_bsb.fontset,label,len); + else +#endif + t_width = XTextWidth(entry->sme_bsb.font, label, len); + + width = entry->rectangle.width - + (entry->sme_bsb.left_margin + + entry->sme_bsb.right_margin); + x_loc += (width - t_width)/2; + break; + case XtJustifyRight: +#ifdef XAW_INTERNATIONALIZATION + if ( entry->sme.international == True ) + t_width = XmbTextEscapement(entry->sme_bsb.fontset,label,len); + else +#endif + t_width = XTextWidth(entry->sme_bsb.font, label, len); + + x_loc = entry->rectangle.width - + (entry->sme_bsb.right_margin + t_width); + break; + case XtJustifyLeft: + default: + break; + } + + /* this will center the text in the gadget top-to-bottom */ + +#ifdef XAW_INTERNATIONALIZATION + if ( entry->sme.international==True ) { + y_loc += ((int)entry->rectangle.height - + (fontset_ascent + fontset_descent)) / 2 + fontset_ascent; + + XmbDrawString(XtDisplayOfObject(w), XtWindowOfObject(w), + entry->sme_bsb.fontset, gc, x_loc + s, y_loc, label, len); + } + else +#endif + { + y_loc += ((int)entry->rectangle.height - + (font_ascent + font_descent)) / 2 + font_ascent; + + XDrawString(XtDisplayOfObject(w), XtWindowOfObject(w), gc, + x_loc + s, y_loc, label, len); + } + + if (entry->sme_bsb.underline >= 0 && entry->sme_bsb.underline < len) { + int ul = entry->sme_bsb.underline; + int ul_x1_loc = x_loc + s; + int ul_wid; + + if (ul != 0) + ul_x1_loc += XTextWidth(entry->sme_bsb.font, label, ul); + ul_wid = XTextWidth(entry->sme_bsb.font, &label[ul], 1) - 2; + XDrawLine(XtDisplayOfObject(w), XtWindowOfObject(w), gc, + ul_x1_loc, y_loc + 1, ul_x1_loc + ul_wid, y_loc + 1); + } + } + + DrawBitmaps(w, gc); +} + + +/* Function Name: SetValues + * Description: Relayout the menu when one of the resources is changed. + * Arguments: current - current state of the widget. + * request - what was requested. + * new - what the widget will become. + * Returns: none + */ + +/* ARGSUSED */ +static Boolean +SetValues(current, request, new, args, num_args) +Widget current, request, new; +ArgList args; +Cardinal *num_args; +{ + Widget parent = XtParent(new); + SmeBSBObject entry = (SmeBSBObject) new; + SmeBSBObject old_entry = (SmeBSBObject) current; + Boolean ret_val = FALSE; + + if (old_entry->sme_bsb.label != entry->sme_bsb.label) { + if (old_entry->sme_bsb.label != XtName( new ) ) + XtFree( (char *) old_entry->sme_bsb.label ); + + if (entry->sme_bsb.label != XtName(new) ) + entry->sme_bsb.label = XtNewString( entry->sme_bsb.label ); + + ret_val = TRUE; + } + + if (entry->sme_bsb.underline != old_entry->sme_bsb.underline) + ret_val = TRUE; + + if (entry->rectangle.sensitive != old_entry->rectangle.sensitive) + ret_val = TRUE; + +#ifdef XAW_INTERNATIONALIZATION + if ( ( (old_entry->sme_bsb.font != entry->sme_bsb.font) && + (old_entry->sme.international == False ) ) || + (old_entry->sme_bsb.foreground != entry->sme_bsb.foreground) ) { +#else + if ( (old_entry->sme_bsb.font != entry->sme_bsb.font) || + (old_entry->sme_bsb.foreground != entry->sme_bsb.foreground) ) { +#endif + DestroyGCs(current); + CreateGCs(new); + + ret_val = TRUE; + } + + if (entry->sme_bsb.left_bitmap != old_entry->sme_bsb.left_bitmap) + { + GetBitmapInfo(new, TRUE); + +#ifdef XAW_MULTIPLANE_PIXMAPS + entry->sme_bsb.left_stippled = None; + if (old_entry->sme_bsb.left_stippled != None) + XFreePixmap(XtDisplayOfObject(current), + old_entry->sme_bsb.left_stippled); +#endif + + ret_val = TRUE; + } + + if (entry->sme_bsb.left_margin != old_entry->sme_bsb.left_margin) + ret_val = TRUE; + + if (entry->sme_bsb.right_bitmap != old_entry->sme_bsb.right_bitmap) + { + GetBitmapInfo(new, FALSE); + +#ifdef XAW_MULTIPLANE_PIXMAPS + entry->sme_bsb.right_stippled = None; + if (old_entry->sme_bsb.right_stippled != None) + XFreePixmap(XtDisplayOfObject(current), + old_entry->sme_bsb.right_stippled); +#endif + + ret_val = TRUE; + } + + if (entry->sme_bsb.right_margin != old_entry->sme_bsb.right_margin) + ret_val = TRUE; + +#ifdef XAW_INTERNATIONALIZATION + if ( ( old_entry->sme_bsb.fontset != entry->sme_bsb.fontset) && + (old_entry->sme.international == True ) ) + /* don't change the GCs - the fontset is not in them */ + ret_val = TRUE; +#endif + + if (ret_val) { + GetDefaultSize(new, + &(entry->rectangle.width), &(entry->rectangle.height)); + entry->sme_bsb.set_values_area_cleared = TRUE; + + (parent->core.widget_class->core_class.resize)(new); + } + + return(ret_val); +} + +/* Function Name: QueryGeometry. + * Description: Returns the preferred geometry for this widget. + * Arguments: w - the menu entry object. + * itended, return_val - the intended and return geometry info. + * Returns: A Geometry Result. + * + * See the Intrinsics manual for details on what this function is for. + * + * I just return the height and width of the label plus the margins. + */ + +static XtGeometryResult +QueryGeometry(w, intended, return_val) +Widget w; +XtWidgetGeometry *intended, *return_val; +{ + SmeBSBObject entry = (SmeBSBObject) w; + Dimension width, height, h; + XtGeometryResult ret_val = XtGeometryYes; + XtGeometryMask mode = intended->request_mode; + + GetDefaultSize(w, &width, &height ); + + if ( ((mode & CWWidth) && (intended->width != width)) || + !(mode & CWWidth) ) { + return_val->request_mode |= CWWidth; + return_val->width = width; + ret_val = XtGeometryAlmost; + } + + if ( ((mode & CWHeight) && (intended->height != height)) || + !(mode & CWHeight) ) { + return_val->request_mode |= CWHeight; + return_val->height = height; + ret_val = XtGeometryAlmost; + } + + if (ret_val == XtGeometryAlmost) { + mode = return_val->request_mode; + + if ( ((mode & CWWidth) && (width == entry->rectangle.width)) && + ((mode & CWHeight) && (height == entry->rectangle.height)) ) + return(XtGeometryNo); + } + + entry->rectangle.width = width; + entry->rectangle.height = height; + + return(ret_val); +} + +/* + * FlipColors() used to be called directly, but it's blind + * state toggling caused re-unhighlighting problems. + */ + +static void +Highlight(w) +Widget w; +{ + SmeBSBObject entry = (SmeBSBObject) w; + + entry->sme_threeD.shadowed = True; + FlipColors(w); +} + +static void +Unhighlight(w) +Widget w; +{ + SmeBSBObject entry = (SmeBSBObject) w; + + entry->sme_threeD.shadowed = False; + FlipColors(w); +} + +/************************************************************ + * + * Private Functions. + * + ************************************************************/ + +/* Function Name: GetDefaultSize + * Description: Calculates the Default (preferred) size of + * this menu entry. + * Arguments: w - the menu entry widget. + * width, height - default sizes (RETURNED). + * Returns: none. + */ + +static void +GetDefaultSize(w, width, height) +Widget w; +Dimension * width, * height; +{ + SmeBSBObject entry = (SmeBSBObject) w; + Dimension h; + +#ifdef XAW_INTERNATIONALIZATION + if ( entry->sme.international == True ) { + XFontSetExtents *ext = XExtentsOfFontSet(entry->sme_bsb.fontset); + + if (entry->sme_bsb.label == NULL) + *width = 0; + else + *width = XmbTextEscapement(entry->sme_bsb.fontset, entry->sme_bsb.label, + strlen(entry->sme_bsb.label)); + + *height = ext->max_ink_extent.height; + } + else +#endif + { + if (entry->sme_bsb.label == NULL) + *width = 0; + else + *width = XTextWidth(entry->sme_bsb.font, entry->sme_bsb.label, + strlen(entry->sme_bsb.label)); + + *height = (entry->sme_bsb.font->max_bounds.ascent + + entry->sme_bsb.font->max_bounds.descent); + } + + *width += entry->sme_bsb.left_margin + entry->sme_bsb.right_margin; + *width += (2 * entry->sme_threeD.shadow_width); + + h = (entry->sme_bsb.left_bitmap_height > entry->sme_bsb.right_bitmap_height) + ? entry->sme_bsb.left_bitmap_height : entry->sme_bsb.right_bitmap_height; + if (h > *height) *height = h; + *height = ((int)*height * (100 + entry->sme_bsb.vert_space)) / 100; + *height += (2 * entry->sme_threeD.shadow_width); +} + +/* Function Name: DrawBitmaps + * Description: Draws left and right bitmaps. + * Arguments: w - the simple menu widget. + * gc - graphics context to use for drawing. + * Returns: none + */ + +static void +DrawBitmaps(w, gc) +Widget w; +GC gc; +{ +#ifdef XAW_MULTIPLANE_PIXMAPS + Widget parent = XtParent(w); +#endif + int x_loc, y_loc; + SmeBSBObject entry = (SmeBSBObject) w; + Pixmap pm; + + if ( (entry->sme_bsb.left_bitmap == None) && + (entry->sme_bsb.right_bitmap == None) ) return; + +/* + * Draw Left Bitmap. + */ + + if (entry->sme_bsb.left_bitmap != None) { + x_loc = entry->sme_threeD.shadow_width + + (int)(entry->sme_bsb.left_margin - + entry->sme_bsb.left_bitmap_width) / 2; + + y_loc = entry->rectangle.y + (int)(entry->rectangle.height - + entry->sme_bsb.left_bitmap_height) / 2; + + pm = entry->sme_bsb.left_bitmap; +#ifdef XAW_MULTIPLANE_PIXMAPS + if (!XtIsSensitive(w)) { + if (entry->sme_bsb.left_stippled == None) + entry->sme_bsb.left_stippled = stipplePixmap(w, + entry->sme_bsb.left_bitmap, + parent->core.colormap, + parent->core.background_pixel, + entry->sme_bsb.left_depth); + if (entry->sme_bsb.left_stippled != None) + pm = entry->sme_bsb.left_stippled; + } +#endif + + if (entry->sme_bsb.left_depth == 1) + XCopyPlane(XtDisplayOfObject(w), pm, + XtWindowOfObject(w), gc, 0, 0, + entry->sme_bsb.left_bitmap_width, + entry->sme_bsb.left_bitmap_height, x_loc, y_loc, 1); + else + XCopyArea (XtDisplayOfObject(w), pm, + XtWindowOfObject(w), gc, 0, 0, + entry->sme_bsb.left_bitmap_width, + entry->sme_bsb.left_bitmap_height, x_loc, y_loc); + } + +/* + * Draw Right Bitmap. + */ + + if (entry->sme_bsb.right_bitmap != None) { + x_loc = entry->rectangle.width - entry->sme_threeD.shadow_width - + (int)(entry->sme_bsb.right_margin + + entry->sme_bsb.right_bitmap_width) / 2; + + y_loc = entry->rectangle.y + (int)(entry->rectangle.height - + entry->sme_bsb.right_bitmap_height) / 2; + + pm = entry->sme_bsb.right_bitmap; +#ifdef XAW_MULTIPLANE_PIXMAPS + if (!XtIsSensitive(w)) { + if (entry->sme_bsb.right_stippled == None) + entry->sme_bsb.right_stippled = stipplePixmap(w, + entry->sme_bsb.right_bitmap, + parent->core.colormap, + parent->core.background_pixel, + entry->sme_bsb.right_depth); + if (entry->sme_bsb.right_stippled != None) + pm = entry->sme_bsb.right_stippled; + } +#endif + + if (entry->sme_bsb.right_depth == 1) + XCopyPlane(XtDisplayOfObject(w), pm, + XtWindowOfObject(w), gc, 0, 0, + entry->sme_bsb.right_bitmap_width, + entry->sme_bsb.right_bitmap_height, x_loc, y_loc, 1); + else + XCopyArea (XtDisplayOfObject(w), pm, + XtWindowOfObject(w), gc, 0, 0, + entry->sme_bsb.right_bitmap_width, + entry->sme_bsb.right_bitmap_height, x_loc, y_loc); + } +} + +/* Function Name: GetBitmapInfo + * Description: Gets the bitmap information from either of the bitmaps. + * Arguments: w - the bsb menu entry widget. + * is_left - TRUE if we are testing left bitmap, + * FALSE if we are testing the right bitmap. + * Returns: none + */ + +static void +GetBitmapInfo(w, is_left) +Widget w; +Boolean is_left; +{ + SmeBSBObject entry = (SmeBSBObject) w; + Window root; + int x, y; + unsigned int width, height, bw; + char buf[BUFSIZ]; + + if (is_left) { + width = height = 0; + + if (entry->sme_bsb.left_bitmap != None) { + if (!XGetGeometry(XtDisplayOfObject(w), + entry->sme_bsb.left_bitmap, &root, &x, &y, + &width, &height, &bw, &entry->sme_bsb.left_depth)) { + (void) sprintf(buf, "Xaw SmeBSB Object: %s %s \"%s\".", + "Could not get Left Bitmap", + "geometry information for menu entry", + XtName(w)); + XtAppError(XtWidgetToApplicationContext(w), buf); + } +#ifdef NEVER + if (entry->sme_bsb.left_depth != 1) { + (void) sprintf(buf, "Xaw SmeBSB Object: %s \"%s\" %s.", + "Left Bitmap of entry", XtName(w), + "is not one bit deep"); + XtAppError(XtWidgetToApplicationContext(w), buf); + } +#endif + } + + entry->sme_bsb.left_bitmap_width = (Dimension) width; + entry->sme_bsb.left_bitmap_height = (Dimension) height; + } else { + width = height = 0; + + if (entry->sme_bsb.right_bitmap != None) { + if (!XGetGeometry(XtDisplayOfObject(w), + entry->sme_bsb.right_bitmap, &root, &x, &y, + &width, &height, &bw, &entry->sme_bsb.right_depth)) { + (void) sprintf(buf, "Xaw SmeBSB Object: %s %s \"%s\".", + "Could not get Right Bitmap", + "geometry information for menu entry", + XtName(w)); + XtAppError(XtWidgetToApplicationContext(w), buf); + } +#ifdef NEVER + if (entry->sme_bsb.right_depth != 1) { + (void) sprintf(buf, "Xaw SmeBSB Object: %s \"%s\" %s.", + "Right Bitmap of entry", XtName(w), + "is not one bit deep"); + XtAppError(XtWidgetToApplicationContext(w), buf); + } +#endif + } + + entry->sme_bsb.right_bitmap_width = (Dimension) width; + entry->sme_bsb.right_bitmap_height = (Dimension) height; + } +} + +/* Function Name: CreateGCs + * Description: Creates all gc's for the simple menu widget. + * Arguments: w - the simple menu widget. + * Returns: none. + */ + +static void +CreateGCs(w) +Widget w; +{ + SmeBSBObject entry = (SmeBSBObject) w; + XGCValues values; + XtGCMask mask; +#ifdef XAW_INTERNATIONALIZATION + XtGCMask mask_i18n; +#endif + + values.foreground = XtParent(w)->core.background_pixel; + values.background = entry->sme_bsb.foreground; + values.font = entry->sme_bsb.font->fid; + values.graphics_exposures = FALSE; + mask = GCForeground | GCBackground | GCGraphicsExposures | GCFont; +#ifdef XAW_INTERNATIONALIZATION + mask_i18n = GCForeground | GCBackground | GCGraphicsExposures; + if ( entry->sme.international == True ) + entry->sme_bsb.rev_gc = XtAllocateGC(w, 0, mask_i18n, &values, GCFont, 0 ); + else +#endif + entry->sme_bsb.rev_gc = XtGetGC(w, mask, &values); + + values.foreground = entry->sme_bsb.foreground; + values.background = XtParent(w)->core.background_pixel; +#ifdef XAW_INTERNATIONALIZATION + if ( entry->sme.international == True ) + entry->sme_bsb.norm_gc = XtAllocateGC(w, 0, mask_i18n, &values, GCFont, 0 ); + else +#endif + entry->sme_bsb.norm_gc = XtGetGC(w, mask, &values); + + values.fill_style = FillTiled; + values.tile = XmuCreateStippledPixmap(XtScreenOfObject(w), + entry->sme_bsb.foreground, + XtParent(w)->core.background_pixel, + XtParent(w)->core.depth); + values.graphics_exposures = FALSE; + mask |= GCTile | GCFillStyle; +#ifdef XAW_INTERNATIONALIZATION + if ( entry->sme.international == True ) + entry->sme_bsb.norm_gray_gc = XtAllocateGC(w, 0, mask_i18n, &values, GCFont, 0 ); + else +#endif + entry->sme_bsb.norm_gray_gc = XtGetGC(w, mask, &values); + + values.foreground ^= values.background; + values.background = 0; + values.function = GXxor; + mask = GCForeground | GCBackground | GCGraphicsExposures | GCFunction; + entry->sme_bsb.invert_gc = XtGetGC(w, mask, &values); +} + +/* Function Name: DestroyGCs + * Description: Removes all gc's for the simple menu widget. + * Arguments: w - the simple menu widget. + * Returns: none. + */ + +static void +DestroyGCs(w) +Widget w; +{ + SmeBSBObject entry = (SmeBSBObject) w; + + XtReleaseGC(w, entry->sme_bsb.norm_gc); + XtReleaseGC(w, entry->sme_bsb.norm_gray_gc); + XtReleaseGC(w, entry->sme_bsb.rev_gc); + XtReleaseGC(w, entry->sme_bsb.invert_gc); +} + +/* Function Name: FlipColors + * Description: Invert the colors of the current entry. + * Arguments: w - the bsb menu entry widget. + * Returns: none. + */ + +static void +FlipColors(w) +Widget w; +{ + SmeBSBObject entry = (SmeBSBObject) w; + SmeBSBObjectClass oclass = (SmeBSBObjectClass) XtClass (w); + SimpleMenuWidget smw = (SimpleMenuWidget) XtParent (w); + ThreeDWidget tdw = (ThreeDWidget) smw->simple_menu.threeD; + Dimension s = tdw->threeD.shadow_width; + + if (entry->sme_bsb.set_values_area_cleared) { + entry->sme_threeD.shadowed = False; + return; + } + + if (entry->sme_threeD.shadow_width > 0) { + (*oclass->sme_threeD_class.shadowdraw) (w); + } else + XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w), + entry->sme_bsb.invert_gc, + s, (int) entry->rectangle.y, + (unsigned int) entry->rectangle.width - 2 * s, + (unsigned int) entry->rectangle.height); +} + diff --git a/src/SmeBSB.h b/src/SmeBSB.h new file mode 100644 index 0000000..47ad6e0 --- /dev/null +++ b/src/SmeBSB.h @@ -0,0 +1,111 @@ +/* + * $XConsortium: SmeBSB.h,v 1.7 94/04/17 20:12:49 kaleb Exp $ + * +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + */ + +/* + * SmeBSB.h - Public Header file for SmeBSB object. + * + * This is the public header file for the Athena BSB Sme object. + * It is intended to be used with the simple menu widget. This object + * provides bitmap - string - bitmap style entries. + * + * Date: April 3, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifndef _SmeBSB_h +#define _SmeBSB_h + +#include <X11/Xmu/Converters.h> + +#include "Xaw3dP.h" +#include <X11/Xaw3d/Sme.h> + +/**************************************************************** + * + * SmeBSB object + * + ****************************************************************/ + +/* BSB Menu Entry Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + callback Callback Callback NULL + destroyCallback Callback Pointer NULL + font Font XFontStruct * XtDefaultFont + foreground Foreground Pixel XtDefaultForeground + height Height Dimension 0 + label Label String Name of entry + leftBitmap LeftBitmap Pixmap None + leftMargin HorizontalMargins Dimension 4 + menuName MenuName String NULL + rightBitmap RightBitmap Pixmap None + rightMargin HorizontalMargins Dimension 4 + sensitive Sensitive Boolean True + underline Underline int -1 + vertSpace VertSpace int 25 + width Width Dimension 0 + x Position Position 0n + y Position Position 0 + +*/ + +typedef struct _SmeBSBClassRec *SmeBSBObjectClass; +typedef struct _SmeBSBRec *SmeBSBObject; + +extern WidgetClass smeBSBObjectClass; + +#define XtNleftBitmap "leftBitmap" +#define XtNleftMargin "leftMargin" +#define XtNleftWhitespace "leftWhitespace" +#define XtNrightBitmap "rightBitmap" +#define XtNrightMargin "rightMargin" +#define XtNrightWhitespace "rightWhitespace" +#define XtNvertSpace "vertSpace" +#define XtNmenuName "menuName" +#define XtNunderline "underline" + +#ifdef XAW_INTERNATIONALIZATION +#ifndef XtNfontSet +#define XtNfontSet "fontSet" +#endif +#ifndef XtCFontSet +#define XtCFontSet "FontSet" +#endif +#endif + +#define XtCLeftBitmap "LeftBitmap" +#define XtCRightBitmap "RightBitmap" +#define XtCHorizontalMargins "HorizontalMargins" +#define XtCVertSpace "VertSpace" +#define XtCMenuName "MenuName" +#define XtCUnderline "Underline" + +#endif /* _SmeBSB_h */ diff --git a/src/SmeBSBP.h b/src/SmeBSBP.h new file mode 100644 index 0000000..6ef1c4b --- /dev/null +++ b/src/SmeBSBP.h @@ -0,0 +1,120 @@ +/* + * $XConsortium: SmeBSBP.h,v 1.8 94/04/17 21:44:11 rws Exp $ + * +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + * Author: Chris D. Peterson, MIT X Consortium + */ + +/* + * SmeP.h - Private definitions for Sme object + * + */ + +#ifndef _XawSmeBSBP_h +#define _XawSmeBSBP_h + +/*********************************************************************** + * + * Sme Object Private Data + * + ***********************************************************************/ + +#include "Xaw3dP.h" +#include <X11/Xaw3d/SmeThreeDP.h> +#include <X11/Xaw3d/SmeBSB.h> + +/************************************************************ + * + * New fields for the Sme Object class record. + * + ************************************************************/ + +typedef struct _SmeBSBClassPart { + XtPointer extension; +} SmeBSBClassPart; + +/* Full class record declaration */ +typedef struct _SmeBSBClassRec { + RectObjClassPart rect_class; + SmeClassPart sme_class; + SmeThreeDClassPart sme_threeD_class; + SmeBSBClassPart sme_bsb_class; +} SmeBSBClassRec; + +extern SmeBSBClassRec smeBSBClassRec; + +/* New fields for the Sme Object record */ +typedef struct { + /* resources */ + String label; /* The entry label. */ + int vert_space; /* extra vert space to leave, as a percentage + of the font height of the label. */ + Pixmap left_bitmap, right_bitmap; /* pixmaps to show. */ + Dimension left_margin, right_margin; /* left and right margins. */ + Pixel foreground; /* foreground color. */ + XFontStruct * font; /* The font to show label in. */ +#ifdef XAW_INTERNATIONALIZATION + XFontSet fontset; /* or fontset */ +#endif + XtJustify justify; /* Justification for the label. */ + int underline; /* index of letter to underline in label. */ + + /* private resources. */ + Boolean set_values_area_cleared; /* Remember if we need to unhighlight. */ + GC norm_gc; /* noral color gc. */ + GC rev_gc; /* reverse color gc. */ + GC norm_gray_gc; /* Normal color (grayed out) gc. */ + GC invert_gc; /* gc for flipping colors. */ + Pixmap left_stippled, right_stippled; /* insensitive pixmaps */ + Dimension left_bitmap_width; /* size and depth of each pixmap. */ + Dimension left_bitmap_height; + Dimension right_bitmap_width; + Dimension right_bitmap_height; + unsigned int left_depth; + unsigned int right_depth; + String menu_name; /* name of nested sub-menu or NULL */ +} SmeBSBPart; + +/**************************************************************** + * + * Full instance record declaration + * + ****************************************************************/ + +typedef struct _SmeBSBRec { + ObjectPart object; + RectObjPart rectangle; + SmePart sme; + SmeThreeDPart sme_threeD; + SmeBSBPart sme_bsb; +} SmeBSBRec; + +/************************************************************ + * + * Private declarations. + * + ************************************************************/ + +#endif /* _XawSmeBSBP_h */ diff --git a/src/SmeLine.c b/src/SmeLine.c new file mode 100644 index 0000000..27aa65b --- /dev/null +++ b/src/SmeLine.c @@ -0,0 +1,294 @@ +/* $XConsortium: SmeLine.c,v 1.15 94/04/17 20:12:51 eswu Exp $ */ + +/* +Copyright (c) 1989 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + * Author: Chris D. Peterson, MIT X Consortium + */ + +/* + * Sme.c - Source code for the generic menu entry + * + * Date: September 26, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> + +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/ThreeDP.h> +#include <X11/Xaw3d/SimpleMenP.h> +#include <X11/Xaw3d/SmeLineP.h> +#include <X11/Xaw3d/Cardinals.h> + +#define offset(field) XtOffsetOf(SmeLineRec, sme_line.field) +static XtResource resources[] = { + {XtNlineWidth, XtCLineWidth, XtRDimension, sizeof(Dimension), + offset(line_width), XtRImmediate, (XtPointer) 1}, + {XtNstipple, XtCStipple, XtRBitmap, sizeof(Pixmap), + offset(stipple), XtRImmediate, (XtPointer) XtUnspecifiedPixmap}, + {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), + offset(foreground), XtRString, XtDefaultForeground}, +}; +#undef offset + +/* + * Function definitions. + */ + +static void Redisplay(), Initialize(); +static void DestroyGC(), CreateGC(); +static Boolean SetValues(); +static XtGeometryResult QueryGeometry(); + + +#define SUPERCLASS (&smeClassRec) + +SmeLineClassRec smeLineClassRec = { + { + /* superclass */ (WidgetClass) SUPERCLASS, + /* class_name */ "SmeLine", + /* size */ sizeof(SmeLineRec), + /* class_initialize */ XawInitializeWidgetSet, + /* class_part_initialize*/ NULL, + /* Class init'ed */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ NULL, + /* actions */ NULL, + /* num_actions */ ZERO, + /* resources */ resources, + /* resource_count */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ FALSE, + /* compress_exposure */ FALSE, + /* compress_enterleave*/ FALSE, + /* visible_interest */ FALSE, + /* destroy */ DestroyGC, + /* resize */ NULL, + /* expose */ Redisplay, + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* set_values_almost */ XtInheritSetValuesAlmost, + /* get_values_hook */ NULL, + /* accept_focus */ NULL, + /* intrinsics version */ XtVersion, + /* callback offsets */ NULL, + /* tm_table */ NULL, + /* query_geometry */ QueryGeometry, + /* display_accelerator*/ NULL, + /* extension */ NULL + },{ + /* Menu Entry Fields */ + + /* highlight */ XtInheritHighlight, + /* unhighlight */ XtInheritUnhighlight, + /* notify */ XtInheritNotify, + /* extension */ NULL + },{ + /* Line Menu Entry Fields */ + /* extension */ NULL + } +}; + +WidgetClass smeLineObjectClass = (WidgetClass) &smeLineClassRec; + +/************************************************************ + * + * Semi-Public Functions. + * + ************************************************************/ + +/* Function Name: Initialize + * Description: Initializes the simple menu widget + * Arguments: request - the widget requested by the argument list. + * new - the new widget with both resource and non + * resource values. + * Returns: none. + */ + +/* ARGSUSED */ +static void +Initialize(request, new, args, num_args) +Widget request, new; +ArgList args; +Cardinal *num_args; +{ + SmeLineObject entry = (SmeLineObject) new; + + if (entry->rectangle.height == 0) + entry->rectangle.height = entry->sme_line.line_width; + + CreateGC(new); +} + +/* Function Name: CreateGC + * Description: Creates the GC for the line entry widget. + * Arguments: w - the Line entry widget. + * Returns: none + * + * We can only share the GC if there is no stipple, because + * we need to change the stipple origin when drawing. + */ + +static void +CreateGC(w) +Widget w; +{ + SmeLineObject entry = (SmeLineObject) w; + XGCValues values; + XtGCMask mask = GCForeground | GCGraphicsExposures | GCLineWidth ; + + values.foreground = entry->sme_line.foreground; + values.graphics_exposures = FALSE; + values.line_width = entry->sme_line.line_width; + + if (entry->sme_line.stipple != XtUnspecifiedPixmap) { + values.stipple = entry->sme_line.stipple; + values.fill_style = FillStippled; + mask |= GCStipple | GCFillStyle; + + entry->sme_line.gc = XCreateGC(XtDisplayOfObject(w), + RootWindowOfScreen(XtScreenOfObject(w)), + mask, &values); + } + else + entry->sme_line.gc = XtGetGC(w, mask, &values); +} + +/* Function Name: DestroyGC + * Description: Destroys the GC when we are done with it. + * Arguments: w - the Line entry widget. + * Returns: none + */ + +static void +DestroyGC(w) +Widget w; +{ + SmeLineObject entry = (SmeLineObject) w; + + if (entry->sme_line.stipple != XtUnspecifiedPixmap) + XFreeGC(XtDisplayOfObject(w), entry->sme_line.gc); + else + XtReleaseGC(w, entry->sme_line.gc); +} + +/* Function Name: Redisplay + * Description: Paints the Line + * Arguments: w - the menu entry. + * event, region - NOT USED. + * Returns: none + */ + +/*ARGSUSED*/ +static void +Redisplay(w, event, region) +Widget w; +XEvent * event; +Region region; +{ + SmeLineObject entry = (SmeLineObject) w; + SimpleMenuWidget smw = (SimpleMenuWidget) XtParent (w); + ThreeDWidget tdw = (ThreeDWidget) smw->simple_menu.threeD; + Dimension s = tdw->threeD.shadow_width; + int y = entry->rectangle.y + + (int)(entry->rectangle.height - entry->sme_line.line_width) / 2; + + if (entry->sme_line.stipple != XtUnspecifiedPixmap) + XSetTSOrigin(XtDisplayOfObject(w), entry->sme_line.gc, 0, y); + + XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w), + entry->sme_line.gc, + s, y, (unsigned int) entry->rectangle.width - 2 * s, + (unsigned int) entry->sme_line.line_width ); +} + +/* Function Name: SetValues + * Description: Relayout the menu when one of the resources is changed. + * Arguments: current - current state of the widget. + * request - what was requested. + * new - what the widget will become. + * Returns: none + */ + +/* ARGSUSED */ +static Boolean +SetValues(current, request, new, args, num_args) +Widget current, request, new; +ArgList args; +Cardinal *num_args; +{ + SmeLineObject entry = (SmeLineObject) new; + SmeLineObject old_entry = (SmeLineObject) current; + + if ( (entry->sme_line.line_width != old_entry->sme_line.line_width) && + (entry->sme_line.stipple != old_entry->sme_line.stipple) ) { + DestroyGC(current); + CreateGC(new); + return(TRUE); + } + return(FALSE); +} + +/* Function Name: QueryGeometry. + * Description: Returns the preferred geometry for this widget. + * Arguments: w - the menu entry object. + * itended, return - the intended and return geometry info. + * Returns: A Geometry Result. + * + * See the Intrinsics manual for details on what this function is for. + * + * I just return the height and a width of 1. + */ + +static XtGeometryResult +QueryGeometry(w, intended, return_val) +Widget w; +XtWidgetGeometry *intended, *return_val; +{ + SmeObject entry = (SmeObject) w; + Dimension width; + XtGeometryResult ret_val = XtGeometryYes; + XtGeometryMask mode = intended->request_mode; + + width = 1; /* we can be really small. */ + + if ( ((mode & CWWidth) && (intended->width != width)) || + !(mode & CWWidth) ) { + return_val->request_mode |= CWWidth; + return_val->width = width; + mode = return_val->request_mode; + + if ( (mode & CWWidth) && (width == entry->rectangle.width) ) + return(XtGeometryNo); + return(XtGeometryAlmost); + } + return(ret_val); +} diff --git a/src/SmeLine.h b/src/SmeLine.h new file mode 100644 index 0000000..42b969e --- /dev/null +++ b/src/SmeLine.h @@ -0,0 +1,79 @@ +/* + * $XConsortium: SmeLine.h,v 1.4 94/04/17 20:12:53 kit Exp $ + * +Copyright (c) 1989 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + */ + +/* + * SmeLine.h - Public Header file for SmeLine object. + * + * This is the public header file for the Athena SmeLine object. + * It is intended to be used with the simple menu widget. + * + * Date: April 3, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifndef _SmeLine_h +#define _SmeLine_h + +#include <X11/Xaw3d/Sme.h> +#include <X11/Xmu/Converters.h> + +/**************************************************************** + * + * SmeLine Object + * + ****************************************************************/ + +/* Menu Entry Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + callback Callback Pointer NULL + destroyCallback Callback Pointer NULL + height Height Dimension 0 + sensitive Sensitive Boolean True + width Width Dimension 0 + x Position Position 0n + y Position Position 0 + +*/ + +#define XtCLineWidth "LineWidth" +#define XtCStipple "Stipple" + +#define XtNlineWidth "lineWidth" +#define XtNstipple "stipple" + +typedef struct _SmeLineClassRec* SmeLineObjectClass; +typedef struct _SmeLineRec* SmeLineObject; + +extern WidgetClass smeLineObjectClass; + +#endif /* _SmeLine_h */ diff --git a/src/SmeLineP.h b/src/SmeLineP.h new file mode 100644 index 0000000..c6b612d --- /dev/null +++ b/src/SmeLineP.h @@ -0,0 +1,97 @@ +/* + * $XConsortium: SmeLineP.h,v 1.4 94/04/17 20:12:54 kit Exp $ + * +Copyright (c) 1989 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + * Author: Chris D. Peterson, MIT X Consortium + */ + +/* + * SmeLineP.h - Private definitions for SmeLine widget + * + */ + +#ifndef _XawSmeLineP_h +#define _XawSmeLineP_h + +/*********************************************************************** + * + * SmeLine Widget Private Data + * + ***********************************************************************/ + +#include <X11/Xaw3d/SmeP.h> +#include <X11/Xaw3d/SmeLine.h> + +/************************************************************ + * + * New fields for the SmeLine widget class record. + * + ************************************************************/ + +typedef struct _SmeLineClassPart { + XtPointer extension; +} SmeLineClassPart; + +/* Full class record declaration */ +typedef struct _SmeLineClassRec { + RectObjClassPart rect_class; + SmeClassPart sme_class; + SmeLineClassPart sme_line_class; +} SmeLineClassRec; + +extern SmeLineClassRec smeLineClassRec; + +/* New fields for the SmeLine widget record */ +typedef struct { + /* resources */ + Pixel foreground; /* Foreground color. */ + Pixmap stipple; /* Line Stipple. */ + Dimension line_width; /* Width of the line. */ + + /* private data. */ + + GC gc; /* Graphics context for drawing line. */ +} SmeLinePart; + +/**************************************************************** + * + * Full instance record declaration + * + ****************************************************************/ + +typedef struct _SmeLineRec { + ObjectPart object; + RectObjPart rectangle; + SmePart sme; + SmeLinePart sme_line; +} SmeLineRec; + +/************************************************************ + * + * Private declarations. + * + ************************************************************/ + +#endif /* _XawSmeLineP_h */ diff --git a/src/SmeP.h b/src/SmeP.h new file mode 100644 index 0000000..9501771 --- /dev/null +++ b/src/SmeP.h @@ -0,0 +1,107 @@ +/* + * $XConsortium: SmeP.h,v 1.6 94/04/17 20:12:54 kaleb Exp $ + * +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + */ + +/* + * SmeP.h - Private Header file for Sme object. + * + * This is the private header file for the Athena Sme object. + * This object is intended to be used with the simple menu widget. + * + * Date: April 3, 1989 + * + * By: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + */ + +#ifndef _XawSmeP_h +#define _XawSmeP_h + +/*********************************************************************** + * + * Sme Widget Private Data + * + ***********************************************************************/ + +#include "Xaw3dP.h" +#include <X11/Xaw3d/Sme.h> + +/************************************************************ + * + * New fields for the Sme widget class record. + * + ************************************************************/ + +typedef struct _SmeClassPart { + void (*highlight)(); + void (*unhighlight)(); + void (*notify)(); + XtPointer extension; +} SmeClassPart; + +/* Full class record declaration */ +typedef struct _SmeClassRec { + RectObjClassPart rect_class; + SmeClassPart sme_class; +} SmeClassRec; + +extern SmeClassRec smeClassRec; + +/* New fields for the Sme widget record */ +typedef struct { + /* resources */ + XtCallbackList callbacks; /* The callback list */ +#ifdef XAW_INTERNATIONALIZATION + Boolean international; +#endif +} SmePart; + +/**************************************************************** + * + * Full instance record declaration + * + ****************************************************************/ + +typedef struct _SmeRec { + ObjectPart object; + RectObjPart rectangle; + SmePart sme; +} SmeRec; + +/************************************************************ + * + * Private declarations. + * + ************************************************************/ + +typedef void (*_XawEntryVoidFunc)(); + +#define XtInheritHighlight ((_XawEntryVoidFunc) _XtInherit) +#define XtInheritUnhighlight XtInheritHighlight +#define XtInheritNotify XtInheritHighlight + +#endif /* _XawSmeP_h */ diff --git a/src/SmeThreeD.c b/src/SmeThreeD.c new file mode 100644 index 0000000..a01023c --- /dev/null +++ b/src/SmeThreeD.c @@ -0,0 +1,596 @@ +/* +* $KK: SmeThreeD.c,v 0.3 92/11/04 xx:xx:xx keithley Exp $ +*/ + +/*********************************************************** +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. +Copyright 1992, 1993 by Kaleb Keithley + + All Rights Reserved + +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 names of Digital, MIT, or Kaleb +Keithley not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#include "Xaw3dP.h" +#include <X11/Xlib.h> +#include <X11/StringDefs.h> +#include <X11/IntrinsicP.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/ThreeDP.h> +#include <X11/Xaw3d/SimpleMenP.h> +#include <X11/Xaw3d/SmeThreeDP.h> +#include <X11/Xosdefs.h> + +/* Initialization of defaults */ + +#define XtNtopShadowPixmap "topShadowPixmap" +#define XtCTopShadowPixmap "TopShadowPixmap" +#define XtNbottomShadowPixmap "bottomShadowPixmap" +#define XtCBottomShadowPixmap "BottomShadowPixmap" +#define XtNshadowed "shadowed" +#define XtCShadowed "Shadowed" + +#define offset(field) XtOffsetOf(SmeThreeDRec, field) + +static XtResource resources[] = { + {XtNshadowWidth, XtCShadowWidth, XtRDimension, sizeof(Dimension), + offset(sme_threeD.shadow_width), XtRImmediate, (XtPointer) 2}, + {XtNtopShadowPixel, XtCTopShadowPixel, XtRPixel, sizeof(Pixel), + offset(sme_threeD.top_shadow_pixel), XtRString, XtDefaultForeground}, + {XtNbottomShadowPixel, XtCBottomShadowPixel, XtRPixel, sizeof(Pixel), + offset(sme_threeD.bot_shadow_pixel), XtRString, XtDefaultForeground}, + {XtNtopShadowPixmap, XtCTopShadowPixmap, XtRPixmap, sizeof(Pixmap), + offset(sme_threeD.top_shadow_pxmap), XtRImmediate, (XtPointer) NULL}, + {XtNbottomShadowPixmap, XtCBottomShadowPixmap, XtRPixmap, sizeof(Pixmap), + offset(sme_threeD.bot_shadow_pxmap), XtRImmediate, (XtPointer) NULL}, + {XtNtopShadowContrast, XtCTopShadowContrast, XtRInt, sizeof(int), + offset(sme_threeD.top_shadow_contrast), XtRImmediate, (XtPointer) 20}, + {XtNbottomShadowContrast, XtCBottomShadowContrast, XtRInt, sizeof(int), + offset(sme_threeD.bot_shadow_contrast), XtRImmediate, (XtPointer) 40}, + {XtNuserData, XtCUserData, XtRPointer, sizeof(XtPointer), + offset(sme_threeD.user_data), XtRPointer, (XtPointer) NULL}, + {XtNbeNiceToColormap, XtCBeNiceToColormap, XtRBoolean, sizeof(Boolean), + offset(sme_threeD.be_nice_to_cmap), XtRImmediate, (XtPointer) True}, + {XtNshadowed, XtCShadowed, XtRBoolean, sizeof(Boolean), + offset(sme_threeD.shadowed), XtRImmediate, (XtPointer) False}, + {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension), + XtOffsetOf(RectObjRec,rectangle.border_width), XtRImmediate, + (XtPointer)0} +}; + +#undef offset + +static void Initialize(), Destroy(); +static void ClassPartInitialize(), _XawSme3dDrawShadows(); +static Boolean SetValues(); + +SmeThreeDClassRec smeThreeDClassRec = { + { /* core fields */ + /* superclass */ (WidgetClass) &smeClassRec, + /* class_name */ "SmeThreeD", + /* widget_size */ sizeof(SmeThreeDRec), + /* class_initialize */ NULL, + /* class_part_initialize */ ClassPartInitialize, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ NULL, + /* actions */ NULL, + /* num_actions */ 0, + /* resources */ resources, + /* resource_count */ 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 */ NULL, + /* query_geometry */ XtInheritQueryGeometry, + /* display_accelerator */ NULL, + /* extension */ NULL + }, + { /* Menu Entry fields */ + /* highlight */ XtInheritHighlight, + /* unhighlight */ XtInheritUnhighlight, + /* notify */ XtInheritNotify, + /* extension */ NULL + }, + { /* threeD fields */ + /* shadow draw */ _XawSme3dDrawShadows + } +}; + +WidgetClass smeThreeDObjectClass = (WidgetClass) &smeThreeDClassRec; + +/**************************************************************** + * + * Private Procedures + * + ****************************************************************/ + + +#define shadowpm_width 8 +#define shadowpm_height 8 +static char shadowpm_bits[] = { + 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55}; + +static char mtshadowpm_bits[] = { + 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24}; + +static char mbshadowpm_bits[] = { + 0x6d, 0xdb, 0xb6, 0x6d, 0xdb, 0xb6, 0x6d, 0xdb}; + +/* ARGSUSED */ +static void AllocTopShadowGC (w) + Widget w; +{ + SmeThreeDObject tdo = (SmeThreeDObject) w; + Screen *scn = XtScreenOfObject (w); + XtGCMask valuemask; + XGCValues myXGCV; + + if (tdo->sme_threeD.be_nice_to_cmap || DefaultDepthOfScreen (scn) == 1) { + valuemask = GCTile | GCFillStyle; + myXGCV.tile = tdo->sme_threeD.top_shadow_pxmap; + myXGCV.fill_style = FillTiled; + } else { + valuemask = GCForeground; + myXGCV.foreground = tdo->sme_threeD.top_shadow_pixel; + } + tdo->sme_threeD.top_shadow_GC = XtGetGC(w, valuemask, &myXGCV); +} + +/* ARGSUSED */ +static void AllocBotShadowGC (w) + Widget w; +{ + SmeThreeDObject tdo = (SmeThreeDObject) w; + Screen *scn = XtScreenOfObject (w); + XtGCMask valuemask; + XGCValues myXGCV; + + if (tdo->sme_threeD.be_nice_to_cmap || DefaultDepthOfScreen (scn) == 1) { + valuemask = GCTile | GCFillStyle; + myXGCV.tile = tdo->sme_threeD.bot_shadow_pxmap; + myXGCV.fill_style = FillTiled; + } else { + valuemask = GCForeground; + myXGCV.foreground = tdo->sme_threeD.bot_shadow_pixel; + } + tdo->sme_threeD.bot_shadow_GC = XtGetGC(w, valuemask, &myXGCV); +} + +/* ARGSUSED */ +static void AllocEraseGC (w) + Widget w; +{ + Widget parent = XtParent (w); + SmeThreeDObject tdo = (SmeThreeDObject) w; + XtGCMask valuemask; + XGCValues myXGCV; + + valuemask = GCForeground; + myXGCV.foreground = parent->core.background_pixel; + tdo->sme_threeD.erase_GC = XtGetGC(w, valuemask, &myXGCV); +} + +/* ARGSUSED */ +static void AllocTopShadowPixmap (new) + Widget new; +{ + SmeThreeDObject tdo = (SmeThreeDObject) new; + Widget parent = XtParent (new); + Display *dpy = XtDisplayOfObject (new); + Screen *scn = XtScreenOfObject (new); + unsigned long top_fg_pixel = 0, top_bg_pixel = 0; + char *pm_data; + Boolean create_pixmap = FALSE; + + /* + * I know, we're going to create two pixmaps for each and every + * shadow'd widget. Yeuck. I'm semi-relying on server side + * pixmap cacheing. + */ + + if (DefaultDepthOfScreen (scn) == 1) { + top_fg_pixel = BlackPixelOfScreen (scn); + top_bg_pixel = WhitePixelOfScreen (scn); + pm_data = mtshadowpm_bits; + create_pixmap = TRUE; + } else if (tdo->sme_threeD.be_nice_to_cmap) { + if (parent->core.background_pixel == WhitePixelOfScreen (scn)) { + top_fg_pixel = WhitePixelOfScreen (scn); + top_bg_pixel = grayPixel( BlackPixelOfScreen (scn), dpy, scn); + } else if (parent->core.background_pixel == BlackPixelOfScreen (scn)) { + top_fg_pixel = grayPixel( BlackPixelOfScreen (scn), dpy, scn); + top_bg_pixel = WhitePixelOfScreen (scn); + } else { + top_fg_pixel = parent->core.background_pixel; + top_bg_pixel = WhitePixelOfScreen (scn); + } +#ifndef XAW_GRAY_BLKWHT_STIPPLES + if (parent->core.background_pixel == WhitePixelOfScreen (scn) || + parent->core.background_pixel == BlackPixelOfScreen (scn)) { + pm_data = mtshadowpm_bits; + } else +#endif + pm_data = shadowpm_bits; + + create_pixmap = TRUE; + } + + if (create_pixmap) + tdo->sme_threeD.top_shadow_pxmap = XCreatePixmapFromBitmapData (dpy, + RootWindowOfScreen (scn), + pm_data, + shadowpm_width, + shadowpm_height, + top_fg_pixel, + top_bg_pixel, + DefaultDepthOfScreen (scn)); +} + +/* ARGSUSED */ +static void AllocBotShadowPixmap (new) + Widget new; +{ + SmeThreeDObject tdo = (SmeThreeDObject) new; + Widget parent = XtParent (new); + Display *dpy = XtDisplayOfObject (new); + Screen *scn = XtScreenOfObject (new); + unsigned long bot_fg_pixel = 0, bot_bg_pixel = 0; + char *pm_data; + Boolean create_pixmap = FALSE; + + if (DefaultDepthOfScreen (scn) == 1) { + bot_fg_pixel = BlackPixelOfScreen (scn); + bot_bg_pixel = WhitePixelOfScreen (scn); + pm_data = mbshadowpm_bits; + create_pixmap = TRUE; + } else if (tdo->sme_threeD.be_nice_to_cmap) { + if (parent->core.background_pixel == WhitePixelOfScreen (scn)) { + bot_fg_pixel = grayPixel( WhitePixelOfScreen (scn), dpy, scn); + bot_bg_pixel = BlackPixelOfScreen (scn); + } else if (parent->core.background_pixel == BlackPixelOfScreen (scn)) { + bot_fg_pixel = BlackPixelOfScreen (scn); + bot_bg_pixel = grayPixel( BlackPixelOfScreen (scn), dpy, scn); + } else { + bot_fg_pixel = parent->core.background_pixel; + bot_bg_pixel = BlackPixelOfScreen (scn); + } +#ifndef XAW_GRAY_BLKWHT_STIPPLES + if (parent->core.background_pixel == WhitePixelOfScreen (scn) || + parent->core.background_pixel == BlackPixelOfScreen (scn)) { + pm_data = mbshadowpm_bits; + } else +#endif + pm_data = shadowpm_bits; + + create_pixmap = TRUE; + } + + if (create_pixmap) + tdo->sme_threeD.bot_shadow_pxmap = XCreatePixmapFromBitmapData (dpy, + RootWindowOfScreen (scn), + pm_data, + shadowpm_width, + shadowpm_height, + bot_fg_pixel, + bot_bg_pixel, + DefaultDepthOfScreen (scn)); +} + +/* ARGSUSED */ +void XawSme3dComputeTopShadowRGB (new, xcol_out) + Widget new; + XColor *xcol_out; +{ + if (XtIsSubclass (new, smeThreeDObjectClass)) { + SmeThreeDObject tdo = (SmeThreeDObject) new; + Widget w = XtParent (new); + XColor get_c; + double contrast; + Display *dpy = XtDisplayOfObject (new); + Screen *scn = XtScreenOfObject (new); + Colormap cmap = w->core.colormap; + + get_c.pixel = w->core.background_pixel; + if (get_c.pixel == WhitePixelOfScreen (scn) || + get_c.pixel == BlackPixelOfScreen (scn)) { + contrast = (100 - tdo->sme_threeD.top_shadow_contrast) / 100.0; + xcol_out->red = contrast * 65535.0; + xcol_out->green = contrast * 65535.0; + xcol_out->blue = contrast * 65535.0; + } else { + contrast = 1.0 + tdo->sme_threeD.top_shadow_contrast / 100.0; + XQueryColor (dpy, cmap, &get_c); +#define MIN(x,y) (unsigned short) (x < y) ? x : y + xcol_out->red = MIN (65535, (int) (contrast * (double) get_c.red)); + xcol_out->green = MIN (65535, (int) (contrast * (double) get_c.green)); + xcol_out->blue = MIN (65535, (int) (contrast * (double) get_c.blue)); +#undef MIN + } + } else + xcol_out->red = xcol_out->green = xcol_out->blue = 0; +} + +/* ARGSUSED */ +static void AllocTopShadowPixel (new) + Widget new; +{ + XColor set_c; + SmeThreeDObject tdo = (SmeThreeDObject) new; + Widget w = XtParent (new); + Display *dpy = XtDisplayOfObject (new); + Colormap cmap = w->core.colormap; + + XawSme3dComputeTopShadowRGB (new, &set_c); + (void) XAllocColor (dpy, cmap, &set_c); + tdo->sme_threeD.top_shadow_pixel = set_c.pixel; +} + + +/* ARGSUSED */ +void XawSme3dComputeBottomShadowRGB (new, xcol_out) + Widget new; + XColor *xcol_out; +{ + if (XtIsSubclass (new, smeThreeDObjectClass)) { + SmeThreeDObject tdo = (SmeThreeDObject) new; + Widget w = XtParent (new); + XColor get_c; + double contrast; + Display *dpy = XtDisplayOfObject (new); + Screen *scn = XtScreenOfObject (new); + Colormap cmap = w->core.colormap; + + get_c.pixel = w->core.background_pixel; + if (get_c.pixel == WhitePixelOfScreen (scn) || + get_c.pixel == BlackPixelOfScreen (scn)) { + contrast = tdo->sme_threeD.bot_shadow_contrast / 100.0; + xcol_out->red = contrast * 65535.0; + xcol_out->green = contrast * 65535.0; + xcol_out->blue = contrast * 65535.0; + } else { + XQueryColor (dpy, cmap, &get_c); + contrast = (100 - tdo->sme_threeD.bot_shadow_contrast) / 100.0; + xcol_out->red = contrast * get_c.red; + xcol_out->green = contrast * get_c.green; + xcol_out->blue = contrast * get_c.blue; + } + } else + xcol_out->red = xcol_out->green = xcol_out->blue = 0; +} + +/* ARGSUSED */ +static void AllocBotShadowPixel (new) + Widget new; +{ + XColor set_c; + SmeThreeDObject tdo = (SmeThreeDObject) new; + Widget w = XtParent (new); + Display *dpy = XtDisplayOfObject (new); + Colormap cmap = w->core.colormap; + + XawSme3dComputeBottomShadowRGB (new, &set_c); + (void) XAllocColor (dpy, cmap, &set_c); + tdo->sme_threeD.bot_shadow_pixel = set_c.pixel; +} + + +/* ARGSUSED */ +static void ClassPartInitialize (wc) + WidgetClass wc; +{ + SmeThreeDClassRec *tdwc = (SmeThreeDClassRec *) wc; + SmeThreeDClassRec *super = + (SmeThreeDClassRec *) tdwc->rect_class.superclass; + + if (tdwc->sme_threeD_class.shadowdraw == XtInheritXawSme3dShadowDraw) + tdwc->sme_threeD_class.shadowdraw = super->sme_threeD_class.shadowdraw; +} + +/* ARGSUSED */ +static void Initialize (request, new, args, num_args) + Widget request, new; + ArgList args; + Cardinal *num_args; +{ + SmeThreeDObject w = (SmeThreeDObject) new; + Screen *scr = XtScreenOfObject (new); + + if (w->sme_threeD.be_nice_to_cmap || DefaultDepthOfScreen (scr) == 1) { + AllocTopShadowPixmap (new); + AllocBotShadowPixmap (new); + } else { + if (w->sme_threeD.top_shadow_pixel == w->sme_threeD.bot_shadow_pixel) { + AllocTopShadowPixel (new); + AllocBotShadowPixel (new); + } + w->sme_threeD.top_shadow_pxmap = w->sme_threeD.bot_shadow_pxmap = 0; + } + AllocTopShadowGC (new); + AllocBotShadowGC (new); + AllocEraseGC (new); +} + +static void Destroy (gw) + Widget gw; +{ + SmeThreeDObject w = (SmeThreeDObject) gw; + XtReleaseGC (gw, w->sme_threeD.top_shadow_GC); + XtReleaseGC (gw, w->sme_threeD.bot_shadow_GC); + XtReleaseGC (gw, w->sme_threeD.erase_GC); + if (w->sme_threeD.top_shadow_pxmap) + XFreePixmap (XtDisplayOfObject (gw), w->sme_threeD.top_shadow_pxmap); + if (w->sme_threeD.bot_shadow_pxmap) + XFreePixmap (XtDisplayOfObject (gw), w->sme_threeD.bot_shadow_pxmap); +} + +/* ARGSUSED */ +static Boolean SetValues (gcurrent, grequest, gnew, args, num_args) + Widget gcurrent, grequest, gnew; + ArgList args; + Cardinal *num_args; +{ + SmeThreeDObject current = (SmeThreeDObject) gcurrent; + SmeThreeDObject new = (SmeThreeDObject) gnew; + Boolean redisplay = FALSE; + Boolean alloc_top_pixel = FALSE; + Boolean alloc_bot_pixel = FALSE; + Boolean alloc_top_pixmap = FALSE; + Boolean alloc_bot_pixmap = FALSE; + +#if 0 + (*threeDWidgetClass->core_class.superclass->core_class.set_values) + (gcurrent, grequest, gnew, NULL, 0); +#endif + if (new->sme_threeD.shadow_width != current->sme_threeD.shadow_width) + redisplay = TRUE; + if (new->sme_threeD.be_nice_to_cmap != current->sme_threeD.be_nice_to_cmap) { + if (new->sme_threeD.be_nice_to_cmap) { + alloc_top_pixmap = TRUE; + alloc_bot_pixmap = TRUE; + } else { + alloc_top_pixel = TRUE; + alloc_bot_pixel = TRUE; + } + redisplay = TRUE; + } + if (!new->sme_threeD.be_nice_to_cmap && + new->sme_threeD.top_shadow_contrast != current->sme_threeD.top_shadow_contrast) + alloc_top_pixel = TRUE; + if (!new->sme_threeD.be_nice_to_cmap && + new->sme_threeD.bot_shadow_contrast != current->sme_threeD.bot_shadow_contrast) + alloc_bot_pixel = TRUE; + if (alloc_top_pixel) + AllocTopShadowPixel (gnew); + if (alloc_bot_pixel) + AllocBotShadowPixel (gnew); + if (alloc_top_pixmap) + AllocTopShadowPixmap (gnew); + if (alloc_bot_pixmap) + AllocBotShadowPixmap (gnew); + if (!new->sme_threeD.be_nice_to_cmap && + new->sme_threeD.top_shadow_pixel != current->sme_threeD.top_shadow_pixel) + alloc_top_pixel = TRUE; + if (!new->sme_threeD.be_nice_to_cmap && + new->sme_threeD.bot_shadow_pixel != current->sme_threeD.bot_shadow_pixel) + alloc_bot_pixel = TRUE; + if (new->sme_threeD.be_nice_to_cmap) { + if (alloc_top_pixmap) { + XtReleaseGC (gcurrent, current->sme_threeD.top_shadow_GC); + AllocTopShadowGC (gnew); + redisplay = True; + } + if (alloc_bot_pixmap) { + XtReleaseGC (gcurrent, current->sme_threeD.bot_shadow_GC); + AllocBotShadowGC (gnew); + redisplay = True; + } + } else { + if (alloc_top_pixel) { + if (new->sme_threeD.top_shadow_pxmap) { + XFreePixmap (XtDisplayOfObject (gnew), new->sme_threeD.top_shadow_pxmap); + new->sme_threeD.top_shadow_pxmap = (Pixmap) NULL; + } + XtReleaseGC (gcurrent, current->sme_threeD.top_shadow_GC); + AllocTopShadowGC (gnew); + redisplay = True; + } + if (alloc_bot_pixel) { + if (new->sme_threeD.bot_shadow_pxmap) { + XFreePixmap (XtDisplayOfObject (gnew), new->sme_threeD.bot_shadow_pxmap); + new->sme_threeD.bot_shadow_pxmap = (Pixmap) NULL; + } + XtReleaseGC (gcurrent, current->sme_threeD.bot_shadow_GC); + AllocBotShadowGC (gnew); + redisplay = True; + } + } + return (redisplay); +} + +/* ARGSUSED */ +static void +_XawSme3dDrawShadows(gw) + Widget gw; +{ + SmeThreeDObject tdo = (SmeThreeDObject) gw; + SimpleMenuWidget smw = (SimpleMenuWidget) XtParent(gw); + ThreeDWidget tdw = (ThreeDWidget) smw->simple_menu.threeD; + Dimension s = tdo->sme_threeD.shadow_width; + Dimension ps = tdw->threeD.shadow_width; + XPoint pt[6]; + + /* + * draw the shadows using the core part width and height, + * and the threeD part shadow_width. + * + * no point to do anything if the shadow_width is 0 or the + * widget has not been realized. + */ + if (s > 0 && XtIsRealized(gw)) + { + Dimension h = tdo->rectangle.height; + Dimension w = tdo->rectangle.width - ps; + Dimension x = tdo->rectangle.x + ps; + Dimension y = tdo->rectangle.y; + Display *dpy = XtDisplayOfObject(gw); + Window win = XtWindowOfObject(gw); + GC top, bot; + + if (tdo->sme_threeD.shadowed) + { + top = tdo->sme_threeD.top_shadow_GC; + bot = tdo->sme_threeD.bot_shadow_GC; + } + else + top = bot = tdo->sme_threeD.erase_GC; + + /* top-left shadow */ + pt[0].x = x; pt[0].y = y + h; + pt[1].x = x; pt[1].y = y; + pt[2].x = w; pt[2].y = y; + pt[3].x = w - s; pt[3].y = y + s; + pt[4].x = ps + s; pt[4].y = y + s; + pt[5].x = ps + s; pt[5].y = y + h - s; + XFillPolygon(dpy, win, top, pt, 6, Complex, CoordModeOrigin); + + /* bottom-right shadow */ +/* pt[0].x = x; pt[0].y = y + h; */ + pt[1].x = w; pt[1].y = y + h; +/* pt[2].x = w; pt[2].y = y; */ +/* pt[3].x = w - s; pt[3].y = y + s; */ + pt[4].x = w - s; pt[4].y = y + h - s; +/* pt[5].x = ps + s; pt[5].y = y + h - s; */ + XFillPolygon(dpy, win, bot, pt, 6, Complex, CoordModeOrigin); + } +} + diff --git a/src/SmeThreeD.h b/src/SmeThreeD.h new file mode 100644 index 0000000..b4d458f --- /dev/null +++ b/src/SmeThreeD.h @@ -0,0 +1,96 @@ +/* +* $KK: SmeThreeD.h,v 0.3 92/11/04 xx:xx:xx keithley Exp $ +*/ + +/*********************************************************** +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. +Copyright 1992 by Kaleb Keithley + + All Rights Reserved + +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 names of Digital, MIT, or Kaleb +Keithley not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _XawSmeThreeD_h +#define _XawSmeThreeD_h + +/*********************************************************************** + * + * ThreeD Widget + * + ***********************************************************************/ + +#include <X11/Xmu/Converters.h> +#include <X11/Xaw3d/Sme.h> + +/* Parameters: + + Name Class RepType Default Value + ---- ----- ------- ------------- + shadowWidth ShadowWidth Dimension 2 + topShadowPixel TopShadowPixel Pixel dynamic + bottomShadowPixel BottomShadowPixel Pixel dynamic + topShadowContrast TopShadowContrast Int 20 + bottomShadowContrast BottomShadowContrast Int 40 + userData UserData XtPointer NULL + beNiceToColormap BeNiceToColormap Boolean False + +*/ + +#define XtNshadowWidth "shadowWidth" +#define XtCShadowWidth "ShadowWidth" +#define XtNtopShadowPixel "topShadowPixel" +#define XtCTopShadowPixel "TopShadowPixel" +#define XtNbottomShadowPixel "bottomShadowPixel" +#define XtCBottomShadowPixel "BottomShadowPixel" +#define XtNtopShadowContrast "topShadowContrast" +#define XtCTopShadowContrast "TopShadowContrast" +#define XtNbottomShadowContrast "bottomShadowContrast" +#define XtCBottomShadowContrast "BottomShadowContrast" +#define XtNbeNiceToColormap "beNiceToColormap" +#define XtCBeNiceToColormap "BeNiceToColormap" +#define XtNbeNiceToColourmap "beNiceToColormap" +#define XtCBeNiceToColourmap "BeNiceToColormap" +#define XtNuserData "userData" +#define XtCUserData "UserData" + +typedef struct _SmeThreeDClassRec *SmeThreeDObjectClass; +typedef struct _SmeThreeDRec *SmeThreeDObject; + +extern WidgetClass smeThreeDWidgetClass; + +_XFUNCPROTOBEGIN + +extern void XawSme3dComputeTopShadowRGB ( +#if NeedFunctionPrototypes + Widget /* new */, + XColor* /* xcol_out */ +#endif +); + +extern void XawSme3dComputeBottomShadowRGB ( +#if NeedFunctionPrototypes + Widget /* new */, + XColor* /* xcol_out */ +#endif +); + +_XFUNCPROTOEND + +#endif /* _XawSmeThreeD_h */ diff --git a/src/SmeThreeDP.h b/src/SmeThreeDP.h new file mode 100644 index 0000000..a07dd40 --- /dev/null +++ b/src/SmeThreeDP.h @@ -0,0 +1,82 @@ +/* +* $KK: SmeThreeDP.h,v 0.3 92/11/04 xx:xx:xx keithley Exp $ +*/ + +/*********************************************************** +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. +Copyright 1992 by Kaleb Keithley + + All Rights Reserved + +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 names of Digital, MIT, or Kaleb +Keithley not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _XawSmeThreeDP_h +#define _XawSmeThreeDP_h + +#include <X11/Xaw3d/SmeThreeD.h> +#include <X11/Xaw3d/SmeP.h> + +typedef struct { + Dimension shadow_width; + Pixel top_shadow_pixel; + Pixel bot_shadow_pixel; + Pixmap top_shadow_pxmap; + Pixmap bot_shadow_pxmap; + int top_shadow_contrast; + int bot_shadow_contrast; + GC top_shadow_GC; + GC bot_shadow_GC; + GC erase_GC; + XtPointer user_data; + Boolean be_nice_to_cmap; + Boolean shadowed; + } SmeThreeDPart; + +/* Full instance record declaration */ +typedef struct _SmeThreeDRec { + ObjectPart object; + RectObjPart rectangle; + SmePart sme; + SmeThreeDPart sme_threeD; + } SmeThreeDRec; + +typedef void (*XawSme3dShadowDrawProc)( +#if NeedFunctionPrototypes + Widget +#endif +); + +typedef struct { + XawSme3dShadowDrawProc shadowdraw; + } SmeThreeDClassPart; + +/* Full class record declaration. */ +typedef struct _SmeThreeDClassRec { + RectObjClassPart rect_class; + SmeClassPart sme_class; + SmeThreeDClassPart sme_threeD_class; + } SmeThreeDClassRec; + +/* Class pointer. */ +extern SmeThreeDClassRec smeThreeDClassRec; + +#define XtInheritXawSme3dShadowDraw ((XawSme3dShadowDrawProc) _XtInherit) + +#endif /* _XawSmeThreeDP_h */ diff --git a/src/StripCharP.h b/src/StripCharP.h new file mode 100644 index 0000000..feb91e7 --- /dev/null +++ b/src/StripCharP.h @@ -0,0 +1,109 @@ +/* +* $XConsortium: StripCharP.h,v 1.5 94/04/17 20:12:55 converse Exp $ +*/ + + +/*********************************************************** + +Copyright (c) 1987, 1988 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _XawStripChartP_h +#define _XawStripChartP_h + +#include <X11/Xaw3d/StripChart.h> +#include <X11/Xaw3d/ThreeDP.h> + +#define NO_GCS 0 +#define FOREGROUND 1 << 0 +#define HIGHLIGHT 1 << 1 +#define ALL_GCS (FOREGROUND | HIGHLIGHT) + +/* New fields for the stripChart widget instance record */ + +typedef struct { + Pixel fgpixel; /* color index for graph */ + Pixel hipixel; /* color index for lines */ + GC fgGC; /* graphics context for fgpixel */ + GC hiGC; /* graphics context for hipixel */ + + /* start of graph stuff */ + + int update; /* update frequence */ + int scale; /* scale factor */ + int min_scale; /* smallest scale factor */ + int interval; /* data point interval */ + XPoint * points ; /* Poly point for repairing graph lines. */ + double max_value; /* Max Value in window */ + double valuedata[2048];/* record of data points */ + XtIntervalId interval_id; + XtCallbackList get_value; /* proc to call to fetch load pt */ + int jump_val; /* Amount to jump on each scroll. */ +} StripChartPart; + +/* Full instance record declaration */ +typedef struct _StripChartRec { + CorePart core; + SimplePart simple; + ThreeDPart threeD; + StripChartPart strip_chart; +} StripChartRec; + +/* New fields for the StripChart widget class record */ +typedef struct {int dummy;} StripChartClassPart; + +/* Full class record declaration. */ +typedef struct _StripChartClassRec { + CoreClassPart core_class; + SimpleClassPart simple_class; + ThreeDClassPart threeD_class; + StripChartClassPart strip_chart_class; +} StripChartClassRec; + +/* Class pointer. */ +extern StripChartClassRec stripChartClassRec; + +#endif /* _XawStripChartP_h */ diff --git a/src/StripChart.c b/src/StripChart.c new file mode 100644 index 0000000..5344f97 --- /dev/null +++ b/src/StripChart.c @@ -0,0 +1,556 @@ +/* $XConsortium: StripChart.c,v 1.25 94/04/17 20:12:56 kaleb Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/StripCharP.h> +#include <X11/Xfuncs.h> + +#define MS_PER_SEC 1000 + +/* Private Data */ + +#define offset(field) XtOffsetOf(StripChartRec, field) + +static XtResource resources[] = { + {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension), + offset(core.width), XtRImmediate, (XtPointer) 120}, + {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension), + offset(core.height), XtRImmediate, (XtPointer) 120}, + {XtNupdate, XtCInterval, XtRInt, sizeof(int), + offset(strip_chart.update), XtRImmediate, (XtPointer) 10}, + {XtNminScale, XtCScale, XtRInt, sizeof(int), + offset(strip_chart.min_scale), XtRImmediate, (XtPointer) 1}, + {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), + offset(strip_chart.fgpixel), XtRString, XtDefaultForeground}, + {XtNhighlight, XtCForeground, XtRPixel, sizeof(Pixel), + offset(strip_chart.hipixel), XtRString, XtDefaultForeground}, + {XtNgetValue, XtCCallback, XtRCallback, sizeof(XtPointer), + offset(strip_chart.get_value), XtRImmediate, (XtPointer) NULL}, + {XtNjumpScroll, XtCJumpScroll, XtRInt, sizeof(int), + offset(strip_chart.jump_val), XtRImmediate, (XtPointer) DEFAULT_JUMP}, +}; + +#undef offset + +static void Initialize(), Destroy(), Redisplay(), MoveChart(), SetPoints(); +static Boolean SetValues(); +static int repaint_window(); + +StripChartClassRec stripChartClassRec = { + { /* core fields */ + /* superclass */ (WidgetClass) &threeDClassRec, + /* class_name */ "StripChart", + /* size */ sizeof(StripChartRec), + /* class_initialize */ XawInitializeWidgetSet, + /* 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 */ XtExposeCompressMultiple | + XtExposeGraphicsExposeMerged, + /* compress_enterleave */ TRUE, + /* visible_interest */ FALSE, + /* destroy */ Destroy, + /* resize */ SetPoints, + /* expose */ Redisplay, + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* set_values_almost */ NULL, + /* get_values_hook */ NULL, + /* accept_focus */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* tm_table */ NULL, + /* query_geometry */ XtInheritQueryGeometry, + /* display_accelerator */ XtInheritDisplayAccelerator, + /* extension */ NULL + }, + { /* Simple class fields */ + /* change_sensitive */ XtInheritChangeSensitive + }, + { /* ThreeD fields */ + /* shadowdraw */ XtInheritXaw3dShadowDraw + }, + { /* Stripchart fields */ + /* ignore */ 0 + } +}; + +WidgetClass stripChartWidgetClass = (WidgetClass) &stripChartClassRec; + +/**************************************************************** + * + * Private Procedures + * + ****************************************************************/ + +static void draw_it(); + +/* Function Name: CreateGC + * Description: Creates the GC's + * Arguments: w - the strip chart widget. + * which - which GC's to create. + * Returns: none + */ + +static void +CreateGC(w, which) +StripChartWidget w; +unsigned int which; +{ + XGCValues myXGCV; + + if (which & FOREGROUND) { + myXGCV.foreground = w->strip_chart.fgpixel; + w->strip_chart.fgGC = XtGetGC((Widget) w, GCForeground, &myXGCV); + } + + if (which & HIGHLIGHT) { + myXGCV.foreground = w->strip_chart.hipixel; + w->strip_chart.hiGC = XtGetGC((Widget) w, GCForeground, &myXGCV); + } +} + +/* Function Name: DestroyGC + * Description: Destroys the GC's + * Arguments: w - the strip chart widget. + * which - which GC's to destroy. + * Returns: none + */ + +static void +DestroyGC(w, which) +StripChartWidget w; +unsigned int which; +{ + if (which & FOREGROUND) + XtReleaseGC((Widget) w, w->strip_chart.fgGC); + + if (which & HIGHLIGHT) + XtReleaseGC((Widget) w, w->strip_chart.hiGC); +} + +/* ARGSUSED */ +static void Initialize (greq, gnew, args, num_args) + Widget greq, gnew; + ArgList args; + Cardinal *num_args; +{ + StripChartWidget w = (StripChartWidget)gnew; + + if (w->strip_chart.update > 0) + w->strip_chart.interval_id = + XtAppAddTimeOut( XtWidgetToApplicationContext(gnew), + (unsigned long) w->strip_chart.update * MS_PER_SEC, + draw_it, (XtPointer) gnew); + CreateGC(w, (unsigned int) ALL_GCS); + + w->strip_chart.scale = w->strip_chart.min_scale; + w->strip_chart.interval = 0; + w->strip_chart.max_value = 0.0; + w->strip_chart.points = NULL; + SetPoints((Widget)w); +} + +static void Destroy (gw) + Widget gw; +{ + StripChartWidget w = (StripChartWidget)gw; + + if (w->strip_chart.update > 0) + XtRemoveTimeOut (w->strip_chart.interval_id); + if (w->strip_chart.points) + XtFree((char *) w->strip_chart.points); + DestroyGC(w, (unsigned int) ALL_GCS); +} + +/* + * NOTE: This function really needs to recieve graphics exposure + * events, but since this is not easily supported until R4 I am + * going to hold off until then. + */ + +/* ARGSUSED */ +static void Redisplay(gw, event, region) + Widget gw; + XEvent *event; + Region region; +{ + + StripChartWidget w = (StripChartWidget)gw; + StripChartWidgetClass swclass = (StripChartWidgetClass) XtClass (gw); + Dimension x, width, s = w->threeD.shadow_width; + + (*swclass->threeD_class.shadowdraw) (gw, event, region, w->threeD.relief, FALSE); + + if (event->type == GraphicsExpose) { + x = event->xgraphicsexpose.x; + width = event->xgraphicsexpose.width; + } else { + x = event->xexpose.x; + width = event->xexpose.width; + } + if (x > s) x -= s; /* respect shadow width, but don't become negative */ + else x = 0; + if (x + width > w->core.width - 2 * s) /* ditto for right boundary */ + width = w->core.width - 2 * s - x; + + (void) repaint_window (gw, x, width); +} + +/* ARGSUSED */ +static void +draw_it(client_data, id) +XtPointer client_data; +XtIntervalId *id; /* unused */ +{ + StripChartWidget w = (StripChartWidget)client_data; + StripChartWidgetClass swclass = (StripChartWidgetClass) XtClass ((Widget) w); + Dimension s = w->threeD.shadow_width; + double value; + + if (w->strip_chart.update > 0) + w->strip_chart.interval_id = + XtAppAddTimeOut(XtWidgetToApplicationContext( (Widget) w), + (unsigned long) w->strip_chart.update * MS_PER_SEC, + draw_it, client_data); + + if (w->strip_chart.interval >= (int)( w->core.width - 2 * s)) + MoveChart( (StripChartWidget) w, TRUE); + + /* Get the value, stash the point and draw corresponding line. */ + + if (w->strip_chart.get_value == NULL) + return; + + XtCallCallbacks( (Widget)w, XtNgetValue, (XtPointer)&value ); + + /* + * Keep w->strip_chart.max_value up to date, and if this data + * point is off the graph, change the scale to make it fit. + */ + + if (value > w->strip_chart.max_value) { + w->strip_chart.max_value = value; + if (XtIsRealized((Widget)w) && + w->strip_chart.max_value > w->strip_chart.scale) { + XClearWindow(XtDisplay ((Widget) w), XtWindow ((Widget) w)); + w->strip_chart.interval = repaint_window((Widget)w, 0, (int) w->core.width - 2 * s); + (*swclass->threeD_class.shadowdraw) ((Widget) w, + (XEvent *)0, (Region)0, + w->threeD.relief, FALSE); + } + } + + w->strip_chart.valuedata[w->strip_chart.interval] = value; + if (XtIsRealized((Widget)w)) { + int y = (int) (( w->core.height - 2 * s) + - (int)(( w->core.height - 2 * s) * value) / w->strip_chart.scale); + + XFillRectangle(XtDisplay((Widget) w), XtWindow((Widget) w), w->strip_chart.fgGC, + w->strip_chart.interval + s, + y + s, (unsigned int) 1, + (w->core.height - 2 * s) - y); + /* + * Fill in the graph lines we just painted over. + */ + + if (w->strip_chart.points != NULL) { + w->strip_chart.points[0].x = w->strip_chart.interval + s; + XDrawPoints(XtDisplay(w), XtWindow(w), w->strip_chart.hiGC, + w->strip_chart.points, w->strip_chart.scale, + CoordModePrevious); + } + + XFlush(XtDisplay(w)); /* Flush output buffers */ + } + w->strip_chart.interval++; /* Next point */ +} /* draw_it */ + +/* Blts data according to current size, then redraws the stripChart window. + * Next represents the number of valid points in data. Returns the (possibly) + * adjusted value of next. If next is 0, this routine draws an empty window + * (scale - 1 lines for graph). If next is less than the current window width, + * the returned value is identical to the initial value of next and data is + * unchanged. Otherwise keeps half a window's worth of data. If data is + * changed, then w->strip_chart.max_value is updated to reflect the + * largest data point. + */ + +static int +repaint_window(gw, left, width) +Widget gw; +int left, width; +{ + StripChartWidget w = (StripChartWidget) gw; + Dimension s = w->threeD.shadow_width; + StripChartWidgetClass swclass = (StripChartWidgetClass) XtClass ((Widget) w); + int i, j; + int next = w->strip_chart.interval; + int scale = w->strip_chart.scale; + int scalewidth = 0; + + /* Compute the minimum scale required to graph the data, but don't go + lower than min_scale. */ + if (w->strip_chart.interval != 0 || scale <= (int)w->strip_chart.max_value) + scale = ((int) (w->strip_chart.max_value)) + 1; + if (scale < w->strip_chart.min_scale) + scale = w->strip_chart.min_scale; + + if (scale != w->strip_chart.scale) { + w->strip_chart.scale = scale; + left = 0; + width = next; /* check this */ + scalewidth = w->core.width - 2 * s; + + SetPoints(gw); + + if (XtIsRealized (gw)) { + XClearWindow (XtDisplay (gw), XtWindow (gw)); + (*swclass->threeD_class.shadowdraw) (gw, (XEvent *)0, (Region)0, w->threeD.relief, FALSE); + } + + } + + if (XtIsRealized(gw)) { + Display *dpy = XtDisplay(gw); + Window win = XtWindow(gw); + + width += left - 1; + if (!scalewidth) scalewidth = width; + + if (next < (++width - s)) width = next + s; + + /* Draw data point lines. */ + for (i = left; i < width; i++) { + int y = (int) (( w->core.height - 2 * s) - + (int)(( w->core.height - 2 * s) * w->strip_chart.valuedata[i]) / + w->strip_chart.scale); + + XFillRectangle(dpy, win, w->strip_chart.fgGC, + i + s, y + s, (unsigned int) 1, + (unsigned int) (w->core.height - 2 * s - y )); + } + + /* Draw graph reference lines */ + for (i = 1; i < w->strip_chart.scale; i++) { + j = i * ((w->core.height - 2 * s) / w->strip_chart.scale); + XDrawLine(dpy, win, w->strip_chart.hiGC, + left + s, j + s, scalewidth + s, j + s); + } + } + return(next); +} + +/* Function Name: MoveChart + * Description: moves the chart over when it would run off the end. + * Arguments: w - the load widget. + * blit - blit the bits? (TRUE/FALSE). + * Returns: none. + */ + +static void +MoveChart(w, blit) +StripChartWidget w; +Boolean blit; +{ + Dimension s = w->threeD.shadow_width; + double old_max; + int left, i, j; + int next = w->strip_chart.interval; + + if (!XtIsRealized((Widget) w)) return; + + if (w->strip_chart.jump_val < 0) w->strip_chart.jump_val = DEFAULT_JUMP; + if (w->strip_chart.jump_val == DEFAULT_JUMP) + j = ( w->core.width - 2 * s) / 2; /* Half the window width. */ + else { + j = ( w->core.width - 2 * s) - w->strip_chart.jump_val; + if (j < 0) j = 0; + } + + (void) memmove((char *)(w->strip_chart.valuedata), + (char *)(w->strip_chart.valuedata + next - j), + j * sizeof(double)); + next = w->strip_chart.interval = j; + + /* + * Since we just lost some data, recompute the + * w->strip_chart.max_value. + */ + + old_max = w->strip_chart.max_value; + w->strip_chart.max_value = 0.0; + for (i = 0; i < next; i++) { + if (w->strip_chart.valuedata[i] > w->strip_chart.max_value) + w->strip_chart.max_value = w->strip_chart.valuedata[i]; + } + + if (!blit) return; /* we are done... */ + + if ( ((int) old_max) != ( (int) w->strip_chart.max_value) ) { + XClearWindow(XtDisplay(w), XtWindow(w)); + repaint_window((Widget)w, 0, w->core.width - 2 * s); + return; + } + + XCopyArea(XtDisplay((Widget)w), XtWindow((Widget)w), XtWindow((Widget)w), + w->strip_chart.hiGC, + (int) ((w->strip_chart.jump_val == DEFAULT_JUMP) ? + (j + s) : (w->strip_chart.jump_val + s)), s, + (unsigned int) j, (unsigned int) ( w->core.height - 2 * s), + s, s); + + XClearArea(XtDisplay((Widget)w), XtWindow((Widget)w), + (int) j + s, s, + (unsigned int) ((w->strip_chart.jump_val == DEFAULT_JUMP) ? + j : w->strip_chart.jump_val), + (unsigned int) ( w->core.height - 2 * s), + FALSE); + + /* Draw graph reference lines */ + left = j; + for (i = 1; i < w->strip_chart.scale; i++) { + j = i * ((w->core.height - 2 * s) / w->strip_chart.scale); + XDrawLine(XtDisplay((Widget) w), XtWindow( (Widget) w), + w->strip_chart.hiGC, + left, j + s, ((int)w->core.width - s - 1), j + s); + } + return; +} + +/* ARGSUSED */ +static Boolean SetValues (current, request, new, args, num_args) + Widget current, request, new; + ArgList args; + Cardinal *num_args; +{ + StripChartWidget old = (StripChartWidget)current; + StripChartWidget w = (StripChartWidget)new; + Boolean ret_val = FALSE; + unsigned int new_gc = NO_GCS; + + if (w->strip_chart.update != old->strip_chart.update) { + if (old->strip_chart.update > 0) + XtRemoveTimeOut (old->strip_chart.interval_id); + if (w->strip_chart.update > 0) + w->strip_chart.interval_id = + XtAppAddTimeOut(XtWidgetToApplicationContext(new), + (unsigned long) w->strip_chart.update * MS_PER_SEC, + draw_it, (XtPointer)w); + } + + if ( w->strip_chart.min_scale > (int) ((w->strip_chart.max_value) + 1) ) + ret_val = TRUE; + + if ( w->strip_chart.fgpixel != old->strip_chart.fgpixel ) { + new_gc |= FOREGROUND; + ret_val = True; + } + + if ( w->strip_chart.hipixel != old->strip_chart.hipixel ) { + new_gc |= HIGHLIGHT; + ret_val = True; + } + + DestroyGC(old, new_gc); + CreateGC(w, new_gc); + + return( ret_val ); +} + +/* Function Name: SetPoints + * Description: Sets up the polypoint that will be used to draw in + * the graph lines. + * Arguments: w - the StripChart widget. + * Returns: none. + */ + +#define HEIGHT ( (unsigned int) w->core.height) + +static void +SetPoints(widget) +Widget widget; +{ + StripChartWidget w = (StripChartWidget) widget; + Dimension s = w->threeD.shadow_width; + XPoint * points; + Cardinal size; + int i; + + if (w->strip_chart.scale <= 1) { /* no scale lines. */ + XtFree ((char *) w->strip_chart.points); + w->strip_chart.points = NULL; + return; + } + + size = sizeof(XPoint) * (w->strip_chart.scale - 1); + + points = (XPoint *) XtRealloc( (XtPointer) w->strip_chart.points, size); + w->strip_chart.points = points; + + /* Draw graph reference lines into clip mask */ + + for (i = 1; i < w->strip_chart.scale; i++) { + points[i - 1].x = 0; + points[i - 1].y = ( short)(((double)w->core.height - 2.0 * (double) s) / (double) w->strip_chart.scale ); + } + points[0].y += (short)s; +} diff --git a/src/StripChart.h b/src/StripChart.h new file mode 100644 index 0000000..93052d0 --- /dev/null +++ b/src/StripChart.h @@ -0,0 +1,118 @@ +/* $XConsortium: StripChart.h,v 1.6 94/04/17 20:12:57 converse Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _XawStripChart_h +#define _XawStripChart_h + +/*********************************************************************** + * + * StripChart Widget + * + ***********************************************************************/ + +/* StripChart resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + accelerators Accelerators AcceleratorTable NULL + ancestorSensitive AncestorSensitive Boolean True + background Background Pixel XtDefaultBackground + backgroundPixmap Pixmap Pixmap XtUnspecifiedPixmap + borderColor BorderColor Pixel XtDefaultForeground + borderPixmap Pixmap Pixmap XtUnspecifiedPixmap + borderWidth BorderWidth Dimension 1 + colormap Colormap Colormap parent's colormap + cursor Cursor Cursor None + cursorName Cursor String NULL + depth Depth int parent's depth + destroyCallback Callback XtCallbackList NULL + foreground Foreground Pixel XtDefaultForeground + getValue Callback XtCallbackList NULL + height Height Dimension 120 + highlight Foreground Pixel XtDefaultForeground + insensitiveBorder Insensitive Pixmap GreyPixmap + jumpScroll JumpScroll int 1/2 width + mappedWhenManaged MappedWhenManaged Boolean True + minScale Scale int 1 + pointerColor Foreground Pixel XtDefaultForeground + pointerColorBackground Background Pixel XtDefaultBackground + screen Screen Screen parent's screen + sensitive Sensitive Boolean True + translations Translations TranslationTable NULL + update Interval int 10 (seconds) + width Width Dimension 120 + x Position Position 0 + y Position Position 0 + +*/ + +#define DEFAULT_JUMP -1 + +#ifndef _XtStringDefs_h_ +#define XtNhighlight "highlight" +#define XtNupdate "update" +#endif + +#define XtCJumpScroll "JumpScroll" +#define XtCScale "Scale" + +#define XtNgetValue "getValue" +#define XtNjumpScroll "jumpScroll" +#define XtNminScale "minScale" +#define XtNscale "scale" +#define XtNvmunix "vmunix" + +typedef struct _StripChartRec *StripChartWidget; +typedef struct _StripChartClassRec *StripChartWidgetClass; + +extern WidgetClass stripChartWidgetClass; + +#endif /* _XawStripChart_h */ +/* DON'T ADD STUFF AFTER THIS #endif */ diff --git a/src/Template.c b/src/Template.c new file mode 100644 index 0000000..33063aa --- /dev/null +++ b/src/Template.c @@ -0,0 +1,94 @@ +/* $XConsortium: Template.c,v 1.5 94/04/17 20:12:58 converse Exp $ */ + +/* + +Copyright (c) 1987 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include "TemplateP.h" + +static XtResource resources[] = { +#define offset(field) XtOffsetOf(TemplateRec, template.field) + /* {name, class, type, size, offset, default_type, default_addr}, */ + { XtNtemplateResource, XtCTemplateResource, XtRTemplateResource, + sizeof(char*), offset(resource), XtRString, (XtPointer) "default" }, +#undef offset +}; + +static void TemplateAction(/* Widget, XEvent*, String*, Cardinal* */); + +static XtActionsRec actions[] = +{ + /* {name, procedure}, */ + {"template", TemplateAction}, +}; + +static char translations[] = +"<Key>: template() \n\ +"; + +TemplateClassRec templateClassRec = { + { /* core fields */ + /* superclass */ (WidgetClass) &widgetClassRec, + /* class_name */ "Template", + /* widget_size */ sizeof(TemplateRec), + /* class_initialize */ NULL, + /* class_part_initialize */ NULL, + /* class_inited */ FALSE, + /* initialize */ NULL, + /* initialize_hook */ NULL, + /* realize */ XtInheritRealize, + /* actions */ actions, + /* num_actions */ XtNumber(actions), + /* resources */ resources, + /* num_resources */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ TRUE, + /* compress_exposure */ TRUE, + /* compress_enterleave */ TRUE, + /* visible_interest */ FALSE, + /* destroy */ NULL, + /* resize */ NULL, + /* expose */ NULL, + /* set_values */ NULL, + /* 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 + }, + { /* template fields */ + /* empty */ 0 + } +}; + +WidgetClass templateWidgetClass = (WidgetClass)&templateClassRec; diff --git a/src/Template.h b/src/Template.h new file mode 100644 index 0000000..dbb6b14 --- /dev/null +++ b/src/Template.h @@ -0,0 +1,71 @@ +/* $XConsortium: Template.h,v 1.6 94/04/17 20:12:59 converse Exp $ */ + +/* + +Copyright (c) 1987 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +#ifndef _Template_h +#define _Template_h + +/**************************************************************** + * + * Template widget + * + ****************************************************************/ + +/* Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + background Background Pixel XtDefaultBackground + border BorderColor Pixel XtDefaultForeground + borderWidth BorderWidth Dimension 1 + destroyCallback Callback Pointer NULL + height Height Dimension 0 + mappedWhenManaged MappedWhenManaged Boolean True + sensitive Sensitive Boolean True + width Width Dimension 0 + x Position Position 0 + y Position Position 0 + +*/ + +/* define any special resource names here that are not in <X11/StringDefs.h> */ + +#define XtNtemplateResource "templateResource" + +#define XtCTemplateResource "TemplateResource" + +/* declare specific TemplateWidget class and instance datatypes */ + +typedef struct _TemplateClassRec* TemplateWidgetClass; +typedef struct _TemplateRec* TemplateWidget; + +/* declare the class constant */ + +extern WidgetClass templateWidgetClass; + +#endif /* _Template_h */ diff --git a/src/TemplateP.h b/src/TemplateP.h new file mode 100644 index 0000000..d20175e --- /dev/null +++ b/src/TemplateP.h @@ -0,0 +1,64 @@ +/* $XConsortium: TemplateP.h,v 1.7 94/04/17 20:13:00 rws Exp $ */ + +/* + +Copyright (c) 1987 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + + +#ifndef _TemplateP_h +#define _TemplateP_h + +#include <X11/Xaw3d/Template.h> +/* include superclass private header file */ +#include <X11/CoreP.h> + +/* define unique representation types not found in <X11/StringDefs.h> */ + +#define XtRTemplateResource "TemplateResource" + +typedef struct { + int empty; +} TemplateClassPart; + +typedef struct _TemplateClassRec { + CoreClassPart core_class; + TemplateClassPart template_class; +} TemplateClassRec; + +extern TemplateClassRec templateClassRec; + +typedef struct { + /* resources */ + char* resource; + /* private state */ +} TemplatePart; + +typedef struct _TemplateRec { + CorePart core; + TemplatePart template; +} TemplateRec; + +#endif /* _TemplateP_h */ diff --git a/src/Text.c b/src/Text.c new file mode 100644 index 0000000..4b47bbd --- /dev/null +++ b/src/Text.c @@ -0,0 +1,3600 @@ +/* $XConsortium: Text.c,v 1.197 95/06/14 15:07:27 kaleb Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#include "Xaw3dP.h" +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Shell.h> +#include <X11/Xatom.h> +#include <X11/Xutil.h> +#ifdef XAW_INTERNATIONALIZATION +#include "XawI18n.h" +#endif +#include <stdio.h> +#include <X11/Xmu/Atoms.h> +#include <X11/Xmu/CharSet.h> +#include <X11/Xmu/Converters.h> +#include <X11/Xmu/StdSel.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/Cardinals.h> +#include <X11/Xaw3d/Scrollbar.h> +#include <X11/Xaw3d/TextP.h> +#ifdef XAW_INTERNATIONALIZATION +#include <X11/Xaw3d/MultiSinkP.h> +#include <X11/Xaw3d/XawImP.h> +#endif +#include <X11/Xaw3d/ThreeDP.h> +#include <X11/Xfuncs.h> +#include <ctype.h> /* for isprint() */ + +#ifndef MAX_LEN_CT +#define MAX_LEN_CT 6 /* for sequence: ESC $ ( A \xx \xx */ +#endif + +unsigned long FMT8BIT = 0L; +unsigned long XawFmt8Bit = 0L; +#ifdef XAW_INTERNATIONALIZATION +unsigned long XawFmtWide = 0L; +#endif + +#define SinkClearToBG XawTextSinkClearToBackground + +#define SrcScan XawTextSourceScan +#define SrcRead XawTextSourceRead +#define SrcReplace XawTextSourceReplace +#define SrcSearch XawTextSourceSearch +#define SrcCvtSel XawTextSourceConvertSelection +#define SrcSetSelection XawTextSourceSetSelection + +#define BIGNUM ((Dimension)32023) +#define MULTI_CLICK_TIME 500L + +/* + * Compute a the maximum length of a cut buffer that we can pass at any + * time. The 64 allows for the overhead of the Change Property request. + */ + +#define MAX_CUT_LEN(dpy) (XMaxRequestSize(dpy) - 64) + +#define IsValidLine(ctx, num) ( ((num) == 0) || \ + ((ctx)->text.lt.info[(num)].position != 0) ) + +/* + * Defined in Text.c + */ +static void UnrealizeScrollbars(); +static void VScroll(), VJump(), HScroll(), HJump(), ClearWindow(); +static void DisplayTextWindow(), ModifySelection(), PushCopyQueue(); +static void UpdateTextInLine(), UpdateTextInRectangle(), PopCopyQueue(); +static void FlushUpdate(); +static Boolean LineAndXYForPosition(), TranslateExposeRegion(); +static XawTextPosition FindGoodPosition(), _BuildLineTable(); + +void _XawTextAlterSelection(), _XawTextExecuteUpdate(); +void _XawTextSetScrollBars(), _XawTextPrepareToUpdate(); + +/**************************************************************** + * + * Full class record constant + * + ****************************************************************/ + +static XawTextSelectType defaultSelectTypes[] = { + XawselectPosition, XawselectWord, XawselectLine, XawselectParagraph, + XawselectAll, XawselectNull, +}; + +static XPointer defaultSelectTypesPtr = (XPointer)defaultSelectTypes; +extern char *_XawDefaultTextTranslations1, *_XawDefaultTextTranslations2, + *_XawDefaultTextTranslations3, *_XawDefaultTextTranslations4; +static Dimension defWidth = 100; +static Dimension defHeight = DEFAULT_TEXT_HEIGHT; + +#define offset(field) XtOffsetOf(TextRec, field) +static XtResource resources[] = { + {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension), + offset(core.width), XtRDimension, (XtPointer)&defWidth}, + {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor), + offset(simple.cursor), XtRString, "xterm"}, + {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension), + offset(core.height), XtRDimension, (XtPointer)&defHeight}, + {XtNdisplayPosition, XtCTextPosition, XtRInt, sizeof(XawTextPosition), + offset(text.lt.top), XtRImmediate, (XtPointer)0}, + {XtNinsertPosition, XtCTextPosition, XtRInt, sizeof(XawTextPosition), + offset(text.insertPos), XtRImmediate,(XtPointer)0}, + {XtNleftMargin, XtCMargin, XtRPosition, sizeof (Position), + offset(text.r_margin.left), XtRImmediate, (XtPointer)2}, + {XtNrightMargin, XtCMargin, XtRPosition, sizeof (Position), + offset(text.r_margin.right), XtRImmediate, (XtPointer)4}, + {XtNtopMargin, XtCMargin, XtRPosition, sizeof (Position), + offset(text.r_margin.top), XtRImmediate, (XtPointer)2}, + {XtNbottomMargin, XtCMargin, XtRPosition, sizeof (Position), + offset(text.r_margin.bottom), XtRImmediate, (XtPointer)2}, + {XtNselectTypes, XtCSelectTypes, XtRPointer, + sizeof(XawTextSelectType*), offset(text.sarray), + XtRPointer, (XtPointer)&defaultSelectTypesPtr}, + {XtNtextSource, XtCTextSource, XtRWidget, sizeof (Widget), + offset(text.source), XtRImmediate, NULL}, + {XtNtextSink, XtCTextSink, XtRWidget, sizeof (Widget), + offset(text.sink), XtRImmediate, NULL}, + {XtNdisplayCaret, XtCOutput, XtRBoolean, sizeof(Boolean), + offset(text.display_caret), XtRImmediate, (XtPointer)True}, + {XtNscrollVertical, XtCScroll, XtRScrollMode, sizeof(XawTextScrollMode), + offset(text.scroll_vert), XtRImmediate, (XtPointer) XawtextScrollNever}, + {XtNscrollHorizontal, XtCScroll, XtRScrollMode, sizeof(XawTextScrollMode), + offset(text.scroll_horiz), XtRImmediate, (XtPointer) XawtextScrollNever}, + {XtNwrap, XtCWrap, XtRWrapMode, sizeof(XawTextWrapMode), + offset(text.wrap), XtRImmediate, (XtPointer) XawtextWrapNever}, + {XtNresize, XtCResize, XtRResizeMode, sizeof(XawTextResizeMode), + offset(text.resize), XtRImmediate, (XtPointer) XawtextResizeNever}, + {XtNautoFill, XtCAutoFill, XtRBoolean, sizeof(Boolean), + offset(text.auto_fill), XtRImmediate, (XtPointer) FALSE}, + {XtNunrealizeCallback, XtCCallback, XtRCallback, sizeof(XtPointer), + offset(text.unrealize_callbacks), XtRCallback, (XtPointer) NULL} +}; +#undef offset + +/* ARGSUSED */ +static void +CvtStringToScrollMode(args, num_args, fromVal, toVal) +XrmValuePtr args; /* unused */ +Cardinal *num_args; /* unused */ +XrmValuePtr fromVal; +XrmValuePtr toVal; +{ + static XawTextScrollMode scrollMode; + static XrmQuark QScrollNever, QScrollAlways, QScrollWhenNeeded; + XrmQuark q; + char lowerName[40]; + static Boolean inited = FALSE; + + if ( !inited ) { + QScrollNever = XrmPermStringToQuark(XtEtextScrollNever); + QScrollWhenNeeded = XrmPermStringToQuark(XtEtextScrollWhenNeeded); + QScrollAlways = XrmPermStringToQuark(XtEtextScrollAlways); + inited = TRUE; + } + + if (strlen ((char*) fromVal->addr) < sizeof lowerName) { + XmuCopyISOLatin1Lowered (lowerName, (char *)fromVal->addr); + q = XrmStringToQuark(lowerName); + + if (q == QScrollNever) scrollMode = XawtextScrollNever; + else if (q == QScrollWhenNeeded) scrollMode = XawtextScrollWhenNeeded; + else if (q == QScrollAlways) scrollMode = XawtextScrollAlways; + else { + toVal->size = 0; + toVal->addr = NULL; + return; + } + toVal->size = sizeof scrollMode; + toVal->addr = (XPointer) &scrollMode; + return; + } + toVal->size = 0; + toVal->addr = NULL; +} + +/* ARGSUSED */ +static void +CvtStringToWrapMode(args, num_args, fromVal, toVal) +XrmValuePtr args; /* unused */ +Cardinal *num_args; /* unused */ +XrmValuePtr fromVal; +XrmValuePtr toVal; +{ + static XawTextWrapMode wrapMode; + static XrmQuark QWrapNever, QWrapLine, QWrapWord; + XrmQuark q; + char lowerName[BUFSIZ]; + static Boolean inited = FALSE; + + if ( !inited ) { + QWrapNever = XrmPermStringToQuark(XtEtextWrapNever); + QWrapLine = XrmPermStringToQuark(XtEtextWrapLine); + QWrapWord = XrmPermStringToQuark(XtEtextWrapWord); + inited = TRUE; + } + + if (strlen ((char*) fromVal->addr) < sizeof lowerName) { + XmuCopyISOLatin1Lowered (lowerName, (char *)fromVal->addr); + q = XrmStringToQuark(lowerName); + + if (q == QWrapNever) wrapMode = XawtextWrapNever; + else if (q == QWrapLine) wrapMode = XawtextWrapLine; + else if (q == QWrapWord) wrapMode = XawtextWrapWord; + else { + toVal->size = 0; + toVal->addr = NULL; + return; + } + toVal->size = sizeof wrapMode; + toVal->addr = (XPointer) &wrapMode; + return; + } + toVal->size = 0; + toVal->addr = NULL; +} + +/* ARGSUSED */ +static void +CvtStringToResizeMode(args, num_args, fromVal, toVal) +XrmValuePtr args; /* unused */ +Cardinal *num_args; /* unused */ +XrmValuePtr fromVal; +XrmValuePtr toVal; +{ + static XawTextResizeMode resizeMode; + static XrmQuark QResizeNever, QResizeWidth, QResizeHeight, QResizeBoth; + XrmQuark q; + char lowerName[40]; + static Boolean inited = FALSE; + + if ( !inited ) { + QResizeNever = XrmPermStringToQuark(XtEtextResizeNever); + QResizeWidth = XrmPermStringToQuark(XtEtextResizeWidth); + QResizeHeight = XrmPermStringToQuark(XtEtextResizeHeight); + QResizeBoth = XrmPermStringToQuark(XtEtextResizeBoth); + inited = TRUE; + } + + if (strlen ((char*) fromVal->addr) < sizeof lowerName) { + XmuCopyISOLatin1Lowered (lowerName, (char *)fromVal->addr); + q = XrmStringToQuark(lowerName); + + if (q == QResizeNever) resizeMode = XawtextResizeNever; + else if (q == QResizeWidth) resizeMode = XawtextResizeWidth; + else if (q == QResizeHeight) resizeMode = XawtextResizeHeight; + else if (q == QResizeBoth) resizeMode = XawtextResizeBoth; + else { + toVal->size = 0; + toVal->addr = NULL; + return; + } + toVal->size = sizeof resizeMode; + toVal->addr = (XPointer) &resizeMode; + return; + } + toVal->size = 0; + toVal->addr = NULL; +} + +static void +ClassInitialize() +{ + int len1 = strlen (_XawDefaultTextTranslations1); + int len2 = strlen (_XawDefaultTextTranslations2); + int len3 = strlen (_XawDefaultTextTranslations3); + int len4 = strlen (_XawDefaultTextTranslations4); + char *buf = XtMalloc ((unsigned)(len1 + len2 + len3 + len4 + 1)); + char *cp = buf; + + if (!XawFmt8Bit) + FMT8BIT = XawFmt8Bit = XrmPermStringToQuark("FMT8BIT"); +#ifdef XAW_INTERNATIONALIZATION + if (!XawFmtWide) + XawFmtWide = XrmPermStringToQuark("FMTWIDE"); +#endif + + XawInitializeWidgetSet(); + +/* + * Set the number of actions. + */ + + textClassRec.core_class.num_actions = _XawTextActionsTableCount; + + (void) strcpy( cp, _XawDefaultTextTranslations1); cp += len1; + (void) strcpy( cp, _XawDefaultTextTranslations2); cp += len2; + (void) strcpy( cp, _XawDefaultTextTranslations3); cp += len3; + (void) strcpy( cp, _XawDefaultTextTranslations4); + textWidgetClass->core_class.tm_table = buf; + + XtAddConverter(XtRString, XtRScrollMode, CvtStringToScrollMode, + (XtConvertArgList)NULL, (Cardinal)0 ); + XtAddConverter(XtRString, XtRWrapMode, CvtStringToWrapMode, + (XtConvertArgList)NULL, (Cardinal)0 ); + XtAddConverter(XtRString, XtRResizeMode, CvtStringToResizeMode, + (XtConvertArgList)NULL, (Cardinal)0 ); +} + +/* Function Name: PositionHScrollBar. + * Description: Positions the Horizontal scrollbar. + * Arguments: ctx - the text widget. + * Returns: none + */ + +static void +PositionHScrollBar(ctx) +TextWidget ctx; +{ + Widget vbar = ctx->text.vbar, hbar = ctx->text.hbar; + Position top, left = 0; + int s = ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; + + if (ctx->text.hbar == NULL) return; + + if (vbar != NULL) + left += (Position) (vbar->core.width + vbar->core.border_width); + + XtResizeWidget( hbar, ctx->core.width - left - s, hbar->core.height, + hbar->core.border_width ); + + left = s / 2 - (Position) hbar->core.border_width; + if (left < 0) left = 0; + if (vbar != NULL) + left += (Position) (vbar->core.width + vbar->core.border_width); + + top = ctx->core.height - (hbar->core.height + hbar->core.border_width + s / 2); + + XtMoveWidget( hbar, left, top); +} + +/* Function Name: PositionVScrollBar. + * Description: Positions the Vertical scrollbar. + * Arguments: ctx - the text widget. + * Returns: none. + */ + +static void +PositionVScrollBar(ctx) +TextWidget ctx; +{ + Widget vbar = ctx->text.vbar; + Position pos; + Dimension bw; + int s = ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; + + if (vbar == NULL) return; + bw = vbar->core.border_width; + + XtResizeWidget( vbar, vbar->core.width, ctx->core.height - s, bw); + pos = s / 2 - (Position)bw; + if (pos < 0) pos = 0; + + XtMoveWidget( vbar, pos, pos); +} + +static void +CreateVScrollBar(ctx) +TextWidget ctx; +{ + Widget vbar; + + if (ctx->text.vbar != NULL) return; + + ctx->text.vbar = vbar = + XtCreateWidget("vScrollbar", scrollbarWidgetClass, (Widget)ctx, + (ArgList) NULL, ZERO); + XtAddCallback( vbar, XtNscrollProc, VScroll, (XtPointer)ctx ); + XtAddCallback( vbar, XtNjumpProc, VJump, (XtPointer)ctx ); + if (ctx->text.hbar == NULL) + XtAddCallback((Widget) ctx, XtNunrealizeCallback, UnrealizeScrollbars, + (XtPointer) NULL); + + ctx->text.r_margin.left += vbar->core.width + vbar->core.border_width; + ctx->text.margin.left = ctx->text.r_margin.left; + + PositionVScrollBar(ctx); + PositionHScrollBar(ctx); /* May modify location of Horiz. Bar. */ + + if (XtIsRealized((Widget)ctx)) { + XtRealizeWidget(vbar); + XtMapWidget(vbar); + } +} + +/* Function Name: DestroyVScrollBar + * Description: Removes a vertical ScrollBar. + * Arguments: ctx - the parent text widget. + * Returns: none. + */ + +static void +DestroyVScrollBar(ctx) +TextWidget ctx; +{ + Widget vbar = ctx->text.vbar; + + if (vbar == NULL) return; + + ctx->text.r_margin.left -= vbar->core.width + vbar->core.border_width; + ctx->text.margin.left = ctx->text.r_margin.left; + if (ctx->text.hbar == NULL) + XtRemoveCallback((Widget) ctx, XtNunrealizeCallback, UnrealizeScrollbars, + (XtPointer) NULL); + XtDestroyWidget(vbar); + ctx->text.vbar = NULL; + PositionHScrollBar(ctx); +} + +static void +CreateHScrollBar(ctx) +TextWidget ctx; +{ + Arg args[1]; + Widget hbar; + + if (ctx->text.hbar != NULL) return; + + XtSetArg(args[0], XtNorientation, XtorientHorizontal); + ctx->text.hbar = hbar = + XtCreateWidget("hScrollbar", scrollbarWidgetClass, (Widget)ctx, args, ONE); + XtAddCallback( hbar, XtNscrollProc, HScroll, (XtPointer)ctx ); + XtAddCallback( hbar, XtNjumpProc, HJump, (XtPointer)ctx ); + if (ctx->text.vbar == NULL) + XtAddCallback((Widget) ctx, XtNunrealizeCallback, UnrealizeScrollbars, + (XtPointer) NULL); + +/**/ + ctx->text.r_margin.bottom += hbar->core.height + hbar->core.border_width; + ctx->text.margin.bottom = ctx->text.r_margin.bottom; +/**/ + PositionHScrollBar(ctx); + if (XtIsRealized((Widget)ctx)) { + XtRealizeWidget(hbar); + XtMapWidget(hbar); + } +} + +/* Function Name: DestroyHScrollBar + * Description: Removes a horizontal ScrollBar. + * Arguments: ctx - the parent text widget. + * Returns: none. + */ + +static void +DestroyHScrollBar(ctx) +TextWidget ctx; +{ + Widget hbar = ctx->text.hbar; + + if (hbar == NULL) return; + +/**/ + ctx->text.r_margin.bottom -= hbar->core.height + hbar->core.border_width; + ctx->text.margin.bottom = ctx->text.r_margin.bottom; +/**/ + if (ctx->text.vbar == NULL) + XtRemoveCallback((Widget) ctx, XtNunrealizeCallback, UnrealizeScrollbars, + (XtPointer) NULL); + XtDestroyWidget(hbar); + ctx->text.hbar = NULL; +} + +/* ARGSUSED */ +static void +Initialize(request, new, args, num_args) +Widget request, new; +ArgList args; /* unused */ +Cardinal *num_args; /* unused */ +{ + TextWidget ctx = (TextWidget) new; + char error_buf[BUFSIZ]; + int s; + + ctx->text.threeD = XtVaCreateWidget("threeD", threeDWidgetClass, new, + XtNx, 0, XtNy, 0, + XtNwidth, 10, XtNheight, 10, /* dummy */ + NULL); + + s = ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; + + ctx->text.r_margin.left += s; + ctx->text.r_margin.right += s; + ctx->text.r_margin.top += s; + ctx->text.r_margin.bottom += s - 1; + + ctx->text.lt.lines = 0; + ctx->text.lt.info = NULL; + (void) bzero((char *) &(ctx->text.origSel), sizeof(XawTextSelection)); + (void) bzero((char *) &(ctx->text.s), sizeof(XawTextSelection)); + ctx->text.s.type = XawselectPosition; + ctx->text.salt = NULL; + ctx->text.hbar = ctx->text.vbar = (Widget) NULL; + ctx->text.lasttime = 0; /* ||| correct? */ + ctx->text.time = 0; /* ||| correct? */ + ctx->text.showposition = TRUE; + ctx->text.lastPos = (ctx->text.source != NULL) ? GETLASTPOS : 0; + ctx->text.file_insert = NULL; + ctx->text.search = NULL; + ctx->text.updateFrom = (XawTextPosition *) XtMalloc((unsigned) ONE); + ctx->text.updateTo = (XawTextPosition *) XtMalloc((unsigned) ONE); + ctx->text.numranges = ctx->text.maxranges = 0; + ctx->text.gc = DefaultGCOfScreen(XtScreen(ctx)); + ctx->text.hasfocus = FALSE; + ctx->text.margin = ctx->text.r_margin; /* Strucure copy. */ + ctx->text.update_disabled = FALSE; + ctx->text.old_insert = -1; + ctx->text.mult = 1; + ctx->text.single_char = FALSE; + ctx->text.copy_area_offsets = NULL; + ctx->text.salt2 = NULL; + + if (ctx->core.height == DEFAULT_TEXT_HEIGHT) { + ctx->core.height = VMargins(ctx); + if (ctx->text.sink != NULL) + ctx->core.height += XawTextSinkMaxHeight(ctx->text.sink, 1); + } + + if (ctx->text.scroll_vert != XawtextScrollNever) + if ( (ctx->text.resize == XawtextResizeHeight) || + (ctx->text.resize == XawtextResizeBoth) ) { + (void) sprintf(error_buf, "Xaw Text Widget %s:\n %s %s.", ctx->core.name, + "Vertical scrolling not allowed with height resize.\n", + "Vertical scrolling has been DEACTIVATED."); + XtAppWarning(XtWidgetToApplicationContext(new), error_buf); + ctx->text.scroll_vert = XawtextScrollNever; + } + else if (ctx->text.scroll_vert == XawtextScrollAlways) + CreateVScrollBar(ctx); + + if (ctx->text.scroll_horiz != XawtextScrollNever) + if (ctx->text.wrap != XawtextWrapNever) { + (void) sprintf(error_buf, "Xaw Text Widget %s:\n %s %s.", ctx->core.name, + "Horizontal scrolling not allowed with wrapping active.\n", + "Horizontal scrolling has been DEACTIVATED."); + XtAppWarning(XtWidgetToApplicationContext(new), error_buf); + ctx->text.scroll_horiz = XawtextScrollNever; + } + else if ( (ctx->text.resize == XawtextResizeWidth) || + (ctx->text.resize == XawtextResizeBoth) ) { + (void) sprintf(error_buf, "Xaw Text Widget %s:\n %s %s.", ctx->core.name, + "Horizontal scrolling not allowed with width resize.\n", + "Horizontal scrolling has been DEACTIVATED."); + XtAppWarning(XtWidgetToApplicationContext(new), error_buf); + ctx->text.scroll_horiz = XawtextScrollNever; + } + else if (ctx->text.scroll_horiz == XawtextScrollAlways) + CreateHScrollBar(ctx); +} + +static void +Realize( w, valueMask, attributes ) +Widget w; +Mask *valueMask; +XSetWindowAttributes *attributes; +{ + TextWidget ctx = (TextWidget)w; + void _XawTextCheckResize(); + + (*textClassRec.core_class.superclass->core_class.realize) + (w, valueMask, attributes); + + if (ctx->text.hbar != NULL) { /* Put up Hbar -- Must be first. */ + XtRealizeWidget(ctx->text.hbar); + XtMapWidget(ctx->text.hbar); + } + + if (ctx->text.vbar != NULL) { /* Put up Vbar. */ + XtRealizeWidget(ctx->text.vbar); + XtMapWidget(ctx->text.vbar); + } + + _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE); + _XawTextSetScrollBars(ctx); + _XawTextCheckResize(ctx); +} + +/*ARGSUSED*/ +static void UnrealizeScrollbars(widget, client, call) +Widget widget; /* Text widget */ +XtPointer client; /* unused */ +XtPointer call; /* unused */ +{ + TextWidget ctx = (TextWidget) widget; + + if (ctx->text.hbar) + XtUnrealizeWidget(ctx->text.hbar); + if (ctx->text.vbar) + XtUnrealizeWidget(ctx->text.vbar); +} + +/* Utility routines for support of Text */ + +static void +_CreateCutBuffers(d) +Display *d; +{ + static struct _DisplayRec { + struct _DisplayRec *next; + Display *dpy; + } *dpy_list = NULL; + struct _DisplayRec *dpy_ptr; + + for (dpy_ptr = dpy_list; dpy_ptr != NULL; dpy_ptr = dpy_ptr->next) + if (dpy_ptr->dpy == d) return; + + dpy_ptr = XtNew(struct _DisplayRec); + dpy_ptr->next = dpy_list; + dpy_ptr->dpy = d; + dpy_list = dpy_ptr; + +#define Create(buffer) \ + XChangeProperty(d, RootWindow(d, 0), buffer, XA_STRING, 8, \ + PropModeAppend, NULL, 0 ); + + Create( XA_CUT_BUFFER0 ); + Create( XA_CUT_BUFFER1 ); + Create( XA_CUT_BUFFER2 ); + Create( XA_CUT_BUFFER3 ); + Create( XA_CUT_BUFFER4 ); + Create( XA_CUT_BUFFER5 ); + Create( XA_CUT_BUFFER6 ); + Create( XA_CUT_BUFFER7 ); + +#undef Create +} + +/* + * Procedure to manage insert cursor visibility for editable text. It uses + * the value of ctx->insertPos and an implicit argument. In the event that + * position is immediately preceded by an eol graphic, then the insert cursor + * is displayed at the beginning of the next line. +*/ +static void +InsertCursor (w, state) +Widget w; +XawTextInsertState state; +{ + TextWidget ctx = (TextWidget)w; + Position x, y; + int line; + + if (ctx->text.lt.lines < 1) return; + + if ( LineAndXYForPosition(ctx, ctx->text.insertPos, &line, &x, &y) ) { + if (line < ctx->text.lt.lines) + y += (ctx->text.lt.info[line + 1].y - ctx->text.lt.info[line].y) + 1; + else + y += (ctx->text.lt.info[line].y - ctx->text.lt.info[line - 1].y) + 1; + + if (ctx->text.display_caret) + XawTextSinkInsertCursor(ctx->text.sink, x, y, state); + } + ctx->text.ev_x = x; + ctx->text.ev_y = y; + + /* Keep Input Method up to speed */ + +#ifdef XAW_INTERNATIONALIZATION + if ( ctx->simple.international ) { + Arg list[1]; + + XtSetArg (list[0], XtNinsertPosition, ctx->text.insertPos); + _XawImSetValues (w, list, 1); + } +#endif +} + +/* + * Procedure to register a span of text that is no longer valid on the display + * It is used to avoid a number of small, and potentially overlapping, screen + * updates. +*/ + +void +_XawTextNeedsUpdating(ctx, left, right) +TextWidget ctx; +XawTextPosition left, right; +{ + int i; + if (left < right) { + for (i = 0; i < ctx->text.numranges; i++) { + if (left <= ctx->text.updateTo[i] && right >= ctx->text.updateFrom[i]) { + ctx->text.updateFrom[i] = Min(left, ctx->text.updateFrom[i]); + ctx->text.updateTo[i] = Max(right, ctx->text.updateTo[i]); + return; + } + } + ctx->text.numranges++; + if (ctx->text.numranges > ctx->text.maxranges) { + ctx->text.maxranges = ctx->text.numranges; + i = ctx->text.maxranges * sizeof(XawTextPosition); + ctx->text.updateFrom = (XawTextPosition *) + XtRealloc((char *)ctx->text.updateFrom, (unsigned) i); + ctx->text.updateTo = (XawTextPosition *) + XtRealloc((char *)ctx->text.updateTo, (unsigned) i); + } + ctx->text.updateFrom[ctx->text.numranges - 1] = left; + ctx->text.updateTo[ctx->text.numranges - 1] = right; + } +} + +/* + * Procedure to read a span of text in Ascii form. This is purely a hack and + * we probably need to add a function to sources to provide this functionality. + * [note: this is really a private procedure but is used in multiple modules]. + */ + +char * +_XawTextGetText(ctx, left, right) +TextWidget ctx; +XawTextPosition left, right; +{ + char *result, *tempResult; + XawTextBlock text; + int bytes; + + if (_XawTextFormat(ctx) == XawFmt8Bit) + bytes = sizeof(unsigned char); +#ifdef XAW_INTERNATIONALIZATION + else if (_XawTextFormat(ctx) == XawFmtWide) + bytes = sizeof(wchar_t); +#endif + else /* if there is another fomat, add here */ + bytes = 1; + + /* leave space for ZERO */ + tempResult=result=XtMalloc( (unsigned)(((Cardinal)(right-left))+ONE )* bytes); + while (left < right) { + left = SrcRead(ctx->text.source, left, &text, (int)(right - left)); + if (!text.length) + break; + memmove(tempResult, text.ptr, text.length * bytes); + tempResult += text.length * bytes; + } + + if (bytes == sizeof(wchar_t)) + *((wchar_t*)tempResult) = (wchar_t)0; + else + *tempResult = '\0'; + return(result); +} + +/* Like _XawTextGetText, but enforces ICCCM STRING type encoding. This +routine is currently used to put just the ASCII chars in the selection into a +cut buffer. */ + +char * +_XawTextGetSTRING(ctx, left, right) +TextWidget ctx; +XawTextPosition left, right; +{ + unsigned char *s; + unsigned char c; + long i, j, n; + wchar_t *ws, wc; + + /* allow ESC in accordance with ICCCM */ +#ifdef XAW_INTERNATIONALIZATION + if (_XawTextFormat(ctx) == XawFmtWide) { + MultiSinkObject sink = (MultiSinkObject) ctx->text.sink; + ws = (wchar_t *)_XawTextGetText(ctx, left, right); + n = wcslen(ws); + for (j = 0, i = 0; j < n; j++) { + wc = ws[j]; + if (XwcTextEscapement (sink->multi_sink.fontset, &wc, 1) || + (wc == _Xaw_atowc(XawTAB)) || (wc == _Xaw_atowc(XawLF)) || (wc == _Xaw_atowc(XawESC))) + ws[i++] = wc; + } + ws[i] = (wchar_t)0; + return (char *)ws; + } else +#endif + { + s = (unsigned char *)_XawTextGetText(ctx, left, right); + /* only HT and NL control chars are allowed, strip out others */ + n = strlen((char *)s); + i = 0; + for (j = 0; j < n; j++) { + c = s[j]; + if (((c >= 0x20) && c <= 0x7f) || + (c >= 0xa0) || (c == XawTAB) || (c == XawLF) || (c == XawESC)) { + s[i] = c; + i++; + } + } + s[i] = 0; + return (char *)s; + } +#undef ESC + +} + +/* + * This routine maps an x and y position in a window that is displaying text + * into the corresponding position in the source. + * + * NOTE: it is illegal to call this routine unless there is a valid line table! + */ + +/*** figure out what line it is on ***/ + +static XawTextPosition +PositionForXY (ctx, x, y) +TextWidget ctx; +Position x,y; +{ + int fromx, line, width, height; + XawTextPosition position; + + if (ctx->text.lt.lines == 0) return 0; + + for (line = 0; line < ctx->text.lt.lines - 1; line++) { + if (y <= ctx->text.lt.info[line + 1].y) + break; + } + position = ctx->text.lt.info[line].position; + if (position >= ctx->text.lastPos) + return(ctx->text.lastPos); + fromx = (int) ctx->text.margin.left; + XawTextSinkFindPosition( ctx->text.sink, position, fromx, x - fromx, + FALSE, &position, &width, &height); + if (position > ctx->text.lastPos) return(ctx->text.lastPos); + if (position >= ctx->text.lt.info[line + 1].position) + position = SrcScan(ctx->text.source, ctx->text.lt.info[line + 1].position, + XawstPositions, XawsdLeft, 1, TRUE); + return(position); +} + +/* + * This routine maps a source position in to the corresponding line number + * of the text that is displayed in the window. + * + * NOTE: It is illegal to call this routine unless there is a valid line table! + */ + +static int +LineForPosition (ctx, position) +TextWidget ctx; +XawTextPosition position; +{ + int line; + + for (line = 0; line < ctx->text.lt.lines; line++) + if (position < ctx->text.lt.info[line + 1].position) + break; + return(line); +} + +/* + * This routine maps a source position into the corresponding line number + * and the x, y coordinates of the text that is displayed in the window. + * + * NOTE: It is illegal to call this routine unless there is a valid line table! + */ + +static Boolean +LineAndXYForPosition (ctx, pos, line, x, y) +TextWidget ctx; +XawTextPosition pos; +int *line; +Position *x, *y; +{ + XawTextPosition linePos, endPos; + Boolean visible; + int realW, realH; + + *line = 0; + *x = ctx->text.margin.left; + *y = ctx->text.margin.top; + if ((visible = IsPositionVisible(ctx, pos))) { + *line = LineForPosition(ctx, pos); + *y = ctx->text.lt.info[*line].y; + *x = ctx->text.margin.left; + linePos = ctx->text.lt.info[*line].position; + XawTextSinkFindDistance( ctx->text.sink, linePos, + *x, pos, &realW, &endPos, &realH); + *x += realW; + } + return(visible); +} + +/* + * This routine builds a line table. It does this by starting at the + * specified position and measuring text to determine the staring position + * of each line to be displayed. It also determines and saves in the + * linetable all the required metrics for displaying a given line (e.g. + * x offset, y offset, line length, etc.). + */ + +void +#if NeedFunctionPrototypes +_XawTextBuildLineTable ( + TextWidget ctx, + XawTextPosition position, + _XtBoolean force_rebuild) +#else +_XawTextBuildLineTable (ctx, position, force_rebuild) + TextWidget ctx; + XawTextPosition position; + Boolean force_rebuild; +#endif +{ + Dimension height = 0; + int lines = 0; + Cardinal size; + + if ((int)ctx->core.height > VMargins(ctx)) { + height = ctx->core.height - VMargins(ctx); + lines = XawTextSinkMaxLines(ctx->text.sink, height); + } + size = sizeof(XawTextLineTableEntry) * (lines + 1); + + if ( (lines != ctx->text.lt.lines) || (ctx->text.lt.info == NULL) ) { + ctx->text.lt.info = (XawTextLineTableEntry *) XtRealloc((char *) ctx->text. + lt.info, size); + ctx->text.lt.lines = lines; + force_rebuild = TRUE; + } + + if ( force_rebuild || (position != ctx->text.lt.top) ) { + (void) bzero((char *) ctx->text.lt.info, size); + (void) _BuildLineTable(ctx, ctx->text.lt.top = position, zeroPosition, 0); + } +} + +/* + * This assumes that the line table does not change size. + */ + +static XawTextPosition +_BuildLineTable(ctx, position, min_pos, line) +TextWidget ctx; +XawTextPosition position, min_pos; +int line; +{ + XawTextLineTableEntry * lt = ctx->text.lt.info + line; + XawTextPosition endPos; + Position y; + int count, width, realW, realH; + Widget src = ctx->text.source; + + if ( ((ctx->text.resize == XawtextResizeWidth) || + (ctx->text.resize == XawtextResizeBoth) ) || + (ctx->text.wrap == XawtextWrapNever) ) + width = BIGNUM; + else + width = Max(0, ((int)ctx->core.width - (int)HMargins(ctx))); + + y = ( (line == 0) ? ctx->text.margin.top : lt->y ); + + /* CONSTCOND */ + while ( TRUE ) { + lt->y = y; + lt->position = position; + + XawTextSinkFindPosition( ctx->text.sink, position, ctx->text.margin.left, + width, ctx->text.wrap == XawtextWrapWord, + &endPos, &realW, &realH); + lt->textWidth = realW; + y += realH; + + if (ctx->text.wrap == XawtextWrapNever) + endPos = SrcScan(src, position, XawstEOL, XawsdRight, 1, TRUE); + + if ( endPos == ctx->text.lastPos) { /* We have reached the end. */ + if(SrcScan(src, position, XawstEOL, XawsdRight, 1, FALSE) == endPos) + break; + } + + ++lt; + ++line; + if ( (line > ctx->text.lt.lines) || + ((lt->position == (position = endPos)) && (position > min_pos)) ) + return(position); + } + +/* + * If we are at the end of the buffer put two special lines in the table. + * + * a) Both have position > text.lastPos and lt->textWidth = 0. + * b) The first has a real height, and the second has a height that + * is the rest of the screen. + * + * I could fill in the rest of the table with valid heights and a large + * lastPos, but this method keeps the number of fill regions down to a + * minimum. + * + * One valid entry is needed at the end of the table so that the cursor + * does not jump off the bottom of the window. + */ + + for ( count = 0; count < 2 ; count++) + if (line++ < ctx->text.lt.lines) { /* make sure not to run of the end. */ + (++lt)->y = (count == 0) ? y : ctx->core.height + - 2 * ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; + lt->textWidth = 0; + lt->position = ctx->text.lastPos + 100; + } + + if (line < ctx->text.lt.lines) /* Clear out rest of table. */ + (void) bzero( (char *) (lt + 1), + (ctx->text.lt.lines - line) * sizeof(XawTextLineTableEntry) ); + + ctx->text.lt.info[ctx->text.lt.lines].position = lt->position; + + return(endPos); +} + +/* Function Name: GetWidestLine + * Description: Returns the width (in pixels) of the widest line that + * is currently visable. + * Arguments: ctx - the text widget. + * Returns: the width of the widest line. + * + * NOTE: This function requires a valid line table. + */ + +static Dimension +GetWidestLine(ctx) +TextWidget ctx; +{ + int i; + Dimension widest; + XawTextLineTablePtr lt = &(ctx->text.lt); + + for (i = 0, widest = 1 ; i < lt->lines ; i++) + if (widest < lt->info[i].textWidth) + widest = lt->info[i].textWidth; + + return(widest); +} + +static void +CheckVBarScrolling(ctx) +TextWidget ctx; +{ + float first, last; + Boolean temp = (ctx->text.vbar == NULL); + + if (ctx->text.scroll_vert == XawtextScrollNever) return; + + if ( (ctx->text.lastPos > 0) && (ctx->text.lt.lines > 0)) { + first = ctx->text.lt.top; + first /= (float) ctx->text.lastPos; + last = ctx->text.lt.info[ctx->text.lt.lines].position; + if ( ctx->text.lt.info[ctx->text.lt.lines].position < ctx->text.lastPos ) + last /= (float) ctx->text.lastPos; + else + last = 1.0; + + if (ctx->text.scroll_vert == XawtextScrollWhenNeeded) { + int line; + XawTextPosition last_pos; + Position y = ctx->core.height - ctx->text.margin.bottom; + + if (ctx->text.hbar != NULL) + y -= (ctx->text.hbar->core.height + + 2 * ctx->text.hbar->core.border_width); + + last_pos = PositionForXY(ctx, (Position) ctx->core.width, y); + line = LineForPosition(ctx, last_pos); + + if ( (y < ctx->text.lt.info[line + 1].y) || ((last - first) < 1.0) ) + CreateVScrollBar(ctx); + else + DestroyVScrollBar(ctx); + } + + if (ctx->text.vbar != NULL) + XawScrollbarSetThumb(ctx->text.vbar, first, last - first); + + if ( (ctx->text.vbar == NULL) != temp) { + _XawTextNeedsUpdating(ctx, zeroPosition, ctx->text.lastPos); + if (ctx->text.vbar == NULL) + _XawTextBuildLineTable (ctx, zeroPosition, FALSE); + } + } + else if (ctx->text.vbar != NULL) + if (ctx->text.scroll_vert == XawtextScrollWhenNeeded) + DestroyVScrollBar(ctx); + else if (ctx->text.scroll_vert == XawtextScrollAlways) + XawScrollbarSetThumb(ctx->text.vbar, 0.0, 1.0); +} + +/* + * This routine is used by Text to notify an associated scrollbar of the + * correct metrics (position and shown fraction) for the text being currently + * displayed in the window. + */ + +void +_XawTextSetScrollBars(ctx) +TextWidget ctx; +{ + float first, last, widest; + Boolean temp = (ctx->text.hbar == NULL); + Boolean vtemp = (ctx->text.vbar == NULL); + int s = ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; + + CheckVBarScrolling(ctx); + + if (ctx->text.scroll_horiz == XawtextScrollNever) return; + + if (ctx->text.vbar != NULL) + widest = (int)(ctx->core.width - ctx->text.vbar->core.width - + 2 * s - ctx->text.vbar->core.border_width); + else + widest = ctx->core.width - 2 * s; + widest /= (last = GetWidestLine(ctx)); + if (ctx->text.scroll_horiz == XawtextScrollWhenNeeded) + if (widest < 1.0) + CreateHScrollBar(ctx); + else + DestroyHScrollBar(ctx); + + if ( (ctx->text.hbar == NULL) != temp ) { + _XawTextBuildLineTable (ctx, ctx->text.lt.top, TRUE); + CheckVBarScrolling(ctx); /* Recheck need for vbar, now that we added + or removed the hbar.*/ + } + + if (ctx->text.hbar != NULL) { + first = ctx->text.r_margin.left - ctx->text.margin.left; + first /= last; + XawScrollbarSetThumb(ctx->text.hbar, first, widest); + } + + if (((ctx->text.hbar == NULL) && (ctx->text.margin.left != + ctx->text.r_margin.left)) || + (ctx->text.vbar == NULL) != vtemp) + { + ctx->text.margin.left = ctx->text.r_margin.left; + _XawTextNeedsUpdating(ctx, zeroPosition, ctx->text.lastPos); + FlushUpdate(ctx); + } +} + +/* + * The routine will scroll the displayed text by lines. If the arg is + * positive, move up; otherwise, move down. [note: this is really a private + * procedure but is used in multiple modules]. + */ + +void +_XawTextVScroll(ctx, n) +TextWidget ctx; +int n; +{ + XawTextPosition top, target; + int y; + Arg list[1]; + XawTextLineTable * lt = &(ctx->text.lt); + int s = ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; + + if (abs(n) > ctx->text.lt.lines) + n = (n > 0) ? ctx->text.lt.lines : -ctx->text.lt.lines; + + if (n == 0) return; + + if (n > 0) { + if ( IsValidLine(ctx, n) ) + top = Min(lt->info[n].position, ctx->text.lastPos); + else + top = ctx->text.lastPos; + + y = IsValidLine(ctx, n) ? lt->info[n].y : ctx->core.height - 2 * s; + _XawTextBuildLineTable(ctx, top, FALSE); + if (top >= ctx->text.lastPos) + DisplayTextWindow( (Widget) ctx); + else { + XCopyArea(XtDisplay(ctx), XtWindow(ctx), XtWindow(ctx), ctx->text.gc, + s, y, (int)ctx->core.width - 2 * s, (int)ctx->core.height - y - s, + s, ctx->text.margin.top); + + PushCopyQueue(ctx, 0, (int) -y); + SinkClearToBG(ctx->text.sink, + (Position) s, + (Position) (ctx->text.margin.top + ctx->core.height - y - s), + (Dimension) ctx->core.width - 2 * s, + (Dimension) ctx->core.height - 2 * s); + + if (n < lt->lines) n++; /* update descenders at bottom */ + _XawTextNeedsUpdating(ctx, lt->info[lt->lines - n].position, + ctx->text.lastPos); + _XawTextSetScrollBars(ctx); + } + } + else { + XawTextPosition updateTo; + unsigned int height, clear_height; + + n = -n; + target = lt->top; + top = SrcScan(ctx->text.source, target, XawstEOL, + XawsdLeft, n+1, FALSE); + + _XawTextBuildLineTable(ctx, top, FALSE); + y = IsValidLine(ctx, n) ? lt->info[n].y : ctx->core.height - 2 * s; + updateTo = IsValidLine(ctx, n) ? lt->info[n].position : ctx->text.lastPos; + if (IsValidLine(ctx, lt->lines - n)) + height = lt->info[lt->lines-n].y - ctx->text.margin.top; + else if (ctx->core.height - HMargins(ctx)) + height = ctx->core.height - HMargins(ctx); + else + height = 0; + if (y > (int) ctx->text.margin.top) + clear_height = y - ctx->text.margin.top; + else + clear_height = 0; + + if ( updateTo == target ) { + XCopyArea(XtDisplay(ctx), XtWindow(ctx), XtWindow(ctx), ctx->text.gc, + s, ctx->text.margin.top, (int) ctx->core.width - 2 * s, + height, s, y); + PushCopyQueue(ctx, 0, (int) y); + SinkClearToBG(ctx->text.sink, (Position) s, ctx->text.margin.top, + (Dimension) ctx->core.width - 2 * s, (Dimension) clear_height); + + _XawTextNeedsUpdating(ctx, lt->info[0].position, updateTo); + _XawTextSetScrollBars(ctx); + } + else if (lt->top != target) + DisplayTextWindow((Widget)ctx); + } + XtSetArg (list[0], XtNinsertPosition, ctx->text.lt.top+ctx->text.lt.lines); +#ifdef XAW_INTERNATIONALIZATION + _XawImSetValues ((Widget) ctx, list, 1); +#endif + + _ShadowSurroundedBox((Widget)ctx, (ThreeDWidget)ctx->text.threeD, + 0, 0, ctx->core.width, ctx->core.height, + ((ThreeDWidget)ctx->text.threeD)->threeD.relief, False); +} + +/*ARGSUSED*/ +static void +HScroll(w, closure, callData) +Widget w; +XtPointer closure; /* TextWidget */ +XtPointer callData; /* #pixels */ +{ + TextWidget ctx = (TextWidget) closure; + Widget tw = (Widget) ctx; + Position old_left, pixels = (Position)(int) callData; + XRectangle rect, t_rect; + int s = ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; + + _XawTextPrepareToUpdate(ctx); + + old_left = ctx->text.margin.left; + ctx->text.margin.left -= pixels; + if (ctx->text.margin.left > ctx->text.r_margin.left) { + ctx->text.margin.left = ctx->text.r_margin.left; + pixels = old_left - ctx->text.margin.left; + } + + if (pixels > 0) { + rect.width = (unsigned short) pixels + ctx->text.margin.right; + rect.x = (short) ctx->core.width - (short) rect.width; + rect.y = (short) ctx->text.margin.top; + rect.height = (unsigned short) ctx->core.height - rect.y - 2 * s; + + XCopyArea(XtDisplay(tw), XtWindow(tw), XtWindow(tw), ctx->text.gc, + pixels + s, (int) rect.y, + (unsigned int) rect.x, (unsigned int) ctx->core.height - 2 * s, + s, (int) rect.y); + + PushCopyQueue(ctx, (int) -pixels, 0); + } + else if (pixels < 0) { + rect.x = s; + + if (ctx->text.vbar != NULL) + rect.x += (short) (ctx->text.vbar->core.width + + ctx->text.vbar->core.border_width); + + rect.width = (Position) - pixels; + rect.y = ctx->text.margin.top; + rect.height = ctx->core.height - rect.y - 2 * s; + + XCopyArea(XtDisplay(tw), XtWindow(tw), XtWindow(tw), ctx->text.gc, + (int) rect.x, (int) rect.y, + (unsigned int) ctx->core.width - rect.width - 2 * s, + (unsigned int) rect.height, + (int) rect.x + rect.width, (int) rect.y); + + PushCopyQueue(ctx, (int) rect.width, 0); + +/* + * Redraw the line overflow marks. + */ + + t_rect.x = ctx->core.width - ctx->text.margin.right - s; + t_rect.width = ctx->text.margin.right; + t_rect.y = rect.y; + t_rect.height = rect.height - 2 * s; + + SinkClearToBG(ctx->text.sink, (Position) t_rect.x, (Position) t_rect.y, + (Dimension) t_rect.width, (Dimension) t_rect.height); + + UpdateTextInRectangle(ctx, &t_rect); + } + +/* + * Put in the text that just became visible. + */ + + if ( pixels != 0 ) { + SinkClearToBG(ctx->text.sink, (Position) rect.x, (Position) rect.y, + (Dimension) rect.width, (Dimension) rect.height); + + UpdateTextInRectangle(ctx, &rect); + } + _XawTextExecuteUpdate(ctx); + _XawTextSetScrollBars(ctx); +} + +/*ARGSUSED*/ +static void +HJump(w, closure, callData) +Widget w; +XtPointer closure, callData; /* closure = TextWidget, callData = percent. */ +{ + TextWidget ctx = (TextWidget) closure; + float * percent = (float *) callData; + Position new_left, old_left = ctx->text.margin.left; + + long move; /*difference of Positions can be bigger than Position; lint err */ + + new_left = ctx->text.r_margin.left; + new_left -= (Position) (*percent * GetWidestLine(ctx)); + move = old_left - new_left; + + if (abs(move) < (int)ctx->core.width) { + HScroll(w, (XtPointer) ctx, (XtPointer) move); + return; + } + _XawTextPrepareToUpdate(ctx); + ctx->text.margin.left = new_left; + if (XtIsRealized((Widget) ctx)) DisplayTextWindow((Widget) ctx); + _XawTextExecuteUpdate(ctx); +} + +/* Function Name: UpdateTextInLine + * Description: Updates some text in a given line. + * Arguments: ctx - the text widget. + * line - the line number (in the line table) of this line. + * left, right - left and right pixel offsets of the + * area to update. + * Returns: none. + */ + +static void +UpdateTextInLine(ctx, line, left, right) +TextWidget ctx; +int line; +Position left, right; +{ + XawTextPosition pos1, pos2; + int width, height, local_left, local_width; + XawTextLineTableEntry * lt = ctx->text.lt.info + line; + + if ( ((int)(lt->textWidth + ctx->text.margin.left) < left) || + ( ctx->text.margin.left > right ) ) + return; /* no need to update. */ + + local_width = left - ctx->text.margin.left; + XawTextSinkFindPosition(ctx->text.sink, lt->position, + (int) ctx->text.margin.left, + local_width, FALSE, &pos1, &width, &height); + + if (right >= (Position) lt->textWidth - ctx->text.margin.left) + if ( (IsValidLine(ctx, line + 1)) && + (ctx->text.lt.info[line + 1].position <= ctx->text.lastPos) ) + pos2 = SrcScan( ctx->text.source, (lt + 1)->position, XawstPositions, + XawsdLeft, 1, TRUE); + else + pos2 = GETLASTPOS; + else { + XawTextPosition t_pos; + + local_left = ctx->text.margin.left + width; + local_width = right - local_left; + XawTextSinkFindPosition(ctx->text.sink, pos1, local_left, + local_width, FALSE, &pos2, &width, &height); + + t_pos = SrcScan( ctx->text.source, pos2, + XawstPositions, XawsdRight, 1, TRUE); + if (t_pos < (lt + 1)->position) + pos2 = t_pos; + } + + _XawTextNeedsUpdating(ctx, pos1, pos2); +} + +/* + * The routine will scroll the displayed text by pixels. If the calldata is + * positive, move up; otherwise, move down. + */ + +/*ARGSUSED*/ +static void +VScroll(w, closure, callData) +Widget w; +XtPointer closure; /* TextWidget */ +XtPointer callData; /* #pixels */ +{ + TextWidget ctx = (TextWidget)closure; + int height, nlines, lines = (int) callData; + + height = ctx->core.height - VMargins(ctx); + if (height < 1) + height = 1; + nlines = (int) (lines * (int) ctx->text.lt.lines) / height; +#ifdef XAW_ARROW_SCROLLBARS + if (nlines == 0 && lines != 0) + nlines = lines > 0 ? 1 : -1; +#endif + _XawTextPrepareToUpdate(ctx); + _XawTextVScroll(ctx, nlines); + _XawTextExecuteUpdate(ctx); +} + +/* + * The routine "thumbs" the displayed text. Thumbing means reposition the + * displayed view of the source to a new position determined by a fraction + * of the way from beginning to end. Ideally, this should be determined by + * the number of displayable lines in the source. This routine does it as a + * fraction of the first position and last position and then normalizes to + * the start of the line containing the position. + * + * BUG/deficiency: The normalize to line portion of this routine will + * cause thumbing to always position to the start of the source. + */ + +/*ARGSUSED*/ +static void +VJump(w, closure, callData) +Widget w; +XtPointer closure, callData; /* closuer = TextWidget, callData = percent. */ +{ + float * percent = (float *) callData; + TextWidget ctx = (TextWidget)closure; + XawTextPosition position, old_top, old_bot; + XawTextLineTable * lt = &(ctx->text.lt); + + _XawTextPrepareToUpdate(ctx); + old_top = lt->top; + if ( (lt->lines > 0) && (IsValidLine(ctx, lt->lines - 1)) ) + old_bot = lt->info[lt->lines - 1].position; + else + old_bot = ctx->text.lastPos; + + position = (long) (*percent * (float) ctx->text.lastPos); + position= SrcScan(ctx->text.source, position, XawstEOL, XawsdLeft, 1, FALSE); + if ( (position >= old_top) && (position <= old_bot) ) { + int line = 0; + for (;(line < lt->lines) && (position > lt->info[line].position) ; line++); + _XawTextVScroll(ctx, line); + } + else { + XawTextPosition new_bot; + _XawTextBuildLineTable(ctx, position, FALSE); + new_bot = IsValidLine(ctx, lt->lines-1) ? lt->info[lt->lines-1].position + : ctx->text.lastPos; + + if ((old_top >= lt->top) && (old_top <= new_bot)) { + int line = 0; + for (;(line < lt->lines) && (old_top > lt->info[line].position); line++); + _XawTextBuildLineTable(ctx, old_top, FALSE); + _XawTextVScroll(ctx, -line); + } + else + DisplayTextWindow( (Widget) ctx); + } + _XawTextExecuteUpdate(ctx); +} + +static Boolean +MatchSelection(selection, s) +Atom selection; +XawTextSelection *s; +{ + Atom *match; + int count; + + for (count = 0, match = s->selections; count < s->atom_count; match++, count++) + if (*match == selection) + return True; + return False; +} + +static Boolean +ConvertSelection(w, selection, target, type, value, length, format) +Widget w; +Atom *selection, *target, *type; +XtPointer *value; +unsigned long *length; +int *format; +{ + Display* d = XtDisplay(w); + TextWidget ctx = (TextWidget)w; + Widget src = ctx->text.source; + XawTextEditType edit_mode; + Arg args[1]; + + XawTextSelectionSalt *salt = NULL; + XawTextSelection *s; + + if (*target == XA_TARGETS(d)) { + Atom* targetP, * std_targets; + unsigned long std_length; + + if ( SrcCvtSel(src, selection, target, type, value, length, format) ) + return True; + + XmuConvertStandardSelection(w, ctx->text.time, selection, + target, type, (XPointer*)&std_targets, + &std_length, format); + + *value = XtMalloc((unsigned) sizeof(Atom)*(std_length + 7)); + targetP = *(Atom**)value; + *length = std_length + 6; + *targetP++ = XA_STRING; + *targetP++ = XA_TEXT(d); + *targetP++ = XA_COMPOUND_TEXT(d); + *targetP++ = XA_LENGTH(d); + *targetP++ = XA_LIST_LENGTH(d); + *targetP++ = XA_CHARACTER_POSITION(d); + + XtSetArg(args[0], XtNeditType,&edit_mode); + XtGetValues(src, args, ONE); + + if (edit_mode == XawtextEdit) { + *targetP++ = XA_DELETE(d); + (*length)++; + } + (void) memmove((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length); + XtFree((char*)std_targets); + *type = XA_ATOM; + *format = 32; + return True; + } + + if ( SrcCvtSel(src, selection, target, type, value, length, format) ) + return True; + + if (MatchSelection (*selection, &ctx->text.s)) + s = &ctx->text.s; + else + { + for (salt = ctx->text.salt; salt; salt = salt->next) + if (MatchSelection (*selection, &salt->s)) + break; + if (!salt) + return False; + s = &salt->s; + } + if (*target == XA_STRING || + *target == XA_TEXT(d) || + *target == XA_COMPOUND_TEXT(d)) { + if (*target == XA_TEXT(d)) { +#ifdef XAW_INTERNATIONALIZATION + if (_XawTextFormat(ctx) == XawFmtWide) + *type = XA_COMPOUND_TEXT(d); + else +#endif + *type = XA_STRING; + } else { + *type = *target; + } + /* + * If salt is True, the salt->contents stores CT string, + * its length is measured in bytes. + * Refer to _XawTextSaltAwaySelection(). + * + * by Li Yuhong, Mar. 20, 1991. + */ + if (!salt) { + *value = _XawTextGetSTRING(ctx, s->left, s->right); +#ifdef XAW_INTERNATIONALIZATION + if (_XawTextFormat(ctx) == XawFmtWide) { + XTextProperty textprop; + if (XwcTextListToTextProperty(d, (wchar_t **)value, 1, + XCompoundTextStyle, &textprop) + < Success) { + XtFree(*value); + return False; + } + XtFree(*value); + *value = (XtPointer)textprop.value; + *length = textprop.nitems; + } else +#endif + { + *length = strlen(*value); + } + } else { + *value = XtMalloc((salt->length + 1) * sizeof(unsigned char)); + strcpy (*value, salt->contents); + *length = salt->length; + } +#ifdef XAW_INTERNATIONALIZATION + if (_XawTextFormat(ctx) == XawFmtWide && *type == XA_STRING) { + XTextProperty textprop; + wchar_t **wlist; + int count; + textprop.encoding = XA_COMPOUND_TEXT(d); + textprop.value = (unsigned char *)*value; + textprop.nitems = strlen(*value); + textprop.format = 8; + if (XwcTextPropertyToTextList(d, &textprop, (wchar_t ***)&wlist, &count) + < Success) { + XtFree(*value); + return False; + } + XtFree(*value); + if (XwcTextListToTextProperty( d, (wchar_t **)wlist, 1, + XStringStyle, &textprop) < Success) { + XwcFreeStringList( (wchar_t**) wlist ); + return False; + } + *value = (XtPointer) textprop.value; + *length = textprop.nitems; + XwcFreeStringList( (wchar_t**) wlist ); + } +#endif + *format = 8; + return True; + } + + if ( (*target == XA_LIST_LENGTH(d)) || (*target == XA_LENGTH(d)) ) { + long * temp; + + temp = (long *) XtMalloc( (unsigned) sizeof(long) ); + if (*target == XA_LIST_LENGTH(d)) + *temp = 1L; + else /* *target == XA_LENGTH(d) */ + *temp = (long) (s->right - s->left); + + *value = (XPointer) temp; + *type = XA_INTEGER; + *length = 1L; + *format = 32; + return True; + } + + if (*target == XA_CHARACTER_POSITION(d)) { + long * temp; + + temp = (long *) XtMalloc( (unsigned)( 2 * sizeof(long) ) ); + temp[0] = (long) (s->left + 1); + temp[1] = s->right; + *value = (XPointer) temp; + *type = XA_SPAN(d); + *length = 2L; + *format = 32; + return True; + } + + if (*target == XA_DELETE(d)) { + void _XawTextZapSelection(); /* From TextAction.c */ + + if (!salt) + _XawTextZapSelection( ctx, (XEvent *) NULL, TRUE); + *value = NULL; + *type = XA_NULL(d); + *length = 0; + *format = 32; + return True; + } + + if (XmuConvertStandardSelection(w, ctx->text.time, selection, target, type, + (XPointer *)value, length, format)) + return True; + + /* else */ + return False; +} + +/* Function Name: GetCutBuffferNumber + * Description: Returns the number of the cut buffer. + * Arguments: atom - the atom to check. + * Returns: the number of the cut buffer representing this atom or + * NOT_A_CUT_BUFFER. + */ + +#define NOT_A_CUT_BUFFER -1 + +static int +GetCutBufferNumber(atom) +Atom atom; +{ + if (atom == XA_CUT_BUFFER0) return(0); + if (atom == XA_CUT_BUFFER1) return(1); + if (atom == XA_CUT_BUFFER2) return(2); + if (atom == XA_CUT_BUFFER3) return(3); + if (atom == XA_CUT_BUFFER4) return(4); + if (atom == XA_CUT_BUFFER5) return(5); + if (atom == XA_CUT_BUFFER6) return(6); + if (atom == XA_CUT_BUFFER7) return(7); + return(NOT_A_CUT_BUFFER); +} + +static void +LoseSelection(w, selection) +Widget w; +Atom *selection; +{ + TextWidget ctx = (TextWidget) w; + Atom* atomP; + int i; + XawTextSelectionSalt *salt, *prevSalt, *nextSalt; + + _XawTextPrepareToUpdate(ctx); + + atomP = ctx->text.s.selections; + for (i = 0 ; i < ctx->text.s.atom_count; i++, atomP++) + if ( (*selection == *atomP) || + (GetCutBufferNumber(*atomP) != NOT_A_CUT_BUFFER) )/* is a cut buffer */ + *atomP = (Atom)0; + + while (ctx->text.s.atom_count && + ctx->text.s.selections[ctx->text.s.atom_count-1] == 0) + ctx->text.s.atom_count--; + +/* + * Must walk the selection list in opposite order from UnsetSelection. + */ + + atomP = ctx->text.s.selections; + for (i = 0 ; i < ctx->text.s.atom_count; i++, atomP++) + if (*atomP == (Atom)0) { + *atomP = ctx->text.s.selections[--ctx->text.s.atom_count]; + while (ctx->text.s.atom_count && + ctx->text.s.selections[ctx->text.s.atom_count-1] == 0) + ctx->text.s.atom_count--; + } + + if (ctx->text.s.atom_count == 0) + ModifySelection(ctx, ctx->text.insertPos, ctx->text.insertPos); + + if (ctx->text.old_insert >= 0) /* Update in progress. */ + _XawTextExecuteUpdate(ctx); + + prevSalt = 0; + for (salt = ctx->text.salt; salt; salt = nextSalt) + { + atomP = salt->s.selections; + nextSalt = salt->next; + for (i = 0 ; i < salt->s.atom_count; i++, atomP++) + if (*selection == *atomP) + *atomP = (Atom)0; + + while (salt->s.atom_count && + salt->s.selections[salt->s.atom_count-1] == 0) + { + salt->s.atom_count--; + } + + /* + * Must walk the selection list in opposite order from UnsetSelection. + */ + + atomP = salt->s.selections; + for (i = 0 ; i < salt->s.atom_count; i++, atomP++) + if (*atomP == (Atom)0) + { + *atomP = salt->s.selections[--salt->s.atom_count]; + while (salt->s.atom_count && + salt->s.selections[salt->s.atom_count-1] == 0) + salt->s.atom_count--; + } + if (salt->s.atom_count == 0) + { + XtFree ((char *) salt->s.selections); + XtFree (salt->contents); + if (prevSalt) + prevSalt->next = nextSalt; + else + ctx->text.salt = nextSalt; + XtFree ((char *) salt); + } + else + prevSalt = salt; + } +} + +void +_XawTextSaltAwaySelection (ctx, selections, num_atoms) +TextWidget ctx; +Atom* selections; +int num_atoms; +{ + XawTextSelectionSalt *salt; + int i, j; + + for (i = 0; i < num_atoms; i++) + LoseSelection ((Widget) ctx, selections + i); + if (num_atoms == 0) + return; + salt = (XawTextSelectionSalt *) + XtMalloc( (unsigned) sizeof(XawTextSelectionSalt) ); + if (!salt) + return; + salt->s.selections = (Atom *) + XtMalloc( (unsigned) ( num_atoms * sizeof (Atom) ) ); + if (!salt->s.selections) + { + XtFree ((char *) salt); + return; + } + salt->s.left = ctx->text.s.left; + salt->s.right = ctx->text.s.right; + salt->s.type = ctx->text.s.type; + salt->contents = _XawTextGetSTRING(ctx, ctx->text.s.left, ctx->text.s.right); +#ifdef XAW_INTERNATIONALIZATION + if (_XawTextFormat(ctx) == XawFmtWide) { + XTextProperty textprop; + if (XwcTextListToTextProperty(XtDisplay((Widget)ctx), + (wchar_t**)(&(salt->contents)), 1, XCompoundTextStyle, + &textprop) < Success) { + XtFree(salt->contents); + salt->length = 0; + return; + } + XtFree(salt->contents); + salt->contents = (char *)textprop.value; + salt->length = textprop.nitems; + } else +#endif + salt->length = strlen (salt->contents); + salt->next = ctx->text.salt; + ctx->text.salt = salt; + j = 0; + for (i = 0; i < num_atoms; i++) + { + if (GetCutBufferNumber (selections[i]) == NOT_A_CUT_BUFFER) + { + salt->s.selections[j++] = selections[i]; + XtOwnSelection ((Widget) ctx, selections[i], ctx->text.time, + ConvertSelection, LoseSelection, (XtSelectionDoneProc)NULL); + } + } + salt->s.atom_count = j; +} + +static void +_SetSelection(ctx, left, right, selections, count) +TextWidget ctx; +XawTextPosition left, right; +Atom *selections; +Cardinal count; +{ + XawTextPosition pos; + + if (left < ctx->text.s.left) { + pos = Min(right, ctx->text.s.left); + _XawTextNeedsUpdating(ctx, left, pos); + } + if (left > ctx->text.s.left) { + pos = Min(left, ctx->text.s.right); + _XawTextNeedsUpdating(ctx, ctx->text.s.left, pos); + } + if (right < ctx->text.s.right) { + pos = Max(right, ctx->text.s.left); + _XawTextNeedsUpdating(ctx, pos, ctx->text.s.right); + } + if (right > ctx->text.s.right) { + pos = Max(left, ctx->text.s.right); + _XawTextNeedsUpdating(ctx, pos, right); + } + + ctx->text.s.left = left; + ctx->text.s.right = right; + + SrcSetSelection(ctx->text.source, left, right, + (count == 0) ? None : selections[0]); + + if (left < right) { + Widget w = (Widget) ctx; + int buffer; + + while (count) { + Atom selection = selections[--count]; + + if ((buffer = GetCutBufferNumber(selection)) != NOT_A_CUT_BUFFER) { + + unsigned char *ptr, *tptr; + unsigned int amount, max_len = MAX_CUT_LEN(XtDisplay(w)); + unsigned long len; + + tptr= ptr= (unsigned char *) _XawTextGetSTRING(ctx, ctx->text.s.left, + ctx->text.s.right); +#ifdef XAW_INTERNATIONALIZATION + if (_XawTextFormat(ctx) == XawFmtWide) { + /* + * Only XA_STRING(Latin 1) is allowed in CUT_BUFFER, + * so we get it from wchar string, then free the wchar string. + */ + XTextProperty textprop; + if (XwcTextListToTextProperty(XtDisplay(w), (wchar_t**)&ptr, 1, + XStringStyle, &textprop) < Success) { + XtFree((char *)ptr); + return; + } + XtFree((char *)ptr); + tptr = ptr = textprop.value; + } +#endif + if (buffer == 0) { + _CreateCutBuffers(XtDisplay(w)); + XRotateBuffers(XtDisplay(w), 1); + } + amount = Min ( (len = strlen((char *)ptr)), max_len); + XChangeProperty(XtDisplay(w), RootWindow(XtDisplay(w), 0), selection, + XA_STRING, 8, PropModeReplace, ptr, amount); + + while (len > max_len) { + len -= max_len; + tptr += max_len; + amount = Min (len, max_len); + XChangeProperty(XtDisplay(w), RootWindow(XtDisplay(w), 0), + selection, XA_STRING, 8, PropModeAppend, + tptr, amount); + } + XtFree ((char *)ptr); + } + else /* This is a real selection */ + XtOwnSelection(w, selection, ctx->text.time, ConvertSelection, + LoseSelection, (XtSelectionDoneProc)NULL); + } + } + else + XawTextUnsetSelection((Widget)ctx); +} + +/* + * This internal routine deletes the text from pos1 to pos2 in a source and + * then inserts, at pos1, the text that was passed. As a side effect it + * "invalidates" that portion of the displayed text (if any). + * + * NOTE: It is illegal to call this routine unless there is a valid line table! + */ + +int +_XawTextReplace (ctx, pos1, pos2, text) +TextWidget ctx; +XawTextPosition pos1, pos2; +XawTextBlock *text; +{ + int i, line1, delta, error; + XawTextPosition updateFrom, updateTo; + Widget src = ctx->text.source; + XawTextEditType edit_mode; + Arg args[1]; + Boolean tmp = ctx->text.update_disabled; + + ctx->text.update_disabled = True; /* No redisplay during replacement. */ + +/* + * The insertPos may not always be set to the right spot in XawtextAppend + */ + + XtSetArg(args[0], XtNeditType, &edit_mode); + XtGetValues(src, args, ONE); + + if ((pos1 == ctx->text.insertPos) && (edit_mode == XawtextAppend)) { + ctx->text.insertPos = ctx->text.lastPos; + pos2 = SrcScan(src, ctx->text.insertPos, XawstPositions, XawsdRight, + (int)(ctx->text.insertPos - pos1), (Boolean)TRUE); + pos1 = ctx->text.insertPos; + if ( (pos1 == pos2) && (text->length == 0) ) { + ctx->text.update_disabled = FALSE; /* rearm redisplay. */ + return( XawEditError ); + } + } + + updateFrom = SrcScan(src, pos1, XawstWhiteSpace, XawsdLeft, 1, FALSE); + updateFrom = Max(updateFrom, ctx->text.lt.top); + + line1 = LineForPosition(ctx, updateFrom); + if ( (error = SrcReplace(src, pos1, pos2, text)) != 0) { + ctx->text.update_disabled = tmp; /* restore redisplay */ + return(error); + } + + XawTextUnsetSelection((Widget)ctx); + + ctx->text.lastPos = GETLASTPOS; + if (ctx->text.lt.top >= ctx->text.lastPos) { + _XawTextBuildLineTable(ctx, ctx->text.lastPos, FALSE); + ClearWindow( (Widget) ctx); + ctx->text.update_disabled = tmp; /* restore redisplay */ + return(0); /* Things are fine. */ + } + + ctx->text.single_char = (text->length <= 1 && pos2 - pos1 <= 1); + + delta = text->length - (pos2 - pos1); + + if (delta < ctx->text.lastPos) { + for (pos2 += delta, i = 0; i < ctx->text.numranges; i++) { + if (ctx->text.updateFrom[i] > pos1) + ctx->text.updateFrom[i] += delta; + if (ctx->text.updateTo[i] >= pos1) + ctx->text.updateTo[i] += delta; + } + } + + /* + * fixup all current line table entries to reflect edit. + * %%% it is not legal to do arithmetic on positions. + * using Scan would be more proper. + */ + if (delta != 0) { + XawTextLineTableEntry *lineP; + i = LineForPosition(ctx, pos1) + 1; + for (lineP = ctx->text.lt.info + i; i <= ctx->text.lt.lines; i++, lineP++) + lineP->position += delta; + } + + /* + * Now process the line table and fixup in case edits caused + * changes in line breaks. If we are breaking on word boundaries, + * this code checks for moving words to and from lines. + */ + + if (IsPositionVisible(ctx, updateFrom)) { + updateTo = _BuildLineTable(ctx, + ctx->text.lt.info[line1].position, pos1, line1); + _XawTextNeedsUpdating(ctx, updateFrom, updateTo); + } + + ctx->text.update_disabled = tmp; /* restore redisplay */ + return(0); /* Things are fine. */ +} + +/* + * This routine will display text between two arbitrary source positions. + * In the event that this span contains highlighted text for the selection, + * only that portion will be displayed highlighted. + * + * NOTE: it is illegal to call this routine unless there + * is a valid line table! + */ + +static void +DisplayText(w, pos1, pos2) +Widget w; +XawTextPosition pos1, pos2; +{ + TextWidget ctx = (TextWidget)w; + Position x, y; + int height, line, i, lastPos = ctx->text.lastPos; + XawTextPosition startPos, endPos; + Boolean clear_eol, done_painting; + Dimension s = ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; + + pos1 = (pos1 < ctx->text.lt.top) ? ctx->text.lt.top : pos1; + pos2 = FindGoodPosition(ctx, pos2); + if ( (pos1 >= pos2) || !LineAndXYForPosition(ctx, pos1, &line, &x, &y) ) + return; /* line not visible, or pos1 >= pos2. */ + + for ( startPos = pos1, i = line; IsValidLine(ctx, i) && + (i < ctx->text.lt.lines) ; i++) { + + + if ( (endPos = ctx->text.lt.info[i + 1].position) > pos2 ) { + clear_eol = ((endPos = pos2) >= lastPos); + done_painting = (!clear_eol || ctx->text.single_char); + } + else { + clear_eol = TRUE; + done_painting = FALSE; + } + + height = ctx->text.lt.info[i + 1].y - ctx->text.lt.info[i].y - s + 1; + + if ( (endPos > startPos) ) { + + /* note to self: _ShadowSurroundedBox() hacks are in here */ + + if ( (x == (Position) ctx->text.margin.left) && (x > 0) ) + { + SinkClearToBG (ctx->text.sink, + (Position) s, y, + (Dimension) ctx->text.margin.left, (Dimension)height); + _ShadowSurroundedBox((Widget)ctx, (ThreeDWidget)ctx->text.threeD, + 0, 0, ctx->core.width, ctx->core.height, + ((ThreeDWidget)ctx->text.threeD)->threeD.relief, + False); + } + + if ( (startPos >= ctx->text.s.right) || (endPos <= ctx->text.s.left) ) + XawTextSinkDisplayText(ctx->text.sink, x, y, startPos, endPos, FALSE); + else if ((startPos >= ctx->text.s.left) && (endPos <= ctx->text.s.right)) + XawTextSinkDisplayText(ctx->text.sink, x, y, startPos, endPos, TRUE); + else { + DisplayText(w, startPos, ctx->text.s.left); + DisplayText(w, Max(startPos, ctx->text.s.left), + Min(endPos, ctx->text.s.right)); + DisplayText(w, ctx->text.s.right, endPos); + } + } + startPos = endPos; + if (clear_eol) { + Position myx = ctx->text.lt.info[i].textWidth + ctx->text.margin.left; + + SinkClearToBG(ctx->text.sink, + (Position) myx, + (Position) y, w->core.width - myx/* - 2 * s*/, + (Dimension) height); + _ShadowSurroundedBox((Widget)ctx, (ThreeDWidget)ctx->text.threeD, + 0, 0, ctx->core.width, ctx->core.height, + ((ThreeDWidget)ctx->text.threeD)->threeD.relief, + False); + + /* + * We only get here if single character is true, and we need + * to clear to the end of the screen. We know that since there + * was only one character deleted that this is the same + * as clearing an extra line, so we do this, and are done. + * + * This a performance hack, and a pretty gross one, but it works. + * + * Chris Peterson 11/13/89. + */ + + if (done_painting) { + y += height; + SinkClearToBG(ctx->text.sink, + (Position) ctx->text.margin.left, (Position) y, + w->core.width - ctx->text.margin.left/* - 2 * s*/, + (Dimension) Min(height, ctx->core.height - 2 * s - y)); + _ShadowSurroundedBox((Widget)ctx, (ThreeDWidget)ctx->text.threeD, + 0, 0, ctx->core.width, ctx->core.height, + ((ThreeDWidget)ctx->text.threeD)->threeD.relief, + False); + + break; /* set single_char to FALSE and return. */ + } + } + + x = (Position) ctx->text.margin.left; + y = ctx->text.lt.info[i + 1].y; + if ( done_painting + || (y >= (int)(ctx->core.height - ctx->text.margin.bottom)) ) + break; + } + ctx->text.single_char = FALSE; +} + +/* + * This routine implements multi-click selection in a hardwired manner. + * It supports multi-click entity cycling (char, word, line, file) and mouse + * motion adjustment of the selected entitie (i.e. select a word then, with + * button still down, adjust wich word you really meant by moving the mouse). + * [NOTE: This routine is to be replaced by a set of procedures that + * will allows clients to implements a wide class of draw through and + * multi-click selection user interfaces.] + */ + +static void +DoSelection (ctx, pos, time, motion) +TextWidget ctx; +XawTextPosition pos; +Time time; +Boolean motion; +{ + XawTextPosition newLeft, newRight; + XawTextSelectType newType, *sarray; + Widget src = ctx->text.source; + + if (motion) + newType = ctx->text.s.type; + else { + if ( (abs((long) time - (long) ctx->text.lasttime) < MULTI_CLICK_TIME) && + ((pos >= ctx->text.s.left) && (pos <= ctx->text.s.right))) { + sarray = ctx->text.sarray; + for (;*sarray != XawselectNull && *sarray != ctx->text.s.type; sarray++); + + if (*sarray == XawselectNull) + newType = *(ctx->text.sarray); + else { + newType = *(sarray + 1); + if (newType == XawselectNull) + newType = *(ctx->text.sarray); + } + } + else /* single-click event */ + newType = *(ctx->text.sarray); + + ctx->text.lasttime = time; + } + switch (newType) { + case XawselectPosition: + newLeft = newRight = pos; + break; + case XawselectChar: + newLeft = pos; + newRight = SrcScan(src, pos, XawstPositions, XawsdRight, 1, FALSE); + break; + case XawselectWord: + case XawselectParagraph: + { + XawTextScanType stype; + + if (newType == XawselectWord) + stype = XawstWhiteSpace; + else + stype = XawstParagraph; + + /* + * Somewhat complicated, but basically I treat the space between + * two objects as another object. The object that I am currently + * in then becomes the end of the selection. + * + * Chris Peterson - 4/19/90. + */ + + newRight = SrcScan(ctx->text.source, pos, stype, XawsdRight, 1, FALSE); + newRight =SrcScan(ctx->text.source, newRight,stype,XawsdLeft,1, FALSE); + + if (pos != newRight) + newLeft = SrcScan(ctx->text.source, pos, stype, XawsdLeft, 1, FALSE); + else + newLeft = pos; + + newLeft =SrcScan(ctx->text.source, newLeft, stype, XawsdRight,1,FALSE); + + if (newLeft > newRight) { + XawTextPosition temp = newLeft; + newLeft = newRight; + newRight = temp; + } + } + break; + case XawselectLine: + newLeft = SrcScan(src, pos, XawstEOL, XawsdLeft, 1, FALSE); + newRight = SrcScan(src, pos, XawstEOL, XawsdRight, 1, FALSE); + break; + case XawselectAll: + newLeft = SrcScan(src, pos, XawstAll, XawsdLeft, 1, FALSE); + newRight = SrcScan(src, pos, XawstAll, XawsdRight, 1, FALSE); + break; + default: + XtAppWarning(XtWidgetToApplicationContext((Widget) ctx), + "Text Widget: empty selection array."); + return; + } + + if ( (newLeft != ctx->text.s.left) || (newRight != ctx->text.s.right) + || (newType != ctx->text.s.type)) { + ModifySelection(ctx, newLeft, newRight); + if (pos - ctx->text.s.left < ctx->text.s.right - pos) + ctx->text.insertPos = newLeft; + else + ctx->text.insertPos = newRight; + ctx->text.s.type = newType; + } + if (!motion) { /* setup so we can freely mix select extend calls*/ + ctx->text.origSel.type = ctx->text.s.type; + ctx->text.origSel.left = ctx->text.s.left; + ctx->text.origSel.right = ctx->text.s.right; + + if (pos >= ctx->text.s.left + ((ctx->text.s.right - ctx->text.s.left) / 2)) + ctx->text.extendDir = XawsdRight; + else + ctx->text.extendDir = XawsdLeft; + } +} + +/* + * This routine implements extension of the currently selected text in + * the "current" mode (i.e. char word, line, etc.). It worries about + * extending from either end of the selection and handles the case when you + * cross through the "center" of the current selection (e.g. switch which + * end you are extending!). + */ + +static void +ExtendSelection (ctx, pos, motion) +TextWidget ctx; +XawTextPosition pos; +Boolean motion; +{ + XawTextScanDirection dir; + + if (!motion) { /* setup for extending selection */ + if (ctx->text.s.left == ctx->text.s.right) /* no current selection. */ + ctx->text.s.left = ctx->text.s.right = ctx->text.insertPos; + else { + ctx->text.origSel.left = ctx->text.s.left; + ctx->text.origSel.right = ctx->text.s.right; + } + + ctx->text.origSel.type = ctx->text.s.type; + + if (pos >= ctx->text.s.left + ((ctx->text.s.right - ctx->text.s.left) / 2)) + ctx->text.extendDir = XawsdRight; + else + ctx->text.extendDir = XawsdLeft; + } + else /* check for change in extend direction */ + if ((ctx->text.extendDir == XawsdRight && pos <= ctx->text.origSel.left) || + (ctx->text.extendDir == XawsdLeft && pos >= ctx->text.origSel.right)) { + ctx->text.extendDir = (ctx->text.extendDir == XawsdRight) ? + XawsdLeft : XawsdRight; + ModifySelection(ctx, ctx->text.origSel.left, ctx->text.origSel.right); + } + + dir = ctx->text.extendDir; + switch (ctx->text.s.type) { + case XawselectWord: + case XawselectParagraph: + { + XawTextPosition left_pos, right_pos; + XawTextScanType stype; + + if (ctx->text.s.type == XawselectWord) + stype = XawstWhiteSpace; + else + stype = XawstParagraph; + + /* + * Somewhat complicated, but basically I treat the space between + * two objects as another object. The object that I am currently + * in then becomes the end of the selection. + * + * Chris Peterson - 4/19/90. + */ + + right_pos = SrcScan(ctx->text.source, pos, stype, XawsdRight, 1, FALSE); + right_pos =SrcScan(ctx->text.source, right_pos,stype,XawsdLeft,1, FALSE); + + if (pos != right_pos) + left_pos = SrcScan(ctx->text.source, pos, stype, XawsdLeft, 1, FALSE); + else + left_pos = pos; + + left_pos =SrcScan(ctx->text.source, left_pos, stype, XawsdRight,1,FALSE); + + if (dir == XawsdLeft) + pos = Min(left_pos, right_pos); + else /* dir == XawsdRight */ + pos = Max(left_pos, right_pos); + } + break; + case XawselectLine: + pos = SrcScan(ctx->text.source, pos, XawstEOL, dir, 1, dir == XawsdRight); + break; + case XawselectAll: + pos = ctx->text.insertPos; + case XawselectPosition: /* fall through. */ + default: + break; + } + + if (dir == XawsdRight) + ModifySelection(ctx, ctx->text.s.left, pos); + else + ModifySelection(ctx, pos, ctx->text.s.right); + + ctx->text.insertPos = pos; +} + +/* + * Clear the window to background color. + */ + +static void +ClearWindow (w) +Widget w; +{ + TextWidget ctx = (TextWidget) w; + int s = ((ThreeDWidget)ctx->text.threeD)->threeD.shadow_width; + + if (XtIsRealized(w)) + { + SinkClearToBG(ctx->text.sink, + (Position) s, (Position) s, + w->core.width - 2 * s, w->core.height - 2 * s); + /* note to self: _ShadowSurroundedBox() hack might be needed here */ + } +} + +/* Function Name: _XawTextClearAndCenterDisplay + * Description: Redraws the display with the cursor in insert point + * centered vertically. + * Arguments: ctx - the text widget. + * Returns: none. + */ + +void +_XawTextClearAndCenterDisplay(ctx) +TextWidget ctx; +{ + int insert_line = LineForPosition(ctx, ctx->text.insertPos); + int scroll_by = insert_line - ctx->text.lt.lines/2; + + _XawTextVScroll(ctx, scroll_by); + DisplayTextWindow( (Widget) ctx); +} + +/* + * Internal redisplay entire window. + * Legal to call only if widget is realized. + */ + +static void +DisplayTextWindow (w) +Widget w; +{ + TextWidget ctx = (TextWidget) w; + ClearWindow(w); + _XawTextBuildLineTable(ctx, ctx->text.lt.top, FALSE); + _XawTextNeedsUpdating(ctx, zeroPosition, ctx->text.lastPos); + _XawTextSetScrollBars(ctx); +} + +/* + * This routine checks to see if the window should be resized (grown or + * shrunk) when text to be painted overflows to the right or + * the bottom of the window. It is used by the keyboard input routine. + */ + +void +_XawTextCheckResize(ctx) +TextWidget ctx; +{ + Widget w = (Widget) ctx; + int line = 0, old_height; + XtWidgetGeometry rbox, return_geom; + + if ( (ctx->text.resize == XawtextResizeWidth) || + (ctx->text.resize == XawtextResizeBoth) ) { + XawTextLineTableEntry *lt; + rbox.width = 0; + for (lt = ctx->text.lt.info; + IsValidLine(ctx, line) && (line < ctx->text.lt.lines); + line++, lt++) { + if ((int)(lt->textWidth + ctx->text.margin.left) > (int)rbox.width) + rbox.width = lt->textWidth + ctx->text.margin.left; + } + + rbox.width += ctx->text.margin.right; + if (rbox.width > ctx->core.width) { /* Only get wider. */ + rbox.request_mode = CWWidth; + if (XtMakeGeometryRequest(w, &rbox, &return_geom) == XtGeometryAlmost) + (void) XtMakeGeometryRequest(w, &return_geom, (XtWidgetGeometry*) NULL); + } + } + + if ( !((ctx->text.resize == XawtextResizeHeight) || + (ctx->text.resize == XawtextResizeBoth)) ) + return; + + if (IsPositionVisible(ctx, ctx->text.lastPos)) + line = LineForPosition(ctx, ctx->text.lastPos); + else + line = ctx->text.lt.lines; + + if ( (line + 1) == ctx->text.lt.lines ) return; + + old_height = ctx->core.height; + rbox.request_mode = CWHeight; + rbox.height = XawTextSinkMaxHeight(ctx->text.sink, line + 1) + VMargins(ctx); + + if ((int)rbox.height < old_height) return; /* It will only get taller. */ + + if (XtMakeGeometryRequest(w, &rbox, &return_geom) == XtGeometryAlmost) + if (XtMakeGeometryRequest(w, &return_geom, (XtWidgetGeometry*)NULL) != XtGeometryYes) + return; + + _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE); +} + +/* + * Converts (params, num_params) to a list of atoms & caches the + * list in the TextWidget instance. + */ + +Atom* +_XawTextSelectionList(ctx, list, nelems) +TextWidget ctx; +String *list; +Cardinal nelems; +{ + Atom * sel = ctx->text.s.selections; + Display *dpy = XtDisplay((Widget) ctx); + int n; + + if (nelems > ctx->text.s.array_size) { + sel = (Atom *) XtRealloc((char *) sel, sizeof(Atom) * nelems); + ctx->text.s.array_size = nelems; + ctx->text.s.selections = sel; + } + for (n=nelems; --n >= 0; sel++, list++) + *sel = XInternAtom(dpy, *list, False); + + ctx->text.s.atom_count = nelems; + return ctx->text.s.selections; +} + +/* Function Name: SetSelection + * Description: Sets the current selection. + * Arguments: ctx - the text widget. + * defaultSel - the default selection. + * l, r - the left and right ends of the selection. + * list, nelems - the selection list (as strings). + * Returns: none. + * + * NOTE: if (ctx->text.s.left >= ctx->text.s.right) then the selection + * is unset. + */ + +void +_XawTextSetSelection(ctx, l, r, list, nelems) +TextWidget ctx; +XawTextPosition l, r; +String *list; +Cardinal nelems; +{ + if (nelems == 1 && !strcmp (list[0], "none")) + return; + if (nelems == 0) { + String defaultSel = "PRIMARY"; + list = &defaultSel; + nelems = 1; + } + _SetSelection(ctx, l, r, _XawTextSelectionList(ctx, list, nelems), nelems); +} + + +/* Function Name: ModifySelection + * Description: Modifies the current selection. + * Arguments: ctx - the text widget. + * left, right - the left and right ends of the selection. + * Returns: none. + * + * NOTE: if (ctx->text.s.left >= ctx->text.s.right) then the selection + * is unset. + */ + +static void +ModifySelection(ctx, left, right) +TextWidget ctx; +XawTextPosition left, right; +{ + if (left == right) + ctx->text.insertPos = left; + _SetSelection( ctx, left, right, (Atom*) NULL, ZERO ); +} + +/* + * This routine is used to perform various selection functions. The goal is + * to be able to specify all the more popular forms of draw-through and + * multi-click selection user interfaces from the outside. + */ + +void +_XawTextAlterSelection (ctx, mode, action, params, num_params) +TextWidget ctx; +XawTextSelectionMode mode; /* {XawsmTextSelect, XawsmTextExtend} */ +XawTextSelectionAction action; /* {XawactionStart, + XawactionAdjust, XawactionEnd} */ +String *params; +Cardinal *num_params; +{ + XawTextPosition position; + Boolean flag; + +/* + * This flag is used by TextPop.c:DoReplace() to determine if the selection + * is okay to use, or if it has been modified. + */ + + if (ctx->text.search != NULL) + ctx->text.search->selection_changed = TRUE; + + position = PositionForXY (ctx, (int) ctx->text.ev_x, (int) ctx->text.ev_y); + + flag = (action != XawactionStart); + if (mode == XawsmTextSelect) + DoSelection (ctx, position, ctx->text.time, flag); + else /* mode == XawsmTextExtend */ + ExtendSelection (ctx, position, flag); + + if (action == XawactionEnd) + _XawTextSetSelection(ctx, ctx->text.s.left, ctx->text.s.right, + params, *num_params); +} + +/* Function Name: RectanglesOverlap + * Description: Returns TRUE if two rectangles overlap. + * Arguments: rect1, rect2 - the two rectangles to check. + * Returns: TRUE iff these rectangles overlap. + */ + +static Boolean +RectanglesOverlap(rect1, rect2) +XRectangle *rect1, *rect2; +{ + return ( (rect1->x < rect2->x + (short) rect2->width) && + (rect2->x < rect1->x + (short) rect1->width) && + (rect1->y < rect2->y + (short) rect2->height) && + (rect2->y < rect1->y + (short) rect1->height) ); +} + +/* Function Name: UpdateTextInRectangle. + * Description: Updates the text in a rectangle. + * Arguments: ctx - the text widget. + * rect - the rectangle to update. + * Returns: none. + */ + +static void +UpdateTextInRectangle(ctx, rect) +TextWidget ctx; +XRectangle * rect; +{ + XawTextLineTableEntry *info = ctx->text.lt.info; + int line, x = rect->x, y = rect->y; + int right = rect->width + x, bottom = rect->height + y; + + for (line = 0;( (line < ctx->text.lt.lines) && + IsValidLine(ctx, line) && (info->y < bottom)); line++, info++) + if ( (info + 1)->y >= y ) + UpdateTextInLine(ctx, line, x, right); +} + +/* + * This routine processes all "expose region" XEvents. In general, its job + * is to the best job at minimal re-paint of the text, displayed in the + * window, that it can. + */ + +/* ARGSUSED */ +static void +ProcessExposeRegion(w, event, region) +Widget w; +XEvent *event; +Region region; /* Unused. */ +{ + TextWidget ctx = (TextWidget) w; + XRectangle expose, cursor; + Boolean need_to_draw; + + if (event->type == Expose) { + expose.x = event->xexpose.x; + expose.y = event->xexpose.y; + expose.width = event->xexpose.width; + expose.height = event->xexpose.height; + } + else if (event->type == GraphicsExpose) { + expose.x = event->xgraphicsexpose.x; + expose.y = event->xgraphicsexpose.y; + expose.width = event->xgraphicsexpose.width; + expose.height = event->xgraphicsexpose.height; + } + else { /* No Expose */ + PopCopyQueue(ctx); + return; /* no more processing necessary. */ + } + + need_to_draw = TranslateExposeRegion(ctx, &expose); + if ((event->type == GraphicsExpose) && (event->xgraphicsexpose.count == 0)) + PopCopyQueue(ctx); + + if (!need_to_draw) + return; /* don't draw if we don't need to. */ + + _XawTextPrepareToUpdate(ctx); + UpdateTextInRectangle(ctx, &expose); + XawTextSinkGetCursorBounds(ctx->text.sink, &cursor); + if (RectanglesOverlap(&cursor, &expose)) { + SinkClearToBG(ctx->text.sink, (Position) cursor.x, (Position) cursor.y, + (Dimension) cursor.width, (Dimension) cursor.height); + UpdateTextInRectangle(ctx, &cursor); + } + _XawTextExecuteUpdate(ctx); + + _ShadowSurroundedBox((Widget)ctx, (ThreeDWidget)ctx->text.threeD, + 0, 0, ctx->core.width, ctx->core.height, + ((ThreeDWidget)ctx->text.threeD)->threeD.relief, False); +} + +/* + * This routine does all setup required to syncronize batched screen updates + */ + +void +_XawTextPrepareToUpdate(ctx) +TextWidget ctx; +{ + if (ctx->text.old_insert < 0) { + InsertCursor((Widget)ctx, XawisOff); + ctx->text.numranges = 0; + ctx->text.showposition = FALSE; + ctx->text.old_insert = ctx->text.insertPos; + } +} + +/* + * This is a private utility routine used by _XawTextExecuteUpdate. It + * processes all the outstanding update requests and merges update + * ranges where possible. + */ + +static +void FlushUpdate(ctx) +TextWidget ctx; +{ + int i, w; + XawTextPosition updateFrom, updateTo; + if (!XtIsRealized((Widget)ctx)) { + ctx->text.numranges = 0; + return; + } + while (ctx->text.numranges > 0) { + updateFrom = ctx->text.updateFrom[0]; + w = 0; + for (i = 1 ; i < ctx->text.numranges ; i++) { + if (ctx->text.updateFrom[i] < updateFrom) { + updateFrom = ctx->text.updateFrom[i]; + w = i; + } + } + updateTo = ctx->text.updateTo[w]; + ctx->text.numranges--; + ctx->text.updateFrom[w] = ctx->text.updateFrom[ctx->text.numranges]; + ctx->text.updateTo[w] = ctx->text.updateTo[ctx->text.numranges]; + for (i = ctx->text.numranges - 1 ; i >= 0 ; i--) { + while (ctx->text.updateFrom[i] <= updateTo && i < ctx->text.numranges) { + updateTo = ctx->text.updateTo[i]; + ctx->text.numranges--; + ctx->text.updateFrom[i] = ctx->text.updateFrom[ctx->text.numranges]; + ctx->text.updateTo[i] = ctx->text.updateTo[ctx->text.numranges]; + } + } + DisplayText((Widget)ctx, updateFrom, updateTo); + } +} + +/* + * This is a private utility routine used by _XawTextExecuteUpdate. This + * routine worries about edits causing new data or the insertion point becoming + * invisible (off the screen, or under the horiz. scrollbar). Currently + * it always makes it visible by scrolling. It probably needs + * generalization to allow more options. + */ + +void +_XawTextShowPosition(ctx) +TextWidget ctx; +{ + int x, y, lines, number; + Boolean no_scroll; + XawTextPosition max_pos, top, first; + + if ( (!XtIsRealized((Widget)ctx)) || (ctx->text.lt.lines <= 0) ) + return; + +/* + * Find out the bottom the visable window, and make sure that the + * cursor does not go past the end of this space. + * + * This makes sure that the cursor does not go past the end of the + * visable window. + */ + + x = ctx->core.width; + y = ctx->core.height - ctx->text.margin.bottom; + if (ctx->text.hbar != NULL) + y -= ctx->text.hbar->core.height + 2 * ctx->text.hbar->core.border_width; + + max_pos = PositionForXY (ctx, x, y); + lines = LineForPosition(ctx, max_pos) + 1; /* number of visable lines. */ + + if ( (ctx->text.insertPos >= ctx->text.lt.top) && + (ctx->text.insertPos < max_pos)) + return; + + first = ctx->text.lt.top; + no_scroll = FALSE; + + if (ctx->text.insertPos < first) { /* We need to scroll down. */ + top = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstEOL, XawsdLeft, 1, FALSE); + + /* count the number of lines we have to scroll */ + + number = 0; + while (first > top) { + first = SrcScan(ctx->text.source, first, + XawstEOL, XawsdLeft, 1, TRUE); + + if ( - number > lines ) + break; + + number--; + } + + if (first <= top) { /* If we found the proper number + of lines. */ + + /* Back up to just before the last CR. */ + + first = SrcScan(ctx->text.source, first, + XawstPositions, XawsdRight, 1, TRUE); + + /* Check to make sure the cursor is visable. */ + + if (first <= top) + number++; + + lines = number; + } + else + no_scroll = TRUE; + } + else { /* We need to Scroll up */ + top = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstEOL, XawsdLeft, lines, FALSE); + + if (top < max_pos) + lines = LineForPosition(ctx, top); + else + no_scroll = TRUE; + } + + if (no_scroll) { + _XawTextBuildLineTable(ctx, top, FALSE); + DisplayTextWindow((Widget)ctx); + } + else + _XawTextVScroll(ctx, lines); + + _XawTextSetScrollBars(ctx); +} + +/* + * This routine causes all batched screen updates to be performed + */ + +void +_XawTextExecuteUpdate(ctx) +TextWidget ctx; +{ + if ( ctx->text.update_disabled || (ctx->text.old_insert < 0) ) + return; + + if((ctx->text.old_insert != ctx->text.insertPos) || (ctx->text.showposition)) + _XawTextShowPosition(ctx); + FlushUpdate(ctx); + InsertCursor((Widget)ctx, XawisOn); + ctx->text.old_insert = -1; +} + + +static void +TextDestroy(w) +Widget w; +{ + TextWidget ctx = (TextWidget)w; + + DestroyHScrollBar(ctx); + DestroyVScrollBar(ctx); + + XtFree((char *)ctx->text.s.selections); + XtFree((char *)ctx->text.lt.info); + XtFree((char *)ctx->text.search); + XtFree((char *)ctx->text.updateFrom); + XtFree((char *)ctx->text.updateTo); +} + +/* + * by the time we are managed (and get this far) we had better + * have both a source and a sink + */ + +static void +Resize(w) +Widget w; +{ + TextWidget ctx = (TextWidget) w; + + PositionVScrollBar(ctx); + PositionHScrollBar(ctx); + + _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE); + _XawTextSetScrollBars(ctx); +} + +/* + * This routine allow the application program to Set attributes. + */ + +/*ARGSUSED*/ +static Boolean +SetValues(current, request, new, args, num_args) +Widget current, request, new; +ArgList args; +Cardinal *num_args; +{ + TextWidget oldtw = (TextWidget) current; + TextWidget newtw = (TextWidget) new; + Boolean redisplay = FALSE; + Boolean display_caret = newtw->text.display_caret; + + + newtw->text.display_caret = oldtw->text.display_caret; + _XawTextPrepareToUpdate(newtw); + newtw->text.display_caret = display_caret; + + if (oldtw->text.r_margin.left != newtw->text.r_margin.left) { + newtw->text.margin.left = newtw->text.r_margin.left; + if (newtw->text.vbar != NULL) + newtw->text.margin.left += newtw->text.vbar->core.width + + newtw->text.vbar->core.border_width; + redisplay = TRUE; + } + + if (oldtw->text.scroll_vert != newtw->text.scroll_vert) { + if (newtw->text.scroll_vert == XawtextScrollNever) + DestroyVScrollBar(newtw); + else if (newtw->text.scroll_vert == XawtextScrollAlways) + CreateVScrollBar(newtw); + redisplay = TRUE; + } + + if (oldtw->text.r_margin.bottom != newtw->text.r_margin.bottom) { + newtw->text.margin.bottom = newtw->text.r_margin.bottom; + if (newtw->text.hbar != NULL) + newtw->text.margin.bottom += newtw->text.hbar->core.height + + newtw->text.hbar->core.border_width; + redisplay = TRUE; + } + + if (oldtw->text.scroll_horiz != newtw->text.scroll_horiz) { + if (newtw->text.scroll_horiz == XawtextScrollNever) + DestroyHScrollBar(newtw); + else if (newtw->text.scroll_horiz == XawtextScrollAlways) + CreateHScrollBar(newtw); + redisplay = TRUE; + } + + if ( oldtw->text.source != newtw->text.source ) + XawTextSetSource( (Widget) newtw, newtw->text.source, newtw->text.lt.top); + + newtw->text.redisplay_needed = False; + XtSetValues( (Widget)newtw->text.source, args, *num_args ); + XtSetValues( (Widget)newtw->text.sink, args, *num_args ); + + if ( oldtw->text.wrap != newtw->text.wrap || + oldtw->text.lt.top != newtw->text.lt.top || + oldtw->text.r_margin.right != newtw->text.r_margin.right || + oldtw->text.r_margin.top != newtw->text.r_margin.top || + oldtw->text.sink != newtw->text.sink || + newtw->text.redisplay_needed ) + { + _XawTextBuildLineTable(newtw, newtw->text.lt.top, TRUE); + redisplay = TRUE; + } + + if (oldtw->text.insertPos != newtw->text.insertPos) { + newtw->text.showposition = TRUE; + redisplay = TRUE; + } + + _XawTextExecuteUpdate(newtw); + if (redisplay) + _XawTextSetScrollBars(newtw); + + return redisplay; +} + +/* invoked by the Simple widget's SetValues */ +static Boolean ChangeSensitive(w) + Widget w; /* the new widget */ +{ + Arg args[1]; + TextWidget tw = (TextWidget) w; + + (*(&simpleClassRec)->simple_class.change_sensitive)(w); + + XtSetArg(args[0], XtNancestorSensitive, + (tw->core.ancestor_sensitive && tw->core.sensitive)); + if (tw->text.vbar) + XtSetValues(tw->text.vbar, args, ONE); + if (tw->text.hbar) + XtSetValues(tw->text.hbar, args, ONE); + return False; +} + +/* Function Name: GetValuesHook + * Description: This is a get values hook routine that gets the + * values in the text source and sink. + * Arguments: w - the Text Widget. + * args - the argument list. + * num_args - the number of args. + * Returns: none. + */ + +static void +GetValuesHook(w, args, num_args) +Widget w; +ArgList args; +Cardinal * num_args; +{ + XtGetValues( ((TextWidget) w)->text.source, args, *num_args ); + XtGetValues( ((TextWidget) w)->text.sink, args, *num_args ); +} + +/* Function Name: FindGoodPosition + * Description: Returns a valid position given any postition + * Arguments: pos - any position. + * Returns: a position between (0 and lastPos); + */ + +static XawTextPosition +FindGoodPosition(ctx, pos) +TextWidget ctx; +XawTextPosition pos; +{ + if (pos < 0) return(0); + return ( ((pos > ctx->text.lastPos) ? ctx->text.lastPos : pos) ); +} + +/************************************************************ + * + * Routines for handling the copy area expose queue. + * + ************************************************************/ + +/* Function Name: PushCopyQueue + * Description: Pushes a value onto the copy queue. + * Arguments: ctx - the text widget. + * h, v - amount of offset in the horiz and vert directions. + * Returns: none + */ + +static void +PushCopyQueue(ctx, h, v) +TextWidget ctx; +int h, v; +{ + struct text_move * offsets = XtNew(struct text_move); + + offsets->h = h; + offsets->v = v; + offsets->next = NULL; + + if (ctx->text.copy_area_offsets == NULL) + ctx->text.copy_area_offsets = offsets; + else { + struct text_move * end = ctx->text.copy_area_offsets; + for ( ; end->next != NULL; end = end->next) {} + end->next = offsets; + } +} + +/* Function Name: PopCopyQueue + * Description: Pops the top value off of the copy queue. + * Arguments: ctx - the text widget. + * Returns: none. + */ + +static void +PopCopyQueue(ctx) +TextWidget ctx; +{ + struct text_move * offsets = ctx->text.copy_area_offsets; + + if (offsets == NULL) + (void) printf( "Xaw Text widget %s: empty copy queue\n", + XtName( (Widget) ctx ) ); + else { + ctx->text.copy_area_offsets = offsets->next; + XtFree((char *) offsets); /* free what you allocate. */ + } +} + +/* Function Name: TranslateExposeRegion + * Description: Translates the expose that came into + * the cordinates that now exist in the Text widget. + * Arguments: ctx - the text widget. + * expose - a Rectangle, who's region currently + * contains the expose event location. + * this region will be returned containing + * the new rectangle. + * Returns: True if there is drawing that needs to be done. + */ + +static Boolean +TranslateExposeRegion(ctx, expose) +TextWidget ctx; +XRectangle * expose; +{ + struct text_move * offsets = ctx->text.copy_area_offsets; + int value; + int x, y, width, height; + + /* + * Skip over the first one, this has already been taken into account. + */ + + if (!offsets || !(offsets = offsets->next)) + return(TRUE); + + x = expose->x; + y = expose->y; + width = expose->width; + height = expose->height; + + while (offsets) { + x += offsets->h; + y += offsets->v; + offsets = offsets->next; + } + + /* + * remove that area of the region that is now outside the window. + */ + + if (y < 0) { + height += y; + y = 0; + } + + value = y + height - ctx->core.height; + if (value > 0) + height -= value; + + if (height <= 0) + return(FALSE); /* no need to draw outside the window. */ + + /* + * and now in the horiz direction... + */ + + if (x < 0) { + width += x; + x = 0; + } + + value = x + width - ctx->core.width; + if (value > 0) + width -= value; + + if (width <= 0) + return(FALSE); /* no need to draw outside the window. */ + + expose->x = x; + expose->y = y; + expose->width = width; + expose->height = height; + return(TRUE); +} + +/* Li wrote this so the IM can find a given text position's screen position. */ + +void +#if NeedFunctionPrototypes +_XawTextPosToXY( + Widget w, + XawTextPosition pos, + Position* x, + Position* y ) +#else +_XawTextPosToXY( w, pos, x, y ) + Widget w; + XawTextPosition pos; + Position *x, *y; +#endif +{ + int line; + LineAndXYForPosition( (TextWidget)w, pos, &line, x, y ); +} + +/******************************************************************* +The following routines provide procedural interfaces to Text window state +setting and getting. They need to be redone so than the args code can use +them. I suggest we create a complete set that takes the context as an +argument and then have the public version lookup the context and call the +internal one. The major value of this set is that they have actual application +clients and therefore the functionality provided is required for any future +version of Text. +********************************************************************/ + +void +#if NeedFunctionPrototypes +XawTextDisplay (Widget w) +#else +XawTextDisplay (w) +Widget w; +#endif +{ + if (!XtIsRealized(w)) return; + + _XawTextPrepareToUpdate( (TextWidget) w); + DisplayTextWindow(w); + _XawTextExecuteUpdate( (TextWidget) w); +} + +void +#if NeedFunctionPrototypes +XawTextSetSelectionArray(Widget w, XawTextSelectType *sarray) +#else +XawTextSetSelectionArray(w, sarray) +Widget w; +XawTextSelectType *sarray; +#endif +{ + ((TextWidget)w)->text.sarray = sarray; +} + +void +#if NeedFunctionPrototypes +XawTextGetSelectionPos(Widget w, XawTextPosition *left, XawTextPosition *right) +#else +XawTextGetSelectionPos(w, left, right) +Widget w; +XawTextPosition* left,* right; +#endif +{ + *left = ((TextWidget) w)->text.s.left; + *right = ((TextWidget) w)->text.s.right; +} + + +void +#if NeedFunctionPrototypes +XawTextSetSource(Widget w, Widget source, XawTextPosition startPos) +#else +XawTextSetSource(w, source, startPos) +Widget w, source; +XawTextPosition startPos; +#endif +{ + TextWidget ctx = (TextWidget) w; + + ctx->text.source = source; + ctx->text.lt.top = startPos; + ctx->text.s.left = ctx->text.s.right = 0; + ctx->text.insertPos = startPos; + ctx->text.lastPos = GETLASTPOS; + + _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE); + XawTextDisplay(w); +} + +/* + * This public routine deletes the text from startPos to endPos in a source and + * then inserts, at startPos, the text that was passed. As a side effect it + * "invalidates" that portion of the displayed text (if any), so that things + * will be repainted properly. + */ + +int +#if NeedFunctionPrototypes +XawTextReplace(Widget w, XawTextPosition startPos, XawTextPosition endPos, + XawTextBlock *text) +#else +XawTextReplace(w, startPos, endPos, text) +Widget w; +XawTextPosition startPos, endPos; +XawTextBlock *text; +#endif +{ + TextWidget ctx = (TextWidget) w; + int result; + + _XawTextPrepareToUpdate(ctx); + endPos = FindGoodPosition(ctx, endPos); + startPos = FindGoodPosition(ctx, startPos); + if ((result = _XawTextReplace(ctx, startPos, endPos, text)) == XawEditDone) { + int delta = text->length - (endPos - startPos); + if (ctx->text.insertPos >= (endPos + delta)) { + XawTextScanDirection sd = (delta < 0) ? XawsdLeft : XawsdRight; + ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstPositions, sd, abs(delta), TRUE); + } + } + + _XawTextCheckResize(ctx); + _XawTextExecuteUpdate(ctx); + _XawTextSetScrollBars(ctx); + + return result; +} + +XawTextPosition +#if NeedFunctionPrototypes +XawTextTopPosition(Widget w) +#else +XawTextTopPosition(w) +Widget w; +#endif +{ + return( ((TextWidget) w)->text.lt.top ); +} + +void +#if NeedFunctionPrototypes +XawTextSetInsertionPoint(Widget w, XawTextPosition position) +#else +XawTextSetInsertionPoint(w, position) +Widget w; +XawTextPosition position; +#endif +{ + TextWidget ctx = (TextWidget) w; + + _XawTextPrepareToUpdate(ctx); + ctx->text.insertPos = FindGoodPosition(ctx, position); + ctx->text.showposition = TRUE; + + _XawTextExecuteUpdate(ctx); +} + +XawTextPosition +#if NeedFunctionPrototypes +XawTextGetInsertionPoint(Widget w) +#else +XawTextGetInsertionPoint(w) +Widget w; +#endif +{ + return( ((TextWidget) w)->text.insertPos); +} + +/* + * NOTE: Must walk the selection list in opposite order from LoseSelection. + */ + +void +#if NeedFunctionPrototypes +XawTextUnsetSelection(Widget w) +#else +XawTextUnsetSelection(w) +Widget w; +#endif +{ + TextWidget ctx = (TextWidget)w; + + while (ctx->text.s.atom_count != 0) { + Atom sel = ctx->text.s.selections[ctx->text.s.atom_count - 1]; + if ( sel != (Atom) 0 ) { +/* + * As selections are lost the atom_count will decrement. + */ + if (GetCutBufferNumber(sel) == NOT_A_CUT_BUFFER) + XtDisownSelection(w, sel, ctx->text.time); + LoseSelection(w, &sel); /* In case this is a cut buffer, or + XtDisownSelection failed to call us. */ + } + } +} + +void +#if NeedFunctionPrototypes +XawTextSetSelection (Widget w, XawTextPosition left, XawTextPosition right) +#else +XawTextSetSelection (w, left, right) +Widget w; +XawTextPosition left, right; +#endif +{ + TextWidget ctx = (TextWidget) w; + + _XawTextPrepareToUpdate(ctx); + _XawTextSetSelection(ctx, FindGoodPosition(ctx, left), + FindGoodPosition(ctx, right), (String*)NULL, ZERO); + _XawTextExecuteUpdate(ctx); +} + +void +#if NeedFunctionPrototypes +XawTextInvalidate(Widget w, XawTextPosition from, XawTextPosition to) +#else +XawTextInvalidate(w, from, to) +Widget w; +XawTextPosition from,to; +#endif +{ + TextWidget ctx = (TextWidget) w; + + from = FindGoodPosition(ctx, from); + to = FindGoodPosition(ctx, to); + ctx->text.lastPos = GETLASTPOS; + _XawTextPrepareToUpdate(ctx); + _XawTextNeedsUpdating(ctx, from, to); + _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE); + _XawTextExecuteUpdate(ctx); +} + +/*ARGSUSED*/ +void +#if NeedFunctionPrototypes +XawTextDisableRedisplay(Widget w) +#else +XawTextDisableRedisplay(w) +Widget w; +#endif +{ + ((TextWidget) w)->text.update_disabled = True; + _XawTextPrepareToUpdate( (TextWidget) w); +} + +void +#if NeedFunctionPrototypes +XawTextEnableRedisplay(Widget w) +#else +XawTextEnableRedisplay(w) +Widget w; +#endif +{ + TextWidget ctx = (TextWidget)w; + XawTextPosition lastPos; + + if (!ctx->text.update_disabled) return; + + ctx->text.update_disabled = False; + lastPos = ctx->text.lastPos = GETLASTPOS; + ctx->text.lt.top = FindGoodPosition(ctx, ctx->text.lt.top); + ctx->text.insertPos = FindGoodPosition(ctx, ctx->text.insertPos); + if ( (ctx->text.s.left > lastPos) || (ctx->text.s.right > lastPos) ) + ctx->text.s.left = ctx->text.s.right = 0; + + _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE); + if (XtIsRealized(w)) + DisplayTextWindow(w); + _XawTextExecuteUpdate(ctx); +} + +Widget +#if NeedFunctionPrototypes +XawTextGetSource(Widget w) +#else +XawTextGetSource(w) +Widget w; +#endif +{ + return ((TextWidget)w)->text.source; +} + +void +#if NeedFunctionPrototypes +XawTextDisplayCaret (Widget w, +#if NeedWidePrototypes + /* Boolean */ int display_caret) +#else + Boolean display_caret) +#endif +#else +XawTextDisplayCaret (w, display_caret) +Widget w; +Boolean display_caret; +#endif +{ + TextWidget ctx = (TextWidget) w; + + if (ctx->text.display_caret == display_caret) return; + + if (XtIsRealized(w)) { + _XawTextPrepareToUpdate(ctx); + ctx->text.display_caret = display_caret; + _XawTextExecuteUpdate(ctx); + } + else + ctx->text.display_caret = display_caret; +} + +/* Function Name: XawTextSearch(w, dir, text). + * Description: searches for the given text block. + * Arguments: w - The text widget. + * dir - The direction to search. + * text - The text block containing info about the string + * to search for. + * Returns: The position of the text found, or XawTextSearchError on + * an error. + */ + +XawTextPosition +#if NeedFunctionPrototypes +XawTextSearch(Widget w, +#if NeedWidePrototypes + /* XawTextScanDirection */ int dir, +#else + XawTextScanDirection dir, +#endif + XawTextBlock *text) +#else +XawTextSearch(w, dir, text) +Widget w; +XawTextScanDirection dir; +XawTextBlock * text; +#endif +{ + TextWidget ctx = (TextWidget) w; + + return(SrcSearch(ctx->text.source, ctx->text.insertPos, dir, text)); +} + +TextClassRec textClassRec = { + { /* core fields */ + /* superclass */ (WidgetClass) &simpleClassRec, + /* class_name */ "Text", + /* widget_size */ sizeof(TextRec), + /* class_initialize */ ClassInitialize, + /* class_part_init */ NULL, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ Realize, + /* actions */ _XawTextActionsTable, + /* num_actions */ 0, /* Set in ClassInitialize. */ + /* resources */ resources, + /* num_ resource */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ TRUE, + /* compress_exposure*/ XtExposeGraphicsExpose | XtExposeNoExpose, + /* compress_enterleave*/ TRUE, + /* visible_interest */ FALSE, + /* destroy */ TextDestroy, + /* resize */ Resize, + /* expose */ ProcessExposeRegion, + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* set_values_almost*/ XtInheritSetValuesAlmost, + /* get_values_hook */ GetValuesHook, + /* accept_focus */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* tm_table */ NULL, /* set in ClassInitialize */ + /* query_geometry */ XtInheritQueryGeometry, + /* display_accelerator*/ XtInheritDisplayAccelerator, + /* extension */ NULL + }, + { /* Simple fields */ + /* change_sensitive */ ChangeSensitive + }, + { /* text fields */ + /* empty */ 0 + } +}; + +WidgetClass textWidgetClass = (WidgetClass)&textClassRec; diff --git a/src/Text.h b/src/Text.h new file mode 100644 index 0000000..9157927 --- /dev/null +++ b/src/Text.h @@ -0,0 +1,310 @@ +/* $XConsortium: Text.h,v 1.45 94/04/17 20:13:05 kaleb Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _XawText_h +#define _XawText_h + +#include <X11/Xaw3d/Simple.h> + +/* + Text widget + + Class: textWidgetClass + Class Name: Text + Superclass: Simple + + Resources added by the Text widget: + + Name Class RepType Default Value + ---- ----- ------- ------------- + autoFill AutoFill Boolean False + bottomMargin Margin Position 2 + displayPosition TextPosition XawTextPosition 0 + insertPosition TextPosition XawTextPosition 0 + leftMargin Margin Position 2 + resize Resize XawTextResizeMode XawTextResizeNever + rightMargin Margin Position 4 + scrollHorizontal Scroll XawTextScrollMode XawtextScrollNever + scrollVertical Scroll XawTextScrollMode XawtextScrollNever + selectTypes SelectTypes Pointer see documentation + textSink TextSink Widget NULL + textSource TextSource Widget NULL + topMargin Margin Position 2 + unrealizeCallback Callback Callback NULL + wrap Wrap XawTextWrapMode XawTextWrapNever + +*/ + +typedef long XawTextPosition; + +typedef enum { XawtextScrollNever, + XawtextScrollWhenNeeded, XawtextScrollAlways} XawTextScrollMode; + +typedef enum { XawtextWrapNever, + XawtextWrapLine, XawtextWrapWord} XawTextWrapMode; + +typedef enum { XawtextResizeNever, XawtextResizeWidth, + XawtextResizeHeight, XawtextResizeBoth} XawTextResizeMode; + +typedef enum {XawsdLeft, XawsdRight} XawTextScanDirection; +typedef enum {XawtextRead, XawtextAppend, XawtextEdit} XawTextEditType; +typedef enum {XawselectNull, XawselectPosition, XawselectChar, XawselectWord, + XawselectLine, XawselectParagraph, XawselectAll} XawTextSelectType; + +typedef struct { + int firstPos; + int length; + char *ptr; + unsigned long format; + } XawTextBlock, *XawTextBlockPtr; + +#include <X11/Xaw3d/TextSink.h> +#include <X11/Xaw3d/TextSrc.h> + +#define XtEtextScrollNever "never" +#define XtEtextScrollWhenNeeded "whenneeded" +#define XtEtextScrollAlways "always" + +#define XtEtextWrapNever "never" +#define XtEtextWrapLine "line" +#define XtEtextWrapWord "word" + +#define XtEtextResizeNever "never" +#define XtEtextResizeWidth "width" +#define XtEtextResizeHeight "height" +#define XtEtextResizeBoth "both" + +#define XtNautoFill "autoFill" +#define XtNbottomMargin "bottomMargin" +#define XtNdialogHOffset "dialogHOffset" +#define XtNdialogVOffset "dialogVOffset" +#define XtNdisplayCaret "displayCaret" +#define XtNdisplayPosition "displayPosition" +#define XtNleftMargin "leftMargin" +#define XtNrightMargin "rightMargin" +#define XtNscrollVertical "scrollVertical" +#define XtNscrollHorizontal "scrollHorizontal" +#define XtNselectTypes "selectTypes" +#define XtNtopMargin "topMargin" +#define XtNwrap "wrap" + +#define XtCAutoFill "AutoFill" +#define XtCScroll "Scroll" +#define XtCSelectTypes "SelectTypes" +#define XtCWrap "Wrap" + +#ifndef _XtStringDefs_h_ +#define XtNinsertPosition "insertPosition" +#define XtNresize "resize" +#define XtNselection "selection" +#define XtCResize "Resize" +#endif + +/* Return Error code for XawTextSearch */ + +#define XawTextSearchError (-12345L) + +/* Return codes from XawTextReplace */ + +#define XawReplaceError -1 +#define XawEditDone 0 +#define XawEditError 1 +#define XawPositionError 2 + +extern unsigned long FMT8BIT; +extern unsigned long XawFmt8Bit; +extern unsigned long XawFmtWide; + +/* Class record constants */ + +extern WidgetClass textWidgetClass; + +typedef struct _TextClassRec *TextWidgetClass; +typedef struct _TextRec *TextWidget; + +_XFUNCPROTOBEGIN + +extern XrmQuark _XawTextFormat( +#if NeedFunctionPrototypes + TextWidget /* tw */ +#endif +); + +extern void XawTextDisplay( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +extern void XawTextEnableRedisplay( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +extern void XawTextDisableRedisplay( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +extern void XawTextSetSelectionArray( +#if NeedFunctionPrototypes + Widget /* w */, + XawTextSelectType* /* sarray */ +#endif +); + +extern void XawTextGetSelectionPos( +#if NeedFunctionPrototypes + Widget /* w */, + XawTextPosition* /* begin_return */, + XawTextPosition* /* end_return */ +#endif +); + +extern void XawTextSetSource( +#if NeedFunctionPrototypes + Widget /* w */, + Widget /* source */, + XawTextPosition /* position */ +#endif +); + +extern int XawTextReplace( +#if NeedFunctionPrototypes + Widget /* w */, + XawTextPosition /* start */, + XawTextPosition /* end */, + XawTextBlock* /* text */ +#endif +); + +extern XawTextPosition XawTextTopPosition( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +extern void XawTextSetInsertionPoint( +#if NeedFunctionPrototypes + Widget /* w */, + XawTextPosition /* position */ +#endif +); + +extern XawTextPosition XawTextGetInsertionPoint( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +extern void XawTextUnsetSelection( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +extern void XawTextSetSelection( +#if NeedFunctionPrototypes + Widget /* w */, + XawTextPosition /* left */, + XawTextPosition /* right */ +#endif +); + +extern void XawTextInvalidate( +#if NeedFunctionPrototypes + Widget /* w */, + XawTextPosition /* from */, + XawTextPosition /* to */ +#endif +); + +extern Widget XawTextGetSource( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +extern XawTextPosition XawTextSearch( +#if NeedFunctionPrototypes + Widget /* w */, +#if NeedWidePrototypes + /* XawTextScanDirection */ int /* dir */, +#else + XawTextScanDirection /* dir */, +#endif + XawTextBlock* /* text */ +#endif +); + +extern void XawTextDisplayCaret( +#if NeedFunctionPrototypes + Widget /* w */, +#if NeedWidePrototypes + /* Boolean */ int /* visible */ +#else + Boolean /* visible */ +#endif +#endif +); + +_XFUNCPROTOEND + +/* + * For R3 compatability only. + */ + +#include <X11/Xaw3d/AsciiSrc.h> +#include <X11/Xaw3d/AsciiSink.h> + +#endif /* _XawText_h */ +/* DON'T ADD STUFF AFTER THIS #endif */ diff --git a/src/TextAction.c b/src/TextAction.c new file mode 100644 index 0000000..65b8539 --- /dev/null +++ b/src/TextAction.c @@ -0,0 +1,2327 @@ +/* $XConsortium: TextAction.c,v 1.53 95/06/14 15:07:27 kaleb Exp $ */ + +/* + +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +#include "Xaw3dP.h" +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xutil.h> +#include <X11/Xatom.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xmu/StdSel.h> /* for XmuConvertStandardSelection */ +#include <X11/Xmu/Atoms.h> /* for XA_COMPOUND_TEXT */ +#include <X11/Xaw3d/TextP.h> +#ifdef XAW_INTERNATIONALIZATION +#include <X11/Xaw3d/MultiSrcP.h> +#include <X11/Xaw3d/XawImP.h> +#endif +#include <X11/Xfuncs.h> +#ifdef XAW_INTERNATIONALIZATION +#include "XawI18n.h" +#endif +#include <stdio.h> +#include <ctype.h> + +#define SrcScan XawTextSourceScan +#define FindDist XawTextSinkFindDistance +#define FindPos XawTextSinkFindPosition + +#define XawTextActionMaxHexChars 100 + +/* + * These are defined in TextPop.c + */ + +void _XawTextInsertFileAction(), _XawTextInsertFile(), _XawTextSearch(); +void _XawTextSearch(), _XawTextDoSearchAction(), _XawTextDoReplaceAction(); +void _XawTextSetField(), _XawTextPopdownSearchAction(); + +/* + * These are defined in Text.c + */ + +char * _XawTextGetText(); +void _XawTextAlterSelection(), _XawTextVScroll(); +void _XawTextSetSelection(), _XawTextCheckResize(), _XawTextExecuteUpdate(); +void _XawTextSetScrollBars(), _XawTextClearAndCenterDisplay(); +Atom * _XawTextSelectionList(); +void _XawTextPrepareToUpdate(); +int _XawTextReplace(); + +static void ParameterError(w, param) + Widget w; + String param; +{ + String params[2]; + Cardinal num_params = 2; + params[0] = XtName(w); + params[1] = param; + + XtAppWarningMsg( XtWidgetToApplicationContext(w), + "parameterError", "textAction", "XawError", + "Widget: %s Parameter: %s", + params, &num_params); + XBell( XtDisplay( w ), 50 ); +} + +static void +StartAction(ctx, event) +TextWidget ctx; +XEvent *event; +{ + _XawTextPrepareToUpdate(ctx); + if (event != NULL) { + switch (event->type) { + case ButtonPress: + case ButtonRelease: + ctx->text.time = event->xbutton.time; + break; + case KeyPress: + case KeyRelease: + ctx->text.time = event->xkey.time; + break; + case MotionNotify: + ctx->text.time = event->xmotion.time; + break; + case EnterNotify: + case LeaveNotify: + ctx->text.time = event->xcrossing.time; + } + } +} + +static void +NotePosition(ctx, event) +TextWidget ctx; +XEvent* event; +{ + switch (event->type) { + case ButtonPress: + case ButtonRelease: + ctx->text.ev_x = event->xbutton.x; + ctx->text.ev_y = event->xbutton.y; + break; + case KeyPress: + case KeyRelease: + { + XRectangle cursor; + XawTextSinkGetCursorBounds(ctx->text.sink, &cursor); + ctx->text.ev_x = cursor.x + cursor.width / 2;; + ctx->text.ev_y = cursor.y + cursor.height / 2;; + } + break; + case MotionNotify: + ctx->text.ev_x = event->xmotion.x; + ctx->text.ev_y = event->xmotion.y; + break; + case EnterNotify: + case LeaveNotify: + ctx->text.ev_x = event->xcrossing.x; + ctx->text.ev_y = event->xcrossing.y; + } +} + +static void +EndAction(ctx) +TextWidget ctx; +{ + _XawTextCheckResize(ctx); + _XawTextExecuteUpdate(ctx); + ctx->text.mult = 1; +} + + +struct _SelectionList { + String* params; + Cardinal count; + Time time; + Boolean CT_asked; /* flag if asked XA_COMPOUND_TEXT */ + Atom selection; /* selection atom when asking XA_COMPOUND_TEXT */ +}; + +static int ProbablyMB(s) + char* s; +{ + int escapes = 0; + int has_hi_bit = False; + + /* if it has more than one ESC char, I assume it is COMPOUND_TEXT. + If it has at least one hi bit set character, I pretend it is multibyte. */ + + while ( (wchar_t)(*s) != (wchar_t)0 ) { + if ( *s & 128 ) + has_hi_bit = True; + if ( *s++ == '\033' ) + escapes++; + if ( escapes >= 2 ) + return( 0 ); + } + return( has_hi_bit ); +} +static void GetSelection(); + +/* ARGSUSED */ +static void +_SelectionReceived(w, client_data, selection, type, value, length, format) +Widget w; +XtPointer client_data; +Atom *selection, *type; +XtPointer value; +unsigned long *length; +int* format; +{ + TextWidget ctx = (TextWidget)w; + XawTextBlock text; + + if (*type == 0 /*XT_CONVERT_FAIL*/ || *length == 0) { + struct _SelectionList* list = (struct _SelectionList*)client_data; + if (list != NULL) { + if (list->CT_asked) { + + /* If we just asked for a XA_COMPOUND_TEXT and got a null + response, we'll ask again, this time for an XA_STRING. */ + + list->CT_asked = False; + XtGetSelectionValue(w, list->selection, XA_STRING, _SelectionReceived, + (XtPointer)list, list->time); + } else { + GetSelection(w, list->time, list->params, list->count); + XtFree(client_data); + } + } + return; + } + + /* Many programs, especially old terminal emulators, give us multibyte text +but tell us it is COMPOUND_TEXT :( The following routine checks to see if the +string is a legal multibyte string in our locale using a spooky heuristic :O +and if it is we can only assume the sending client is using the same locale as +we are, and convert it. I also warn the user that the other client is evil. */ + + StartAction( ctx, (XEvent*) NULL ); +#ifdef XAW_INTERNATIONALIZATION + if (_XawTextFormat(ctx) == XawFmtWide) { + XTextProperty textprop; + Display *d = XtDisplay((Widget)ctx); + wchar_t **wlist; + int count; + int try_CT = 1; + + /* IS THE SELECTION IN MULTIBYTE FORMAT? */ + + if ( ProbablyMB( (char *) value ) ) { + char * list[1]; + list[0] = (char *) value; + if ( XmbTextListToTextProperty( d, (char**) list, 1, + XCompoundTextStyle, &textprop ) == Success ) + try_CT = 0; + } + + /* OR IN COMPOUND TEXT FORMAT? */ + + if ( try_CT ) { + textprop.encoding = XA_COMPOUND_TEXT(d); + textprop.value = (unsigned char *)value; + textprop.nitems = strlen(value); + textprop.format = 8; + } + + if ( XwcTextPropertyToTextList( d, &textprop, (wchar_t***) &wlist, &count ) + != Success) { + XwcFreeStringList( (wchar_t**) wlist ); + + /* Notify the user on strerr and in the insertion :) */ + textprop.value = (unsigned char *) " >> ILLEGAL SELECTION << "; + count = 1; + fprintf( stderr, "Xaw Text Widget: An attempt was made to insert an illegal selection.\n" ); + + if ( XwcTextPropertyToTextList( d, &textprop, (wchar_t***) &wlist, &count ) + != Success) return; + } + + XFree(value); + value = (XPointer)wlist[0]; + + *length = wcslen(wlist[0]); + XtFree((XtPointer)wlist); + text.format = XawFmtWide; + } else +#endif + text.format = XawFmt8Bit; + text.ptr = (char*)value; + text.firstPos = 0; + text.length = *length; + if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) { + XBell(XtDisplay(ctx), 0); + return; + } + ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstPositions, XawsdRight, text.length, TRUE); + + _XawTextSetScrollBars(ctx); + EndAction(ctx); + XtFree(client_data); + XFree(value); /* the selection value should be freed with XFree */ +} + +static void +GetSelection(w, time, params, num_params) +Widget w; +Time time; +String* params; /* selections in precedence order */ +Cardinal num_params; +{ + Atom selection; + int buffer; + + selection = XInternAtom(XtDisplay(w), *params, False); + + switch (selection) { + case XA_CUT_BUFFER0: buffer = 0; break; + case XA_CUT_BUFFER1: buffer = 1; break; + case XA_CUT_BUFFER2: buffer = 2; break; + case XA_CUT_BUFFER3: buffer = 3; break; + case XA_CUT_BUFFER4: buffer = 4; break; + case XA_CUT_BUFFER5: buffer = 5; break; + case XA_CUT_BUFFER6: buffer = 6; break; + case XA_CUT_BUFFER7: buffer = 7; break; + default: buffer = -1; + } + if (buffer >= 0) { + int nbytes; + unsigned long length; + int fmt8 = 8; + Atom type = XA_STRING; + char *line = XFetchBuffer(XtDisplay(w), &nbytes, buffer); + if ((length = nbytes)) + _SelectionReceived(w, (XtPointer) NULL, &selection, &type, (XPointer)line, + &length, &fmt8); + else if (num_params > 1) + GetSelection(w, time, params+1, num_params-1); + } else { + struct _SelectionList* list; + if (--num_params) { + list = XtNew(struct _SelectionList); + list->params = params + 1; + list->count = num_params; + list->time = time; + list->CT_asked = True; + list->selection = selection; + } else list = NULL; + XtGetSelectionValue(w, selection, XA_COMPOUND_TEXT(XtDisplay(w)), + _SelectionReceived, (XtPointer)list, time); + } +} + +static void +InsertSelection(w, event, params, num_params) +Widget w; +XEvent* event; +String* params; /* precedence list of selections to try */ +Cardinal* num_params; +{ + StartAction((TextWidget)w, event); /* Get Time. */ + GetSelection(w, ((TextWidget)w)->text.time, params, *num_params); + EndAction((TextWidget)w); +} + +/************************************************************ + * + * Routines for Moving Around. + * + ************************************************************/ + +static void +Move(ctx, event, dir, type, include) +TextWidget ctx; +XEvent* event; +XawTextScanDirection dir; +XawTextScanType type; +Boolean include; +{ + StartAction(ctx, event); + ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, + type, dir, ctx->text.mult, include); + EndAction(ctx); +} + +/*ARGSUSED*/ +static void +MoveForwardChar(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + Move((TextWidget) w, event, XawsdRight, XawstPositions, TRUE); +} + +/*ARGSUSED*/ +static void +MoveBackwardChar(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + Move((TextWidget) w, event, XawsdLeft, XawstPositions, TRUE); +} + +/*ARGSUSED*/ +static void +MoveForwardWord(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + Move((TextWidget) w, event, XawsdRight, XawstWhiteSpace, FALSE); +} + +/*ARGSUSED*/ +static void +MoveBackwardWord(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + Move((TextWidget) w, event, XawsdLeft, XawstWhiteSpace, FALSE); +} + +/*ARGSUSED*/ +static void MoveForwardParagraph(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + Move((TextWidget) w, event, XawsdRight, XawstParagraph, FALSE); +} + +/*ARGSUSED*/ +static void MoveBackwardParagraph(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + Move((TextWidget) w, event, XawsdLeft, XawstParagraph, FALSE); +} + +/*ARGSUSED*/ +static void +MoveToLineEnd(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + Move((TextWidget) w, event, XawsdRight, XawstEOL, FALSE); +} + +/*ARGSUSED*/ +static void +MoveToLineStart(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + Move((TextWidget) w, event, XawsdLeft, XawstEOL, FALSE); +} + + +static void +MoveLine(ctx, event, dir) +TextWidget ctx; +XEvent* event; +XawTextScanDirection dir; +{ + XawTextPosition new, next_line, junk; + int from_left, garbage; + + StartAction(ctx, event); + + if (dir == XawsdLeft) + ctx->text.mult++; + + new = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstEOL, XawsdLeft, 1, FALSE); + + FindDist(ctx->text.sink, new, ctx->text.margin.left, ctx->text.insertPos, + &from_left, &junk, &garbage); + + new = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, dir, + ctx->text.mult, (dir == XawsdRight)); + + next_line = SrcScan(ctx->text.source, new, XawstEOL, XawsdRight, 1, FALSE); + + FindPos(ctx->text.sink, new, ctx->text.margin.left, from_left, FALSE, + &(ctx->text.insertPos), &garbage, &garbage); + + if (ctx->text.insertPos > next_line) + ctx->text.insertPos = next_line; + + EndAction(ctx); +} + +/*ARGSUSED*/ +static void +MoveNextLine(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + MoveLine( (TextWidget) w, event, XawsdRight); +} + +/*ARGSUSED*/ +static void +MovePreviousLine(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + MoveLine( (TextWidget) w, event, XawsdLeft); +} + +/*ARGSUSED*/ +static void +MoveBeginningOfFile(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + Move((TextWidget) w, event, XawsdLeft, XawstAll, TRUE); +} + +/*ARGSUSED*/ +static void +MoveEndOfFile(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + Move((TextWidget) w, event, XawsdRight, XawstAll, TRUE); +} + +static void +Scroll(ctx, event, dir) +TextWidget ctx; +XEvent* event; +XawTextScanDirection dir; +{ + StartAction(ctx, event); + + if (dir == XawsdLeft) + _XawTextVScroll(ctx, ctx->text.mult); + else + _XawTextVScroll(ctx, -ctx->text.mult); + + EndAction(ctx); +} + +/*ARGSUSED*/ +static void +ScrollOneLineUp(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + Scroll( (TextWidget) w, event, XawsdLeft); +} + +/*ARGSUSED*/ +static void +ScrollOneLineDown(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + Scroll( (TextWidget) w, event, XawsdRight); +} + +static void +MovePage(ctx, event, dir) +TextWidget ctx; +XEvent* event; +XawTextScanDirection dir; +{ + int scroll_val = Max(1, ctx->text.lt.lines - 2); + + if (dir == XawsdLeft) + scroll_val = -scroll_val; + + StartAction(ctx, event); + _XawTextVScroll(ctx, scroll_val); + ctx->text.insertPos = ctx->text.lt.top; + EndAction(ctx); +} + +/*ARGSUSED*/ +static void +MoveNextPage(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + MovePage((TextWidget) w, event, XawsdRight); +} + +/*ARGSUSED*/ +static void +MovePreviousPage(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + MovePage((TextWidget) w, event, XawsdLeft); +} + +/************************************************************ + * + * Delete Routines. + * + ************************************************************/ + +static Boolean +MatchSelection(selection, s) + Atom selection; + XawTextSelection* s; +{ + Atom *match; + int count; + + for (count = 0, match = s->selections; count < s->atom_count; match++, count++) + if (*match == selection) + return True; + return False; +} + +#define SrcCvtSel XawTextSourceConvertSelection + +static Boolean +ConvertSelection(w, selection, target, type, value, length, format) + Widget w; + Atom *selection, *target, *type; + XtPointer* value; + unsigned long* length; + int* format; +{ + Display* d = XtDisplay(w); + TextWidget ctx = (TextWidget)w; + Widget src = ctx->text.source; + XawTextEditType edit_mode; + Arg args[1]; + XawTextSelectionSalt *salt = NULL; + XawTextSelection *s; + + if (*target == XA_TARGETS(d)) { + Atom* targetP, * std_targets; + unsigned long std_length; + + if ( SrcCvtSel(src, selection, target, type, value, length, format) ) + return True; + + XmuConvertStandardSelection(w, ctx->text.time, selection, + target, type, (XPointer*)&std_targets, + &std_length, format); + + *value = XtMalloc((unsigned) sizeof(Atom)*(std_length + 7)); + targetP = *(Atom**)value; + + *length = std_length + 6; + *targetP++ = XA_STRING; + *targetP++ = XA_TEXT(d); + *targetP++ = XA_COMPOUND_TEXT(d); + *targetP++ = XA_LENGTH(d); + *targetP++ = XA_LIST_LENGTH(d); + *targetP++ = XA_CHARACTER_POSITION(d); + + XtSetArg(args[0], XtNeditType,&edit_mode); + XtGetValues(src, args, 1); + + if (edit_mode == XawtextEdit) { + *targetP++ = XA_DELETE(d); + (*length)++; + } + memcpy((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length); + XtFree((char*)std_targets); + *type = XA_ATOM; + *format = 32; + return True; + } + + if ( SrcCvtSel(src, selection, target, type, value, length, format) ) + return True; + + for (salt = ctx->text.salt2; salt; salt = salt->next) + if (MatchSelection (*selection, &salt->s)) + break; + if (!salt) + return False; + s = &salt->s; + if (*target == XA_STRING || + *target == XA_TEXT(d) || + *target == XA_COMPOUND_TEXT(d)) { + if (*target == XA_TEXT(d)) { +#ifdef XAW_INTERNATIONALIZATION + if (_XawTextFormat(ctx) == XawFmtWide) + *type = XA_COMPOUND_TEXT(d); + else +#endif + *type = XA_STRING; + } else { + *type = *target; + } + /* + * If salt is True, the salt->contents stores CT string, + * its length is measured in bytes. + * Refer to _XawTextSaltAwaySelection(). + * + * by Li Yuhong, Mar. 20, 1991. + */ + if (!salt) { + *value = (char *)_XawTextGetSTRING(ctx, s->left, s->right); +#ifdef XAW_INTERNATIONALIZATION + if (_XawTextFormat(ctx) == XawFmtWide) { + XTextProperty textprop; + if (XwcTextListToTextProperty(d, (wchar_t**)value, 1, + XCompoundTextStyle, &textprop) + < Success) { + XtFree(*value); + return False; + } + XtFree(*value); + *value = (XtPointer)textprop.value; + *length = textprop.nitems; + } else +#endif + { + *length = strlen(*value); + } + } else { + *value = XtMalloc((salt->length + 1) * sizeof(unsigned char)); + strcpy (*value, salt->contents); + *length = salt->length; + } +#ifdef XAW_INTERNATIONALIZATION + if (_XawTextFormat(ctx) == XawFmtWide && *type == XA_STRING) { + XTextProperty textprop; + wchar_t** wlist; + int count; + textprop.encoding = XA_COMPOUND_TEXT(d); + textprop.value = (unsigned char *)*value; + textprop.nitems = strlen(*value); + textprop.format = 8; + if (XwcTextPropertyToTextList(d, &textprop, (wchar_t***)&wlist, &count) + < Success) { + XtFree(*value); + return False; + } + XtFree(*value); + if (XwcTextListToTextProperty(d, (wchar_t**)wlist, 1, + XStringStyle, &textprop) < Success) { + XwcFreeStringList( (wchar_t**) wlist ); + return False; + } + *value = (XtPointer)textprop.value; + *length = textprop.nitems; + XwcFreeStringList( (wchar_t**) wlist ); + } +#endif + *format = 8; + return True; + } + + if ( (*target == XA_LIST_LENGTH(d)) || (*target == XA_LENGTH(d)) ) { + long * temp; + + temp = (long *) XtMalloc(sizeof(long)); + if (*target == XA_LIST_LENGTH(d)) + *temp = 1L; + else /* *target == XA_LENGTH(d) */ + *temp = (long) (s->right - s->left); + + *value = (XPointer) temp; + *type = XA_INTEGER; + *length = 1L; + *format = 32; + return True; + } + + if (*target == XA_CHARACTER_POSITION(d)) { + long * temp; + + temp = (long *) XtMalloc(2 * sizeof(long)); + temp[0] = (long) (s->left + 1); + temp[1] = s->right; + *value = (XPointer) temp; + *type = XA_SPAN(d); + *length = 2L; + *format = 32; + return True; + } + + if (*target == XA_DELETE(d)) { + void _XawTextZapSelection(); /* From TextAction.c */ + + if (!salt) + _XawTextZapSelection( ctx, (XEvent *) NULL, TRUE); + *value = NULL; + *type = XA_NULL(d); + *length = 0; + *format = 32; + return True; + } + + if (XmuConvertStandardSelection(w, ctx->text.time, selection, target, type, + (XPointer *)value, length, format)) + return True; + + /* else */ + return False; +} + +static void +LoseSelection(w, selection) + Widget w; + Atom* selection; +{ + TextWidget ctx = (TextWidget) w; + Atom* atomP; + int i; + XawTextSelectionSalt *salt, *prevSalt, *nextSalt; + + prevSalt = 0; + for (salt = ctx->text.salt2; salt; salt = nextSalt) + { + atomP = salt->s.selections; + nextSalt = salt->next; + for (i = 0 ; i < salt->s.atom_count; i++, atomP++) + if (*selection == *atomP) + *atomP = (Atom)0; + + while (salt->s.atom_count && + salt->s.selections[salt->s.atom_count-1] == 0) + { + salt->s.atom_count--; + } + + /* + * Must walk the selection list in opposite order from UnsetSelection. + */ + + atomP = salt->s.selections; + for (i = 0 ; i < salt->s.atom_count; i++, atomP++) + if (*atomP == (Atom)0) + { + *atomP = salt->s.selections[--salt->s.atom_count]; + while (salt->s.atom_count && + salt->s.selections[salt->s.atom_count-1] == 0) + salt->s.atom_count--; + } + if (salt->s.atom_count == 0) + { + XtFree ((char *) salt->s.selections); + + /* WARNING: the next line frees memory not allocated in Xaw. */ + /* Could be a serious bug. Someone look into it. */ + XtFree (salt->contents); + if (prevSalt) + prevSalt->next = nextSalt; + else + ctx->text.salt2 = nextSalt; + XtFree ((char *) salt); + } + else + prevSalt = salt; + } +} + +static void +_DeleteOrKill(ctx, from, to, kill) +TextWidget ctx; +XawTextPosition from, to; +Boolean kill; +{ + XawTextBlock text; + + if (kill && from < to) { + XawTextSelectionSalt *salt; + Atom selection = XInternAtom(XtDisplay(ctx), "SECONDARY", False); + + LoseSelection ((Widget) ctx, &selection); + salt = (XawTextSelectionSalt *) XtMalloc (sizeof (XawTextSelectionSalt)); + if (!salt) + return; + salt->s.selections = (Atom *) XtMalloc (sizeof (Atom)); + if (!salt->s.selections) + { + XtFree ((char *) salt); + return; + } + salt->s.left = from; + salt->s.right = to; + salt->contents = (char *)_XawTextGetSTRING(ctx, from, to); +#ifdef XAW_INTERNATIONALIZATION + if (_XawTextFormat(ctx) == XawFmtWide) { + XTextProperty textprop; + if (XwcTextListToTextProperty(XtDisplay((Widget)ctx), + (wchar_t**)(&(salt->contents)), 1, XCompoundTextStyle, + &textprop) < Success) { + XtFree(salt->contents); + salt->length = 0; + return; + } + XtFree(salt->contents); + salt->contents = (char *)textprop.value; + salt->length = textprop.nitems; + } else +#endif + salt->length = strlen (salt->contents); + salt->next = ctx->text.salt2; + ctx->text.salt2 = salt; + salt->s.selections[0] = selection; + XtOwnSelection ((Widget) ctx, selection, ctx->text.time, + ConvertSelection, LoseSelection, NULL); + salt->s.atom_count = 1; +/* + XStoreBuffer(XtDisplay(ctx), ptr, strlen(ptr), 1); + XtFree(ptr); +*/ + } + text.length = 0; + text.firstPos = 0; + + text.format = _XawTextFormat(ctx); + text.ptr = ""; /* These two lines needed to make legal TextBlock */ + + if (_XawTextReplace(ctx, from, to, &text)) { + XBell(XtDisplay(ctx), 50); + return; + } + ctx->text.insertPos = from; + ctx->text.showposition = TRUE; +} + +static void +DeleteOrKill(ctx, event, dir, type, include, kill) +TextWidget ctx; +XEvent* event; +XawTextScanDirection dir; +XawTextScanType type; +Boolean include, kill; +{ + XawTextPosition from, to; + + StartAction(ctx, event); + to = SrcScan(ctx->text.source, ctx->text.insertPos, + type, dir, ctx->text.mult, include); + +/* + * If no movement actually happened, then bump the count and try again. + * This causes the character position at the very beginning and end of + * a boundary to act correctly. + */ + + if (to == ctx->text.insertPos) + to = SrcScan(ctx->text.source, ctx->text.insertPos, + type, dir, ctx->text.mult + 1, include); + + if (dir == XawsdLeft) { + from = to; + to = ctx->text.insertPos; + } + else + from = ctx->text.insertPos; + + _DeleteOrKill(ctx, from, to, kill); + _XawTextSetScrollBars(ctx); + EndAction(ctx); +} + +/*ARGSUSED*/ +static void +DeleteForwardChar(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + DeleteOrKill((TextWidget) w, event, XawsdRight, XawstPositions, TRUE, FALSE); +} + +/*ARGSUSED*/ +static void +DeleteBackwardChar(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + DeleteOrKill((TextWidget) w, event, XawsdLeft, XawstPositions, TRUE, FALSE); +} + +/*ARGSUSED*/ +static void +DeleteForwardWord(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + DeleteOrKill((TextWidget) w, event, + XawsdRight, XawstWhiteSpace, FALSE, FALSE); +} + +/*ARGSUSED*/ +static void +DeleteBackwardWord(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + DeleteOrKill((TextWidget) w, event, + XawsdLeft, XawstWhiteSpace, FALSE, FALSE); +} + +/*ARGSUSED*/ +static void +KillForwardWord(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + DeleteOrKill((TextWidget) w, event, + XawsdRight, XawstWhiteSpace, FALSE, TRUE); +} + +/*ARGSUSED*/ +static void +KillBackwardWord(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + DeleteOrKill((TextWidget) w, event, + XawsdLeft, XawstWhiteSpace, FALSE, TRUE); +} + +/*ARGSUSED*/ +static void +KillToEndOfLine(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + TextWidget ctx = (TextWidget) w; + XawTextPosition end_of_line; + + StartAction(ctx, event); + end_of_line = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, + XawsdRight, ctx->text.mult, FALSE); + if (end_of_line == ctx->text.insertPos) + end_of_line = SrcScan(ctx->text.source, ctx->text.insertPos, XawstEOL, + XawsdRight, ctx->text.mult, TRUE); + + _DeleteOrKill(ctx, ctx->text.insertPos, end_of_line, TRUE); + _XawTextSetScrollBars(ctx); + EndAction(ctx); +} + +/*ARGSUSED*/ +static void +KillToEndOfParagraph(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + DeleteOrKill((TextWidget) w, event, XawsdRight, XawstParagraph, FALSE, TRUE); +} + +void +_XawTextZapSelection(ctx, event, kill) +TextWidget ctx; +XEvent* event; +Boolean kill; +{ + StartAction(ctx, event); + _DeleteOrKill(ctx, ctx->text.s.left, ctx->text.s.right, kill); + _XawTextSetScrollBars(ctx); + EndAction(ctx); +} + +/*ARGSUSED*/ +static void +KillCurrentSelection(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + _XawTextZapSelection( (TextWidget) w, event, TRUE); +} + +/*ARGSUSED*/ +static void +DeleteCurrentSelection(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + _XawTextZapSelection( (TextWidget) w, event, FALSE); +} + +/************************************************************ + * + * Insertion Routines. + * + ************************************************************/ + +static int +InsertNewLineAndBackupInternal(ctx) +TextWidget ctx; +{ + int count, error = XawEditDone; + XawTextBlock text; + + text.format = _XawTextFormat(ctx); + text.length = ctx->text.mult; + text.firstPos = 0; + +#ifdef XAW_INTERNATIONALIZATION + if ( text.format == XawFmtWide ) { + wchar_t* wptr; + text.ptr = XtMalloc(sizeof(wchar_t) * ctx->text.mult); + wptr = (wchar_t *)text.ptr; + for (count = 0; count < ctx->text.mult; count++ ) + wptr[count] = _Xaw_atowc(XawLF); + } + else +#endif + { + text.ptr = XtMalloc(sizeof(char) * ctx->text.mult); + for (count = 0; count < ctx->text.mult; count++ ) + text.ptr[count] = XawLF; + } + + if (_XawTextReplace(ctx, ctx->text.insertPos, ctx->text.insertPos, &text)) { + XBell( XtDisplay(ctx), 50); + error = XawEditError; + } + else + ctx->text.showposition = TRUE; + + XtFree( text.ptr ); + return( error ); +} + +/*ARGSUSED*/ +static void +InsertNewLineAndBackup(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + StartAction( (TextWidget) w, event ); + (void) InsertNewLineAndBackupInternal( (TextWidget) w ); + _XawTextSetScrollBars( (TextWidget) w); + EndAction( (TextWidget) w ); +} + +static int +LocalInsertNewLine(ctx, event) + TextWidget ctx; + XEvent* event; +{ + StartAction(ctx, event); + if (InsertNewLineAndBackupInternal(ctx) == XawEditError) + return(XawEditError); + ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstPositions, XawsdRight, ctx->text.mult, TRUE); + _XawTextSetScrollBars(ctx); + EndAction(ctx); + return(XawEditDone); +} + +/*ARGSUSED*/ +static void +InsertNewLine(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + (void) LocalInsertNewLine( (TextWidget) w, event); +} + +/*ARGSUSED*/ +static void +InsertNewLineAndIndent(w, event, p, n) +Widget w; +XEvent *event; +String *p; +Cardinal *n; +{ + XawTextBlock text; + XawTextPosition pos1; + int length; + TextWidget ctx = (TextWidget) w; + String line_to_ip; + + StartAction(ctx, event); + pos1 = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstEOL, XawsdLeft, 1, FALSE); + + line_to_ip = _XawTextGetText(ctx, pos1, ctx->text.insertPos); + + text.format = _XawTextFormat(ctx); + text.firstPos = 0; + +#ifdef XAW_INTERNATIONALIZATION + if ( text.format == XawFmtWide ) { + wchar_t* ptr; + text.ptr = XtMalloc( ( 2 + wcslen((wchar_t*)line_to_ip) ) * sizeof(wchar_t) ); + + ptr = (wchar_t*)text.ptr; + ptr[0] = _Xaw_atowc( XawLF ); + wcscpy( (wchar_t*) ++ptr, (wchar_t*) line_to_ip ); + + length = wcslen((wchar_t*)text.ptr); + while ( length && ( iswspace(*ptr) || ( *ptr == _Xaw_atowc(XawTAB) ) ) ) + ptr++, length--; + *ptr = (wchar_t)0; + text.length = wcslen((wchar_t*)text.ptr); + + } else +#endif + { + char *ptr; + length = strlen(line_to_ip); + /* The current line + \0 and LF will be copied to this + buffer. Before my fix, only length + 1 bytes were + allocated, causing on machine with non-wasteful + malloc implementation segmentation violations by + overwriting the bypte after the allocated area + + -gustaf neumann + */ + text.ptr = XtMalloc( ( 2 + length ) * sizeof( char ) ); + + ptr = text.ptr; + ptr[0] = XawLF; + strcpy( ++ptr, line_to_ip ); + + length++; + while ( length && ( isspace(*ptr) || ( *ptr == XawTAB ) ) ) + ptr++, length--; + *ptr = '\0'; + text.length = strlen(text.ptr); + } + XtFree( line_to_ip ); + + if (_XawTextReplace(ctx,ctx->text.insertPos, ctx->text.insertPos, &text)) { + XBell(XtDisplay(ctx), 50); + XtFree(text.ptr); + EndAction(ctx); + return; + } + XtFree(text.ptr); + ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstPositions, XawsdRight, text.length, TRUE); + _XawTextSetScrollBars(ctx); + EndAction(ctx); +} + +/************************************************************ + * + * Selection Routines. + * + *************************************************************/ + +static void +SelectWord(w, event, params, num_params) +Widget w; +XEvent* event; +String* params; +Cardinal* num_params; +{ + TextWidget ctx = (TextWidget) w; + XawTextPosition l, r; + + StartAction(ctx, event); + l = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstWhiteSpace, XawsdLeft, 1, FALSE); + r = SrcScan(ctx->text.source, l, XawstWhiteSpace, XawsdRight, 1, FALSE); + _XawTextSetSelection(ctx, l, r, params, *num_params); + EndAction(ctx); +} + +static void +SelectAll(w, event, params, num_params) +Widget w; +XEvent* event; +String* params; +Cardinal* num_params; +{ + TextWidget ctx = (TextWidget) w; + + StartAction(ctx, event); + _XawTextSetSelection(ctx,zeroPosition,ctx->text.lastPos,params,*num_params); + EndAction(ctx); +} + +static void +ModifySelection(ctx, event, mode, action, params, num_params) +TextWidget ctx; +XEvent* event; +XawTextSelectionMode mode; +XawTextSelectionAction action; +String* params; /* unused */ +Cardinal* num_params; /* unused */ +{ + StartAction(ctx, event); + NotePosition(ctx, event); + _XawTextAlterSelection(ctx, mode, action, params, num_params); + EndAction(ctx); +} + +/* ARGSUSED */ +static void +SelectStart(w, event, params, num_params) +Widget w; +XEvent* event; +String* params; /* unused */ +Cardinal* num_params; /* unused */ +{ + ModifySelection((TextWidget) w, event, + XawsmTextSelect, XawactionStart, params, num_params); +} + +/* ARGSUSED */ +static void +SelectAdjust(w, event, params, num_params) +Widget w; +XEvent* event; +String* params; /* unused */ +Cardinal* num_params; /* unused */ +{ + ModifySelection((TextWidget) w, event, + XawsmTextSelect, XawactionAdjust, params, num_params); +} + +static void +SelectEnd(w, event, params, num_params) +Widget w; +XEvent* event; +String* params; +Cardinal* num_params; +{ + ModifySelection((TextWidget) w, event, + XawsmTextSelect, XawactionEnd, params, num_params); +} + +/* ARGSUSED */ +static void +ExtendStart(w, event, params, num_params) +Widget w; +XEvent* event; +String* params; /* unused */ +Cardinal* num_params; /* unused */ +{ + ModifySelection((TextWidget) w, event, + XawsmTextExtend, XawactionStart, params, num_params); +} + +/* ARGSUSED */ +static void +ExtendAdjust(w, event, params, num_params) +Widget w; +XEvent* event; +String* params; /* unused */ +Cardinal* num_params; /* unused */ +{ + ModifySelection((TextWidget) w, event, + XawsmTextExtend, XawactionAdjust, params, num_params); +} + +static void +ExtendEnd(w, event, params, num_params) +Widget w; +XEvent* event; +String* params; +Cardinal* num_params; +{ + ModifySelection((TextWidget) w, event, + XawsmTextExtend, XawactionEnd, params, num_params); +} + +static void +SelectSave(w, event, params, num_params) +Widget w; +XEvent* event; +String* params; +Cardinal* num_params; +{ + int num_atoms; + Atom* sel; + Display* dpy = XtDisplay(w); + Atom selections[256]; + + StartAction( (TextWidget) w, event ); + num_atoms = *num_params; + if (num_atoms > 256) + num_atoms = 256; + for (sel=selections; --num_atoms >= 0; sel++, params++) + *sel = XInternAtom(dpy, *params, False); + num_atoms = *num_params; + _XawTextSaltAwaySelection( (TextWidget) w, selections, num_atoms ); + EndAction( (TextWidget) w ); +} + +/************************************************************ + * + * Misc. Routines. + * + ************************************************************/ + +/* ARGSUSED */ +static void +RedrawDisplay(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + StartAction( (TextWidget) w, event); + _XawTextClearAndCenterDisplay((TextWidget) w); + EndAction( (TextWidget) w); +} + +/*ARGSUSED*/ +static void +TextFocusIn (w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + TextWidget ctx = (TextWidget) w; + + /* Let the input method know focus has arrived. */ +#ifdef XAW_INTERNATIONALIZATION + _XawImSetFocusValues (w, NULL, 0); +#endif + if ( event->xfocus.detail == NotifyPointer ) return; + + ctx->text.hasfocus = TRUE; +} + +/*ARGSUSED*/ +static void +TextFocusOut(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + TextWidget ctx = (TextWidget) w; + + /* Let the input method know focus has left.*/ +#ifdef XAW_INTERNATIONALIZATION + _XawImUnsetFocus(w); +#endif + if ( event->xfocus.detail == NotifyPointer ) return; + ctx->text.hasfocus = FALSE; +} + +/*ARGSUSED*/ +static void +TextEnterWindow( w, event, params, num_params ) + Widget w; + XEvent* event; + String* params; + Cardinal* num_params; +{ + TextWidget ctx = (TextWidget) w; + +#ifdef XAW_INTERNATIONALIZATION + if ((event->xcrossing.detail != NotifyInferior) && event->xcrossing.focus && + !ctx->text.hasfocus) { + _XawImSetFocusValues(w, NULL, 0); + } +#endif +} + +/*ARGSUSED*/ +static void +TextLeaveWindow( w, event, params, num_params ) + Widget w; + XEvent* event; + String* params; + Cardinal* num_params; +{ + TextWidget ctx = (TextWidget) w; + +#ifdef XAW_INTERNATIONALIZATION + if ((event->xcrossing.detail != NotifyInferior) && event->xcrossing.focus && + !ctx->text.hasfocus) { + _XawImUnsetFocus(w); + } +#endif +} + +static XComposeStatus compose_status = {NULL, 0}; + +/* Function Name: AutoFill + * Description: Breaks the line at the previous word boundry when + * called inside InsertChar. + * Arguments: ctx - The text widget. + * Returns: none + */ + +static void +AutoFill(ctx) +TextWidget ctx; +{ + int width, height, x, line_num, max_width; + XawTextPosition ret_pos; + XawTextBlock text; + + if ( !((ctx->text.auto_fill) && (ctx->text.mult == 1)) ) + return; + + for ( line_num = 0; line_num < ctx->text.lt.lines ; line_num++) + if ( ctx->text.lt.info[line_num].position >= ctx->text.insertPos ) + break; + line_num--; /* backup a line. */ + + max_width = Max(0, (int)(ctx->core.width - HMargins(ctx))); + + x = ctx->text.margin.left; + XawTextSinkFindPosition( ctx->text.sink,ctx->text.lt.info[line_num].position, + x, max_width, TRUE, &ret_pos, &width, &height); + + if ( ret_pos >= ctx->text.insertPos ) + return; + + text.format = XawFmt8Bit; +#ifdef XAW_INTERNATIONALIZATION + if (_XawTextFormat(ctx) == XawFmtWide) { + text.format = XawFmtWide; + text.ptr = (char *)XtMalloc(sizeof(wchar_t) * 2); + ((wchar_t*)text.ptr)[0] = _Xaw_atowc(XawLF); + ((wchar_t*)text.ptr)[1] = 0; + } else +#endif + text.ptr = "\n"; + text.length = 1; + text.firstPos = 0; + + if (_XawTextReplace(ctx, ret_pos - 1, ret_pos, &text)) + XBell(XtDisplay((Widget) ctx), 0); /* Unable to edit, complain. */ +} + +/*ARGSUSED*/ +static void +InsertChar(w, event, p, n) +Widget w; +XEvent* event; +String* p; +Cardinal* n; +{ + TextWidget ctx = (TextWidget) w; + char *ptr, strbuf[BUFSIZ]; + int count, error; + KeySym keysym; + XawTextBlock text; + +#ifdef XAW_INTERNATIONALIZATION + if (XtIsSubclass (ctx->text.source, (WidgetClass) multiSrcObjectClass)) + text.length = _XawImWcLookupString (w, &event->xkey, + (wchar_t*) strbuf, BUFSIZ, &keysym, (Status*) &compose_status); + else +#endif + text.length = XLookupString ((XKeyEvent*)event, strbuf, BUFSIZ, &keysym, &compose_status); + + if (text.length == 0) + return; + + text.format = _XawTextFormat( ctx ); +#ifdef XAW_INTERNATIONALIZATION + if ( text.format == XawFmtWide ) { + text.ptr = ptr = XtMalloc(sizeof(wchar_t) * text.length * ctx->text.mult ); + for (count = 0; count < ctx->text.mult; count++ ) { + memcpy((char*) ptr, (char *)strbuf, sizeof(wchar_t) * text.length ); + ptr += sizeof(wchar_t) * text.length; + } + + } else +#endif + { /* == XawFmt8Bit */ + text.ptr = ptr = XtMalloc( sizeof(char) * text.length * ctx->text.mult ); + for ( count = 0; count < ctx->text.mult; count++ ) { + strncpy( ptr, strbuf, text.length ); + ptr += text.length; + } + } + + text.length = text.length * ctx->text.mult; + text.firstPos = 0; + + StartAction(ctx, event); + + error = _XawTextReplace(ctx, ctx->text.insertPos,ctx->text.insertPos, &text); + + if (error == XawEditDone) { + ctx->text.insertPos = SrcScan(ctx->text.source, ctx->text.insertPos, + XawstPositions, XawsdRight, text.length, TRUE); + AutoFill(ctx); + } + else + XBell(XtDisplay(ctx), 50); + + XtFree(text.ptr); + _XawTextSetScrollBars(ctx); + EndAction(ctx); +} + + +/* IfHexConvertHexElseReturnParam() - called by InsertString + * + * i18n requires the ability to specify multiple characters in a hexa- + * decimal string at once. Since Insert was already too long, I made + * this a seperate routine. + * + * A legal hex string in MBNF: '0' 'x' ( HEX-DIGIT HEX-DIGIT )+ '\0' + * + * WHEN: the passed param is a legal hex string + * RETURNS: a pointer to that converted, null terminated hex string; + * len_return holds the character count of conversion result + * + * WHEN: the passed param is not a legal hex string: + * RETURNS: the parameter passed; + * len_return holds the char count of param. + * + * NOTE: In neither case will there be strings to free. */ + +static char* +IfHexConvertHexElseReturnParam(param, len_return) + char* param; + int* len_return; +{ + char *p; /* steps through param char by char */ + char c; /* holds the character pointed to by p */ + + int ind; /* steps through hexval buffer char by char */ + static char hexval[ XawTextActionMaxHexChars ]; + Boolean first_digit; + + /* reject if it doesn't begin with 0x and at least one more character. */ + + if ( ( param[0] != '0' ) || ( param[1] != 'x' ) || ( param[2] == '\0' ) ) { + *len_return = strlen( param ); + return( param ); + } + + /* Skip the 0x; go character by character shifting and adding. */ + + first_digit = True; + ind = 0; + hexval[ ind ] = '\0'; + + for ( p = param+2; ( c = *p ); p++ ) { + hexval[ ind ] *= 16; + if (c >= '0' && c <= '9') + hexval[ ind ] += c - '0'; + else if (c >= 'a' && c <= 'f') + hexval[ ind ] += c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + hexval[ ind ] += c - 'A' + 10; + else break; + + /* If we didn't break in preceding line, it was a good hex char. */ + + if ( first_digit ) + first_digit = False; + else { + first_digit = True; + if ( ++ind < XawTextActionMaxHexChars ) + hexval[ ind ] = '\0'; + else { + *len_return = strlen( param ); + return( param ); + } + } + } + + /* We quit the above loop becasue we hit a non hex. If that char is \0... */ + + if ( ( c == '\0' ) && first_digit ) { + *len_return = strlen( hexval ); + return( hexval ); /* ...it was a legal hex string, so return it.*/ + } + + /* Else, there were non-hex chars or odd digit count, so... */ + + *len_return = strlen( param ); + return( param ); /* ...return the verbatim string. */ +} + + +/* InsertString() - action + * + * Mostly rewritten for R6 i18n. + * + * Each parameter, in turn, will be insert at the inputPos + * and the inputPos advances to the insertion's end. + * + * The exception is that parameters composed of the two + * characters 0x, followed only by an even number of + * hexadecimal digits will be converted to characters. */ + +/*ARGSUSED*/ +static void +InsertString(w, event, params, num_params) +Widget w; +XEvent* event; +String* params; +Cardinal* num_params; +{ + TextWidget ctx = (TextWidget) w; + XtAppContext app_con = XtWidgetToApplicationContext(w); + XawTextBlock text; + int i; + + text.firstPos = 0; + text.format = _XawTextFormat( ctx ); + + StartAction(ctx, event); + for ( i = *num_params; i; i--, params++ ) { /* DO FOR EACH PARAMETER */ + + text.ptr = IfHexConvertHexElseReturnParam( *params, &text.length ); + + if ( text.length == 0 ) continue; + +#ifdef XAW_INTERNATIONALIZATION + if ( _XawTextFormat( ctx ) == XawFmtWide ) { /* convert to WC */ + + int temp_len; + text.ptr = (char*) _XawTextMBToWC( XtDisplay(w), text.ptr, + &text.length ); + + if ( text.ptr == NULL ) { /* conversion error */ + XtAppWarningMsg( app_con, + "insertString", "textAction", "XawError", + "insert-string()'s parameter contents not legal in this locale.", + NULL, NULL ); + ParameterError( w, *params ); + continue; + } + + /* Double check that the new input is legal: try to convert to MB. */ + + temp_len = text.length; /* _XawTextWCToMB's 3rd arg is in_out */ + if ( _XawTextWCToMB( XtDisplay(w), (wchar_t*)text.ptr, &temp_len ) == NULL ) { + XtAppWarningMsg( app_con, + "insertString", "textAction", "XawError", + "insert-string()'s parameter contents not legal in this locale.", + NULL, NULL ); + ParameterError( w, *params ); + continue; + } + } /* convert to WC */ +#endif + + if ( _XawTextReplace( ctx, ctx->text.insertPos, + ctx->text.insertPos, &text ) ) { + XBell( XtDisplay( ctx ), 50 ); + EndAction( ctx ); + return; + } + + /* Advance insertPos to the end of the string we just inserted. */ + ctx->text.insertPos = SrcScan( ctx->text.source, ctx->text.insertPos, + XawstPositions, XawsdRight, text.length, TRUE ); + + } /* DO FOR EACH PARAMETER */ + + EndAction( ctx ); +} + + +/* DisplayCaret() - action + * + * The parameter list should contain one boolean value. If the + * argument is true, the cursor will be displayed. If false, not. + * + * The exception is that EnterNotify and LeaveNotify events may + * have a second argument, "always". If they do not, the cursor + * is only affected if the focus member of the event is true. */ + +static void +DisplayCaret(w, event, params, num_params) +Widget w; +XEvent* event; /* CrossingNotify special-cased */ +String* params; /* Off, False, No, On, True, Yes, etc. */ +Cardinal* num_params; /* 0, 1 or 2 */ +{ + TextWidget ctx = (TextWidget)w; + Boolean display_caret = True; + + if ( ( event->type == EnterNotify || event->type == LeaveNotify ) && + ( ( *num_params >= 2 ) && ( strcmp( params[1], "always" ) == 0 ) ) && + ( !event->xcrossing.focus ) ) + return; + + if (*num_params > 0) { /* default arg is "True" */ + XrmValue from, to; + from.size = strlen(from.addr = params[0]); + XtConvert( w, XtRString, &from, XtRBoolean, &to ); + + if ( to.addr != NULL ) + display_caret = *(Boolean*)to.addr; + if ( ctx->text.display_caret == display_caret ) + return; + } + StartAction(ctx, event); + ctx->text.display_caret = display_caret; + EndAction(ctx); +} + + +/* Multiply() - action + * + * The parameter list may contain either a number or the string 'Reset'. + * + * A number will multiply the current multiplication factor by that number. + * Many of the text widget actions will will perform n actions, where n is + * the multiplication factor. + * + * The string reset will reset the mutiplication factor to 1. */ + +/* ARGSUSED */ +static void +Multiply(w, event, params, num_params) +Widget w; +XEvent* event; +String* params; +Cardinal* num_params; +{ + TextWidget ctx = (TextWidget) w; + int mult; + + if (*num_params != 1) { + XtAppError( XtWidgetToApplicationContext( w ), + "Xaw Text Widget: multiply() takes exactly one argument."); + XBell( XtDisplay( w ), 0 ); + return; + } + + if ( ( params[0][0] == 'r' ) || ( params[0][0] == 'R' ) ) { + XBell( XtDisplay( w ), 0 ); + ctx->text.mult = 1; + return; + } + + if ( ( mult = atoi( params[0] ) ) == 0 ) { + char buf[ BUFSIZ ]; + sprintf(buf, "%s %s", "Xaw Text Widget: multiply() argument", + "must be a number greater than zero, or 'Reset'." ); + XtAppError( XtWidgetToApplicationContext( w ), buf ); + XBell( XtDisplay( w ), 50 ); + return; + } + + ctx->text.mult *= mult; +} + + +/* StripOutOldCRs() - called from FormRegion + * + * removes CRs in widget ctx, from from to to. + * + * RETURNS: the new ending location (we may add some characters), + * or XawReplaceError if the widget can't be written to. */ + +static XawTextPosition +StripOutOldCRs(ctx, from, to) +TextWidget ctx; +XawTextPosition from, to; +{ + XawTextPosition startPos, endPos, eop_begin, eop_end, temp; + Widget src = ctx->text.source; + XawTextBlock text; + char *buf; + static wchar_t wc_two_spaces[ 3 ]; + + /* Initialize our TextBlock with two spaces. */ + + text.firstPos = 0; + text.format = _XawTextFormat(ctx); + if ( text.format == XawFmt8Bit ) + text.ptr= " "; +#ifdef XAW_INTERNATIONALIZATION + else { + wc_two_spaces[0] = _Xaw_atowc(XawSP); + wc_two_spaces[1] = _Xaw_atowc(XawSP); + wc_two_spaces[2] = 0; + text.ptr = (char*) wc_two_spaces; + } +#endif + + /* Strip out CR's. */ + + eop_begin = eop_end = startPos = endPos = from; + /* CONSTCOND */ + while (TRUE) { + endPos=SrcScan(src, startPos, XawstEOL, XawsdRight, 1, FALSE); + + temp = SrcScan(src, endPos, XawstWhiteSpace, XawsdLeft, 1, FALSE); + temp = SrcScan(src, temp, XawstWhiteSpace, XawsdRight,1, FALSE); + + if (temp > startPos) + endPos = temp; + + if (endPos >= to) + break; + + if (endPos >= eop_begin) { + startPos = eop_end; + eop_begin=SrcScan(src, startPos, XawstParagraph, XawsdRight, 1,FALSE); + eop_end = SrcScan(src, startPos, XawstParagraph, XawsdRight, 1, TRUE); + } + else { + XawTextPosition periodPos, next_word; + int i, len; + + periodPos= SrcScan(src, endPos, XawstPositions, XawsdLeft, 1, TRUE); + next_word = SrcScan(src, endPos, XawstWhiteSpace, XawsdRight, 1, FALSE); + + len = next_word - periodPos; + + text.length = 1; + buf = _XawTextGetText(ctx, periodPos, next_word); +#ifdef XAW_INTERNATIONALIZATION + if (text.format == XawFmtWide) { + if ( (periodPos < endPos) && (((wchar_t*)buf)[0] == _Xaw_atowc('.'))) + text.length++; + } else +#endif + if ( (periodPos < endPos) && (buf[0] == '.') ) + text.length++; /* Put in two spaces. */ + + /* + * Remove all extra spaces. + */ + + for (i = 1 ; i < len; i++) +#ifdef XAW_INTERNATIONALIZATION + if (text.format == XawFmtWide) { + if ( !iswspace(((wchar_t*)buf)[i]) || ((periodPos + i) >= to) ) { + break; + } + } else +#endif + if ( !isspace(buf[i]) || ((periodPos + i) >= to) ) { + break; + } + + XtFree(buf); + + to -= (i - text.length - 1); + startPos = SrcScan(src, periodPos, XawstPositions, XawsdRight, i, TRUE); + if (_XawTextReplace(ctx, endPos, startPos, &text) != XawEditDone) + return XawReplaceError; + startPos -= i - text.length; + } + } + return(to); +} + + +/* InsertNewCRs() - called from FormRegion + * + * inserts new CRs for FormRegion, thus for FormParagraph action */ + +static void +InsertNewCRs(ctx, from, to) +TextWidget ctx; +XawTextPosition from, to; +{ + XawTextPosition startPos, endPos, space, eol; + XawTextBlock text; + int i, width, height, len; + char * buf; + static wchar_t wide_CR[ 2 ]; + + text.firstPos = 0; + text.length = 1; + text.format = _XawTextFormat( ctx ); + + if ( text.format == XawFmt8Bit ) + text.ptr = "\n"; +#ifdef XAW_INTERNATIONALIZATION + else { + wide_CR[0] = _Xaw_atowc(XawLF); + wide_CR[1] = 0; + text.ptr = (char*) wide_CR; + } +#endif + + startPos = from; + /* CONSTCOND */ + while (TRUE) { + XawTextSinkFindPosition( ctx->text.sink, startPos, + (int) ctx->text.margin.left, + (int) (ctx->core.width - HMargins(ctx)), + TRUE, &eol, &width, &height); + if (eol >= to) + break; + + eol = SrcScan(ctx->text.source, eol, XawstPositions, XawsdLeft, 1, TRUE); + space= SrcScan(ctx->text.source, eol, XawstWhiteSpace,XawsdRight,1, TRUE); + + startPos = endPos = eol; + if (eol == space) + return; + + len = (int) (space - eol); + buf = _XawTextGetText(ctx, eol, space); + for ( i = 0 ; i < len ; i++) +#ifdef XAW_INTERNATIONALIZATION + if (text.format == XawFmtWide) { + if (!iswspace(((wchar_t*)buf)[i])) + break; + } else +#endif + if (!isspace(buf[i])) + break; + + to -= (i - 1); + endPos = SrcScan(ctx->text.source, endPos, + XawstPositions, XawsdRight, i, TRUE); + XtFree(buf); + + if (_XawTextReplace(ctx, startPos, endPos, &text)) + return; + + startPos = SrcScan(ctx->text.source, startPos, + XawstPositions, XawsdRight, 1, TRUE); + } +} + + +/* FormRegion() - called by FormParagraph + * + * oversees the work of paragraph-forming a region + * + * RETURNS: XawEditDone if successful, or XawReplaceError. */ + +static int +FormRegion(ctx, from, to) +TextWidget ctx; +XawTextPosition from, to; +{ + if ( from >= to ) return XawEditDone; + + if ( ( to = StripOutOldCRs( ctx, from, to ) ) == XawReplaceError ) + return XawReplaceError; + + /* insure that the insertion point is within legal bounds */ + if ( ctx->text.insertPos > SrcScan( ctx->text.source, 0, + XawstAll, XawsdRight, 1, TRUE ) ) + ctx->text.insertPos = to; + + InsertNewCRs(ctx, from, to); + _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE); + return XawEditDone; +} + + +/* FormParagraph() - action + * + * removes and reinserts CRs to maximize line length without clipping */ + +/* ARGSUSED */ +static void +FormParagraph(w, event, params, num_params) +Widget w; +XEvent* event; +String* params; +Cardinal* num_params; +{ + TextWidget ctx = (TextWidget) w; + XawTextPosition from, to; + + StartAction(ctx, event); + + from = SrcScan( ctx->text.source, ctx->text.insertPos, + XawstParagraph, XawsdLeft, 1, FALSE ); + to = SrcScan( ctx->text.source, from, + XawstParagraph, XawsdRight, 1, FALSE ); + + if ( FormRegion( ctx, from, to ) == XawReplaceError ) + XBell( XtDisplay( w ), 0 ); + _XawTextSetScrollBars( ctx ); + EndAction( ctx ); +} + + +/* TransposeCharacters() - action + * + * Swaps the character to the left of the mark + * with the character to the right of the mark. */ + +/* ARGSUSED */ +static void +TransposeCharacters(w, event, params, num_params) +Widget w; +XEvent* event; +String* params; +Cardinal* num_params; +{ + TextWidget ctx = (TextWidget) w; + XawTextPosition start, end; + XawTextBlock text; + char* buf; + int i; + + StartAction(ctx, event); + + /* Get bounds. */ + + start = SrcScan( ctx->text.source, ctx->text.insertPos, XawstPositions, + XawsdLeft, 1, TRUE ); + end = SrcScan( ctx->text.source, ctx->text.insertPos, XawstPositions, + XawsdRight, ctx->text.mult, TRUE ); + + /* Make sure we aren't at the very beginning or end of the buffer. */ + + if ( ( start == ctx->text.insertPos ) || ( end == ctx->text.insertPos ) ) { + XBell( XtDisplay( w ), 0 ); /* complain. */ + EndAction( ctx ); + return; + } + + ctx->text.insertPos = end; + + text.firstPos = 0; + text.format = _XawTextFormat(ctx); + + /* Retrieve text and swap the characters. */ + +#ifdef XAW_INTERNATIONALIZATION + if ( text.format == XawFmtWide) { + wchar_t wc; + wchar_t* wbuf; + + wbuf = (wchar_t*) _XawTextGetText(ctx, start, end); + text.length = wcslen( wbuf ); + wc = wbuf[ 0 ]; + for ( i = 1; i < text.length; i++ ) + wbuf[ i-1 ] = wbuf[ i ]; + wbuf[ i-1 ] = wc; + buf = (char*) wbuf; /* so that it gets assigned and freed */ + + } else +#endif + { /* thus text.format == XawFmt8Bit */ + char c; + buf = _XawTextGetText( ctx, start, end ); + text.length = strlen( buf ); + c = buf[ 0 ]; + for ( i = 1; i < text.length; i++ ) + buf[ i-1 ] = buf[ i ]; + buf[ i-1 ] = c; + } + + text.ptr = buf; + + /* Store new text in source. */ + + if (_XawTextReplace (ctx, start, end, &text)) /* Unable to edit, complain. */ + XBell(XtDisplay(w), 0); + XtFree((char *) buf); + EndAction(ctx); +} + + +/* NoOp() - action + * This action performs no action, and allows the user or + * application programmer to unbind a translation. + * + * Note: If the parameter list contains the string "RingBell" then + * this action will ring the bell. + */ + +/*ARGSUSED*/ +static void +NoOp(w, event, params, num_params) +Widget w; +XEvent* event; +String* params; +Cardinal* num_params; +{ + if (*num_params != 1) + return; + + switch(params[0][0]) { + case 'R': + case 'r': + XBell(XtDisplay(w), 0); + default: /* Fall Through */ + break; + } +} + +/* Reconnect() - action + * This reconnects to the input method. The user will typically call + * this action if/when connection has been severed, or when the app + * was started up before an IM was started up. + */ + +#ifdef XAW_INTERNATIONALIZATION +/*ARGSUSED*/ +static void +Reconnect( w, event, params, num_params ) + Widget w; + XEvent* event; + String* params; + Cardinal* num_params; +{ + _XawImReconnect( w ); +} +#endif + + +XtActionsRec _XawTextActionsTable[] = { + +/* motion bindings */ + + {"forward-character", MoveForwardChar}, + {"backward-character", MoveBackwardChar}, + {"forward-word", MoveForwardWord}, + {"backward-word", MoveBackwardWord}, + {"forward-paragraph", MoveForwardParagraph}, + {"backward-paragraph", MoveBackwardParagraph}, + {"beginning-of-line", MoveToLineStart}, + {"end-of-line", MoveToLineEnd}, + {"next-line", MoveNextLine}, + {"previous-line", MovePreviousLine}, + {"next-page", MoveNextPage}, + {"previous-page", MovePreviousPage}, + {"beginning-of-file", MoveBeginningOfFile}, + {"end-of-file", MoveEndOfFile}, + {"scroll-one-line-up", ScrollOneLineUp}, + {"scroll-one-line-down", ScrollOneLineDown}, + +/* delete bindings */ + + {"delete-next-character", DeleteForwardChar}, + {"delete-previous-character", DeleteBackwardChar}, + {"delete-next-word", DeleteForwardWord}, + {"delete-previous-word", DeleteBackwardWord}, + {"delete-selection", DeleteCurrentSelection}, + +/* kill bindings */ + + {"kill-word", KillForwardWord}, + {"backward-kill-word", KillBackwardWord}, + {"kill-selection", KillCurrentSelection}, + {"kill-to-end-of-line", KillToEndOfLine}, + {"kill-to-end-of-paragraph", KillToEndOfParagraph}, + +/* new line stuff */ + + {"newline-and-indent", InsertNewLineAndIndent}, + {"newline-and-backup", InsertNewLineAndBackup}, + {"newline", InsertNewLine}, + +/* Selection stuff */ + + {"select-word", SelectWord}, + {"select-all", SelectAll}, + {"select-start", SelectStart}, + {"select-adjust", SelectAdjust}, + {"select-end", SelectEnd}, + {"select-save", SelectSave}, + {"extend-start", ExtendStart}, + {"extend-adjust", ExtendAdjust}, + {"extend-end", ExtendEnd}, + {"insert-selection", InsertSelection}, + +/* Miscellaneous */ + + {"redraw-display", RedrawDisplay}, + {"insert-file", _XawTextInsertFile}, + {"search", _XawTextSearch}, + {"insert-char", InsertChar}, + {"insert-string", InsertString}, + {"focus-in", TextFocusIn}, + {"focus-out", TextFocusOut}, + {"enter-window", TextEnterWindow}, + {"leave-window", TextLeaveWindow}, + {"display-caret", DisplayCaret}, + {"multiply", Multiply}, + {"form-paragraph", FormParagraph}, + {"transpose-characters", TransposeCharacters}, + {"no-op", NoOp}, + +/* Action to bind special translations for text Dialogs. */ + + {"InsertFileAction", _XawTextInsertFileAction}, + {"DoSearchAction", _XawTextDoSearchAction}, + {"DoReplaceAction", _XawTextDoReplaceAction}, + {"SetField", _XawTextSetField}, + {"PopdownSearchAction", _XawTextPopdownSearchAction}, + +/* Reconnect to Input Method */ +#ifdef XAW_INTERNATIONALIZATION + {"reconnect-im", Reconnect} /* Li Yuhong, Omron KK, 1991 */ +#endif +}; + +Cardinal _XawTextActionsTableCount = XtNumber(_XawTextActionsTable); diff --git a/src/TextP.h b/src/TextP.h new file mode 100644 index 0000000..9121314 --- /dev/null +++ b/src/TextP.h @@ -0,0 +1,290 @@ +/* +* $XConsortium: TextP.h,v 1.54 95/06/14 15:07:27 kaleb Exp $ +*/ + + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _XawTextP_h +#define _XawTextP_h + +#include <X11/Xaw3d/Text.h> +#include <X11/Xaw3d/SimpleP.h> + +/**************************************************************** + * + * Text widget private + * + ****************************************************************/ +#define MAXCUT 30000 /* Maximum number of characters that can be cut. */ + +#define GETLASTPOS XawTextSourceScan(ctx->text.source, 0, \ + XawstAll, XawsdRight, 1, TRUE) + +#define zeroPosition ((XawTextPosition) 0) + +extern XtActionsRec _XawTextActionsTable[]; +extern Cardinal _XawTextActionsTableCount; + +#define XawLF 0x0a +#define XawCR 0x0d +#define XawTAB 0x09 +#define XawBS 0x08 +#define XawSP 0x20 +#define XawDEL 0x7f +#define XawESC 0x1b +#define XawBSLASH '\\' + +/* constants that subclasses may want to know */ +#define DEFAULT_TEXT_HEIGHT ((Dimension)~0) + +/* displayable text management data structures */ + +typedef struct { + XawTextPosition position; + Position y; + Dimension textWidth; +} XawTextLineTableEntry, *XawTextLineTableEntryPtr; + +typedef struct { + XawTextPosition left, right; + XawTextSelectType type; + Atom* selections; + int atom_count; + int array_size; +} XawTextSelection; + +typedef struct _XawTextSelectionSalt { + struct _XawTextSelectionSalt *next; + XawTextSelection s; + /* + * The element "contents" stores the CT string which is gotten in the + * function _XawTextSaltAwaySelection(). + */ + char *contents; + int length; +} XawTextSelectionSalt; + +/* Line Tables are n+1 long - last position displayed is in last lt entry */ +typedef struct { + XawTextPosition top; /* Top of the displayed text. */ + int lines; /* How many lines in this table. */ + XawTextLineTableEntry *info; /* A dynamic array, one entry per line */ +} XawTextLineTable, *XawTextLineTablePtr; + + +typedef struct _XawTextMargin { + Position left, right, top, bottom; +} XawTextMargin; + +#define VMargins(ctx) ( (ctx)->text.margin.top + (ctx)->text.margin.bottom ) +#define HMargins(ctx) ( (ctx)->text.margin.left + (ctx)->text.margin.right ) + +#define IsPositionVisible(ctx, pos) \ + (pos >= ctx->text.lt.info[0].position && \ + pos < ctx->text.lt.info[ctx->text.lt.lines].position) + +/* + * Search & Replace data structure. + */ + +struct SearchAndReplace { + Boolean selection_changed; /* flag so that the selection cannot be + changed out from underneath query-replace.*/ + Widget search_popup; /* The poppup widget that allows searches.*/ + Widget label1; /* The label widgets for the search window. */ + Widget label2; + Widget left_toggle; /* The left search toggle radioGroup. */ + Widget right_toggle; /* The right search toggle radioGroup. */ + Widget rep_label; /* The Replace label string. */ + Widget rep_text; /* The Replace text field. */ + Widget search_text; /* The Search text field. */ + Widget rep_one; /* The Replace one button. */ + Widget rep_all; /* The Replace all button. */ +}; + +/* Private Text Definitions */ + +typedef int (*ActionProc)(); + +/* New fields for the Text widget class record */ + +typedef struct {int empty;} TextClassPart; + +struct text_move { + int h, v; + struct text_move * next; +}; + +/* Full class record declaration */ +typedef struct _TextClassRec { + CoreClassPart core_class; + SimpleClassPart simple_class; + TextClassPart text_class; +} TextClassRec; + +extern TextClassRec textClassRec; + +/* New fields for the Text widget record */ +typedef struct _TextPart { + /* resources */ + + Widget source, sink; + XawTextPosition insertPos; + XawTextSelection s; + XawTextSelectType *sarray; /* Array to cycle for selections. */ + XawTextSelectionSalt *salt; /* salted away selections */ + int options; /* wordbreak, scroll, etc. */ + int dialog_horiz_offset; /* position for popup dialog */ + int dialog_vert_offset; /* position for popup dialog */ + Boolean display_caret; /* insertion pt visible iff T */ + Boolean auto_fill; /* Auto fill mode? */ + XawTextScrollMode scroll_vert, scroll_horiz; /*what type of scrollbars.*/ + XawTextWrapMode wrap; /* The type of wrapping. */ + XawTextResizeMode resize; /* what to resize */ + XawTextMargin r_margin; /* The real margins. */ + XtCallbackList unrealize_callbacks; /* used for scrollbars */ + + /* private state */ + + XawTextMargin margin; /* The current margins. */ + XawTextLineTable lt; + XawTextScanDirection extendDir; + XawTextSelection origSel; /* the selection being modified */ + Time lasttime; /* timestamp of last processed action */ + Time time; /* time of last key or button action */ + Position ev_x, ev_y; /* x, y coords for key or button action */ + Widget vbar, hbar; /* The scroll bars (none = NULL). */ + struct SearchAndReplace * search;/* Search and replace structure. */ + Widget file_insert; /* The file insert popup widget. */ + XawTextPosition *updateFrom; /* Array of start positions for update. */ + XawTextPosition *updateTo; /* Array of end positions for update. */ + int numranges; /* How many update ranges there are. */ + int maxranges; /* How many ranges we have space for */ + XawTextPosition lastPos; /* Last position of source. */ + GC gc; + Boolean showposition; /* True if we need to show the position. */ + Boolean hasfocus; /* TRUE if we currently have input focus.*/ + Boolean update_disabled; /* TRUE if display updating turned off */ + Boolean single_char; /* Single character replaced. */ + XawTextPosition old_insert; /* Last insertPos for batched updates */ + short mult; /* Multiplier. */ + struct text_move * copy_area_offsets; /* Text offset area (linked list) */ + Widget threeD; /* shadow drawing */ + + /* private state, shared w/Source and Sink */ + Boolean redisplay_needed; /* in SetValues */ + XawTextSelectionSalt *salt2; /* salted away selections */ +} TextPart; + +/************************************************************* + * + * Resource types private to Text widget. + * + *************************************************************/ + +#define XtRScrollMode "ScrollMode" +#define XtRWrapMode "WrapMode" +#define XtRResizeMode "ResizeMode" + +/**************************************************************** + * + * Full instance record declaration + * + ****************************************************************/ + +typedef struct _TextRec { + CorePart core; + SimplePart simple; + TextPart text; +} TextRec; + +/******************************************** + * + * Semi-private functions + * for use by other Xaw modules only + * + *******************************************/ + +extern void _XawTextBuildLineTable ( +#if NeedFunctionPrototypes + TextWidget /*ctx*/, + XawTextPosition /*top pos*/, + _XtBoolean /* force_rebuild */ +#endif +); + +extern char* _XawTextGetSTRING( +#if NeedFunctionPrototypes + TextWidget /*ctx*/, + XawTextPosition /*left*/, + XawTextPosition /*right*/ +#endif +); + +extern void _XawTextSaltAwaySelection( +#if NeedFunctionPrototypes + TextWidget /*ctx*/, + Atom* /*selections*/, + int /*num_atoms*/ +#endif +); + +extern void _XawTextPosToXY( +#if NeedFunctionPrototypes + Widget /* w */, + XawTextPosition /* pos */, + Position * /* x */, + Position * /*y */ +#endif +); + +#endif /* _XawTextP_h */ + + diff --git a/src/TextPop.c b/src/TextPop.c new file mode 100644 index 0000000..260b4dc --- /dev/null +++ b/src/TextPop.c @@ -0,0 +1,1434 @@ +/* $XConsortium: TextPop.c,v 1.31 94/04/17 20:13:10 kaleb Exp $ */ + +/* + +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +/************************************************************ + * + * This file is broken up into three sections one dealing with + * each of the three popups created here: + * + * FileInsert, Search, and Replace. + * + * There is also a section at the end for utility functions + * used by all more than one of these dialogs. + * + * The following functions are the only non-static ones defined + * in this module. They are located at the begining of the + * section that contains this dialog box that uses them. + * + * void _XawTextInsertFileAction(w, event, params, num_params); + * void _XawTextDoSearchAction(w, event, params, num_params); + * void _XawTextDoReplaceAction(w, event, params, num_params); + * void _XawTextInsertFile(w, event, params, num_params); + * + *************************************************************/ + +#include "Xaw3dP.h" +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Shell.h> +#include <X11/Xaw3d/TextP.h> +#include <X11/Xaw3d/AsciiText.h> +#include <X11/Xaw3d/Cardinals.h> +#include <X11/Xaw3d/Command.h> +#include <X11/Xaw3d/Form.h> +#include <X11/Xaw3d/Toggle.h> +#include <X11/Xmu/CharSet.h> +#ifdef XAW_INTERNATIONALIZATION +#include "XawI18n.h" +#endif +#include <stdio.h> +#include <X11/Xos.h> /* for O_RDONLY */ +#include <errno.h> + +#ifdef X_NOT_STDC_ENV +extern int errno; +#endif + +#define INSERT_FILE ("Enter Filename:") + +#define SEARCH_LABEL_1 ("Use <Tab> to change fields.") +#define SEARCH_LABEL_2 ("Use ^q<Tab> for <Tab>.") +#define DISMISS_NAME ("cancel") +#define DISMISS_NAME_LEN 6 +#define FORM_NAME ("form") +#define LABEL_NAME ("label") +#define TEXT_NAME ("text") + +#define R_OFFSET 1 + +static void CenterWidgetOnPoint(), PopdownSearch(), DoInsert(), _SetField(); +static void InitializeSearchWidget(), SetResource(), SetSearchLabels(); +static void DoReplaceOne(), DoReplaceAll(); +static Widget CreateDialog(), GetShell(); +static void SetWMProtocolTranslations(); +static Boolean DoSearch(), SetResourceByName(), Replace(); +static String GetString(); + +static String GetStringRaw(); + +static void AddInsertFileChildren(); +static Boolean InsertFileNamed(); +static void AddSearchChildren(); + +static char radio_trans_string[] = + "<Btn1Down>,<Btn1Up>: set() notify()"; + +static char search_text_trans[] = + "~Shift<Key>Return: DoSearchAction(Popdown) \n\ + Shift<Key>Return: DoSearchAction() SetField(Replace) \n\ + Ctrl<Key>q,<Key>Tab: insert-char() \n\ + Ctrl<Key>c: PopdownSearchAction() \n\ + <Btn1Down>: select-start() SetField(Search) \n\ + <Key>Tab: DoSearchAction() SetField(Replace)"; + +static char rep_text_trans[] = + "~Shift<Key>Return: DoReplaceAction(Popdown) \n\ + Shift<Key>Return: SetField(Search) \n\ + Ctrl<Key>q,<Key>Tab: insert-char() \n\ + Ctrl<Key>c: PopdownSearchAction() \n\ + <Btn1Down>: select-start() DoSearchAction() SetField(Replace)\n\ + <Key>Tab: SetField(Search)"; + +/************************************************************ + * + * This section of the file contains all the functions that + * the file insert dialog box uses. + * + ************************************************************/ + +/* Function Name: _XawTextInsertFileAction + * Description: Action routine that can be bound to dialog box's + * Text Widget that will insert a file into the main + * Text Widget. + * Arguments: (Standard Action Routine args) + * Returns: none. + */ + +/* ARGSUSED */ +void +_XawTextInsertFileAction(w, event, params, num_params) +Widget w; +XEvent *event; +String * params; +Cardinal * num_params; +{ + DoInsert(w, (XtPointer) XtParent(XtParent(XtParent(w))), (XtPointer)NULL); +} + +/* Function Name: _XawTextInsertFile + * Description: Action routine that can be bound to the text widget + * it will popup the insert file dialog box. + * Arguments: w - the text widget. + * event - X Event (used to get x and y location). + * params, num_params - the parameter list. + * Returns: none. + * + * NOTE: + * + * The parameter list may contain one entry. + * + * Entry: This entry is optional and contains the value of the default + * file to insert. + */ + +void +_XawTextInsertFile(w, event, params, num_params) +Widget w; +XEvent *event; +String * params; +Cardinal * num_params; +{ + TextWidget ctx = (TextWidget)w; + char * ptr; + XawTextEditType edit_mode; + Arg args[1]; + + XtSetArg(args[0], XtNeditType,&edit_mode); + XtGetValues(ctx->text.source, args, ONE); + + if (edit_mode != XawtextEdit) { + XBell(XtDisplay(w), 0); + return; + } + + if (*num_params == 0) + ptr = ""; + else + ptr = params[0]; + + if (!ctx->text.file_insert) { + ctx->text.file_insert = CreateDialog(w, ptr, "insertFile", + AddInsertFileChildren); + XtRealizeWidget(ctx->text.file_insert); + SetWMProtocolTranslations(ctx->text.file_insert); + } + + CenterWidgetOnPoint(ctx->text.file_insert, event); + XtPopup(ctx->text.file_insert, XtGrabNone); +} + +/* Function Name: PopdownFileInsert + * Description: Pops down the file insert button. + * Arguments: w - the widget that caused this action. + * closure - a pointer to the main text widget that + * popped up this dialog. + * call_data - *** NOT USED ***. + * Returns: none. + */ + +/* ARGSUSED */ +static void +PopdownFileInsert(w, closure, call_data) +Widget w; /* The Dialog Button Pressed. */ +XtPointer closure; /* Text Widget. */ +XtPointer call_data; /* unused */ +{ + TextWidget ctx = (TextWidget) closure; + + XtPopdown( ctx->text.file_insert ); + (void) SetResourceByName( ctx->text.file_insert, LABEL_NAME, + XtNlabel, (XtArgVal) INSERT_FILE); +} + +/* Function Name: DoInsert + * Description: Actually insert the file named in the text widget + * of the file dialog. + * Arguments: w - the widget that activated this callback. + * closure - a pointer to the text widget to insert the + * file into. + * Returns: none. + */ + +/* ARGSUSED */ +static void +DoInsert(w, closure, call_data) +Widget w; /* The Dialog Button Pressed. */ +XtPointer closure; /* Text Widget */ +XtPointer call_data; /* unused */ +{ + TextWidget ctx = (TextWidget) closure; + char buf[BUFSIZ], msg[BUFSIZ]; + Widget temp_widget; + + (void) sprintf(buf, "%s.%s", FORM_NAME, TEXT_NAME); + if ( (temp_widget = XtNameToWidget(ctx->text.file_insert, buf)) == NULL ) { + (void) strcpy(msg, + "*** Error: Could not get text widget from file insert popup"); + } + else + if (InsertFileNamed( (Widget) ctx, GetString( temp_widget ))) { + PopdownFileInsert(w, closure, call_data); + return; + } + else + (void) sprintf( msg, "*** Error: %s ***", strerror(errno)); + + (void)SetResourceByName(ctx->text.file_insert, + LABEL_NAME, XtNlabel, (XtArgVal) msg); + XBell(XtDisplay(w), 0); +} + +/* Function Name: InsertFileNamed + * Description: Inserts a file into the text widget. + * Arguments: tw - The text widget to insert this file into. + * str - name of the file to insert. + * Returns: TRUE if the insert was sucessful, FALSE otherwise. + */ + + +static Boolean +InsertFileNamed(tw, str) +Widget tw; +char *str; +{ + FILE *file; + XawTextBlock text; + XawTextPosition pos; + + if ( (str == NULL) || (strlen(str) == 0) || + ((file = fopen(str, "r")) == NULL)) + return(FALSE); + + pos = XawTextGetInsertionPoint(tw); + + fseek(file, 0L, 2); + + + text.firstPos = 0; + text.length = (ftell(file))/sizeof(unsigned char); + text.ptr = XtMalloc((text.length + 1) * sizeof(unsigned char)); + text.format = XawFmt8Bit; + + fseek(file, 0L, 0); + if (fread(text.ptr, sizeof(unsigned char), text.length, file) != text.length) + XtErrorMsg("readError", "insertFileNamed", "XawError", + "fread returned error.", NULL, NULL); + + /* DELETE if (text.format == XawFmtWide) { + wchar_t* _XawTextMBToWC(); + wchar_t* wstr; + wstr = _XawTextMBToWC(XtDisplay(tw), text.ptr, &(text.length)); + wstr[text.length] = NULL; + XtFree(text.ptr); + text.ptr = (char *)wstr; + } else { + (text.ptr)[text.length] = '\0'; + }*/ + + if (XawTextReplace(tw, pos, pos, &text) != XawEditDone) { + XtFree(text.ptr); + fclose(file); + return(FALSE); + } + pos += text.length; + XtFree(text.ptr); + fclose(file); + XawTextSetInsertionPoint(tw, pos); + return(TRUE); +} + + +/* Function Name: AddInsertFileChildren + * Description: Adds all children to the InsertFile dialog widget. + * Arguments: form - the form widget for the insert dialog widget. + * ptr - a pointer to the initial string for the Text Widget. + * tw - the main text widget. + * Returns: none + */ + +static void +AddInsertFileChildren(form, ptr, tw) +Widget form, tw; +char * ptr; +{ + Arg args[10]; + Cardinal num_args; + Widget label, text, cancel, insert; + XtTranslations trans; + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, INSERT_FILE);num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNresizable, TRUE ); num_args++; + XtSetArg(args[num_args], XtNborderWidth, 0 ); num_args++; + label = XtCreateManagedWidget (LABEL_NAME, labelWidgetClass, form, + args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNfromVert, label); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainRight); num_args++; + XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++; + XtSetArg(args[num_args], XtNresizable, TRUE); num_args++; + XtSetArg(args[num_args], XtNresize, XawtextResizeWidth); num_args++; + XtSetArg(args[num_args], XtNstring, ptr); num_args++; + text = XtCreateManagedWidget(TEXT_NAME, asciiTextWidgetClass, form, + args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, "Insert File"); num_args++; + XtSetArg(args[num_args], XtNfromVert, text); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + insert = XtCreateManagedWidget("insert", commandWidgetClass, form, + args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, "Cancel"); num_args++; + XtSetArg(args[num_args], XtNfromVert, text); num_args++; + XtSetArg(args[num_args], XtNfromHoriz, insert); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + cancel = XtCreateManagedWidget(DISMISS_NAME, commandWidgetClass, form, + args, num_args); + + XtAddCallback(cancel, XtNcallback, PopdownFileInsert, (XtPointer) tw); + XtAddCallback(insert, XtNcallback, DoInsert, (XtPointer) tw); + + XtSetKeyboardFocus(form, text); + +/* + * Bind <CR> to insert file. + */ + + trans = XtParseTranslationTable("<Key>Return: InsertFileAction()"); + XtOverrideTranslations(text, trans); + +} + +/************************************************************ + * + * This section of the file contains all the functions that + * the search dialog box uses. + * + ************************************************************/ + +/* Function Name: _XawTextDoSearchAction + * Description: Action routine that can be bound to dialog box's + * Text Widget that will search for a string in the main + * Text Widget. + * Arguments: (Standard Action Routine args) + * Returns: none. + * + * Note: + * + * If the search was sucessful and the argument popdown is passed to + * this action routine then the widget will automatically popdown the + * search widget. + */ + +/* ARGSUSED */ +void +_XawTextDoSearchAction(w, event, params, num_params) +Widget w; +XEvent *event; +String * params; +Cardinal * num_params; +{ + TextWidget tw = (TextWidget) XtParent(XtParent(XtParent(w))); + Boolean popdown = FALSE; + + if ( (*num_params == 1) && + ((params[0][0] == 'p') || (params[0][0] == 'P')) ) + popdown = TRUE; + + if (DoSearch(tw->text.search) && popdown) + PopdownSearch(w, (XtPointer) tw->text.search, (XtPointer)NULL); +} + +/* Function Name: _XawTextPopdownSearchAction + * Description: Action routine that can be bound to dialog box's + * Text Widget that will popdown the search widget. + * Arguments: (Standard Action Routine args) + * Returns: none. + */ + +/* ARGSUSED */ +void +_XawTextPopdownSearchAction(w, event, params, num_params) +Widget w; +XEvent *event; +String * params; +Cardinal * num_params; +{ + TextWidget tw = (TextWidget) XtParent(XtParent(XtParent(w))); + + PopdownSearch(w, (XtPointer) tw->text.search, (XtPointer)NULL); +} + +/* Function Name: PopdownSeach + * Description: Pops down the search widget and resets it. + * Arguments: w - *** NOT USED ***. + * closure - a pointer to the search structure. + * call_data - *** NOT USED ***. + * Returns: none + */ + +/* ARGSUSED */ +static void +PopdownSearch(w, closure, call_data) +Widget w; +XtPointer closure; +XtPointer call_data; +{ + struct SearchAndReplace * search = (struct SearchAndReplace *) closure; + + XtPopdown( search->search_popup ); + SetSearchLabels(search, SEARCH_LABEL_1, SEARCH_LABEL_2, FALSE); +} + +/* Function Name: SearchButton + * Description: Performs a search when the button is clicked. + * Arguments: w - *** NOT USED **. + * closure - a pointer to the search info. + * call_data - *** NOT USED ***. + * Returns: + */ + +/* ARGSUSED */ +static void +SearchButton(w, closure, call_data) +Widget w; +XtPointer closure; +XtPointer call_data; +{ + (void) DoSearch( (struct SearchAndReplace *) closure ); +} + +/* Function Name: _XawTextSearch + * Description: Action routine that can be bound to the text widget + * it will popup the search dialog box. + * Arguments: w - the text widget. + * event - X Event (used to get x and y location). + * params, num_params - the parameter list. + * Returns: none. + * + * NOTE: + * + * The parameter list contains one or two entries that may be the following. + * + * First Entry: The first entry is the direction to search by default. + * This arguement must be specified and may have a value of + * "left" or "right". + * + * Second Entry: This entry is optional and contains the value of the default + * string to search for. + */ + +#define SEARCH_HEADER ("Text Widget - Search():") + +void +_XawTextSearch(w, event, params, num_params) +Widget w; +XEvent *event; +String * params; +Cardinal * num_params; +{ + TextWidget ctx = (TextWidget)w; + XawTextScanDirection dir; + char * ptr, buf[BUFSIZ]; + XawTextEditType edit_mode; + Arg args[1]; + +#ifdef notdef + if (ctx->text.source->Search == NULL) { + XBell(XtDisplay(w), 0); + return; + } +#endif + + if ( (*num_params < 1) || (*num_params > 2) ) { + (void) sprintf(buf, "%s %s\n%s", SEARCH_HEADER, + "This action must have only", + "one or two parameters"); + XtAppWarning(XtWidgetToApplicationContext(w), buf); + return; + } + + if (*num_params == 2 ) + ptr = params[1]; + else +#ifdef XAW_INTERNATIONALIZATION + if (_XawTextFormat(ctx) == XawFmtWide) { + /*This just does the equivalent of ptr = ""L, a waste because params[1] isnt W aligned.*/ + ptr = (char *)XtMalloc(sizeof(wchar_t)); + *((wchar_t*)ptr) = (wchar_t)0; + } else +#endif + ptr = ""; + + switch(params[0][0]) { + case 'b': /* Left. */ + case 'B': + dir = XawsdLeft; + break; + case 'f': /* Right. */ + case 'F': + dir = XawsdRight; + break; + default: + (void) sprintf(buf, "%s %s\n%s", SEARCH_HEADER, + "The first parameter must be", + "Either 'backward' or 'forward'"); + XtAppWarning(XtWidgetToApplicationContext(w), buf); + return; + } + + if (ctx->text.search== NULL) { + ctx->text.search = XtNew(struct SearchAndReplace); + ctx->text.search->search_popup = CreateDialog(w, ptr, "search", + AddSearchChildren); + XtRealizeWidget(ctx->text.search->search_popup); + SetWMProtocolTranslations(ctx->text.search->search_popup); + } + else if (*num_params > 1) { + XtVaSetValues(ctx->text.search->search_text, XtNstring, ptr, NULL); + } + + XtSetArg(args[0], XtNeditType,&edit_mode); + XtGetValues(ctx->text.source, args, ONE); + + InitializeSearchWidget(ctx->text.search, dir, (edit_mode == XawtextEdit)); + + CenterWidgetOnPoint(ctx->text.search->search_popup, event); + XtPopup(ctx->text.search->search_popup, XtGrabNone); +} + +/* Function Name: InitializeSearchWidget + * Description: This function initializes the search widget and + * is called each time the search widget is poped up. + * Arguments: search - the search widget structure. + * dir - direction to search. + * replace_active - state of the sensitivity for the + * replace button. + * Returns: none. + */ + +static void +InitializeSearchWidget(search, dir, replace_active) +struct SearchAndReplace * search; +XawTextScanDirection dir; +Boolean replace_active; +{ + SetResource(search->rep_one, XtNsensitive, (XtArgVal) replace_active); + SetResource(search->rep_all, XtNsensitive, (XtArgVal) replace_active); + SetResource(search->rep_label, XtNsensitive, (XtArgVal) replace_active); + SetResource(search->rep_text, XtNsensitive, (XtArgVal) replace_active); + + switch (dir) { + case XawsdLeft: + SetResource(search->left_toggle, XtNstate, (XtArgVal) TRUE); + break; + case XawsdRight: + SetResource(search->right_toggle, XtNstate, (XtArgVal) TRUE); + break; + default: + break; + } +} + +/* Function Name: AddSearchChildren + * Description: Adds all children to the Search Dialog Widget. + * Arguments: form - the form widget for the search widget. + * ptr - a pointer to the initial string for the Text Widget. + * tw - the main text widget. + * Returns: none. + */ + +static void +AddSearchChildren(form, ptr, tw) +Widget form, tw; +char * ptr; +{ + Arg args[10]; + Cardinal num_args; + Widget cancel, search_button, s_label, s_text, r_text; + XtTranslations trans; + struct SearchAndReplace * search = ((TextWidget) tw)->text.search; + + num_args = 0; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNresizable, TRUE ); num_args++; + XtSetArg(args[num_args], XtNborderWidth, 0 ); num_args++; + search->label1 = XtCreateManagedWidget("label1", labelWidgetClass, form, + args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNfromVert, search->label1); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNresizable, TRUE ); num_args++; + XtSetArg(args[num_args], XtNborderWidth, 0 ); num_args++; + search->label2 = XtCreateManagedWidget("label2", labelWidgetClass, form, + args, num_args); + +/* + * We need to add R_OFFSET to the radio_data, because the value zero (0) + * has special meaning. + */ + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, "Backward"); num_args++; + XtSetArg(args[num_args], XtNfromVert, search->label2); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNradioData, (XPointer) XawsdLeft + R_OFFSET); + num_args++; + search->left_toggle = XtCreateManagedWidget("backwards", toggleWidgetClass, + form, args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, "Forward"); num_args++; + XtSetArg(args[num_args], XtNfromVert, search->label2); num_args++; + XtSetArg(args[num_args], XtNfromHoriz, search->left_toggle); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNradioGroup, search->left_toggle); num_args++; + XtSetArg(args[num_args], XtNradioData, (XPointer) XawsdRight + R_OFFSET); + num_args++; + search->right_toggle = XtCreateManagedWidget("forwards", toggleWidgetClass, + form, args, num_args); + + { + XtTranslations radio_translations; + + radio_translations = XtParseTranslationTable(radio_trans_string); + XtOverrideTranslations(search->left_toggle, radio_translations); + XtOverrideTranslations(search->right_toggle, radio_translations); + } + + num_args = 0; + XtSetArg(args[num_args], XtNfromVert, search->left_toggle); num_args++; + XtSetArg(args[num_args], XtNlabel, "Search for: ");num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNborderWidth, 0 ); num_args++; + s_label = XtCreateManagedWidget("searchLabel", labelWidgetClass, form, + args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNfromVert, search->left_toggle); num_args++; + XtSetArg(args[num_args], XtNfromHoriz, s_label); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainRight); num_args++; + XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++; + XtSetArg(args[num_args], XtNresizable, TRUE); num_args++; + XtSetArg(args[num_args], XtNresize, XawtextResizeWidth); num_args++; + XtSetArg(args[num_args], XtNstring, ptr); num_args++; + s_text = XtCreateManagedWidget("searchText", asciiTextWidgetClass, form, + args, num_args); + search->search_text = s_text; + + num_args = 0; + XtSetArg(args[num_args], XtNfromVert, s_text); num_args++; + XtSetArg(args[num_args], XtNlabel, "Replace with:");num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNborderWidth, 0 ); num_args++; + search->rep_label = XtCreateManagedWidget("replaceLabel", labelWidgetClass, + form, args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNfromHoriz, s_label); num_args++; + XtSetArg(args[num_args], XtNfromVert, s_text); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainRight); num_args++; + XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++; + XtSetArg(args[num_args], XtNresizable, TRUE); num_args++; + XtSetArg(args[num_args], XtNresize, XawtextResizeWidth); num_args++; + XtSetArg(args[num_args], XtNstring, ""); num_args++; + r_text = XtCreateManagedWidget("replaceText", asciiTextWidgetClass, + form, args, num_args); + search->rep_text = r_text; + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, "Search"); num_args++; + XtSetArg(args[num_args], XtNfromVert, r_text); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + search_button = XtCreateManagedWidget("search", commandWidgetClass, form, + args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, "Replace"); num_args++; + XtSetArg(args[num_args], XtNfromVert, r_text); num_args++; + XtSetArg(args[num_args], XtNfromHoriz, search_button); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + search->rep_one = XtCreateManagedWidget("replaceOne", commandWidgetClass, + form, args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, "Replace All"); num_args++; + XtSetArg(args[num_args], XtNfromVert, r_text); num_args++; + XtSetArg(args[num_args], XtNfromHoriz, search->rep_one); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + search->rep_all = XtCreateManagedWidget("replaceAll", commandWidgetClass, + form, args, num_args); + + num_args = 0; + XtSetArg(args[num_args], XtNlabel, "Cancel"); num_args++; + XtSetArg(args[num_args], XtNfromVert, r_text); num_args++; + XtSetArg(args[num_args], XtNfromHoriz, search->rep_all); num_args++; + XtSetArg(args[num_args], XtNleft, XtChainLeft); num_args++; + XtSetArg(args[num_args], XtNright, XtChainLeft); num_args++; + cancel = XtCreateManagedWidget(DISMISS_NAME, commandWidgetClass, form, + args, num_args); + + XtAddCallback(search_button, XtNcallback, SearchButton, (XtPointer) search); + XtAddCallback(search->rep_one, XtNcallback, DoReplaceOne, (XtPointer) search); + XtAddCallback(search->rep_all, XtNcallback, DoReplaceAll, (XtPointer) search); + XtAddCallback(cancel, XtNcallback, PopdownSearch, (XtPointer) search); + +/* + * Initialize the text entry fields. + */ + + { + Pixel color; + num_args = 0; + XtSetArg(args[num_args], XtNbackground, &color); num_args++; + XtGetValues(search->rep_text, args, num_args); + num_args = 0; + XtSetArg(args[num_args], XtNborderColor, color); num_args++; + XtSetValues(search->rep_text, args, num_args); + XtSetKeyboardFocus(form, search->search_text); + } + + SetSearchLabels(search, SEARCH_LABEL_1, SEARCH_LABEL_2, FALSE); + +/* + * Bind Extra translations. + */ + + trans = XtParseTranslationTable(search_text_trans); + XtOverrideTranslations(search->search_text, trans); + + trans = XtParseTranslationTable(rep_text_trans); + XtOverrideTranslations(search->rep_text, trans); +} + +/* Function Name: DoSearch + * Description: Performs a search. + * Arguments: search - the serach structure. + * Returns: TRUE if sucessful. + */ + +/* ARGSUSED */ +static Boolean +DoSearch(search) +struct SearchAndReplace * search; +{ + char msg[BUFSIZ]; + Widget tw = XtParent(search->search_popup); + XawTextPosition pos; + XawTextScanDirection dir; + XawTextBlock text; + + TextWidget ctx = (TextWidget)tw; + + text.ptr = GetStringRaw(search->search_text); + text.format = _XawTextFormat(ctx); +#ifdef XAW_INTERNATIONALIZATION + if (text.format == XawFmtWide) + text.length = wcslen((wchar_t*)text.ptr); + else +#endif + text.length = strlen(text.ptr); + text.firstPos = 0; + + dir = (XawTextScanDirection)(int) ((XPointer)XawToggleGetCurrent(search->left_toggle) - + R_OFFSET); + + pos = XawTextSearch( tw, dir, &text); + + + /* The Raw string in find.ptr may be WC I can't use here, so I re - call + GetString to get a tame version. */ + + if (pos == XawTextSearchError) + (void) sprintf( msg, "Could not find string ``%s''.", GetString( search->search_text ) ); + else { + if (dir == XawsdRight) + XawTextSetInsertionPoint( tw, pos + text.length); + else + XawTextSetInsertionPoint( tw, pos); + + XawTextSetSelection( tw, pos, pos + text.length); + search->selection_changed = FALSE; /* selection is good. */ + return(TRUE); + } + + XawTextUnsetSelection(tw); + SetSearchLabels(search, msg, "", TRUE); + return(FALSE); +} + +/************************************************************ + * + * This section of the file contains all the functions that + * the replace dialog box uses. + * + ************************************************************/ + +/* Function Name: _XawTextDoReplaceAction + * Description: Action routine that can be bound to dialog box's + * Text Widget that will replace a string in the main + * Text Widget. + * Arguments: (Standard Action Routine args) + * Returns: none. + */ + +/* ARGSUSED */ +void +_XawTextDoReplaceAction(w, event, params, num_params) +Widget w; +XEvent *event; +String * params; +Cardinal * num_params; +{ + TextWidget ctx = (TextWidget) XtParent(XtParent(XtParent(w))); + Boolean popdown = FALSE; + + if ( (*num_params == 1) && + ((params[0][0] == 'p') || (params[0][0] == 'P')) ) + popdown = TRUE; + + if (Replace( ctx->text.search, TRUE, popdown) && popdown) + PopdownSearch(w, (XtPointer) ctx->text.search, (XtPointer)NULL); +} + +/* Function Name: DoReplaceOne + * Description: Replaces the first instance of the string + * in the search dialog's text widget + * with the one in the replace dialog's text widget. + * Arguments: w - *** Not Used ***. + * closure - a pointer to the search structure. + * call_data - *** Not Used ***. + * Returns: none. + */ + +/* ARGSUSED */ +static void +DoReplaceOne(w, closure, call_data) +Widget w; /* The Button Pressed. */ +XtPointer closure; /* Text Widget. */ +XtPointer call_data; /* unused */ +{ + Replace( (struct SearchAndReplace *) closure, TRUE, FALSE); +} + +/* Function Name: DoReplaceOne + * Description: Replaces every instance of the string + * in the search dialog's text widget + * with the one in the replace dialog's text widget. + * Arguments: w - *** Not Used ***. + * closure - a pointer to the search structure. + * call_data - *** Not Used ***. + * Returns: none. + */ + +/* ARGSUSED */ +static void +DoReplaceAll(w, closure, call_data) +Widget w; /* The Button Pressed. */ +XtPointer closure; /* Text Widget. */ +XtPointer call_data; /* unused */ +{ + Replace( (struct SearchAndReplace *) closure, FALSE, FALSE); +} + +/* Function Name: Replace + * Description: This is the function that does the real work of + * replacing strings in the main text widget. + * Arguments: tw - the Text Widget to replce the string in. + * once_only - If TRUE then only replace the first one found. + * other replace all of them. + * show_current - If true then leave the selection on the + * string that was just replaced, otherwise + * move it onto the next one. + * Returns: none. + */ + +static Boolean +Replace(search, once_only, show_current) +struct SearchAndReplace * search; +Boolean once_only, show_current; +{ + XawTextPosition pos, new_pos, end_pos; + XawTextScanDirection dir; + XawTextBlock find, replace; + Widget tw = XtParent(search->search_popup); + int count = 0; + + TextWidget ctx = (TextWidget)tw; + + find.ptr = GetStringRaw( search->search_text); + find.format = _XawTextFormat(ctx); +#ifdef XAW_INTERNATIONALIZATION + if (find.format == XawFmtWide) + find.length = wcslen((wchar_t*)find.ptr); + else +#endif + find.length = strlen(find.ptr); + find.firstPos = 0; + + replace.ptr = GetStringRaw(search->rep_text); + replace.firstPos = 0; + replace.format = _XawTextFormat(ctx); +#ifdef XAW_INTERNATIONALIZATION + if (replace.format == XawFmtWide) + replace.length = wcslen((wchar_t*)replace.ptr); + else +#endif + replace.length = strlen(replace.ptr); + + dir = (XawTextScanDirection)(int) ((XPointer)XawToggleGetCurrent(search->left_toggle) - + R_OFFSET); + /* CONSTCOND */ + while (TRUE) { + if (count != 0) { + new_pos = XawTextSearch( tw, dir, &find); + + if ( (new_pos == XawTextSearchError) ) { + if (count == 0) { + char msg[BUFSIZ]; + + /* The Raw string in find.ptr may be WC I can't use here, + so I call GetString to get a tame version.*/ + + (void) sprintf( msg, "%s %s %s", "*** Error: Could not find string ``", + GetString( search->search_text ), "''. ***"); + SetSearchLabels(search, msg, "", TRUE); + return(FALSE); + } + else + break; + } + pos = new_pos; + end_pos = pos + find.length; + } + else { + XawTextGetSelectionPos(tw, &pos, &end_pos); + + if (search->selection_changed) { + SetSearchLabels(search, "Selection has been modified, aborting.", + "", TRUE); + return(FALSE); + } + if (pos == end_pos) + return(FALSE); + } + + if (XawTextReplace(tw, pos, end_pos, &replace) != XawEditDone) { + char msg[BUFSIZ]; + + (void) sprintf( msg, "'%s' with '%s'. ***", find.ptr, replace.ptr); + SetSearchLabels(search, "*** Error while replacing", msg, TRUE); + return(FALSE); + } + + if (dir == XawsdRight) + XawTextSetInsertionPoint( tw, pos + replace.length); + else + XawTextSetInsertionPoint( tw, pos); + + if (once_only) + if (show_current) + break; + else { + DoSearch(search); + return(TRUE); + } + count++; + } + + if (replace.length == 0) + XawTextUnsetSelection(tw); + else + XawTextSetSelection( tw, pos, pos + replace.length); + + return(TRUE); +} + +/* Function Name: SetSearchLabels + * Description: Sets both the search labels, and also rings the bell + * Arguments: search - the search structure. + * msg1, msg2 - message to put in each search label. + * bell - if TRUE then ring bell. + * Returns: none. + */ + +static void +SetSearchLabels(search, msg1, msg2, bell) +struct SearchAndReplace * search; +String msg1, msg2; +Boolean bell; +{ + (void) SetResource( search->label1, XtNlabel, (XtArgVal) msg1); + (void) SetResource( search->label2, XtNlabel, (XtArgVal) msg2); + if (bell) + XBell(XtDisplay(search->search_popup), 0); +} + +/************************************************************ + * + * This section of the file contains utility routines used by + * other functions in this file. + * + ************************************************************/ + + +/* Function Name: _XawTextSetField + * Description: Action routine that can be bound to dialog box's + * Text Widget that will send input to the field specified. + * Arguments: (Standard Action Routine args) + * Returns: none. + */ + +/* ARGSUSED */ +void +_XawTextSetField(w, event, params, num_params) +Widget w; +XEvent *event; +String * params; +Cardinal * num_params; +{ + struct SearchAndReplace * search; + Widget new, old; + + search = ((TextWidget) XtParent(XtParent(XtParent(w))))->text.search; + + if (*num_params != 1) { + SetSearchLabels(search, "*** Error: SetField Action must have", + "exactly one argument. ***", TRUE); + return; + } + switch (params[0][0]) { + case 's': + case 'S': + new = search->search_text; + old = search->rep_text; + break; + case 'r': + case 'R': + old = search->search_text; + new = search->rep_text; + break; + default: + SetSearchLabels(search, "*** Error: SetField Action's first Argument must", + "be either 'Search' or 'Replace'. ***", TRUE); + return; + } + _SetField(new, old); +} + +/* Function Name: SetField + * Description: Sets the current text field. + * Arguments: new, old - new and old text fields. + * Returns: none + */ + +static void +_SetField(new, old) +Widget new, old; +{ + Arg args[2]; + Pixel new_border, old_border, old_bg; + + if (!XtIsSensitive(new)) { + XBell(XtDisplay(old), 0); /* Don't set field to an inactive Widget. */ + return; + } + + XtSetKeyboardFocus(XtParent(new), new); + + XtSetArg(args[0], XtNborderColor, &old_border); + XtSetArg(args[1], XtNbackground, &old_bg); + XtGetValues(new, args, TWO); + + XtSetArg(args[0], XtNborderColor, &new_border); + XtGetValues(old, args, ONE); + + if (old_border != old_bg) /* Colors are already correct, return. */ + return; + + SetResource(old, XtNborderColor, (XtArgVal) old_border); + SetResource(new, XtNborderColor, (XtArgVal) new_border); +} + +/* Function Name: SetResourceByName + * Description: Sets a resource in any of the dialog children given + * name of the child and the shell widget of the dialog. + * Arguments: shell - shell widget of the popup. + * name - name of the child. + * res_name - name of the resource. + * value - the value of the resource. + * Returns: TRUE if sucessful. + */ + +static Boolean +SetResourceByName(shell, name, res_name, value) +Widget shell; +char * name, * res_name; +XtArgVal value; +{ + Widget temp_widget; + char buf[BUFSIZ]; + + (void) sprintf(buf, "%s.%s", FORM_NAME, name); + + if ( (temp_widget = XtNameToWidget(shell, buf)) != NULL) { + SetResource(temp_widget, res_name, value); + return(TRUE); + } + return(FALSE); +} + +/* Function Name: SetResource + * Description: Sets a resource in a widget + * Arguments: w - the widget. + * res_name - name of the resource. + * value - the value of the resource. + * Returns: none. + */ + +static void +SetResource(w, res_name, value) +Widget w; +char * res_name; +XtArgVal value; +{ + Arg args[1]; + + XtSetArg(args[0], res_name, value); + XtSetValues( w, args, ONE ); +} + +/* Function Name: GetString{Raw} + * Description: Gets the value for the string in the popup. + * Arguments: text - the text widget whose string we will get. + * + * GetString returns the string as a MB. + * GetStringRaw returns the exact buffer contents suitable for a search. + * + */ + +static String +GetString(text) +Widget text; +{ + String string; + Arg args[1]; + + XtSetArg( args[0], XtNstring, &string ); + XtGetValues( text, args, ONE ); + return(string); +} + +static String +GetStringRaw(tw) +Widget tw; +{ + TextWidget ctx = (TextWidget)tw; + XawTextPosition last; + char *_XawTextGetText(); + + last = XawTextSourceScan(ctx->text.source, 0, XawstAll, XawsdRight, + ctx->text.mult, TRUE); + return (_XawTextGetText(ctx, 0, last)); +} + +/* Function Name: CenterWidgetOnPoint. + * Description: Centers a shell widget on a point relative to + * the root window. + * Arguments: w - the shell widget. + * event - event containing the location of the point + * Returns: none. + * + * NOTE: The widget is not allowed to go off the screen. + */ + +static void +CenterWidgetOnPoint(w, event) +Widget w; +XEvent *event; +{ + Arg args[3]; + Cardinal num_args; + Dimension width, height, b_width; + Position x = 0, y = 0, max_x, max_y; + + if (event != NULL) { + switch (event->type) { + case ButtonPress: + case ButtonRelease: + x = event->xbutton.x_root; + y = event->xbutton.y_root; + break; + case KeyPress: + case KeyRelease: + x = event->xkey.x_root; + y = event->xkey.y_root; + break; + default: + return; + } + } + + num_args = 0; + XtSetArg(args[num_args], XtNwidth, &width); num_args++; + XtSetArg(args[num_args], XtNheight, &height); num_args++; + XtSetArg(args[num_args], XtNborderWidth, &b_width); num_args++; + XtGetValues(w, args, num_args); + + width += 2 * b_width; + height += 2 * b_width; + + x -= ( (Position) width/2 ); + if (x < 0) x = 0; + if ( x > (max_x = (Position) (XtScreen(w)->width - width)) ) x = max_x; + + y -= ( (Position) height/2 ); + if (y < 0) y = 0; + if ( y > (max_y = (Position) (XtScreen(w)->height - height)) ) y = max_y; + + num_args = 0; + XtSetArg(args[num_args], XtNx, x); num_args++; + XtSetArg(args[num_args], XtNy, y); num_args++; + XtSetValues(w, args, num_args); +} + +/* Function Name: CreateDialog + * Description: Actually creates a dialog. + * Arguments: parent - the parent of the dialog - the main text widget. + * ptr - initial_string for the dialog. + * name - name of the dialog. + * func - function to create the children of the dialog. + * Returns: the popup shell of the dialog. + * + * NOTE: + * + * The function argument is passed the following arguements. + * + * form - the from widget that is the dialog. + * ptr - the initial string for the dialog's text widget. + * parent - the parent of the dialog - the main text widget. + */ + +static Widget +CreateDialog(parent, ptr, name, func) +Widget parent; +String ptr, name; +void (*func)(); +{ + Widget popup, form; + Arg args[5]; + Cardinal num_args; + + num_args = 0; + XtSetArg(args[num_args], XtNiconName, name); num_args++; + XtSetArg(args[num_args], XtNgeometry, NULL); num_args++; + XtSetArg(args[num_args], XtNallowShellResize, TRUE); num_args++; + XtSetArg(args[num_args], XtNtransientFor, GetShell(parent)); num_args++; + popup = XtCreatePopupShell(name, transientShellWidgetClass, + parent, args, num_args); + + form = XtCreateManagedWidget(FORM_NAME, formWidgetClass, popup, + (ArgList)NULL, ZERO); + XtManageChild (form); + + (*func) (form, ptr, parent); + return(popup); +} + + /* Function Name: GetShell + * Description: Walks up the widget hierarchy to find the + * nearest shell widget. + * Arguments: w - the widget whose parent shell should be returned. + * Returns: The shell widget among the ancestors of w that is the + * fewest levels up in the widget hierarchy. + */ + +static Widget +GetShell(w) +Widget w; +{ + while ((w != NULL) && !XtIsShell(w)) + w = XtParent(w); + + return (w); +} + +static Boolean InParams(str, p, n) + String str; + String *p; + Cardinal n; +{ + int i; + for (i=0; i < n; p++, i++) + if (! XmuCompareISOLatin1(*p, str)) return True; + return False; +} + +static char *WM_DELETE_WINDOW = "WM_DELETE_WINDOW"; + +static void WMProtocols(w, event, params, num_params) + Widget w; /* popup shell */ + XEvent *event; + String *params; + Cardinal *num_params; +{ + Atom wm_delete_window; + Atom wm_protocols; + + wm_delete_window = XInternAtom(XtDisplay(w), WM_DELETE_WINDOW, True); + wm_protocols = XInternAtom(XtDisplay(w), "WM_PROTOCOLS", True); + + /* Respond to a recognized WM protocol request iff + * event type is ClientMessage and no parameters are passed, or + * event type is ClientMessage and event data is matched to parameters, or + * event type isn't ClientMessage and parameters make a request. + */ +#define DO_DELETE_WINDOW InParams(WM_DELETE_WINDOW, params, *num_params) + + if ((event->type == ClientMessage && + event->xclient.message_type == wm_protocols && + event->xclient.data.l[0] == wm_delete_window && + (*num_params == 0 || DO_DELETE_WINDOW)) + || + (event->type != ClientMessage && DO_DELETE_WINDOW)) { + +#undef DO_DELETE_WINDOW + + Widget cancel; + char descendant[DISMISS_NAME_LEN + 2]; + (void) sprintf(descendant, "*%s", DISMISS_NAME); + cancel = XtNameToWidget(w, descendant); + if (cancel) XtCallCallbacks(cancel, XtNcallback, (XtPointer)NULL); + } +} + +static void SetWMProtocolTranslations(w) + Widget w; /* realized popup shell */ +{ + int i; + XtAppContext app_context; + Atom wm_delete_window; + static XtTranslations compiled_table; /* initially 0 */ + static XtAppContext *app_context_list; /* initially 0 */ + static Cardinal list_size; /* initially 0 */ + + app_context = XtWidgetToApplicationContext(w); + + /* parse translation table once */ + if (! compiled_table) compiled_table = XtParseTranslationTable + ("<Message>WM_PROTOCOLS: XawWMProtocols()\n"); + + /* add actions once per application context */ + for (i=0; i < list_size && app_context_list[i] != app_context; i++) ; + if (i == list_size) { + XtActionsRec actions[1]; + actions[0].string = "XawWMProtocols"; + actions[0].proc = WMProtocols; + list_size++; + app_context_list = (XtAppContext *) XtRealloc + ((char *)app_context_list, list_size * sizeof(XtAppContext)); + XtAppAddActions(app_context, actions, 1); + app_context_list[i] = app_context; + } + + /* establish communication between the window manager and each shell */ + XtAugmentTranslations(w, compiled_table); + wm_delete_window = XInternAtom(XtDisplay(w), WM_DELETE_WINDOW, False); + (void) XSetWMProtocols(XtDisplay(w), XtWindow(w), &wm_delete_window, 1); +} diff --git a/src/TextSink.c b/src/TextSink.c new file mode 100644 index 0000000..7c7e2a9 --- /dev/null +++ b/src/TextSink.c @@ -0,0 +1,779 @@ +/* $XConsortium: TextSink.c,v 1.19 94/04/17 20:13:11 kaleb Exp $ */ +/* + +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +/* + * Author: Chris Peterson, MIT X Consortium. + * + * Much code taken from X11R3 AsciiSink. + */ + +/* + * TextSink.c - TextSink object. (For use with the text widget). + * + */ + +#include <stdio.h> +#include <ctype.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/TextSinkP.h> +#include <X11/Xaw3d/TextP.h> + +/**************************************************************** + * + * Full class record constant + * + ****************************************************************/ + +static void ClassPartInitialize(), Initialize(), Destroy(); +static Boolean SetValues(); + +static int MaxHeight(), MaxLines(); +static void DisplayText(), InsertCursor(), ClearToBackground(), FindPosition(); +static void FindDistance(), Resolve(), SetTabs(), GetCursorBounds(); + +#define offset(field) XtOffsetOf(TextSinkRec, text_sink.field) +static XtResource resources[] = { + {XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel), + offset(foreground), XtRString, XtDefaultForeground}, + {XtNbackground, XtCBackground, XtRPixel, sizeof (Pixel), + offset(background), XtRString, XtDefaultBackground}, +}; +#undef offset + +#define SuperClass (&objectClassRec) +TextSinkClassRec textSinkClassRec = { + { +/* core_class fields */ + /* superclass */ (WidgetClass) SuperClass, + /* class_name */ "TextSink", + /* widget_size */ sizeof(TextSinkRec), + /* class_initialize */ XawInitializeWidgetSet, + /* class_part_initialize */ ClassPartInitialize, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* obj1 */ NULL, + /* obj2 */ NULL, + /* obj3 */ 0, + /* resources */ resources, + /* num_resources */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* obj4 */ FALSE, + /* obj5 */ FALSE, + /* obj6 */ FALSE, + /* obj7 */ FALSE, + /* destroy */ Destroy, + /* obj8 */ NULL, + /* obj9 */ NULL, + /* set_values */ SetValues, + /* set_values_hook */ NULL, + /* obj10 */ NULL, + /* get_values_hook */ NULL, + /* obj11 */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* obj12 */ NULL, + /* obj13 */ NULL, + /* obj14 */ NULL, + /* extension */ NULL + }, +/* textSink_class fields */ + { + /* DisplayText */ DisplayText, + /* InsertCursor */ InsertCursor, + /* ClearToBackground */ ClearToBackground, + /* FindPosition */ FindPosition, + /* FindDistance */ FindDistance, + /* Resolve */ Resolve, + /* MaxLines */ MaxLines, + /* MaxHeight */ MaxHeight, + /* SetTabs */ SetTabs, + /* GetCursorBounds */ GetCursorBounds, + } +}; + +WidgetClass textSinkObjectClass = (WidgetClass)&textSinkClassRec; + +static void +ClassPartInitialize(wc) +WidgetClass wc; +{ + TextSinkObjectClass t_src, superC; + + t_src = (TextSinkObjectClass) wc; + superC = (TextSinkObjectClass) t_src->object_class.superclass; + +/* + * We don't need to check for null super since we'll get to TextSink + * eventually. + */ + + if (t_src->text_sink_class.DisplayText == XtInheritDisplayText) + t_src->text_sink_class.DisplayText = superC->text_sink_class.DisplayText; + + if (t_src->text_sink_class.InsertCursor == XtInheritInsertCursor) + t_src->text_sink_class.InsertCursor = + superC->text_sink_class.InsertCursor; + + if (t_src->text_sink_class.ClearToBackground== XtInheritClearToBackground) + t_src->text_sink_class.ClearToBackground = + superC->text_sink_class.ClearToBackground; + + if (t_src->text_sink_class.FindPosition == XtInheritFindPosition) + t_src->text_sink_class.FindPosition = + superC->text_sink_class.FindPosition; + + if (t_src->text_sink_class.FindDistance == XtInheritFindDistance) + t_src->text_sink_class.FindDistance = + superC->text_sink_class.FindDistance; + + if (t_src->text_sink_class.Resolve == XtInheritResolve) + t_src->text_sink_class.Resolve = superC->text_sink_class.Resolve; + + if (t_src->text_sink_class.MaxLines == XtInheritMaxLines) + t_src->text_sink_class.MaxLines = superC->text_sink_class.MaxLines; + + if (t_src->text_sink_class.MaxHeight == XtInheritMaxHeight) + t_src->text_sink_class.MaxHeight = superC->text_sink_class.MaxHeight; + + if (t_src->text_sink_class.SetTabs == XtInheritSetTabs) + t_src->text_sink_class.SetTabs = superC->text_sink_class.SetTabs; + + if (t_src->text_sink_class.GetCursorBounds == XtInheritGetCursorBounds) + t_src->text_sink_class.GetCursorBounds = + superC->text_sink_class.GetCursorBounds; +} + +/* Function Name: Initialize + * Description: Initializes the TextSink Object. + * Arguments: request, new - the requested and new values for the object + * instance. + * Returns: none. + * + */ + +/* ARGSUSED */ +static void +Initialize(request, new, args, num_args) +Widget request, new; +ArgList args; +Cardinal *num_args; +{ + TextSinkObject sink = (TextSinkObject) new; + + sink->text_sink.tab_count = 0; /* Initialize the tab stops. */ + sink->text_sink.tabs = NULL; + sink->text_sink.char_tabs = NULL; +} + +/* Function Name: Destroy + * Description: This function cleans up when the object is + * destroyed. + * Arguments: w - the TextSink Object. + * Returns: none. + */ + +static void +Destroy(w) +Widget w; +{ + TextSinkObject sink = (TextSinkObject) w; + + XtFree((char *) sink->text_sink.tabs); + XtFree((char *) sink->text_sink.char_tabs); +} + +/* Function Name: SetValues + * Description: Sets the values for the TextSink + * Arguments: current - current state of the object. + * request - what was requested. + * new - what the object will become. + * Returns: True if redisplay is needed. + */ + +/* ARGSUSED */ +static Boolean +SetValues(current, request, new, args, num_args) +Widget current, request, new; +ArgList args; +Cardinal *num_args; +{ + TextSinkObject w = (TextSinkObject) new; + TextSinkObject old_w = (TextSinkObject) current; + + if (w->text_sink.foreground != old_w->text_sink.foreground) + ((TextWidget)XtParent(new))->text.redisplay_needed = True; + + return FALSE; +} + +/************************************************************ + * + * Class specific methods. + * + ************************************************************/ + +/* Function Name: DisplayText + * Description: Stub function that in subclasses will display text. + * Arguments: w - the TextSink Object. + * x, y - location to start drawing text. + * pos1, pos2 - location of starting and ending points + * in the text buffer. + * highlight - hightlight this text? + * Returns: none. + * + * This function doesn't actually display anything, it is only a place + * holder. + */ + +/* ARGSUSED */ +static void +DisplayText(w, x, y, pos1, pos2, highlight) +Widget w; +Position x, y; +Boolean highlight; +XawTextPosition pos1, pos2; +{ + return; +} + +/* Function Name: InsertCursor + * Description: Places the InsertCursor. + * Arguments: w - the TextSink Object. + * x, y - location for the cursor. + * staye - whether to turn the cursor on, or off. + * Returns: none. + * + * This function doesn't actually display anything, it is only a place + * holder. + */ + +/* ARGSUSED */ +static void +InsertCursor(w, x, y, state) +Widget w; +Position x, y; +XawTextInsertState state; +{ + return; +} + +/* Function Name: ClearToBackground + * Description: Clears a region of the sink to the background color. + * Arguments: w - the TextSink Object. + * x, y - location of area to clear. + * width, height - size of area to clear + * Returns: void. + * + */ + +/* ARGSUSED */ +static void +ClearToBackground (w, x, y, width, height) +Widget w; +Position x, y; +Dimension width, height; +{ +/* + * Don't clear in height or width are zero. + * XClearArea() has special semantic for these values. + */ + + if ( (height == 0) || (width == 0) ) return; + XClearArea(XtDisplayOfObject(w), XtWindowOfObject(w), + x, y, width, height, False); +} + +/* Function Name: FindPosition + * Description: Finds a position in the text. + * Arguments: w - the TextSink Object. + * fromPos - reference position. + * fromX - reference location. + * width, - width of section to paint text. + * stopAtWordBreak - returned position is a word break? + * resPos - Position to return. *** RETURNED *** + * resWidth - Width actually used. *** RETURNED *** + * resHeight - Height actually used. *** RETURNED *** + * Returns: none (see above). + */ + +/* ARGSUSED */ +static void +FindPosition(w, fromPos, fromx, width, stopAtWordBreak, + resPos, resWidth, resHeight) +Widget w; +XawTextPosition fromPos; +int fromx, width; +Boolean stopAtWordBreak; +XawTextPosition *resPos; +int *resWidth, *resHeight; +{ + *resPos = fromPos; + *resHeight = *resWidth = 0; +} + +/* Function Name: FindDistance + * Description: Find the Pixel Distance between two text Positions. + * Arguments: w - the TextSink Object. + * fromPos - starting Position. + * fromX - x location of starting Position. + * toPos - end Position. + * resWidth - Distance between fromPos and toPos. + * resPos - Acutal toPos used. + * resHeight - Height required by this text. + * Returns: none. + */ + +/* ARGSUSED */ +static void +FindDistance (w, fromPos, fromx, toPos, resWidth, resPos, resHeight) +Widget w; +XawTextPosition fromPos; +int fromx; +XawTextPosition toPos; +int *resWidth; +XawTextPosition *resPos; +int *resHeight; +{ + *resWidth = *resHeight = 0; + *resPos = fromPos; +} + +/* Function Name: Resolve + * Description: Resloves a location to a position. + * Arguments: w - the TextSink Object. + * pos - a reference Position. + * fromx - a reference Location. + * width - width to move. + * resPos - the resulting position. + * Returns: none + */ + +/* ARGSUSED */ +static void +Resolve (w, pos, fromx, width, resPos) +Widget w; +XawTextPosition pos; +int fromx, width; +XawTextPosition *resPos; +{ + *resPos = pos; +} + +/* Function Name: MaxLines + * Description: Finds the Maximum number of lines that will fit in + * a given height. + * Arguments: w - the TextSink Object. + * height - height to fit lines into. + * Returns: the number of lines that will fit. + */ + +/* ARGSUSED */ +static int +MaxLines(w, height) +Widget w; +Dimension height; +{ + /* + * The fontset has gone down to descent Sink Widget, so + * the functions such MaxLines, SetTabs... are bound to the descent. + * + * by Li Yuhong, Jan. 15, 1991 + */ + return 0; +} + +/* Function Name: MaxHeight + * Description: Finds the Minium height that will contain a given number + * lines. + * Arguments: w - the TextSink Object. + * lines - the number of lines. + * Returns: the height. + */ + +/* ARGSUSED */ +static int +MaxHeight(w, lines) +Widget w; +int lines; +{ + return 0; +} + +/* Function Name: SetTabs + * Description: Sets the Tab stops. + * Arguments: w - the TextSink Object. + * tab_count - the number of tabs in the list. + * tabs - the text positions of the tabs. + * Returns: none + */ + +/*ARGSUSED*/ +static void +SetTabs(w, tab_count, tabs) +Widget w; +int tab_count; +short *tabs; +{ + return; +} + +/* Function Name: GetCursorBounds + * Description: Finds the bounding box for the insert curor (caret). + * Arguments: w - the TextSinkObject. + * rect - an X rectance containing the cursor bounds. + * Returns: none (fills in rect). + */ + +/* ARGSUSED */ +static void +GetCursorBounds(w, rect) +Widget w; +XRectangle * rect; +{ + rect->x = rect->y = rect->width = rect->height = 0; +} +/************************************************************ + * + * Public Functions. + * + ************************************************************/ + + +/* Function Name: XawTextSinkDisplayText + * Description: Stub function that in subclasses will display text. + * Arguments: w - the TextSink Object. + * x, y - location to start drawing text. + * pos1, pos2 - location of starting and ending points + * in the text buffer. + * highlight - hightlight this text? + * Returns: none. + * + * This function doesn't actually display anything, it is only a place + * holder. + */ + +/* ARGSUSED */ +void +#if NeedFunctionPrototypes +XawTextSinkDisplayText(Widget w, +#if NeedWidePrototypes + /* Position */ int x, /* Position */ int y, +#else + Position x, Position y, +#endif + XawTextPosition pos1, XawTextPosition pos2, +#if NeedWidePrototypes + /* Boolean */ int highlight) +#else + Boolean highlight) +#endif +#else +XawTextSinkDisplayText(w, x, y, pos1, pos2, highlight) +Widget w; +Position x, y; +Boolean highlight; +XawTextPosition pos1, pos2; +#endif +{ + TextSinkObjectClass class = (TextSinkObjectClass) w->core.widget_class; + + (*class->text_sink_class.DisplayText)(w, x, y, pos1, pos2, highlight); +} + +/* Function Name: XawTextSinkInsertCursor + * Description: Places the InsertCursor. + * Arguments: w - the TextSink Object. + * x, y - location for the cursor. + * staye - whether to turn the cursor on, or off. + * Returns: none. + * + * This function doesn't actually display anything, it is only a place + * holder. + */ + +/* ARGSUSED */ +void +#if NeedFunctionPrototypes +XawTextSinkInsertCursor(Widget w, +#if NeedWidePrototypes + int x, int y, int state) +#else + Position x, Position y, XawTextInsertState state) +#endif +#else +XawTextSinkInsertCursor(w, x, y, state) +Widget w; +Position x, y; +XawTextInsertState state; +#endif +{ + TextSinkObjectClass class = (TextSinkObjectClass) w->core.widget_class; + + (*class->text_sink_class.InsertCursor)(w, x, y, state); +} + + +/* Function Name: XawTextSinkClearToBackground + * Description: Clears a region of the sink to the background color. + * Arguments: w - the TextSink Object. + * x, y - location of area to clear. + * width, height - size of area to clear + * Returns: void. + * + * This function doesn't actually display anything, it is only a place + * holder. + */ + +/* ARGSUSED */ +void +#if NeedFunctionPrototypes +XawTextSinkClearToBackground (Widget w, +#if NeedWidePrototypes + int x, int y, int width, int height) +#else + Position x, Position y, + Dimension width, Dimension height) +#endif +#else +XawTextSinkClearToBackground (w, x, y, width, height) +Widget w; +Position x, y; +Dimension width, height; +#endif +{ + TextSinkObjectClass class = (TextSinkObjectClass) w->core.widget_class; + + (*class->text_sink_class.ClearToBackground)(w, x, y, width, height); +} + +/* Function Name: XawTextSinkFindPosition + * Description: Finds a position in the text. + * Arguments: w - the TextSink Object. + * fromPos - reference position. + * fromX - reference location. + * width, - width of section to paint text. + * stopAtWordBreak - returned position is a word break? + * resPos - Position to return. *** RETURNED *** + * resWidth - Width actually used. *** RETURNED *** + * resHeight - Height actually used. *** RETURNED *** + * Returns: none (see above). + */ + +/* ARGSUSED */ +void +#if NeedFunctionPrototypes +XawTextSinkFindPosition(Widget w, XawTextPosition fromPos, int fromx, + int width, +#if NeedWidePrototypes + /* Boolean */ int stopAtWordBreak, +#else + Boolean stopAtWordBreak, +#endif + XawTextPosition *resPos, int *resWidth, int *resHeight) +#else +XawTextSinkFindPosition(w, fromPos, fromx, width, stopAtWordBreak, + resPos, resWidth, resHeight) +Widget w; +XawTextPosition fromPos; +int fromx, width; +Boolean stopAtWordBreak; +XawTextPosition *resPos; +int *resWidth, *resHeight; +#endif +{ + TextSinkObjectClass class = (TextSinkObjectClass) w->core.widget_class; + + (*class->text_sink_class.FindPosition)(w, fromPos, fromx, width, + stopAtWordBreak, + resPos, resWidth, resHeight); +} + +/* Function Name: XawTextSinkFindDistance + * Description: Find the Pixel Distance between two text Positions. + * Arguments: w - the TextSink Object. + * fromPos - starting Position. + * fromX - x location of starting Position. + * toPos - end Position. + * resWidth - Distance between fromPos and toPos. + * resPos - Acutal toPos used. + * resHeight - Height required by this text. + * Returns: none. + */ + +/* ARGSUSED */ +void +#if NeedFunctionPrototypes +XawTextSinkFindDistance (Widget w, XawTextPosition fromPos, int fromx, + XawTextPosition toPos, int *resWidth, + XawTextPosition *resPos, int *resHeight) +#else +XawTextSinkFindDistance (w, fromPos, fromx, toPos, resWidth, resPos, resHeight) +Widget w; +XawTextPosition fromPos, toPos, *resPos; +int fromx, *resWidth, *resHeight; +#endif +{ + TextSinkObjectClass class = (TextSinkObjectClass) w->core.widget_class; + + (*class->text_sink_class.FindDistance)(w, fromPos, fromx, toPos, + resWidth, resPos, resHeight); +} + +/* Function Name: XawTextSinkResolve + * Description: Resloves a location to a position. + * Arguments: w - the TextSink Object. + * pos - a reference Position. + * fromx - a reference Location. + * width - width to move. + * resPos - the resulting position. + * Returns: none + */ + +/* ARGSUSED */ +void +#if NeedFunctionPrototypes +XawTextSinkResolve(Widget w, XawTextPosition pos, int fromx, int width, + XawTextPosition *resPos) +#else +XawTextSinkResolve(w, pos, fromx, width, resPos) +Widget w; +XawTextPosition pos; +int fromx, width; +XawTextPosition *resPos; +#endif +{ + TextSinkObjectClass class = (TextSinkObjectClass) w->core.widget_class; + + (*class->text_sink_class.Resolve)(w, pos, fromx, width, resPos); +} + +/* Function Name: XawTextSinkMaxLines + * Description: Finds the Maximum number of lines that will fit in + * a given height. + * Arguments: w - the TextSink Object. + * height - height to fit lines into. + * Returns: the number of lines that will fit. + */ + +/* ARGSUSED */ +int +#if NeedFunctionPrototypes +XawTextSinkMaxLines(Widget w, +#if NeedWidePrototypes + /* Dimension */ int height) +#else + Dimension height) +#endif +#else +XawTextSinkMaxLines(w, height) +Widget w; +Dimension height; +#endif +{ + TextSinkObjectClass class = (TextSinkObjectClass) w->core.widget_class; + + return((*class->text_sink_class.MaxLines)(w, height)); +} + +/* Function Name: XawTextSinkMaxHeight + * Description: Finds the Minimum height that will contain a given number + * lines. + * Arguments: w - the TextSink Object. + * lines - the number of lines. + * Returns: the height. + */ + +/* ARGSUSED */ +int +#if NeedFunctionPrototypes +XawTextSinkMaxHeight(Widget w, int lines) +#else +XawTextSinkMaxHeight(w, lines) +Widget w; +int lines; +#endif +{ + TextSinkObjectClass class = (TextSinkObjectClass) w->core.widget_class; + + return((*class->text_sink_class.MaxHeight)(w, lines)); +} + +/* Function Name: XawTextSinkSetTabs + * Description: Sets the Tab stops. + * Arguments: w - the TextSink Object. + * tab_count - the number of tabs in the list. + * tabs - the text positions of the tabs. + * Returns: none + */ + +void +#if NeedFunctionPrototypes +XawTextSinkSetTabs(Widget w, int tab_count, int *tabs) +#else +XawTextSinkSetTabs(w, tab_count, tabs) +Widget w; +int tab_count, *tabs; +#endif +{ + if (tab_count > 0) { + TextSinkObjectClass class = (TextSinkObjectClass) w->core.widget_class; + short *char_tabs = (short*)XtMalloc( (unsigned)tab_count*sizeof(short) ); + short *tab; + int i; + + for (i = tab_count, tab = char_tabs; i; i--) *tab++ = (short)*tabs++; + + (*class->text_sink_class.SetTabs)(w, tab_count, char_tabs); + XtFree((char *)char_tabs); + } +} + +/* Function Name: XawTextSinkGetCursorBounds + * Description: Finds the bounding box for the insert curor (caret). + * Arguments: w - the TextSinkObject. + * rect - an X rectance containing the cursor bounds. + * Returns: none (fills in rect). + */ + +/* ARGSUSED */ +void +#if NeedFunctionPrototypes +XawTextSinkGetCursorBounds(Widget w, XRectangle *rect) +#else +XawTextSinkGetCursorBounds(w, rect) +Widget w; +XRectangle * rect; +#endif +{ + TextSinkObjectClass class = (TextSinkObjectClass) w->core.widget_class; + + (*class->text_sink_class.GetCursorBounds)(w, rect); +} diff --git a/src/TextSink.h b/src/TextSink.h new file mode 100644 index 0000000..957938b --- /dev/null +++ b/src/TextSink.h @@ -0,0 +1,317 @@ +/* + * $XConsortium: TextSink.h,v 1.10 94/04/17 20:13:12 kaleb Exp $ + */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _XawTextSink_h +#define _XawTextSink_h + +#include <X11/Xaw3d/Text.h> + +/*********************************************************************** + * + * TextSink Object + * + ***********************************************************************/ + +/* Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + foreground Foreground Pixel XtDefaultForeground + background Background Pixel XtDefaultBackground + +*/ + +/* Class record constants */ + +extern WidgetClass textSinkObjectClass; + +typedef struct _TextSinkClassRec *TextSinkObjectClass; +typedef struct _TextSinkRec *TextSinkObject; + +typedef enum {XawisOn, XawisOff} XawTextInsertState; + +/************************************************************ + * + * Public Functions. + * + ************************************************************/ + +_XFUNCPROTOBEGIN + +/* Function Name: XawTextSinkDisplayText + * Description: Stub function that in subclasses will display text. + * Arguments: w - the TextSink Object. + * x, y - location to start drawing text. + * pos1, pos2 - location of starting and ending points + * in the text buffer. + * highlight - hightlight this text? + * Returns: none. + * + * This function doesn't actually display anything, it is only a place + * holder. + */ + +extern void XawTextSinkDisplayText( +#if NeedFunctionPrototypes + Widget /* w */, +#if NeedWidePrototypes + /* Position */ int /* x */, + /* Position */ int /* y */, +#else + Position /* x */, + Position /* y */, +#endif + XawTextPosition /* pos1 */, + XawTextPosition /* pos2 */, +#if NeedWidePrototypes + /* Boolean */ int /* highlight */ +#else + Boolean /* highlight */ +#endif +#endif +); + +/* Function Name: XawTextSinkInsertCursor + * Description: Places the InsertCursor. + * Arguments: w - the TextSink Object. + * x, y - location for the cursor. + * staye - whether to turn the cursor on, or off. + * Returns: none. + * + * This function doesn't actually display anything, it is only a place + * holder. + */ + +extern void XawTextSinkInsertCursor( +#if NeedFunctionPrototypes + Widget /* w */, +#if NeedWidePrototypes + /* Position */ int /* x */, + /* Position */ int /* y */, + /* XawTextInsertState */ int /* state */ +#else + Position /* x */, + Position /* y */, + XawTextInsertState /* state */ +#endif +#endif +); + +/* Function Name: XawTextSinkClearToBackground + * Description: Clears a region of the sink to the background color. + * Arguments: w - the TextSink Object. + * x, y - location of area to clear. + * width, height - size of area to clear + * Returns: void. + * + * This function doesn't actually display anything, it is only a place + * holder. + */ + +extern void XawTextSinkClearToBackground( +#if NeedFunctionPrototypes + Widget /* w */, +#if NeedWidePrototypes + /* Position */ int /* x */, + /* Position */ int /* y */, + /* Dimension */ int /* width */, + /* Dimension */ int /* height */ +#else + Position /* x */, + Position /* y */, + Dimension /* width */, + Dimension /* height */ +#endif +#endif +); + +/* Function Name: XawTextSinkFindPosition + * Description: Finds a position in the text. + * Arguments: w - the TextSink Object. + * fromPos - reference position. + * fromX - reference location. + * width, - width of section to paint text. + * stopAtWordBreak - returned position is a word break? + * resPos - Position to return. *** RETURNED *** + * resWidth - Width actually used. *** RETURNED *** + * resHeight - Height actually used. *** RETURNED *** + * Returns: none (see above). + */ + +extern void XawTextSinkFindPosition( +#if NeedFunctionPrototypes + Widget /* w */, + XawTextPosition /* fromPos */, + int /* fromX */, + int /* width */, +#if NeedWidePrototypes + /* Boolean */ int /* stopAtWordBreak */, +#else + Boolean /* stopAtWordBreak */, +#endif + XawTextPosition* /* pos_return */, + int* /* width_return */, + int* /* height_return */ +#endif +); + +/* Function Name: XawTextSinkFindDistance + * Description: Find the Pixel Distance between two text Positions. + * Arguments: w - the TextSink Object. + * fromPos - starting Position. + * fromX - x location of starting Position. + * toPos - end Position. + * resWidth - Distance between fromPos and toPos. + * resPos - Acutal toPos used. + * resHeight - Height required by this text. + * Returns: none. + */ + +extern void XawTextSinkFindDistance ( +#if NeedFunctionPrototypes + Widget /* w */, + XawTextPosition /* fromPos */, + int /* fromX */, + XawTextPosition /* toPos */, + int* /* width_return */, + XawTextPosition* /* pos_return */, + int* /* height_return */ +#endif +); + +/* Function Name: XawTextSinkResolve + * Description: Resloves a location to a position. + * Arguments: w - the TextSink Object. + * pos - a reference Position. + * fromx - a reference Location. + * width - width to move. + * resPos - the resulting position. + * Returns: none + */ + +extern void XawTextSinkResolve( +#if NeedFunctionPrototypes + Widget /* w */, + XawTextPosition /* fromPos */, + int /* fromX */, + int /* width */, + XawTextPosition* /* pos_return */ +#endif +); + +/* Function Name: XawTextSinkMaxLines + * Description: Finds the Maximum number of lines that will fit in + * a given height. + * Arguments: w - the TextSink Object. + * height - height to fit lines into. + * Returns: the number of lines that will fit. + */ + +extern int XawTextSinkMaxLines( +#if NeedFunctionPrototypes + Widget /* w */, +#if NeedWidePrototypes + /* Dimension */ int /* height */ +#else + Dimension /* height */ +#endif +#endif +); + +/* Function Name: XawTextSinkMaxHeight + * Description: Finds the Minium height that will contain a given number + * lines. + * Arguments: w - the TextSink Object. + * lines - the number of lines. + * Returns: the height. + */ + +extern int XawTextSinkMaxHeight( +#if NeedFunctionPrototypes + Widget /* w */, + int /* lines */ +#endif +); + +/* Function Name: XawTextSinkSetTabs + * Description: Sets the Tab stops. + * Arguments: w - the TextSink Object. + * tab_count - the number of tabs in the list. + * tabs - the text positions of the tabs. + * Returns: none + */ + +extern void XawTextSinkSetTabs( +#if NeedFunctionPrototypes + Widget /* w */, + int /* tab_count */, + int* /* tabs */ +#endif +); + +/* Function Name: XawTextSinkGetCursorBounds + * Description: Finds the bounding box for the insert curor (caret). + * Arguments: w - the TextSinkObject. + * rect - an X rectance containing the cursor bounds. + * Returns: none (fills in rect). + */ + +extern void XawTextSinkGetCursorBounds( +#if NeedFunctionPrototypes + Widget /* w */, + XRectangle* /* rect_return */ +#endif +); + +_XFUNCPROTOEND + +#endif /* _XawTextSrc_h */ diff --git a/src/TextSinkP.h b/src/TextSinkP.h new file mode 100644 index 0000000..e45bf75 --- /dev/null +++ b/src/TextSinkP.h @@ -0,0 +1,143 @@ +/* +* $XConsortium: TextSinkP.h,v 1.6 94/04/17 20:13:13 kaleb Exp $ +*/ + + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * TextSinkP.h - Private definitions for TextSink object + * + */ + +#ifndef _XawTextSinkP_h +#define _XawTextSinkP_h + +/*********************************************************************** + * + * TextSink Object Private Data + * + ***********************************************************************/ + +#include <X11/Xaw3d/TextSink.h> +#include <X11/Xaw3d/TextP.h> /* This source works with the Text widget. */ +#include <X11/Xaw3d/TextSrcP.h> /* This source works with the Text Source. */ + +/************************************************************ + * + * New fields for the TextSink object class record. + * + ************************************************************/ + +typedef struct _TextSinkClassPart { + void (*DisplayText)(); + void (*InsertCursor)(); + void (*ClearToBackground)(); + void (*FindPosition)(); + void (*FindDistance)(); + void (*Resolve)(); + int (*MaxLines)(); + int (*MaxHeight)(); + void (*SetTabs)(); + void (*GetCursorBounds)(); +} TextSinkClassPart; + +/* Full class record declaration */ +typedef struct _TextSinkClassRec { + ObjectClassPart object_class; + TextSinkClassPart text_sink_class; +} TextSinkClassRec; + +extern TextSinkClassRec textSinkClassRec; + +/* New fields for the TextSink object record */ +typedef struct { + /* resources */ + Pixel foreground; /* Foreground color. */ + Pixel background; /* Background color. */ + + /* private state. */ + Position *tabs; /* The tab stops as pixel values. */ + short *char_tabs; /* The tabs stops as character values. */ + int tab_count; /* number of items in tabs */ + +} TextSinkPart; + +/**************************************************************** + * + * Full instance record declaration + * + ****************************************************************/ + +typedef struct _TextSinkRec { + ObjectPart object; + TextSinkPart text_sink; +} TextSinkRec; + +/************************************************************ + * + * Private declarations. + * + ************************************************************/ + +typedef int (*_XawSinkIntFunc)(); +typedef void (*_XawSinkVoidFunc)(); + +#define XtInheritDisplayText ((_XawSinkVoidFunc) _XtInherit) +#define XtInheritInsertCursor ((_XawSinkVoidFunc) _XtInherit) +#define XtInheritClearToBackground ((_XawSinkVoidFunc) _XtInherit) +#define XtInheritFindPosition ((_XawSinkVoidFunc) _XtInherit) +#define XtInheritFindDistance ((_XawSinkVoidFunc) _XtInherit) +#define XtInheritResolve ((_XawSinkVoidFunc) _XtInherit) +#define XtInheritMaxLines ((_XawSinkIntFunc) _XtInherit) +#define XtInheritMaxHeight ((_XawSinkIntFunc) _XtInherit) +#define XtInheritSetTabs ((_XawSinkVoidFunc) _XtInherit) +#define XtInheritGetCursorBounds ((_XawSinkVoidFunc) _XtInherit) + +#endif /* _XawTextSinkP_h */ diff --git a/src/TextSrc.c b/src/TextSrc.c new file mode 100644 index 0000000..d954954 --- /dev/null +++ b/src/TextSrc.c @@ -0,0 +1,676 @@ +/* $XConsortium: TextSrc.c,v 1.15 94/04/17 20:13:14 kaleb Exp $ */ +/* + +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +/* + * Author: Chris Peterson, MIT X Consortium. + * Much code taken from X11R3 String and Disk Sources. + */ + +/* + * TextSrc.c - TextSrc object. (For use with the text widget). + * + */ + +#include "Xaw3dP.h" +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xutil.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/TextSrcP.h> +#include <X11/Xmu/Atoms.h> +#include <X11/Xmu/CharSet.h> +#ifdef XAW_INTERNATIONALIZATION +#include "XawI18n.h" +#endif +#include <stdio.h> +#include <ctype.h> + +/**************************************************************** + * + * Full class record constant + * + ****************************************************************/ + +/* Private Data */ + +#define offset(field) XtOffsetOf(TextSrcRec, textSrc.field) +static XtResource resources[] = { + {XtNeditType, XtCEditType, XtREditMode, sizeof(XawTextEditType), + offset(edit_mode), XtRString, "read"}, +}; + +static void ClassInitialize(), ClassPartInitialize(), SetSelection(); +static void CvtStringToEditMode(); +static Boolean ConvertSelection(); +static XawTextPosition Search(), Scan(), Read(); +static int Replace(); + +#define SuperClass (&objectClassRec) +TextSrcClassRec textSrcClassRec = { + { +/* core_class fields */ + /* superclass */ (WidgetClass) SuperClass, + /* class_name */ "TextSrc", + /* widget_size */ sizeof(TextSrcRec), + /* class_initialize */ ClassInitialize, + /* class_part_initialize */ ClassPartInitialize, + /* class_inited */ FALSE, + /* initialize */ NULL, + /* initialize_hook */ NULL, + /* realize */ NULL, + /* actions */ NULL, + /* num_actions */ 0, + /* resources */ resources, + /* num_resources */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ FALSE, + /* compress_exposure */ FALSE, + /* compress_enterleave */ FALSE, + /* visible_interest */ FALSE, + /* destroy */ NULL, + /* resize */ NULL, + /* expose */ NULL, + /* set_values */ NULL, + /* set_values_hook */ NULL, + /* set_values_almost */ NULL, + /* get_values_hook */ NULL, + /* accept_focus */ NULL, + /* version */ XtVersion, + /* callback_private */ NULL, + /* tm_table */ NULL, + /* query_geometry */ NULL, + /* display_accelerator */ NULL, + /* extension */ NULL, + }, +/* textSrc_class fields */ + { + /* Read */ Read, + /* Replace */ Replace, + /* Scan */ Scan, + /* Search */ Search, + /* SetSelection */ SetSelection, + /* ConvertSelection */ ConvertSelection + } +}; + +WidgetClass textSrcObjectClass = (WidgetClass)&textSrcClassRec; + +static void +ClassInitialize () +{ + XawInitializeWidgetSet (); + XtAddConverter(XtRString, XtREditMode, CvtStringToEditMode, NULL, 0); +} + + +static void +ClassPartInitialize(wc) +WidgetClass wc; +{ + TextSrcObjectClass t_src, superC; + + t_src = (TextSrcObjectClass) wc; + superC = (TextSrcObjectClass) t_src->object_class.superclass; + +/* + * We don't need to check for null super since we'll get to TextSrc + * eventually. + */ + if (t_src->textSrc_class.Read == XtInheritRead) + t_src->textSrc_class.Read = superC->textSrc_class.Read; + + if (t_src->textSrc_class.Replace == XtInheritReplace) + t_src->textSrc_class.Replace = superC->textSrc_class.Replace; + + if (t_src->textSrc_class.Scan == XtInheritScan) + t_src->textSrc_class.Scan = superC->textSrc_class.Scan; + + if (t_src->textSrc_class.Search == XtInheritSearch) + t_src->textSrc_class.Search = superC->textSrc_class.Search; + + if (t_src->textSrc_class.SetSelection == XtInheritSetSelection) + t_src->textSrc_class.SetSelection = superC->textSrc_class.SetSelection; + + if (t_src->textSrc_class.ConvertSelection == XtInheritConvertSelection) + t_src->textSrc_class.ConvertSelection = + superC->textSrc_class.ConvertSelection; +} + +/************************************************************ + * + * Class specific methods. + * + ************************************************************/ + +/* Function Name: Read + * Description: This function reads the source. + * Arguments: w - the TextSrc Object. + * pos - position of the text to retreive. + * RETURNED text - text block that will contain returned text. + * length - maximum number of characters to read. + * Returns: The number of characters read into the buffer. + */ + +/* ARGSUSED */ +static XawTextPosition +Read(w, pos, text, length) +Widget w; +XawTextPosition pos; +XawTextBlock *text; +int length; +{ + XtAppError(XtWidgetToApplicationContext(w), + "TextSrc Object: No read function is defined."); + + return( (XawTextPosition) 0 ); /* for gcc -Wall and lint */ +} + +/* Function Name: Replace. + * Description: Replaces a block of text with new text. + * Arguments: src - the Text Source Object. + * startPos, endPos - ends of text that will be removed. + * text - new text to be inserted into buffer at startPos. + * Returns: XawEditError. + */ + +/*ARGSUSED*/ +static int +Replace (w, startPos, endPos, text) +Widget w; +XawTextPosition startPos, endPos; +XawTextBlock *text; +{ + return(XawEditError); +} + +/* Function Name: Scan + * Description: Scans the text source for the number and type + * of item specified. + * Arguments: w - the TextSrc Object. + * position - the position to start scanning. + * type - type of thing to scan for. + * dir - direction to scan. + * count - which occurance if this thing to search for. + * include - whether or not to include the character found in + * the position that is returned. + * Returns: EXITS WITH AN ERROR MESSAGE. + * + */ + +/* ARGSUSED */ +static +XawTextPosition +Scan (w, position, type, dir, count, include) +Widget w; +XawTextPosition position; +XawTextScanType type; +XawTextScanDirection dir; +int count; +Boolean include; +{ + XtAppError(XtWidgetToApplicationContext(w), + "TextSrc Object: No SCAN function is defined."); + + return( (XawTextPosition) 0 ); /* for gcc -Wall and lint */ +} + +/* Function Name: Search + * Description: Searchs the text source for the text block passed + * Arguments: w - the TextSource Object. + * position - the position to start scanning. + * dir - direction to scan. + * text - the text block to search for. + * Returns: XawTextSearchError. + */ + +/* ARGSUSED */ +static XawTextPosition +Search(w, position, dir, text) +Widget w; +XawTextPosition position; +XawTextScanDirection dir; +XawTextBlock * text; +{ + return(XawTextSearchError); +} + +/* Function Name: ConvertSelection + * Description: Dummy selection converter. + * Arguments: w - the TextSrc object. + * selection - the current selection atom. + * target - the current target atom. + * type - the type to conver the selection to. + * RETURNED value, length - the return value that has been converted. + * RETURNED format - the format of the returned value. + * Returns: TRUE if the selection has been converted. + * + */ + +/* ARGSUSED */ +static Boolean +ConvertSelection(w, selection, target, type, value, length, format) +Widget w; +Atom * selection, * target, * type; +XtPointer * value; +unsigned long * length; +int * format; +{ + return(FALSE); +} + +/* Function Name: SetSelection + * Description: allows special setting of the selection. + * Arguments: w - the TextSrc object. + * left, right - bounds of the selection. + * selection - the selection atom. + * Returns: none + */ + +/* ARGSUSED */ +static void +SetSelection(w, left, right, selection) +Widget w; +XawTextPosition left, right; +Atom selection; +{ + /* This space intentionally left blank. */ +} + + +/* ARGSUSED */ +static void +CvtStringToEditMode(args, num_args, fromVal, toVal) +XrmValuePtr args; /* unused */ +Cardinal *num_args; /* unused */ +XrmValuePtr fromVal; +XrmValuePtr toVal; +{ + static XawTextEditType editType; + static XrmQuark QRead, QAppend, QEdit; + XrmQuark q; + char lowerName[40]; + static Boolean inited = FALSE; + + if ( !inited ) { + QRead = XrmPermStringToQuark(XtEtextRead); + QAppend = XrmPermStringToQuark(XtEtextAppend); + QEdit = XrmPermStringToQuark(XtEtextEdit); + inited = TRUE; + } + + if (strlen ((char*) fromVal->addr) < sizeof lowerName) { + XmuCopyISOLatin1Lowered (lowerName, (char *)fromVal->addr); + q = XrmStringToQuark(lowerName); + + if (q == QRead) editType = XawtextRead; + else if (q == QAppend) editType = XawtextAppend; + else if (q == QEdit) editType = XawtextEdit; + else { + toVal->size = 0; + toVal->addr = NULL; + return; + } + toVal->size = sizeof editType; + toVal->addr = (XPointer) &editType; + return; + } + toVal->size = 0; + toVal->addr = NULL; +} + + + +/************************************************************ + * + * Public Functions. + * + ************************************************************/ + +/* Function Name: XawTextSourceRead + * Description: This function reads the source. + * Arguments: w - the TextSrc Object. + * pos - position of the text to retreive. + * RETURNED text - text block that will contain returned text. + * length - maximum number of characters to read. + * Returns: The number of characters read into the buffer. + */ + +XawTextPosition +#if NeedFunctionPrototypes +XawTextSourceRead(Widget w, XawTextPosition pos, XawTextBlock *text, + int length) +#else +XawTextSourceRead(w, pos, text, length) +Widget w; +XawTextPosition pos; +XawTextBlock *text; +int length; +#endif +{ + TextSrcObjectClass class = (TextSrcObjectClass) w->core.widget_class; + + if ( !XtIsSubclass( w, textSrcObjectClass ) ) + XtErrorMsg("bad argument", "textSource", "XawError", + "XawTextSourceRead's 1st parameter must be subclass of asciiSrc.", + NULL, NULL); + + return((*class->textSrc_class.Read)(w, pos, text, length)); +} + +/* Function Name: XawTextSourceReplace. + * Description: Replaces a block of text with new text. + * Arguments: src - the Text Source Object. + * startPos, endPos - ends of text that will be removed. + * text - new text to be inserted into buffer at startPos. + * Returns: XawEditError or XawEditDone. + */ + +/*ARGSUSED*/ +int +#if NeedFunctionPrototypes +XawTextSourceReplace (Widget w, XawTextPosition startPos, + XawTextPosition endPos, XawTextBlock *text) +#else +XawTextSourceReplace (w, startPos, endPos, text) +Widget w; +XawTextPosition startPos, endPos; +XawTextBlock *text; +#endif +{ + TextSrcObjectClass class = (TextSrcObjectClass) w->core.widget_class; + + if ( !XtIsSubclass( w, textSrcObjectClass ) ) + XtErrorMsg("bad argument", "textSource", "XawError", + "XawTextSourceReplace's 1st parameter must be subclass of asciiSrc.", + NULL, NULL); + + return((*class->textSrc_class.Replace)(w, startPos, endPos, text)); +} + +/* Function Name: XawTextSourceScan + * Description: Scans the text source for the number and type + * of item specified. + * Arguments: w - the TextSrc Object. + * position - the position to start scanning. + * type - type of thing to scan for. + * dir - direction to scan. + * count - which occurance if this thing to search for. + * include - whether or not to include the character found in + * the position that is returned. + * Returns: The position of the text. + * + */ + +XawTextPosition +#if NeedFunctionPrototypes +XawTextSourceScan(Widget w, XawTextPosition position, +#if NeedWidePrototypes + int type, int dir, +#else + XawTextScanType type, XawTextScanDirection dir, +#endif + int count, +#if NeedWidePrototypes + int include) +#else + Boolean include) +#endif +#else +XawTextSourceScan(w, position, type, dir, count, include) +Widget w; +XawTextPosition position; +XawTextScanType type; +XawTextScanDirection dir; +int count; +Boolean include; +#endif +{ + TextSrcObjectClass class = (TextSrcObjectClass) w->core.widget_class; + + if ( !XtIsSubclass( w, textSrcObjectClass ) ) + XtErrorMsg("bad argument", "textSource", "XawError", + "XawTextSourceScan's 1st parameter must be subclass of asciiSrc.", + NULL, NULL); + + return((*class->textSrc_class.Scan)(w, position, type, dir, count, include)); +} + +/* Function Name: XawTextSourceSearch + * Description: Searchs the text source for the text block passed + * Arguments: w - the TextSource Object. + * position - the position to start scanning. + * dir - direction to scan. + * text - the text block to search for. + * Returns: The position of the text we are searching for or + * XawTextSearchError. + */ + +XawTextPosition +#if NeedFunctionPrototypes +XawTextSourceSearch(Widget w, XawTextPosition position, +#if NeedWidePrototypes + int dir, +#else + XawTextScanDirection dir, +#endif + XawTextBlock *text) +#else +XawTextSourceSearch(w, position, dir, text) +Widget w; +XawTextPosition position; +XawTextScanDirection dir; +XawTextBlock * text; +#endif +{ + TextSrcObjectClass class = (TextSrcObjectClass) w->core.widget_class; + + if ( !XtIsSubclass( w, textSrcObjectClass ) ) + XtErrorMsg("bad argument", "textSource", "XawError", + "XawTextSourceSearch's 1st parameter must be subclass of asciiSrc.", + NULL, NULL); + + return((*class->textSrc_class.Search)(w, position, dir, text)); +} + +/* Function Name: XawTextSourceConvertSelection + * Description: Dummy selection converter. + * Arguments: w - the TextSrc object. + * selection - the current selection atom. + * target - the current target atom. + * type - the type to conver the selection to. + * RETURNED value, length - the return value that has been converted. + * RETURNED format - the format of the returned value. + * Returns: TRUE if the selection has been converted. + * + */ + +Boolean +#if NeedFunctionPrototypes +XawTextSourceConvertSelection(Widget w, Atom *selection, Atom *target, + Atom *type, XtPointer *value, + unsigned long *length, int *format) +#else +XawTextSourceConvertSelection(w, selection, + target, type, value, length, format) +Widget w; +Atom * selection, * target, * type; +XtPointer * value; +unsigned long * length; +int * format; +#endif +{ + TextSrcObjectClass class = (TextSrcObjectClass) w->core.widget_class; + + if ( !XtIsSubclass( w, textSrcObjectClass ) ) + XtErrorMsg("bad argument", "textSource", "XawError", + "XawTextSourceConvertSelectionXawTextSourceConvertSelection's 1st parameter must be subclass of asciiSrc.", + NULL, NULL); + + return((*class->textSrc_class.ConvertSelection)(w, selection, target, type, + value, length, format)); +} + +/* Function Name: XawTextSourceSetSelection + * Description: allows special setting of the selection. + * Arguments: w - the TextSrc object. + * left, right - bounds of the selection. + * selection - the selection atom. + * Returns: none + */ + +void +#if NeedFunctionPrototypes +XawTextSourceSetSelection(Widget w, XawTextPosition left, + XawTextPosition right, Atom selection) +#else +XawTextSourceSetSelection(w, left, right, selection) +Widget w; +XawTextPosition left, right; +Atom selection; +#endif +{ + TextSrcObjectClass class = (TextSrcObjectClass) w->core.widget_class; + + if ( !XtIsSubclass( w, textSrcObjectClass ) ) + XtErrorMsg("bad argument", "textSource", "XawError", + "'s 1st parameter must be subclass of asciiSrc.", + NULL, NULL); + + (*class->textSrc_class.SetSelection)(w, left, right, selection); +} + +/******************************************************************** + * + * External Functions for Multi Text. + * + ********************************************************************/ + +/* + * TextFormat(): + * returns the format of text: FMT8BIT or FMTWIDE. + * + */ +XrmQuark +#if NeedFunctionPrototypes +_XawTextFormat(TextWidget tw) +#else +_XawTextFormat(tw) + TextWidget tw; +#endif +{ + return (((TextSrcObject)(tw->text.source))->textSrc.text_format); +} + + +#ifdef XAW_INTERNATIONALIZATION +/* _XawTextWCToMB(): + * convert the wchar string to external encoding. + * The caller is responsible for freeing both the source and ret string. + * + * wstr - source wchar string. + * len_in_out - lengh of string. + * As In, length of source wchar string, measured in wchar. + * As Out, length of returned string. + */ + + +char * +_XawTextWCToMB( d, wstr, len_in_out ) + Display* d; + wchar_t* wstr; + int* len_in_out; + +{ + XTextProperty textprop; + if (XwcTextListToTextProperty(d, (wchar_t**)&wstr, 1, + XTextStyle, &textprop) < Success) { + XtWarningMsg("convertError", "textSource", "XawError", + "Non-character code(s) in buffer.", NULL, NULL); + *len_in_out = 0; + return( NULL ); + } + *len_in_out = textprop.nitems; + return((char *)textprop.value); +} + + +/* _XawTextMBToWC(): + * convert the string to internal processing codeset WC. + * The caller is responsible for freeing both the source and ret string. + * + * str - source string. + * len_in_out - lengh of string. + * As In, it is length of source string. + * As Out, it is length of returned string, measured in wchar. + */ + +wchar_t* _XawTextMBToWC( d, str, len_in_out ) +Display *d; +char *str; +int *len_in_out; +{ + if (*len_in_out == 0) { + return(NULL); + } else { + XTextProperty textprop; + char *buf; + wchar_t **wlist, *wstr; + int count; + buf = XtMalloc(*len_in_out + 1); + if (!buf) { + XtErrorMsg("convertError", "multiSourceCreate", "XawError", + "No Memory", NULL, NULL); + *len_in_out = 0; + return (NULL); /* The above function doesn't really return. */ + } + strncpy(buf, str, *len_in_out); + *(buf + *len_in_out) = '\0'; + if (XmbTextListToTextProperty(d, &buf, 1, XTextStyle, &textprop) + != Success) { + XtWarningMsg("convertError", "textSource", "XawError", + "No Memory, or Locale not supported.", NULL, NULL); + XtFree(buf); + *len_in_out = 0; + return (NULL); + } + XtFree(buf); + if (XwcTextPropertyToTextList(d, &textprop, + (wchar_t***)&wlist, &count) != Success) { + XtWarningMsg("convertError", "multiSourceCreate", "XawError", + "Non-character code(s) in source.", NULL, NULL); + *len_in_out = 0; + return (NULL); + } + wstr = wlist[0]; + *len_in_out = wcslen(wstr); + XFree((char**)wlist); /* this is evil */ + return(wstr); + } +} +#endif + diff --git a/src/TextSrc.h b/src/TextSrc.h new file mode 100644 index 0000000..edd3153 --- /dev/null +++ b/src/TextSrc.h @@ -0,0 +1,237 @@ +/* + * $XConsortium: TextSrc.h,v 1.11 94/04/17 20:13:15 kaleb Exp $ + */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _XawTextSrc_h +#define _XawTextSrc_h + +/*********************************************************************** + * + * TextSrc Object + * + ***********************************************************************/ + +#include <X11/Xaw3d/Text.h> + +/* Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + editType EditType XawTextEditType XawtextRead + +*/ + +/* Class record constants */ + +extern WidgetClass textSrcObjectClass; + +typedef struct _TextSrcClassRec *TextSrcObjectClass; +typedef struct _TextSrcRec *TextSrcObject; + +typedef enum {XawstPositions, XawstWhiteSpace, XawstEOL, XawstParagraph, + XawstAll} XawTextScanType; +typedef enum {Normal, Selected }highlightType; +typedef enum {XawsmTextSelect, XawsmTextExtend} XawTextSelectionMode; +typedef enum {XawactionStart, XawactionAdjust, XawactionEnd} + XawTextSelectionAction; + +/* + * Error Conditions: + */ + +#define XawTextReadError -1 +#define XawTextScanError -1 + +/************************************************************ + * + * Public Functions. + * + ************************************************************/ + +_XFUNCPROTOBEGIN + +/* Function Name: XawTextSourceRead + * Description: This function reads the source. + * Arguments: w - the TextSrc Object. + * pos - position of the text to retreive. + * RETURNED text - text block that will contain returned text. + * length - maximum number of characters to read. + * Returns: The number of characters read into the buffer. + */ + +extern XawTextPosition XawTextSourceRead( +#if NeedFunctionPrototypes + Widget /* w */, + XawTextPosition /* pos */, + XawTextBlock* /* text_return */, + int /* length */ +#endif +); + +/* Function Name: XawTextSourceReplace. + * Description: Replaces a block of text with new text. + * Arguments: src - the Text Source Object. + * startPos, endPos - ends of text that will be removed. + * text - new text to be inserted into buffer at startPos. + * Returns: XawEditError or XawEditDone. + */ + +extern int XawTextSourceReplace ( +#if NeedFunctionPrototypes + Widget /* w */, + XawTextPosition /* start */, + XawTextPosition /* end */, + XawTextBlock* /* text */ +#endif +); + +/* Function Name: XawTextSourceScan + * Description: Scans the text source for the number and type + * of item specified. + * Arguments: w - the TextSrc Object. + * position - the position to start scanning. + * type - type of thing to scan for. + * dir - direction to scan. + * count - which occurance if this thing to search for. + * include - whether or not to include the character found in + * the position that is returned. + * Returns: The position of the text. + * + */ + +extern XawTextPosition XawTextSourceScan( +#if NeedFunctionPrototypes + Widget /* w */, + XawTextPosition /* position */, +#if NeedWidePrototypes + /* XawTextScanType */ int /* type */, + /* XawTextScanDirection */ int /* dir */, +#else + XawTextScanType /* type */, + XawTextScanDirection /* dir */, +#endif + int /* count */, +#if NeedWidePrototypes + /* Boolean */ int /* include */ +#else + Boolean /* include */ +#endif +#endif +); + +/* Function Name: XawTextSourceSearch + * Description: Searchs the text source for the text block passed + * Arguments: w - the TextSource Object. + * position - the position to start scanning. + * dir - direction to scan. + * text - the text block to search for. + * Returns: The position of the text we are searching for or + * XawTextSearchError. + */ + +extern XawTextPosition XawTextSourceSearch( +#if NeedFunctionPrototypes + Widget /* w */, + XawTextPosition /* position */, +#if NeedWidePrototypes + /* XawTextScanDirection */ int /* dir */, +#else + XawTextScanDirection /* dir */, +#endif + XawTextBlock* /* text */ +#endif +); + +/* Function Name: XawTextSourceConvertSelection + * Description: Dummy selection converter. + * Arguments: w - the TextSrc object. + * selection - the current selection atom. + * target - the current target atom. + * type - the type to conver the selection to. + * RETURNED value, length - the return value that has been converted. + * RETURNED format - the format of the returned value. + * Returns: TRUE if the selection has been converted. + * + */ + +extern Boolean XawTextSourceConvertSelection( +#if NeedFunctionPrototypes + Widget /* w */, + Atom* /* selection */, + Atom* /* target */, + Atom* /* type */, + XtPointer* /* value_return */, + unsigned long* /* length_return */, + int* /* format_return */ +#endif +); + +/* Function Name: XawTextSourceSetSelection + * Description: allows special setting of the selection. + * Arguments: w - the TextSrc object. + * left, right - bounds of the selection. + * selection - the selection atom. + * Returns: none + */ + +extern void XawTextSourceSetSelection( +#if NeedFunctionPrototypes + Widget /* w */, + XawTextPosition /* start */, + XawTextPosition /* end */, + Atom /* selection */ +#endif +); + +_XFUNCPROTOEND + +#endif /* _XawTextSrc_h */ +/* DON'T ADD STUFF AFTER THIS #endif */ diff --git a/src/TextSrcP.h b/src/TextSrcP.h new file mode 100644 index 0000000..c7e0db7 --- /dev/null +++ b/src/TextSrcP.h @@ -0,0 +1,164 @@ +/* +* $XConsortium: TextSrcP.h,v 1.20 94/04/17 20:13:15 kaleb Exp $ +*/ + + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * TextSrcP.h - Private definitions for TextSrc object + * + */ + +#ifndef _XawTextSrcP_h +#define _XawTextSrcP_h + +/*********************************************************************** + * + * TextSrc Object Private Data + * + ***********************************************************************/ + +#include <X11/Xaw3d/TextSrc.h> +#include <X11/Xaw3d/TextP.h> /* This source works with the Text widget. */ + +/************************************************************ + * + * New fields for the TextSrc object class record. + * + ************************************************************/ + +typedef struct { + XtPointer next_extension; + XrmQuark record_type; + long version; + Cardinal record_size; + int (*Input)(); +} TextSrcExtRec, *TextSrcExt; + +typedef struct _TextSrcClassPart { + XawTextPosition (*Read)(); + int (*Replace)(); + XawTextPosition (*Scan)(); + XawTextPosition (*Search)(); + void (*SetSelection)(); + Boolean (*ConvertSelection)(); +} TextSrcClassPart; + +/* Full class record declaration */ +typedef struct _TextSrcClassRec { + ObjectClassPart object_class; + TextSrcClassPart textSrc_class; +} TextSrcClassRec; + +extern TextSrcClassRec textSrcClassRec; + +/* New fields for the TextSrc object record */ +typedef struct { + /* resources */ + XawTextEditType edit_mode; + XrmQuark text_format; /* 2 formats: FMT8BIT for Ascii */ + /* FMTWIDE for ISO 10646 */ +} TextSrcPart; + +/**************************************************************** + * + * Full instance record declaration + * + ****************************************************************/ + +typedef struct _TextSrcRec { + ObjectPart object; + TextSrcPart textSrc; +} TextSrcRec; + +/****************************************************************** + * + * Semiprivate declarations of functions used in other modules + * + ******************************************************************/ + +char* _XawTextWCToMB( +#if NeedFunctionPrototypes + Display* /* d */, + wchar_t* /* wstr */, + int* /* len_in_out */ +#endif +); + +wchar_t* _XawTextMBToWC( +#if NeedFunctionPrototypes + Display* /* d */, + char* /* str */, + int* /* len_in_out */ +#endif +); + +/************************************************************ + * + * Private declarations. + * + ************************************************************/ + +typedef Boolean (*_XawBooleanFunc)(); +typedef int (*_XawIntFunc)(); +typedef XawTextPosition (*_XawTextPositionFunc)(); +typedef void (*_XawTextVoidFunc)(); + +#define XtInheritInput ((_XawTextPositionFunc) _XtInherit) +#define XtInheritRead ((_XawTextPositionFunc) _XtInherit) +#define XtInheritReplace ((_XawIntFunc) _XtInherit) +#define XtInheritScan ((_XawTextPositionFunc) _XtInherit) +#define XtInheritSearch ((_XawTextPositionFunc) _XtInherit) +#define XtInheritSetSelection ((_XawTextVoidFunc) _XtInherit) +#define XtInheritConvertSelection ((_XawBooleanFunc) _XtInherit) +#define XtTextSrcExtVersion 1 +#define XtTextSrcExtTypeString "XT_TEXTSRC_EXT" + +#endif /* _XawTextSrcP_h */ diff --git a/src/TextTr.c b/src/TextTr.c new file mode 100644 index 0000000..a3cd8a9 --- /dev/null +++ b/src/TextTr.c @@ -0,0 +1,147 @@ +/* $XConsortium: TextTr.c,v 1.20 95/06/14 15:07:27 kaleb Exp $ */ + +/* + +Copyright (c) 1991, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +/* INTERNATIONALIZATION: + +The OMRON R5 contrib added the following action to the old TextTr: + + Ctrl<Key>backslash: reconnect-im() + +This is needed when the im is killed or otherwise becomes unreachable. +This keystroke is evil (inconvenient, hard-to-remember, not obvious) +so I am adding one more translation: + + <Key>Kanji: reconnect-im() + +The Japanese user typically hits their Kanji key when they want to do +input. This merely makes sure the input is connected. +*/ + +char *_XawDefaultTextTranslations1 = +"\ +Ctrl<Key>A: beginning-of-line() \n\ +Ctrl<Key>B: backward-character() \n\ +Ctrl<Key>C: insert-selection(CUT_BUFFER0) \n\ +Ctrl<Key>D: delete-next-character() \n\ +Ctrl<Key>E: end-of-line() \n\ +Ctrl<Key>F: forward-character() \n\ +Ctrl<Key>G: multiply(Reset) \n\ +Ctrl<Key>H: delete-previous-character() \n\ +Ctrl<Key>J: newline-and-indent() \n\ +Ctrl<Key>K: kill-to-end-of-line() \n\ +Ctrl<Key>L: redraw-display() \n\ +Ctrl<Key>M: newline() \n\ +Ctrl<Key>N: next-line() \n\ +Ctrl<Key>O: newline-and-backup() \n\ +Ctrl<Key>P: previous-line() \n\ +Ctrl<Key>R: search(backward) \n\ +Ctrl<Key>S: search(forward) \n\ +Ctrl<Key>T: transpose-characters() \n\ +Ctrl<Key>U: multiply(4) \n\ +Ctrl<Key>V: next-page() \n\ +Ctrl<Key>W: kill-selection() \n\ +Ctrl<Key>Y: insert-selection(SECONDARY) \n\ +Ctrl<Key>Z: scroll-one-line-up() \n\ +", *_XawDefaultTextTranslations2 = "\ +Meta<Key>B: backward-word() \n\ +Meta<Key>F: forward-word() \n\ +Meta<Key>I: insert-file() \n\ +Meta<Key>K: kill-to-end-of-paragraph() \n\ +Meta<Key>Q: form-paragraph() \n\ +Meta<Key>V: previous-page() \n\ +Meta<Key>Y: insert-selection(PRIMARY, CUT_BUFFER0) \n\ +Meta<Key>Z: scroll-one-line-down() \n\ +:Meta<Key>d: delete-next-word() \n\ +:Meta<Key>D: kill-word() \n\ +:Meta<Key>h: delete-previous-word() \n\ +:Meta<Key>H: backward-kill-word() \n\ +:Meta<Key>\\<: beginning-of-file() \n\ +:Meta<Key>\\>: end-of-file() \n\ +:Meta<Key>]: forward-paragraph() \n\ +:Meta<Key>[: backward-paragraph() \n\ +~Shift Meta<Key>Delete: delete-previous-word() \n\ + Shift Meta<Key>Delete: backward-kill-word() \n\ +~Shift Meta<Key>BackSpace: delete-previous-word() \n\ + Shift Meta<Key>BackSpace: backward-kill-word() \n\ +", +#if XtVersion >= 11006 +*_XawDefaultTextTranslations3 = "\ +<Key>Home: beginning-of-file() \n\ +:<Key>KP_Home: beginning-of-file() \n\ +<Key>End: end-of-file() \n\ +:<Key>KP_End: end-of-file() \n\ +<Key>Next: next-page() \n\ +:<Key>KP_Next: next-page() \n\ +<Key>Prior: previous-page() \n\ +:<Key>KP_Prior: previous-page() \n\ +<Key>Right: forward-character() \n\ +:<Key>KP_Right: forward-character() \n\ +<Key>Left: backward-character() \n\ +:<Key>KP_Left: backward-character() \n\ +<Key>Down: next-line() \n\ +:<Key>KP_Down: next-line() \n\ +<Key>Up: previous-line() \n\ +:<Key>KP_Up: previous-line() \n\ +<Key>Delete: delete-previous-character() \n\ +:<Key>KP_Delete: delete-previous-character() \n\ +<Key>BackSpace: delete-previous-character() \n\ +<Key>Linefeed: newline-and-indent() \n\ +<Key>Return: newline() \n\ +:<Key>KP_Enter: newline() \n\ +Ctrl<Key>backslash: reconnect-im() \n\ +<Key>Kanji: reconnect-im()\n\ +<Key>: insert-char() \n\ +", +#else +*_XawDefaultTextTranslations3 = "\ +<Key>Right: forward-character() \n\ +<Key>Left: backward-character() \n\ +<Key>Down: next-line() \n\ +<Key>Up: previous-line() \n\ +<Key>Delete: delete-previous-character() \n\ +<Key>BackSpace: delete-previous-character() \n\ +<Key>Linefeed: newline-and-indent() \n\ +<Key>Return: newline() \n\ +<Key>KP_Enter: newline() \n\ +<Key>: insert-char() \n\ +", +#endif +*_XawDefaultTextTranslations4 = "\ +<EnterWindow>: enter-window() \n\ +<LeaveWindow>: leave-window() \n\ +<FocusIn>: focus-in() \n\ +<FocusOut>: focus-out() \n\ +<Btn1Down>: select-start() \n\ +<Btn1Motion>: extend-adjust() \n\ +<Btn1Up>: extend-end(PRIMARY, CUT_BUFFER0) \n\ +<Btn2Down>: insert-selection(PRIMARY, CUT_BUFFER0) \n\ +<Btn3Down>: extend-start() \n\ +<Btn3Motion>: extend-adjust() \n\ +<Btn3Up>: extend-end(PRIMARY, CUT_BUFFER0) \ +"; diff --git a/src/ThreeD.c b/src/ThreeD.c new file mode 100644 index 0000000..8166a7c --- /dev/null +++ b/src/ThreeD.c @@ -0,0 +1,839 @@ +/* +* $KK: ThreeD.c,v 0.3 92/11/04 xx:xx:xx keithley Exp $ +*/ + +/*********************************************************** +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. +Copyright 1992 by Kaleb Keithley + + All Rights Reserved + +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 names of Digital, MIT, or Kaleb +Keithley not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * Portions Copyright (c) 2003 David J. Hawkey Jr. + * Rights, permissions, and disclaimer per the above DEC/MIT license. + */ + +#include "Xaw3dP.h" +#include <X11/Xlib.h> +#include <X11/StringDefs.h> +#include <X11/IntrinsicP.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/ThreeDP.h> +#include <X11/Xosdefs.h> + +/* Initialization of defaults */ + +#define XtNtopShadowPixmap "topShadowPixmap" +#define XtCTopShadowPixmap "TopShadowPixmap" +#define XtNbottomShadowPixmap "bottomShadowPixmap" +#define XtCBottomShadowPixmap "BottomShadowPixmap" + +static char defRelief[] = "Raised"; + +#define offset(field) XtOffsetOf(ThreeDRec, field) + +static XtResource resources[] = { + {XtNshadowWidth, XtCShadowWidth, XtRDimension, sizeof(Dimension), + offset(threeD.shadow_width), XtRImmediate, (XtPointer) 2}, + {XtNtopShadowPixel, XtCTopShadowPixel, XtRPixel, sizeof(Pixel), + offset(threeD.top_shadow_pixel), XtRString, XtDefaultForeground}, + {XtNbottomShadowPixel, XtCBottomShadowPixel, XtRPixel, sizeof(Pixel), + offset(threeD.bot_shadow_pixel), XtRString, XtDefaultForeground}, + {XtNtopShadowPixmap, XtCTopShadowPixmap, XtRPixmap, sizeof(Pixmap), + offset(threeD.top_shadow_pxmap), XtRImmediate, (XtPointer) NULL}, + {XtNbottomShadowPixmap, XtCBottomShadowPixmap, XtRPixmap, sizeof(Pixmap), + offset(threeD.bot_shadow_pxmap), XtRImmediate, (XtPointer) NULL}, + {XtNtopShadowContrast, XtCTopShadowContrast, XtRInt, sizeof(int), + offset(threeD.top_shadow_contrast), XtRImmediate, (XtPointer) 20}, + {XtNbottomShadowContrast, XtCBottomShadowContrast, XtRInt, sizeof(int), + offset(threeD.bot_shadow_contrast), XtRImmediate, (XtPointer) 40}, + {XtNuserData, XtCUserData, XtRPointer, sizeof(XtPointer), + offset(threeD.user_data), XtRPointer, (XtPointer) NULL}, + {XtNbeNiceToColormap, XtCBeNiceToColormap, XtRBoolean, sizeof(Boolean), + offset(threeD.be_nice_to_cmap), XtRImmediate, (XtPointer) True}, + {XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension), + XtOffsetOf(RectObjRec,rectangle.border_width), XtRImmediate, + (XtPointer)0}, + {XtNrelief, XtCRelief, XtRRelief, sizeof(XtRelief), + offset(threeD.relief), XtRString, (XtPointer) defRelief} +}; + +#undef offset + +static void ClassInitialize(), ClassPartInitialize(), Initialize(), Destroy(); +static void Redisplay(), Realize(), _Xaw3dDrawShadows(); +static Boolean SetValues(); + +ThreeDClassRec threeDClassRec = { + { /* core fields */ + /* superclass */ (WidgetClass) &simpleClassRec, + /* class_name */ "ThreeD", + /* widget_size */ sizeof(ThreeDRec), + /* class_initialize */ ClassInitialize, + /* class_part_initialize */ ClassPartInitialize, + /* class_inited */ FALSE, + /* initialize */ Initialize, + /* initialize_hook */ NULL, + /* realize */ Realize, + /* actions */ NULL, + /* num_actions */ 0, + /* resources */ resources, + /* resource_count */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ TRUE, + /* compress_exposure */ TRUE, + /* compress_enterleave */ TRUE, + /* visible_interest */ FALSE, + /* destroy */ Destroy, + /* resize */ XtInheritResize, + /* 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 */ XtInheritQueryGeometry, + /* display_accelerator */ XtInheritDisplayAccelerator, + /* extension */ NULL + }, + { /* simple fields */ + /* change_sensitive */ XtInheritChangeSensitive + }, + { /* threeD fields */ + /* shadow draw */ _Xaw3dDrawShadows + } +}; + +WidgetClass threeDWidgetClass = (WidgetClass) &threeDClassRec; + +/**************************************************************** + * + * Private Procedures + * + ****************************************************************/ + +#define mbshadowpm_size 3 +static char mbshadowpm_bits[] = {0x05, 0x03, 0x06}; + +#define mtshadowpm_size 3 +static char mtshadowpm_bits[] = {0x02, 0x04, 0x01}; + +#define shadowpm_size 2 +static char shadowpm_bits[] = {0x02, 0x01}; + +/* ARGSUSED */ +static void AllocTopShadowGC (w) + Widget w; +{ + ThreeDWidget tdw = (ThreeDWidget) w; + Screen *scn = XtScreen (w); + XtGCMask valuemask; + XGCValues myXGCV; + + if (tdw->threeD.be_nice_to_cmap || DefaultDepthOfScreen (scn) == 1) { + valuemask = GCTile | GCFillStyle; + myXGCV.tile = tdw->threeD.top_shadow_pxmap; + myXGCV.fill_style = FillTiled; + } else { + valuemask = GCForeground; + myXGCV.foreground = tdw->threeD.top_shadow_pixel; + } + tdw->threeD.top_shadow_GC = XtGetGC(w, valuemask, &myXGCV); +} + +/* ARGSUSED */ +static void AllocBotShadowGC (w) + Widget w; +{ + ThreeDWidget tdw = (ThreeDWidget) w; + Screen *scn = XtScreen (w); + XtGCMask valuemask; + XGCValues myXGCV; + + if (tdw->threeD.be_nice_to_cmap || DefaultDepthOfScreen (scn) == 1) { + valuemask = GCTile | GCFillStyle; + myXGCV.tile = tdw->threeD.bot_shadow_pxmap; + myXGCV.fill_style = FillTiled; + } else { + valuemask = GCForeground; + myXGCV.foreground = tdw->threeD.bot_shadow_pixel; + } + tdw->threeD.bot_shadow_GC = XtGetGC(w, valuemask, &myXGCV); +} + +/* ARGSUSED */ +static void AllocTopShadowPixmap (new) + Widget new; +{ + ThreeDWidget tdw = (ThreeDWidget) new; + Display *dpy = XtDisplay (new); + Screen *scn = XtScreen (new); + unsigned long top_fg_pixel = 0, top_bg_pixel = 0; + char *pm_data = NULL; + Boolean create_pixmap = FALSE; + unsigned int pm_size; + + /* + * I know, we're going to create two pixmaps for each and every + * shadow'd widget. Yeuck. I'm semi-relying on server side + * pixmap cacheing. + */ + + if (DefaultDepthOfScreen (scn) == 1) { + top_fg_pixel = BlackPixelOfScreen (scn); + top_bg_pixel = WhitePixelOfScreen (scn); + pm_data = mtshadowpm_bits; + pm_size = mtshadowpm_size; + create_pixmap = TRUE; + } else if (tdw->threeD.be_nice_to_cmap) { + if (tdw->core.background_pixel == WhitePixelOfScreen (scn)) { + top_fg_pixel = WhitePixelOfScreen (scn); + top_bg_pixel = grayPixel( BlackPixelOfScreen (scn), dpy, scn); + } else if (tdw->core.background_pixel == BlackPixelOfScreen (scn)) { + top_fg_pixel = grayPixel( BlackPixelOfScreen (scn), dpy, scn); + top_bg_pixel = WhitePixelOfScreen (scn); + } else { + top_fg_pixel = tdw->core.background_pixel; + top_bg_pixel = WhitePixelOfScreen (scn); + } +#ifndef XAW_GRAY_BLKWHT_STIPPLES + if (tdw->core.background_pixel == WhitePixelOfScreen (scn) || + tdw->core.background_pixel == BlackPixelOfScreen (scn)) { + pm_data = mtshadowpm_bits; + pm_size = mtshadowpm_size; + } else +#endif + { + pm_data = shadowpm_bits; + pm_size = shadowpm_size; + } + + create_pixmap = TRUE; + } else { + pm_size = 0; /* keep gcc happy */ + } + + if (create_pixmap) + tdw->threeD.top_shadow_pxmap = XCreatePixmapFromBitmapData (dpy, + RootWindowOfScreen (scn), + pm_data, + pm_size, + pm_size, + top_fg_pixel, + top_bg_pixel, + DefaultDepthOfScreen (scn)); +} + +/* ARGSUSED */ +static void AllocBotShadowPixmap (new) + Widget new; +{ + ThreeDWidget tdw = (ThreeDWidget) new; + Display *dpy = XtDisplay (new); + Screen *scn = XtScreen (new); + unsigned long bot_fg_pixel = 0, bot_bg_pixel = 0; + char *pm_data = NULL; + Boolean create_pixmap = FALSE; + unsigned int pm_size; + + if (DefaultDepthOfScreen (scn) == 1) { + bot_fg_pixel = BlackPixelOfScreen (scn); + bot_bg_pixel = WhitePixelOfScreen (scn); + pm_data = mbshadowpm_bits; + pm_size = mbshadowpm_size; + create_pixmap = TRUE; + } else if (tdw->threeD.be_nice_to_cmap) { + if (tdw->core.background_pixel == WhitePixelOfScreen (scn)) { + bot_fg_pixel = grayPixel( WhitePixelOfScreen (scn), dpy, scn); + bot_bg_pixel = BlackPixelOfScreen (scn); + } else if (tdw->core.background_pixel == BlackPixelOfScreen (scn)) { + bot_fg_pixel = BlackPixelOfScreen (scn); + bot_bg_pixel = grayPixel( BlackPixelOfScreen (scn), dpy, scn); + } else { + bot_fg_pixel = tdw->core.background_pixel; + bot_bg_pixel = BlackPixelOfScreen (scn); + } +#ifndef XAW_GRAY_BLKWHT_STIPPLES + if (tdw->core.background_pixel == WhitePixelOfScreen (scn) || + tdw->core.background_pixel == BlackPixelOfScreen (scn)) { + pm_data = mbshadowpm_bits; + pm_size = mbshadowpm_size; + } else +#endif + { + pm_data = shadowpm_bits; + pm_size = shadowpm_size; + } + create_pixmap = TRUE; + } else { + pm_size = 0; /* keep gcc happy */ + } + + if (create_pixmap) + tdw->threeD.bot_shadow_pxmap = XCreatePixmapFromBitmapData (dpy, + RootWindowOfScreen (scn), + pm_data, + pm_size, + pm_size, + bot_fg_pixel, + bot_bg_pixel, + DefaultDepthOfScreen (scn)); +} + +/* ARGSUSED */ +void Xaw3dComputeTopShadowRGB (new, xcol_out) + Widget new; + XColor *xcol_out; +{ + if (XtIsSubclass (new, threeDWidgetClass)) { + ThreeDWidget tdw = (ThreeDWidget) new; + XColor get_c; + double contrast; + Display *dpy = XtDisplay (new); + Screen *scn = XtScreen (new); + Colormap cmap = new->core.colormap; + + get_c.pixel = tdw->core.background_pixel; + if (get_c.pixel == WhitePixelOfScreen (scn) || + get_c.pixel == BlackPixelOfScreen (scn)) { + contrast = (100 - tdw->threeD.top_shadow_contrast) / 100.0; + xcol_out->red = contrast * 65535.0; + xcol_out->green = contrast * 65535.0; + xcol_out->blue = contrast * 65535.0; + } else { + contrast = 1.0 + tdw->threeD.top_shadow_contrast / 100.0; + XQueryColor (dpy, cmap, &get_c); +#define MIN(x,y) (unsigned short) (x < y) ? x : y + xcol_out->red = MIN (65535, (int) (contrast * (double) get_c.red)); + xcol_out->green = MIN (65535, (int) (contrast * (double) get_c.green)); + xcol_out->blue = MIN (65535, (int) (contrast * (double) get_c.blue)); +#undef MIN + } + } else + xcol_out->red = xcol_out->green = xcol_out->blue = 0; +} + +/* ARGSUSED */ +static void AllocTopShadowPixel (new) + Widget new; +{ + XColor set_c; + ThreeDWidget tdw = (ThreeDWidget) new; + Display *dpy = XtDisplay (new); + Screen *scn = XtScreen (new); + Colormap cmap = new->core.colormap; + + Xaw3dComputeTopShadowRGB (new, &set_c); + (void) XAllocColor (dpy, cmap, &set_c); + tdw->threeD.top_shadow_pixel = set_c.pixel; +} + +/* ARGSUSED */ +void Xaw3dComputeBottomShadowRGB (new, xcol_out) + Widget new; + XColor *xcol_out; +{ + if (XtIsSubclass (new, threeDWidgetClass)) { + ThreeDWidget tdw = (ThreeDWidget) new; + XColor get_c; + double contrast; + Display *dpy = XtDisplay (new); + Screen *scn = XtScreen (new); + Colormap cmap = new->core.colormap; + + get_c.pixel = tdw->core.background_pixel; + if (get_c.pixel == WhitePixelOfScreen (scn) || + get_c.pixel == BlackPixelOfScreen (scn)) { + contrast = tdw->threeD.bot_shadow_contrast / 100.0; + xcol_out->red = contrast * 65535.0; + xcol_out->green = contrast * 65535.0; + xcol_out->blue = contrast * 65535.0; + } else { + XQueryColor (dpy, cmap, &get_c); + contrast = (100 - tdw->threeD.bot_shadow_contrast) / 100.0; + xcol_out->red = contrast * get_c.red; + xcol_out->green = contrast * get_c.green; + xcol_out->blue = contrast * get_c.blue; + } + } else + xcol_out->red = xcol_out->green = xcol_out->blue = 0; +} + +/* ARGSUSED */ +static void AllocBotShadowPixel (new) + Widget new; +{ + XColor set_c; + ThreeDWidget tdw = (ThreeDWidget) new; + Display *dpy = XtDisplay (new); + Screen *scn = XtScreen (new); + Colormap cmap = new->core.colormap; + + Xaw3dComputeBottomShadowRGB (new, &set_c); + (void) XAllocColor (dpy, cmap, &set_c); + tdw->threeD.bot_shadow_pixel = set_c.pixel; +} + + +static XrmQuark XtQReliefNone, XtQReliefRaised, XtQReliefSunken, + XtQReliefRidge, XtQReliefGroove; + +#define done(address, type) { \ + toVal->size = sizeof(type); \ + toVal->addr = (XPointer) address; \ + return; \ + } + +/* ARGSUSED */ +static void _CvtStringToRelief(args, num_args, fromVal, toVal) + XrmValuePtr args; /* unused */ + Cardinal *num_args; /* unused */ + XrmValuePtr fromVal; + XrmValuePtr toVal; +{ + static XtRelief relief; + XrmQuark q; + char lowerName[1000]; + + XmuCopyISOLatin1Lowered (lowerName, (char*)fromVal->addr); + q = XrmStringToQuark(lowerName); + if (q == XtQReliefNone) { + relief = XtReliefNone; + done(&relief, XtRelief); + } + if (q == XtQReliefRaised) { + relief = XtReliefRaised; + done(&relief, XtRelief); + } + if (q == XtQReliefSunken) { + relief = XtReliefSunken; + done(&relief, XtRelief); + } + if (q == XtQReliefRidge) { + relief = XtReliefRidge; + done(&relief, XtRelief); + } + if (q == XtQReliefGroove) { + relief = XtReliefGroove; + done(&relief, XtRelief); + } + XtStringConversionWarning(fromVal->addr, "relief"); + toVal->addr = NULL; + toVal->size = 0; +} + +static void ClassInitialize() +{ + XawInitializeWidgetSet(); + XtQReliefNone = XrmPermStringToQuark("none"); + XtQReliefRaised = XrmPermStringToQuark("raised"); + XtQReliefSunken = XrmPermStringToQuark("sunken"); + XtQReliefRidge = XrmPermStringToQuark("ridge"); + XtQReliefGroove = XrmPermStringToQuark("groove"); + + XtAddConverter( XtRString, XtRRelief, _CvtStringToRelief, + (XtConvertArgList)NULL, 0 ); +} + + +/* ARGSUSED */ +static void ClassPartInitialize (wc) + WidgetClass wc; + +{ + ThreeDClassRec *tdwc = (ThreeDClassRec*) wc; + ThreeDClassRec *super = (ThreeDClassRec*) tdwc->core_class.superclass; + + if (tdwc->threeD_class.shadowdraw == XtInheritXaw3dShadowDraw) + tdwc->threeD_class.shadowdraw = super->threeD_class.shadowdraw; +} + + +/* ARGSUSED */ +static void Initialize (request, new, args, num_args) + Widget request, new; + ArgList args; + Cardinal *num_args; +{ + ThreeDWidget tdw = (ThreeDWidget) new; + Screen *scr = XtScreen (new); + + if (tdw->threeD.be_nice_to_cmap || DefaultDepthOfScreen (scr) == 1) { + AllocTopShadowPixmap (new); + AllocBotShadowPixmap (new); + } else { + if (tdw->threeD.top_shadow_pixel == tdw->threeD.bot_shadow_pixel) { + /* + Eeek. We're probably going to XQueryColor() twice + for each widget. Necessary because you can set the + top and bottom shadows independent of each other in + SetValues. Some cacheing would certainly help... + */ + AllocTopShadowPixel (new); + AllocBotShadowPixel (new); + } + tdw->threeD.top_shadow_pxmap = tdw->threeD.bot_shadow_pxmap = (Pixmap) 0; + } + AllocTopShadowGC (new); + AllocBotShadowGC (new); +} + +static void Realize (gw, valueMask, attrs) + Widget gw; + XtValueMask *valueMask; + XSetWindowAttributes *attrs; +{ + /* + * This is necessary because Simple doesn't have a realize method + * XtInheritRealize in the ThreeD class record doesn't work. This + * daisychains through Simple to the Core class realize method + */ + (*threeDWidgetClass->core_class.superclass->core_class.realize) + (gw, valueMask, attrs); +} + +static void Destroy (w) + Widget w; +{ + ThreeDWidget tdw = (ThreeDWidget) w; + XtReleaseGC (w, tdw->threeD.top_shadow_GC); + XtReleaseGC (w, tdw->threeD.bot_shadow_GC); + if (tdw->threeD.top_shadow_pxmap) + XFreePixmap (XtDisplay (w), tdw->threeD.top_shadow_pxmap); + if (tdw->threeD.bot_shadow_pxmap) + XFreePixmap (XtDisplay (w), tdw->threeD.bot_shadow_pxmap); +} + +/* ARGSUSED */ +static void Redisplay (w, event, region) + Widget w; + XEvent *event; /* unused */ + Region region; /* unused */ +{ + ThreeDWidget tdw = (ThreeDWidget) w; + + _Xaw3dDrawShadows (w, event, region, tdw->threeD.relief, True); +} + +/* ARGSUSED */ +static Boolean SetValues (gcurrent, grequest, gnew, args, num_args) + Widget gcurrent, grequest, gnew; + ArgList args; + Cardinal *num_args; +{ + ThreeDWidget current = (ThreeDWidget) gcurrent; + ThreeDWidget new = (ThreeDWidget) gnew; + Boolean redisplay = FALSE; + Boolean alloc_top_pixel = FALSE; + Boolean alloc_bot_pixel = FALSE; + Boolean alloc_top_pxmap = FALSE; + Boolean alloc_bot_pxmap = FALSE; + + (*threeDWidgetClass->core_class.superclass->core_class.set_values) + (gcurrent, grequest, gnew, NULL, 0); + if (new->threeD.relief != current->threeD.relief) + redisplay = TRUE; + if (new->threeD.shadow_width != current->threeD.shadow_width) + redisplay = TRUE; + if (new->threeD.be_nice_to_cmap != current->threeD.be_nice_to_cmap) { + if (new->threeD.be_nice_to_cmap) { + alloc_top_pxmap = TRUE; + alloc_bot_pxmap = TRUE; + } else { + alloc_top_pixel = TRUE; + alloc_bot_pixel = TRUE; + } + redisplay = TRUE; + } + if (!new->threeD.be_nice_to_cmap && + new->threeD.top_shadow_contrast != current->threeD.top_shadow_contrast) + alloc_top_pixel = TRUE; + if (!new->threeD.be_nice_to_cmap && + new->threeD.bot_shadow_contrast != current->threeD.bot_shadow_contrast) + alloc_bot_pixel = TRUE; + if (alloc_top_pixel) + AllocTopShadowPixel (gnew); + if (alloc_bot_pixel) + AllocBotShadowPixel (gnew); + if (alloc_top_pxmap) + AllocTopShadowPixmap (gnew); + if (alloc_bot_pxmap) + AllocBotShadowPixmap (gnew); + if (!new->threeD.be_nice_to_cmap && + new->threeD.top_shadow_pixel != current->threeD.top_shadow_pixel) + alloc_top_pixel = TRUE; + if (!new->threeD.be_nice_to_cmap && + new->threeD.bot_shadow_pixel != current->threeD.bot_shadow_pixel) + alloc_bot_pixel = TRUE; + if (new->threeD.be_nice_to_cmap) { + if (alloc_top_pxmap) { + XtReleaseGC (gcurrent, current->threeD.top_shadow_GC); + AllocTopShadowGC (gnew); + redisplay = True; + } + if (alloc_bot_pxmap) { + XtReleaseGC (gcurrent, current->threeD.bot_shadow_GC); + AllocBotShadowGC (gnew); + redisplay = True; + } + } else { + if (alloc_top_pixel) { + if (new->threeD.top_shadow_pxmap) { + XFreePixmap (XtDisplay (gnew), new->threeD.top_shadow_pxmap); + new->threeD.top_shadow_pxmap = (Pixmap) NULL; + } + XtReleaseGC (gcurrent, current->threeD.top_shadow_GC); + AllocTopShadowGC (gnew); + redisplay = True; + } + if (alloc_bot_pixel) { + if (new->threeD.bot_shadow_pxmap) { + XFreePixmap (XtDisplay (gnew), new->threeD.bot_shadow_pxmap); + new->threeD.bot_shadow_pxmap = (Pixmap) NULL; + } + XtReleaseGC (gcurrent, current->threeD.bot_shadow_GC); + AllocBotShadowGC (gnew); + redisplay = True; + } + } + return (redisplay); +} + +/* ARGSUSED */ +static void +_Xaw3dDrawShadows (gw, event, region, relief, out) + Widget gw; + XEvent *event; + Region region; + XtRelief relief; + Boolean out; +{ + XPoint pt[6]; + ThreeDWidget tdw = (ThreeDWidget) gw; + Dimension s = tdw->threeD.shadow_width; + + /* + * Draw the shadows using the core part width and height, + * and the threeD part relief and shadow_width. + * No point to do anything if the shadow_width is 0 or the + * widget has not been realized. + */ + if ((s > 0) && XtIsRealized (gw)) { + Dimension h = tdw->core.height; + Dimension w = tdw->core.width; + Dimension hms = h - s; + Dimension wms = w - s; + Display *dpy = XtDisplay (gw); + Window win = XtWindow (gw); + GC realtop = tdw->threeD.top_shadow_GC; + GC realbot = tdw->threeD.bot_shadow_GC; + GC top, bot; + + if (out) { + top = tdw->threeD.top_shadow_GC; + bot = tdw->threeD.bot_shadow_GC; + } else { + top = tdw->threeD.bot_shadow_GC; + bot = tdw->threeD.top_shadow_GC; + } + + if (relief == XtReliefRaised || relief == XtReliefSunken) { + /* top-left shadow */ + if ((region == NULL) || + (XRectInRegion (region, 0, 0, w, s) != RectangleOut) || + (XRectInRegion (region, 0, 0, s, h) != RectangleOut)) { + pt[0].x = 0; pt[0].y = h; + pt[1].x = pt[1].y = 0; + pt[2].x = w; pt[2].y = 0; + pt[3].x = wms; pt[3].y = s; + pt[4].x = pt[4].y = s; + pt[5].x = s; pt[5].y = hms; + XFillPolygon (dpy, win, + (relief == XtReliefRaised) ? top : bot, + pt, 6, Complex, CoordModeOrigin); + } + + /* bottom-right shadow */ + if ((region == NULL) || + (XRectInRegion (region, 0, hms, w, s) != RectangleOut) || + (XRectInRegion (region, wms, 0, s, h) != RectangleOut)) { + pt[0].x = 0; pt[0].y = h; + pt[1].x = w; pt[1].y = h; + pt[2].x = w; pt[2].y = 0; + pt[3].x = wms; pt[3].y = s; + pt[4].x = wms; pt[4].y = hms; + pt[5].x = s; pt[5].y = hms; + XFillPolygon (dpy, win, + (relief == XtReliefRaised) ? bot : top, + pt, 6, Complex, CoordModeOrigin); + } + } else if (relief == XtReliefRidge || relief == XtReliefGroove) { + /* split the shadow width */ + s /= 2; hms = h - s; wms = w - s; + + /* outer top-left shadow */ + if ((region == NULL) || + (XRectInRegion (region, 0, 0, w, s) != RectangleOut) || + (XRectInRegion (region, 0, 0, s, h) != RectangleOut)) { + pt[0].x = 0; pt[0].y = h; + pt[1].x = pt[1].y = 0; + pt[2].x = w; pt[2].y = 0; + pt[3].x = wms; pt[3].y = s; + pt[4].x = pt[4].y = s; + pt[5].x = s; pt[5].y = hms; + XFillPolygon (dpy, win, + (relief == XtReliefRidge) ? realtop : realbot, + pt, 6, Complex, CoordModeOrigin); + } + + /* outer bottom-right shadow */ + if ((region == NULL) || + (XRectInRegion (region, 0, hms, w, s) != RectangleOut) || + (XRectInRegion (region, wms, 0, s, h) != RectangleOut)) { + pt[0].x = 0; pt[0].y = h; + pt[1].x = w; pt[1].y = h; + pt[2].x = w; pt[2].y = 0; + pt[3].x = wms; pt[3].y = s; + pt[4].x = wms; pt[4].y = hms; + pt[5].x = s; pt[5].y = hms; + XFillPolygon (dpy, win, + (relief == XtReliefRidge) ? realbot : realtop, + pt, 6, Complex, CoordModeOrigin); + } + + /* inner top-left shadow */ + if ((region == NULL) || + (XRectInRegion (region, 0, 0, w, s) != RectangleOut) || + (XRectInRegion (region, 0, 0, s, h) != RectangleOut)) { + pt[0].x = s; pt[0].y = h; + pt[1].x = pt[1].y = s; + pt[2].x = w; pt[2].y = s; + pt[3].x = wms; pt[3].y = s * 2; + pt[4].x = pt[4].y = s * 2; + pt[5].x = s * 2; pt[5].y = hms; + XFillPolygon (dpy, win, + (relief == XtReliefRidge) ? bot: top, + pt, 6, Complex, CoordModeOrigin); + } + + /* inner bottom-right shadow */ + if ((region == NULL) || + (XRectInRegion (region, 0, hms, w, s) != RectangleOut) || + (XRectInRegion (region, wms, 0, s, h) != RectangleOut)) { + pt[0].x = s; pt[0].y = hms; + pt[1].x = wms; pt[1].y = hms; + pt[2].x = wms; pt[2].y = s; + pt[3].x = wms - s; pt[3].y = s * 2; + pt[4].x = wms - s; pt[4].y = hms - s; + pt[5].x = s * 2; pt[5].y = hms - s; + XFillPolygon (dpy, win, + (relief == XtReliefRidge) ? top : bot, + pt, 6, Complex, CoordModeOrigin); + } + } + } +} + +/* + * _ShadowSurroundedBox() is somewhat redundant with _Xaw3dDrawShadows(), + * but has a more explicit interface, and ignores threeD part relief. + */ + +/* ARGSUSED */ +void +_ShadowSurroundedBox(gw, tdw, x0, y0, x1, y1, relief, out) +Widget gw; +ThreeDWidget tdw; +Position x0, y0, x1, y1; +XtRelief relief; /* unused */ +Boolean out; +{ + XPoint pt[6]; + Dimension s = tdw->threeD.shadow_width; + + /* + * Draw the shadows using the core part width and height, + * and the threeD part shadow_width. + * No point to do anything if the shadow_width is 0 or the + * widget has not been realized. + */ + if ((s > 0) && XtIsRealized(gw)) + { + Dimension h = y1 - y0; + Dimension w = x1 - x0; + Dimension wms = w - s; + Dimension hms = h - s; + Dimension sm = (s > 1 ? s / 2 : 1); + Dimension wmsm = w - sm; + Dimension hmsm = h - sm; + Display *dpy = XtDisplay(gw); + Window win = XtWindow(gw); + GC top, bot; + + if (out) + { + top = tdw->threeD.top_shadow_GC; + bot = tdw->threeD.bot_shadow_GC; + } + else + { + top = tdw->threeD.bot_shadow_GC; + bot = tdw->threeD.top_shadow_GC; + } + + /* top-left shadow */ + pt[0].x = x0; pt[0].y = y0 + h; + pt[1].x = x0; pt[1].y = y0; + pt[2].x = x0 + w; pt[2].y = y0; + pt[3].x = x0 + wmsm; pt[3].y = y0 + sm - 1; + pt[4].x = x0 + sm; pt[4].y = y0 + sm; + pt[5].x = x0 + sm - 1; pt[5].y = y0 + hmsm; + XFillPolygon(dpy, win, top, pt, 6, Complex, CoordModeOrigin); + if (s > 1) + { + pt[0].x = x0 + s - 1; pt[0].y = y0 + hms; + pt[1].x = x0 + s; pt[1].y = y0 + s; + pt[2].x = x0 + wms; pt[2].y = y0 + s - 1; + XFillPolygon(dpy, win, top, pt, 6, Complex, CoordModeOrigin); + } + + /* bottom-right shadow */ + pt[0].x = x0; pt[0].y = y0 + h; + pt[1].x = x0 + w; pt[1].y = y0 + h; + pt[2].x = x0 + w; pt[2].y = y0; + pt[3].x = x0 + wmsm; pt[3].y = y0 + sm - 1; + pt[4].x = x0 + wmsm; pt[4].y = y0 + hmsm; + pt[5].x = x0 + sm - 1; pt[5].y = y0 + hmsm; + XFillPolygon(dpy, win, bot, pt, 6, Complex, CoordModeOrigin); + if (s > 1) + { + pt[0].x = x0 + s - 1; pt[0].y = y0 + hms; + pt[1].x = x0 + wms; pt[1].y = y0 + hms; + pt[2].x = x0 + wms; pt[2].y = y0 + s - 1; + XFillPolygon(dpy, win, bot, pt, 6, Complex, CoordModeOrigin); + } + } +} + diff --git a/src/ThreeD.h b/src/ThreeD.h new file mode 100644 index 0000000..d7cf8e2 --- /dev/null +++ b/src/ThreeD.h @@ -0,0 +1,119 @@ +/* +* $KK: ThreeD.h,v 0.3 92/11/04 xx:xx:xx keithley Exp $ +*/ + +/*********************************************************** +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. +Copyright 1992 by Kaleb Keithley + + All Rights Reserved + +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 names of Digital, MIT, or Kaleb +Keithley not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _XawThreeD_h +#define _XawThreeD_h + +/*********************************************************************** + * + * ThreeD Widget + * + ***********************************************************************/ + +#include <X11/Xmu/Converters.h> + +/* Parameters: + + Name Class RepType Default Value + ---- ----- ------- ------------- + shadowWidth ShadowWidth Dimension 2 + topShadowPixel TopShadowPixel Pixel dynamic + bottomShadowPixel BottomShadowPixel Pixel dynamic + topShadowContrast TopShadowContrast Int 20 + bottomShadowContrast BottomShadowContrast Int 40 + userData UserData XtPointer NULL + beNiceToColormap BeNiceToColormap Boolean False + relief Relief XtRelief XtReliefRaised + +*/ + +#define XtNshadowWidth "shadowWidth" +#define XtCShadowWidth "ShadowWidth" +#define XtNtopShadowPixel "topShadowPixel" +#define XtCTopShadowPixel "TopShadowPixel" +#define XtNbottomShadowPixel "bottomShadowPixel" +#define XtCBottomShadowPixel "BottomShadowPixel" +#define XtNtopShadowContrast "topShadowContrast" +#define XtCTopShadowContrast "TopShadowContrast" +#define XtNbottomShadowContrast "bottomShadowContrast" +#define XtCBottomShadowContrast "BottomShadowContrast" +#define XtNbeNiceToColormap "beNiceToColormap" +#define XtCBeNiceToColormap "BeNiceToColormap" +#define XtNbeNiceToColourmap "beNiceToColormap" +#define XtCBeNiceToColourmap "BeNiceToColormap" +#define XtNuserData "userData" +#define XtCUserData "UserData" +#define XtNrelief "relief" +#define XtCRelief "Relief" + +typedef enum { + XtReliefNone, + XtReliefRaised, + XtReliefSunken, + XtReliefRidge, + XtReliefGroove +} XtRelief; + +typedef struct _ThreeDRec *ThreeDWidget; +typedef struct _ThreeDClassRec *ThreeDWidgetClass; + +extern WidgetClass threeDWidgetClass; + +_XFUNCPROTOBEGIN + +extern void Xaw3dComputeTopShadowRGB ( +#if NeedFunctionPrototypes + Widget /* new */, + XColor* /* xcol_out */ +#endif +); + +extern void Xaw3dComputeBottomShadowRGB ( +#if NeedFunctionPrototypes + Widget /* new */, + XColor* /* xcol_out */ +#endif +); + +extern void _ShadowSurroundedBox ( +#if NeedFunctionPrototypes + Widget, + ThreeDWidget, + Position, + Position, + Position, + Position, + XtRelief, + Boolean +#endif +); + +_XFUNCPROTOEND + +#endif /* _XawThreeD_h */ diff --git a/src/ThreeDP.h b/src/ThreeDP.h new file mode 100644 index 0000000..44ccb97 --- /dev/null +++ b/src/ThreeDP.h @@ -0,0 +1,77 @@ +/* +* $KK: ThreeDP.h,v 0.3 92/11/04 xx:xx:xx keithley Exp $ +*/ + +/*********************************************************** +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. +Copyright 1992 by Kaleb Keithley + + All Rights Reserved + +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 names of Digital, MIT, or Kaleb +Keithley not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#ifndef _ThreeDP_h +#define _ThreeDP_h + +#include <X11/Xaw3d/ThreeD.h> +#include <X11/Xaw3d/SimpleP.h> + +#define XtRRelief "Relief" + +typedef struct { + Dimension shadow_width; + Pixel top_shadow_pixel; + Pixel bot_shadow_pixel; + Pixmap top_shadow_pxmap; + Pixmap bot_shadow_pxmap; + int top_shadow_contrast; + int bot_shadow_contrast; + GC top_shadow_GC; + GC bot_shadow_GC; + XtPointer user_data; + Boolean be_nice_to_cmap; + XtRelief relief; + } ThreeDPart; + +/* Full instance record declaration */ +typedef struct _ThreeDRec { + CorePart core; + SimplePart simple; + ThreeDPart threeD; + } ThreeDRec; + +typedef struct { + void (*shadowdraw)(); + } ThreeDClassPart; + +#define XtInheritXaw3dShadowDraw ((void (*)())_XtInherit) + +/* Full class record declaration. */ +typedef struct _ThreeDClassRec { + CoreClassPart core_class; + SimpleClassPart simple_class; + ThreeDClassPart threeD_class; + } ThreeDClassRec; + +/* Class pointer. */ +extern ThreeDClassRec threeDClassRec; + + +#endif /* _ThreeDP_h */ diff --git a/src/Tip.c b/src/Tip.c new file mode 100644 index 0000000..888eeac --- /dev/null +++ b/src/Tip.c @@ -0,0 +1,718 @@ +/* + * Copyright (c) 1999 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + * + * Author: Paulo César Pereira de Andrade + */ + +/* + * Portions Copyright (c) 2003 David J. Hawkey Jr. + * Rights, permissions, and disclaimer per the above XFree86 license. + */ + +/* $XFree86: xc/lib/Xaw/Tip.c,v 1.5 2000/05/18 16:29:53 dawes Exp $ */ + +#include "Xaw3dP.h" +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xos.h> +#include <X11/Xmu/Converters.h> +#include <X11/Xaw3d/TipP.h> +#include <X11/Xaw3d/XawInit.h> + +#define TIP_EVENT_MASK (ButtonPressMask | \ + ButtonReleaseMask | \ + PointerMotionMask | \ + ButtonMotionMask | \ + KeyPressMask | \ + KeyReleaseMask | \ + EnterWindowMask | \ + LeaveWindowMask) + +/* + * Types + */ +typedef struct _WidgetInfo { + Widget widget; + String label; + struct _WidgetInfo *next; +} WidgetInfo; + +typedef struct _XawTipInfo { + Screen *screen; + TipWidget tip; + Bool mapped; + WidgetInfo *widgets; + struct _XawTipInfo *next; +} XawTipInfo; + +typedef struct { + XawTipInfo *info; + WidgetInfo *winfo; +} TimeoutInfo; + +/* + * Class Methods + */ +static void XawTipClassInitialize(); +static void XawTipInitialize(); +static void XawTipDestroy(); +static void XawTipExpose(); +static void XawTipRealize(); +static Boolean XawTipSetValues(); + +/* + * Prototypes + */ +static void TipEventHandler(); +static void TipShellEventHandler(); +static WidgetInfo *CreateWidgetInfo(); +static WidgetInfo *FindWidgetInfo(); +static XawTipInfo *CreateTipInfo(); +static XawTipInfo *FindTipInfo(); +static void ResetTip(); +static void TipTimeoutCallback(); +static void TipLayout(); +static void TipPosition(); + +/* + * Initialization + */ +#define offset(field) XtOffsetOf(TipRec, tip.field) +static XtResource resources[] = { + {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), + offset(foreground), XtRString, XtDefaultForeground}, + {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct*), + offset(font), XtRString, XtDefaultFont}, +#ifdef XAW_INTERNATIONALIZATION + {XtNfontSet, XtCFontSet, XtRFontSet, sizeof(XFontSet), + offset(fontset), XtRString, XtDefaultFontSet}, +#endif + {XtNlabel, XtCLabel, XtRString, sizeof(String), + offset(label), XtRString, NULL}, + {XtNencoding, XtCEncoding, XtRUnsignedChar, sizeof(unsigned char), + offset(encoding), XtRImmediate, (XtPointer)XawTextEncoding8bit}, + {XtNinternalHeight, XtCHeight, XtRDimension, sizeof(Dimension), + offset(internal_height), XtRImmediate, (XtPointer)2}, + {XtNinternalWidth, XtCWidth, XtRDimension, sizeof(Dimension), + offset(internal_width), XtRImmediate, (XtPointer)2}, + {XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof(int), + offset(backing_store), XtRImmediate, + (XtPointer)(Always + WhenMapped + NotUseful)}, + {XtNtimeout, XtCTimeout, XtRInt, sizeof(int), + offset(timeout), XtRImmediate, (XtPointer)500}, +}; +#undef offset + +TipClassRec tipClassRec = { + /* core */ + { + (WidgetClass)&widgetClassRec, /* superclass */ + "Tip", /* class_name */ + sizeof(TipRec), /* widget_size */ + XawTipClassInitialize, /* class_initialize */ + NULL, /* class_part_initialize */ + False, /* class_inited */ + XawTipInitialize, /* initialize */ + NULL, /* initialize_hook */ + XawTipRealize, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + True, /* compress_motion */ + True, /* compress_exposure */ + True, /* compress_enterleave */ + False, /* visible_interest */ + XawTipDestroy, /* destroy */ + NULL, /* resize */ + XawTipExpose, /* expose */ + XawTipSetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL, /* extension */ + }, + /* tip */ + { + NULL, /* extension */ + }, +}; + +WidgetClass tipWidgetClass = (WidgetClass)&tipClassRec; + +static XawTipInfo *TipInfoList = NULL; +static TimeoutInfo TimeoutData; + +/* + * Implementation + */ + +/* + * XmuCvtBackingStoreToString() from XFree86's distribution, because + * X.Org's distribution doesn't have it. + */ + +/*ARGSUSED*/ +static Boolean +XawCvtBackingStoreToString(dpy, args, num_args, fromVal, toVal, data) +Display *dpy; +XrmValuePtr args; +Cardinal *num_args; +XrmValuePtr fromVal, toVal; +XtPointer *data; +{ + static String buffer; + Cardinal size; + + switch (*(int *)fromVal->addr) + { + case NotUseful: + buffer = XtEnotUseful; + break; + case WhenMapped: + buffer = XtEwhenMapped; + break; + case Always: + buffer = XtEalways; + break; + case (Always + WhenMapped + NotUseful): + buffer = XtEdefault; + break; + default: + XtWarning("Cannot convert BackingStore to String"); + toVal->addr = NULL; + toVal->size = 0; + return (False); + } + + size = strlen(buffer) + 1; + if (toVal->addr != NULL) + { + if (toVal->size < size) + { + toVal->size = size; + return (False); + } + strcpy((char *)toVal->addr, buffer); + } + else + toVal->addr = (XPointer)buffer; + toVal->size = sizeof(String); + + return (True); +} + +static void +XawTipClassInitialize() +{ + XawInitializeWidgetSet(); + XtAddConverter(XtRString, XtRBackingStore, XmuCvtStringToBackingStore, + NULL, 0); + XtSetTypeConverter(XtRBackingStore, XtRString, XawCvtBackingStoreToString, + NULL, 0, XtCacheNone, NULL); +} + +/*ARGSUSED*/ +static void +XawTipInitialize(req, w, args, num_args) +Widget req, w; +ArgList args; +Cardinal *num_args; +{ + TipWidget tip = (TipWidget)w; + XGCValues values; + + tip->tip.timer = 0; + + values.foreground = tip->tip.foreground; + values.background = tip->core.background_pixel; + values.font = tip->tip.font->fid; + values.graphics_exposures = False; + + tip->tip.gc = XtAllocateGC(w, 0, GCForeground | GCBackground | GCFont | + GCGraphicsExposures, &values, GCFont, 0); +} + +static void +XawTipDestroy(w) +Widget w; +{ + XawTipInfo *info = FindTipInfo(w); + WidgetInfo *winfo; + TipWidget tip = (TipWidget)w; + + if (tip->tip.timer) + XtRemoveTimeOut(tip->tip.timer); + + XtReleaseGC(w, tip->tip.gc); + + XtRemoveEventHandler(XtParent(w), KeyPressMask, False, + TipShellEventHandler, (XtPointer)NULL); + + while (info->widgets) { + winfo = info->widgets->next; + XtFree((char *)info->widgets->label); + XtFree((char *)info->widgets); + info->widgets = winfo; + } + + if (info == TipInfoList) + TipInfoList = TipInfoList->next; + else { + XawTipInfo *p = TipInfoList; + + while (p && p->next != info) + p = p->next; + if (p) + p->next = info->next; + } + + XtFree((char *)info); +} + +static void +XawTipRealize(w, mask, attr) +Widget w; +Mask *mask; +XSetWindowAttributes *attr; +{ + TipWidget tip = (TipWidget)w; + + if (tip->tip.backing_store == Always || + tip->tip.backing_store == NotUseful || + tip->tip.backing_store == WhenMapped) { + *mask |= CWBackingStore; + attr->backing_store = tip->tip.backing_store; + } + else + *mask &= ~CWBackingStore; + *mask |= CWOverrideRedirect; + attr->override_redirect = True; + + XtWindow(w) = XCreateWindow(DisplayOfScreen(XtScreen(w)), + RootWindowOfScreen(XtScreen(w)), + XtX(w), XtY(w), + XtWidth(w) ? XtWidth(w) : 1, + XtHeight(w) ? XtHeight(w) : 1, + XtBorderWidth(w), + DefaultDepthOfScreen(XtScreen(w)), + InputOutput, CopyFromParent, *mask, attr); +} + +static void +XawTipExpose(w, event, region) +Widget w; +XEvent *event; +Region region; +{ + TipWidget tip = (TipWidget)w; + GC gc = tip->tip.gc; + char *nl, *label = tip->tip.label; + Position y = tip->tip.internal_height + tip->tip.font->max_bounds.ascent; + int len; + +#ifdef XAW_INTERNATIONALIZATION + if (tip->tip.international == True) { + Position ksy = tip->tip.internal_height; + XFontSetExtents *ext = XExtentsOfFontSet(tip->tip.fontset); + + ksy += abs(ext->max_ink_extent.y); + + while ((nl = index(label, '\n')) != NULL) { + XmbDrawString(XtDisplay(w), XtWindow(w), tip->tip.fontset, + gc, tip->tip.internal_width, ksy, label, + (int)(nl - label)); + ksy += ext->max_ink_extent.height; + label = nl + 1; + } + len = strlen(label); + if (len) + XmbDrawString(XtDisplay(w), XtWindow(w), tip->tip.fontset, gc, + tip->tip.internal_width, ksy, label, len); + } + else +#endif + { + while ((nl = index(label, '\n')) != NULL) { + if (tip->tip.encoding) + XDrawString16(XtDisplay(w), XtWindow(w), gc, + tip->tip.internal_width, y, + (XChar2b*)label, (int)(nl - label) >> 1); + else + XDrawString(XtDisplay(w), XtWindow(w), gc, + tip->tip.internal_width, y, + label, (int)(nl - label)); + y += tip->tip.font->max_bounds.ascent + + tip->tip.font->max_bounds.descent; + label = nl + 1; + } + len = strlen(label); + if (len) { + if (tip->tip.encoding) + XDrawString16(XtDisplay(w), XtWindow(w), gc, + tip->tip.internal_width, y, + (XChar2b*)label, len >> 1); + else + XDrawString(XtDisplay(w), XtWindow(w), gc, + tip->tip.internal_width, y, label, len); + } + } +} + +/*ARGSUSED*/ +static Boolean +XawTipSetValues(current, request, cnew, args, num_args) +Widget current, request, cnew; +ArgList args; +Cardinal *num_args; +{ + TipWidget curtip = (TipWidget)current; + TipWidget newtip = (TipWidget)cnew; + Boolean redisplay = False; + + if (curtip->tip.font->fid != newtip->tip.font->fid || + curtip->tip.foreground != newtip->tip.foreground) { + XGCValues values; + + values.foreground = newtip->tip.foreground; + values.background = newtip->core.background_pixel; + values.font = newtip->tip.font->fid; + values.graphics_exposures = False; + XtReleaseGC(cnew, curtip->tip.gc); + newtip->tip.gc = XtAllocateGC(cnew, 0, GCForeground | GCBackground | + GCFont | GCGraphicsExposures, &values, + GCFont, 0); + redisplay = True; + } + + return (redisplay); +} + +static void +TipLayout(info) +XawTipInfo *info; +{ + XFontStruct *fs = info->tip->tip.font; + int width = 0, height; + char *nl, *label = info->tip->tip.label; + +#ifdef XAW_INTERNATIONALIZATION + if (info->tip->tip.international == True) { + XFontSet fset = info->tip->tip.fontset; + XFontSetExtents *ext = XExtentsOfFontSet(fset); + + height = ext->max_ink_extent.height; + if ((nl = index(label, '\n')) != NULL) { + /*CONSTCOND*/ + while (True) { + int w = XmbTextEscapement(fset, label, (int)(nl - label)); + + if (w > width) + width = w; + if (*nl == '\0') + break; + label = nl + 1; + if (*label) + height += ext->max_ink_extent.height; + if ((nl = index(label, '\n')) == NULL) + nl = index(label, '\0'); + } + } + else + width = XmbTextEscapement(fset, label, strlen(label)); + } + else +#endif + { + height = fs->max_bounds.ascent + fs->max_bounds.descent; + if ((nl = index(label, '\n')) != NULL) { + /*CONSTCOND*/ + while (True) { + int w = info->tip->tip.encoding ? + XTextWidth16(fs, (XChar2b*)label, + (int)(nl - label) >> 1) : + XTextWidth(fs, label, (int)(nl - label)); + + if (w > width) + width = w; + if (*nl == '\0') + break; + label = nl + 1; + if (*label) + height += fs->max_bounds.ascent + fs->max_bounds.descent; + if ((nl = index(label, '\n')) == NULL) + nl = index(label, '\0'); + } + } + else + width = info->tip->tip.encoding ? + XTextWidth16(fs, (XChar2b*)label, strlen(label) >> 1) : + XTextWidth(fs, label, strlen(label)); + } + XtWidth(info->tip) = width + info->tip->tip.internal_width * 2; + XtHeight(info->tip) = height + info->tip->tip.internal_height * 2; +} + +#define DEFAULT_TIP_OFFSET 12 + +static void +TipPosition(info) +XawTipInfo *info; +{ + Window r, c; + int rx, ry, wx, wy; + unsigned mask; + Position x, y; + int bw2 = XtBorderWidth(info->tip) * 2; + int scr_width = WidthOfScreen(XtScreen(info->tip)); + int scr_height = HeightOfScreen(XtScreen(info->tip)); + int win_width = XtWidth(info->tip) + bw2; + int win_height = XtHeight(info->tip) + bw2; + + XQueryPointer(XtDisplay((Widget)info->tip), XtWindow((Widget)info->tip), + &r, &c, &rx, &ry, &wx, &wy, &mask); + x = rx + DEFAULT_TIP_OFFSET; + y = ry + DEFAULT_TIP_OFFSET; + + if (x + win_width > scr_width) + x = scr_width - win_width; + if (x < 0) + x = 0; + + if (y + win_height > scr_height) + y -= win_height + (DEFAULT_TIP_OFFSET << 1); + if (y < 0) + y = 0; + + XMoveResizeWindow(XtDisplay(info->tip), XtWindow(info->tip), + (int)(XtX(info->tip) = x), (int)(XtY(info->tip) = y), + (unsigned)XtWidth(info->tip), + (unsigned)XtHeight(info->tip)); +} + +static WidgetInfo * +CreateWidgetInfo(w) +Widget w; +{ + WidgetInfo *winfo = XtNew(WidgetInfo); + + winfo->widget = w; + winfo->label = NULL; + winfo->next = NULL; + + return (winfo); +} + +static WidgetInfo * +FindWidgetInfo(info, w) +XawTipInfo *info; +Widget w; +{ + WidgetInfo *winfo, *wlist = info->widgets; + + if (wlist == NULL) + return (info->widgets = CreateWidgetInfo(w)); + + for (winfo = wlist; wlist; winfo = wlist, wlist = wlist->next) + if (wlist->widget == w) + return (wlist); + + return (winfo->next = CreateWidgetInfo(w)); +} + +static XawTipInfo * +CreateTipInfo(w) +Widget w; +{ + XawTipInfo *info = XtNew(XawTipInfo); + Widget shell = w; + + while (XtParent(shell)) + shell = XtParent(shell); + + info->tip = (TipWidget)XtCreateWidget("tip", tipWidgetClass, + shell, NULL, 0); + XtRealizeWidget((Widget)info->tip); + info->screen = XtScreen(w); + info->mapped = False; + info->widgets = NULL; + info->next = NULL; + XtAddEventHandler(shell, KeyPressMask, False, TipShellEventHandler, + (XtPointer)NULL); + + return (info); +} + +static XawTipInfo * +FindTipInfo(w) +Widget w; +{ + XawTipInfo *info, *list = TipInfoList; + Screen *screen; + + if (list == NULL) + return (TipInfoList = CreateTipInfo(w)); + + screen = XtScreen(w); + for (info = list; list; info = list, list = list->next) + if (list->screen == screen) + return (list); + + return (info->next = CreateTipInfo(w)); +} + +static void +ResetTip(info, winfo, add_timeout) +XawTipInfo *info; +WidgetInfo *winfo; +Bool add_timeout; +{ + if (info->tip->tip.timer) { + XtRemoveTimeOut(info->tip->tip.timer); + info->tip->tip.timer = 0; + } + if (info->mapped) { + XtRemoveGrab(XtParent((Widget)info->tip)); + XUnmapWindow(XtDisplay((Widget)info->tip), XtWindow((Widget)info->tip)); + info->mapped = False; + } + if (add_timeout) { + TimeoutData.info = info; + TimeoutData.winfo = winfo; + info->tip->tip.timer = + XtAppAddTimeOut(XtWidgetToApplicationContext((Widget)info->tip), + info->tip->tip.timeout, TipTimeoutCallback, + (XtPointer)&TimeoutData); + } +} + +static void +TipTimeoutCallback(closure, id) +XtPointer closure; +XtIntervalId *id; +{ + TimeoutInfo *cinfo = (TimeoutInfo *)closure; + XawTipInfo *info = cinfo->info; + WidgetInfo *winfo = cinfo->winfo; + Arg args[2]; + + info->tip->tip.label = winfo->label; + info->tip->tip.encoding = 0; + XtSetArg(args[0], XtNencoding, &info->tip->tip.encoding); +#ifdef XAW_INTERNATIONALIZATION + info->tip->tip.international = False; + XtSetArg(args[1], XtNinternational, &info->tip->tip.international); +#endif + XtGetValues(winfo->widget, args, 2); + + TipLayout(info); + TipPosition(info); + XMapRaised(XtDisplay((Widget)info->tip), XtWindow((Widget)info->tip)); + XtAddGrab(XtParent((Widget)info->tip), True, True); + info->mapped = True; +} + +/*ARGSUSED*/ +static void +TipShellEventHandler(w, client_data, event, continue_to_dispatch) +Widget w; +XtPointer client_data; +XEvent *event; +Boolean *continue_to_dispatch; +{ + XawTipInfo *info = FindTipInfo(w); + + ResetTip(info, FindWidgetInfo(info, w), False); +} + +/*ARGSUSED*/ +static void +TipEventHandler(w, client_data, event, continue_to_dispatch) +Widget w; +XtPointer client_data; +XEvent *event; +Boolean *continue_to_dispatch; +{ + XawTipInfo *info = FindTipInfo(w); + Boolean add_timeout; + + switch (event->type) { + case EnterNotify: + add_timeout = True; + break; + case MotionNotify: + /* If any button is pressed, timer is 0 */ + if (info->mapped) + return; + add_timeout = info->tip->tip.timer != 0; + break; + default: + add_timeout = False; + break; + } + ResetTip(info, FindWidgetInfo(info, w), add_timeout); +} + +/* + * Public routines + */ +void +XawTipEnable(w, label) +Widget w; +String label; +{ + if (XtIsWidget(w) && label && *label) { + XawTipInfo *info = FindTipInfo(w); + WidgetInfo *winfo = FindWidgetInfo(info, w); + + if (winfo->label) + XtFree((char *)winfo->label); + winfo->label = XtNewString(label); + + XtAddEventHandler(w, TIP_EVENT_MASK, False, TipEventHandler, + (XtPointer)NULL); + } +} + +void +XawTipDisable(w) +Widget w; +{ + if (XtIsWidget(w)) { + XawTipInfo *info = FindTipInfo(w); + + XtRemoveEventHandler(w, TIP_EVENT_MASK, False, TipEventHandler, + (XtPointer)NULL); + ResetTip(info, FindWidgetInfo(info, w), False); + } +} diff --git a/src/Tip.h b/src/Tip.h new file mode 100644 index 0000000..f576fd7 --- /dev/null +++ b/src/Tip.h @@ -0,0 +1,135 @@ +/* + * Copyright (c) 1999 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + * + * Author: Paulo César Pereira de Andrade + */ + +/* $XFree86: xc/lib/Xaw/Tip.h,v 1.1 1999/06/27 14:07:35 dawes Exp $ */ + +#ifndef _XawTip_h +#define _XawTip_h + +/* + * Tip Widget + */ + +#include "Xaw3dP.h" +#include <X11/Xaw3d/Simple.h> + +/* Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + background Background Pixel XtDefaultBackground + backgroundPixmap BackgroundPixmap Pixmap XtUnspecifiedPixmap + border BorderColor Pixel XtDefaultForeground + borderWidth BorderWidth Dimension 1 + destroyCallback Callback XtCallbackList NULL + font Font XFontStruct* XtDefaultFont + foreground Foreground Pixel XtDefaultForeground + height Height Dimension text height + internalHeight Height Dimension 2 + internalWidth Width Dimension 2 + label Label String NULL + timeout Timeout Int 500 + width Width Dimension text width + x Position Position 0 + y Position Position 0 + +*/ + +typedef struct _TipClassRec *TipWidgetClass; +typedef struct _TipRec *TipWidget; + +extern WidgetClass tipWidgetClass; + +#define XawTextEncoding8bit 0 +#define XawTextEncodingChar2b 1 + +#define XtNencoding "encoding" +#define XtNtimeout "timeout" +#define XtNtip "tip" + +#ifdef XAW_INTERNATIONALIZATION +#ifndef XtNfontSet +#define XtNfontSet "fontSet" +#endif +#ifndef XtCFontSet +#define XtCFontSet "FontSet" +#endif +#endif + +#define XtCEncoding "Encoding" +#define XtCTimeout "Timeout" +#define XtCTip "Tip" + +#ifndef _XtStringDefs_h_ +#define XtNforeground "foreground" +#define XtNlabel "label" +#define XtNfont "font" +#define XtNinternalWidth "internalWidth" +#define XtNinternalHeight "internalHeight" +#endif + +/* + * Public Functions + */ + +/* + * Function: + * XawTipEnable + * + * Parameters: + * Widget - widget for tooltip + * String - tooltip label + * + * Description: + * Enables the tip event handler for this widget. + */ +void XawTipEnable( +#if NeedFunctionPrototypes + Widget, + String +#endif +); + +/* + * Function: + * XawTipDisable + * + * Parameters: + * Widget - widget for tooltip + * + * Description: + * Disables the tip event handler for this widget. + */ +void XawTipDisable( +#if NeedFunctionPrototypes + Widget +#endif +); + +#endif /* _XawTip_h */ diff --git a/src/TipP.h b/src/TipP.h new file mode 100644 index 0000000..a4430d7 --- /dev/null +++ b/src/TipP.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 1999 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of the XFree86 Project shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from the + * XFree86 Project. + * + * Author: Paulo César Pereira de Andrade + */ + +/* $XFree86: xc/lib/Xaw/TipP.h,v 1.1 1999/06/27 14:07:35 dawes Exp $ */ + +#ifndef _XawTipP_h +#define _XawTipP_h + +#include "Xaw3dP.h" +#include <X11/Xaw3d/Tip.h> + +typedef struct { + XtPointer extension; +} TipClassPart; + +typedef struct _TipClassRec { + CoreClassPart core_class; + TipClassPart tip_class; +} TipClassRec; + +extern TipClassRec tipClassRec; + +typedef struct _TipPart { + /* resources */ + Pixel foreground; + XFontStruct *font; +#ifdef XAW_INTERNATIONALIZATION + XFontSet fontset; +#endif + Dimension internal_width; + Dimension internal_height; + String label; + int backing_store; + int timeout; + + /* private */ + GC gc; + XtIntervalId timer; +#ifdef XAW_INTERNATIONALIZATION + Boolean international; +#endif + unsigned char encoding; +} TipPart; + +typedef struct _TipRec { + CorePart core; + TipPart tip; +} TipRec; + +#endif /* _XawTipP_h */ diff --git a/src/Toggle.c b/src/Toggle.c new file mode 100644 index 0000000..66902c4 --- /dev/null +++ b/src/Toggle.c @@ -0,0 +1,619 @@ +/* $XConsortium: Toggle.c,v 1.28 94/04/17 20:13:17 kaleb Exp $ */ + +/* + +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + */ + +/* + * Toggle.c - Toggle button widget + * + * Author: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + * + * Date: January 12, 1989 + * + */ + +#include <stdio.h> + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xmu/Converters.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xaw3d/ToggleP.h> + +/**************************************************************** + * + * Full class record constant + * + ****************************************************************/ + +/* Private Data */ + +/* + * The order of toggle and notify are important, as the state has + * to be set when we call the notify proc. + */ + +static char defaultTranslations[] = + "<EnterWindow>: highlight(Always) \n\ + <LeaveWindow>: unhighlight() \n\ + <Btn1Down>,<Btn1Up>: toggle() notify()"; + +#define offset(field) XtOffsetOf(ToggleRec, field) + +static XtResource resources[] = { + {XtNstate, XtCState, XtRBoolean, sizeof(Boolean), + offset(command.set), XtRString, "off"}, + {XtNradioGroup, XtCWidget, XtRWidget, sizeof(Widget), + offset(toggle.widget), XtRWidget, (XtPointer) NULL }, + {XtNradioData, XtCRadioData, XtRPointer, sizeof(XtPointer), + offset(toggle.radio_data), XtRPointer, (XtPointer) NULL }, +}; + +#undef offset + + +static void Toggle(), Initialize(), Notify(), ToggleSet(); +static void ToggleDestroy(), ClassInit(); +static Boolean SetValues(); + +/* Functions for handling the Radio Group. */ + +static RadioGroup * GetRadioGroup(); +static void CreateRadioGroup(), AddToRadioGroup(), TurnOffRadioSiblings(); +static void RemoveFromRadioGroup(); + +static XtActionsRec actionsList[] = +{ + {"toggle", Toggle}, + {"notify", Notify}, + {"set", ToggleSet}, +}; + +#define SuperClass ((CommandWidgetClass)&commandClassRec) + +ToggleClassRec toggleClassRec = { + { + (WidgetClass) SuperClass, /* superclass */ + "Toggle", /* class_name */ + sizeof(ToggleRec), /* size */ + ClassInit, /* class_initialize */ + NULL, /* class_part_initialize */ + FALSE, /* class_inited */ + Initialize, /* initialize */ + NULL, /* initialize_hook */ + XtInheritRealize, /* realize */ + actionsList, /* actions */ + XtNumber(actionsList), /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* resource_count */ + NULLQUARK, /* xrm_class */ + FALSE, /* compress_motion */ + TRUE, /* compress_exposure */ + TRUE, /* compress_enterleave */ + FALSE, /* visible_interest */ + NULL, /* destroy */ + XtInheritResize, /* resize */ + XtInheritExpose, /* expose */ + SetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + defaultTranslations, /* tm_table */ + XtInheritQueryGeometry, /* query_geometry */ + XtInheritDisplayAccelerator, /* display_accelerator */ + NULL /* extension */ + }, /* CoreClass fields initialization */ + { + XtInheritChangeSensitive /* change_sensitive */ + }, /* SimpleClass fields initialization */ + { + XtInheritXaw3dShadowDraw /* shadowdraw */ + }, /* ThreeDClass fields initialization */ + { + 0 /* field not used */ + }, /* LabelClass fields initialization */ + { + 0 /* field not used */ + }, /* CommandClass fields initialization */ + { + NULL, /* Set Procedure. */ + NULL, /* Unset Procedure. */ + NULL /* extension. */ + } /* ToggleClass fields initialization */ +}; + + /* for public consumption */ +WidgetClass toggleWidgetClass = (WidgetClass) &toggleClassRec; + +/**************************************************************** + * + * Private Procedures + * + ****************************************************************/ + +static void +ClassInit() +{ + XtActionList actions; + Cardinal num_actions; + Cardinal i; + ToggleWidgetClass class = (ToggleWidgetClass) toggleWidgetClass; + static XtConvertArgRec parentCvtArgs[] = { + {XtBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.parent), + sizeof(Widget)} + }; + + XawInitializeWidgetSet(); + XtSetTypeConverter(XtRString, XtRWidget, XmuNewCvtStringToWidget, + parentCvtArgs, XtNumber(parentCvtArgs), XtCacheNone, + (XtDestructor)NULL); +/* + * Find the set and unset actions in the command widget's action table. + */ + + XtGetActionList(commandWidgetClass, &actions, &num_actions); + + for (i = 0 ; i < num_actions ; i++) { + if (streq(actions[i].string, "set")) + class->toggle_class.Set = actions[i].proc; + if (streq(actions[i].string, "unset")) + class->toggle_class.Unset = actions[i].proc; + + if ( (class->toggle_class.Set != NULL) && + (class->toggle_class.Unset != NULL) ) { + XtFree((char *) actions); + return; + } + } + +/* We should never get here. */ + XtError("Aborting, due to errors resolving bindings in the Toggle widget."); +} + +/*ARGSUSED*/ +static void Initialize(request, new, args, num_args) + Widget request, new; + ArgList args; + Cardinal *num_args; +{ + ToggleWidget tw = (ToggleWidget) new; + ToggleWidget tw_req = (ToggleWidget) request; + + tw->toggle.radio_group = NULL; + + if (tw->toggle.radio_data == NULL) + tw->toggle.radio_data = (XtPointer) new->core.name; + + if (tw->toggle.widget != NULL) { + if ( GetRadioGroup(tw->toggle.widget) == NULL) + CreateRadioGroup(new, tw->toggle.widget); + else + AddToRadioGroup( GetRadioGroup(tw->toggle.widget), new); + } + XtAddCallback(new, XtNdestroyCallback, ToggleDestroy, (XtPointer)NULL); + +/* + * Command widget assumes that the widget is unset, so we only + * have to handle the case where it needs to be set. + * + * If this widget is in a radio group then it may cause another + * widget to be unset, thus calling the notify proceedure. + * + * I want to set the toggle if the user set the state to "On" in + * the resource group, reguardless of what my ancestors did. + */ + + if (tw_req->command.set) + ToggleSet(new, (XEvent *)NULL, (String *)NULL, (Cardinal *)0); +} + +/************************************************************ + * + * Action Procedures + * + ************************************************************/ + +/* ARGSUSED */ +static void +ToggleSet(w,event,params,num_params) +Widget w; +XEvent *event; +String *params; /* unused */ +Cardinal *num_params; /* unused */ +{ + ToggleWidgetClass class = (ToggleWidgetClass) w->core.widget_class; + + TurnOffRadioSiblings(w); + class->toggle_class.Set(w, event, NULL, 0); +} + +/* ARGSUSED */ +static void +Toggle(w,event,params,num_params) +Widget w; +XEvent *event; +String *params; /* unused */ +Cardinal *num_params; /* unused */ +{ + ToggleWidget tw = (ToggleWidget)w; + ToggleWidgetClass class = (ToggleWidgetClass) w->core.widget_class; + + if (tw->command.set) + class->toggle_class.Unset(w, event, NULL, 0); + else + ToggleSet(w, event, params, num_params); +} + +/* ARGSUSED */ +static void Notify(w,event,params,num_params) +Widget w; +XEvent *event; +String *params; /* unused */ +Cardinal *num_params; /* unused */ +{ + ToggleWidget tw = (ToggleWidget) w; + long antilint = tw->command.set; + + XtCallCallbacks( w, XtNcallback, (XtPointer) antilint ); +} + +/************************************************************ + * + * Set specified arguments into widget + * + ***********************************************************/ + +/* ARGSUSED */ +static Boolean +SetValues (current, request, new, args, num_args) +Widget current, request, new; +ArgList args; +Cardinal *num_args; +{ + ToggleWidget oldtw = (ToggleWidget) current; + ToggleWidget tw = (ToggleWidget) new; + ToggleWidget rtw = (ToggleWidget) request; + + if (oldtw->toggle.widget != tw->toggle.widget) + XawToggleChangeRadioGroup(new, tw->toggle.widget); + + if (!tw->core.sensitive && oldtw->core.sensitive && rtw->command.set) + tw->command.set = True; + + if (oldtw->command.set != tw->command.set) { + tw->command.set = oldtw->command.set; + Toggle(new, (XEvent *)NULL, (String *)NULL, (Cardinal *)0); + } + return(FALSE); +} + +/* Function Name: ToggleDestroy + * Description: Destroy Callback for toggle widget. + * Arguments: w - the toggle widget that is being destroyed. + * junk, grabage - not used. + * Returns: none. + */ + +/* ARGSUSED */ +static void +ToggleDestroy(w, junk, garbage) +Widget w; +XtPointer junk, garbage; +{ + RemoveFromRadioGroup(w); +} + +/************************************************************ + * + * Below are all the private procedures that handle + * radio toggle buttons. + * + ************************************************************/ + +/* Function Name: GetRadioGroup + * Description: Gets the radio group associated with a give toggle + * widget. + * Arguments: w - the toggle widget who's radio group we are getting. + * Returns: the radio group associated with this toggle group. + */ + +static RadioGroup * +GetRadioGroup(w) +Widget w; +{ + ToggleWidget tw = (ToggleWidget) w; + + if (tw == NULL) return(NULL); + return( tw->toggle.radio_group ); +} + +/* Function Name: CreateRadioGroup + * Description: Creates a radio group. give two widgets. + * Arguments: w1, w2 - the toggle widgets to add to the radio group. + * Returns: none. + * + * NOTE: A pointer to the group is added to each widget's radio_group + * field. + */ + +static void +CreateRadioGroup(w1, w2) +Widget w1, w2; +{ + char error_buf[BUFSIZ]; + ToggleWidget tw1 = (ToggleWidget) w1; + ToggleWidget tw2 = (ToggleWidget) w2; + + if ( (tw1->toggle.radio_group != NULL) || (tw2->toggle.radio_group != NULL) ) { + (void) sprintf(error_buf, "%s %s", "Toggle Widget Error - Attempting", + "to create a new toggle group, when one already exists."); + XtWarning(error_buf); + } + + AddToRadioGroup( (RadioGroup *)NULL, w1 ); + AddToRadioGroup( GetRadioGroup(w1), w2 ); +} + +/* Function Name: AddToRadioGroup + * Description: Adds a toggle to the radio group. + * Arguments: group - any element of the radio group the we are adding to. + * w - the new toggle widget to add to the group. + * Returns: none. + */ + +static void +AddToRadioGroup(group, w) +RadioGroup * group; +Widget w; +{ + ToggleWidget tw = (ToggleWidget) w; + RadioGroup * local; + + local = (RadioGroup *) XtMalloc( sizeof(RadioGroup) ); + local->widget = w; + tw->toggle.radio_group = local; + + if (group == NULL) { /* Creating new group. */ + group = local; + group->next = NULL; + group->prev = NULL; + return; + } + local->prev = group; /* Adding to previous group. */ + if ((local->next = group->next) != NULL) + local->next->prev = local; + group->next = local; +} + +/* Function Name: TurnOffRadioSiblings + * Description: Deactivates all radio siblings. + * Arguments: widget - a toggle widget. + * Returns: none. + */ + +static void +TurnOffRadioSiblings(w) +Widget w; +{ + RadioGroup * group; + ToggleWidgetClass class = (ToggleWidgetClass) w->core.widget_class; + + if ( (group = GetRadioGroup(w)) == NULL) /* Punt if there is no group */ + return; + + /* Go to the top of the group. */ + + for ( ; group->prev != NULL ; group = group->prev ); + + while ( group != NULL ) { + ToggleWidget local_tog = (ToggleWidget) group->widget; + if ( local_tog->command.set ) { + class->toggle_class.Unset(group->widget, NULL, NULL, 0); + Notify( group->widget, (XEvent *)NULL, (String *)NULL, (Cardinal *)0); + } + group = group->next; + } +} + +/* Function Name: RemoveFromRadioGroup + * Description: Removes a toggle from a RadioGroup. + * Arguments: w - the toggle widget to remove. + * Returns: none. + */ + +static void +RemoveFromRadioGroup(w) +Widget w; +{ + RadioGroup * group = GetRadioGroup(w); + if (group != NULL) { + if (group->prev != NULL) + (group->prev)->next = group->next; + if (group->next != NULL) + (group->next)->prev = group->prev; + XtFree((char *) group); + } +} + +/************************************************************ + * + * Public Routines + * + ************************************************************/ + +/* Function Name: XawToggleChangeRadioGroup + * Description: Allows a toggle widget to change radio groups. + * Arguments: w - The toggle widget to change groups. + * radio_group - any widget in the new group. + * Returns: none. + */ + +void +#if NeedFunctionPrototypes +XawToggleChangeRadioGroup(Widget w, Widget radio_group) +#else +XawToggleChangeRadioGroup(w, radio_group) +Widget w, radio_group; +#endif +{ + ToggleWidget tw = (ToggleWidget) w; + RadioGroup * group; + + RemoveFromRadioGroup(w); + +/* + * If the toggle that we are about to add is set then we will + * unset all toggles in the new radio group. + */ + + if ( tw->command.set && radio_group != NULL ) + XawToggleUnsetCurrent(radio_group); + + if (radio_group != NULL) + if ((group = GetRadioGroup(radio_group)) == NULL) + CreateRadioGroup(w, radio_group); + else AddToRadioGroup(group, w); +} + +/* Function Name: XawToggleGetCurrent + * Description: Returns the RadioData associated with the toggle + * widget that is currently active in a toggle group. + * Arguments: w - any toggle widget in the toggle group. + * Returns: The XtNradioData associated with the toggle widget. + */ + +XtPointer +#if NeedFunctionPrototypes +XawToggleGetCurrent(Widget w) +#else +XawToggleGetCurrent(w) +Widget w; +#endif +{ + RadioGroup * group; + + if ( (group = GetRadioGroup(w)) == NULL) return(NULL); + for ( ; group->prev != NULL ; group = group->prev); + + while ( group != NULL ) { + ToggleWidget local_tog = (ToggleWidget) group->widget; + if ( local_tog->command.set ) + return( local_tog->toggle.radio_data ); + group = group->next; + } + return(NULL); +} + +/* Function Name: XawToggleSetCurrent + * Description: Sets the Toggle widget associated with the + * radio_data specified. + * Arguments: radio_group - any toggle widget in the toggle group. + * radio_data - radio data of the toggle widget to set. + * Returns: none. + */ + +void +#if NeedFunctionPrototypes +XawToggleSetCurrent(Widget radio_group, XtPointer radio_data) +#else +XawToggleSetCurrent(radio_group, radio_data) +Widget radio_group; +XtPointer radio_data; +#endif +{ + RadioGroup * group; + ToggleWidget local_tog; + +/* Special case of no radio group. */ + + if ( (group = GetRadioGroup(radio_group)) == NULL) { + local_tog = (ToggleWidget) radio_group; + if ( (local_tog->toggle.radio_data == radio_data) ) + if (!local_tog->command.set) { + ToggleSet((Widget) local_tog, (XEvent *)NULL, (String *)NULL, (Cardinal *)0); + Notify((Widget) local_tog, (XEvent *)NULL, (String *)NULL, (Cardinal *)0); + } + return; + } + +/* + * find top of radio_roup + */ + + for ( ; group->prev != NULL ; group = group->prev); + +/* + * search for matching radio data. + */ + + while ( group != NULL ) { + local_tog = (ToggleWidget) group->widget; + if ( (local_tog->toggle.radio_data == radio_data) ) { + if (!local_tog->command.set) { /* if not already set. */ + ToggleSet((Widget) local_tog, (XEvent *)NULL, (String *)NULL, (Cardinal *)0); + Notify((Widget) local_tog, (XEvent *)NULL, (String *)NULL, (Cardinal *)0); + } + return; /* found it, done */ + } + group = group->next; + } +} + +/* Function Name: XawToggleUnsetCurrent + * Description: Unsets all Toggles in the radio_group specified. + * Arguments: radio_group - any toggle widget in the toggle group. + * Returns: none. + */ + +void +#if NeedFunctionPrototypes +XawToggleUnsetCurrent(Widget radio_group) +#else +XawToggleUnsetCurrent(radio_group) +Widget radio_group; +#endif +{ + ToggleWidgetClass class; + ToggleWidget local_tog = (ToggleWidget) radio_group; + + /* Special Case no radio group. */ + + if (local_tog->command.set) { + class = (ToggleWidgetClass) local_tog->core.widget_class; + class->toggle_class.Unset(radio_group, NULL, NULL, 0); + Notify(radio_group, (XEvent *)NULL, (String *)NULL, (Cardinal *)0); + } + if ( GetRadioGroup(radio_group) == NULL) return; + TurnOffRadioSiblings(radio_group); +} + diff --git a/src/Toggle.h b/src/Toggle.h new file mode 100644 index 0000000..7083139 --- /dev/null +++ b/src/Toggle.h @@ -0,0 +1,177 @@ +/* + * $XConsortium: Toggle.h,v 1.16 94/04/17 20:13:19 kaleb Exp $ + * +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + */ + +/* + * ToggleP.h - Private definitions for Toggle widget + * + * Author: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + * + * Date: January 12, 1989 + */ + +#ifndef _XawToggle_h +#define _XawToggle_h + +/*********************************************************************** + * + * Toggle Widget + * + ***********************************************************************/ + +#include <X11/Xaw3d/Command.h> + +/* Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + radioGroup RadioGroup Widget NULL + + radioData RadioData Pointer (XPointer) Widget ++ + state State Boolean Off + + background Background Pixel XtDefaultBackground + bitmap Pixmap Pixmap None + border BorderColor Pixel XtDefaultForeground + borderWidth BorderWidth Dimension 1 + callback Callback Pointer NULL + cursor Cursor Cursor None + destroyCallback Callback Pointer NULL + font Font XFontStructx* XtDefaultFont + foreground Foreground Pixel XtDefaultForeground + height Height Dimension text height + highlightThickness Thickness Dimension 2 + insensitiveBorder Insensitive Pixmap Gray + internalHeight Height Dimension 2 + internalWidth Width Dimension 4 + justify Justify XtJustify XtJustifyCenter + label Label String NULL + mappedWhenManaged MappedWhenManaged Boolean True + resize Resize Boolean True + sensitive Sensitive Boolean True + width Width Dimension text width + x Position Position 0 + y Position Position 0 + ++ To use the toggle as a radio toggle button, set this resource to point to + any other widget in the radio group. + +++ This is the data returned from a call to XtToggleGetCurrent, by default + this is set to the name of toggle widget. + +*/ + +/* + * These should be in StringDefs.h but aren't so we will define + * them here if they are needed. + */ + + +#define XtCWidget "Widget" +#define XtCState "State" +#define XtCRadioGroup "RadioGroup" +#define XtCRadioData "RadioData" + +#ifndef _XtStringDefs_h_ +#define XtRWidget "Widget" +#endif + +#define XtNstate "state" +#define XtNradioGroup "radioGroup" +#define XtNradioData "radioData" + +extern WidgetClass toggleWidgetClass; + +typedef struct _ToggleClassRec *ToggleWidgetClass; +typedef struct _ToggleRec *ToggleWidget; + + +/************************************************************ + * + * Public Functions + * + ************************************************************/ + +_XFUNCPROTOBEGIN + +/* Function Name: XawToggleChangeRadioGroup + * Description: Allows a toggle widget to change radio lists. + * Arguments: w - The toggle widget to change lists. + * radio_group - any widget in the new list. + * Returns: none. + */ + +extern void XawToggleChangeRadioGroup( +#if NeedFunctionPrototypes + Widget /* w */, + Widget /* radio_group */ +#endif +); + +/* Function Name: XawToggleGetCurrent + * Description: Returns the RadioData associated with the toggle + * widget that is currently active in a toggle list. + * Arguments: radio_group - any toggle widget in the toggle list. + * Returns: The XtNradioData associated with the toggle widget. + */ + +extern XtPointer XawToggleGetCurrent( +#if NeedFunctionPrototypes + Widget /* radio_group */ +#endif +); + +/* Function Name: XawToggleSetCurrent + * Description: Sets the Toggle widget associated with the + * radio_data specified. + * Arguments: radio_group - any toggle widget in the toggle list. + * radio_data - radio data of the toggle widget to set. + * Returns: none. + */ + +extern void XawToggleSetCurrent( +#if NeedFunctionPrototypes + Widget /* radio_group */, + XtPointer /* radio_data */ +#endif +); + +/* Function Name: XawToggleUnsetCurrent + * Description: Unsets all Toggles in the radio_group specified. + * Arguments: radio_group - any toggle widget in the toggle list. + * Returns: none. + */ + +extern void XawToggleUnsetCurrent( +#if NeedFunctionPrototypes + Widget /* radio_group */ +#endif +); + +_XFUNCPROTOEND + +#endif /* _XawToggle_h */ diff --git a/src/ToggleP.h b/src/ToggleP.h new file mode 100644 index 0000000..0155ae4 --- /dev/null +++ b/src/ToggleP.h @@ -0,0 +1,113 @@ +/* $XConsortium: ToggleP.h,v 1.9 94/04/17 20:13:19 converse Exp $ */ + +/* + +Copyright (c) 1989 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +/* + * ToggleP.h - Private definitions for Toggle widget + * + * Author: Chris D. Peterson + * MIT X Consortium + * kit@expo.lcs.mit.edu + * + * Date: January 12, 1989 + * + */ + +#ifndef _XawToggleP_h +#define _XawToggleP_h + +#include <X11/Xaw3d/Toggle.h> +#include <X11/Xaw3d/CommandP.h> + +/*********************************************************************** + * + * Toggle Widget Private Data + * + ***********************************************************************/ + +#define streq(a, b) ( strcmp((a), (b)) == 0 ) + +typedef struct _RadioGroup { + struct _RadioGroup *prev, *next; /* Pointers to other elements in group. */ + Widget widget; /* Widget corrosponding to this element. */ +} RadioGroup; + +/************************************ + * + * Class structure + * + ***********************************/ + + /* New fields for the Toggle widget class record */ +typedef struct _ToggleClass { + XtActionProc Set; + XtActionProc Unset; + XtPointer extension; +} ToggleClassPart; + + /* Full class record declaration */ +typedef struct _ToggleClassRec { + CoreClassPart core_class; + SimpleClassPart simple_class; + ThreeDClassPart threeD_class; + LabelClassPart label_class; + CommandClassPart command_class; + ToggleClassPart toggle_class; +} ToggleClassRec; + +extern ToggleClassRec toggleClassRec; + +/*************************************** + * + * Instance (widget) structure + * + **************************************/ + + /* New fields for the Toggle widget record */ +typedef struct { + /* resources */ + Widget widget; + XtPointer radio_data; + + /* private data */ + RadioGroup * radio_group; +} TogglePart; + + /* Full widget declaration */ +typedef struct _ToggleRec { + CorePart core; + SimplePart simple; + ThreeDPart threeD; + LabelPart label; + CommandPart command; + TogglePart toggle; +} ToggleRec; + +#endif /* _XawToggleP_h */ + + diff --git a/src/Tree.c b/src/Tree.c new file mode 100644 index 0000000..94b8d70 --- /dev/null +++ b/src/Tree.c @@ -0,0 +1,1008 @@ +/* + * $XConsortium: Tree.c,v 1.45 94/04/17 20:13:20 kaleb Exp $ + * + +Copyright (c) 1990, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + * Copyright 1989 Prentice Hall + * + * Permission to use, copy, modify, and distribute this software for any + * purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation. + * + * Prentice Hall and the authors disclaim all warranties with regard + * to this software, including all implied warranties of merchantability and + * fitness. In no event shall Prentice Hall or the authors be liable + * for any special, indirect or cosequential damages or any damages whatsoever + * resulting from loss of use, data or profits, whether in an action of + * contract, negligence or other tortious action, arising out of or in + * connection with the use or performance of this software. + * + * Authors: Jim Fulton, MIT X Consortium, + * based on a version by Douglas Young, Prentice Hall + * + * This widget is based on the Tree widget described on pages 397-419 of + * Douglas Young's book "The X Window System, Programming and Applications + * with Xt OSF/Motif Edition." The layout code has been rewritten to use + * additional blank space to make the structure of the graph easier to see + * as well as to support vertical trees. + */ + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xaw3d/Cardinals.h> +#include <X11/Xaw3d/TreeP.h> + +#define IsHorizontal(tw) ((tw)->tree.gravity == WestGravity || \ + (tw)->tree.gravity == EastGravity) + + + /* widget class method */ +static void ClassInitialize(); +static void Initialize(); +static void ConstraintInitialize(); +static void ConstraintDestroy(); +static Boolean ConstraintSetValues(); +static void Destroy(); +static Boolean SetValues(); +static XtGeometryResult GeometryManager(); +static void ChangeManaged(); +static void Redisplay(); +static XtGeometryResult QueryGeometry(); + + /* utility routines */ +static void insert_node(); +static void delete_node(); +static void layout_tree(); + + +/* + * resources of the tree itself + */ +static XtResource resources[] = { + { XtNautoReconfigure, XtCAutoReconfigure, XtRBoolean, sizeof (Boolean), + XtOffsetOf(TreeRec, tree.auto_reconfigure), XtRImmediate, + (XtPointer) FALSE }, + { XtNhSpace, XtCHSpace, XtRDimension, sizeof (Dimension), + XtOffsetOf(TreeRec, tree.hpad), XtRImmediate, (XtPointer) 0 }, + { XtNvSpace, XtCVSpace, XtRDimension, sizeof (Dimension), + XtOffsetOf(TreeRec, tree.vpad), XtRImmediate, (XtPointer) 0 }, + { XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel), + XtOffsetOf(TreeRec, tree.foreground), XtRString, + XtDefaultForeground}, + { XtNlineWidth, XtCLineWidth, XtRDimension, sizeof (Dimension), + XtOffsetOf(TreeRec, tree.line_width), XtRImmediate, (XtPointer) 0 }, + { XtNgravity, XtCGravity, XtRGravity, sizeof (XtGravity), + XtOffsetOf(TreeRec, tree.gravity), XtRImmediate, + (XtPointer) WestGravity }, +}; + + +/* + * resources that are attached to all children of the tree + */ +static XtResource treeConstraintResources[] = { + { XtNtreeParent, XtCTreeParent, XtRWidget, sizeof (Widget), + XtOffsetOf(TreeConstraintsRec, tree.parent), XtRImmediate, NULL }, + { XtNtreeGC, XtCTreeGC, XtRGC, sizeof(GC), + XtOffsetOf(TreeConstraintsRec, tree.gc), XtRImmediate, NULL }, +}; + + +TreeClassRec treeClassRec = { + { + /* core_class fields */ + (WidgetClass) &constraintClassRec, /* superclass */ + "Tree", /* class_name */ + sizeof(TreeRec), /* widget_size */ + ClassInitialize, /* class_init */ + NULL, /* class_part_init */ + FALSE, /* class_inited */ + Initialize, /* initialize */ + NULL, /* initialize_hook */ + XtInheritRealize, /* realize */ + NULL, /* actions */ + 0, /* num_actions */ + resources, /* resources */ + XtNumber(resources), /* num_resources */ + NULLQUARK, /* xrm_class */ + TRUE, /* compress_motion */ + TRUE, /* compress_exposure */ + TRUE, /* compress_enterleave*/ + TRUE, /* visible_interest */ + Destroy, /* destroy */ + NULL, /* resize */ + Redisplay, /* expose */ + SetValues, /* set_values */ + NULL, /* set_values_hook */ + XtInheritSetValuesAlmost, /* set_values_almost */ + NULL, /* get_values_hook */ + NULL, /* accept_focus */ + XtVersion, /* version */ + NULL, /* callback_private */ + NULL, /* tm_table */ + QueryGeometry, /* query_geometry */ + NULL, /* display_accelerator*/ + NULL, /* extension */ + }, + { + /* composite_class fields */ + GeometryManager, /* geometry_manager */ + ChangeManaged, /* change_managed */ + XtInheritInsertChild, /* insert_child */ + XtInheritDeleteChild, /* delete_child */ + NULL, /* extension */ + }, + { + /* constraint_class fields */ + treeConstraintResources, /* subresources */ + XtNumber(treeConstraintResources), /* subresource_count */ + sizeof(TreeConstraintsRec), /* constraint_size */ + ConstraintInitialize, /* initialize */ + ConstraintDestroy, /* destroy */ + ConstraintSetValues, /* set_values */ + NULL, /* extension */ + }, + { + /* Tree class fields */ + 0, /* ignore */ + } +}; + +WidgetClass treeWidgetClass = (WidgetClass) &treeClassRec; + + +/***************************************************************************** + * * + * tree utility routines * + * * + *****************************************************************************/ + +static void initialize_dimensions (listp, sizep, n) + Dimension **listp; + int *sizep; + int n; +{ + int i; + Dimension *l; + + if (!*listp) { + *listp = (Dimension *) XtCalloc ((unsigned int) n, + (unsigned int) sizeof(Dimension)); + *sizep = ((*listp) ? n : 0); + return; + } + if (n > *sizep) { + *listp = (Dimension *) XtRealloc((char *) *listp, + (unsigned int) (n*sizeof(Dimension))); + if (!*listp) { + *sizep = 0; + return; + } + for (i = *sizep, l = (*listp) + i; i < n; i++, l++) *l = 0; + *sizep = n; + } + return; +} + +static GC get_tree_gc (w) + TreeWidget w; +{ + XtGCMask valuemask = GCBackground | GCForeground; + XGCValues values; + + values.background = w->core.background_pixel; + values.foreground = w->tree.foreground; + if (w->tree.line_width != 0) { + valuemask |= GCLineWidth; + values.line_width = w->tree.line_width; + } + + return XtGetGC ((Widget) w, valuemask, &values); +} + +static void insert_node (parent, node) + Widget parent, node; +{ + TreeConstraints pc; + TreeConstraints nc = TREE_CONSTRAINT(node); + int nindex; + + nc->tree.parent = parent; + + if (parent == NULL) return; + + /* + * If there isn't more room in the children array, + * allocate additional space. + */ + pc = TREE_CONSTRAINT(parent); + nindex = pc->tree.n_children; + + if (pc->tree.n_children == pc->tree.max_children) { + pc->tree.max_children += (pc->tree.max_children / 2) + 2; + pc->tree.children = (WidgetList) XtRealloc ((char *)pc->tree.children, + (unsigned int) + ((pc->tree.max_children) * + sizeof(Widget))); + } + + /* + * Add the sub_node in the next available slot and + * increment the counter. + */ + pc->tree.children[nindex] = node; + pc->tree.n_children++; +} + +static void delete_node (parent, node) + Widget parent, node; +{ + TreeConstraints pc; + int pos, i; + + /* + * Make sure the parent exists. + */ + if (!parent) return; + + pc = TREE_CONSTRAINT(parent); + + /* + * Find the sub_node on its parent's list. + */ + for (pos = 0; pos < pc->tree.n_children; pos++) + if (pc->tree.children[pos] == node) break; + + if (pos == pc->tree.n_children) return; + + /* + * Decrement the number of children + */ + pc->tree.n_children--; + + /* + * Fill in the gap left by the sub_node. + * Zero the last slot for good luck. + */ + for (i = pos; i < pc->tree.n_children; i++) + pc->tree.children[i] = pc->tree.children[i+1]; + + pc->tree.children[pc->tree.n_children]=0; +} + +static void check_gravity (tw, grav) + TreeWidget tw; + XtGravity grav; +{ + switch (tw->tree.gravity) { + case WestGravity: case NorthGravity: case EastGravity: case SouthGravity: + break; + default: + tw->tree.gravity = grav; + break; + } +} + + +/***************************************************************************** + * * + * tree class methods * + * * + *****************************************************************************/ + +static void ClassInitialize () +{ + XawInitializeWidgetSet(); + XtAddConverter (XtRString, XtRGravity, XmuCvtStringToGravity, + (XtConvertArgList) NULL, (Cardinal) 0); +} + + +/*ARGSUSED*/ +static void Initialize (grequest, gnew, args, num_args) + Widget grequest, gnew; + ArgList args; + Cardinal *num_args; +{ + TreeWidget request = (TreeWidget) grequest, new = (TreeWidget) gnew; + Arg arglist[2]; + + /* + * Make sure the widget's width and height are + * greater than zero. + */ + if (request->core.width <= 0) new->core.width = 5; + if (request->core.height <= 0) new->core.height = 5; + + /* + * Set the padding according to the orientation + */ + if (request->tree.hpad == 0 && request->tree.vpad == 0) { + if (IsHorizontal (request)) { + new->tree.hpad = TREE_HORIZONTAL_DEFAULT_SPACING; + new->tree.vpad = TREE_VERTICAL_DEFAULT_SPACING; + } else { + new->tree.hpad = TREE_VERTICAL_DEFAULT_SPACING; + new->tree.vpad = TREE_HORIZONTAL_DEFAULT_SPACING; + } + } + + /* + * Create a graphics context for the connecting lines. + */ + new->tree.gc = get_tree_gc (new); + + /* + * Create the hidden root widget. + */ + new->tree.tree_root = (Widget) NULL; + XtSetArg(arglist[0], XtNwidth, 1); + XtSetArg(arglist[1], XtNheight, 1); + new->tree.tree_root = XtCreateWidget ("root", widgetClass, gnew, + arglist,TWO); + + /* + * Allocate the array used to hold the widest values per depth + */ + new->tree.largest = NULL; + new->tree.n_largest = 0; + initialize_dimensions (&new->tree.largest, &new->tree.n_largest, + TREE_INITIAL_DEPTH); + + /* + * make sure that our gravity is one of the acceptable values + */ + check_gravity (new, WestGravity); +} + + +/* ARGSUSED */ +static void ConstraintInitialize (request, new, args, num_args) + Widget request, new; + ArgList args; + Cardinal *num_args; +{ + TreeConstraints tc = TREE_CONSTRAINT(new); + TreeWidget tw = (TreeWidget) new->core.parent; + + /* + * Initialize the widget to have no sub-nodes. + */ + tc->tree.n_children = 0; + tc->tree.max_children = 0; + tc->tree.children = (Widget *) NULL; + tc->tree.x = tc->tree.y = 0; + tc->tree.bbsubwidth = 0; + tc->tree.bbsubheight = 0; + + + /* + * If this widget has a super-node, add it to that + * widget' sub-nodes list. Otherwise make it a sub-node of + * the tree_root widget. + */ + if (tc->tree.parent) + insert_node (tc->tree.parent, new); + else if (tw->tree.tree_root) + insert_node (tw->tree.tree_root, new); +} + + +/* ARGSUSED */ +static Boolean SetValues (gcurrent, grequest, gnew, args, num_args) + Widget gcurrent, grequest, gnew; + ArgList args; + Cardinal *num_args; +{ + TreeWidget current = (TreeWidget) gcurrent, new = (TreeWidget) gnew; + Boolean redraw = FALSE; + + /* + * If the foreground color has changed, redo the GC's + * and indicate a redraw. + */ + if (new->tree.foreground != current->tree.foreground || + new->core.background_pixel != current->core.background_pixel || + new->tree.line_width != current->tree.line_width) { + XtReleaseGC (gnew, new->tree.gc); + new->tree.gc = get_tree_gc (new); + redraw = TRUE; + } + + /* + * If the minimum spacing has changed, recalculate the + * tree layout. layout_tree() does a redraw, so we don't + * need SetValues to do another one. + */ + if (new->tree.gravity != current->tree.gravity) { + check_gravity (new, current->tree.gravity); + } + + if (IsHorizontal(new) != IsHorizontal(current)) { + if (new->tree.vpad == current->tree.vpad && + new->tree.hpad == current->tree.hpad) { + new->tree.vpad = current->tree.hpad; + new->tree.hpad = current->tree.vpad; + } + } + + if (new->tree.vpad != current->tree.vpad || + new->tree.hpad != current->tree.hpad || + new->tree.gravity != current->tree.gravity) { + layout_tree (new, TRUE); + redraw = FALSE; + } + return redraw; +} + + +/* ARGSUSED */ +static Boolean ConstraintSetValues (current, request, new, args, num_args) + Widget current, request, new; + ArgList args; + Cardinal *num_args; +{ + TreeConstraints newc = TREE_CONSTRAINT(new); + TreeConstraints curc = TREE_CONSTRAINT(current); + TreeWidget tw = (TreeWidget) new->core.parent; + + /* + * If the parent field has changed, remove the widget + * from the old widget's children list and add it to the + * new one. + */ + if (curc->tree.parent != newc->tree.parent){ + if (curc->tree.parent) + delete_node (curc->tree.parent, new); + if (newc->tree.parent) + insert_node(newc->tree.parent, new); + + /* + * If the Tree widget has been realized, + * compute new layout. + */ + if (XtIsRealized((Widget)tw)) + layout_tree (tw, FALSE); + } + return False; +} + + +static void ConstraintDestroy (w) + Widget w; +{ + TreeConstraints tc = TREE_CONSTRAINT(w); + TreeWidget tw = (TreeWidget) XtParent(w); + int i; + + /* + * Remove the widget from its parent's sub-nodes list and + * make all this widget's sub-nodes sub-nodes of the parent. + */ + + if (tw->tree.tree_root == w) { + if (tc->tree.n_children > 0) + tw->tree.tree_root = tc->tree.children[0]; + else + tw->tree.tree_root = NULL; + } + + delete_node (tc->tree.parent, (Widget) w); + for (i = 0; i< tc->tree.n_children; i++) + insert_node (tc->tree.parent, tc->tree.children[i]); + + layout_tree ((TreeWidget) (w->core.parent), FALSE); +} + +/* ARGSUSED */ +static XtGeometryResult GeometryManager (w, request, reply) + Widget w; + XtWidgetGeometry *request; + XtWidgetGeometry *reply; +{ + + TreeWidget tw = (TreeWidget) w->core.parent; + + /* + * No position changes allowed!. + */ + if ((request->request_mode & CWX && request->x!=w->core.x) + ||(request->request_mode & CWY && request->y!=w->core.y)) + return (XtGeometryNo); + + /* + * Allow all resize requests. + */ + + if (request->request_mode & CWWidth) + w->core.width = request->width; + if (request->request_mode & CWHeight) + w->core.height = request->height; + if (request->request_mode & CWBorderWidth) + w->core.border_width = request->border_width; + + if (tw->tree.auto_reconfigure) layout_tree (tw, FALSE); + return (XtGeometryYes); +} + +static void ChangeManaged (gw) + Widget gw; +{ + layout_tree ((TreeWidget) gw, FALSE); +} + + +static void Destroy (gw) + Widget gw; +{ + TreeWidget w = (TreeWidget) gw; + + XtReleaseGC (gw, w->tree.gc); + if (w->tree.largest) XtFree ((char *) w->tree.largest); +} + + +/* ARGSUSED */ +static void Redisplay (gw, event, region) + Widget gw; + XEvent *event; + Region region; +{ + TreeWidget tw = (TreeWidget) gw; + + /* + * If the Tree widget is visible, visit each managed child. + */ + if (tw->core.visible) { + int i, j; + Display *dpy = XtDisplay (tw); + Window w = XtWindow (tw); + + for (i = 0; i < tw->composite.num_children; i++) { + Widget child = tw->composite.children[i]; + TreeConstraints tc = TREE_CONSTRAINT(child); + + /* + * Don't draw lines from the fake tree_root. + */ + if (child != tw->tree.tree_root && tc->tree.n_children) { + int srcx = child->core.x + child->core.border_width; + int srcy = child->core.y + child->core.border_width; + + switch (tw->tree.gravity) { + case WestGravity: + srcx += child->core.width + child->core.border_width; + /* fall through */ + case EastGravity: + srcy += child->core.height / 2; + break; + + case NorthGravity: + srcy += child->core.height + child->core.border_width; + /* fall through */ + case SouthGravity: + srcx += child->core.width / 2; + break; + } + + for (j = 0; j < tc->tree.n_children; j++) { + Widget k = tc->tree.children[j]; + GC gc = (tc->tree.gc ? tc->tree.gc : tw->tree.gc); + + switch (tw->tree.gravity) { + case WestGravity: + /* + * right center to left center + */ + XDrawLine (dpy, w, gc, srcx, srcy, + (int) k->core.x, + (k->core.y + ((int) k->core.border_width) + + ((int) k->core.height) / 2)); + break; + + case NorthGravity: + /* + * bottom center to top center + */ + XDrawLine (dpy, w, gc, srcx, srcy, + (k->core.x + ((int) k->core.border_width) + + ((int) k->core.width) / 2), + (int) k->core.y); + break; + + case EastGravity: + /* + * left center to right center + */ + XDrawLine (dpy, w, gc, srcx, srcy, + (k->core.x + + (((int) k->core.border_width) << 1) + + (int) k->core.width), + (k->core.y + ((int) k->core.border_width) + + ((int) k->core.height) / 2)); + break; + + case SouthGravity: + /* + * top center to bottom center + */ + XDrawLine (dpy, w, gc, srcx, srcy, + (k->core.x + ((int) k->core.border_width) + + ((int) k->core.width) / 2), + (k->core.y + + (((int) k->core.border_width) << 1) + + (int) k->core.height)); + break; + } + } + } + } + } +} + +static XtGeometryResult QueryGeometry (w, intended, preferred) + Widget w; + XtWidgetGeometry *intended, *preferred; +{ + TreeWidget tw = (TreeWidget) w; + + preferred->request_mode = (CWWidth | CWHeight); + preferred->width = tw->tree.maxwidth; + preferred->height = tw->tree.maxheight; + + if (((intended->request_mode & (CWWidth | CWHeight)) == + (CWWidth | CWHeight)) && + intended->width == preferred->width && + intended->height == preferred->height) + return XtGeometryYes; + else if (preferred->width == w->core.width && + preferred->height == w->core.height) + return XtGeometryNo; + else + return XtGeometryAlmost; +} + + +/***************************************************************************** + * * + * tree layout algorithm * + * * + * Each node in the tree is "shrink-wrapped" with a minimal bounding * + * rectangle, laid next to its siblings (with a small about of padding in * + * between) and then wrapped with their parent. Parents are centered about * + * their children (or vice versa if the parent is larger than the children). * + * * + *****************************************************************************/ + +static void compute_bounding_box_subtree (tree, w, depth) + TreeWidget tree; + Widget w; + int depth; +{ + TreeConstraints tc = TREE_CONSTRAINT(w); /* info attached to all kids */ + int i; + Bool horiz = IsHorizontal (tree); + Dimension newwidth, newheight; + Dimension bw2 = w->core.border_width * 2; + + /* + * Set the max-size per level. + */ + if (depth >= tree->tree.n_largest) { + initialize_dimensions (&tree->tree.largest, + &tree->tree.n_largest, depth + 1); + } + newwidth = ((horiz ? w->core.width : w->core.height) + bw2); + if (tree->tree.largest[depth] < newwidth) + tree->tree.largest[depth] = newwidth; + + + /* + * initialize + */ + tc->tree.bbwidth = w->core.width + bw2; + tc->tree.bbheight = w->core.height + bw2; + + if (tc->tree.n_children == 0) return; + + /* + * Figure the size of the opposite dimension (vertical if tree is + * horizontal, else vice versa). The other dimension will be set + * in the second pass once we know the maximum dimensions. + */ + newwidth = 0; + newheight = 0; + for (i = 0; i < tc->tree.n_children; i++) { + Widget child = tc->tree.children[i]; + TreeConstraints cc = TREE_CONSTRAINT(child); + + compute_bounding_box_subtree (tree, child, depth + 1); + + if (horiz) { + if (newwidth < cc->tree.bbwidth) newwidth = cc->tree.bbwidth; + newheight += tree->tree.vpad + cc->tree.bbheight; + } else { + if (newheight < cc->tree.bbheight) newheight = cc->tree.bbheight; + newwidth += tree->tree.hpad + cc->tree.bbwidth; + } + } + + + tc->tree.bbsubwidth = newwidth; + tc->tree.bbsubheight = newheight; + + /* + * Now fit parent onto side (or top) of bounding box and correct for + * extra padding. Be careful of unsigned arithmetic. + */ + if (horiz) { + tc->tree.bbwidth += tree->tree.hpad + newwidth; + newheight -= tree->tree.vpad; + if (newheight > tc->tree.bbheight) tc->tree.bbheight = newheight; + } else { + tc->tree.bbheight += tree->tree.vpad + newheight; + newwidth -= tree->tree.hpad; + if (newwidth > tc->tree.bbwidth) tc->tree.bbwidth = newwidth; + } +} + + +static void set_positions (tw, w, level) + TreeWidget tw; + Widget w; + int level; +{ + int i; + + if (w) { + TreeConstraints tc = TREE_CONSTRAINT(w); + + if (level > 0) { + /* + * mirror if necessary + */ + switch (tw->tree.gravity) { + case EastGravity: + tc->tree.x = (((Position) tw->tree.maxwidth) - + ((Position) w->core.width) - tc->tree.x); + break; + + case SouthGravity: + tc->tree.y = (((Position) tw->tree.maxheight) - + ((Position) w->core.height) - tc->tree.y); + break; + } + + /* + * Move the widget into position. + */ + XtMoveWidget (w, tc->tree.x, tc->tree.y); + } + + /* + * Set the positions of all children. + */ + for (i = 0; i < tc->tree.n_children; i++) + set_positions (tw, tc->tree.children[i], level + 1); + } +} + + +static void arrange_subtree (tree, w, depth, x, y) + TreeWidget tree; + Widget w; + int depth; + Position x, y; +{ + TreeConstraints tc = TREE_CONSTRAINT(w); /* info attached to all kids */ + TreeConstraints firstcc, lastcc; + int i; + int newx, newy; + Bool horiz = IsHorizontal (tree); + Widget child = NULL; + Dimension tmp; + Dimension bw2 = w->core.border_width * 2; + Bool relayout = True; + + + /* + * If no children, then just lay out where requested. + */ + tc->tree.x = x; + tc->tree.y = y; + + if (horiz) { + int myh = (w->core.height + bw2); + + if (myh > (int)tc->tree.bbsubheight) { + y += (myh - (int)tc->tree.bbsubheight) / 2; + relayout = False; + } + } else { + int myw = (w->core.width + bw2); + + if (myw > (int)tc->tree.bbsubwidth) { + x += (myw - (int)tc->tree.bbsubwidth) / 2; + relayout = False; + } + } + + if ((tmp = ((Dimension) x) + tc->tree.bbwidth) > tree->tree.maxwidth) + tree->tree.maxwidth = tmp; + if ((tmp = ((Dimension) y) + tc->tree.bbheight) > tree->tree.maxheight) + tree->tree.maxheight = tmp; + + if (tc->tree.n_children == 0) return; + + + /* + * Have children, so walk down tree laying out children, then laying + * out parents. + */ + if (horiz) { + newx = x + tree->tree.largest[depth]; + if (depth > 0) newx += tree->tree.hpad; + newy = y; + } else { + newx = x; + newy = y + tree->tree.largest[depth]; + if (depth > 0) newy += tree->tree.vpad; + } + + for (i = 0; i < tc->tree.n_children; i++) { + TreeConstraints cc; + + child = tc->tree.children[i]; /* last value is used outside loop */ + cc = TREE_CONSTRAINT(child); + + arrange_subtree (tree, child, depth + 1, newx, newy); + if (horiz) { + newy += tree->tree.vpad + cc->tree.bbheight; + } else { + newx += tree->tree.hpad + cc->tree.bbwidth; + } + } + + /* + * now layout parent between first and last children + */ + if (relayout) { + Position adjusted; + firstcc = TREE_CONSTRAINT (tc->tree.children[0]); + lastcc = TREE_CONSTRAINT (child); + + /* Adjustments are disallowed if they result in a position above + * or to the left of the originally requested position, because + * this could collide with the position of the previous sibling. + */ + if (horiz) { + tc->tree.x = x; + adjusted = firstcc->tree.y + + ((lastcc->tree.y + (Position) child->core.height + + (Position) child->core.border_width * 2 - + firstcc->tree.y - (Position) w->core.height - + (Position) w->core.border_width * 2 + 1) / 2); + if (adjusted > tc->tree.y) tc->tree.y = adjusted; + } else { + adjusted = firstcc->tree.x + + ((lastcc->tree.x + (Position) child->core.width + + (Position) child->core.border_width * 2 - + firstcc->tree.x - (Position) w->core.width - + (Position) w->core.border_width * 2 + 1) / 2); + if (adjusted > tc->tree.x) tc->tree.x = adjusted; + tc->tree.y = y; + } + } +} + +static void set_tree_size (tw, insetvalues, width, height) + TreeWidget tw; + Boolean insetvalues; + Dimension width, height; +{ + if (insetvalues) { + tw->core.width = width; + tw->core.height = height; + } else { + Dimension replyWidth = 0, replyHeight = 0; + XtGeometryResult result = XtMakeResizeRequest ((Widget) tw, + width, height, + &replyWidth, + &replyHeight); + /* + * Accept any compromise. + */ + if (result == XtGeometryAlmost) + XtMakeResizeRequest ((Widget) tw, replyWidth, replyHeight, + (Dimension *) NULL, (Dimension *) NULL); + } + return; +} + +static void layout_tree (tw, insetvalues) + TreeWidget tw; + Boolean insetvalues; +{ + int i; + Dimension *dp; + + /* + * Do a depth-first search computing the width and height of the bounding + * box for the tree at that position (and below). Then, walk again using + * this information to layout the children at each level. + */ + + if (tw->tree.tree_root == NULL) + return; + + tw->tree.maxwidth = tw->tree.maxheight = 0; + for (i = 0, dp = tw->tree.largest; i < tw->tree.n_largest; i++, dp++) + *dp = 0; + initialize_dimensions (&tw->tree.largest, &tw->tree.n_largest, + tw->tree.n_largest); + compute_bounding_box_subtree (tw, tw->tree.tree_root, 0); + + /* + * Second pass to do final layout. Each child's bounding box is stacked + * on top of (if horizontal, else next to) on top of its siblings. The + * parent is centered between the first and last children. + */ + arrange_subtree (tw, tw->tree.tree_root, 0, 0, 0); + + /* + * Move each widget into place. + */ + set_tree_size (tw, insetvalues, tw->tree.maxwidth, tw->tree.maxheight); + set_positions (tw, tw->tree.tree_root, 0); + + /* + * And redisplay. + */ + if (XtIsRealized ((Widget) tw)) { + XClearArea (XtDisplay(tw), XtWindow((Widget)tw), 0, 0, 0, 0, True); + } +} + + + +/***************************************************************************** + * * + * Public Routines * + * * + *****************************************************************************/ + +void +#if NeedFunctionPrototypes +XawTreeForceLayout (Widget tree) +#else +XawTreeForceLayout (tree) + Widget tree; +#endif +{ + layout_tree ((TreeWidget) tree, FALSE); +} + diff --git a/src/Tree.h b/src/Tree.h new file mode 100644 index 0000000..fde1117 --- /dev/null +++ b/src/Tree.h @@ -0,0 +1,125 @@ +/* + * $XConsortium: Tree.h,v 1.13 94/04/17 20:13:22 kaleb Exp $ + * + +Copyright (c) 1990, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + * Copyright 1989 Prentice Hall + * + * Permission to use, copy, modify, and distribute this software for any + * purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation. + * + * Prentice Hall and the authors disclaim all warranties with regard + * to this software, including all implied warranties of merchantability and + * fitness. In no event shall Prentice Hall or the authors be liable + * for any special, indirect or cosequential damages or any damages whatsoever + * resulting from loss of use, data or profits, whether in an action of + * contract, negligence or other tortious action, arising out of or in + * connection with the use or performance of this software. + * + * Authors: Jim Fulton, MIT X Consortium, + * based on a version by Douglas Young, Prentice Hall + * + * This widget is based on the Tree widget described on pages 397-419 of + * Douglas Young's book "The X Window System, Programming and Applications + * with Xt OSF/Motif Edition." The layout code has been rewritten to use + * additional blank space to make the structure of the graph easier to see + * as well as to support vertical trees. + */ + + +#ifndef _XawTree_h +#define _XawTree_h + +#include <X11/Xmu/Converters.h> + +/****************************************************************************** + * + * Tree Widget (subclass of ConstraintClass) + * + ****************************************************************************** + * + * Parameters: + * + * Name Class Type Default + * ---- ----- ---- ------- + * + * autoReconfigure AutoReconfigure Boolean FALSE + * background Background Pixel XtDefaultBackground + * foreground Foreground Pixel XtDefaultForeground + * gravity Gravity XtGravity West + * hSpace HSpace Dimension 20 + * lineWidth LineWidth Dimension 0 + * vSpace VSpace Dimension 6 + * + * + * Constraint Resources attached to children: + * + * treeGC TreeGC GC NULL + * treeParent TreeParent Widget NULL + * + * + *****************************************************************************/ + + /* new instance field names */ +#ifndef _XtStringDefs_h_ +#define XtNhSpace "hSpace" +#define XtNvSpace "vSpace" +#define XtCHSpace "HSpace" +#define XtCVSpace "VSpace" +#endif + +#define XtNautoReconfigure "autoReconfigure" +#define XtNlineWidth "lineWidth" +#define XtNtreeGC "treeGC" +#define XtNtreeParent "treeParent" +#define XtNgravity "gravity" + + /* new class field names */ +#define XtCAutoReconfigure "AutoReconfigure" +#define XtCLineWidth "LineWidth" +#define XtCTreeGC "TreeGC" +#define XtCTreeParent "TreeParent" +#define XtCGravity "Gravity" + +#define XtRGC "GC" + /* external declarations */ +extern WidgetClass treeWidgetClass; + +typedef struct _TreeClassRec *TreeWidgetClass; +typedef struct _TreeRec *TreeWidget; + +_XFUNCPROTOBEGIN + +extern void XawTreeForceLayout ( +#if NeedFunctionPrototypes + Widget /* tree */ +#endif +); + +_XFUNCPROTOEND + +#endif /* _XawTree_h */ diff --git a/src/TreeP.h b/src/TreeP.h new file mode 100644 index 0000000..9905138 --- /dev/null +++ b/src/TreeP.h @@ -0,0 +1,132 @@ +/* + * $XConsortium: TreeP.h,v 1.14 94/04/17 20:13:24 jim Exp $ + * + +Copyright (c) 1990 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + * Copyright 1989 Prentice Hall + * + * Permission to use, copy, modify, and distribute this software for any + * purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation. + * + * Prentice Hall and the authors disclaim all warranties with regard + * to this software, including all implied warranties of merchantability and + * fitness. In no event shall Prentice Hall or the authors be liable + * for any special, indirect or cosequential damages or any damages whatsoever + * resulting from loss of use, data or profits, whether in an action of + * contract, negligence or other tortious action, arising out of or in + * connection with the use or performance of this software. + * + * Authors: Jim Fulton, MIT X Consortium, + * based on a version by Douglas Young, Prentice Hall + * + * This widget is based on the Tree widget described on pages 397-419 of + * Douglas Young's book "The X Window System, Programming and Applications + * with Xt OSF/Motif Edition." The layout code has been rewritten to use + * additional blank space to make the structure of the graph easier to see + * as well as to support vertical trees. + */ + + +#ifndef _XawTreeP_h +#define _XawTreeP_h + +#include <X11/Xaw3d/Tree.h> + +typedef struct _TreeClassPart { + int ignore; +} TreeClassPart; + +typedef struct _TreeClassRec { + CoreClassPart core_class; + CompositeClassPart composite_class; + ConstraintClassPart constraint_class; + TreeClassPart tree_class; +} TreeClassRec; + +extern TreeClassRec treeClassRec; + +typedef struct { + /* fields available through resources */ + Dimension hpad; /* hSpace/HSpace */ + Dimension vpad; /* vSpace/VSpace */ + Dimension line_width; /* lineWidth/LineWidth */ + Pixel foreground; /* foreground/Foreground */ + XtGravity gravity; /* gravity/Gravity */ + Boolean auto_reconfigure; /* autoReconfigure/AutoReconfigure */ + /* private fields */ + GC gc; /* used to draw lines */ + Widget tree_root; /* hidden root off all children */ + Dimension *largest; /* list of largest per depth */ + int n_largest; /* number of elements in largest */ + Dimension maxwidth, maxheight; /* for shrink wrapping */ +} TreePart; + + +typedef struct _TreeRec { + CorePart core; + CompositePart composite; + ConstraintPart constraint; + TreePart tree; +} TreeRec; + + +/* + * structure attached to all children + */ +typedef struct _TreeConstraintsPart { + /* resources */ + Widget parent; /* treeParent/TreeParent */ + GC gc; /* treeGC/TreeGC */ + /* private data */ + Widget *children; + int n_children; + int max_children; + Dimension bbsubwidth, bbsubheight; /* bounding box of sub tree */ + Dimension bbwidth, bbheight; /* bounding box including node */ + Position x, y; +} TreeConstraintsPart; + +typedef struct _TreeConstraintsRec { + TreeConstraintsPart tree; +} TreeConstraintsRec, *TreeConstraints; + + +/* + * useful macros + */ + +#define TREE_CONSTRAINT(w) \ + ((TreeConstraints)((w)->core.constraints)) + +#define TREE_INITIAL_DEPTH 10 /* for allocating largest array */ +#define TREE_HORIZONTAL_DEFAULT_SPACING 20 +#define TREE_VERTICAL_DEFAULT_SPACING 6 + +#endif /* _XawTreeP_h */ + + + diff --git a/src/Vendor.c b/src/Vendor.c new file mode 100644 index 0000000..4fa43db --- /dev/null +++ b/src/Vendor.c @@ -0,0 +1,604 @@ +/* $XConsortium: Vendor.c,v 1.27 94/04/17 20:13:25 kaleb Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* + * Portions Copyright (c) 1996 Alfredo Kojima + * Rights, permissions, and disclaimer per the above X Consortium license. + */ + +/* + * This is a copy of Xt/Vendor.c with an additional ClassInitialize + * procedure to register Xmu resource type converters, and all the + * monkey business associated with input methods... + * + */ + +/* Make sure all wm properties can make it out of the resource manager */ + +#include "Xaw3dP.h" +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/ShellP.h> +#include <X11/VendorP.h> +#include <X11/Xmu/Converters.h> +#include <X11/Xmu/Atoms.h> +#include <X11/Xmu/Editres.h> +#ifdef XAW_INTERNATIONALIZATION +#include <X11/Xmu/ExtAgent.h> +#endif +#ifdef XAW_MULTIPLANE_PIXMAPS +#include <X11/xpm.h> +#include <X11/Xmu/Drawing.h> +#endif + +/* The following two headers are for the input method. */ +#ifdef XAW_INTERNATIONALIZATION +#include <X11/Xaw3d/VendorEP.h> +#include <X11/Xaw3d/XawImP.h> +#endif + + +static XtResource resources[] = { + {XtNinput, XtCInput, XtRBool, sizeof(Bool), + XtOffsetOf(VendorShellRec, wm.wm_hints.input), + XtRImmediate, (XtPointer)True} +}; + +/*************************************************************************** + * + * Vendor shell class record + * + ***************************************************************************/ + +static void XawVendorShellClassInitialize(); +static void XawVendorShellInitialize(); +static Boolean XawVendorShellSetValues(); +static void Realize(), ChangeManaged(); +static XtGeometryResult GeometryManager(); +#ifdef XAW_INTERNATIONALIZATION +static void XawVendorShellClassPartInit(); +void XawVendorShellExtResize(); +#endif + +#ifdef XAW_INTERNATIONALIZATION +static CompositeClassExtensionRec vendorCompositeExt = { + /* next_extension */ NULL, + /* record_type */ NULLQUARK, + /* version */ XtCompositeExtensionVersion, + /* record_size */ sizeof (CompositeClassExtensionRec), + /* accepts_objects */ TRUE, + /* allows_change_managed_set */ FALSE +}; +#endif + +#define SuperClass (&wmShellClassRec) +externaldef(vendorshellclassrec) VendorShellClassRec vendorShellClassRec = { + { + /* superclass */ (WidgetClass)SuperClass, + /* class_name */ "VendorShell", + /* size */ sizeof(VendorShellRec), + /* class_initialize */ XawVendorShellClassInitialize, +#ifdef XAW_INTERNATIONALIZATION + /* class_part_init */ XawVendorShellClassPartInit, +#else + /* class_part_init */ NULL, +#endif + /* Class init'ed ? */ FALSE, + /* initialize */ XawVendorShellInitialize, + /* initialize_hook */ NULL, + /* realize */ Realize, + /* actions */ NULL, + /* num_actions */ 0, + /* resources */ resources, + /* resource_count */ XtNumber(resources), + /* xrm_class */ NULLQUARK, + /* compress_motion */ FALSE, + /* compress_exposure */ TRUE, + /* compress_enterleave*/ FALSE, + /* visible_interest */ FALSE, + /* destroy */ NULL, +#ifdef XAW_INTERNATIONALIZATION + /* resize */ XawVendorShellExtResize, +#else + /* resize */ XtInheritResize, +#endif + /* expose */ NULL, + /* set_values */ XawVendorShellSetValues, + /* set_values_hook */ NULL, + /* set_values_almost */ XtInheritSetValuesAlmost, + /* get_values_hook */ NULL, + /* accept_focus */ NULL, + /* intrinsics version */ XtVersion, + /* callback offsets */ NULL, + /* tm_table */ NULL, + /* query_geometry */ NULL, + /* display_accelerator*/ NULL, + /* extension */ NULL + },{ + /* geometry_manager */ GeometryManager, + /* change_managed */ ChangeManaged, + /* insert_child */ XtInheritInsertChild, + /* delete_child */ XtInheritDeleteChild, +#ifdef XAW_INTERNATIONALIZATION + /* extension */ (XtPointer) &vendorCompositeExt +#else + /* extension */ NULL +#endif + },{ + /* extension */ NULL + },{ + /* extension */ NULL + },{ + /* extension */ NULL + } +}; + +externaldef(vendorshellwidgetclass) WidgetClass vendorShellWidgetClass = + (WidgetClass) (&vendorShellClassRec); + + +#ifdef XAW_INTERNATIONALIZATION +/*************************************************************************** + * + * The following section is for the Vendor shell Extension class record + * + ***************************************************************************/ + +static XtResource ext_resources[] = { + {XtNinputMethod, XtCInputMethod, XtRString, sizeof(String), + XtOffsetOf(XawVendorShellExtRec, vendor_ext.im.input_method), + XtRString, (XtPointer)NULL}, + {XtNpreeditType, XtCPreeditType, XtRString, sizeof(String), + XtOffsetOf(XawVendorShellExtRec, vendor_ext.im.preedit_type), + XtRString, (XtPointer)"OverTheSpot,OffTheSpot,Root"}, + {XtNopenIm, XtCOpenIm, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XawVendorShellExtRec, vendor_ext.im.open_im), + XtRImmediate, (XtPointer)TRUE}, + {XtNsharedIc, XtCSharedIc, XtRBoolean, sizeof(Boolean), + XtOffsetOf(XawVendorShellExtRec, vendor_ext.ic.shared_ic), + XtRImmediate, (XtPointer)FALSE} +}; + +static void XawVendorShellExtClassInitialize(); +static void XawVendorShellExtInitialize(); +static void XawVendorShellExtDestroy(); +static Boolean XawVendorShellExtSetValues(); + +externaldef(vendorshellextclassrec) XawVendorShellExtClassRec + xawvendorShellExtClassRec = { + { + /* superclass */ (WidgetClass)&objectClassRec, + /* class_name */ "VendorShellExt", + /* size */ sizeof(XawVendorShellExtRec), + /* class_initialize */ XawVendorShellExtClassInitialize, + /* class_part_initialize*/ NULL, + /* Class init'ed ? */ FALSE, + /* initialize */ XawVendorShellExtInitialize, + /* initialize_hook */ NULL, + /* pad */ NULL, + /* pad */ NULL, + /* pad */ 0, + /* resources */ ext_resources, + /* resource_count */ XtNumber(ext_resources), + /* xrm_class */ NULLQUARK, + /* pad */ FALSE, + /* pad */ FALSE, + /* pad */ FALSE, + /* pad */ FALSE, + /* destroy */ XawVendorShellExtDestroy, + /* pad */ NULL, + /* pad */ NULL, + /* set_values */ XawVendorShellExtSetValues, + /* set_values_hook */ NULL, + /* pad */ NULL, + /* get_values_hook */ NULL, + /* pad */ NULL, + /* version */ XtVersion, + /* callback_offsets */ NULL, + /* pad */ NULL, + /* pad */ NULL, + /* pad */ NULL, + /* extension */ NULL + },{ + /* extension */ NULL + } +}; + +externaldef(xawvendorshellwidgetclass) WidgetClass + xawvendorShellExtWidgetClass = (WidgetClass) (&xawvendorShellExtClassRec); +#endif + + +/*ARGSUSED*/ +static Boolean +XawCvtCompoundTextToString(dpy, args, num_args, fromVal, toVal, cvt_data) +Display *dpy; +XrmValuePtr args; +Cardinal *num_args; +XrmValue *fromVal; +XrmValue *toVal; +XtPointer *cvt_data; +{ + XTextProperty prop; + char **list; + int count; + static char *mbs = NULL; + int len; + + prop.value = (unsigned char *)fromVal->addr; + prop.encoding = XA_COMPOUND_TEXT(dpy); + prop.format = 8; + prop.nitems = fromVal->size; + + if(XmbTextPropertyToTextList(dpy, &prop, &list, &count) < Success) { + XtAppWarningMsg(XtDisplayToApplicationContext(dpy), + "converter", "XmbTextPropertyToTextList", "XawError", + "conversion from CT to MB failed.", NULL, 0); + return False; + } + len = strlen(*list); + toVal->size = len; + mbs = XtRealloc(mbs, len + 1); /* keep buffer because no one call free :( */ + strcpy(mbs, *list); + XFreeStringList(list); + toVal->addr = (XtPointer)mbs; + return True; +} + +#ifdef XAW_MULTIPLANE_PIXMAPS +#define DONE(type, address) \ + {to->size = sizeof(type); to->addr = (XPointer)address;} + +/* ARGSUSED */ +static Boolean +_XawCvtStringToPixmap(dpy, args, nargs, from, to, data) +Display *dpy; +XrmValuePtr args; +Cardinal *nargs; +XrmValuePtr from, to; +XtPointer *data; +{ + static Pixmap pixmap; + Window win; + XpmAttributes attr; + XpmColorSymbol colors[1]; + + if (*nargs != 3) + XtAppErrorMsg(XtDisplayToApplicationContext(dpy), + "_XawCvtStringToPixmap", "wrongParameters", "XtToolkitError", + "_XawCvtStringToPixmap needs screen, colormap, and background_pixel", + (String *) NULL, (Cardinal *) NULL); + + if (strcmp(from->addr, "None") == 0) + { + pixmap = None; + DONE(Pixmap, &pixmap); + return (True); + } + if (strcmp(from->addr, "ParentRelative") == 0) + { + pixmap = ParentRelative; + DONE(Pixmap, &pixmap); + return (True); + } + + win = RootWindowOfScreen(*((Screen **) args[0].addr)); + + attr.colormap = *((Colormap *) args[1].addr); + attr.closeness = 32768; /* might help on 8-bpp displays? */ + attr.valuemask = XpmColormap | XpmCloseness; + + colors[0].name = NULL; + colors[0].value = "none"; + colors[0].pixel = *((Pixel *) args[2].addr); + attr.colorsymbols = colors; + attr.numsymbols = 1; + attr.valuemask |= XpmColorSymbols; + + if (XpmReadFileToPixmap(dpy, win, (String) from->addr, + &pixmap, NULL, &attr) != XpmSuccess) + { + if ((pixmap = XmuLocateBitmapFile(*((Screen **) args[0].addr), + (char *)from->addr, NULL, 0, NULL, NULL, NULL, NULL)) == None) + { + XtDisplayStringConversionWarning(dpy, (String) from->addr, + XtRPixmap); + return (False); + } + } + + if (to->addr == NULL) + to->addr = (XtPointer) & pixmap; + else + { + if (to->size < sizeof(Pixmap)) + { + to->size = sizeof(Pixmap); + XtDisplayStringConversionWarning(dpy, (String) from->addr, + XtRPixmap); + return (False); + } + + *((Pixmap *) to->addr) = pixmap; + } + to->size = sizeof(Pixmap); + return (True); +} +#endif + +static void XawVendorShellClassInitialize() +{ + static XtConvertArgRec screenConvertArg[] = { + {XtWidgetBaseOffset, (XtPointer) XtOffsetOf(WidgetRec, core.screen), + sizeof(Screen *)} + }; +#ifdef XAW_MULTIPLANE_PIXMAPS + static XtConvertArgRec _XawCvtStrToPix[] = { + {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.screen), + sizeof(Screen *)}, + {XtWidgetBaseOffset, (XtPointer)XtOffsetOf(WidgetRec, core.colormap), + sizeof(Colormap)}, + {XtWidgetBaseOffset, + (XtPointer)XtOffsetOf(WidgetRec, core.background_pixel), + sizeof(Pixel)} + }; +#endif + + XtAddConverter(XtRString, XtRCursor, XmuCvtStringToCursor, + screenConvertArg, XtNumber(screenConvertArg)); + +#ifdef XAW_MULTIPLANE_PIXMAPS + XtSetTypeConverter(XtRString, XtRBitmap, + (XtTypeConverter)_XawCvtStringToPixmap, + _XawCvtStrToPix, XtNumber(_XawCvtStrToPix), + XtCacheByDisplay, (XtDestructor)NULL); +#else + XtAddConverter(XtRString, XtRBitmap, XmuCvtStringToBitmap, + screenConvertArg, XtNumber(screenConvertArg)); +#endif + + XtSetTypeConverter("CompoundText", XtRString, XawCvtCompoundTextToString, + NULL, 0, XtCacheNone, NULL); +} + +#ifdef XAW_INTERNATIONALIZATION +static void XawVendorShellClassPartInit(class) + WidgetClass class; +{ + CompositeClassExtension ext; + VendorShellWidgetClass vsclass = (VendorShellWidgetClass) class; + + if ((ext = (CompositeClassExtension) + XtGetClassExtension (class, + XtOffsetOf(CompositeClassRec, + composite_class.extension), + NULLQUARK, 1L, (Cardinal) 0)) == NULL) { + ext = (CompositeClassExtension) XtNew (CompositeClassExtensionRec); + if (ext != NULL) { + ext->next_extension = vsclass->composite_class.extension; + ext->record_type = NULLQUARK; + ext->version = XtCompositeExtensionVersion; + ext->record_size = sizeof (CompositeClassExtensionRec); + ext->accepts_objects = TRUE; + ext->allows_change_managed_set = FALSE; + vsclass->composite_class.extension = (XtPointer) ext; + } + } +} +#endif + +#ifdef __osf__ +/* stupid OSF/1 shared libraries have the wrong semantics */ +/* symbols do not get resolved external to the shared library */ +void _XawFixupVendorShell() +{ + transientShellWidgetClass->core_class.superclass = + (WidgetClass) &vendorShellClassRec; + topLevelShellWidgetClass->core_class.superclass = + (WidgetClass) &vendorShellClassRec; +} +#endif + +/* ARGSUSED */ +static void XawVendorShellInitialize(req, new, args, num_args) + Widget req, new; + ArgList args; + Cardinal *num_args; +{ + XtAddEventHandler(new, (EventMask) 0, TRUE, _XEditResCheckMessages, NULL); +#ifdef XAW_INTERNATIONALIZATION + XtAddEventHandler(new, (EventMask) 0, TRUE, XmuRegisterExternalAgent, NULL); + XtCreateWidget("shellext", xawvendorShellExtWidgetClass, + new, args, *num_args); +#endif +} + +/* ARGSUSED */ +static Boolean XawVendorShellSetValues(old, ref, new) + Widget old, ref, new; +{ + return FALSE; +} + +static void Realize(wid, vmask, attr) + Widget wid; + Mask *vmask; + XSetWindowAttributes *attr; +{ + WidgetClass super = wmShellWidgetClass; + + /* Make my superclass do all the dirty work */ + + (*super->core_class.realize) (wid, vmask, attr); +#ifdef XAW_INTERNATIONALIZATION + _XawImRealize(wid); +#endif +} + + +#ifdef XAW_INTERNATIONALIZATION +static void XawVendorShellExtClassInitialize() +{ +} + +/* ARGSUSED */ +static void XawVendorShellExtInitialize(req, new) + Widget req, new; +{ + _XawImInitialize(new->core.parent, new); +} + +/* ARGSUSED */ +static void XawVendorShellExtDestroy( w ) + Widget w; +{ + _XawImDestroy( w->core.parent, w ); +} + +/* ARGSUSED */ +static Boolean XawVendorShellExtSetValues(old, ref, new) + Widget old, ref, new; +{ + return FALSE; +} + +void XawVendorShellExtResize( w ) + Widget w; +{ + ShellWidget sw = (ShellWidget) w; + Widget childwid; + int i; + int core_height; + + _XawImResizeVendorShell( w ); + core_height = _XawImGetShellHeight( w ); + for( i = 0; i < sw->composite.num_children; i++ ) { + if( XtIsManaged( sw->composite.children[ i ] ) ) { + childwid = sw->composite.children[ i ]; + XtResizeWidget( childwid, sw->core.width, core_height, + childwid->core.border_width ); + } + } +} +#endif + +/*ARGSUSED*/ +static XtGeometryResult GeometryManager( wid, request, reply ) + Widget wid; + XtWidgetGeometry *request; + XtWidgetGeometry *reply; +{ + ShellWidget shell = (ShellWidget)(wid->core.parent); + XtWidgetGeometry my_request; + + if(shell->shell.allow_shell_resize == FALSE && XtIsRealized(wid)) + return(XtGeometryNo); + + if (request->request_mode & (CWX | CWY)) + return(XtGeometryNo); + + /* %%% worry about XtCWQueryOnly */ + my_request.request_mode = 0; + if (request->request_mode & CWWidth) { + my_request.width = request->width; + my_request.request_mode |= CWWidth; + } + if (request->request_mode & CWHeight) { + my_request.height = request->height +#ifdef XAW_INTERNATIONALIZATION + + _XawImGetImAreaHeight( wid ) +#endif + ; + my_request.request_mode |= CWHeight; + } + if (request->request_mode & CWBorderWidth) { + my_request.border_width = request->border_width; + my_request.request_mode |= CWBorderWidth; + } + if (XtMakeGeometryRequest((Widget)shell, &my_request, NULL) + == XtGeometryYes) { + /* assert: if (request->request_mode & CWWidth) then + * shell->core.width == request->width + * assert: if (request->request_mode & CWHeight) then + * shell->core.height == request->height + * + * so, whatever the WM sized us to (if the Shell requested + * only one of the two) is now the correct child size + */ + + wid->core.width = shell->core.width; + wid->core.height = shell->core.height; + if (request->request_mode & CWBorderWidth) { + wid->core.x = wid->core.y = -request->border_width; + } +#ifdef XAW_INTERNATIONALIZATION + _XawImCallVendorShellExtResize(wid); +#endif + return XtGeometryYes; + } else return XtGeometryNo; +} + +static void ChangeManaged(wid) + Widget wid; +{ + ShellWidget w = (ShellWidget) wid; + Widget* childP; + int i; + + (*SuperClass->composite_class.change_managed)(wid); + for (i = w->composite.num_children, childP = w->composite.children; + i; i--, childP++) { + if (XtIsManaged(*childP)) { + XtSetKeyboardFocus(wid, *childP); + break; + } + } +} diff --git a/src/VendorEP.h b/src/VendorEP.h new file mode 100644 index 0000000..9da02d9 --- /dev/null +++ b/src/VendorEP.h @@ -0,0 +1,81 @@ +/* $XConsortium: VendorEP.h,v 1.2 94/04/17 20:13:25 kaleb Exp $ */ + +/* + * Copyright 1991 by OMRON Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 OMRON not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. OMRON makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + * OMRON 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: Seiji Kuwari OMRON Corporation + * kuwa@omron.co.jp + * kuwa%omron.co.jp@uunet.uu.net + */ + +/* + +Copyright (c) 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +#ifndef _VendorEP_h +#define _VendorEP_h + +#include <X11/Xaw3d/XawImP.h> + +typedef struct { + XtPointer extension; +} XawVendorShellExtClassPart; + +typedef struct _VendorShellExtClassRec { + ObjectClassPart object_class; + XawVendorShellExtClassPart vendor_shell_ext_class; +} XawVendorShellExtClassRec; + +typedef struct { + Widget parent; + XawImPart im; + XawIcPart ic; +} XawVendorShellExtPart; + +typedef struct XawVendorShellExtRec { + ObjectPart object; + XawVendorShellExtPart vendor_ext; +} XawVendorShellExtRec, *XawVendorShellExtWidget; + +#endif /* _VendorEP_h */ diff --git a/src/Viewport.c b/src/Viewport.c new file mode 100644 index 0000000..b257cd3 --- /dev/null +++ b/src/Viewport.c @@ -0,0 +1,1200 @@ +/* $XConsortium: Viewport.c,v 1.71 94/04/17 20:13:26 kaleb Exp $ */ + +/*********************************************************** + +Copyright (c) 1987, 1988, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> + +#include <X11/Xaw3d/XawInit.h> +#include <X11/Xmu/Misc.h> +#include <X11/Xaw3d/Scrollbar.h> +#include <X11/Xaw3d/ViewportP.h> + +static void ScrollUpDownProc(), ThumbProc(); +static Boolean GetGeometry(); + +static void ComputeWithForceBars(); + +#define offset(field) XtOffsetOf(ViewportRec, viewport.field) +static XtResource resources[] = { + {XtNforceBars, XtCBoolean, XtRBoolean, sizeof(Boolean), + offset(forcebars), XtRImmediate, (XtPointer)False}, + {XtNallowHoriz, XtCBoolean, XtRBoolean, sizeof(Boolean), + offset(allowhoriz), XtRImmediate, (XtPointer)False}, + {XtNallowVert, XtCBoolean, XtRBoolean, sizeof(Boolean), + offset(allowvert), XtRImmediate, (XtPointer)False}, + {XtNuseBottom, XtCBoolean, XtRBoolean, sizeof(Boolean), + offset(usebottom), XtRImmediate, (XtPointer)False}, + {XtNuseRight, XtCBoolean, XtRBoolean, sizeof(Boolean), + offset(useright), XtRImmediate, (XtPointer)False}, + {XtNreportCallback, XtCReportCallback, XtRCallback, sizeof(XtPointer), + offset(report_callbacks), XtRImmediate, (XtPointer) NULL}, +}; +#undef offset + +static void Initialize(), ConstraintInitialize(), + Realize(), Resize(), ChangeManaged(); +static Boolean SetValues(), Layout(); +static XtGeometryResult GeometryManager(), PreferredGeometry(); + +#define superclass (&formClassRec) +ViewportClassRec viewportClassRec = { + { /* core_class fields */ + /* superclass */ (WidgetClass) superclass, + /* class_name */ "Viewport", + /* widget_size */ sizeof(ViewportRec), + /* class_initialize */ XawInitializeWidgetSet, + /* class_part_init */ 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 */ NULL, + /* resize */ Resize, + /* expose */ XtInheritExpose, + /* 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 */ PreferredGeometry, + /* display_accelerator*/ XtInheritDisplayAccelerator, + /* extension */ NULL + }, + { /* composite_class fields */ + /* geometry_manager */ GeometryManager, + /* change_managed */ ChangeManaged, + /* insert_child */ XtInheritInsertChild, + /* delete_child */ XtInheritDeleteChild, + /* extension */ NULL + }, + { /* constraint_class fields */ + /* subresourses */ NULL, + /* subresource_count */ 0, + /* constraint_size */ sizeof(ViewportConstraintsRec), + /* initialize */ ConstraintInitialize, + /* destroy */ NULL, + /* set_values */ NULL, + /* extension */ NULL + }, + { /* form_class fields */ + /* layout */ Layout + }, + { /* viewport_class fields */ + /* empty */ 0 + } +}; + + +WidgetClass viewportWidgetClass = (WidgetClass)&viewportClassRec; + +static Widget CreateScrollbar(w, horizontal) + ViewportWidget w; + Boolean horizontal; +{ + Widget clip = w->viewport.clip; + ViewportConstraints constraints = + (ViewportConstraints)clip->core.constraints; + static Arg barArgs[] = { + {XtNorientation, (XtArgVal) 0}, + {XtNlength, (XtArgVal) 0}, + {XtNleft, (XtArgVal) 0}, + {XtNright, (XtArgVal) 0}, + {XtNtop, (XtArgVal) 0}, + {XtNbottom, (XtArgVal) 0}, + {XtNmappedWhenManaged, (XtArgVal) False}, + }; + Widget bar; + + XtSetArg(barArgs[0], XtNorientation, + horizontal ? XtorientHorizontal : XtorientVertical ); + XtSetArg(barArgs[1], XtNlength, + horizontal ? clip->core.width : clip->core.height); + XtSetArg(barArgs[2], XtNleft, + (!horizontal && w->viewport.useright) ? XtChainRight : XtChainLeft); + XtSetArg(barArgs[3], XtNright, + (!horizontal && !w->viewport.useright) ? XtChainLeft : XtChainRight); + XtSetArg(barArgs[4], XtNtop, + (horizontal && w->viewport.usebottom) ? XtChainBottom : XtChainTop); + XtSetArg(barArgs[5], XtNbottom, + (horizontal && !w->viewport.usebottom) ? XtChainTop : XtChainBottom); + + bar = XtCreateWidget((horizontal ? "horizontal" : "vertical"), + scrollbarWidgetClass, (Widget)w, + barArgs, XtNumber(barArgs) ); + XtAddCallback( bar, XtNscrollProc, ScrollUpDownProc, (XtPointer)w ); + XtAddCallback( bar, XtNjumpProc, ThumbProc, (XtPointer)w ); + + if (horizontal) { + w->viewport.horiz_bar = bar; + constraints->form.vert_base = bar; + } + else { + w->viewport.vert_bar = bar; + constraints->form.horiz_base = bar; + } + + XtManageChild( bar ); + + return bar; +} + +/* ARGSUSED */ +static void Initialize(request, new, args, num_args) + Widget request, new; + ArgList args; + Cardinal *num_args; +{ + ViewportWidget w = (ViewportWidget)new; + static Arg clip_args[8]; + static Arg threeD_args[8]; + Cardinal arg_cnt; + Widget h_bar, v_bar; + Dimension clip_height, clip_width; + Dimension pad = 0, sw = 0; + + w->form.default_spacing = 0; /* Reset the default spacing to 0 pixels. */ + + +/* + * Initialize all widget pointers to NULL. + */ + + w->viewport.child = (Widget) NULL; + w->viewport.horiz_bar = w->viewport.vert_bar = (Widget)NULL; + +/* + * Create 3D Widget. + */ + + arg_cnt = 0; + XtSetArg(threeD_args[arg_cnt], XtNleft, XtChainLeft); arg_cnt++; + XtSetArg(threeD_args[arg_cnt], XtNright, XtChainRight); arg_cnt++; + XtSetArg(threeD_args[arg_cnt], XtNtop, XtChainTop); arg_cnt++; + XtSetArg(threeD_args[arg_cnt], XtNbottom, XtChainBottom); arg_cnt++; + XtSetArg(threeD_args[arg_cnt], XtNwidth, w->core.width); arg_cnt++; + XtSetArg(threeD_args[arg_cnt], XtNheight, w->core.height); arg_cnt++; + XtSetArg(threeD_args[arg_cnt], XtNrelief, XtReliefSunken); arg_cnt++; + w->viewport.threeD = + (ThreeDWidget)XtCreateManagedWidget("threeD", threeDWidgetClass, new, + threeD_args, arg_cnt); + XtVaGetValues((Widget)(w->viewport.threeD), XtNshadowWidth, &sw, NULL); + if (sw) + { + pad = 2; + + arg_cnt = 0; + XtSetArg(threeD_args[arg_cnt], XtNborderWidth, 0); arg_cnt++; + XtSetValues((Widget)w, threeD_args, arg_cnt); + } + +/* + * Create Clip Widget. + */ + + arg_cnt = 0; + XtSetArg(clip_args[arg_cnt], XtNbackgroundPixmap, None); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNborderWidth, 0); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNleft, XtChainLeft); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNright, XtChainRight); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNtop, XtChainTop); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNbottom, XtChainBottom); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNwidth, w->core.width - 2 * sw); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNheight, w->core.height - 2 * sw); arg_cnt++; + + w->viewport.clip = XtCreateManagedWidget("clip", widgetClass, new, + clip_args, arg_cnt); + + if (!w->viewport.forcebars) + return; /* If we are not forcing the bars then we are done. */ + + if (w->viewport.allowhoriz) + (void) CreateScrollbar(w, True); + if (w->viewport.allowvert) + (void) CreateScrollbar(w, False); + + h_bar = w->viewport.horiz_bar; + v_bar = w->viewport.vert_bar; + +/* + * Set the clip widget to the correct height. + */ + + clip_width = w->core.width - 2 * sw; + clip_height = w->core.height - 2 * sw; + + if ( (h_bar != NULL) && + ((int)w->core.width > + (int)(h_bar->core.width + h_bar->core.border_width + pad)) ) + clip_width -= h_bar->core.width + h_bar->core.border_width + pad; + + if ( (v_bar != NULL) && + ((int)w->core.height > + (int)(v_bar->core.height + v_bar->core.border_width + pad)) ) + clip_height -= v_bar->core.height + v_bar->core.border_width + pad; + + arg_cnt = 0; + XtSetArg(clip_args[arg_cnt], XtNwidth, clip_width); arg_cnt++; + XtSetArg(clip_args[arg_cnt], XtNheight, clip_height); arg_cnt++; + XtSetValues(w->viewport.clip, clip_args, arg_cnt); +} + +/* ARGSUSED */ +static void ConstraintInitialize(request, new, args, num_args) + Widget request, new; + ArgList args; + Cardinal *num_args; +{ + ((ViewportConstraints)new->core.constraints)->viewport.reparented = False; +} + +static void Realize(widget, value_mask, attributes) + Widget widget; + XtValueMask *value_mask; + XSetWindowAttributes *attributes; +{ + ViewportWidget w = (ViewportWidget)widget; + Widget child = w->viewport.child; + Widget clip = w->viewport.clip; + Widget threeD = (Widget)w->viewport.threeD; + + *value_mask |= CWBitGravity; + attributes->bit_gravity = NorthWestGravity; + (*superclass->core_class.realize)(widget, value_mask, attributes); + + (*w->core.widget_class->core_class.resize)(widget); /* turn on bars */ + + if (child != (Widget)NULL) { + XtMoveWidget( child, (Position)0, (Position)0 ); + XtRealizeWidget( clip ); + XtRealizeWidget( child ); + XtRealizeWidget( threeD ); + XLowerWindow( XtDisplay(threeD), XtWindow(threeD) ); + XReparentWindow( XtDisplay(w), XtWindow(child), XtWindow(clip), + (Position)0, (Position)0 ); + XtMapWidget( child ); + } +} + +/* ARGSUSED */ +static Boolean SetValues(current, request, new, args, num_args) + Widget current, request, new; + ArgList args; + Cardinal *num_args; +{ + ViewportWidget w = (ViewportWidget)new; + ViewportWidget cw = (ViewportWidget)current; + + if ( (w->viewport.forcebars != cw->viewport.forcebars) || + (w->viewport.allowvert != cw->viewport.allowvert) || + (w->viewport.allowhoriz != cw->viewport.allowhoriz) || + (w->viewport.useright != cw->viewport.useright) || + (w->viewport.usebottom != cw->viewport.usebottom) ) + { + (*w->core.widget_class->core_class.resize)(new); /* Recompute layout.*/ + } + + return False; +} + + +static void ChangeManaged(widget) + Widget widget; +{ + ViewportWidget w = (ViewportWidget)widget; + int num_children = w->composite.num_children; + Widget child, *childP; + int i; + + child = (Widget)NULL; + for (childP=w->composite.children, i=0; i < num_children; childP++, i++) { + if (XtIsManaged(*childP) + && *childP != w->viewport.clip + && *childP != w->viewport.horiz_bar + && *childP != w->viewport.vert_bar + && *childP != (Widget)w->viewport.threeD) + { + child = *childP; + break; + } + } + + if (child != w->viewport.child) { + w->viewport.child = child; + if (child != (Widget)NULL) { + XtResizeWidget( child, child->core.width, + child->core.height, (Dimension)0 ); + if (XtIsRealized(widget)) { + ViewportConstraints constraints = + (ViewportConstraints)child->core.constraints; + if (!XtIsRealized(child)) { + Window window = XtWindow(w); + XtMoveWidget( child, (Position)0, (Position)0 ); +#ifdef notdef + /* this is dirty, but it saves the following code: */ + XtRealizeWidget( child ); + XReparentWindow( XtDisplay(w), XtWindow(child), + XtWindow(w->viewport.clip), + (Position)0, (Position)0 ); + if (child->core.mapped_when_managed) + XtMapWidget( child ); +#else + w->core.window = XtWindow(w->viewport.clip); + XtRealizeWidget( child ); + w->core.window = window; +#endif /* notdef */ + constraints->viewport.reparented = True; + } + else if (!constraints->viewport.reparented) { + XReparentWindow( XtDisplay(w), XtWindow(child), + XtWindow(w->viewport.clip), + (Position)0, (Position)0 ); + constraints->viewport.reparented = True; + if (child->core.mapped_when_managed) + XtMapWidget( child ); + } + } + GetGeometry( widget, child->core.width, child->core.height ); + (*((ViewportWidgetClass)w->core.widget_class)->form_class.layout) + ( (FormWidget)w, w->core.width, w->core.height ); + /* %%% do we need to hide this child from Form? */ + } + } + +#ifdef notdef + (*superclass->composite_class.change_managed)( widget ); +#endif +} + + +static void SetBar(w, top, length, total) + Widget w; + Position top; + Dimension length, total; +{ + XawScrollbarSetThumb(w, (float)top/(float)total, + (float)length/(float)total); +} + +static void RedrawThumbs(w) + ViewportWidget w; +{ + Widget child = w->viewport.child; + Widget clip = w->viewport.clip; + + if (w->viewport.horiz_bar != (Widget)NULL) + SetBar( w->viewport.horiz_bar, -(child->core.x), + clip->core.width, child->core.width ); + + if (w->viewport.vert_bar != (Widget)NULL) + SetBar( w->viewport.vert_bar, -(child->core.y), + clip->core.height, child->core.height ); +} + + + +static void SendReport (w, changed) + ViewportWidget w; + unsigned int changed; +{ + XawPannerReport rep; + + if (w->viewport.report_callbacks) { + Widget child = w->viewport.child; + Widget clip = w->viewport.clip; + + rep.changed = changed; + rep.slider_x = -child->core.x; /* child is canvas */ + rep.slider_y = -child->core.y; /* clip is slider */ + rep.slider_width = clip->core.width; + rep.slider_height = clip->core.height; + rep.canvas_width = child->core.width; + rep.canvas_height = child->core.height; + XtCallCallbackList ((Widget) w, w->viewport.report_callbacks, + (XtPointer) &rep); + } +} + + +static void MoveChild(w, x, y) + ViewportWidget w; + Position x, y; +{ + Widget child = w->viewport.child; + Widget clip = w->viewport.clip; + + /* make sure we never move past right/bottom borders */ + if (-x + (int)clip->core.width > (int)child->core.width) + x = -(child->core.width - clip->core.width); + + if (-y + (int)clip->core.height > (int)child->core.height) + y = -(child->core.height - clip->core.height); + + /* make sure we never move past left/top borders */ + if (x >= 0) x = 0; + if (y >= 0) y = 0; + + XtMoveWidget(child, x, y); + SendReport (w, (XawPRSliderX | XawPRSliderY)); + + RedrawThumbs(w); +} + + +static void ComputeLayout(widget, query, destroy_scrollbars) + Widget widget; /* Viewport */ + Boolean query; /* query child's preferred geom? */ + Boolean destroy_scrollbars; /* destroy un-needed scrollbars? */ +{ + ViewportWidget w = (ViewportWidget)widget; + Widget child = w->viewport.child; + Widget clip = w->viewport.clip; + Widget threeD = (Widget)w->viewport.threeD; + ViewportConstraints constraints + = (ViewportConstraints)clip->core.constraints; + Boolean needshoriz, needsvert; + int clip_width, clip_height; + int bar_width, bar_height; + XtWidgetGeometry intended; + Dimension pad = 0, sw = 0; + + /* + * I've made two optimizations here. The first does away with the + * loop, and the second defers setting the child dimensions to the + * clip if smaller until after adjusting for possible scrollbars. + * If you find that these go too far, define the identifiers here + * as required. -- djhjr + */ +#define NEED_LAYOUT_LOOP +#undef PREP_CHILD_TO_CLIP + + if (child == (Widget) NULL) return; + + XtVaGetValues(threeD, XtNshadowWidth, &sw, NULL); + if (sw) pad = 2; + + clip_width = w->core.width - 2 * sw; + clip_height = w->core.height - 2 * sw; + intended.request_mode = CWBorderWidth; + intended.border_width = 0; + + if (w->viewport.forcebars) { + needsvert = w->viewport.allowvert; + needshoriz = w->viewport.allowhoriz; + ComputeWithForceBars(widget, query, &intended, + &clip_width, &clip_height); + } + else { +#ifdef NEED_LAYOUT_LOOP + Dimension prev_width, prev_height; + XtGeometryMask prev_mode; +#endif + XtWidgetGeometry preferred; + + needshoriz = needsvert = False; + + /* + * intended.{width,height} caches the eventual child dimensions, + * but we don't set the mode bits until after we decide that the + * child's preferences are not acceptable. + */ + + if (!w->viewport.allowhoriz) + intended.request_mode |= CWWidth; + +#ifdef PREP_CHILD_TO_CLIP + if ((int)child->core.width < clip_width) + intended.width = clip_width; + else +#endif + intended.width = child->core.width; + + if (!w->viewport.allowvert) + intended.request_mode |= CWHeight; + +#ifdef PREP_CHILD_TO_CLIP + if ((int)child->core.height < clip_height) + intended.height = clip_height; + else +#endif + intended.height = child->core.height; + + if (!query) { + preferred.width = child->core.width; + preferred.height = child->core.height; + } + +#ifdef NEED_LAYOUT_LOOP + do { /* while intended != prev */ +#endif + if (query) { + (void) XtQueryGeometry( child, &intended, &preferred ); + if ( !(preferred.request_mode & CWWidth) ) + preferred.width = intended.width; + if ( !(preferred.request_mode & CWHeight) ) + preferred.height = intended.height; + } + +#ifdef NEED_LAYOUT_LOOP + prev_width = intended.width; + prev_height = intended.height; + prev_mode = intended.request_mode; +#endif + + /* + * Note that having once decided to turn on either bar + * we'll not change our mind until we're next resized, + * thus avoiding potential oscillations. + */ + +#define CheckHoriz() \ + if (w->viewport.allowhoriz && \ + (int)preferred.width > clip_width + 2 * sw) { \ + if (!needshoriz) { \ + Widget bar = w->viewport.horiz_bar; \ + needshoriz = True; \ + if (bar == (Widget)NULL) \ + bar = CreateScrollbar(w, True); \ + clip_height -= bar->core.height + \ + bar->core.border_width + pad; \ + if (clip_height < 1) clip_height = 1; \ + } \ + intended.width = preferred.width; \ + } +/* enddef */ + CheckHoriz(); + if (w->viewport.allowvert && + (int)preferred.height > clip_height + 2 * sw) { + if (!needsvert) { + Widget bar = w->viewport.vert_bar; + needsvert = True; + if (bar == (Widget)NULL) + bar = CreateScrollbar(w, False); + clip_width -= bar->core.width + + bar->core.border_width + pad; + if (clip_width < 1) clip_width = 1; + if (!needshoriz) CheckHoriz(); + } + intended.height = preferred.height; + } + +#ifdef PREP_CHILD_TO_CLIP + if (!w->viewport.allowhoriz || + (int)preferred.width < clip_width) { + intended.width = clip_width; + intended.request_mode |= CWWidth; + } + if (!w->viewport.allowvert || + (int)preferred.height < clip_height) { + intended.height = clip_height; + intended.request_mode |= CWHeight; + } +#endif +#ifdef NEED_LAYOUT_LOOP + } while ( intended.request_mode != prev_mode || + (intended.request_mode & CWWidth && + intended.width != prev_width) || + (intended.request_mode & CWHeight && + intended.height != prev_height) ); +#endif + +#ifndef PREP_CHILD_TO_CLIP + if (!w->viewport.allowhoriz || + (int)preferred.width < clip_width) { + intended.width = clip_width; + intended.request_mode |= CWWidth; + } + if (!w->viewport.allowvert || + (int)preferred.height < clip_height) { + intended.height = clip_height; + intended.request_mode |= CWHeight; + } +#endif + } + + bar_width = bar_height = 0; + if (needsvert) + bar_width = w->viewport.vert_bar->core.width + + w->viewport.vert_bar->core.border_width + pad; + if (needshoriz) + bar_height = w->viewport.horiz_bar->core.height + + w->viewport.horiz_bar->core.border_width + pad; + + if (XtIsRealized(threeD)) + XLowerWindow( XtDisplay(threeD), XtWindow(threeD) ); + + XtMoveWidget( threeD, + (Position)(!needsvert ? 0 : + (w->viewport.useright ? 0 : bar_width)), + (Position)(!needshoriz ? 0 : + (w->viewport.usebottom ? 0 : bar_height)) ); + XtResizeWidget( threeD, (Dimension)(w->core.width - bar_width), + (Dimension)(w->core.height - bar_height), (Dimension)0 ); + + if (XtIsRealized(clip)) + XRaiseWindow( XtDisplay(clip), XtWindow(clip) ); + + XtMoveWidget( clip, + (Position)(!needsvert ? sw : + (w->viewport.useright ? sw : bar_width + sw)), + (Position)(!needshoriz ? sw : + (w->viewport.usebottom ? sw : bar_height + sw)) ); + XtResizeWidget( clip, (Dimension)clip_width, (Dimension)clip_height, + (Dimension)0 ); + + if (w->viewport.horiz_bar != (Widget)NULL) { + Widget bar = w->viewport.horiz_bar; + if (!needshoriz) { + constraints->form.vert_base = (Widget)NULL; + if (destroy_scrollbars) { + XtDestroyWidget( bar ); + w->viewport.horiz_bar = (Widget)NULL; + } + } + else { + int bw = bar->core.border_width; + XtResizeWidget( bar, + (Dimension)(clip_width + 2 * sw), bar->core.height, + (Dimension)bw ); + XtMoveWidget( bar, + (Position)((needsvert && !w->viewport.useright) + ? w->viewport.vert_bar->core.width + pad + : -bw), + (Position)(w->viewport.usebottom + ? w->core.height - bar->core.height - bw + : -bw) ); + XtSetMappedWhenManaged( bar, True ); + } + } + + if (w->viewport.vert_bar != (Widget)NULL) { + Widget bar = w->viewport.vert_bar; + if (!needsvert) { + constraints->form.horiz_base = (Widget)NULL; + if (destroy_scrollbars) { + XtDestroyWidget( bar ); + w->viewport.vert_bar = (Widget)NULL; + } + } + else { + int bw = bar->core.border_width; + XtResizeWidget( bar, + bar->core.width, (Dimension)(clip_height + 2 * sw), + (Dimension)bw ); + XtMoveWidget( bar, + (Position)(w->viewport.useright + ? w->core.width - bar->core.width - bw + : -bw), + (Position)((needshoriz && !w->viewport.usebottom) + ? w->viewport.horiz_bar->core.height + pad + : -bw) ); + XtSetMappedWhenManaged( bar, True ); + } + } + + if (child != (Widget)NULL) { + XtResizeWidget( child, (Dimension)intended.width, + (Dimension)intended.height, (Dimension)0 ); + MoveChild(w, + needshoriz ? child->core.x : 0, + needsvert ? child->core.y : 0); + } + + SendReport (w, XawPRAll); +} + +/* Function Name: ComputeWithForceBars + * Description: Computes the layout give forcebars is set. + * Arguments: widget - the viewport widget. + * query - whether or not to query the child. + * intended - the cache of the childs height is + * stored here ( USED AND RETURNED ). + * clip_width, clip_height - size of clip window. + * (USED AND RETURNED ). + * Returns: none. + */ + +static void +ComputeWithForceBars(widget, query, intended, clip_width, clip_height) +Widget widget; +Boolean query; +XtWidgetGeometry * intended; +int *clip_width, *clip_height; +{ + ViewportWidget w = (ViewportWidget)widget; + Widget child = w->viewport.child; + XtWidgetGeometry preferred; + Dimension pad = 0, sw = 0; + +/* + * If forcebars then needs = allows = has. + * Thus if needsvert is set it MUST have a scrollbar. + */ + + XtVaGetValues((Widget)(w->viewport.threeD), XtNshadowWidth, &sw, NULL); + if (sw) pad = 2; + + if (w->viewport.allowvert) { + if (w->viewport.vert_bar == NULL) + w->viewport.vert_bar = CreateScrollbar(w, False); + + *clip_width -= w->viewport.vert_bar->core.width + + w->viewport.vert_bar->core.border_width + pad; + } + + if (w->viewport.allowhoriz) { + if (w->viewport.horiz_bar == NULL) + w->viewport.horiz_bar = CreateScrollbar(w, True); + + *clip_height -= w->viewport.horiz_bar->core.height + + w->viewport.horiz_bar->core.border_width + pad; + } + + AssignMax( *clip_width, 1 ); + AssignMax( *clip_height, 1 ); + + if (!w->viewport.allowvert) { + intended->height = *clip_height; + intended->request_mode |= CWHeight; + } + if (!w->viewport.allowhoriz) { + intended->width = *clip_width; + intended->request_mode |= CWWidth; + } + + if ( query ) { + if ( (w->viewport.allowvert || w->viewport.allowhoriz) ) { + XtQueryGeometry( child, intended, &preferred ); + + if ( !(intended->request_mode & CWWidth) ) + if ( preferred.request_mode & CWWidth ) + intended->width = preferred.width; + else + intended->width = child->core.width; + + if ( !(intended->request_mode & CWHeight) ) + if ( preferred.request_mode & CWHeight ) + intended->height = preferred.height; + else + intended->height = child->core.height; + } + } + else { + if (w->viewport.allowvert) + intended->height = child->core.height; + if (w->viewport.allowhoriz) + intended->width = child->core.width; + } + + if (*clip_width > (int)intended->width) + intended->width = *clip_width; + if (*clip_height > (int)intended->height) + intended->height = *clip_height; +} + +static void Resize(widget) + Widget widget; +{ + ComputeLayout( widget, /*query=*/True, /*destroy=*/True ); +} + + +/* ARGSUSED */ +static Boolean Layout(w, width, height) + FormWidget w; + Dimension width, height; +{ + ComputeLayout( (Widget)w, /*query=*/True, /*destroy=*/True ); + w->form.preferred_width = w->core.width; + w->form.preferred_height = w->core.height; + return False; +} + + +static void ScrollUpDownProc(widget, closure, call_data) + Widget widget; + XtPointer closure; + XtPointer call_data; +{ + ViewportWidget w = (ViewportWidget)closure; + Widget child = w->viewport.child; + int pix = (int)call_data; + Position x, y; + + if (child == NULL) return; /* no child to scroll. */ + + x = child->core.x - ((widget == w->viewport.horiz_bar) ? pix : 0); + y = child->core.y - ((widget == w->viewport.vert_bar) ? pix : 0); + MoveChild(w, x, y); +} + + +/* ARGSUSED */ +static void ThumbProc(widget, closure, call_data) + Widget widget; + XtPointer closure; + XtPointer call_data; +{ + ViewportWidget w = (ViewportWidget)closure; + Widget child = w->viewport.child; + float *percent = (float *) call_data; + Position x, y; + + if (child == NULL) return; /* no child to scroll. */ + + if (widget == w->viewport.horiz_bar) +#ifdef macII /* bug in the macII A/UX 1.0 cc */ + x = (int)(-*percent * child->core.width); +#else /* else not macII */ + x = -(int)(*percent * child->core.width); +#endif /* macII */ + else + x = child->core.x; + + if (widget == w->viewport.vert_bar) +#ifdef macII /* bug in the macII A/UX 1.0 cc */ + y = (int)(-*percent * child->core.height); +#else /* else not macII */ + y = -(int)(*percent * child->core.height); +#endif /* macII */ + else + y = child->core.y; + + MoveChild(w, x, y); +} + +static XtGeometryResult +TestSmaller(w, request, reply_return) + ViewportWidget w; XtWidgetGeometry *request, *reply_return; +{ + if (request->width < w->core.width || request->height < w->core.height) + return XtMakeGeometryRequest((Widget)w, request, reply_return); + else + return XtGeometryYes; +} + +static XtGeometryResult +GeometryRequestPlusScrollbar(w, horizontal, request, reply_return) + Boolean horizontal; + ViewportWidget w; + XtWidgetGeometry *request, *reply_return; +{ + Widget bar; + XtWidgetGeometry plusScrollbars; + Dimension pad = 0, sw = 0; + + XtVaGetValues((Widget)(w->viewport.threeD), XtNshadowWidth, &sw, NULL); + if (sw) pad = 2; + + plusScrollbars = *request; + if ((bar = w->viewport.horiz_bar) == (Widget)NULL) + bar = CreateScrollbar(w, horizontal); + request->width += bar->core.width + pad; + request->height += bar->core.height + pad; + XtDestroyWidget(bar); + return XtMakeGeometryRequest((Widget) w, &plusScrollbars, reply_return); + } + +#define WidthChange() (request->width != w->core.width) +#define HeightChange() (request->height != w->core.height) + +static XtGeometryResult +QueryGeometry(w, request, reply_return) + ViewportWidget w; XtWidgetGeometry *request, *reply_return; +{ + if (w->viewport.allowhoriz && w->viewport.allowvert) + return TestSmaller(w, request, reply_return); + + else if (w->viewport.allowhoriz && !w->viewport.allowvert) { + if (WidthChange() && !HeightChange()) + return TestSmaller(w, request, reply_return); + else if (!WidthChange() && HeightChange()) + return XtMakeGeometryRequest((Widget) w, request, reply_return); + else if (WidthChange() && HeightChange()) /* hard part */ + return GeometryRequestPlusScrollbar(w, True, request, reply_return); + else /* !WidthChange() && !HeightChange() */ + return XtGeometryYes; + } + else if (!w->viewport.allowhoriz && w->viewport.allowvert) { + if (!WidthChange() && HeightChange()) + return TestSmaller(w, request, reply_return); + else if (WidthChange() && !HeightChange()) + return XtMakeGeometryRequest((Widget)w, request, reply_return); + else if (WidthChange() && HeightChange()) /* hard part */ + return GeometryRequestPlusScrollbar(w, False, request, reply_return); + else /* !WidthChange() && !HeightChange() */ + return XtGeometryYes; + } + else /* (!w->viewport.allowhoriz && !w->viewport.allowvert) */ + return XtMakeGeometryRequest((Widget) w, request, reply_return); +} + +#undef WidthChange +#undef HeightChange + +static XtGeometryResult GeometryManager(child, request, reply) + Widget child; + XtWidgetGeometry *request, *reply; +{ + ViewportWidget w = (ViewportWidget)child->core.parent; + Boolean rWidth = (Boolean)(request->request_mode & CWWidth); + Boolean rHeight = (Boolean)(request->request_mode & CWHeight); + XtWidgetGeometry allowed; + XtGeometryResult result; + Boolean reconfigured; + Boolean child_changed_size; + Dimension height_remaining; + Dimension pad = 0, sw = 0; + + if (request->request_mode & XtCWQueryOnly) + return QueryGeometry(w, request, reply); + + if (child != w->viewport.child + || request->request_mode & ~(CWWidth | CWHeight + | CWBorderWidth) + || ((request->request_mode & CWBorderWidth) + && request->border_width > 0)) + return XtGeometryNo; + + XtVaGetValues((Widget)(w->viewport.threeD), XtNshadowWidth, &sw, NULL); + if (sw) pad = 2; + + allowed = *request; + + reconfigured = GetGeometry( (Widget)w, + (rWidth ? request->width : w->core.width), + (rHeight ? request->height : w->core.height) + ); + + child_changed_size = ((rWidth && child->core.width != request->width) || + (rHeight && child->core.height != request->height)); + + height_remaining = w->core.height; + if (rWidth && w->core.width != request->width) { + if (w->viewport.allowhoriz && request->width > w->core.width) { + /* horizontal scrollbar will be needed so possibly reduce height */ + Widget bar; + if ((bar = w->viewport.horiz_bar) == (Widget)NULL) + bar = CreateScrollbar( w, True ); + height_remaining -= bar->core.height + + bar->core.border_width + pad; + reconfigured = True; + } + else { + allowed.width = w->core.width; + } + } + if (rHeight && height_remaining != request->height) { + if (w->viewport.allowvert && request->height > height_remaining) { + /* vertical scrollbar will be needed, so possibly reduce width */ + if (!w->viewport.allowhoriz || request->width < w->core.width) { + Widget bar; + if ((bar = w->viewport.vert_bar) == (Widget)NULL) + bar = CreateScrollbar( w, False ); + if (!rWidth) { + allowed.width = w->core.width; + allowed.request_mode |= CWWidth; + } + if ( (int)allowed.width > + (int)(bar->core.width + bar->core.border_width + pad) ) + allowed.width -= bar->core.width + + bar->core.border_width + pad; + else + allowed.width = 1; + reconfigured = True; + } + } + else { + allowed.height = height_remaining; + } + } + + if (allowed.width != request->width || allowed.height != request->height) { + *reply = allowed; + result = XtGeometryAlmost; + } + else { + if (rWidth) child->core.width = request->width; + if (rHeight) child->core.height = request->height; + result = XtGeometryYes; + } + + if (reconfigured || child_changed_size) + ComputeLayout( (Widget)w, + /*query=*/ False, + /*destroy=*/ (result == XtGeometryYes) ? True : False ); + + return result; + } + + +static Boolean GetGeometry(w, width, height) + Widget w; + Dimension width, height; +{ + XtWidgetGeometry geometry, return_geom; + XtGeometryResult result; + + if (width == w->core.width && height == w->core.height) + return False; + + geometry.request_mode = CWWidth | CWHeight; + geometry.width = width; + geometry.height = height; + + if (XtIsRealized(w)) { + if (((ViewportWidget)w)->viewport.allowhoriz && width > w->core.width) + geometry.width = w->core.width; + if (((ViewportWidget)w)->viewport.allowvert && height > w->core.height) + geometry.height = w->core.height; + } else { + /* This is the Realize call; we'll inherit a w&h iff none currently */ + if (w->core.width != 0) { + if (w->core.height != 0) return False; + geometry.width = w->core.width; + } + if (w->core.height != 0) geometry.height = w->core.height; + } + + result = XtMakeGeometryRequest(w, &geometry, &return_geom); + if (result == XtGeometryAlmost) + result = XtMakeGeometryRequest(w, &return_geom, (XtWidgetGeometry *)NULL); + + return (result == XtGeometryYes); +} + +static XtGeometryResult PreferredGeometry(w, constraints, reply) + Widget w; + XtWidgetGeometry *constraints, *reply; +{ + if (((ViewportWidget)w)->viewport.child != NULL) + return XtQueryGeometry( ((ViewportWidget)w)->viewport.child, + constraints, reply ); + else + return XtGeometryYes; +} + + +void +#if NeedFunctionPrototypes +XawViewportSetLocation (Widget gw, +#if NeedWidePrototypes + double xoff, double yoff) +#else + float xoff, float yoff) +#endif +#else +XawViewportSetLocation (gw, xoff, yoff) + Widget gw; + float xoff,yoff; +#endif +{ + ViewportWidget w = (ViewportWidget) gw; + Widget child = w->viewport.child; + Position x, y; + + if (xoff > 1.0) /* scroll to right */ + x = child->core.width; + else if (xoff < 0.0) /* if the offset is < 0.0 nothing */ + x = child->core.x; + else + x = (Position) (((float) child->core.width) * xoff); + + if (yoff > 1.0) + y = child->core.height; + else if (yoff < 0.0) + y = child->core.y; + else + y = (Position) (((float) child->core.height) * yoff); + + MoveChild (w, -x, -y); +} + +void +#if NeedFunctionPrototypes +XawViewportSetCoordinates (Widget gw, +#if NeedWidePrototypes + int x, int y) +#else + Position x, Position y) +#endif +#else +XawViewportSetCoordinates (gw, x, y) + Widget gw; + Position x, y; +#endif +{ + ViewportWidget w = (ViewportWidget) gw; + Widget child = w->viewport.child; + + if (x > (int)child->core.width) + x = child->core.width; + else if (x < 0) + x = child->core.x; + + if (y > (int)child->core.height) + y = child->core.height; + else if (y < 0) + y = child->core.y; + + MoveChild (w, -x, -y); +} + diff --git a/src/Viewport.h b/src/Viewport.h new file mode 100644 index 0000000..499905e --- /dev/null +++ b/src/Viewport.h @@ -0,0 +1,124 @@ +/* $XConsortium: Viewport.h,v 1.23 94/04/17 20:13:27 kaleb Exp $ */ + +/************************************************************ + +Copyright (c) 1987, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +#ifndef _XawViewport_h +#define _XawViewport_h + +#include <X11/Xaw3d/Form.h> +#include <X11/Xaw3d/Reports.h> + +/* Resources: + + Name Class RepType Default Value + ---- ----- ------- ------------- + allowHoriz Boolean Boolean False + allowVert Boolean Boolean False + background Background Pixel XtDefaultBackground + border BorderColor Pixel XtDefaultForeground + borderWidth BorderWidth Dimension 1 + destroyCallback Callback Pointer NULL + foreceBars Boolean Boolean False + height Height Dimension 0 + mappedWhenManaged MappedWhenManaged Boolean True + reportCallback ReportCallback Pointer NULL + sensitive Sensitive Boolean True + useBottom Boolean Boolean False + useRight Boolean Boolean False + width Width Dimension 0 + x Position Position 0 + y Position Position 0 + +*/ + +/* fields added to Form */ +#ifndef _XtStringDefs_h_ +#define XtNforceBars "forceBars" +#define XtNallowHoriz "allowHoriz" +#define XtNallowVert "allowVert" +#define XtNuseBottom "useBottom" +#define XtNuseRight "useRight" +#endif + +extern WidgetClass viewportWidgetClass; + +typedef struct _ViewportClassRec *ViewportWidgetClass; +typedef struct _ViewportRec *ViewportWidget; + +_XFUNCPROTOBEGIN + +extern void XawViewportSetLocation ( +#if NeedFunctionPrototypes + Widget /* gw */, +#if NeedWidePrototypes + /* float */ double /* xoff */, + /* float */ double /* yoff */ +#else + float /* xoff */, + float /* yoff */ +#endif +#endif +); + +extern void XawViewportSetCoordinates ( +#if NeedFunctionPrototypes + Widget /* gw */, +#if NeedWidePrototypes + /* Position */ int /* x */, + /* Position */ int /* y */ +#else + Position /* x */, + Position /* y */ +#endif +#endif +); + +_XFUNCPROTOEND + +#endif /* _XawViewport_h */ diff --git a/src/ViewportP.h b/src/ViewportP.h new file mode 100644 index 0000000..20e279b --- /dev/null +++ b/src/ViewportP.h @@ -0,0 +1,108 @@ +/* + * $XConsortium: ViewportP.h,v 1.14 94/04/17 20:13:28 jim Exp $ + * Private declarations for ViewportWidgetClass + */ + +/************************************************************ + +Copyright (c) 1987 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +********************************************************/ + +#ifndef _ViewportP_h +#define _ViewportP_h + +#include <X11/Xaw3d/Viewport.h> +#include <X11/Xaw3d/FormP.h> +#include <X11/Xaw3d/ThreeDP.h> + +typedef struct {int empty;} ViewportClassPart; + +typedef struct _ViewportClassRec { + CoreClassPart core_class; + CompositeClassPart composite_class; + ConstraintClassPart constraint_class; + FormClassPart form_class; + ViewportClassPart viewport_class; +} ViewportClassRec; + +extern ViewportClassRec viewportClassRec; + +typedef struct _ViewportPart { + /* resources */ + Boolean forcebars; /* Whether we should always display */ + /* the selected scrollbars. */ + Boolean allowhoriz; /* Whether we allow horizontal scrollbars. */ + Boolean allowvert; /* Whether we allow vertical scrollbars. */ + Boolean usebottom; /* True iff horiz bars appear at bottom. */ + Boolean useright; /* True iff vert bars appear at right. */ + XtCallbackList report_callbacks; /* when size/position changes */ + /* private state */ + Widget clip, child; /* The clipping and (scrolled) child widgets */ + Widget horiz_bar, vert_bar;/* What scrollbars we currently have. */ + ThreeDWidget threeD; +} ViewportPart; + +typedef struct _ViewportRec { + CorePart core; + CompositePart composite; + ConstraintPart constraint; + FormPart form; + ViewportPart viewport; +} ViewportRec; + +typedef struct { + /* resources */ + + /* private state */ + Boolean reparented; /* True if child has been re-parented */ +} ViewportConstraintsPart; + +typedef struct _ViewportConstraintsRec { + FormConstraintsPart form; + ViewportConstraintsPart viewport; +} ViewportConstraintsRec, *ViewportConstraints; + +#endif /* _ViewportP_h */ diff --git a/src/Xaw3dP.c b/src/Xaw3dP.c new file mode 100644 index 0000000..b3b26f7 --- /dev/null +++ b/src/Xaw3dP.c @@ -0,0 +1,212 @@ +/* + * Xaw3dP.c + * + * Global functions that don't really belong anywhere else. + */ + +/********************************************************************* +Copyright (C) 1992 Kaleb Keithley +Copyright (C) 2000, 2003 David J. Hawkey Jr. + + All Rights Reserved + +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 names of the copyright holders +not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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 TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ + +#include "Xaw3dP.h" +#ifdef XAW_MULTIPLANE_PIXMAPS +#include <stdio.h> +#include <X11/xpm.h> +#endif + +#ifdef XAW_GRAY_BLKWHT_STIPPLES +/* ARGSUSED */ +unsigned long +grayPixel(p, dpy, scn) +unsigned long p; /* unused */ +Display *dpy; +Screen *scn; +{ + static XColor Gray = + { + 0, /* pixel */ + 0, 0, 0, /* red, green, blue */ + 0, /* flags */ + 0 /* pad */ + }; + + if (!Gray.pixel) + { + XColor exact; + + (void)XAllocNamedColor(dpy, DefaultColormapOfScreen(scn), + "gray", &Gray, &exact); /* Blindflug */ + } + + return Gray.pixel; +} +#endif + +#ifdef XAW_MULTIPLANE_PIXMAPS +#define IS_EVEN(x) (((x) % 2) == 0) +#define IS_ODD(x) (((x) % 2) == 1) + +/* ARGSUSED */ +Pixmap +stipplePixmap(w, pm, cm, bg, d) +Widget w; +Pixmap pm; +Colormap cm; +Pixel bg; +unsigned int d; +{ + static Pixmap pixmap; + Display *dpy; + XpmImage image; + XpmAttributes attr; + XpmColor *src_table, *dst_table; + int i, j, index = -1; + + if (pm == None) + return (None); + if (XtIsRealized(w) == False) + return (None); + + dpy = XtDisplayOfObject(w); + + attr.colormap = cm; + attr.closeness = 32768; /* might help on 8-bpp displays? */ + attr.valuemask = XpmColormap | XpmCloseness; + + if (XpmCreateXpmImageFromPixmap(dpy, pm, None, + &image, &attr) != XpmSuccess) + return (None); + if (image.height == 0 || image.width == 0) + { + XpmFreeXpmImage(&image); + return (None); + } + + if (d > 1) + { + XColor x_color; + XpmColor *dst_color; + char dst_rgb[14]; + + /* + * Multi-plane (XPM) pixmap. Don't bother scanning the color table + * for the background color, it might not be there. Copy the color + * table, add an entry for the background color, and set the index + * to that. + */ + + x_color.pixel = bg; + XQueryColor(dpy, cm, &x_color); + sprintf(dst_rgb, "#%04X%04X%04X", + x_color.red, x_color.green, x_color.blue); + + dst_table = (XpmColor *) XtCalloc(sizeof(XpmColor), + image.ncolors + 1); + memcpy(dst_table, image.colorTable, image.ncolors * sizeof(XpmColor)); + + dst_color = &dst_table[image.ncolors]; + switch (w->core.depth) + { + case 1: + dst_color->m_color = dst_rgb; + break; + case 4: + dst_color->g4_color = dst_rgb; + break; + case 6: + dst_color->g_color = dst_rgb; + break; + case 8: + default: + dst_color->c_color = dst_rgb; + break; + } + dst_color->string = "\x01"; /* ! */ + + src_table = image.colorTable; + image.colorTable = dst_table; + + index = image.ncolors++; + } + else + { + XpmColor *src_color; + char *src_rgb; + + /* + * Single-plane (XBM) pixmap. Set the index to the white color. + */ + + for (i = 0, src_color = image.colorTable; i < image.ncolors; + i++, src_color++) + { + switch (w->core.depth) + { + case 1: + src_rgb = src_color->m_color; + break; + case 4: + src_rgb = src_color->g4_color; + break; + case 6: + src_rgb = src_color->g_color; + break; + case 8: + default: + src_rgb = src_color->c_color; + break; + } + if (strcmp(src_rgb, "#000000000000") == 0) + { + index = i; + break; + } + } + + if (index == -1) + { + XpmFreeXpmImage(&image); + return (None); + } + } + + for (i = 0; i < image.height; i++) + for (j = 0; j < image.width; j++) + if ((IS_ODD(i) && IS_EVEN(j)) || (IS_EVEN(i) && IS_ODD(j))) + image.data[(i * image.width) + j] = index; + + attr.depth = d; + attr.valuemask |= XpmDepth; + + i = XpmCreatePixmapFromXpmImage(dpy, pm, &image, &pixmap, NULL, &attr); + + if (d > 1) + { + XtFree((void *)image.colorTable); /* dst_table */ + image.colorTable = src_table; + image.ncolors--; + } + XpmFreeXpmImage(&image); + + return ((i == XpmSuccess) ? pixmap : None); +} +#endif diff --git a/src/Xaw3dP.h.sed b/src/Xaw3dP.h.sed new file mode 100644 index 0000000..391bde3 --- /dev/null +++ b/src/Xaw3dP.h.sed @@ -0,0 +1,83 @@ +/* + * Xaw3dP.h + * + * Global definitions and declarations. Not for public consumption. + */ + +/********************************************************************* +Copyright (C) 1992 Kaleb Keithley +Copyright (C) 2000, 2003 David J. Hawkey Jr. + + All Rights Reserved + +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 names of the copyright holders +not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. + +THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS. IN NO EVENT SHALL THE COPYRIGHT HOLDERS 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 TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*********************************************************************/ + +#ifndef _Xaw3dP_h +#define _Xaw3dP_h + +#include <X11/IntrinsicP.h> + +/* These are set during the build to reflect capability and options. */ +/* I18n support */ +/* XPM support */ +/* gray stipples */ +/* arrow scrollbars */ + +#ifndef XtX +#define XtX(w) (((RectObj)w)->rectangle.x) +#endif +#ifndef XtY +#define XtY(w) (((RectObj)w)->rectangle.y) +#endif +#ifndef XtWidth +#define XtWidth(w) (((RectObj)w)->rectangle.width) +#endif +#ifndef XtHeight +#define XtHeight(w) (((RectObj)w)->rectangle.height) +#endif +#ifndef XtBorderWidth +#define XtBorderWidth(w) (((RectObj)w)->rectangle.border_width) +#endif + +#ifdef XAW_GRAY_BLKWHT_STIPPLES +extern unsigned long +grayPixel( +#if NeedFunctionPrototypes + unsigned long, + Display *, + Screen * +#endif +); +#else +#define grayPixel(p, dpy, scn) (p) +#endif + +#ifdef XAW_MULTIPLANE_PIXMAPS +extern Pixmap +stipplePixmap( +#if NeedFunctionPrototypes + Widget, + Pixmap, + Colormap, + Pixel, + unsigned int +#endif +); +#endif + +#endif /* _Xaw3dP_h */ diff --git a/src/XawI18n.c b/src/XawI18n.c new file mode 100644 index 0000000..c911057 --- /dev/null +++ b/src/XawI18n.c @@ -0,0 +1,88 @@ +/* $XConsortium: XawI18n.c,v 1.6 94/04/17 20:13:28 kaleb Exp $ */ + +/* Copyright 1991 NCR Corporation - Dayton, Ohio, USA */ + +/* + * Copyright 1990, 1991 by OMRON Corporation, NTT Software Corporation, + * and Nippon Telegraph and Telephone Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 names of OMRON, NTT Software, and NTT + * not be used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. OMRON, NTT Software, + * and NTT make no representations about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + * + * OMRON, NTT SOFTWARE, AND NTT, DISCLAIM ALL WARRANTIES WITH REGARD + * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS, IN NO EVENT SHALL OMRON, NTT SOFTWARE, OR NTT 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 TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Li Yuhong OMRON Corporation + */ + +/* + +Copyright (c) 1991, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +#include <X11/IntrinsicP.h> +#include "XawI18n.h" + +#if NeedFunctionPrototypes +wchar_t _Xaw_atowc( + unsigned char c) +#else +wchar_t _Xaw_atowc(c) + unsigned char c; +#endif +{ + wchar_t wc; + char str[2]; + + str[0] = c; + str[1] = '\0'; + + mbtowc(&wc, str, 1); + return wc; +} + +#ifdef NCR +int _Xaw_iswspace(wchar_t w) +{ + int ret = 0; + wchar_t s = _Xaw_atowc(' '); + if (s == w) + ret = 1; + return ret; +} +#endif diff --git a/src/XawI18n.h b/src/XawI18n.h new file mode 100644 index 0000000..1b0ee5d --- /dev/null +++ b/src/XawI18n.h @@ -0,0 +1,78 @@ +/* $XConsortium: XawI18n.h,v 1.12 95/01/25 00:48:44 kaleb Exp $ */ + +/************************************************************ + +Copyright (c) 1993, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +********************************************************/ + +#ifdef HAS_WCTYPE_H +#include <wctype.h> +#include <widec.h> +#define wcslen(c) wslen(c) +#define wcscpy(d,s) wscpy(d,s) +#define wcsncpy(d,s,l) wsncpy(d,s,l) +#endif + +#ifdef HAS_WCHAR_H +#include <wchar.h> +#endif + +#ifdef AIXV3 +#include <ctype.h> +#endif + +#ifdef NCR +#define iswspace(c) _Xaw_iswspace(c) +extern int _Xaw_iswspace(wchar_t); +#endif + +#ifdef sony +#ifndef SVR4 +#include <jctype.h> +#define iswspace(c) jisspace(c) +#endif +#endif + +#ifdef USE_XWCHAR_STRING +#define wcslen(c) _Xwcslen(c) +#define wcscpy(d,s) _Xwcscpy(d,s) +#define wcsncpy(d,s,l) _Xwcsncpy(d,s,l) +#ifdef USE_XMBTOWC +#define mbtowc(wc,s,l) _Xmbtowc(wc,s,l) +#endif +#endif + +extern wchar_t _Xaw_atowc ( +#if NeedFunctionPrototypes + unsigned char c +#endif +); + +#ifndef HAS_ISW_FUNCS +#include <ctype.h> +#ifndef iswspace +#define iswspace(c) (isascii(c) && isspace(toascii(c))) +#endif +#endif diff --git a/src/XawIm.c b/src/XawIm.c new file mode 100644 index 0000000..ead7166 --- /dev/null +++ b/src/XawIm.c @@ -0,0 +1,1716 @@ +/* $XConsortium: XawIm.c,v 1.6 95/01/20 16:17:21 kaleb Exp $ */ + +/* + * Copyright 1991 by OMRON Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 OMRON not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. OMRON makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + * OMRON 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: Seiji Kuwari OMRON Corporation + * kuwa@omron.co.jp + * kuwa%omron.co.jp@uunet.uu.net + */ + + +/* + +Copyright (c) 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> +#include <X11/Xos.h> +#include <X11/Xfuncs.h> +#include <X11/ShellP.h> +#include <X11/Xaw3d/TextP.h> +#include <X11/Xaw3d/MultiSrc.h> +#include <X11/Xaw3d/MultiSinkP.h> +#include <X11/Xaw3d/XawImP.h> +#include <X11/Xaw3d/VendorEP.h> +#include "XawI18n.h" +#include <ctype.h> + +#if NeedVarargsPrototypes +# include <stdarg.h> +# define Va_start(a,b) va_start(a,b) +#else +# include <varargs.h> +# define Va_start(a,b) va_start(a) +#endif + +#define maxAscentOfFontSet(fontset) \ + ( - (XExtentsOfFontSet((fontset)))->max_logical_extent.y) + +#define maxHeightOfFontSet(fontset) \ + ((XExtentsOfFontSet((fontset)))->max_logical_extent.height) + +#define maxDescentOfFontSet(fontset) \ + (maxHeightOfFontSet(fontset) - maxAscentOfFontSet(fontset)) + +#define Offset(field) (XtOffsetOf(XawIcTablePart, field)) + +/***************************************************** + * + * Forward reference prototypes + * + *****************************************************/ + +static XawIcTableList CurrentSharedIcTable( +#if NeedFunctionPrototypes + XawVendorShellExtPart* /* ve */ +#endif +); + +static void DestroyIC( +#if NeedFunctionPrototypes + Widget /* w */, + XawVendorShellExtPart* /* ve */ +#endif +); + +static XtResource resources[] = +{ + { + XtNfontSet, XtCFontSet, XtRFontSet, sizeof(XFontSet), + Offset (font_set), XtRString, XtDefaultFontSet + }, + { + XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel), + Offset (foreground), XtRString, (XtPointer)"XtDefaultForeground" + }, + { + XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel), + Offset (background), XtRString, (XtPointer)"XtDefaultBackground" + }, + { + XtNbackgroundPixmap, XtCPixmap, XtRPixmap, sizeof(Pixmap), + Offset (bg_pixmap), XtRImmediate, (XtPointer) XtUnspecifiedPixmap + }, + { + XtNinsertPosition, XtCTextPosition, XtRInt, sizeof (XawTextPosition), + Offset (cursor_position), XtRImmediate, (XtPointer) 0 + } +}; +#undef Offset + + +static void SetVaArg( arg, value ) + XPointer *arg, value; +{ + *arg = value; +} + +static VendorShellWidget SearchVendorShell( w ) + Widget w; +{ + while(w && !XtIsShell(w)) w = XtParent(w); + if (w && XtIsVendorShell(w)) return((VendorShellWidget)w); + return(NULL); +} + +static XContext extContext = (XContext)NULL; + +static XawVendorShellExtPart *SetExtPart( w, vew ) + VendorShellWidget w; + XawVendorShellExtWidget vew; +{ + contextDataRec *contextData; + + if (extContext == (XContext)NULL) extContext = XUniqueContext(); + + contextData = XtNew(contextDataRec); + contextData->parent = (Widget)w; + contextData->ve = (Widget)vew; + if (XSaveContext(XtDisplay(w), (Window)w, extContext, (char *)contextData)) { + return(NULL); + } + return(&(vew->vendor_ext)); +} + +static XawVendorShellExtPart *GetExtPart( w ) + VendorShellWidget w; +{ + contextDataRec *contextData; + XawVendorShellExtWidget vew; + + if (XFindContext(XtDisplay(w), (Window)w, extContext, + (XPointer*)&contextData)) { + return(NULL); + } + vew = (XawVendorShellExtWidget)contextData->ve; + return(&(vew->vendor_ext)); +} + +static Boolean IsSharedIC( ve ) + XawVendorShellExtPart * ve; +{ + return( ve->ic.shared_ic ); +} + +static XawIcTableList GetIcTableShared( w, ve ) + Widget w; + XawVendorShellExtPart * ve; +{ + XawIcTableList p; + + for (p = ve->ic.ic_table; p; p = p->next) { + if (p->widget == w) { + if (IsSharedIC(ve)) { + return(ve->ic.shared_ic_table); + } else { + return(p); + } + } + } + return(NULL); +} + +static XawIcTableList GetIcTable( w, ve ) + Widget w; + XawVendorShellExtPart * ve; +{ + XawIcTableList p; + + for (p = ve->ic.ic_table; p; p = p->next) { + if (p->widget == w) { + return(p); + } + } + return(NULL); +} + +static XIMStyle GetInputStyleOfIC( ve ) + XawVendorShellExtPart * ve; +{ + + if (!ve) return((XIMStyle)0); + return(ve->ic.input_style); +} + +static void ConfigureCB( w, closure, event ) + Widget w; + XtPointer closure; + XEvent * event; +{ + XawIcTableList p; + XawVendorShellExtPart *ve; + VendorShellWidget vw; + XVaNestedList pe_attr; + XRectangle pe_area; + XawTextMargin *margin; + + if (event->type != ConfigureNotify) return; + + if ((vw = SearchVendorShell(w)) == NULL) return; + + if ((ve = GetExtPart(vw))) { + if (IsSharedIC(ve)) return; + if ((ve->im.xim == NULL) || + ((p = GetIcTableShared(w, ve)) == NULL) || + (p->xic == NULL) || !(p->input_style & XIMPreeditPosition)) return; + pe_area.x = 0; + pe_area.y = 0; + pe_area.width = w->core.width; + pe_area.height = w->core.height; + margin = &(((TextWidget)w)->text.margin); + pe_area.x += margin->left; + pe_area.y += margin->top; + pe_area.width -= (margin->left + margin->right - 1); + pe_area.height -= (margin->top + margin->bottom - 1); + + pe_attr = XVaCreateNestedList(0, XNArea, &pe_area, NULL); + XSetICValues(p->xic, XNPreeditAttributes, pe_attr, NULL); + XtFree(pe_attr); + } +} + +static XContext errContext = (XContext)NULL; + +static Widget SetErrCnxt( w, xim ) + Widget w; + XIM xim; +{ + contextErrDataRec *contextErrData; + + if (errContext == (XContext)NULL) errContext = XUniqueContext(); + + contextErrData = XtNew(contextErrDataRec); + contextErrData->widget = w; + contextErrData->xim = xim; + if (XSaveContext(XtDisplay(w), (Window)xim, errContext, + (char *)contextErrData)) { + return(NULL); + } + return(contextErrData->widget); +} + +static void CloseIM( ve ) + XawVendorShellExtPart * ve; +{ + if (ve->im.xim) + XCloseIM(ve->im.xim); +} + +static Dimension SetVendorShellHeight( ve, height ) + XawVendorShellExtPart* ve; + Dimension height; +{ + Arg args[2]; + Cardinal i = 0; + + if (ve->im.area_height < height || height == 0) { + XtSetArg(args[i], XtNheight, + (ve->parent->core.height + height - ve->im.area_height)); + ve->im.area_height = height; + XtSetValues(ve->parent, args, 1); + } + return(ve->im.area_height); +} + +static void DestroyAllIM( ve ) + XawVendorShellExtPart * ve; +{ + XawIcTableList p; + contextErrDataRec *contextErrData; + + /* + * Destory all ICs + */ + if (IsSharedIC(ve)) { + if ((p = ve->ic.shared_ic_table) && p->xic) { + DestroyIC(p->widget, ve); + p->xic = NULL; + p->ic_focused = FALSE; + } + } else { + for (p = ve->ic.ic_table; p; p = p->next) { + if (p->xic == NULL) continue; + DestroyIC(p->widget, ve); + p->xic = NULL; + p->ic_focused = FALSE; + } + } + if (!ve->im.xim) return; + /* + * Close Input Method + */ + CloseIM(ve); + if (!XFindContext(XDisplayOfIM(ve->im.xim), (Window)ve->im.xim, errContext, + (XPointer*)&contextErrData)) { + if (contextErrData) XtFree((char *)contextErrData); + } + XDeleteContext(XDisplayOfIM(ve->im.xim), (Window)ve->im.xim, errContext); + ve->im.xim = NULL; + + /* + * resize vendor shell to core size + */ + (void) SetVendorShellHeight(ve, 0); + /* + XawVendorShellExtResize(vw); + */ + return; +} + +static void FreeAllDataOfVendorShell(ve, vw) + XawVendorShellExtPart * ve; + VendorShellWidget vw; +{ + XawIcTableList p, next; + contextErrDataRec *contextErrData; + + if (!XFindContext(XtDisplay(vw), (Window)vw, extContext, + (XPointer*)&contextErrData)) { + if (contextErrData) XtFree((char *)contextErrData); + } + XDeleteContext(XtDisplay(vw), (Window)vw, extContext); + if (ve->ic.shared_ic_table) + XtFree((char *)ve->ic.shared_ic_table); + if (ve->im.resources) XtFree((char *)ve->im.resources); + for (p = ve->ic.ic_table; p; p = next) { + next = p->next; + XtFree((char *)p); + } +} + +static void VendorShellDestroyed( w, cl_data, ca_data ) + Widget w; + XtPointer cl_data, ca_data; +{ + XawVendorShellExtPart *ve; + + if ( ( ve = GetExtPart( (VendorShellWidget) w ) ) == NULL ) return; + DestroyAllIM( ve ); + FreeAllDataOfVendorShell( ve, (VendorShellWidget) w ); + return; +} + +/* + * Attempt to open an input method + */ + +static void OpenIM(ve) + XawVendorShellExtPart * ve; +{ + int i; + char *p, *s, *ns, *end, *pbuf, buf[32]; + XIM xim = NULL; + XIMStyles *xim_styles; + XIMStyle input_style = 0; + Boolean found; + + if (ve->im.open_im == False) return; + ve->im.xim = NULL; + if (ve->im.input_method == NULL) { + if ((p = XSetLocaleModifiers("@im=none")) != NULL && *p) + xim = XOpenIM(XtDisplay(ve->parent), NULL, NULL, NULL); + } else { + /* no fragment can be longer than the whole string */ + int len = strlen (ve->im.input_method) + 5; + + if (len < sizeof buf) pbuf = buf; + else pbuf = XtMalloc (len); + + if (pbuf == NULL) return; + + for(ns=s=ve->im.input_method; ns && *s;) { + /* skip any leading blanks */ + while (*s && isspace(*s)) s++; + if (!*s) break; + if ((ns = end = strchr(s, ',')) == NULL) + end = s + strlen(s); + /* strip any trailing blanks */ + while (isspace(*end)) end--; + + strcpy (pbuf, "@im="); + strncat (pbuf, s, end - s); + pbuf[end - s + 4] = '\0'; + + if ((p = XSetLocaleModifiers(pbuf)) != NULL && *p + && (xim = XOpenIM(XtDisplay(ve->parent), NULL, NULL, NULL)) != NULL) + break; + + s = ns + 1; + } + + if (pbuf != buf) XtFree (pbuf); + } + if (xim == NULL) { + if ((p = XSetLocaleModifiers("")) != NULL) { + xim = XOpenIM(XtDisplay(ve->parent), NULL, NULL, NULL); + } + } + if (xim == NULL) { + XtAppWarning(XtWidgetToApplicationContext(ve->parent), + "Input Method Open Failed"); + return; + } + if (XGetIMValues(xim, XNQueryInputStyle, &xim_styles, NULL) + || !xim_styles) { + XtAppWarning(XtWidgetToApplicationContext(ve->parent), + "input method doesn't support any style"); + XCloseIM(xim); + return; + } + found = False; + for(ns = s = ve->im.preedit_type; s && !found;) { + while (*s && isspace(*s)) s++; + if (!*s) break; + if ((ns = end = strchr(s, ',')) == NULL) + end = s + strlen(s); + while (isspace(*end)) end--; + + if (!strncmp(s, "OverTheSpot", end - s)) { + input_style = (XIMPreeditPosition | XIMStatusArea); + } else if (!strncmp(s, "OffTheSpot", end - s)) { + input_style = (XIMPreeditArea | XIMStatusArea); + } else if (!strncmp(s, "Root", end - s)) { + input_style = (XIMPreeditNothing | XIMStatusNothing); + } + for (i = 0; (unsigned short)i < xim_styles->count_styles; i++) + if (input_style == xim_styles->supported_styles[i]) { + ve->ic.input_style = input_style; + SetErrCnxt(ve->parent, xim); + ve->im.xim = xim; + found = True; + break; + } + + s = ns + 1; + } + XFree(xim_styles); + + if (!found) { + XCloseIM(xim); + XtAppWarning(XtWidgetToApplicationContext(ve->parent), + "input method doesn't support my input style"); + } +} + +static Boolean ResizeVendorShell_Core(vw, ve, p) + VendorShellWidget vw; + XawVendorShellExtPart * ve; + XawIcTableList p; +{ + XVaNestedList pe_attr, st_attr; + XRectangle pe_area, st_area; + XRectangle *get_pe_area = NULL, *get_st_area = NULL; + + st_area.width = 0; + if (p->input_style & XIMStatusArea) { + st_attr = XVaCreateNestedList(0, XNArea, &get_st_area, NULL); + XGetICValues(p->xic, XNStatusAttributes, st_attr, NULL); + XFree(st_attr); + if (p->xic == NULL) { + return(FALSE); + } + st_area.x = 0; + st_area.y = vw->core.height - ve->im.area_height; + st_area.width = get_st_area->width; + st_area.height = get_st_area->height; + XFree(get_st_area); + st_attr = XVaCreateNestedList(0, XNArea, &st_area, NULL); + XSetICValues(p->xic, XNStatusAttributes, st_attr, NULL); + XFree(st_attr); + if (p->xic == NULL) { + return(FALSE); + } + } + if (p->input_style & XIMPreeditArea) { + pe_attr = XVaCreateNestedList(0, XNArea, &get_pe_area, NULL); + XGetICValues(p->xic, XNPreeditAttributes, pe_attr, NULL); + XFree(pe_attr); + if (p->xic == NULL) { + return(FALSE); + } + pe_area.x = st_area.width; + pe_area.y = vw->core.height - ve->im.area_height; + pe_area.width = vw->core.width; + pe_area.height = get_pe_area->height; + if (p->input_style & XIMStatusArea) { + pe_area.width -= st_area.width; + } + XFree(get_pe_area); + pe_attr = XVaCreateNestedList(0, XNArea, &pe_area, NULL); + XSetICValues(p->xic, XNPreeditAttributes, pe_attr, NULL); + XFree(pe_attr); + } + return(TRUE); +} + +static void ResizeVendorShell(vw, ve) + VendorShellWidget vw; + XawVendorShellExtPart * ve; +{ + XawIcTableList p; + + if (IsSharedIC(ve)) { + p = ve->ic.shared_ic_table; + if (p->xic == NULL) return; + ResizeVendorShell_Core(vw, ve, p); + return; + } + for (p = ve->ic.ic_table; p; p = p->next) { + if (p->xic == NULL) continue; + if (ResizeVendorShell_Core(vw, ve, p) == FALSE) return; + } +} + +static XawIcTableList CreateIcTable( w, ve ) + Widget w; + XawVendorShellExtPart * ve; +{ + XawIcTableList table; + + table = (XawIcTableList) XtMalloc(sizeof(XawIcTablePart)); + if (table == NULL) return(NULL); + table->widget = w; + table->xic = NULL; + table->flg = table->prev_flg = 0; + table->font_set = NULL; + table->foreground = table->background = 0xffffffff; + table->bg_pixmap = 0; + table->cursor_position = 0xffff; + table->line_spacing = 0; + table->ic_focused = FALSE; + table->openic_error = FALSE; + return(table); +} + +static Boolean RegisterToVendorShell( w, ve ) + Widget w; + XawVendorShellExtPart * ve; +{ + XawIcTableList table; + + if ((table = CreateIcTable(w, ve)) == NULL) return(FALSE); + table->next = ve->ic.ic_table; + ve->ic.ic_table = table; + return(TRUE); +} + +static void UnregisterFromVendorShell(w, ve) + Widget w; + XawVendorShellExtPart * ve; +{ + XawIcTableList *prev, p; + + for (prev = &ve->ic.ic_table; (p = *prev); prev = &p->next) { + if (p->widget == w) { + *prev = p->next; + XtFree((char *)p); + break; + } + } + return; +} + +static void SetICValuesShared(w, ve, p, check) + Widget w; + XawVendorShellExtPart * ve; + XawIcTableList p; + Boolean check; +{ + XawIcTableList pp; + + if ((pp = GetIcTable(w, ve)) == NULL) return; + if (check == TRUE && CurrentSharedIcTable(ve) != pp) return; + + if (pp->prev_flg & CICursorP && p->cursor_position != pp->cursor_position) { + p->cursor_position = pp->cursor_position; + p->flg |= CICursorP; + } + if (pp->prev_flg & CIFontSet && p->font_set != pp->font_set) { + p->font_set = pp->font_set; + p->flg |= (CIFontSet|CICursorP); + } + if (pp->prev_flg & CIFg && p->foreground != pp->foreground) { + p->foreground = pp->foreground; + p->flg |= CIFg; + } + if (pp->prev_flg & CIBg && p->background != pp->background) { + p->background = pp->background; + p->flg |= CIBg; + } + if (pp->prev_flg & CIBgPixmap && p->bg_pixmap != pp->bg_pixmap) { + p->bg_pixmap = pp->bg_pixmap; + p->flg |= CIBgPixmap; + } + if (pp->prev_flg & CILineS && p->line_spacing != pp->line_spacing) { + p->line_spacing = pp->line_spacing; + p->flg |= CILineS; + } +} + +static Boolean IsCreatedIC(w, ve) + Widget w; + XawVendorShellExtPart * ve; +{ + XawIcTableList p; + + if (ve->im.xim == NULL) return(FALSE); + if ((p = GetIcTableShared(w, ve)) == NULL) return(FALSE); + if (p->xic == NULL) return(FALSE); + return(TRUE); +} + +static void SizeNegotiation(p, width, height) + XawIcTableList p; + Dimension width, height; +{ + XRectangle pe_area, st_area; + XVaNestedList pe_attr = NULL, st_attr = NULL; + int ic_cnt = 0, pe_cnt = 0, st_cnt = 0; + XRectangle *pe_area_needed = NULL, *st_area_needed = NULL; + XPointer ic_a[5]; + + if (p->input_style & XIMPreeditArea) { + pe_attr = XVaCreateNestedList(0, XNAreaNeeded, &pe_area_needed, NULL); + SetVaArg( &ic_a[ic_cnt], (XPointer) XNPreeditAttributes); ic_cnt++; + SetVaArg( &ic_a[ic_cnt], (XPointer) pe_attr); ic_cnt++; + } + if (p->input_style & XIMStatusArea) { + st_attr = XVaCreateNestedList(0, XNAreaNeeded, &st_area_needed, NULL); + SetVaArg( &ic_a[ic_cnt], (XPointer) XNStatusAttributes); ic_cnt++; + SetVaArg( &ic_a[ic_cnt], (XPointer) st_attr); ic_cnt++; + } + SetVaArg( &ic_a[ic_cnt], (XPointer) NULL); + + if (ic_cnt > 0) { + XGetICValues(p->xic, ic_a[0], ic_a[1], ic_a[2], ic_a[3], ic_a[4]); + if (pe_attr) XFree(pe_attr); + if (st_attr) XFree(st_attr); + if (p->xic == NULL) { + p->openic_error = True; + return; + } + pe_attr = st_attr = NULL; + ic_cnt = pe_cnt = st_cnt = 0; + if (p->input_style & XIMStatusArea) { + st_area.height = st_area_needed->height; + st_area.x = 0; + st_area.y = height - st_area.height; + if (p->input_style & XIMPreeditArea) { + st_area.width = st_area_needed->width; + } else { + st_area.width = width; + } + + XFree(st_area_needed); + st_attr = XVaCreateNestedList(0, XNArea, &st_area, NULL); + SetVaArg( &ic_a[ic_cnt], (XPointer) XNStatusAttributes); ic_cnt++; + SetVaArg( &ic_a[ic_cnt], (XPointer) st_attr); ic_cnt++; + } + if (p->input_style & XIMPreeditArea) { + if (p->input_style & XIMStatusArea) { + pe_area.x = st_area.width; + pe_area.width = width - st_area.width; + } else { + pe_area.x = 0; + pe_area.width = width; + } + pe_area.height = pe_area_needed->height; + XFree(pe_area_needed); + pe_area.y = height - pe_area.height; + pe_attr = XVaCreateNestedList(0, XNArea, &pe_area, NULL); + SetVaArg( &ic_a[ic_cnt], (XPointer) XNPreeditAttributes); ic_cnt++; + SetVaArg( &ic_a[ic_cnt], (XPointer) pe_attr); ic_cnt++; + } + SetVaArg( &ic_a[ic_cnt], (XPointer) NULL); + XSetICValues(p->xic, ic_a[0], ic_a[1], ic_a[2], ic_a[3], ic_a[4]); + if (pe_attr) XFree(pe_attr); + if (st_attr) XFree(st_attr); + if (p->xic == NULL) { + p->openic_error = True; + return; + } + } +} + +static void CreateIC( w, ve ) + Widget w; + XawVendorShellExtPart* ve; +{ + XawIcTableList p; + XPoint position; + XRectangle pe_area, st_area; + XVaNestedList pe_attr = NULL, st_attr = NULL; + XPointer ic_a[20], pe_a[20], st_a[20]; + Dimension height = 0; + int ic_cnt = 0, pe_cnt = 0, st_cnt = 0; + XawTextMargin *margin; + + if (!XtIsRealized(w)) return; + if (((ve->im.xim == NULL) || (p = GetIcTableShared(w, ve)) == NULL) || + p->xic || (p->openic_error != FALSE)) return; + + p->input_style = GetInputStyleOfIC(ve); + + if (IsSharedIC(ve)) SetICValuesShared(w, ve, p, FALSE); + XFlush(XtDisplay(w)); + + if (p->input_style & (XIMPreeditArea|XIMPreeditPosition|XIMStatusArea)) { + if (p->flg & CIFontSet) { + SetVaArg( &pe_a[pe_cnt], (XPointer) XNFontSet); pe_cnt++; + SetVaArg( &pe_a[pe_cnt], (XPointer) p->font_set); pe_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) XNFontSet); st_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) p->font_set); st_cnt++; + height = maxAscentOfFontSet(p->font_set) + + maxDescentOfFontSet(p->font_set); + height = SetVendorShellHeight(ve, height); + } + if (p->flg & CIFg) { + SetVaArg( &pe_a[pe_cnt], (XPointer) XNForeground); pe_cnt++; + SetVaArg( &pe_a[pe_cnt], (XPointer) p->foreground); pe_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) XNForeground); st_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) p->foreground); st_cnt++; + } + if (p->flg & CIBg) { + SetVaArg( &pe_a[pe_cnt], (XPointer) XNBackground); pe_cnt++; + SetVaArg( &pe_a[pe_cnt], (XPointer) p->background); pe_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) XNBackground); st_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) p->background); st_cnt++; + } + if (p->flg & CIBgPixmap) { + SetVaArg( &pe_a[pe_cnt], (XPointer) XNBackgroundPixmap); pe_cnt++; + SetVaArg( &pe_a[pe_cnt], (XPointer) p->bg_pixmap); pe_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) XNBackgroundPixmap); st_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) p->bg_pixmap); st_cnt++; + } + if (p->flg & CILineS) { + SetVaArg( &pe_a[pe_cnt], (XPointer) XNLineSpace); pe_cnt++; + SetVaArg( &pe_a[pe_cnt], (XPointer) p->line_spacing); pe_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) XNLineSpace); st_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) p->line_spacing); st_cnt++; + } + } + if (p->input_style & XIMPreeditArea) { + pe_area.x = 0; + pe_area.y = ve->parent->core.height - height; + pe_area.width = ve->parent->core.width; + pe_area.height = height; + SetVaArg( &pe_a[pe_cnt], (XPointer) XNArea); pe_cnt++; + SetVaArg( &pe_a[pe_cnt], (XPointer) &pe_area); pe_cnt++; + } + if (p->input_style & XIMPreeditPosition) { + pe_area.x = 0; + pe_area.y = 0; + pe_area.width = w->core.width; + pe_area.height = w->core.height; + margin = &(((TextWidget)w)->text.margin); + pe_area.x += margin->left; + pe_area.y += margin->top; + pe_area.width -= (margin->left + margin->right - 1); + pe_area.height -= (margin->top + margin->bottom - 1); + SetVaArg( &pe_a[pe_cnt], (XPointer) XNArea); pe_cnt++; + SetVaArg( &pe_a[pe_cnt], (XPointer) &pe_area); pe_cnt++; + if (p->flg & CICursorP) { + _XawMultiSinkPosToXY(w, p->cursor_position, &position.x, &position.y); + } else { + position.x = position.y = 0; + } + SetVaArg( &pe_a[pe_cnt], (XPointer) XNSpotLocation); pe_cnt++; + SetVaArg( &pe_a[pe_cnt], (XPointer) &position); pe_cnt++; + } + if (p->input_style & XIMStatusArea) { + st_area.x = 0; + st_area.y = ve->parent->core.height - height; + st_area.width = ve->parent->core.width; + st_area.height = height; + SetVaArg( &st_a[st_cnt], (XPointer) XNArea); st_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) &st_area); st_cnt++; + } + + SetVaArg( &ic_a[ic_cnt], (XPointer) XNInputStyle); ic_cnt++; + SetVaArg( &ic_a[ic_cnt], (XPointer) p->input_style); ic_cnt++; + SetVaArg( &ic_a[ic_cnt], (XPointer) XNClientWindow); ic_cnt++; + SetVaArg( &ic_a[ic_cnt], (XPointer) XtWindow(ve->parent)); ic_cnt++; + SetVaArg( &ic_a[ic_cnt], (XPointer) XNFocusWindow); ic_cnt++; + SetVaArg( &ic_a[ic_cnt], (XPointer) XtWindow(w)); ic_cnt++; + + if (pe_cnt > 0) { + SetVaArg( &pe_a[pe_cnt], (XPointer) NULL); + pe_attr = XVaCreateNestedList(0, pe_a[0], pe_a[1], pe_a[2], pe_a[3], + pe_a[4], pe_a[5], pe_a[6], pe_a[7], pe_a[8], + pe_a[9], pe_a[10], pe_a[11], pe_a[12], + pe_a[13], pe_a[14], pe_a[15], pe_a[16], + pe_a[17], pe_a[18], pe_a[19]); + SetVaArg( &ic_a[ic_cnt], (XPointer) XNPreeditAttributes); ic_cnt++; + SetVaArg( &ic_a[ic_cnt], (XPointer) pe_attr); ic_cnt++; + } + + if (st_cnt > 0) { + SetVaArg( &st_a[st_cnt], (XPointer) NULL); + st_attr = XVaCreateNestedList(0, st_a[0], st_a[1], st_a[2], st_a[3], + st_a[4], st_a[5], st_a[6], st_a[7], st_a[8], + st_a[9], st_a[10], st_a[11], st_a[12], + st_a[13], st_a[14], st_a[15], st_a[16], + st_a[17], st_a[18], st_a[19]); + SetVaArg( &ic_a[ic_cnt], (XPointer) XNStatusAttributes); ic_cnt++; + SetVaArg( &ic_a[ic_cnt], (XPointer) st_attr); ic_cnt++; + } + SetVaArg( &ic_a[ic_cnt], (XPointer) NULL); + + p->xic = XCreateIC(ve->im.xim, ic_a[0], ic_a[1], ic_a[2], ic_a[3], + ic_a[4], ic_a[5], ic_a[6], ic_a[7], ic_a[8], ic_a[9], + ic_a[10], ic_a[11], ic_a[12], ic_a[13], ic_a[14], + ic_a[15], ic_a[16], ic_a[17], ic_a[18], ic_a[19]); + if (pe_attr) XtFree(pe_attr); + if (st_attr) XtFree(st_attr); + + if (p->xic == NULL) { + p->openic_error = True; + return; + } + + SizeNegotiation(p, ve->parent->core.width, ve->parent->core.height); + + p->flg &= ~(CIFontSet | CIFg | CIBg | CIBgPixmap | CICursorP | CILineS); + + if (!IsSharedIC(ve)) { + if (p->input_style & XIMPreeditPosition) { + XtAddEventHandler(w, (EventMask)StructureNotifyMask, FALSE, + (XtEventHandler)ConfigureCB, (Opaque)NULL); + } + } +} + +static void SetICValues( w, ve, focus ) + Widget w; + XawVendorShellExtPart *ve; + Boolean focus; +{ + XawIcTableList p; + XPoint position; + XRectangle pe_area; + XVaNestedList pe_attr = NULL, st_attr = NULL; + XPointer ic_a[20], pe_a[20], st_a[20]; + int ic_cnt = 0, pe_cnt = 0, st_cnt = 0; + XawTextMargin *margin; + int height; + + if ((ve->im.xim == NULL) || ((p = GetIcTableShared(w, ve)) == NULL) || + (p->xic == NULL)) return; + + if (IsSharedIC(ve)) SetICValuesShared(w, ve, p, TRUE); + XFlush(XtDisplay(w)); + if (focus == FALSE && + !(p->flg & (CIFontSet | CIFg | CIBg | + CIBgPixmap | CICursorP | CILineS))) return; +#ifdef SPOT + if ((p->input_style & XIMPreeditPosition) + && ((!IsSharedIC(ve) && ((p->flg & ~CIICFocus) == CICursorP)) + || (IsSharedIC(ve) && p->flg == CICursorP))) { + _XawMultiSinkPosToXY(w, p->cursor_position, &position.x, &position.y); + _XipChangeSpot(p->xic, position.x, position.y); + p->flg &= ~CICursorP; + return; + } +#endif + + if (p->input_style & (XIMPreeditArea|XIMPreeditPosition|XIMStatusArea)) { + if (p->flg & CIFontSet) { + SetVaArg( &pe_a[pe_cnt], (XPointer) XNFontSet); pe_cnt++; + SetVaArg( &pe_a[pe_cnt], (XPointer) p->font_set); pe_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) XNFontSet); st_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) p->font_set); st_cnt++; + height = maxAscentOfFontSet(p->font_set) + + maxDescentOfFontSet(p->font_set); + height = SetVendorShellHeight(ve, height); + } + if (p->flg & CIFg) { + SetVaArg( &pe_a[pe_cnt], (XPointer) XNForeground); pe_cnt++; + SetVaArg( &pe_a[pe_cnt], (XPointer) p->foreground); pe_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) XNForeground); st_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) p->foreground); st_cnt++; + } + if (p->flg & CIBg) { + SetVaArg( &pe_a[pe_cnt], (XPointer) XNBackground); pe_cnt++; + SetVaArg( &pe_a[pe_cnt], (XPointer) p->background); pe_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) XNBackground); st_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) p->background); st_cnt++; + } + if (p->flg & CIBgPixmap) { + SetVaArg( &pe_a[pe_cnt], (XPointer) XNBackgroundPixmap); pe_cnt++; + SetVaArg( &pe_a[pe_cnt], (XPointer) p->bg_pixmap); pe_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) XNBackgroundPixmap); st_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) p->bg_pixmap); st_cnt++; + } + if (p->flg & CILineS) { + SetVaArg( &pe_a[pe_cnt], (XPointer) XNLineSpace); pe_cnt++; + SetVaArg( &pe_a[pe_cnt], (XPointer) p->line_spacing); pe_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) XNLineSpace); st_cnt++; + SetVaArg( &st_a[st_cnt], (XPointer) p->line_spacing); st_cnt++; + } + } + if (p->input_style & XIMPreeditPosition) { + if (p->flg & CICursorP) { + _XawMultiSinkPosToXY(w, p->cursor_position, &position.x, &position.y); + SetVaArg( &pe_a[pe_cnt], (XPointer) XNSpotLocation); pe_cnt++; + SetVaArg( &pe_a[pe_cnt], (XPointer) &position); pe_cnt++; + } + } + if (IsSharedIC(ve)) { + if (p->input_style & XIMPreeditPosition) { + pe_area.x = 0; + pe_area.y = 0; + pe_area.width = w->core.width; + pe_area.height = w->core.height; + margin = &(((TextWidget)w)->text.margin); + pe_area.x += margin->left; + pe_area.y += margin->top; + pe_area.width -= (margin->left + margin->right - 1); + pe_area.height -= (margin->top + margin->bottom - 1); + SetVaArg( &pe_a[pe_cnt], (XPointer) XNArea); pe_cnt++; + SetVaArg( &pe_a[pe_cnt], (XPointer) &pe_area); pe_cnt++; + } + } + + if (pe_cnt > 0) { + SetVaArg( &pe_a[pe_cnt], (XPointer) NULL); + pe_attr = XVaCreateNestedList(0, pe_a[0], pe_a[1], pe_a[2], pe_a[3], + pe_a[4], pe_a[5], pe_a[6], pe_a[7], + pe_a[8], pe_a[9], pe_a[10], pe_a[11], + pe_a[12], pe_a[13], pe_a[14], pe_a[15], + pe_a[16], pe_a[17], pe_a[18], pe_a[19]); + SetVaArg( &ic_a[ic_cnt], (XPointer) XNPreeditAttributes); ic_cnt++; + SetVaArg( &ic_a[ic_cnt], (XPointer) pe_attr); ic_cnt++; + } + if (st_cnt > 0) { + SetVaArg( &st_a[st_cnt], (XPointer) NULL); + st_attr = XVaCreateNestedList(0, st_a[0], st_a[1], st_a[2], st_a[3], + st_a[4], st_a[5], st_a[6], st_a[7], + st_a[8], st_a[9], st_a[10], st_a[11], + st_a[12], st_a[13], st_a[14], st_a[15], + st_a[16], st_a[17], st_a[18], st_a[19]); + SetVaArg( &ic_a[ic_cnt], (XPointer) XNStatusAttributes); ic_cnt++; + SetVaArg( &ic_a[ic_cnt], (XPointer) st_attr); ic_cnt++; + } + if (focus == TRUE) { + SetVaArg( &ic_a[ic_cnt], (XPointer) XNFocusWindow); ic_cnt++; + SetVaArg( &ic_a[ic_cnt], (XPointer) XtWindow(w)); ic_cnt++; + } + if (ic_cnt > 0) { + SetVaArg( &ic_a[ic_cnt], (XPointer) NULL); + XSetICValues(p->xic, ic_a[0], ic_a[1], ic_a[2], ic_a[3], ic_a[4], + ic_a[5], ic_a[6], ic_a[7], ic_a[8], ic_a[9], ic_a[10], + ic_a[11], ic_a[12], ic_a[13], ic_a[14], ic_a[15], + ic_a[16], ic_a[17], ic_a[18], ic_a[19]); + if (pe_attr) XtFree(pe_attr); + if (st_attr) XtFree(st_attr); + } + + if (IsSharedIC(ve) && p->flg & CIFontSet) + SizeNegotiation(p, ve->parent->core.width, ve->parent->core.height); + + p->flg &= ~(CIFontSet | CIFg | CIBg | CIBgPixmap | CICursorP | CILineS); +} + +static void SharedICChangeFocusWindow(w, ve, p) + Widget w; + XawVendorShellExtPart *ve; + XawIcTableList p; +{ + XawIcTableList pp; + + if (w == NULL) { + ve->ic.current_ic_table = NULL; + return; + } + if ((pp = GetIcTable(w, ve)) == NULL) return; + ve->ic.current_ic_table = pp; + SetICValues(w, ve, TRUE); +} + +static XawIcTableList CurrentSharedIcTable( ve ) + XawVendorShellExtPart * ve; +{ + return(ve->ic.current_ic_table); +} + +static void SetICFocus(w, ve) + Widget w; + XawVendorShellExtPart * ve; +{ + XawIcTableList p, pp; + + if ((ve->im.xim == NULL) || ((p = GetIcTableShared(w, ve)) == NULL) || + (p->xic == NULL)) return; + + if (IsSharedIC(ve)) { + pp = CurrentSharedIcTable(ve); + if (pp == NULL || pp->widget != w) { + SharedICChangeFocusWindow(w, ve, p); + } + } + if (p->flg & CIICFocus && p->ic_focused == FALSE) { + p->ic_focused = TRUE; + XSetICFocus(p->xic); + } + p->flg &= ~CIICFocus; +} + +static void UnsetICFocus(w, ve) + Widget w; + XawVendorShellExtPart * ve; +{ + XawIcTableList p, pp; + + if ((ve->im.xim == NULL) || ((p = GetIcTableShared(w, ve)) == NULL) || + (p->xic == NULL)) return; + + if (IsSharedIC(ve) && (pp = CurrentSharedIcTable(ve))) { + if (pp->widget != w) { + return; + } + SharedICChangeFocusWindow(NULL, ve, p); + } + if (p->ic_focused == TRUE) { + XUnsetICFocus(p->xic); + p->ic_focused = FALSE; + } +} + +static void SetValues( w, ve, args, num_args ) + Widget w; + XawVendorShellExtPart * ve; + ArgList args; + Cardinal num_args; +{ + ArgList arg; + + XrmName argName; + XrmResourceList xrmres; + int i; + XawIcTablePart *p, save_tbl; + + if ((p = GetIcTable(w, ve)) == NULL) return; + + memcpy(&save_tbl, p, sizeof(XawIcTablePart)); + + for (arg = args ; num_args != 0; num_args--, arg++) { + argName = XrmStringToName(arg->name); + for (xrmres = (XrmResourceList)ve->im.resources, i = 0; + i < ve->im.num_resources; i++, xrmres++) { + if (argName == xrmres->xrm_name) { + _XtCopyFromArg(arg->value, + (char *)p - xrmres->xrm_offset - 1, + xrmres->xrm_size); + break; + } + } + } + if (p->font_set != save_tbl.font_set) { + p->flg |= CIFontSet; + } + if (p->foreground != save_tbl.foreground) { + p->flg |= CIFg; + } + if (p->background !=save_tbl.background) { + p->flg |= CIBg; + } + if (p->bg_pixmap != save_tbl.bg_pixmap) { + p->flg |= CIBgPixmap; + } + if (p->cursor_position != save_tbl.cursor_position) { + p->flg |= CICursorP; + } + if (p->line_spacing != save_tbl.line_spacing) { + p->flg |= CILineS; + } + p->prev_flg |= p->flg; +} + +static void SetFocus( w, ve ) + Widget w; + XawVendorShellExtPart *ve; +{ + XawIcTableList p; + if ((p = GetIcTableShared(w, ve)) == NULL) return; + + if ( p->ic_focused == FALSE || IsSharedIC(ve)) { + p->flg |= CIICFocus; + } + p->prev_flg |= p->flg; +} + +static void DestroyIC(w, ve) + Widget w; + XawVendorShellExtPart *ve; +{ + XawIcTableList p; + + if ((ve->im.xim == NULL) || ((p = GetIcTableShared(w, ve)) == NULL) || + (p->xic == NULL)) return; + if (IsSharedIC(ve)) { + if (GetIcTable(w, ve) == ve->ic.current_ic_table) { + UnsetICFocus(w, ve); + } + return; + } + XDestroyIC(p->xic); + if (!IsSharedIC(ve)) { + if (p->input_style & XIMPreeditPosition) { + XtRemoveEventHandler(w, (EventMask)StructureNotifyMask, FALSE, + (XtEventHandler)ConfigureCB, (Opaque)NULL); + } + } +} + +static void SetFocusValues( inwidg, args, num_args, focus ) + Widget inwidg; + ArgList args; + Cardinal num_args; + Boolean focus; +{ + XawVendorShellExtPart *ve; + VendorShellWidget vw; + + if ((vw = SearchVendorShell(inwidg)) == NULL) return; + if ((ve = GetExtPart(vw))) { + if (num_args > 0) SetValues(inwidg, ve, args, num_args); + if (focus) SetFocus(inwidg, ve); + if (XtIsRealized((Widget)vw) && ve->im.xim) { + if (IsCreatedIC(inwidg, ve)) { + SetICValues(inwidg, ve, FALSE); + if (focus) SetICFocus(inwidg, ve); + } else { + CreateIC(inwidg, ve); + SetICFocus(inwidg, ve); + } + } + } +} + +static void UnsetFocus( inwidg ) + Widget inwidg; +{ + XawVendorShellExtPart *ve; + VendorShellWidget vw; + XawIcTableList p; + + if ((vw = SearchVendorShell(inwidg)) == NULL) return; + if ((ve = GetExtPart(vw))) { + if ((p = GetIcTableShared(inwidg, ve)) == NULL) return; + if (p->flg & CIICFocus) { + p->flg &= ~CIICFocus; + } + p->prev_flg &= ~CIICFocus; + if (ve->im.xim && XtIsRealized((Widget)vw) && p->xic) { + UnsetICFocus(inwidg, ve); + } + } +} + +static Boolean IsRegistered( w, ve ) + Widget w; + XawVendorShellExtPart* ve; +{ + XawIcTableList p; + + for (p = ve->ic.ic_table; p; p = p->next) + { + if (p->widget == w) return(TRUE); + } + return(FALSE); +} + +static void Register(inwidg, ve) + Widget inwidg; + XawVendorShellExtPart* ve; +{ + if (ve->im.xim == NULL) + { + OpenIM(ve); + } + + if (IsRegistered(inwidg, ve)) return; + + if (RegisterToVendorShell(inwidg, ve) == FALSE) return; + + if (ve->im.xim == NULL) return; + + if (XtIsRealized(ve->parent)) + { + CreateIC(inwidg, ve); + SetICFocus(inwidg, ve); + } +} + +static Boolean NoRegistered(ve) + XawVendorShellExtPart* ve; +{ + if (ve->ic.ic_table == NULL) return(TRUE); + return(FALSE); +} + +static void Unregister(inwidg, ve) + Widget inwidg; + XawVendorShellExtPart* ve; +{ + if (!IsRegistered(inwidg, ve)) return; + + DestroyIC(inwidg, ve); + + UnregisterFromVendorShell(inwidg, ve); + + if (NoRegistered(ve)) + { + CloseIM(ve); + ve->im.xim = NULL; + /* + * resize vendor shell to core size + */ + (void) SetVendorShellHeight(ve, 0); + } +} + +static void AllCreateIC( ve ) + XawVendorShellExtPart* ve; +{ + XawIcTableList p; + + if (ve->im.xim == NULL) return; + if (IsSharedIC(ve) && ve->ic.ic_table[0].widget) { + p = ve->ic.shared_ic_table; + if (p->xic == NULL) + CreateIC(ve->ic.ic_table[0].widget, ve); + SetICFocus(ve->ic.ic_table[0].widget, ve); + return; + } + for (p = ve->ic.ic_table; p; p = p->next) { + if (p->xic == NULL) + CreateIC(p->widget, ve); + } + for (p = ve->ic.ic_table; p; p = p->next) { + SetICFocus(p->widget, ve); + } +} + + +static void Reconnect(ve) + XawVendorShellExtPart* ve; +{ + XawIcTableList p; + + ve->im.open_im = True; + if (ve->im.xim == NULL) { + OpenIM(ve); + } + if (ve->im.xim == NULL) return; + + if (IsSharedIC(ve)) { + p = ve->ic.shared_ic_table; + p->flg = p->prev_flg; + p->openic_error = FALSE; + } else { + for (p = ve->ic.ic_table; p; p = p->next) { + p->flg = p->prev_flg; + p->openic_error = FALSE; + } + } + AllCreateIC(ve); +} + + +static void CompileResourceList( res, num_res ) + XtResourceList res; + unsigned int num_res; +{ + unsigned int count; + +#define xrmres ((XrmResourceList) res) + for (count = 0; count < num_res; res++, count++) { + xrmres->xrm_name = XrmPermStringToQuark(res->resource_name); + xrmres->xrm_class = XrmPermStringToQuark(res->resource_class); + xrmres->xrm_type = XrmPermStringToQuark(res->resource_type); + xrmres->xrm_offset = -res->resource_offset - 1; + xrmres->xrm_default_type = XrmPermStringToQuark(res->default_type); + } +#undef xrmres +} + +static Boolean Initialize( vw, ve ) + VendorShellWidget vw; + XawVendorShellExtPart* ve; +{ + int i; + + if (!XtIsVendorShell((Widget)vw)) return(FALSE); + ve->parent = (Widget)vw; + ve->im.xim = NULL; + ve->im.area_height = 0; + ve->im.resources = (XrmResourceList)XtMalloc(sizeof(resources)); + if (ve->im.resources == NULL) return(FALSE); + memcpy((char *)ve->im.resources, (char *)resources, sizeof(resources)); + ve->im.num_resources = XtNumber(resources); + CompileResourceList( (XtResourceList) ve->im.resources, + ve->im.num_resources ); + if ((ve->ic.shared_ic_table = CreateIcTable( (Widget)vw, ve)) == NULL) + return(FALSE); + ve->ic.current_ic_table = NULL; + ve->ic.ic_table = NULL; + return(TRUE); +} + + +/* Destroy() + * + * This frees all (most?) of the resources malloced by XawIm. + * It is called by _XawImDestroy, which is called by Vendor.c's + * VendorExt's Destroy method. Sheeran, Omron KK, 93/08/05 */ + +static void Destroy( w, ve ) + Widget w; + XawVendorShellExtPart* ve; +{ + contextDataRec *contextData; + contextErrDataRec *contextErrData; + + if (!XtIsVendorShell( w ) ) + return; + XtFree( (char*) ve->im.resources ); + + if (extContext != (XContext)NULL && + !XFindContext (XtDisplay (w), (Window)w, + extContext, (XPointer*)&contextData)) + XtFree( (char*) contextData ); + + if (errContext != (XContext)NULL && + !XFindContext (XDisplayOfIM( ve->im.xim ), (Window) ve->im.xim, + errContext, (XPointer*) &contextErrData)) + XtFree( (char*) contextErrData ); +} + +/********************************************* + * + * SEMI-PRIVATE FUNCTIONS + * For use by other Xaw modules + * + ********************************************/ + +void +#if NeedFunctionPrototypes +_XawImResizeVendorShell( + Widget w ) +#else +_XawImResizeVendorShell( w ) + Widget w; +#endif +{ + XawVendorShellExtPart *ve; + + if ( ( ve = GetExtPart( (VendorShellWidget) w ) ) && ve->im.xim ) { + ResizeVendorShell( (VendorShellWidget) w, ve ); + } +} + + +Dimension +#if NeedFunctionPrototypes +_XawImGetShellHeight( + Widget w ) +#else +_XawImGetShellHeight( w ) + Widget w; +#endif +{ + XawVendorShellExtPart *ve; + + if (!XtIsVendorShell( w ) ) return( w->core.height ); + if ((ve = GetExtPart( (VendorShellWidget) w ))) { + return( w->core.height - ve->im.area_height ); + } + return( w->core.height ); +} + +void +#if NeedFunctionPrototypes +_XawImRealize( + Widget w ) +#else +_XawImRealize( w ) + Widget w; +#endif +{ + XawVendorShellExtPart *ve; + extern void XawVendorShellExtResize(); + + if ( !XtIsRealized( w ) || !XtIsVendorShell( w ) ) return; + if ((ve = GetExtPart( (VendorShellWidget) w ))) { + XtAddEventHandler( w, (EventMask)StructureNotifyMask, FALSE, + XawVendorShellExtResize, (XtPointer)NULL ); + AllCreateIC(ve); + } +} + +void +#if NeedFunctionPrototypes +_XawImInitialize( + Widget w, + Widget ext ) +#else +_XawImInitialize( w, ext ) + Widget w, ext; +#endif +{ + XawVendorShellExtPart *ve; + + if ( !XtIsVendorShell( w ) ) return; + if ((ve = SetExtPart( (VendorShellWidget) w, (XawVendorShellExtWidget)ext)) ) { + if ( Initialize( (VendorShellWidget) w, ve ) == FALSE ) return; + XtAddCallback( w, XtNdestroyCallback, VendorShellDestroyed, + (XtPointer) NULL ); + } +} + +void +#if NeedFunctionPrototypes +_XawImReconnect( + Widget inwidg ) +#else +_XawImReconnect( inwidg ) + Widget inwidg; +#endif +{ + XawVendorShellExtPart *ve; + VendorShellWidget vw; + + if ((vw = SearchVendorShell(inwidg)) == NULL) return; + if ((ve = GetExtPart(vw))) { + Reconnect(ve); + } +} + +void +#if NeedFunctionPrototypes +_XawImRegister( + Widget inwidg) +#else +_XawImRegister(inwidg) + Widget inwidg; +#endif +{ + XawVendorShellExtPart *ve; + VendorShellWidget vw; + + if ((vw = SearchVendorShell(inwidg)) == NULL) return; + if ((ve = GetExtPart(vw))) { + Register(inwidg, ve); + } +} + +void +#if NeedFunctionPrototypes +_XawImUnregister( + Widget inwidg) +#else +_XawImUnregister(inwidg) + Widget inwidg; +#endif +{ + XawVendorShellExtPart *ve; + VendorShellWidget vw; + + if ((vw = SearchVendorShell(inwidg)) == NULL) return; + if ((ve = GetExtPart(vw))) { + Unregister(inwidg, ve); + } +} + +void +#if NeedFunctionPrototypes +_XawImSetValues( + Widget inwidg, + ArgList args, + Cardinal num_args ) +#else +_XawImSetValues( inwidg, args, num_args ) + Widget inwidg; + ArgList args; + Cardinal num_args; +#endif +{ + SetFocusValues( inwidg, args, num_args, FALSE ); +} + +void +#if NeedVarargsPrototypes +_XawImVASetValues( Widget inwidg, ... ) +#else +_XawImVASetValues( inwidg, va_alist ) + Widget inwidg; + va_dcl +#endif +{ + va_list var; + ArgList args = NULL; + Cardinal num_args; + int total_count, typed_count; + + Va_start( var, inwidg ); + _XtCountVaList( var, &total_count, &typed_count ); + va_end( var ); + + Va_start( var, inwidg ); + + _XtVaToArgList( inwidg, var, total_count, &args, &num_args ); + _XawImSetValues( inwidg, args, num_args ); + if ( args != NULL ) { + XtFree( (XtPointer) args ); + } + va_end( var ); +} + +void +#if NeedFunctionPrototypes +_XawImSetFocusValues( + Widget inwidg, + ArgList args, + Cardinal num_args) +#else +_XawImSetFocusValues(inwidg, args, num_args) + Widget inwidg; + ArgList args; + Cardinal num_args; +#endif +{ + SetFocusValues(inwidg, args, num_args, TRUE); +} + +void +#if NeedVarargsPrototypes +_XawImVASetFocusValues(Widget inwidg, ...) +#else +_XawImVASetFocusValues(inwidg, va_alist) + Widget inwidg; + va_dcl +#endif +{ + va_list var; + ArgList args = NULL; + Cardinal num_args; + int total_count, typed_count; + + Va_start(var, inwidg); + _XtCountVaList(var, &total_count, &typed_count); + va_end(var); + + Va_start(var,inwidg); + + _XtVaToArgList(inwidg, var, total_count, &args, &num_args); + _XawImSetFocusValues(inwidg, args, num_args); + if (args != NULL) { + XtFree((XtPointer)args); + } + va_end(var); +} + +void +#if NeedFunctionPrototypes +_XawImUnsetFocus( + Widget inwidg) +#else +_XawImUnsetFocus(inwidg) + Widget inwidg; +#endif +{ + UnsetFocus(inwidg); +} + +int +#if NeedFunctionPrototypes +_XawImWcLookupString( + Widget inwidg, + XKeyPressedEvent *event, + wchar_t* buffer_return, + int bytes_buffer, + KeySym *keysym_return, + Status *status_return) +#else +_XawImWcLookupString( inwidg, event, buffer_return, bytes_buffer, + keysym_return, status_return) + Widget inwidg; + XKeyPressedEvent* event; + wchar_t* buffer_return; + int bytes_buffer; + KeySym* keysym_return; + Status* status_return; +#endif +{ + XawVendorShellExtPart* ve; + VendorShellWidget vw; + XawIcTableList p; + int i, ret; + char tmp_buf[64], *tmp_p; + wchar_t* buf_p; + + if ((vw = SearchVendorShell(inwidg)) && (ve = GetExtPart(vw)) && + ve->im.xim && (p = GetIcTableShared(inwidg, ve)) && p->xic) { + return(XwcLookupString(p->xic, event, buffer_return, bytes_buffer, + keysym_return, status_return)); + } + ret = XLookupString( event, tmp_buf, 64, keysym_return, + (XComposeStatus*) status_return ); + for ( i = 0, tmp_p = tmp_buf, buf_p = buffer_return; i < ret; i++ ) { + *buf_p++ = _Xaw_atowc(*tmp_p++); + } + return( ret ); +} + +int +#if NeedFunctionPrototypes +_XawImGetImAreaHeight( + Widget w) +#else +_XawImGetImAreaHeight( w ) + Widget w; +#endif +{ + XawVendorShellExtPart *ve; + VendorShellWidget vw; + + if ((vw = SearchVendorShell(w)) && (ve = GetExtPart(vw))) { + return(ve->im.area_height); + } + return(0); +} + +void +#if NeedFunctionPrototypes +_XawImCallVendorShellExtResize( + Widget w) +#else +_XawImCallVendorShellExtResize( w ) + Widget w; +#endif +{ + XawVendorShellExtPart *ve; + VendorShellWidget vw; + extern void XawVendorShellExtResize(); + + if ((vw = SearchVendorShell(w)) && (ve = GetExtPart(vw))) { + XawVendorShellExtResize(vw); + } +} + + +/* _XawImDestroy() + * + * This should be called by the VendorExt from its + * core Destroy method. Sheeran, Omron KK 93/08/05 */ + +void +#if NeedFunctionPrototypes +_XawImDestroy( + Widget w, + Widget ext ) +#else +_XawImDestroy( w, ext ) + Widget w; + Widget ext; +#endif +{ + XawVendorShellExtPart *ve; + + if ( !XtIsVendorShell( w ) ) return; + if ((ve = GetExtPart( (VendorShellWidget) w ))) + Destroy( w, ve ); +} diff --git a/src/XawImP.h b/src/XawImP.h new file mode 100644 index 0000000..4c398ff --- /dev/null +++ b/src/XawImP.h @@ -0,0 +1,240 @@ +/* $XConsortium: XawImP.h,v 1.4 95/06/06 20:50:30 kaleb Exp $ */ + +/* + * Copyright 1991 by OMRON Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 OMRON not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. OMRON makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING + * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL + * OMRON 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: Seiji Kuwari OMRON Corporation + * kuwa@omron.co.jp + * kuwa%omron.co.jp@uunet.uu.net + */ + +/* + +Copyright (c) 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +#ifndef _XawImP_h +#define _XawImP_h + +#define XtNinputMethod "inputMethod" +#define XtCInputMethod "InputMethod" +#define XtNpreeditType "preeditType" +#define XtCPreeditType "PreeditType" +#define XtNopenIm "openIm" +#define XtCOpenIm "OpenIm" +#define XtNsharedIc "sharedIc" +#define XtCSharedIc "SharedIc" + +#include <X11/Xaw3d/Text.h> + +#define CIICFocus (1 << 0) +#define CIFontSet (1 << 1) +#define CIFg (1 << 2) +#define CIBg (1 << 3) +#define CIBgPixmap (1 << 4) +#define CICursorP (1 << 5) +#define CILineS (1 << 6) + +typedef struct _XawImPart +{ + XIM xim; + XrmResourceList resources; + Cardinal num_resources; + Boolean open_im; + Boolean initialized; + Dimension area_height; + String input_method; + String preedit_type; +} XawImPart; + +typedef struct _XawIcTablePart +{ + Widget widget; + XIC xic; + XIMStyle input_style; + unsigned long flg; + unsigned long prev_flg; + Boolean ic_focused; + XFontSet font_set; + Pixel foreground; + Pixel background; + Pixmap bg_pixmap; + XawTextPosition cursor_position; + unsigned long line_spacing; + Boolean openic_error; + struct _XawIcTablePart *next; +} XawIcTablePart, *XawIcTableList; + +typedef struct _XawIcPart +{ + XIMStyle input_style; + Boolean shared_ic; + XawIcTableList shared_ic_table; + XawIcTableList current_ic_table; + XawIcTableList ic_table; +} XawIcPart; + +typedef struct _contextDataRec +{ + Widget parent; + Widget ve; +} contextDataRec; + +typedef struct _contextErrDataRec +{ + Widget widget; + XIM xim; +} contextErrDataRec; + +void _XawImResizeVendorShell( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +Dimension _XawImGetShellHeight( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +void _XawImRealize( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +void _XawImInitialize( +#if NeedFunctionPrototypes + Widget, /* w */ + Widget /* ext */ +#endif +); + +void _XawImReconnect( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +void _XawImRegister( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +void _XawImUnregister( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +void _XawImSetValues( +#if NeedFunctionPrototypes + Widget, /* w */ + ArgList, /* args */ + Cardinal /* num_args */ +#endif +); + +/* DON'T USE THIS FUNCTION -- it's going away in the next release */ +void _XawImVASetValues( +#if NeedVarargsPrototypes + Widget, /* w */ + ... +#endif +); + +void _XawImSetFocusValues( +#if NeedFunctionPrototypes + Widget, /* w */ + ArgList, /* args */ + Cardinal /* num_args */ +#endif +); + +/* DON'T USE THIS FUNCTION -- it's going away in the next release */ +void _XawImVASetFocusValues( +#if NeedVarargsPrototypes + Widget, /* w */ + ... +#endif +); + +void _XawImUnsetFocus( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +int _XawImWcLookupString( +#if NeedFunctionPrototypes + Widget, /* w */ + XKeyPressedEvent*, /* event */ + wchar_t*, /* buffer_return */ + int, /* bytes_buffer */ + KeySym*, /* keysym_return */ + Status* /* status return */ +#endif +); + +int _XawImGetImAreaHeight( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +void _XawImCallVendorShellExtResize( +#if NeedFunctionPrototypes + Widget /* w */ +#endif +); + +void _XawImDestroy( +#if NeedFunctionPrototypes + Widget, /* w */ + Widget /* ext */ +#endif +); + +#endif /* _XawImP_h */ diff --git a/src/XawInit.c b/src/XawInit.c new file mode 100644 index 0000000..b2bd482 --- /dev/null +++ b/src/XawInit.c @@ -0,0 +1,49 @@ +/* + * $XConsortium: XawInit.c,v 1.3 94/04/17 20:13:32 jim Exp $ + * +Copyright (c) 1989 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + * + * + * XawInitializeWidgetSet + * + * This routine forces a reference to vendor shell so that the one in this + * widget is installed. Any other cross-widget set initialization should be + * done here as well. All Athena widgets should include "XawInit.h" and + * call this routine from their ClassInitialize procs (this routine may be + * used as the class init proc). + */ + +#include <X11/Intrinsic.h> +#include <X11/Vendor.h> +#include <X11/Xaw3d/XawInit.h> + +void XawInitializeWidgetSet () +{ + static int firsttime = 1; + + if (firsttime) { + firsttime = 0; + XtInitializeWidgetClass (vendorShellWidgetClass); + } +} diff --git a/src/XawInit.h b/src/XawInit.h new file mode 100644 index 0000000..5d19f88 --- /dev/null +++ b/src/XawInit.h @@ -0,0 +1,31 @@ +/* $XConsortium: XawInit.h,v 1.6 94/04/17 20:13:33 kaleb Exp $ + * +Copyright (c) 1989, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + */ + +_XFUNCPROTOBEGIN + +extern void XawInitializeWidgetSet(); /* called from ClassInit procs */ + +_XFUNCPROTOEND diff --git a/src/laygram.y b/src/laygram.y new file mode 100644 index 0000000..c209b64 --- /dev/null +++ b/src/laygram.y @@ -0,0 +1,263 @@ +%{ +#include <X11/Xlib.h> +#include <X11/Xresource.h> +#include <stdio.h> +#include <X11/IntrinsicP.h> +#include <X11/cursorfont.h> +#include <X11/StringDefs.h> + +#include <X11/Xmu/Misc.h> +#include <X11/Xmu/Converters.h> +#include "LayoutP.h" + +static LayoutPtr *dest; + +%} + +%union { + int ival; + XrmQuark qval; + BoxPtr bval; + BoxParamsPtr pval; + GlueRec gval; + LayoutDirection lval; + ExprPtr eval; + Operator oval; +} + +%type <bval> box boxes compositebox +%type <pval> bothparams oneparams +%type <gval> glue opStretch opShrink +%type <lval> orientation +%type <eval> signedExpr simpleExpr expr + +%token OC CC OA CA OP CP +%token <qval> NAME +%token <ival> NUMBER +%token <ival> INFINITY +%token VERTICAL HORIZONTAL + +%token EQUAL DOLLAR + +%left <oval> PLUS MINUS +%left <oval> TIMES DIVIDE PERCENTOF +%right <oval> PERCENT +%nonassoc WIDTH HEIGHT +%right <oval> UMINUS UPLUS + +%% +layout : compositebox + { *dest = $1; } + ; +box : NAME bothparams + { + BoxPtr box = New(LBoxRec); + box->nextSibling = 0; + box->type = WidgetBox; + box->params = *$2; + Dispose ($2); + box->u.widget.quark = $1; + $$ = box; + } + | signedExpr oneparams + { + BoxPtr box = New(LBoxRec); + box->nextSibling = 0; + box->type = GlueBox; + box->params = *$2; + Dispose ($2); + box->u.glue.expr = $1; + $$ = box; + } + | NAME EQUAL signedExpr + { + BoxPtr box = New(LBoxRec); + box->nextSibling = 0; + box->type = VariableBox; + box->u.variable.quark = $1; + box->u.variable.expr = $3; + $$ = box; + } + | compositebox + { + $$ = $1; + } + ; +compositebox : orientation OC boxes CC + { + BoxPtr box = New(LBoxRec); + BoxPtr child; + + box->nextSibling = 0; + box->parent = 0; + box->type = BoxBox; + box->u.box.dir = $1; + box->u.box.firstChild = $3; + for (child = $3; child; child = child->nextSibling) + { + if (child->type == GlueBox) + { + child->params.stretch[!$1].expr = 0; + child->params.shrink[!$1].expr = 0; + child->params.stretch[!$1].order = 100000; + child->params.shrink[!$1].order = 100000; + child->params.stretch[!$1].value = 1; + child->params.shrink[!$1].value = 1; + } + child->parent = box; + } + $$ = box; + } + ; +boxes : box boxes + { + $1->nextSibling = $2; + $$ = $1; + } + | box + { $$ = $1; } + ; +bothparams : OA opStretch opShrink TIMES opStretch opShrink CA + { + BoxParamsPtr p = New(BoxParamsRec); + + p->stretch[LayoutHorizontal] = $2; + p->shrink[LayoutHorizontal] = $3; + p->stretch[LayoutVertical] = $5; + p->shrink[LayoutVertical] = $6; + $$ = p; + } + | + { + BoxParamsPtr p = New(BoxParamsRec); + + ZeroGlue (p->stretch[LayoutHorizontal]); + ZeroGlue (p->shrink[LayoutHorizontal]); + ZeroGlue (p->stretch[LayoutVertical]); + ZeroGlue (p->shrink[LayoutVertical]); + $$ = p; + } + ; +oneparams : OA opStretch opShrink CA + { + BoxParamsPtr p = New(BoxParamsRec); + + p->stretch[LayoutHorizontal] = $2; + p->shrink[LayoutHorizontal] = $3; + p->stretch[LayoutVertical] = $2; + p->shrink[LayoutVertical] = $3; + $$ = p; + } + | + { + BoxParamsPtr p = New(BoxParamsRec); + + ZeroGlue (p->stretch[LayoutHorizontal]); + ZeroGlue (p->shrink[LayoutHorizontal]); + ZeroGlue (p->stretch[LayoutVertical]); + ZeroGlue (p->shrink[LayoutVertical]); + $$ = p; + } + ; +opStretch : PLUS glue + { $$ = $2; } + | + { ZeroGlue ($$); } + ; +opShrink : MINUS glue + { $$ = $2; } + | + { ZeroGlue ($$); } + ; +glue : simpleExpr INFINITY + { $$.order = $2; $$.expr = $1; } + | simpleExpr + { $$.order = 0; $$.expr = $1; } + | INFINITY + { $$.order = $1; $$.expr = 0; $$.value = 1; } + ; +signedExpr : MINUS simpleExpr %prec UMINUS + { + $$ = New(ExprRec); + $$->type = Unary; + $$->u.unary.op = $1; + $$->u.unary.down = $2; + } + | PLUS simpleExpr %prec UPLUS + { $$ = $2; } + | simpleExpr + ; +simpleExpr : WIDTH NAME + { $$ = New(ExprRec); + $$->type = Width; + $$->u.width = $2; + } + | HEIGHT NAME + { $$ = New(ExprRec); + $$->type = Height; + $$->u.height = $2; + } + | OP expr CP + { $$ = $2; } + | simpleExpr PERCENT + { + $$ = New(ExprRec); + $$->type = Unary; + $$->u.unary.op = $2; + $$->u.unary.down = $1; + } + | NUMBER + { $$ = New(ExprRec); + $$->type = Constant; + $$->u.constant = $1; + } + | DOLLAR NAME + { $$ = New(ExprRec); + $$->type = Variable; + $$->u.variable = $2; + } + ; +expr : expr PLUS expr + { binary: ; + $$ = New(ExprRec); + $$->type = Binary; + $$->u.binary.op = $2; + $$->u.binary.left = $1; + $$->u.binary.right = $3; + } + | expr MINUS expr + { goto binary; } + | expr TIMES expr + { goto binary; } + | expr DIVIDE expr + { goto binary; } + | expr PERCENTOF expr + { goto binary; } + | MINUS expr %prec UMINUS + { unary: ; + $$ = New(ExprRec); + $$->type = Unary; + $$->u.unary.op = $1; + $$->u.unary.down = $2; + } + | PLUS expr %prec UPLUS + { $$ = $2; } + | simpleExpr + ; +orientation : VERTICAL + { $$ = LayoutVertical; } + | HORIZONTAL + { $$ = LayoutHorizontal; } + ; +%% + +int yywrap () +{ + return 1; +} + +void yysetdest (c) + LayoutPtr *c; +{ + dest = c; +} diff --git a/src/laylex.l b/src/laylex.l new file mode 100644 index 0000000..7de4f2d --- /dev/null +++ b/src/laylex.l @@ -0,0 +1,127 @@ + +%{ +#ifndef FLEX_SCANNER +#undef input +#undef unput +#endif + +#include <X11/Xlib.h> +#include <X11/Xresource.h> +#include <X11/IntrinsicP.h> +#include <X11/StringDefs.h> + +#include "LayoutP.h" +#include "laygram.h" +static char *yysourcebase, *yysource; + +#ifndef FLEX_SCANNER +#define input() (*yysource++) +#define unput(c) (--yysource) +#else +#include <string.h> +static void my_yyinput(char *buf, int *result, int max_size); +#define YY_INPUT(buf, res, max) my_yyinput(buf, &(res), max) +#endif + +#ifdef __STDC__ +static int count (); +#endif +%} +%% +vertical return VERTICAL; +horizontal return HORIZONTAL; +"{" return OC; +"}" return CC; +"(" return OP; +")" return CP; +"<" return OA; +">" return CA; +infinity { yylval.ival = 1; return INFINITY; } +inff* { yylval.ival = count(yytext, 'f'); return INFINITY; } +[0-9][0-9]* { yylval.ival = atoi(yytext); return NUMBER; } +"=" { return EQUAL; } +"$" { return DOLLAR; } +"+" { yylval.oval = Plus; return PLUS; } +"-" { yylval.oval = Minus; return MINUS; } +"*" { yylval.oval = Times; return TIMES; } +"/" { yylval.oval = Divide; return DIVIDE; } +"%" { yylval.oval = Percent; return PERCENT; } +%[ \t\n]*of { yylval.oval = Percent; return PERCENTOF; } +width return WIDTH; +height return HEIGHT; +\\[a-zA-Z_][a-zA-Z0-9_]* { +#ifdef FLEX_SCANNER + yytext[yyleng] = '\0'; +#else + yytext[yyleng-1] = '\0'; +#endif + yylval.qval = XrmStringToQuark (yytext+1); + return NAME; + } + +[a-zA-Z_][a-zA-Z0-9_]* { +#ifdef FLEX_SCANNER + yytext[yyleng] = '\0'; +#else + yytext[yyleng-1] = '\0'; +#endif + yylval.qval = XrmStringToQuark (yytext); + return NAME; + } +" " ; +"\t" ; +"\n" ; +. fprintf (stderr, "ignoring %c\n", *yytext); +%% + +static int +count (s, c) + char *s; + char c; +{ + int i = 0; + while (*s) + if (*s++ == c) + i++; + return i; +} + +yysetsource(s) + char *s; +{ + yysourcebase = yysource = s; +} + +yyerror(s) + char *s; +{ + char *t; + + fprintf (stderr, "%s\n", s); + t = yysource - 50; + if (t < yysourcebase) + t = yysourcebase; + while (*t && t < yysource + 50) { + if (t == yysource) + putc ('@', stderr); + putc (*t++, stderr); + } + if (t == yysource) + putc ('@', stderr); + if (!*t) + fprintf (stderr, "<EOF>"); + fprintf (stderr, "\n"); +} + +#ifdef FLEX_SCANNER +static void +my_yyinput(buf, result, max_size) + char *buf; int *result; int max_size; +{ + int size = max_size < strlen(yysource) ? max_size : strlen(yysource); + + strncpy(buf, yysource, size); + yysource += size; + *result = size; +} +#endif diff --git a/src/sharedlib.c b/src/sharedlib.c new file mode 100644 index 0000000..486cf0a --- /dev/null +++ b/src/sharedlib.c @@ -0,0 +1,192 @@ +/* $XConsortium: sharedlib.c,v 1.6 94/04/17 20:13:34 kaleb Exp $ */ +/* + +Copyright (c) 1991, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + +*/ + +#if defined(SUNSHLIB) && !defined(SHAREDCODE) + +#include <X11/Xaw3d/Xaw3dP.h> +#include <X11/IntrinsicP.h> +#include <X11/Xaw3d/AsciiSinkP.h> +#include <X11/Xaw3d/AsciiSrcP.h> +#include <X11/Xaw3d/AsciiTextP.h> +#ifdef XAW_INTERNATIONALIZATION +#include <X11/Xaw3d/MultiSinkP.h> +#include <X11/Xaw3d/MultiSrcP.h> +#endif +#include <X11/Xaw3d/BoxP.h> +#include <X11/Xaw3d/CommandP.h> +#include <X11/Xaw3d/DialogP.h> +#include <X11/Xaw3d/FormP.h> +#include <X11/Xaw3d/GripP.h> +#include <X11/Xaw3d/LabelP.h> +#include <X11/Xaw3d/ListP.h> +#include <X11/Xaw3d/MenuButtoP.h> +#include <X11/Xaw3d/PanedP.h> +#include <X11/Xaw3d/PannerP.h> +#include <X11/Xaw3d/PortholeP.h> +#include <X11/Xaw3d/RepeaterP.h> +#include <X11/Xaw3d/ScrollbarP.h> +#include <X11/Xaw3d/SimpleP.h> +#include <X11/Xaw3d/SimpleMenP.h> +#include <X11/Xaw3d/SmeP.h> +#include <X11/Xaw3d/SmeThreeDP.h> +#include <X11/Xaw3d/SmeBSBP.h> +#include <X11/Xaw3d/SmeLineP.h> +#include <X11/Xaw3d/StripCharP.h> +#include <X11/Xaw3d/TextP.h> +#include <X11/Xaw3d/TextSinkP.h> +#include <X11/Xaw3d/TextSrcP.h> +#include <X11/Xaw3d/ThreeDP.h> +#include <X11/Xaw3d/TipP.h> +#include <X11/Xaw3d/ToggleP.h> +#include <X11/Xaw3d/TreeP.h> +#include <X11/VendorP.h> +#include <X11/Xaw3d/ViewportP.h> + +extern AsciiSinkClassRec asciiSinkClassRec; +WidgetClass asciiSinkObjectClass = (WidgetClass)&asciiSinkClassRec; + +extern AsciiSrcClassRec asciiSrcClassRec; +WidgetClass asciiSrcObjectClass = (WidgetClass)&asciiSrcClassRec; + +extern AsciiTextClassRec asciiTextClassRec; +WidgetClass asciiTextWidgetClass = (WidgetClass)&asciiTextClassRec; + +#ifdef ASCII_STRING +extern AsciiStringClassRec asciiStringClassRec; +WidgetClass asciiStringWidgetClass = (WidgetClass)&asciiStringClassRec; +#endif + +#ifdef ASCII_DISK +extern AsciiDiskClassRec asciiDiskClassRec; +WidgetClass asciiDiskWidgetClass = (WidgetClass)&asciiDiskClassRec; +#endif + +#ifdef XAW_INTERNATIONALIZATION +extern MultiSinkClassRec multiSinkClassRec; +WidgetClass multiSinkObjectClass = (WidgetClass)&multiSinkClassRec; +#endif + +#ifdef XAW_INTERNATIONALIZATION +extern MultiSrcClassRec multiSrcClassRec; +WidgetClass multiSrcObjectClass = (WidgetClass)&multiSrcClassRec; +#endif + +extern BoxClassRec boxClassRec; +WidgetClass boxWidgetClass = (WidgetClass)&boxClassRec; + +extern CommandClassRec commandClassRec; +WidgetClass commandWidgetClass = (WidgetClass) &commandClassRec; + +extern DialogClassRec dialogClassRec; +WidgetClass dialogWidgetClass = (WidgetClass)&dialogClassRec; + +extern FormClassRec formClassRec; +WidgetClass formWidgetClass = (WidgetClass)&formClassRec; + +extern GripClassRec gripClassRec; +WidgetClass gripWidgetClass = (WidgetClass) &gripClassRec; + +extern LabelClassRec labelClassRec; +WidgetClass labelWidgetClass = (WidgetClass)&labelClassRec; + +extern ListClassRec listClassRec; +WidgetClass listWidgetClass = (WidgetClass)&listClassRec; + +extern MenuButtonClassRec menuButtonClassRec; +WidgetClass menuButtonWidgetClass = (WidgetClass) &menuButtonClassRec; + +extern PanedClassRec panedClassRec; +WidgetClass panedWidgetClass = (WidgetClass) &panedClassRec; +WidgetClass vPanedWidgetClass = (WidgetClass) &panedClassRec; + +extern PannerClassRec pannerClassRec; +WidgetClass pannerWidgetClass = (WidgetClass) &pannerClassRec; + +extern PortholeClassRec portholeClassRec; +WidgetClass portholeWidgetClass = (WidgetClass) &portholeClassRec; + +extern RepeaterClassRec repeaterClassRec; +WidgetClass repeaterWidgetClass = (WidgetClass) &repeaterClassRec; + +extern ScrollbarClassRec scrollbarClassRec; +WidgetClass scrollbarWidgetClass = (WidgetClass)&scrollbarClassRec; + +extern SimpleClassRec simpleClassRec; +WidgetClass simpleWidgetClass = (WidgetClass)&simpleClassRec; + +extern SimpleMenuClassRec simpleMenuClassRec; +WidgetClass simpleMenuWidgetClass = (WidgetClass)&simpleMenuClassRec; + +extern SmeClassRec smeClassRec; +WidgetClass smeObjectClass = (WidgetClass) &smeClassRec; + +extern smeThreeDClassRec smeThreeDClassRec; +WidgetClass smeThreeDObjectClass = (WidgetClass) &smeThreeDClassRec; + +WidgetClass smeBSBObjectClass = (WidgetClass) &smeBSBClassRec; + +extern SmeLineClassRec smeLineClassRec; +WidgetClass smeLineObjectClass = (WidgetClass) &smeLineClassRec; + +extern StripChartClassRec stripChartClassRec; +WidgetClass stripChartWidgetClass = (WidgetClass) &stripChartClassRec; + +extern TextClassRec textClassRec; +WidgetClass textWidgetClass = (WidgetClass)&textClassRec; + +unsigned long FMT8BIT = 0L; +unsigned long XawFmt8Bit = 0L; +#ifdef XAW_INTERNATIONALIZATION +unsigned long XawFmtWide = 0L; +#endif + +extern TextSinkClassRec textSinkClassRec; +WidgetClass textSinkObjectClass = (WidgetClass)&textSinkClassRec; + +extern TextSrcClassRec textSrcClassRec; +WidgetClass textSrcObjectClass = (WidgetClass)&textSrcClassRec; + +extern ThreeDClassRec threeDClassRec; +WidgetClass threeDClass = (WidgetClass)&threeDClassRec; + +extern TipClassRec tipClassRec; +WidgetClass tipWidgetClass = (WidgetClass)&tipClassRec; + +extern ToggleClassRec toggleClassRec; +WidgetClass toggleWidgetClass = (WidgetClass) &toggleClassRec; + +extern TreeClassRec treeClassRec; +WidgetClass treeWidgetClass = (WidgetClass) &treeClassRec; + +extern VendorShellClassRec vendorShellClassRec; +WidgetClass vendorShellWidgetClass = (WidgetClass) &vendorShellClassRec; + +extern ViewportClassRec viewportClassRec; +WidgetClass viewportWidgetClass = (WidgetClass)&viewportClassRec; + +#endif /* SUNSHLIB */ |