/[dtapublic]/projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkcanvtext.c
ViewVC logotype

Contents of /projs/trunk/shared_source/c_tk_base_7_5_w_mods/tkcanvtext.c

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25