OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [start/] [insight/] [tk/] [generic/] [tkCanvText.c] - Blame information for rev 579

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*
2
 * tkCanvText.c --
3
 *
4
 *      This file implements text items for canvas widgets.
5
 *
6
 * Copyright (c) 1991-1994 The Regents of the University of California.
7
 * Copyright (c) 1994-1995 Sun Microsystems, Inc.
8
 *
9
 * See the file "license.terms" for information on usage and redistribution
10
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
11
 *
12
 * RCS: @(#) $Id: tkCanvText.c,v 1.1.1.1 2002-01-16 10:25:51 markom Exp $
13
 */
14
 
15
#include <stdio.h>
16
#include "tkInt.h"
17
#include "tkCanvas.h"
18
#include "tkPort.h"
19
#include "default.h"
20
 
21
/*
22
 * The structure below defines the record for each text item.
23
 */
24
 
25
typedef struct TextItem  {
26
    Tk_Item header;             /* Generic stuff that's the same for all
27
                                 * types.  MUST BE FIRST IN STRUCTURE. */
28
    Tk_CanvasTextInfo *textInfoPtr;
29
                                /* Pointer to a structure containing
30
                                 * information about the selection and
31
                                 * insertion cursor.  The structure is owned
32
                                 * by (and shared with) the generic canvas
33
                                 * code. */
34
    /*
35
     * Fields that are set by widget commands other than "configure".
36
     */
37
 
38
    double x, y;                /* Positioning point for text. */
39
    int insertPos;              /* Insertion cursor is displayed just to left
40
                                 * of character with this index. */
41
 
42
    /*
43
     * Configuration settings that are updated by Tk_ConfigureWidget.
44
     */
45
 
46
    Tk_Anchor anchor;           /* Where to anchor text relative to (x,y). */
47
    XColor *color;              /* Color for text. */
48
    Tk_Font tkfont;             /* Font for drawing text. */
49
    Tk_Justify justify;         /* Justification mode for text. */
50
    Pixmap stipple;             /* Stipple bitmap for text, or None. */
51
    char *text;                 /* Text for item (malloc-ed). */
52
    int width;                  /* Width of lines for word-wrap, pixels.
53
                                 * Zero means no word-wrap. */
54
 
55
    /*
56
     * Fields whose values are derived from the current values of the
57
     * configuration settings above.
58
     */
59
 
60
    int numChars;               /* Number of non-NULL characters in text. */
61
    Tk_TextLayout textLayout;   /* Cached text layout information. */
62
    int leftEdge;               /* Pixel location of the left edge of the
63
                                 * text item; where the left border of the
64
                                 * text layout is drawn. */
65
    int rightEdge;              /* Pixel just to right of right edge of
66
                                 * area of text item.  Used for selecting up
67
                                 * to end of line. */
68
    GC gc;                      /* Graphics context for drawing text. */
69
    GC selTextGC;               /* Graphics context for selected text. */
70
    GC cursorOffGC;             /* If not None, this gives a graphics context
71
                                 * to use to draw the insertion cursor when
72
                                 * it's off.  Used if the selection and
73
                                 * insertion cursor colors are the same.  */
74
} TextItem;
75
 
76
/*
77
 * Information used for parsing configuration specs:
78
 */
79
 
80
static Tk_CustomOption tagsOption = {Tk_CanvasTagsParseProc,
81
    Tk_CanvasTagsPrintProc, (ClientData) NULL
82
};
83
 
84
static Tk_ConfigSpec configSpecs[] = {
85
    {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
86
        "center", Tk_Offset(TextItem, anchor),
87
        TK_CONFIG_DONT_SET_DEFAULT},
88
    {TK_CONFIG_COLOR, "-fill", (char *) NULL, (char *) NULL,
89
        "black", Tk_Offset(TextItem, color), TK_CONFIG_NULL_OK},
90
    {TK_CONFIG_FONT, "-font", (char *) NULL, (char *) NULL,
91
        DEF_CANVTEXT_FONT, Tk_Offset(TextItem, tkfont), 0},
92
    {TK_CONFIG_JUSTIFY, "-justify", (char *) NULL, (char *) NULL,
93
        "left", Tk_Offset(TextItem, justify),
94
        TK_CONFIG_DONT_SET_DEFAULT},
95
    {TK_CONFIG_BITMAP, "-stipple", (char *) NULL, (char *) NULL,
96
        (char *) NULL, Tk_Offset(TextItem, stipple), TK_CONFIG_NULL_OK},
97
    {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
98
        (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
99
    {TK_CONFIG_STRING, "-text", (char *) NULL, (char *) NULL,
100
        "", Tk_Offset(TextItem, text), 0},
101
    {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
102
        "0", Tk_Offset(TextItem, width), TK_CONFIG_DONT_SET_DEFAULT},
103
    {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
104
        (char *) NULL, 0, 0}
105
};
106
 
107
/*
108
 * Prototypes for procedures defined in this file:
109
 */
110
 
111
static void             ComputeTextBbox _ANSI_ARGS_((Tk_Canvas canvas,
112
                            TextItem *textPtr));
113
static int              ConfigureText _ANSI_ARGS_((Tcl_Interp *interp,
114
                            Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
115
                            char **argv, int flags));
116
static int              CreateText _ANSI_ARGS_((Tcl_Interp *interp,
117
                            Tk_Canvas canvas, struct Tk_Item *itemPtr,
118
                            int argc, char **argv));
119
static void             DeleteText _ANSI_ARGS_((Tk_Canvas canvas,
120
                            Tk_Item *itemPtr, Display *display));
121
static void             DisplayCanvText _ANSI_ARGS_((Tk_Canvas canvas,
122
                            Tk_Item *itemPtr, Display *display, Drawable dst,
123
                            int x, int y, int width, int height));
124
static int              GetSelText _ANSI_ARGS_((Tk_Canvas canvas,
125
                            Tk_Item *itemPtr, int offset, char *buffer,
126
                            int maxBytes));
127
static int              GetTextIndex _ANSI_ARGS_((Tcl_Interp *interp,
128
                            Tk_Canvas canvas, Tk_Item *itemPtr,
129
                            char *indexString, int *indexPtr));
130
static void             ScaleText _ANSI_ARGS_((Tk_Canvas canvas,
131
                            Tk_Item *itemPtr, double originX, double originY,
132
                            double scaleX, double scaleY));
133
static void             SetTextCursor _ANSI_ARGS_((Tk_Canvas canvas,
134
                            Tk_Item *itemPtr, int index));
135
static int              TextCoords _ANSI_ARGS_((Tcl_Interp *interp,
136
                            Tk_Canvas canvas, Tk_Item *itemPtr,
137
                            int argc, char **argv));
138
static void             TextDeleteChars _ANSI_ARGS_((Tk_Canvas canvas,
139
                            Tk_Item *itemPtr, int first, int last));
140
static void             TextInsert _ANSI_ARGS_((Tk_Canvas canvas,
141
                            Tk_Item *itemPtr, int beforeThis, char *string));
142
static int              TextToArea _ANSI_ARGS_((Tk_Canvas canvas,
143
                            Tk_Item *itemPtr, double *rectPtr));
144
static double           TextToPoint _ANSI_ARGS_((Tk_Canvas canvas,
145
                            Tk_Item *itemPtr, double *pointPtr));
146
static int              TextToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
147
                            Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
148
static void             TranslateText _ANSI_ARGS_((Tk_Canvas canvas,
149
                            Tk_Item *itemPtr, double deltaX, double deltaY));
150
 
151
/*
152
 * The structures below defines the rectangle and oval item types
153
 * by means of procedures that can be invoked by generic item code.
154
 */
155
 
156
Tk_ItemType tkTextType = {
157
    "text",                             /* name */
158
    sizeof(TextItem),                   /* itemSize */
159
    CreateText,                         /* createProc */
160
    configSpecs,                        /* configSpecs */
161
    ConfigureText,                      /* configureProc */
162
    TextCoords,                         /* coordProc */
163
    DeleteText,                         /* deleteProc */
164
    DisplayCanvText,                    /* displayProc */
165
    0,                                   /* alwaysRedraw */
166
    TextToPoint,                        /* pointProc */
167
    TextToArea,                         /* areaProc */
168
    TextToPostscript,                   /* postscriptProc */
169
    ScaleText,                          /* scaleProc */
170
    TranslateText,                      /* translateProc */
171
    GetTextIndex,                       /* indexProc */
172
    SetTextCursor,                      /* icursorProc */
173
    GetSelText,                         /* selectionProc */
174
    TextInsert,                         /* insertProc */
175
    TextDeleteChars,                    /* dTextProc */
176
    (Tk_ItemType *) NULL                /* nextPtr */
177
};
178
 
179
/*
180
 *--------------------------------------------------------------
181
 *
182
 * CreateText --
183
 *
184
 *      This procedure is invoked to create a new text item
185
 *      in a canvas.
186
 *
187
 * Results:
188
 *      A standard Tcl return value.  If an error occurred in
189
 *      creating the item then an error message is left in
190
 *      interp->result;  in this case itemPtr is left uninitialized
191
 *      so it can be safely freed by the caller.
192
 *
193
 * Side effects:
194
 *      A new text item is created.
195
 *
196
 *--------------------------------------------------------------
197
 */
198
 
199
static int
200
CreateText(interp, canvas, itemPtr, argc, argv)
201
    Tcl_Interp *interp;                 /* Interpreter for error reporting. */
202
    Tk_Canvas canvas;                   /* Canvas to hold new item. */
203
    Tk_Item *itemPtr;                   /* Record to hold new item;  header
204
                                         * has been initialized by caller. */
205
    int argc;                           /* Number of arguments in argv. */
206
    char **argv;                        /* Arguments describing rectangle. */
207
{
208
    TextItem *textPtr = (TextItem *) itemPtr;
209
 
210
    if (argc < 2) {
211
        Tcl_AppendResult(interp, "wrong # args: should be \"",
212
                Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
213
                itemPtr->typePtr->name, " x y ?options?\"", (char *) NULL);
214
        return TCL_ERROR;
215
    }
216
 
217
    /*
218
     * Carry out initialization that is needed in order to clean
219
     * up after errors during the the remainder of this procedure.
220
     */
221
 
222
    textPtr->textInfoPtr = Tk_CanvasGetTextInfo(canvas);
223
 
224
    textPtr->insertPos  = 0;
225
 
226
    textPtr->anchor     = TK_ANCHOR_CENTER;
227
    textPtr->color      = NULL;
228
    textPtr->tkfont     = NULL;
229
    textPtr->justify    = TK_JUSTIFY_LEFT;
230
    textPtr->stipple    = None;
231
    textPtr->text       = NULL;
232
    textPtr->width      = 0;
233
 
234
    textPtr->numChars   = 0;
235
    textPtr->textLayout = NULL;
236
    textPtr->leftEdge   = 0;
237
    textPtr->rightEdge  = 0;
238
    textPtr->gc         = None;
239
    textPtr->selTextGC  = None;
240
    textPtr->cursorOffGC = None;
241
 
242
    /*
243
     * Process the arguments to fill in the item record.
244
     */
245
 
246
    if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &textPtr->x) != TCL_OK)
247
            || (Tk_CanvasGetCoord(interp, canvas, argv[1], &textPtr->y)
248
                != TCL_OK)) {
249
        return TCL_ERROR;
250
    }
251
 
252
    if (ConfigureText(interp, canvas, itemPtr, argc-2, argv+2, 0) != TCL_OK) {
253
        DeleteText(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
254
        return TCL_ERROR;
255
    }
256
    return TCL_OK;
257
}
258
 
259
/*
260
 *--------------------------------------------------------------
261
 *
262
 * TextCoords --
263
 *
264
 *      This procedure is invoked to process the "coords" widget
265
 *      command on text items.  See the user documentation for
266
 *      details on what it does.
267
 *
268
 * Results:
269
 *      Returns TCL_OK or TCL_ERROR, and sets interp->result.
270
 *
271
 * Side effects:
272
 *      The coordinates for the given item may be changed.
273
 *
274
 *--------------------------------------------------------------
275
 */
276
 
277
static int
278
TextCoords(interp, canvas, itemPtr, argc, argv)
279
    Tcl_Interp *interp;                 /* Used for error reporting. */
280
    Tk_Canvas canvas;                   /* Canvas containing item. */
281
    Tk_Item *itemPtr;                   /* Item whose coordinates are to be
282
                                         * read or modified. */
283
    int argc;                           /* Number of coordinates supplied in
284
                                         * argv. */
285
    char **argv;                        /* Array of coordinates: x1, y1,
286
                                         * x2, y2, ... */
287
{
288
    TextItem *textPtr = (TextItem *) itemPtr;
289
    char x[TCL_DOUBLE_SPACE], y[TCL_DOUBLE_SPACE];
290
 
291
    if (argc == 0) {
292
        Tcl_PrintDouble(interp, textPtr->x, x);
293
        Tcl_PrintDouble(interp, textPtr->y, y);
294
        Tcl_AppendResult(interp, x, " ", y, (char *) NULL);
295
    } else if (argc == 2) {
296
        if ((Tk_CanvasGetCoord(interp, canvas, argv[0], &textPtr->x) != TCL_OK)
297
                || (Tk_CanvasGetCoord(interp, canvas, argv[1],
298
                    &textPtr->y) != TCL_OK)) {
299
            return TCL_ERROR;
300
        }
301
        ComputeTextBbox(canvas, textPtr);
302
    } else {
303
        sprintf(interp->result,
304
                "wrong # coordinates: expected 0 or 2, got %d", argc);
305
        return TCL_ERROR;
306
    }
307
    return TCL_OK;
308
}
309
 
310
/*
311
 *--------------------------------------------------------------
312
 *
313
 * ConfigureText --
314
 *
315
 *      This procedure is invoked to configure various aspects
316
 *      of a text item, such as its border and background colors.
317
 *
318
 * Results:
319
 *      A standard Tcl result code.  If an error occurs, then
320
 *      an error message is left in interp->result.
321
 *
322
 * Side effects:
323
 *      Configuration information, such as colors and stipple
324
 *      patterns, may be set for itemPtr.
325
 *
326
 *--------------------------------------------------------------
327
 */
328
 
329
static int
330
ConfigureText(interp, canvas, itemPtr, argc, argv, flags)
331
    Tcl_Interp *interp;         /* Interpreter for error reporting. */
332
    Tk_Canvas canvas;           /* Canvas containing itemPtr. */
333
    Tk_Item *itemPtr;           /* Rectangle item to reconfigure. */
334
    int argc;                   /* Number of elements in argv.  */
335
    char **argv;                /* Arguments describing things to configure. */
336
    int flags;                  /* Flags to pass to Tk_ConfigureWidget. */
337
{
338
    TextItem *textPtr = (TextItem *) itemPtr;
339
    XGCValues gcValues;
340
    GC newGC, newSelGC;
341
    unsigned long mask;
342
    Tk_Window tkwin;
343
    Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
344
    XColor *selBgColorPtr;
345
 
346
    tkwin = Tk_CanvasTkwin(canvas);
347
    if (Tk_ConfigureWidget(interp, tkwin, configSpecs, argc, argv,
348
            (char *) textPtr, flags) != TCL_OK) {
349
        return TCL_ERROR;
350
    }
351
 
352
    /*
353
     * A few of the options require additional processing, such as
354
     * graphics contexts.
355
     */
356
 
357
    newGC = newSelGC = None;
358
    if ((textPtr->color != NULL) && (textPtr->tkfont != NULL)) {
359
        gcValues.foreground = textPtr->color->pixel;
360
        gcValues.font = Tk_FontId(textPtr->tkfont);
361
        mask = GCForeground|GCFont;
362
        if (textPtr->stipple != None) {
363
            gcValues.stipple = textPtr->stipple;
364
            gcValues.fill_style = FillStippled;
365
            mask |= GCForeground|GCStipple|GCFillStyle;
366
        }
367
        newGC = Tk_GetGCColor(tkwin, mask, &gcValues, textPtr->color, NULL);
368
        gcValues.foreground = textInfoPtr->selFgColorPtr->pixel;
369
        newSelGC = Tk_GetGCColor(tkwin, mask, &gcValues,
370
                                 textInfoPtr->selFgColorPtr, NULL);
371
    }
372
    if (textPtr->gc != None) {
373
        Tk_FreeGC(Tk_Display(tkwin), textPtr->gc);
374
    }
375
    textPtr->gc = newGC;
376
    if (textPtr->selTextGC != None) {
377
        Tk_FreeGC(Tk_Display(tkwin), textPtr->selTextGC);
378
    }
379
    textPtr->selTextGC = newSelGC;
380
 
381
    selBgColorPtr = Tk_3DBorderColor(textInfoPtr->selBorder);
382
    if (Tk_3DBorderColor(textInfoPtr->insertBorder)->pixel
383
            == selBgColorPtr->pixel) {
384
        if (selBgColorPtr->pixel == BlackPixelOfScreen(Tk_Screen(tkwin))) {
385
            gcValues.foreground = WhitePixelOfScreen(Tk_Screen(tkwin));
386
        } else {
387
            gcValues.foreground = BlackPixelOfScreen(Tk_Screen(tkwin));
388
        }
389
        newGC = Tk_GetGC(tkwin, GCForeground, &gcValues);
390
    } else {
391
        newGC = None;
392
    }
393
    if (textPtr->cursorOffGC != None) {
394
        Tk_FreeGC(Tk_Display(tkwin), textPtr->cursorOffGC);
395
    }
396
    textPtr->cursorOffGC = newGC;
397
 
398
 
399
    /*
400
     * If the text was changed, move the selection and insertion indices
401
     * to keep them inside the item.
402
     */
403
 
404
    textPtr->numChars = strlen(textPtr->text);
405
    if (textInfoPtr->selItemPtr == itemPtr) {
406
        if (textInfoPtr->selectFirst >= textPtr->numChars) {
407
            textInfoPtr->selItemPtr = NULL;
408
        } else {
409
            if (textInfoPtr->selectLast >= textPtr->numChars) {
410
                textInfoPtr->selectLast = textPtr->numChars-1;
411
            }
412
            if ((textInfoPtr->anchorItemPtr == itemPtr)
413
                    && (textInfoPtr->selectAnchor >= textPtr->numChars)) {
414
                textInfoPtr->selectAnchor = textPtr->numChars-1;
415
            }
416
        }
417
    }
418
    if (textPtr->insertPos >= textPtr->numChars) {
419
        textPtr->insertPos = textPtr->numChars;
420
    }
421
 
422
    ComputeTextBbox(canvas, textPtr);
423
    return TCL_OK;
424
}
425
 
426
/*
427
 *--------------------------------------------------------------
428
 *
429
 * DeleteText --
430
 *
431
 *      This procedure is called to clean up the data structure
432
 *      associated with a text item.
433
 *
434
 * Results:
435
 *      None.
436
 *
437
 * Side effects:
438
 *      Resources associated with itemPtr are released.
439
 *
440
 *--------------------------------------------------------------
441
 */
442
 
443
static void
444
DeleteText(canvas, itemPtr, display)
445
    Tk_Canvas canvas;                   /* Info about overall canvas widget. */
446
    Tk_Item *itemPtr;                   /* Item that is being deleted. */
447
    Display *display;                   /* Display containing window for
448
                                         * canvas. */
449
{
450
    TextItem *textPtr = (TextItem *) itemPtr;
451
 
452
    if (textPtr->color != NULL) {
453
        Tk_FreeColor(textPtr->color);
454
    }
455
    Tk_FreeFont(textPtr->tkfont);
456
    if (textPtr->stipple != None) {
457
        Tk_FreeBitmap(display, textPtr->stipple);
458
    }
459
    if (textPtr->text != NULL) {
460
        ckfree(textPtr->text);
461
    }
462
 
463
    Tk_FreeTextLayout(textPtr->textLayout);
464
    if (textPtr->gc != None) {
465
        Tk_FreeGC(display, textPtr->gc);
466
    }
467
    if (textPtr->selTextGC != None) {
468
        Tk_FreeGC(display, textPtr->selTextGC);
469
    }
470
    if (textPtr->cursorOffGC != None) {
471
        Tk_FreeGC(display, textPtr->cursorOffGC);
472
    }
473
}
474
 
475
/*
476
 *--------------------------------------------------------------
477
 *
478
 * ComputeTextBbox --
479
 *
480
 *      This procedure is invoked to compute the bounding box of
481
 *      all the pixels that may be drawn as part of a text item.
482
 *      In addition, it recomputes all of the geometry information
483
 *      used to display a text item or check for mouse hits.
484
 *
485
 * Results:
486
 *      None.
487
 *
488
 * Side effects:
489
 *      The fields x1, y1, x2, and y2 are updated in the header
490
 *      for itemPtr, and the linePtr structure is regenerated
491
 *      for itemPtr.
492
 *
493
 *--------------------------------------------------------------
494
 */
495
 
496
static void
497
ComputeTextBbox(canvas, textPtr)
498
    Tk_Canvas canvas;                   /* Canvas that contains item. */
499
    TextItem *textPtr;                  /* Item whose bbos is to be
500
                                         * recomputed. */
501
{
502
    Tk_CanvasTextInfo *textInfoPtr;
503
    int leftX, topY, width, height, fudge;
504
 
505
    Tk_FreeTextLayout(textPtr->textLayout);
506
    textPtr->textLayout = Tk_ComputeTextLayout(textPtr->tkfont,
507
            textPtr->text, textPtr->numChars, textPtr->width,
508
            textPtr->justify, 0, &width, &height);
509
 
510
    /*
511
     * Use overall geometry information to compute the top-left corner
512
     * of the bounding box for the text item.
513
     */
514
 
515
    leftX = (int) (textPtr->x + 0.5);
516
    topY = (int) (textPtr->y + 0.5);
517
    switch (textPtr->anchor) {
518
        case TK_ANCHOR_NW:
519
        case TK_ANCHOR_N:
520
        case TK_ANCHOR_NE:
521
            break;
522
 
523
        case TK_ANCHOR_W:
524
        case TK_ANCHOR_CENTER:
525
        case TK_ANCHOR_E:
526
            topY -= height / 2;
527
            break;
528
 
529
        case TK_ANCHOR_SW:
530
        case TK_ANCHOR_S:
531
        case TK_ANCHOR_SE:
532
            topY -= height;
533
            break;
534
    }
535
    switch (textPtr->anchor) {
536
        case TK_ANCHOR_NW:
537
        case TK_ANCHOR_W:
538
        case TK_ANCHOR_SW:
539
            break;
540
 
541
        case TK_ANCHOR_N:
542
        case TK_ANCHOR_CENTER:
543
        case TK_ANCHOR_S:
544
            leftX -= width / 2;
545
            break;
546
 
547
        case TK_ANCHOR_NE:
548
        case TK_ANCHOR_E:
549
        case TK_ANCHOR_SE:
550
            leftX -= width;
551
            break;
552
    }
553
 
554
    textPtr->leftEdge  = leftX;
555
    textPtr->rightEdge = leftX + width;
556
 
557
    /*
558
     * Last of all, update the bounding box for the item.  The item's
559
     * bounding box includes the bounding box of all its lines, plus
560
     * an extra fudge factor for the cursor border (which could
561
     * potentially be quite large).
562
     */
563
 
564
    textInfoPtr = textPtr->textInfoPtr;
565
    fudge = (textInfoPtr->insertWidth + 1) / 2;
566
    if (textInfoPtr->selBorderWidth > fudge) {
567
        fudge = textInfoPtr->selBorderWidth;
568
    }
569
    textPtr->header.x1 = leftX - fudge;
570
    textPtr->header.y1 = topY;
571
    textPtr->header.x2 = leftX + width + fudge;
572
    textPtr->header.y2 = topY + height;
573
}
574
 
575
/*
576
 *--------------------------------------------------------------
577
 *
578
 * DisplayCanvText --
579
 *
580
 *      This procedure is invoked to draw a text item in a given
581
 *      drawable.
582
 *
583
 * Results:
584
 *      None.
585
 *
586
 * Side effects:
587
 *      ItemPtr is drawn in drawable using the transformation
588
 *      information in canvas.
589
 *
590
 *--------------------------------------------------------------
591
 */
592
 
593
static void
594
DisplayCanvText(canvas, itemPtr, display, drawable, x, y, width, height)
595
    Tk_Canvas canvas;                   /* Canvas that contains item. */
596
    Tk_Item *itemPtr;                   /* Item to be displayed. */
597
    Display *display;                   /* Display on which to draw item. */
598
    Drawable drawable;                  /* Pixmap or window in which to draw
599
                                         * item. */
600
    int x, y, width, height;            /* Describes region of canvas that
601
                                         * must be redisplayed (not used). */
602
{
603
    TextItem *textPtr;
604
    Tk_CanvasTextInfo *textInfoPtr;
605
    int selFirst, selLast;
606
    short drawableX, drawableY;
607
 
608
    textPtr = (TextItem *) itemPtr;
609
    textInfoPtr = textPtr->textInfoPtr;
610
 
611
    if (textPtr->gc == None) {
612
        return;
613
    }
614
 
615
    /*
616
     * If we're stippling, then modify the stipple offset in the GC.  Be
617
     * sure to reset the offset when done, since the GC is supposed to be
618
     * read-only.
619
     */
620
 
621
    if (textPtr->stipple != None) {
622
        Tk_CanvasSetStippleOrigin(canvas, textPtr->gc);
623
    }
624
 
625
    selFirst = -1;
626
    selLast = 0;         /* lint. */
627
    if (textInfoPtr->selItemPtr == itemPtr) {
628
        selFirst = textInfoPtr->selectFirst;
629
        selLast = textInfoPtr->selectLast;
630
        if (selLast >= textPtr->numChars) {
631
            selLast = textPtr->numChars - 1;
632
        }
633
        if ((selFirst >= 0) && (selFirst <= selLast)) {
634
            /*
635
             * Draw a special background under the selection.
636
             */
637
 
638
            int xFirst, yFirst, hFirst;
639
            int xLast, yLast, wLast;
640
 
641
            Tk_CharBbox(textPtr->textLayout, selFirst,
642
                    &xFirst, &yFirst, NULL, &hFirst);
643
            Tk_CharBbox(textPtr->textLayout, selLast,
644
                    &xLast, &yLast, &wLast, NULL);
645
 
646
            /*
647
             * If the selection spans the end of this line, then display
648
             * selection background all the way to the end of the line.
649
             * However, for the last line we only want to display up to the
650
             * last character, not the end of the line.
651
             */
652
 
653
            x = xFirst;
654
            height = hFirst;
655
            for (y = yFirst ; y <= yLast; y += height) {
656
                if (y == yLast) {
657
                    width = (xLast + wLast) - x;
658
                } else {
659
                    width = textPtr->rightEdge - textPtr->leftEdge - x;
660
                }
661
                Tk_CanvasDrawableCoords(canvas,
662
                        (double) (textPtr->leftEdge + x
663
                                - textInfoPtr->selBorderWidth),
664
                        (double) (textPtr->header.y1 + y),
665
                        &drawableX, &drawableY);
666
                Tk_Fill3DRectangle(Tk_CanvasTkwin(canvas), drawable,
667
                        textInfoPtr->selBorder, drawableX, drawableY,
668
                        width + 2 * textInfoPtr->selBorderWidth,
669
                        height, textInfoPtr->selBorderWidth, TK_RELIEF_RAISED);
670
                x = 0;
671
            }
672
        }
673
    }
674
 
675
    /*
676
     * If the insertion point should be displayed, then draw a special
677
     * background for the cursor before drawing the text.  Note:  if
678
     * we're the cursor item but the cursor is turned off, then redraw
679
     * background over the area of the cursor.  This guarantees that
680
     * the selection won't make the cursor invisible on mono displays,
681
     * where both are drawn in the same color.
682
     */
683
 
684
    if ((textInfoPtr->focusItemPtr == itemPtr) && (textInfoPtr->gotFocus)) {
685
        if (Tk_CharBbox(textPtr->textLayout, textPtr->insertPos,
686
                &x, &y, NULL, &height)) {
687
            Tk_CanvasDrawableCoords(canvas,
688
                    (double) (textPtr->leftEdge + x
689
                            - (textInfoPtr->insertWidth / 2)),
690
                    (double) (textPtr->header.y1 + y),
691
                    &drawableX, &drawableY);
692
            if (textInfoPtr->cursorOn) {
693
                Tk_Fill3DRectangle(Tk_CanvasTkwin(canvas), drawable,
694
                        textInfoPtr->insertBorder,
695
                        drawableX, drawableY,
696
                        textInfoPtr->insertWidth, height,
697
                        textInfoPtr->insertBorderWidth, TK_RELIEF_RAISED);
698
            } else if (textPtr->cursorOffGC != None) {
699
                /*
700
                 * Redraw the background over the area of the cursor,
701
                 * even though the cursor is turned off.  This
702
                 * guarantees that the selection won't make the cursor
703
                 * invisible on mono displays, where both may be drawn
704
                 * in the same color.
705
                 */
706
 
707
                XFillRectangle(display, drawable, textPtr->cursorOffGC,
708
                        drawableX, drawableY,
709
                        (unsigned) textInfoPtr->insertWidth,
710
                        (unsigned) height);
711
            }
712
        }
713
    }
714
 
715
 
716
    /*
717
     * Display the text in two pieces: draw the entire text item, then
718
     * draw the selected text on top of it.  The selected text then
719
     * will only need to be drawn if it has different attributes (such
720
     * as foreground color) than regular text.
721
     */
722
 
723
    Tk_CanvasDrawableCoords(canvas, (double) textPtr->leftEdge,
724
            (double) textPtr->header.y1, &drawableX, &drawableY);
725
    Tk_DrawTextLayout(display, drawable, textPtr->gc, textPtr->textLayout,
726
            drawableX, drawableY, 0, -1);
727
 
728
    if ((selFirst >= 0) && (textPtr->selTextGC != textPtr->gc)) {
729
        Tk_DrawTextLayout(display, drawable, textPtr->selTextGC,
730
            textPtr->textLayout, drawableX, drawableY, selFirst,
731
            selLast + 1);
732
    }
733
 
734
    if (textPtr->stipple != None) {
735
        XSetTSOrigin(display, textPtr->gc, 0, 0);
736
    }
737
}
738
 
739
/*
740
 *--------------------------------------------------------------
741
 *
742
 * TextInsert --
743
 *
744
 *      Insert characters into a text item at a given position.
745
 *
746
 * Results:
747
 *      None.
748
 *
749
 * Side effects:
750
 *      The text in the given item is modified.  The cursor and
751
 *      selection positions are also modified to reflect the
752
 *      insertion.
753
 *
754
 *--------------------------------------------------------------
755
 */
756
 
757
static void
758
TextInsert(canvas, itemPtr, beforeThis, string)
759
    Tk_Canvas canvas;           /* Canvas containing text item. */
760
    Tk_Item *itemPtr;           /* Text item to be modified. */
761
    int beforeThis;             /* Index of character before which text is
762
                                 * to be inserted. */
763
    char *string;               /* New characters to be inserted. */
764
{
765
    TextItem *textPtr = (TextItem *) itemPtr;
766
    int length;
767
    char *new;
768
    Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
769
 
770
    length = strlen(string);
771
    if (length == 0) {
772
        return;
773
    }
774
    if (beforeThis < 0) {
775
        beforeThis = 0;
776
    }
777
    if (beforeThis > textPtr->numChars) {
778
        beforeThis = textPtr->numChars;
779
    }
780
 
781
    new = (char *) ckalloc((unsigned) (textPtr->numChars + length + 1));
782
    strncpy(new, textPtr->text, (size_t) beforeThis);
783
    strcpy(new+beforeThis, string);
784
    strcpy(new+beforeThis+length, textPtr->text+beforeThis);
785
    ckfree(textPtr->text);
786
    textPtr->text = new;
787
    textPtr->numChars += length;
788
 
789
    /*
790
     * Inserting characters invalidates indices such as those for the
791
     * selection and cursor.  Update the indices appropriately.
792
     */
793
 
794
    if (textInfoPtr->selItemPtr == itemPtr) {
795
        if (textInfoPtr->selectFirst >= beforeThis) {
796
            textInfoPtr->selectFirst += length;
797
        }
798
        if (textInfoPtr->selectLast >= beforeThis) {
799
            textInfoPtr->selectLast += length;
800
        }
801
        if ((textInfoPtr->anchorItemPtr == itemPtr)
802
                && (textInfoPtr->selectAnchor >= beforeThis)) {
803
            textInfoPtr->selectAnchor += length;
804
        }
805
    }
806
    if (textPtr->insertPos >= beforeThis) {
807
        textPtr->insertPos += length;
808
    }
809
    ComputeTextBbox(canvas, textPtr);
810
}
811
 
812
/*
813
 *--------------------------------------------------------------
814
 *
815
 * TextDeleteChars --
816
 *
817
 *      Delete one or more characters from a text item.
818
 *
819
 * Results:
820
 *      None.
821
 *
822
 * Side effects:
823
 *      Characters between "first" and "last", inclusive, get
824
 *      deleted from itemPtr, and things like the selection
825
 *      position get updated.
826
 *
827
 *--------------------------------------------------------------
828
 */
829
 
830
static void
831
TextDeleteChars(canvas, itemPtr, first, last)
832
    Tk_Canvas canvas;           /* Canvas containing itemPtr. */
833
    Tk_Item *itemPtr;           /* Item in which to delete characters. */
834
    int first;                  /* Index of first character to delete. */
835
    int last;                   /* Index of last character to delete. */
836
{
837
    TextItem *textPtr = (TextItem *) itemPtr;
838
    int count;
839
    char *new;
840
    Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
841
 
842
    if (first < 0) {
843
        first = 0;
844
    }
845
    if (last >= textPtr->numChars) {
846
        last = textPtr->numChars-1;
847
    }
848
    if (first > last) {
849
        return;
850
    }
851
    count = last + 1 - first;
852
 
853
    new = (char *) ckalloc((unsigned) (textPtr->numChars + 1 - count));
854
    strncpy(new, textPtr->text, (size_t) first);
855
    strcpy(new+first, textPtr->text+last+1);
856
    ckfree(textPtr->text);
857
    textPtr->text = new;
858
    textPtr->numChars -= count;
859
 
860
    /*
861
     * Update indexes for the selection and cursor to reflect the
862
     * renumbering of the remaining characters.
863
     */
864
 
865
    if (textInfoPtr->selItemPtr == itemPtr) {
866
        if (textInfoPtr->selectFirst > first) {
867
            textInfoPtr->selectFirst -= count;
868
            if (textInfoPtr->selectFirst < first) {
869
                textInfoPtr->selectFirst = first;
870
            }
871
        }
872
        if (textInfoPtr->selectLast >= first) {
873
            textInfoPtr->selectLast -= count;
874
            if (textInfoPtr->selectLast < (first-1)) {
875
                textInfoPtr->selectLast = (first-1);
876
            }
877
        }
878
        if (textInfoPtr->selectFirst > textInfoPtr->selectLast) {
879
            textInfoPtr->selItemPtr = NULL;
880
        }
881
        if ((textInfoPtr->anchorItemPtr == itemPtr)
882
                && (textInfoPtr->selectAnchor > first)) {
883
            textInfoPtr->selectAnchor -= count;
884
            if (textInfoPtr->selectAnchor < first) {
885
                textInfoPtr->selectAnchor = first;
886
            }
887
        }
888
    }
889
    if (textPtr->insertPos > first) {
890
        textPtr->insertPos -= count;
891
        if (textPtr->insertPos < first) {
892
            textPtr->insertPos = first;
893
        }
894
    }
895
    ComputeTextBbox(canvas, textPtr);
896
    return;
897
}
898
 
899
/*
900
 *--------------------------------------------------------------
901
 *
902
 * TextToPoint --
903
 *
904
 *      Computes the distance from a given point to a given
905
 *      text item, in canvas units.
906
 *
907
 * Results:
908
 *      The return value is 0 if the point whose x and y coordinates
909
 *      are pointPtr[0] and pointPtr[1] is inside the text item.  If
910
 *      the point isn't inside the text item then the return value
911
 *      is the distance from the point to the text item.
912
 *
913
 * Side effects:
914
 *      None.
915
 *
916
 *--------------------------------------------------------------
917
 */
918
 
919
static double
920
TextToPoint(canvas, itemPtr, pointPtr)
921
    Tk_Canvas canvas;           /* Canvas containing itemPtr. */
922
    Tk_Item *itemPtr;           /* Item to check against point. */
923
    double *pointPtr;           /* Pointer to x and y coordinates. */
924
{
925
    TextItem *textPtr;
926
 
927
    textPtr = (TextItem *) itemPtr;
928
    return (double) Tk_DistanceToTextLayout(textPtr->textLayout,
929
            (int) pointPtr[0] - textPtr->leftEdge,
930
            (int) pointPtr[1] - textPtr->header.y1);
931
}
932
 
933
/*
934
 *--------------------------------------------------------------
935
 *
936
 * TextToArea --
937
 *
938
 *      This procedure is called to determine whether an item
939
 *      lies entirely inside, entirely outside, or overlapping
940
 *      a given rectangle.
941
 *
942
 * Results:
943
 *      -1 is returned if the item is entirely outside the area
944
 *      given by rectPtr, 0 if it overlaps, and 1 if it is entirely
945
 *      inside the given area.
946
 *
947
 * Side effects:
948
 *      None.
949
 *
950
 *--------------------------------------------------------------
951
 */
952
 
953
static int
954
TextToArea(canvas, itemPtr, rectPtr)
955
    Tk_Canvas canvas;           /* Canvas containing itemPtr. */
956
    Tk_Item *itemPtr;           /* Item to check against rectangle. */
957
    double *rectPtr;            /* Pointer to array of four coordinates
958
                                 * (x1, y1, x2, y2) describing rectangular
959
                                 * area.  */
960
{
961
    TextItem *textPtr;
962
 
963
    textPtr = (TextItem *) itemPtr;
964
    return Tk_IntersectTextLayout(textPtr->textLayout,
965
            (int) (rectPtr[0] + 0.5) - textPtr->leftEdge,
966
            (int) (rectPtr[1] + 0.5) - textPtr->header.y1,
967
            (int) (rectPtr[2] - rectPtr[0] + 0.5),
968
            (int) (rectPtr[3] - rectPtr[1] + 0.5));
969
}
970
 
971
/*
972
 *--------------------------------------------------------------
973
 *
974
 * ScaleText --
975
 *
976
 *      This procedure is invoked to rescale a text item.
977
 *
978
 * Results:
979
 *      None.
980
 *
981
 * Side effects:
982
 *      Scales the position of the text, but not the size
983
 *      of the font for the text.
984
 *
985
 *--------------------------------------------------------------
986
 */
987
 
988
        /* ARGSUSED */
989
static void
990
ScaleText(canvas, itemPtr, originX, originY, scaleX, scaleY)
991
    Tk_Canvas canvas;                   /* Canvas containing rectangle. */
992
    Tk_Item *itemPtr;                   /* Rectangle to be scaled. */
993
    double originX, originY;            /* Origin about which to scale rect. */
994
    double scaleX;                      /* Amount to scale in X direction. */
995
    double scaleY;                      /* Amount to scale in Y direction. */
996
{
997
    TextItem *textPtr = (TextItem *) itemPtr;
998
 
999
    textPtr->x = originX + scaleX*(textPtr->x - originX);
1000
    textPtr->y = originY + scaleY*(textPtr->y - originY);
1001
    ComputeTextBbox(canvas, textPtr);
1002
    return;
1003
}
1004
 
1005
/*
1006
 *--------------------------------------------------------------
1007
 *
1008
 * TranslateText --
1009
 *
1010
 *      This procedure is called to move a text item by a
1011
 *      given amount.
1012
 *
1013
 * Results:
1014
 *      None.
1015
 *
1016
 * Side effects:
1017
 *      The position of the text item is offset by (xDelta, yDelta),
1018
 *      and the bounding box is updated in the generic part of the
1019
 *      item structure.
1020
 *
1021
 *--------------------------------------------------------------
1022
 */
1023
 
1024
static void
1025
TranslateText(canvas, itemPtr, deltaX, deltaY)
1026
    Tk_Canvas canvas;                   /* Canvas containing item. */
1027
    Tk_Item *itemPtr;                   /* Item that is being moved. */
1028
    double deltaX, deltaY;              /* Amount by which item is to be
1029
                                         * moved. */
1030
{
1031
    TextItem *textPtr = (TextItem *) itemPtr;
1032
 
1033
    textPtr->x += deltaX;
1034
    textPtr->y += deltaY;
1035
    ComputeTextBbox(canvas, textPtr);
1036
}
1037
 
1038
/*
1039
 *--------------------------------------------------------------
1040
 *
1041
 * GetTextIndex --
1042
 *
1043
 *      Parse an index into a text item and return either its value
1044
 *      or an error.
1045
 *
1046
 * Results:
1047
 *      A standard Tcl result.  If all went well, then *indexPtr is
1048
 *      filled in with the index (into itemPtr) corresponding to
1049
 *      string.  Otherwise an error message is left in
1050
 *      interp->result.
1051
 *
1052
 * Side effects:
1053
 *      None.
1054
 *
1055
 *--------------------------------------------------------------
1056
 */
1057
 
1058
static int
1059
GetTextIndex(interp, canvas, itemPtr, string, indexPtr)
1060
    Tcl_Interp *interp;         /* Used for error reporting. */
1061
    Tk_Canvas canvas;           /* Canvas containing item. */
1062
    Tk_Item *itemPtr;           /* Item for which the index is being
1063
                                 * specified. */
1064
    char *string;               /* Specification of a particular character
1065
                                 * in itemPtr's text. */
1066
    int *indexPtr;              /* Where to store converted index. */
1067
{
1068
    TextItem *textPtr = (TextItem *) itemPtr;
1069
    size_t length;
1070
    int c;
1071
    TkCanvas *canvasPtr = (TkCanvas *) canvas;
1072
    Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
1073
 
1074
    c = string[0];
1075
    length = strlen(string);
1076
 
1077
    if ((c == 'e') && (strncmp(string, "end", length) == 0)) {
1078
        *indexPtr = textPtr->numChars;
1079
    } else if ((c == 'i') && (strncmp(string, "insert", length) == 0)) {
1080
        *indexPtr = textPtr->insertPos;
1081
    } else if ((c == 's') && (strncmp(string, "sel.first", length) == 0)
1082
            && (length >= 5)) {
1083
        if (textInfoPtr->selItemPtr != itemPtr) {
1084
            interp->result = "selection isn't in item";
1085
            return TCL_ERROR;
1086
        }
1087
        *indexPtr = textInfoPtr->selectFirst;
1088
    } else if ((c == 's') && (strncmp(string, "sel.last", length) == 0)
1089
            && (length >= 5)) {
1090
        if (textInfoPtr->selItemPtr != itemPtr) {
1091
            interp->result = "selection isn't in item";
1092
            return TCL_ERROR;
1093
        }
1094
        *indexPtr = textInfoPtr->selectLast;
1095
    } else if (c == '@') {
1096
        int x, y;
1097
        double tmp;
1098
        char *end, *p;
1099
 
1100
        p = string+1;
1101
        tmp = strtod(p, &end);
1102
        if ((end == p) || (*end != ',')) {
1103
            goto badIndex;
1104
        }
1105
        x = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);
1106
        p = end+1;
1107
        tmp = strtod(p, &end);
1108
        if ((end == p) || (*end != 0)) {
1109
            goto badIndex;
1110
        }
1111
        y = (int) ((tmp < 0) ? tmp - 0.5 : tmp + 0.5);
1112
        *indexPtr = Tk_PointToChar(textPtr->textLayout,
1113
                x + canvasPtr->scrollX1 - textPtr->leftEdge,
1114
                y + canvasPtr->scrollY1 - textPtr->header.y1);
1115
    } else if (Tcl_GetInt(interp, string, indexPtr) == TCL_OK) {
1116
        if (*indexPtr < 0){
1117
            *indexPtr = 0;
1118
        } else if (*indexPtr > textPtr->numChars) {
1119
            *indexPtr = textPtr->numChars;
1120
        }
1121
    } else {
1122
        /*
1123
         * Some of the paths here leave messages in interp->result,
1124
         * so we have to clear it out before storing our own message.
1125
         */
1126
 
1127
        badIndex:
1128
        Tcl_SetResult(interp, (char *) NULL, TCL_STATIC);
1129
        Tcl_AppendResult(interp, "bad index \"", string, "\"",
1130
                (char *) NULL);
1131
        return TCL_ERROR;
1132
    }
1133
    return TCL_OK;
1134
}
1135
 
