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