~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/lib/Xaw/MultiSink.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Xorg: MultiSink.c,v 1.4 2001/02/09 02:03:44 xorgcvs Exp $ */
 
2
 
 
3
/*
 
4
 * Copyright 1991 by OMRON Corporation
 
5
 *
 
6
 * Permission to use, copy, modify, distribute, and sell this software and its
 
7
 * documentation for any purpose is hereby granted without fee, provided that
 
8
 * the above copyright notice appear in all copies and that both that
 
9
 * copyright notice and this permission notice appear in supporting
 
10
 * documentation, and that the name of OMRON not be used in advertising
 
11
 * or publicity pertaining to distribution of the software without specific,
 
12
 * written prior permission.  OMRON makes no representations about the
 
13
 * suitability of this software for any purpose.  It is provided "as is"
 
14
 * without express or implied warranty.
 
15
 *
 
16
 * OMRON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
17
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 
18
 * EVENT SHALL OMRON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
19
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 
20
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 
21
 * TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
22
 * PERFORMANCE OF THIS SOFTWARE.
 
23
 *
 
24
 *      Author: Li Yuhong        OMRON Corporation
 
25
 */
 
26
 
 
27
/***********************************************************
 
28
 
 
29
Copyright 1987, 1988, 1994, 1998  The Open Group
 
30
 
 
31
Permission to use, copy, modify, distribute, and sell this software and its
 
32
documentation for any purpose is hereby granted without fee, provided that
 
33
the above copyright notice appear in all copies and that both that
 
34
copyright notice and this permission notice appear in supporting
 
35
documentation.
 
36
 
 
37
The above copyright notice and this permission notice shall be included in
 
38
all copies or substantial portions of the Software.
 
39
 
 
40
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
41
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
42
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
43
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
44
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
45
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
46
 
 
47
Except as contained in this notice, the name of The Open Group shall not be
 
48
used in advertising or otherwise to promote the sale, use or other dealings
 
49
in this Software without prior written authorization from The Open Group.
 
50
 
 
51
 
 
52
Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
 
53
 
 
54
                        All Rights Reserved
 
55
 
 
56
Permission to use, copy, modify, and distribute this software and its 
 
57
documentation for any purpose and without fee is hereby granted, 
 
58
provided that the above copyright notice appear in all copies and that
 
59
both that copyright notice and this permission notice appear in 
 
60
supporting documentation, and that the name of Digital not be
 
61
used in advertising or publicity pertaining to distribution of the
 
62
software without specific, written prior permission.  
 
63
 
 
64
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 
65
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 
66
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 
67
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 
68
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 
69
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 
70
SOFTWARE.
 
71
 
 
72
******************************************************************/
 
73
/* $XFree86: xc/lib/Xaw/MultiSink.c,v 1.20 2001/12/14 19:54:41 dawes Exp $ */
 
74
 
 
75
#include <X11/IntrinsicP.h>
 
76
#include <X11/StringDefs.h>
 
77
#include <X11/Xatom.h>
 
78
#include <X11/Xaw/XawInit.h>
 
79
#include <X11/Xaw/MultiSinkP.h>
 
80
#include <X11/Xaw/MultiSrcP.h>
 
81
#include <X11/Xaw/TextP.h>
 
82
#include "XawI18n.h"
 
83
#include <stdio.h>
 
84
#include <ctype.h>
 
85
#include "Private.h"
 
86
 
 
87
#ifdef GETLASTPOS
 
88
#undef GETLASTPOS               /* We will use our own GETLASTPOS */
 
89
#endif
 
90
 
 
91
#define GETLASTPOS      \
 
92
        XawTextSourceScan(source, 0, XawstAll, XawsdRight, 1, True)
 
93
 
 
94
/*
 
95
 * Class Methods
 
96
 */
 
97
static void XawMultiSinkClassInitialize(void);
 
98
static void XawMultiSinkInitialize(Widget, Widget, ArgList, Cardinal*);
 
99
static void XawMultiSinkDestroy(Widget);
 
100
static void XawMultiSinkResize(Widget);
 
101
static Boolean XawMultiSinkSetValues(Widget, Widget, Widget,
 
102
                                     ArgList, Cardinal*);
 
103
static int MaxLines(Widget, unsigned int);
 
104
static int MaxHeight(Widget, int);
 
105
static void SetTabs(Widget, int, short*);
 
106
static void DisplayText(Widget, int, int,
 
107
                        XawTextPosition, XawTextPosition, Bool);
 
108
static void InsertCursor(Widget, int, int, XawTextInsertState);
 
109
static void FindPosition(Widget, XawTextPosition, int, int, Bool,
 
110
                         XawTextPosition*, int*, int*);
 
111
static void FindDistance(Widget, XawTextPosition, int, XawTextPosition, int*,
 
112
                         XawTextPosition*, int*);
 
113
static void Resolve(Widget, XawTextPosition, int, int, XawTextPosition*);
 
114
static void GetCursorBounds(Widget, XRectangle*);
 
115
 
 
116
/*
 
117
 * Prototypes
 
118
 */
 
119
static void GetGC(MultiSinkObject);
 
120
static int CharWidth(MultiSinkObject, XFontSet, int, wchar_t);
 
121
static unsigned int PaintText(Widget w, GC gc, int x, int y,
 
122
                              wchar_t *buf, int len, Bool);
 