1136
/*
1137
 *--------------------------------------------------------------
1138
 *
1139
 * SetTextCursor --
1140
 *
1141
 *      Set the position of the insertion cursor in this item.
1142
 *
1143
 * Results:
1144
 *      None.
1145
 *
1146
 * Side effects:
1147
 *      The cursor position will change.
1148
 *
1149
 *--------------------------------------------------------------
1150
 */
1151
 
1152
        /* ARGSUSED */
1153
static void
1154
SetTextCursor(canvas, itemPtr, index)
1155
    Tk_Canvas canvas;                   /* Record describing canvas widget. */
1156
    Tk_Item *itemPtr;                   /* Text item in which cursor position
1157
                                         * is to be set. */
1158
    int index;                          /* Index of character just before which
1159
                                         * cursor is to be positioned. */
1160
{
1161
    TextItem *textPtr = (TextItem *) itemPtr;
1162
 
1163
    if (index < 0) {
1164
        textPtr->insertPos = 0;
1165
    } else  if (index > textPtr->numChars) {
1166
        textPtr->insertPos = textPtr->numChars;
1167
    } else {
1168
        textPtr->insertPos = index;
1169
    }
1170
}
1171
 
1172
/*
1173
 *--------------------------------------------------------------
1174
 *
1175
 * GetSelText --
1176
 *
1177
 *      This procedure is invoked to return the selected portion
1178
 *      of a text item.  It is only called when this item has
1179
 *      the selection.
1180
 *
1181
 * Results:
1182
 *      The return value is the number of non-NULL bytes stored
1183
 *      at buffer.  Buffer is filled (or partially filled) with a
1184
 *      NULL-terminated string containing part or all of the selection,
1185
 *      as given by offset and maxBytes.
1186
 *
1187
 * Side effects:
1188
 *      None.
1189
 *
1190
 *--------------------------------------------------------------
1191
 */
