home *** CD-ROM | disk | FTP | other *** search
-
- /***********************************************************
- Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
- and the Massachusetts Institute of Technology, Cambridge, 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 names of Digital or MIT 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 <ctype.h>
-
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <X11/Xatom.h>
- #include <X11/IntrinsicP.h>
- #include <X11/StringDefs.h>
- #include <X11/Xaw/XawInit.h>
- #include "KeyWSinkP.h"
- #include <X11/Xaw/AsciiSinkP.h>
- #include <X11/Xaw/AsciiSrcP.h> /* For source function defs. */
- #include <X11/Xaw/TextP.h> /* I also reach into the text widget. */
-
- #ifdef GETLASTPOS
- #undef GETLASTPOS /* We will use our own GETLASTPOS. */
- #endif
-
- #define GETLASTPOS XawTextSourceScan(source, 0, XawstAll, XawsdRight, 1, TRUE)
-
- static void Initialize(), Destroy();
- static Boolean SetValues();
-
- static void DisplayText();
-
-
- #define offset(field) XtOffsetOf(KeyWSinkRec, keyw_sink.field)
-
- static XtResource resources[] = {
- {XtNwordList, XtCWordList, XtRPointer, sizeof(char **),
- offset(wordList), XtRImmediate, (XtPointer) NULL}
- };
- #undef offset
-
- #define SuperClass (&asciiSinkClassRec)
- KeyWSinkClassRec keyWSinkClassRec = {
- {
- /* core_class fields */
- /* superclass */ (WidgetClass) SuperClass,
- /* class_name */ "KeyWSink",
- /* widget_size */ sizeof(KeyWSinkRec),
- /* 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 */ XtInheritInsertCursor,
- /* ClearToBackground */ XtInheritClearToBackground,
- /* FindPosition */ XtInheritFindPosition,
- /* FindDistance */ XtInheritFindDistance,
- /* Resolve */ XtInheritResolve,
- /* MaxLines */ XtInheritMaxLines,
- /* MaxHeight */ XtInheritMaxHeight,
- /* SetTabs */ XtInheritSetTabs,
- /* GetCursorBounds */ XtInheritGetCursorBounds
- },
- /* ascii_sink_class fields */
- {
- /* unused */ 0
- },
- /* keyw_sink_class fields */
- {
- /* unused */ 0
- }
- };
-
- WidgetClass keyWSinkObjectClass = (WidgetClass)&keyWSinkClassRec;
-
- /* Utilities */
-
-
- /* matchw
- given a string buffer and a null-terminated list of words, find
- the leftmost position in the buffer that matches one of the words
- in the list, if any. Returns the offset in the buffer of first match,
- -1 if no match. Also, the int* parameter matchLen is set to the
- length of the match. */
-
- static int
- matchw(buf, len, words, matchLen)
- char *buf;
- int len;
- char *words[];
- int *matchLen;
- {
- int i, j, k;
- int left = len;
- int wLen, last;
- char *start=buf, *bp, *wp;
- int match, tested;
-
- /* loop through the characters in the buffer */
-
- *matchLen = 0;
- if (words == NULL) return -1;
-
- while (left > 0) {
-
- /* loop through each word in the word list */
-
- tested = False;
- for (k=0; words[k]!=NULL; k++) {
-
- /* if too few characters left in buffer, next word */
-
- wLen = strlen(words[k]);
- if ((last = left - wLen + 1) <= 0) continue;
- tested = True;
-
- /* loop through each character in the word */
-
- match = True;
- bp=buf; wp=words[k];
- for (i=0; i < wLen; i++) {
- if ((wp[i] != bp[i]) && (toupper(wp[i]) != bp[i])) {
- match = False;
- break;
- }
- }
-
- if (match) {
- *matchLen = wLen;
- return (buf - start);
- }
- }
-
- if (! tested) return -1;
-
- left--;
- buf++;
- }
-
- return -1;
- }
-
-
- static int
- CharWidth (w, x, c)
- Widget w;
- int x;
- unsigned char c;
- {
- register int i, width, nonPrinting;
- KeyWSinkObject sink = (KeyWSinkObject) w;
- XFontStruct *font = sink->text_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;
- {
- KeyWSinkObject sink = (KeyWSinkObject) w;
- TextWidget ctx = (TextWidget) XtParent(w);
-
- Position max_x;
- Dimension width = XTextWidth(sink->text_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->text_sink.font->ascent,
- (unsigned int) width,
- (unsigned int) (sink->text_sink.font->ascent +
- sink->text_sink.font->descent));
- return(0);
- }
- return(width);
- }
-
- /* Function Name: PaintKeyW
- * Description: highlight selected list of keywords, then calls function
- * to actually paint the text into the window.
- * Arguments: w - the text widget.
- * gc - gc to paint text with.
- * invgc - gc to highlight 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
- PaintKeyW(w, gc, invgc, x, y, buf, len)
- Widget w;
- GC gc, invgc;
- Position x, y;
- unsigned char * buf;
- int len;
- {
- KeyWSinkObject sink = (KeyWSinkObject) w;
- TextWidget ctx = (TextWidget) XtParent(w);
- int first, nch;
- Dimension px, xlen=0;
-
- first = matchw(buf, len, sink->keyw_sink.wordList, &nch);
- while (first != -1) {
- if (first != 0) {
- if ((px = PaintText(w, gc, x+xlen, y, buf, first)) == 0)
- return 0;
- xlen += px;
- len -= first;
- buf += first;
- }
- if ((px = PaintText(w, invgc, x+xlen, y, buf, nch)) == 0) return 0;
- xlen += px;
- len -= nch;
- buf += nch;
-
- first = matchw(buf, len, sink->keyw_sink.wordList, &nch);
- }
-
- if (len > 0) {
- if ((px = PaintText(w, gc, x+xlen, y, buf, len)) == 0) return 0;
- xlen += px;
- }
-
- return xlen;
- }
-
- /* 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;
- {
- KeyWSinkObject sink = (KeyWSinkObject) 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->text_sink.font->ascent;
- for ( j = 0 ; pos1 < pos2 ; ) {
- pos1 = XawTextSourceRead(source, pos1, &blk, pos2 - pos1);
- for (k = 0; k < blk.length; k++) {
- if (j >= BUFSIZ) { /* buffer full, dump the text. */
- if (sink->keyw_sink.wordList == NULL)
- x += PaintText(w, gc, x, y, buf, j);
- else
- x += PaintKeyW(w, gc, invgc, 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;
- */
- if (j != 0) {
- if (sink->keyw_sink.wordList == NULL)
- temp = PaintText(w, gc, x, y, buf, j);
- else
- temp = PaintKeyW(w, gc, invgc, x, y, buf, j);
- if (temp == 0) return;
- }
-
- x += temp;
- width = CharWidth(w, x, (unsigned char) '\t');
- XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
- invgc, (int) x,
- (int) y - sink->text_sink.font->ascent,
- (unsigned int) width,
- (unsigned int) (sink->text_sink.font->ascent +
- sink->text_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)
- if (sink->keyw_sink.wordList == NULL)
- (void) PaintText(w, gc, x, y, buf, j);
- else
- (void) PaintKeyW(w, gc, invgc, 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));
- }
-
-
- static void
- GetGC(sink)
- KeyWSinkObject sink;
- {
- XtGCMask valuemask = (GCFont |
- GCGraphicsExposures | GCForeground | GCBackground );
- XGCValues values;
-
- values.font = sink->text_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)
- Widget request, new;
- {
- KeyWSinkObject sink = (KeyWSinkObject) 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 KeyWSink Object.
- * Returns: none.
- */
-
- static void
- Destroy(w)
- Widget w;
- {
- KeyWSinkObject sink = (KeyWSinkObject) 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 KeyWSink
- * 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)
- Widget current, request, new;
- {
- KeyWSinkObject w = (KeyWSinkObject) new;
- KeyWSinkObject old_w = (KeyWSinkObject) current;
-
- if (w->text_sink.font != old_w->text_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;
- }
-