123
 
 
124
/*
 
125
 * Defined in TextSink.c
 
126
 */
 
127
void _XawTextSinkClearToBackground(Widget, int, int, unsigned, unsigned);
 
128
 
 
129
/*
 
130
 * Initialization
 
131
 */
 
132
static wchar_t wspace[2];
 
133
 
 
134
#define offset(field) XtOffsetOf(MultiSinkRec, multi_sink.field)
 
135
static XtResource resources[] = {
 
136
  {
 
137
    XtNfontSet,
 
138
    XtCFontSet,
 
139
    XtRFontSet,
 
140
    sizeof(XFontSet),
 
141
    offset(fontset),
 
142
    XtRString,
 
143
    XtDefaultFontSet
 
144
  },
 
145
  {
 
146
    XtNecho,
 
147
    XtCOutput,
 
148
    XtRBoolean,
 
149
    sizeof(Boolean),
 
150
    offset(echo),
 
151
    XtRImmediate,
 
152
    (XtPointer)True
 
153
  },
 
154
  {
 
155
    XtNdisplayNonprinting,
 
156
    XtCOutput,
 
157
    XtRBoolean,
 
158
    sizeof(Boolean),
 
159
    offset(display_nonprinting),
 
160
    XtRImmediate,
 
161
    (XtPointer)True
 
162
  },
 
163
};
 
164
#undef offset
 
165
 
 
166
#define SuperClass              (&textSinkClassRec)
 
167
MultiSinkClassRec multiSinkClassRec = {
 
168
  /* object */
 
169
  {
 
170
    (WidgetClass)SuperClass,            /* superclass */
 
171
    "MultiSink",                        /* class_name */
 
172
    sizeof(MultiSinkRec),               /* widget_size */
 
173
    XawMultiSinkClassInitialize,        /* class_initialize */
 
174
    NULL,                               /* class_part_initialize */
 
175
    False,                              /* class_inited */
 
176
    XawMultiSinkInitialize,             /* initialize */
 
177
    NULL,                               /* initialize_hook */
 
178
    NULL,                               /* obj1 */
 
179
    NULL,                               /* obj2 */
 
180
    0,                                  /* obj3 */
 
181
    resources,                          /* resources */
 
182
    XtNumber(resources),                /* num_resources */
 
183
    NULLQUARK,                          /* xrm_class */
 
184
    False,                              /* obj4 */
 
185
    False,                              /* obj5 */
 
186
    False,                              /* obj6 */
 
187
    False,                              /* obj7 */
 
188
    XawMultiSinkDestroy,                /* destroy */
 
189
    (XtProc)XawMultiSinkResize,         /* obj8 */
 
190
    NULL,                               /* obj9 */
 
191
    XawMultiSinkSetValues,              /* set_values */
 
192
    NULL,                               /* set_values_hook */
 
193
    NULL,                               /* obj10 */
 
194
    NULL,                               /* get_values_hook */
 
195
    NULL,                               /* obj11 */
 
196
    XtVersion,                          /* version */
 
197
    NULL,                               /* callback_private */
 
198
    NULL,                               /* obj12 */
 
199
    NULL,                               /* obj13 */
 
200
    NULL,                               /* obj14 */
 
201
    NULL,                               /* extension */
 
202
  },
 
203
    /* text_sink */
 
204
  {
 
205
    DisplayText,                        /* DisplayText */
 
206
    InsertCursor,                       /* InsertCursor */
 
207
    XtInheritClearToBackground,         /* ClearToBackground */
 
208
    FindPosition,                       /* FindPosition */
 
209
    FindDistance,                       /* FindDistance */
 
210
    Resolve,                            /* Resolve */
 
211
    MaxLines,                           /* MaxLines */
 
212
    MaxHeight,                          /* MaxHeight */
 
213
    SetTabs,                            /* SetTabs */
 
214
    GetCursorBounds,                    /* GetCursorBounds */
 
215
  },
 
216
  /* multi_sink */
 
217
  {
 
218
    NULL,                               /* extension */
 
219
  }
 
220
};
 
221
 
 
222
WidgetClass multiSinkObjectClass = (WidgetClass)&multiSinkClassRec;
 
223
 
 
224
/*
 
225
 * Implementation
 
226
 */
 
227
static int
 
228
CharWidth(MultiSinkObject sink, XFontSet fontset, int x, wchar_t c)
 