1192
 
1193
static int
1194
GetSelText(canvas, itemPtr, offset, buffer, maxBytes)
1195
    Tk_Canvas canvas;                   /* Canvas containing selection. */
1196
    Tk_Item *itemPtr;                   /* Text item containing selection. */
1197
    int offset;                         /* Offset within selection of first
1198
                                         * character to be returned. */
1199
    char *buffer;                       /* Location in which to place
1200
                                         * selection. */
1201
    int maxBytes;                       /* Maximum number of bytes to place
1202
                                         * at buffer, not including terminating
1203
                                         * NULL character. */
1204
{
1205
    TextItem *textPtr = (TextItem *) itemPtr;
1206
    int count;
1207
    Tk_CanvasTextInfo *textInfoPtr = textPtr->textInfoPtr;
1208
 
1209
    count = textInfoPtr->selectLast + 1 - textInfoPtr->selectFirst - offset;
1210
    if (textInfoPtr->selectLast == textPtr->numChars) {
1211
        count -= 1;
1212
    }
1213
    if (count > maxBytes) {
1214
        count = maxBytes;
1215
    }
1216
    if (count <= 0) {
1217
        return 0;
1218
    }
1219
    strncpy(buffer, textPtr->text + textInfoPtr->selectFirst + offset,
1220
            (size_t) count);
1221
    buffer[count] = '\0';
1222
    return count;
1223
}
1224
 
