00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 #include <stdio.h>
00052
00053 #include <X11/Xatom.h>
00054 #include <X11/IntrinsicP.h>
00055 #include <X11/StringDefs.h>
00056 #include <X11/Xaw3d/XawInit.h>
00057 #include <X11/Xaw3d/AsciiSinkP.h>
00058 #include <X11/Xaw3d/AsciiSrcP.h>
00059 #include <X11/Xaw3d/TextP.h>
00060
00061 #ifdef GETLASTPOS
00062 #undef GETLASTPOS
00063 #endif
00064
00065 #define GETLASTPOS XawTextSourceScan(source, (XawTextPosition) 0, XawstAll, XawsdRight, 1, TRUE)
00066
00067 static void Initialize(), Destroy();
00068 static Boolean SetValues();
00069 static int MaxLines(), MaxHeight();
00070 static void SetTabs();
00071
00072 static void DisplayText(), InsertCursor(), FindPosition();
00073 static void FindDistance(), Resolve(), GetCursorBounds();
00074
00075 #define offset(field) XtOffsetOf(AsciiSinkRec, ascii_sink.field)
00076
00077 static XtResource resources[] = {
00078 {XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
00079 offset(font), XtRString, XtDefaultFont},
00080 {XtNecho, XtCOutput, XtRBoolean, sizeof(Boolean),
00081 offset(echo), XtRImmediate, (XtPointer) True},
00082 {XtNdisplayNonprinting, XtCOutput, XtRBoolean, sizeof(Boolean),
00083 offset(display_nonprinting), XtRImmediate, (XtPointer) True},
00084 };
00085 #undef offset
00086
00087 #define SuperClass (&textSinkClassRec)
00088 AsciiSinkClassRec asciiSinkClassRec = {
00089 {
00090
00091 (WidgetClass) SuperClass,
00092 "AsciiSink",
00093 sizeof(AsciiSinkRec),
00094 XawInitializeWidgetSet,
00095 NULL,
00096 FALSE,
00097 Initialize,
00098 NULL,
00099 NULL,
00100 NULL,
00101 0,
00102 resources,
00103 XtNumber(resources),
00104 NULLQUARK,
00105 FALSE,
00106 FALSE,
00107 FALSE,
00108 FALSE,
00109 Destroy,
00110 NULL,
00111 NULL,
00112 SetValues,
00113 NULL,
00114 NULL,
00115 NULL,
00116 NULL,
00117 XtVersion,
00118 NULL,
00119 NULL,
00120 NULL,
00121 NULL,
00122 NULL
00123 },
00124
00125 {
00126 DisplayText,
00127 InsertCursor,
00128 XtInheritClearToBackground,
00129 FindPosition,
00130 FindDistance,
00131 Resolve,
00132 MaxLines,
00133 MaxHeight,
00134 SetTabs,
00135 GetCursorBounds
00136 },
00137
00138 {
00139 0
00140 }
00141 };
00142
00143 WidgetClass asciiSinkObjectClass = (WidgetClass)&asciiSinkClassRec;
00144
00145
00146
00147 static int
00148 CharWidth (w, x, c)
00149 Widget w;
00150 int x;
00151 unsigned char c;
00152 {
00153 int i, width, nonPrinting;
00154 AsciiSinkObject sink = (AsciiSinkObject) w;
00155 XFontStruct *font = sink->ascii_sink.font;
00156 Position *tab;
00157
00158 if ( c == XawLF ) return(0);
00159
00160 if (c == XawTAB) {
00161
00162 x -= ((TextWidget) XtParent(w))->text.margin.left;
00163
00164 if (x >= (int)XtParent(w)->core.width) return 0;
00165 for (i = 0, tab = sink->text_sink.tabs ;
00166 i < sink->text_sink.tab_count ; i++, tab++) {
00167 if (x < *tab) {
00168 if (*tab < (int)XtParent(w)->core.width)
00169 return *tab - x;
00170 else
00171 return 0;
00172 }
00173 }
00174 return 0;
00175 }
00176
00177 if ( (nonPrinting = (c < (unsigned char) XawSP)) )
00178 if (sink->ascii_sink.display_nonprinting)
00179 c += '@';
00180 else {
00181 c = XawSP;
00182 nonPrinting = False;
00183 }
00184
00185 if (font->per_char &&
00186 (c >= font->min_char_or_byte2 && c <= font->max_char_or_byte2))
00187 width = font->per_char[c - font->min_char_or_byte2].width;
00188 else
00189 width = font->min_bounds.width;
00190
00191 if (nonPrinting)
00192 width += CharWidth(w, x, (unsigned char) '^');
00193
00194 return width;
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 static Dimension
00210 PaintText(w, gc, x, y, buf, len)
00211 Widget w;
00212 GC gc;
00213 Position x, y;
00214 unsigned char * buf;
00215 int len;
00216 {
00217 AsciiSinkObject sink = (AsciiSinkObject) w;
00218 TextWidget ctx = (TextWidget) XtParent(w);
00219
00220 Position max_x;
00221 Dimension width = XTextWidth(sink->ascii_sink.font, (char *) buf, len);
00222 max_x = (Position) ctx->core.width;
00223
00224 if ( ((int) width) <= -x)
00225 return(width);
00226
00227 XDrawImageString(XtDisplay(ctx), XtWindow(ctx), gc,
00228 (int) x, (int) y, (char *) buf, len);
00229 if ( (((Position) width + x) > max_x) && (ctx->text.margin.right != 0) ) {
00230 x = ctx->core.width - ctx->text.margin.right;
00231 width = ctx->text.margin.right;
00232 XFillRectangle(XtDisplay((Widget) ctx), XtWindow( (Widget) ctx),
00233 sink->ascii_sink.normgc, (int) x,
00234 (int) y - sink->ascii_sink.font->ascent,
00235 (unsigned int) width,
00236 (unsigned int) (sink->ascii_sink.font->ascent +
00237 sink->ascii_sink.font->descent));
00238 return(0);
00239 }
00240 return(width);
00241 }
00242
00243
00244
00245
00246
00247
00248
00249 static void
00250 DisplayText(w, x, y, pos1, pos2, highlight)
00251 Widget w;
00252 Position x, y;
00253 Boolean highlight;
00254 XawTextPosition pos1, pos2;
00255 {
00256 AsciiSinkObject sink = (AsciiSinkObject) w;
00257 Widget source = XawTextGetSource(XtParent(w));
00258 unsigned char buf[BUFSIZ];
00259
00260 int j, k;
00261 XawTextBlock blk;
00262 GC gc = highlight ? sink->ascii_sink.invgc : sink->ascii_sink.normgc;
00263 GC invgc = highlight ? sink->ascii_sink.normgc : sink->ascii_sink.invgc;
00264
00265 if (!sink->ascii_sink.echo) return;
00266
00267 y += sink->ascii_sink.font->ascent;
00268 for ( j = 0 ; pos1 < pos2 ; ) {
00269 pos1 = XawTextSourceRead(source, pos1, &blk, (int) pos2 - pos1);
00270 for (k = 0; k < blk.length; k++) {
00271 if (j >= BUFSIZ) {
00272 x += PaintText(w, gc, x, y, buf, j);
00273 j = 0;
00274 }
00275 buf[j] = blk.ptr[k];
00276 if (buf[j] == XawLF)
00277 continue;
00278
00279 else if (buf[j] == '\t') {
00280 Position temp = 0;
00281 Dimension width;
00282
00283 if ((j != 0) && ((temp = PaintText(w, gc, x, y, buf, j)) == 0))
00284 return;
00285
00286 x += temp;
00287 width = CharWidth(w, x, (unsigned char) '\t');
00288 XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
00289 invgc, (int) x,
00290 (int) y - sink->ascii_sink.font->ascent,
00291 (unsigned int) width,
00292 (unsigned int) (sink->ascii_sink.font->ascent +
00293 sink->ascii_sink.font->descent));
00294 x += width;
00295 j = -1;
00296 }
00297 else if ( buf[j] < (unsigned char) ' ' ) {
00298 if (sink->ascii_sink.display_nonprinting) {
00299 buf[j + 1] = buf[j] + '@';
00300 buf[j] = '^';
00301 j++;
00302 }
00303 else
00304 buf[j] = ' ';
00305 }
00306 j++;
00307 }
00308 }
00309 if (j > 0)
00310 (void) PaintText(w, gc, x, y, buf, j);
00311 }
00312
00313 #define insertCursor_width 6
00314 #define insertCursor_height 3
00315 static char insertCursor_bits[] = {0x0c, 0x1e, 0x33};
00316
00317 static Pixmap
00318 CreateInsertCursor(s)
00319 Screen *s;
00320 {
00321 return (XCreateBitmapFromData (DisplayOfScreen(s), RootWindowOfScreen(s),
00322 insertCursor_bits, insertCursor_width, insertCursor_height));
00323 }
00324
00325
00326
00327
00328
00329
00330
00331
00332 static void
00333 GetCursorBounds(w, rect)
00334 Widget w;
00335 XRectangle * rect;
00336 {
00337 AsciiSinkObject sink = (AsciiSinkObject) w;
00338
00339 rect->width = (unsigned short) insertCursor_width;
00340 rect->height = (unsigned short) insertCursor_height;
00341 rect->x = sink->ascii_sink.cursor_x - (short) (rect->width / 2);
00342 rect->y = sink->ascii_sink.cursor_y - (short) rect->height;
00343 }
00344
00345
00346
00347
00348
00349 static void
00350 InsertCursor (w, x, y, state)
00351 Widget w;
00352 Position x, y;
00353 XawTextInsertState state;
00354 {
00355 AsciiSinkObject sink = (AsciiSinkObject) w;
00356 Widget text_widget = XtParent(w);
00357 XRectangle rect;
00358
00359 sink->ascii_sink.cursor_x = x;
00360 sink->ascii_sink.cursor_y = y;
00361
00362 GetCursorBounds(w, &rect);
00363 if (state != sink->ascii_sink.laststate && XtIsRealized(text_widget))
00364 XCopyPlane(XtDisplay(text_widget),
00365 sink->ascii_sink.insertCursorOn,
00366 XtWindow(text_widget), sink->ascii_sink.xorgc,
00367 0, 0, (unsigned int) rect.width, (unsigned int) rect.height,
00368 (int) rect.x, (int) rect.y, 1);
00369 sink->ascii_sink.laststate = state;
00370 }
00371
00372
00373
00374
00375
00376 static void
00377 FindDistance (w, fromPos, fromx, toPos, resWidth, resPos, resHeight)
00378 Widget w;
00379 XawTextPosition fromPos;
00380 int fromx;
00381 XawTextPosition toPos;
00382 int *resWidth;
00383 XawTextPosition *resPos;
00384 int *resHeight;
00385 {
00386 AsciiSinkObject sink = (AsciiSinkObject) w;
00387 Widget source = XawTextGetSource(XtParent(w));
00388
00389 XawTextPosition index, lastPos;
00390 unsigned char c;
00391 XawTextBlock blk;
00392
00393
00394 lastPos = GETLASTPOS;
00395 XawTextSourceRead(source, fromPos, &blk, (int) toPos - fromPos);
00396 *resWidth = 0;
00397 for (index = fromPos; index != toPos && index < lastPos; index++) {
00398 if (index - blk.firstPos >= blk.length)
00399 XawTextSourceRead(source, index, &blk, (int) toPos - fromPos);
00400 c = blk.ptr[index - blk.firstPos];
00401 *resWidth += CharWidth(w, fromx + *resWidth, c);
00402 if (c == XawLF) {
00403 index++;
00404 break;
00405 }
00406 }
00407 *resPos = index;
00408 *resHeight = sink->ascii_sink.font->ascent +sink->ascii_sink.font->descent;
00409 }
00410
00411
00412 static void
00413 FindPosition(w, fromPos, fromx, width, stopAtWordBreak,
00414 resPos, resWidth, resHeight)
00415 Widget w;
00416 XawTextPosition fromPos;
00417 int fromx;
00418 int width;
00419 int stopAtWordBreak;
00420
00421 XawTextPosition *resPos;
00422 int *resWidth;
00423 int *resHeight;
00424 {
00425 AsciiSinkObject sink = (AsciiSinkObject) w;
00426 Widget source = XawTextGetSource(XtParent(w));
00427
00428 XawTextPosition lastPos, index, whiteSpacePosition = 0;
00429 int lastWidth = 0, whiteSpaceWidth = 0;
00430 Boolean whiteSpaceSeen;
00431 unsigned char c;
00432 XawTextBlock blk;
00433
00434 lastPos = GETLASTPOS;
00435
00436 XawTextSourceRead(source, fromPos, &blk, BUFSIZ);
00437 *resWidth = 0;
00438 whiteSpaceSeen = FALSE;
00439 c = 0;
00440 for (index = fromPos; *resWidth <= width && index < lastPos; index++) {
00441 lastWidth = *resWidth;
00442 if (index - blk.firstPos >= blk.length)
00443 XawTextSourceRead(source, index, &blk, BUFSIZ);
00444 c = blk.ptr[index - blk.firstPos];
00445 *resWidth += CharWidth(w, fromx + *resWidth, c);
00446
00447 if ((c == XawSP || c == XawTAB) && *resWidth <= width) {
00448 whiteSpaceSeen = TRUE;
00449 whiteSpacePosition = index;
00450 whiteSpaceWidth = *resWidth;
00451 }
00452 if (c == XawLF) {
00453 index++;
00454 break;
00455 }
00456 }
00457 if (*resWidth > width && index > fromPos) {
00458 *resWidth = lastWidth;
00459 index--;
00460 if (stopAtWordBreak && whiteSpaceSeen) {
00461 index = whiteSpacePosition + 1;
00462 *resWidth = whiteSpaceWidth;
00463 }
00464 }
00465 if (index == lastPos && c != XawLF) index = lastPos + 1;
00466 *resPos = index;
00467 *resHeight = sink->ascii_sink.font->ascent +sink->ascii_sink.font->descent;
00468 }
00469
00470 static void
00471 Resolve (w, pos, fromx, width, leftPos, rightPos)
00472 Widget w;
00473 XawTextPosition pos;
00474 int fromx, width;
00475 XawTextPosition *leftPos, *rightPos;
00476 {
00477 int resWidth, resHeight;
00478 Widget source = XawTextGetSource(XtParent(w));
00479
00480 FindPosition(w, pos, fromx, width, FALSE, leftPos, &resWidth, &resHeight);
00481 if (*leftPos > GETLASTPOS)
00482 *leftPos = GETLASTPOS;
00483 *rightPos = *leftPos;
00484 }
00485
00486 static void
00487 GetGC(sink)
00488 AsciiSinkObject sink;
00489 {
00490 XtGCMask valuemask = (GCFont |
00491 GCGraphicsExposures | GCForeground | GCBackground );
00492 XGCValues values;
00493
00494 values.font = sink->ascii_sink.font->fid;
00495 values.graphics_exposures = (Bool) FALSE;
00496
00497 values.foreground = sink->text_sink.foreground;
00498 values.background = sink->text_sink.background;
00499 sink->ascii_sink.normgc = XtGetGC((Widget)sink, valuemask, &values);
00500
00501 values.foreground = sink->text_sink.background;
00502 values.background = sink->text_sink.foreground;
00503 sink->ascii_sink.invgc = XtGetGC((Widget)sink, valuemask, &values);
00504
00505 values.function = GXxor;
00506 values.background = (unsigned long) 0L;
00507 values.foreground = (sink->text_sink.background ^
00508 sink->text_sink.foreground);
00509 valuemask = GCGraphicsExposures | GCFunction | GCForeground | GCBackground;
00510
00511 sink->ascii_sink.xorgc = XtGetGC((Widget)sink, valuemask, &values);
00512 }
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526 static void
00527 Initialize(request, new, args, num_args)
00528 Widget request, new;
00529 ArgList args;
00530 Cardinal *num_args;
00531 {
00532 AsciiSinkObject sink = (AsciiSinkObject) new;
00533
00534 GetGC(sink);
00535
00536 sink->ascii_sink.insertCursorOn= CreateInsertCursor(XtScreenOfObject(new));
00537 sink->ascii_sink.laststate = XawisOff;
00538 sink->ascii_sink.cursor_x = sink->ascii_sink.cursor_y = 0;
00539 }
00540
00541
00542
00543
00544
00545
00546
00547
00548 static void
00549 Destroy(w)
00550 Widget w;
00551 {
00552 AsciiSinkObject sink = (AsciiSinkObject) w;
00553
00554 XtReleaseGC(w, sink->ascii_sink.normgc);
00555 XtReleaseGC(w, sink->ascii_sink.invgc);
00556 XtReleaseGC(w, sink->ascii_sink.xorgc);
00557 XFreePixmap(XtDisplayOfObject(w), sink->ascii_sink.insertCursorOn);
00558 }
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569 static Boolean
00570 SetValues(current, request, new, args, num_args)
00571 Widget current, request, new;
00572 ArgList args;
00573 Cardinal *num_args;
00574 {
00575 AsciiSinkObject w = (AsciiSinkObject) new;
00576 AsciiSinkObject old_w = (AsciiSinkObject) current;
00577
00578 if (w->ascii_sink.font != old_w->ascii_sink.font
00579 || w->text_sink.background != old_w->text_sink.background
00580 || w->text_sink.foreground != old_w->text_sink.foreground) {
00581 XtReleaseGC((Widget)w, w->ascii_sink.normgc);
00582 XtReleaseGC((Widget)w, w->ascii_sink.invgc);
00583 XtReleaseGC((Widget)w, w->ascii_sink.xorgc);
00584 GetGC(w);
00585 ((TextWidget)XtParent(new))->text.redisplay_needed = True;
00586 } else {
00587 if ( (w->ascii_sink.echo != old_w->ascii_sink.echo) ||
00588 (w->ascii_sink.display_nonprinting !=
00589 old_w->ascii_sink.display_nonprinting) )
00590 ((TextWidget)XtParent(new))->text.redisplay_needed = True;
00591 }
00592
00593 return False;
00594 }
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605 static int
00606 MaxLines(w, height)
00607 Widget w;
00608 Dimension height;
00609 {
00610 AsciiSinkObject sink = (AsciiSinkObject) w;
00611 int font_height;
00612
00613 font_height = sink->ascii_sink.font->ascent + sink->ascii_sink.font->descent;
00614 return( ((int) height) / font_height );
00615 }
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 static int
00627 MaxHeight(w, lines)
00628 Widget w;
00629 int lines;
00630 {
00631 AsciiSinkObject sink = (AsciiSinkObject) w;
00632
00633 return(lines * (sink->ascii_sink.font->ascent +
00634 sink->ascii_sink.font->descent));
00635 }
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645 static void
00646 SetTabs(w, tab_count, tabs)
00647 Widget w;
00648 int tab_count;
00649 short *tabs;
00650 {
00651 AsciiSinkObject sink = (AsciiSinkObject) w;
00652 int i;
00653 Atom XA_FIGURE_WIDTH;
00654 unsigned long figure_width = 0;
00655 XFontStruct *font = sink->ascii_sink.font;
00656
00657
00658
00659
00660
00661 XA_FIGURE_WIDTH = XInternAtom(XtDisplayOfObject(w), "FIGURE_WIDTH", FALSE);
00662 if ( (XA_FIGURE_WIDTH != None) &&
00663 ( (!XGetFontProperty(font, XA_FIGURE_WIDTH, &figure_width)) ||
00664 (figure_width == 0)) )
00665 if (font->per_char && font->min_char_or_byte2 <= '$' &&
00666 font->max_char_or_byte2 >= '$')
00667 figure_width = font->per_char['$' - font->min_char_or_byte2].width;
00668 else
00669 figure_width = font->max_bounds.width;
00670
00671 if (tab_count > sink->text_sink.tab_count) {
00672 sink->text_sink.tabs = (Position *)
00673 XtRealloc((char *) sink->text_sink.tabs,
00674 (Cardinal) (tab_count * sizeof(Position)));
00675 sink->text_sink.char_tabs = (short *)
00676 XtRealloc((char *) sink->text_sink.char_tabs,
00677 (Cardinal) (tab_count * sizeof(short)));
00678 }
00679
00680 for ( i = 0 ; i < tab_count ; i++ ) {
00681 sink->text_sink.tabs[i] = tabs[i] * figure_width;
00682 sink->text_sink.char_tabs[i] = tabs[i];
00683 }
00684
00685 sink->text_sink.tab_count = tab_count;
00686
00687 #ifndef NO_TAB_FIX
00688 { TextWidget ctx = (TextWidget)XtParent(w);
00689 ctx->text.redisplay_needed = True;
00690 _XawTextBuildLineTable(ctx, ctx->text.lt.top, TRUE);
00691 }
00692 #endif
00693 }