229
{
 
230
    int width = 0;
 
231
 
 
232
    if (c == _Xaw_atowc(XawLF))
 
233
        return (0);
 
234
 
 
235
    if (c == _Xaw_atowc(XawTAB)) {
 
236
        int i;
 
237
        Position *tab;
 
238
 
 
239
        width = x;
 
240
        /* Adjust for Left Margin. */
 
241
        x -= ((TextWidget)XtParent((Widget)sink))->text.left_margin;
 
242
 
 
243
        i = 0;
 
244
        tab = sink->text_sink.tabs;
 
245
        /*CONSTCOND*/
 
246
        while (1) {
 
247
            if (x < *tab)
 
248
                return (*tab - x);
 
249
            /* Start again */
 
250
            if (++i >= sink->text_sink.tab_count) {
 
251
                x -= *tab;
 
252
                i = 0;
 
253
                tab = sink->text_sink.tabs;
 
254
                if (width == x)
 
255
                    return (0);
 
256
            }
 
257
            else
 
258
                ++tab;
 
259
        }
 
260
        /*NOTREACHED*/
 
261
    }
 
262
 
 
263
    if (XwcTextEscapement(fontset, &c, 1) == 0) {
 
264
        if (sink->multi_sink.display_nonprinting)
 
265
            c = _Xaw_atowc('@');
 
266
        else
 
267
            c = _Xaw_atowc(XawSP);
 
268
    }
 
269
 
 
270
      /*
 
271
       * if more efficiency(suppose one column is one ASCII char)
 
272
 
 
273
      width = XwcGetColumn(fontset->font_charset, fontset->num_of_fonts, c) *
 
274
              fontset->font_struct_list[0]->min_bounds.width;
 
275
       *
 
276
       * WARNING: Very Slower!!!
 
277
       *
 
278
       * Li Yuhong.
 
279
       */
 
280
 
 
281
    width = XwcTextEscapement(fontset, &c, 1);
 
282
 
 
283
    return (width);
 
284
}
 
285
 
 
286
/*
 
287
 * Function:
 
288
 *      PaintText
 
289
 *
 
290
 * Parameters:
 
291
 *      w   - text sink object
 
292
 *      gc  - gc to paint text
 
293
 *      x   - location to paint the text
 
294
 *      y   - ""
 
295
 *      buf - buffer and length of text to paint
 
296
 *      len - ""
 
297
 *      clear_bg - clear background before drawing ?
 
298
 *
 
299
 * Description:
 
300
 *      Actually paints the text into the window.
 
301
 *
 
302
 * Returns:
 
303
 *      The width of the text painted
 
304
 */
 
305
static unsigned int
 
306
PaintText(Widget w, GC gc, int x, int y, wchar_t *buf, int len, Bool clear_bg)
 
307
{
 
308
    MultiSinkObject sink = (MultiSinkObject)w;
 
309
    TextWidget ctx = (TextWidget)XtParent(w);
 
310
    XFontSet fontset = sink->multi_sink.fontset;
 
311
    unsigned int width = XwcTextEscapement(fontset, buf, len);
 
312
 
 
313
    if (((int)width) <= -x)             /* Don't draw if we can't see it */
 
314
        return (width);
 
315
 
 
316
    if (clear_bg) {
 
317
        XFontSetExtents *ext = XExtentsOfFontSet(fontset);
 
318
 
 
319
        _XawTextSinkClearToBackground(w, x, y - abs(ext->max_logical_extent.y),
 
320
                                      width, ext->max_logical_extent.height);
 
321
        XwcDrawString(XtDisplay(ctx), XtWindow(ctx), fontset, gc, x, y, buf, len);
 
322
    }
 
323
    else
 
324
        XwcDrawImageString(XtDisplay(ctx), XtWindow(ctx), fontset, gc,
 
325
                           x, y, buf, len);
 
326
 
 
327
    return (width);
 
328
}
 
329
 
 
330
/* Sink Object Functions */
 
331
/*
 
332
 * This function does not know about drawing more than one line of text
 
333
 */
 
334
static void
 
335
DisplayText(Widget w, int x, int y,
 
336
            XawTextPosition pos1, XawTextPosition pos2, Bool highlight)
 
337
{
 
338
    TextWidget ctx = (TextWidget)XtParent(w);
 
339
    MultiSinkObject sink = (MultiSinkObject)w;
 
340
    XFontSet fontset = sink->multi_sink.fontset;
 
341
    Widget source = XawTextGetSource(XtParent(w));
 
342
    wchar_t buf[256];
 
343
    XFontSetExtents *ext = XExtentsOfFontSet(fontset);
 
344
    int j, k;
 
345
    XawTextBlock blk;
 
346
    GC gc, invgc, tabgc;
 
347
    int max_x;
 
348
    Bool clear_bg;
 
349
 
 
350
    if (!sink->multi_sink.echo || !ctx->text.lt.lines)
 
351
        return;
 
352
 
 
353
    max_x = (int)XtWidth(ctx) - ctx->text.r_margin.right;
 
354
    clear_bg = !highlight && ctx->core.background_pixmap != XtUnspecifiedPixmap;
 
355
 
 
356
    gc = highlight ? sink->multi_sink.invgc : sink->multi_sink.normgc;
 
357
    invgc = highlight ? sink->multi_sink.normgc : sink->multi_sink.invgc;
 
358
 
 
359
    if (highlight && sink->multi_sink.xorgc)
 
360
        tabgc = sink->multi_sink.xorgc;
 
361
    else
 
362
        tabgc = invgc;
 
363
 
 
364
    y += abs(ext->max_logical_extent.y);
 
365
    for (j = 0; pos1 < pos2;) {
 
366
        pos1 = XawTextSourceRead(source, pos1, &blk, (int) pos2 - pos1);
 
367
        for (k = 0; k < blk.length; k++) {
 
368
            if ((unsigned) j >= (sizeof(buf) / sizeof(wchar_t)) - 1) {
 
369
                /* buffer full, dump the text */
 
370
                if ((x += PaintText(w, gc, x, y, buf, j, clear_bg)) >= max_x)
 
371
                    return;
 
372
                j = 0;
 
373
            }
 
374
            buf[j] = ((wchar_t *)blk.ptr)[k];
 
375
            if (buf[j] == _Xaw_atowc(XawLF))
 
376
                continue;
 
377
 
 
378
            else if (buf[j] == _Xaw_atowc(XawTAB)) {
 
379
                unsigned int width;
 
380
 
 
381
                if (j != 0 &&
 
382
                    (x += PaintText(w, gc, x, y, buf, j, clear_bg)) >= max_x)
 
383
                    return;
 
384
 
 
385
                width = CharWidth(sink, fontset, x, _Xaw_atowc(XawTAB));
 
386
                if (clear_bg)
 
387
                    _XawTextSinkClearToBackground(w,
 
388
                                        x, y - abs(ext->max_logical_extent.y),
 
389
                                        width, ext->max_logical_extent.height);
 
390
                else
 
391
                    XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
 
392
                                   tabgc, x,
 
393
                                   y - abs(ext->max_logical_extent.y),
 
394
                                   width,
 
395
                                   ext->max_logical_extent.height);
 
396
                x += width;
 
397
                j = -1;
 
398
            }
 
399
            else if (XwcTextEscapement(sink->multi_sink.fontset, &buf[j], 1)
 
400
                     == 0) {
 
401
                if (sink->multi_sink.display_nonprinting)
 
402
                    buf[j] = _Xaw_atowc('@');
 
403
                else
 
404
                    buf[j] = _Xaw_atowc(XawSP);
 
405
            }
 
406
            j++;
 
407
        }
 
408
    }
 