1225
/*
1226
 *--------------------------------------------------------------
1227
 *
1228
 * TextToPostscript --
1229
 *
1230
 *      This procedure is called to generate Postscript for
1231
 *      text items.
1232
 *
1233
 * Results:
1234
 *      The return value is a standard Tcl result.  If an error
1235
 *      occurs in generating Postscript then an error message is
1236
 *      left in interp->result, replacing whatever used
1237
 *      to be there.  If no error occurs, then Postscript for the
1238
 *      item is appended to the result.
1239
 *
1240
 * Side effects:
1241
 *      None.
1242
 *
1243
 *--------------------------------------------------------------
1244
 */
1245
 
1246
static int
1247
TextToPostscript(interp, canvas, itemPtr, prepass)
1248
    Tcl_Interp *interp;                 /* Leave Postscript or error message
1249
                                         * here. */
1250
    Tk_Canvas canvas;                   /* Information about overall canvas. */
1251
    Tk_Item *itemPtr;                   /* Item for which Postscript is
1252
                                         * wanted. */
1253
    int prepass;                        /* 1 means this is a prepass to
1254
                                         * collect font information;  0 means
1255
                                         * final Postscript is being created. */
1256
{
1257
    TextItem *textPtr = (TextItem *) itemPtr;
1258
    int x, y;
1259
    Tk_FontMetrics fm;
1260
    char *justify;
1261
    char buffer[500];
1262
 
1263
    if (textPtr->color == NULL) {
1264
        return TCL_OK;
1265
    }
1266
 
1267
    if (Tk_CanvasPsFont(interp, canvas, textPtr->tkfont) != TCL_OK) {
1268
        return TCL_ERROR;
1269
    }
1270
    if (prepass != 0) {
1271
        return TCL_OK;
1272
    }
1273
    if (Tk_CanvasPsColor(interp, canvas, textPtr->color) != TCL_OK) {
1274
        return TCL_ERROR;
1275
    }
1276
    if (textPtr->stipple != None) {
1277
        Tcl_AppendResult(interp, "/StippleText {\n    ",
1278
                (char *) NULL);
1279
        Tk_CanvasPsStipple(interp, canvas, textPtr->stipple);
1280
        Tcl_AppendResult(interp, "} bind def\n", (char *) NULL);
1281
    }
1282
 
1283
    sprintf(buffer, "%.15g %.15g [\n", textPtr->x,
1284
            Tk_CanvasPsY(canvas, textPtr->y));
1285
    Tcl_AppendResult(interp, buffer, (char *) NULL);
1286
 
1287
    Tk_TextLayoutToPostscript(interp, textPtr->textLayout);
1288
 
1289
    x = 0;  y = 0;  justify = NULL;       /* lint. */
1290
    switch (textPtr->anchor) {
1291
        case TK_ANCHOR_NW:      x = 0; y = 0;     break;
1292
        case TK_ANCHOR_N:       x = 1; y = 0;    break;
1293
        case TK_ANCHOR_NE:      x = 2; y = 0;    break;
1294
        case TK_ANCHOR_E:       x = 2; y = 1;   break;
1295
        case TK_ANCHOR_SE:      x = 2; y = 2;   break;
1296
        case TK_ANCHOR_S:       x = 1; y = 2;   break;
1297
        case TK_ANCHOR_SW:      x = 0; y = 2;    break;
1298
        case TK_ANCHOR_W:       x = 0; y = 1;    break;
1299
        case TK_ANCHOR_CENTER:  x = 1; y = 1;   break;
1300
    }
1301
    switch (textPtr->justify) {
1302
        case TK_JUSTIFY_LEFT:   justify = "0";   break;
1303
        case TK_JUSTIFY_CENTER: justify = "0.5";break;
1304
        case TK_JUSTIFY_RIGHT:  justify = "1";  break;
1305
    }
1306
 
1307
    Tk_GetFontMetrics(textPtr->tkfont, &fm);
1308
    sprintf(buffer, "] %d %g %g %s %s DrawText\n",
1309
            fm.linespace, x / -2.0, y / 2.0, justify,
1310
            ((textPtr->stipple == None) ? "false" : "true"));
1311
    Tcl_AppendResult(interp, buffer, (char *) NULL);
1312
 
1313
    return TCL_OK;
1314
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.