409
 
 
410
    if (j > 0)
 
411
        (void)PaintText(w, gc, x, y, buf, j, clear_bg);
 
412
}
 
413
 
 
414
/*
 
415
 * Function:
 
416
 *      GetCursorBounds
 
417
 *
 
418
 * Parameters:
 
419
 *      w    - text sink object
 
420
 *      rect - X rectangle to return the cursor bounds
 
421
 *
 
422
 * Description:
 
423
 *      Returns the size and location of the cursor.
 
424
 */
 
425
static void
 
426
GetCursorBounds(Widget w, XRectangle *rect)
 
427
{
 
428
    MultiSinkObject sink = (MultiSinkObject)w;
 
429
 
 
430
    rect->width = CharWidth(sink, sink->multi_sink.fontset, 0, _Xaw_atowc(XawSP));
 
431
    rect->height = (XExtentsOfFontSet(sink->multi_sink.fontset)
 
432
                    ->max_logical_extent.height);
 
433
    rect->x = sink->multi_sink.cursor_x;
 
434
    rect->y = sink->multi_sink.cursor_y - (short)rect->height;
 
435
}
 
436
 
 
437
/*
 
438
 * The following procedure manages the "insert" cursor
 
439
 */
 
440
static void
 
441
InsertCursor(Widget w, int x, int y, XawTextInsertState state)
 
442
{
 
443
    MultiSinkObject sink = (MultiSinkObject)w;
 
444
    XFontSet fontset = sink->multi_sink.fontset;
 
445
    Widget ctx = XtParent(w);
 
446
    XawTextPosition position = XawTextGetInsertionPoint(ctx);
 
447
 
 
448
    if (XtIsRealized(ctx)) {
 
449
        int fheight, fdiff;
 
450
        XawTextBlock block;
 
451
        wchar_t c;
 
452
        XawTextPosition selection_start, selection_end;
 
453
        Boolean has_selection;
 
454
        XFontSetExtents *ext = XExtentsOfFontSet(fontset);
 
455
 
 
456
        XawTextGetSelectionPos((Widget)ctx, &selection_start, &selection_end);
 
457
        has_selection = selection_start != selection_end;
 
458
 
 
459
        fheight = ext->max_logical_extent.height;
 
460
        fdiff = fheight - abs(ext->max_logical_extent.y);
 
461
 
 
462
        if ((sink->multi_sink.cursor_position != position || state == XawisOff)
 
463
            && !has_selection && sink->multi_sink.laststate != XawisOff) {
 
464
            wchar_t *ochar;
 
465
 
 
466
            (void)XawTextSourceRead(XawTextGetSource(ctx),
 
467
                                    sink->multi_sink.cursor_position,
 
468
                                    &block, 1);
 
469
            if (!block.length)
 
470
                ochar = NULL;
 
471
            else {
 
472
                c = ((wchar_t *)block.ptr)[0];
 
473
                if (c == _Xaw_atowc(XawLF))
 
474
                    ochar = NULL;
 
475
                else if (c == _Xaw_atowc(XawTAB))
 
476
                    ochar = wspace;
 
477
                else
 
478
                    ochar = (wchar_t *)block.ptr;
 
479
            }
 
480
 
 
481
            if (!ochar)
 
482
                _XawTextSinkClearToBackground(w, sink->multi_sink.cursor_x,
 
483
                                              (sink->multi_sink.cursor_y - 1 -
 
484
                                              fheight), CharWidth(sink, fontset,
 
485
                                                                  0, wspace[0]),
 
486
                                              fheight);
 
487
            else {
 
488
                if (XwcTextEscapement(sink->multi_sink.fontset, ochar, 1) != 0)
 
489
                    DisplayText(w, sink->multi_sink.cursor_x,
 
490
                                sink->multi_sink.cursor_y - 1 - fheight,
 
491
                                sink->multi_sink.cursor_position,
 
492
                                sink->multi_sink.cursor_position + 1,
 
493
                                False);
 
494
                else
 
495
                    PaintText(w, sink->multi_sink.normgc,
 
496
                              sink->multi_sink.cursor_x,
 
497
                              sink->multi_sink.cursor_y - 1 - fdiff,
 
498
                              ochar, 1,
 
499
                              ctx->core.background_pixmap != XtUnspecifiedPixmap);
 
500
            }
 
501
        }
 
502
 
 
503
        if (!has_selection && state != XawisOff) {
 
504
            wchar_t *nchar;
 
505
            Boolean focus = ((TextWidget)ctx)->text.hasfocus;
 
506
 
 
507
            (void)XawTextSourceRead(XawTextGetSource(ctx),
 
508
                                    position, &block, 1);
 
509
            c = ((wchar_t *)block.ptr)[0];
 
510
            if (!block.length || c == _Xaw_atowc(XawLF)
 
511
                || c == _Xaw_atowc(XawTAB))
 
512
                nchar = wspace;
 
513
            else
 
514
                nchar = (wchar_t *)block.ptr;
 
515
 
 
516
            if (focus) {
 
517
                if (XwcTextEscapement(sink->multi_sink.fontset, nchar, 1) != 0)
 
518
                    XwcDrawImageString(XtDisplay(ctx), XtWindow(ctx),
 
519
                                       fontset, sink->multi_sink.invgc,
 
520
                                       x, (y - 1 - fdiff), nchar, 1);
 
521
                else
 
522
                    DisplayText(w, x, y - 1 - fheight,
 
523
                                position, position + 1, True);
 
524
            }
 
525
            else
 
526
                XDrawRectangle(XtDisplay(ctx), XtWindow(ctx),
 
527
                               sink->multi_sink.xorgc ?
 
528
                               sink->multi_sink.xorgc : sink->multi_sink.normgc,
 
529
                               x, y - 1 - fheight,
 
530
                               CharWidth(sink, fontset, 0, *nchar) - 1,
 
531
                               fheight - 1);
 
532
          }
 
533
      }
 
534
 
 
535
    sink->multi_sink.cursor_x = x;
 
536
    sink->multi_sink.cursor_y = y;
 
537
    sink->multi_sink.laststate = state;
 
538
    sink->multi_sink.cursor_position = position;
 
539
}
 
540
 
 
541
/*
 
542
 * Given two positions, find the distance between them
 
543
 */
 
544
static void
 
545
FindDistance(Widget w, XawTextPosition fromPos, int fromx,
 
546
             XawTextPosition toPos, int *resWidth,
 
547
             XawTextPosition *resPos, int *resHeight)
 
548
{
 
549
    MultiSinkObject sink = (MultiSinkObject)w;
 
550
    XFontSet fontset = sink->multi_sink.fontset;
 
551
    TextWidget ctx = (TextWidget)XtParent(w);
 
552
    Widget source = ctx->text.source;
 
553
    XawTextPosition idx, pos;
 
554
    wchar_t c;
 
555
    XFontSetExtents *ext = XExtentsOfFontSet(fontset);
 
556
    XawTextBlock blk;
 
557
    int i, rWidth;
 
558
 
 
559
    pos = XawTextSourceRead(source, fromPos, &blk, toPos - fromPos);
 
560
    rWidth = 0;
 
561
    for (i = 0, idx = fromPos; idx < toPos; i++, idx++) {
 
562
        if (i >= blk.length) {
 
563
            i = 0;
 
564
            XawTextSourceRead(source, pos, &blk, toPos - pos);
 
565
            if (blk.length == 0)
 
566
                break;
 
567
        }
 
568
        c = ((wchar_t *)blk.ptr)[i];
 
569
        rWidth += CharWidth(sink, fontset, fromx + rWidth, c);
 
570
        if (c == _Xaw_atowc(XawLF)) {
 
571
            idx++;
 
572
            break;
 
573
        }
 
574
    }
 
575
 
 
576
    *resPos = idx;
 
577
    *resWidth = rWidth;
 
578
    *resHeight = ext->max_logical_extent.height;
 
579
}
 
580
 
 
581
static void
 
582
FindPosition(Widget w, XawTextPosition fromPos, int fromx, int width,
 
583
             Bool stopAtWordBreak, XawTextPosition *resPos, int *resWidth,
 
584
             int *resHeight)
 
585
{
 
586
    MultiSinkObject sink = (MultiSinkObject)w;
 
587
    TextWidget ctx = (TextWidget)XtParent(w);
 
588
    Widget source = ctx->text.source;
 
589
    XFontSet fontset = sink->multi_sink.fontset;
 
590
    XawTextPosition idx, pos, whiteSpacePosition = 0;
 
591
    int i, lastWidth, whiteSpaceWidth, rWidth;
 
592
    Boolean whiteSpaceSeen;
 
593
    wchar_t c;
 
594
    XFontSetExtents *ext = XExtentsOfFontSet(fontset);
 
595
    XawTextBlock blk;
 
596
 
 
597
    pos = XawTextSourceRead(source, fromPos, &blk, BUFSIZ);
 
598
    rWidth = lastWidth = whiteSpaceWidth = 0;
 
599
    whiteSpaceSeen = False;
 
600
    c = 0;
 
601
 
 
602
    for (i = 0, idx = fromPos; rWidth <= width; i++, idx++) {
 
603
        if (i >= blk.length) {
 
604
            i = 0;
 
605
            pos = XawTextSourceRead(source, pos, &blk, BUFSIZ);
 
606
            if (blk.length == 0)
 
607
                break;
 
608
        }
 
609
        c = ((wchar_t *)blk.ptr)[i];
 
610
        lastWidth = rWidth;
 
611
        rWidth += CharWidth(sink, fontset, fromx + rWidth, c);
 
612
 
 
613
        if (c == _Xaw_atowc(XawLF)) {
 
614
            idx++;
 
615
            break;
 
616
        }
 
617
        else if ((c == _Xaw_atowc(XawSP) || c == _Xaw_atowc(XawTAB))
 
618
                 && rWidth <= width) {
 
619
            whiteSpaceSeen = True;
 
620
            whiteSpacePosition = idx;
 
621
            whiteSpaceWidth = rWidth;
 
622
        }
 
623
    }
 
624
 
 
625
    if (rWidth > width && idx > fromPos) {
 
626
        idx--;
 
627
        rWidth = lastWidth;
 
628
        if (stopAtWordBreak && whiteSpaceSeen) {
 
629
            idx = whiteSpacePosition + 1;
 
630
            rWidth = whiteSpaceWidth;
 
631
        }
 
632
    }
 
633
 
 
634
    if (idx >= ctx->text.lastPos && c != _Xaw_atowc(XawLF))
 
635
        idx = ctx->text.lastPos + 1;
 
636
 
 
637
    *resPos = idx;
 
638
    *resWidth = rWidth;
 
639
    *resHeight = ext->max_logical_extent.height;
 
640
}
 
641
 
 
642
static void
 
643
Resolve(Widget w, XawTextPosition pos, int fromx, int width,
 
644
        XawTextPosition *pos_return)
 
645
{
 
646
    int resWidth, resHeight;
 
647
    Widget source = XawTextGetSource(XtParent(w));
 
648
 
 
649
    FindPosition(w, pos, fromx, width, False, pos_return, &resWidth, &resHeight);
 
650
    if (*pos_return > GETLASTPOS)
 
651
        *pos_return = GETLASTPOS;
 
652
}
 
653
 
 
654
static void
 
655
GetGC(MultiSinkObject sink)
 
656
{
 
657
    XtGCMask valuemask = (GCGraphicsExposures | GCClipXOrigin |
 
658
                          GCForeground | GCBackground);
 
659
    XGCValues values;
 
660
 
 
661
    /* XXX We dont want do share a gc that will change the clip-mask */
 
662
    values.clip_x_origin = (long)sink;
 
663
    values.clip_mask = None;
 
664
    values.graphics_exposures = False;
 
665
    
 
666
    values.foreground = sink->text_sink.foreground;
 
667
    values.background = sink->text_sink.background;
 
668
 
 
669
    sink->multi_sink.normgc = XtAllocateGC((Widget)sink, 0, valuemask, &values,
 
670
                                           GCFont | GCClipMask, 0);
 
671
 
 
672
    values.foreground = sink->text_sink.background;
 
673
#ifndef OLDXAW
 
674
    values.background = sink->text_sink.cursor_color;
 
675
#else
 
676
    values.background = sink->text_sink.foreground;
 
677
#endif
 
678
    sink->multi_sink.invgc = XtAllocateGC((Widget)sink, 0, valuemask, &values,
 
679
                                          GCFont | GCClipMask, 0);
 
680
#ifndef OLDXAW
 
681
    if (sink->text_sink.cursor_color != sink->text_sink.foreground) {
 
682
        values.foreground = sink->text_sink.cursor_color;
 
683
        values.background = sink->text_sink.foreground;
 
684
        sink->multi_sink.xorgc = XtAllocateGC((Widget)sink, 0, valuemask,
 
685
                                              &values, GCFont | GCClipMask, 0);
 
686
    }
 
687
    else
 
688
#endif /* OLDXAW */
 
689
        sink->multi_sink.xorgc = NULL;
 
690
 
 
691
    XawMultiSinkResize((Widget)sink);
 
692
}
 
693
 
 
694
static void
 
695
XawMultiSinkClassInitialize(void)
 
696
{
 
697
    wspace[0] = _Xaw_atowc(XawSP);
 
698
    XawInitializeWidgetSet();
 
699
}
 
700
 
 
701
/*
 
702
 * Function:
 
703
 *      XawMultiSinkInitialize
 
704
 *
 
705
 * Parameters:
 
706
 *      request - requested and new values for the object instance
 
707
 *      cnew    - ""
 
708
 *
 
709
 * Description:
 
710
 *      Initializes the TextSink Object.
 
711
 */
 
712
/* ARGSUSED */
 
713
static void
 
714
XawMultiSinkInitialize(Widget request, Widget cnew,
 
715
                       ArgList args, Cardinal *num_args)
 
716
{
 
717
    MultiSinkObject sink = (MultiSinkObject)cnew;
 
718
 
 
719
    GetGC(sink);
 
720
 
 
721
    sink->multi_sink.cursor_position = 0;
 
722
    sink->multi_sink.laststate = XawisOff;
 
723
    sink->multi_sink.cursor_x = sink->multi_sink.cursor_y = 0;
 
724
}
 
725
 
 
726
/*
 
727
 * Function:
 
728
 *      XawMultiSinkDestroy
 
729
 *
 
730
 * Parameters:
 
731
 *      w - MultiSink Object
 
732
 *
 
733
 * Description:
 
734
 *      This function cleans up when the object is destroyed.
 
735
 */
 
736
static void
 
737
XawMultiSinkDestroy(Widget w)
 
738
{
 
739
    MultiSinkObject sink = (MultiSinkObject)w;
 
740
 
 
741
    XtReleaseGC(w, sink->multi_sink.normgc);
 
742
    XtReleaseGC(w, sink->multi_sink.invgc);
 
743
    if (sink->multi_sink.xorgc)
 
744
        XtReleaseGC(w, sink->multi_sink.xorgc);
 
745
    sink->multi_sink.normgc =
 
746
        sink->multi_sink.invgc =
 
747
        sink->multi_sink.xorgc = NULL;
 
748
}
 
749
 
 
750
static void
 
751
XawMultiSinkResize(Widget w)
 
752
{
 
753
    TextWidget ctx = (TextWidget)XtParent(w);
 
754
    MultiSinkObject sink = (MultiSinkObject)w;
 
755
    XRectangle rect;
 
756
    int width, height;
 
757
 
 
758
    if (w->core.widget_class != multiSinkObjectClass)
 
759
        return;
 
760
 
 
761
    rect.x = ctx->text.r_margin.left;
 
762
    rect.y = ctx->text.r_margin.top;
 
763
    width = (int)XtWidth(ctx) -
 
764
      (int)ctx->text.r_margin.right - (int)ctx->text.r_margin.left;
 
765
    height = (int)XtHeight(ctx) -
 
766
      (int)ctx->text.r_margin.top - (int)ctx->text.r_margin.bottom;
 
767
    rect.width = width;
 
768
    rect.height = height;
 
769
 
 
770
    if (sink->multi_sink.normgc) {
 
771
        if (width >= 0 && height >= 0)
 
772
            XSetClipRectangles(XtDisplay((Widget)ctx), sink->multi_sink.normgc,
 
773
                               0, 0, &rect, 1, Unsorted);
 
774
        else
 
775
            XSetClipMask(XtDisplay((Widget)ctx), sink->multi_sink.normgc, None);
 
776
    }
 
777
    if (sink->multi_sink.invgc) {
 
778
        if (width >= 0 && height >= 0)
 
779
            XSetClipRectangles(XtDisplay((Widget)ctx), sink->multi_sink.invgc,
 
780
                               0, 0, &rect, 1, Unsorted);
 
781
        else
 
782
            XSetClipMask(XtDisplay((Widget)ctx), sink->multi_sink.invgc, None);
 
783
    }
 
784
    if (sink->multi_sink.xorgc) {
 
785
        if (width >= 0 && height >= 0)
 
786
            XSetClipRectangles(XtDisplay((Widget)ctx), sink->multi_sink.xorgc,
 
787
                               0, 0, &rect, 1, Unsorted);
 
788
        else
 
789
            XSetClipMask(XtDisplay((Widget)ctx), sink->multi_sink.xorgc, None);
 
790
    }
 
791
}
 
792
 
 
793
/*
 
794
 * Function:
 
795
 *      XawMultiSinkSetValues
 
796
 *
 
797
 * Parameters:
 
798
 *      current - current state of the object
 
799
 *      request - what was requested
 
800
 *      cnew    - what the object will become
 
801
 *
 
802
 * Description:
 
803
 *      Sets the values for the MultiSink.
 
804
 *
 
805
 * Returns:
 
806
 *      True if redisplay is needed
 
807
 */
 
808
/*ARGSUSED*/
 
809
static Boolean
 
810
XawMultiSinkSetValues(Widget current, Widget request, Widget cnew,
 
811
                      ArgList args, Cardinal *num_args)
 
812
{
 
813
    MultiSinkObject w = (MultiSinkObject)cnew;
 
814
    MultiSinkObject old_w = (MultiSinkObject)current;
 
815
 
 
816
    /* Font set is not in the GC! Do not make a new GC when font set changes! */
 
817
 
 
818
    if (w->multi_sink.fontset != old_w->multi_sink.fontset) {
 
819
        ((TextWidget)XtParent(cnew))->text.redisplay_needed = True;
 
820
#ifndef NO_TAB_FIX
 
821
        SetTabs((Widget)w, w->text_sink.tab_count, w->text_sink.char_tabs);
 
822
#endif
 
823
    }
 
824
 
 
825
    if (w->text_sink.background != old_w->text_sink.background
 
826
        || w->text_sink.foreground != old_w->text_sink.foreground
 
827
#ifndef OLDXAW
 
828
        || w->text_sink.cursor_color != old_w->text_sink.cursor_color
 
829
#endif
 
830
        ) {
 
831
        XtReleaseGC(cnew, w->multi_sink.normgc);
 
832
        XtReleaseGC(cnew, w->multi_sink.invgc);
 
833
        if (w->multi_sink.xorgc)
 
834
            XtReleaseGC(cnew, w->multi_sink.xorgc);
 
835
        GetGC(w);
 
836
        ((TextWidget)XtParent(cnew))->text.redisplay_needed = True;
 
837
    }
 
838
    else if (w->multi_sink.echo != old_w->multi_sink.echo
 
839
             || w->multi_sink.display_nonprinting
 
840
             != old_w->multi_sink.display_nonprinting)
 
841
      ((TextWidget)XtParent(cnew))->text.redisplay_needed = True;
 
842
 
 
843
    return (False);
 
844
}
 
845
 
 
846
/*
 
847
 * Function:
 
848
 *      MaxLines
 
849
 *
 
850
 * Parameters:
 
851
 *      w - MultiSink Object
 
852
 *      height - height to fit lines into
 
853
 *
 
854
 * Description:
 
855
 *      Finds the Maximum number of lines that will fit in a given height.
 
856
 *
 
857
 * Returns:
 
858
 *      The number of lines that will fit
 
859
 */
 
860
/*ARGSUSED*/
 
861
static int
 
862
MaxLines(Widget w, unsigned int height)
 
863
{
 
864
    MultiSinkObject sink = (MultiSinkObject)w;
 
865
    int font_height;
 
866
    XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset);
 
867
 
 
868
    font_height = ext->max_logical_extent.height;
 
869
    return (height / font_height);
 
870
}
 
871
 
 
872
/*
 
873
 * Function:
 
874
 *      MaxHeight
 
875
 *
 
876
 * Parameters:
 
877
 *      w     - MultiSink Object
 
878
 *      lines - number of lines
 
879
 *
 
880
 * Description:
 
881
 *      Finds the Minium height that will contain a given number lines.
 
882
 * Returns:
 
883
 *      The height
 
884
 */
 
885
/*ARGSUSED*/
 
886
static int
 
887
MaxHeight(Widget w, int lines)
 
888
{
 
889
    MultiSinkObject sink = (MultiSinkObject)w;
 
890
    XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset);
 
891
 
 
892
    return (lines * ext->max_logical_extent.height);
 
893
}
 
894
 
 
895
/*
 
896
 * Function:
 
897
 *      SetTabs
 
898
 *
 
899
 * Arguments:
 
900
 *      w         - MultiSink Object
 
901
 *      tab_count - number of tabs in the list
 
902
 *      tabs      - text positions of the tabs
 
903
 *
 
904
 * Description:
 
905
 *      Sets the Tab stops.
 
906
 */
 
907
static void
 
908
SetTabs(Widget w, int tab_count, short* tabs)
 
909
{
 
910
    MultiSinkObject sink = (MultiSinkObject)w;
 
911
    int i;
 
912
    Atom XA_FIGURE_WIDTH;
 
913
    unsigned long figure_width = 0;
 
914
    XFontStruct *font;
 
915
 
 
916
    /*
 
917
     * Bug:
 
918
     *   Suppose the first font of fontset stores the unit of column.
 
919
     *
 
920
     * By Li Yuhong, Mar. 14, 1991
 
921
     */
 
922
    {
 
923
        XFontStruct **f_list;
 
924
        char **f_name;
 
925
 
 
926
        (void)XFontsOfFontSet(sink->multi_sink.fontset, &f_list, &f_name);
 
927
        font = f_list[0];
 
928
    }
 
929
 
 
930
    /*
 
931
     * Find the figure width of the current font
 
932
     */
 
933
    XA_FIGURE_WIDTH = XInternAtom(XtDisplayOfObject(w), "FIGURE_WIDTH", False);
 
934
    if (XA_FIGURE_WIDTH != None
 
935
        && (!XGetFontProperty(font, XA_FIGURE_WIDTH, &figure_width)
 
936
            || figure_width == 0)) {
 
937
        if (font->per_char && font->min_char_or_byte2 <= '$'
 
938
            && font->max_char_or_byte2 >= '$')
 
939
            figure_width = font->per_char['$' - font->min_char_or_byte2].width;
 
940
        else
 
941
            figure_width = font->max_bounds.width;
 
942
    }
 
943
 
 
944
    if (tab_count > sink->text_sink.tab_count) {
 
945
        sink->text_sink.tabs = (Position *)
 
946
            XtRealloc((char *)sink->text_sink.tabs,
 
947
                      (Cardinal)(tab_count * sizeof(Position)));
 
948
        sink->text_sink.char_tabs = (short *)
 
949
            XtRealloc((char *)sink->text_sink.char_tabs,
 
950
                      (Cardinal)(tab_count * sizeof(short)));
 
951
      }
 
952
 
 
953
    for (i = 0 ; i < tab_count ; i++) {
 
954
        sink->text_sink.tabs[i] = tabs[i] * figure_width;
 
955
        sink->text_sink.char_tabs[i] = tabs[i];
 
956
    }
 
957
 
 
958
    sink->text_sink.tab_count = tab_count;
 
959
 
 
960
#ifndef NO_TAB_FIX
 
961
    ((TextWidget)XtParent(w))->text.redisplay_needed = True;
 
962
#endif
 
963
}
 
964
 
 
965
void
 
966
_XawMultiSinkPosToXY(Widget w, XawTextPosition pos, Position *x, Position *y)
 
967
{
 
968
    MultiSinkObject sink = (MultiSinkObject)((TextWidget)w)->text.sink;
 
969
    XFontSetExtents *ext = XExtentsOfFontSet(sink->multi_sink.fontset);
 
970
 
 
971
    _XawTextPosToXY(w, pos, x, y);
 
972
    *y += abs(ext->max_logical_extent.y);
 
973
}