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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 69 - (show annotations) (download)
Sat Nov 5 10:54:17 2016 UTC (6 years, 2 months ago) by dashley
File MIME type: text/plain
File size: 33421 byte(s)
License and property (keyword) changes.
1 /* $Header$ */
2
3 /*
4 * tkCanvWind.c --
5 *
6 * This file implements window items for canvas widgets.
7 *
8 * Copyright (c) 1992-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: tkcanvwind.c,v 1.1.1.1 2001/06/13 04:58:02 dtashley Exp $
15 */
16
17 #include <stdio.h>
18 #include "tkInt.h"
19 #include "tkPort.h"
20 #include "tkCanvas.h"
21
22 /*
23 * The structure below defines the record for each window item.
24 */
25
26 typedef struct WindowItem {
27 Tk_Item header; /* Generic stuff that's the same for all
28 * types. MUST BE FIRST IN STRUCTURE. */
29 double x, y; /* Coordinates of positioning point for
30 * window. */
31 Tk_Window tkwin; /* Window associated with item. NULL means
32 * window has been destroyed. */
33 int width; /* Width to use for window (<= 0 means use
34 * window's requested width). */
35 int height; /* Width to use for window (<= 0 means use
36 * window's requested width). */
37 Tk_Anchor anchor; /* Where to anchor window relative to
38 * (x,y). */
39 Tk_Canvas canvas; /* Canvas containing this item. */
40 } WindowItem;
41
42 /*
43 * Information used for parsing configuration specs:
44 */
45
46 static Tk_CustomOption stateOption = {
47 (Tk_OptionParseProc *) TkStateParseProc,
48 TkStatePrintProc, (ClientData) 2
49 };
50 static Tk_CustomOption tagsOption = {
51 (Tk_OptionParseProc *) Tk_CanvasTagsParseProc,
52 Tk_CanvasTagsPrintProc, (ClientData) NULL
53 };
54
55 static Tk_ConfigSpec configSpecs[] = {
56 {TK_CONFIG_ANCHOR, "-anchor", (char *) NULL, (char *) NULL,
57 "center", Tk_Offset(WindowItem, anchor), TK_CONFIG_DONT_SET_DEFAULT},
58 {TK_CONFIG_PIXELS, "-height", (char *) NULL, (char *) NULL,
59 "0", Tk_Offset(WindowItem, height), TK_CONFIG_DONT_SET_DEFAULT},
60 {TK_CONFIG_CUSTOM, "-state", (char *) NULL, (char *) NULL,
61 (char *) NULL, Tk_Offset(Tk_Item, state), TK_CONFIG_NULL_OK,
62 &stateOption},
63 {TK_CONFIG_CUSTOM, "-tags", (char *) NULL, (char *) NULL,
64 (char *) NULL, 0, TK_CONFIG_NULL_OK, &tagsOption},
65 {TK_CONFIG_PIXELS, "-width", (char *) NULL, (char *) NULL,
66 "0", Tk_Offset(WindowItem, width), TK_CONFIG_DONT_SET_DEFAULT},
67 {TK_CONFIG_WINDOW, "-window", (char *) NULL, (char *) NULL,
68 (char *) NULL, Tk_Offset(WindowItem, tkwin), TK_CONFIG_NULL_OK},
69 {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
70 (char *) NULL, 0, 0}
71 };
72
73 /*
74 * Prototypes for procedures defined in this file:
75 */
76
77 static void ComputeWindowBbox _ANSI_ARGS_((Tk_Canvas canvas,
78 WindowItem *winItemPtr));
79 static int ConfigureWinItem _ANSI_ARGS_((Tcl_Interp *interp,
80 Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
81 Tcl_Obj *CONST argv[], int flags));
82 static int CreateWinItem _ANSI_ARGS_((Tcl_Interp *interp,
83 Tk_Canvas canvas, struct Tk_Item *itemPtr,
84 int argc, Tcl_Obj *CONST argv[]));
85 static void DeleteWinItem _ANSI_ARGS_((Tk_Canvas canvas,
86 Tk_Item *itemPtr, Display *display));
87 static void DisplayWinItem _ANSI_ARGS_((Tk_Canvas canvas,
88 Tk_Item *itemPtr, Display *display, Drawable dst,
89 int x, int y, int width, int height));
90 static void ScaleWinItem _ANSI_ARGS_((Tk_Canvas canvas,
91 Tk_Item *itemPtr, double originX, double originY,
92 double scaleX, double scaleY));
93 static void TranslateWinItem _ANSI_ARGS_((Tk_Canvas canvas,
94 Tk_Item *itemPtr, double deltaX, double deltaY));
95 static int WinItemCoords _ANSI_ARGS_((Tcl_Interp *interp,
96 Tk_Canvas canvas, Tk_Item *itemPtr, int argc,
97 Tcl_Obj *CONST argv[]));
98 static void WinItemLostSlaveProc _ANSI_ARGS_((
99 ClientData clientData, Tk_Window tkwin));
100 static void WinItemRequestProc _ANSI_ARGS_((ClientData clientData,
101 Tk_Window tkwin));
102 static void WinItemStructureProc _ANSI_ARGS_((
103 ClientData clientData, XEvent *eventPtr));
104 static int WinItemToArea _ANSI_ARGS_((Tk_Canvas canvas,
105 Tk_Item *itemPtr, double *rectPtr));
106 static int WinItemToPostscript _ANSI_ARGS_((Tcl_Interp *interp,
107 Tk_Canvas canvas, Tk_Item *itemPtr, int prepass));
108 static double WinItemToPoint _ANSI_ARGS_((Tk_Canvas canvas,
109 Tk_Item *itemPtr, double *pointPtr));
110 #ifdef X_GetImage
111 static int xerrorhandler _ANSI_ARGS_((ClientData clientData,
112 XErrorEvent *e));
113 #endif
114 static int CanvasPsWindow _ANSI_ARGS_((Tcl_Interp *interp,
115 Tk_Window tkwin, Tk_Canvas canvas, double x,
116 double y, int width, int height));
117
118 /*
119 * The structure below defines the window item type by means of procedures
120 * that can be invoked by generic item code.
121 */
122
123 Tk_ItemType tkWindowType = {
124 "window", /* name */
125 sizeof(WindowItem), /* itemSize */
126 CreateWinItem, /* createProc */
127 configSpecs, /* configSpecs */
128 ConfigureWinItem, /* configureProc */
129 WinItemCoords, /* coordProc */
130 DeleteWinItem, /* deleteProc */
131 DisplayWinItem, /* displayProc */
132 1|TK_CONFIG_OBJS, /* flags */
133 WinItemToPoint, /* pointProc */
134 WinItemToArea, /* areaProc */
135 WinItemToPostscript, /* postscriptProc */
136 ScaleWinItem, /* scaleProc */
137 TranslateWinItem, /* translateProc */
138 (Tk_ItemIndexProc *) NULL, /* indexProc */
139 (Tk_ItemCursorProc *) NULL, /* cursorProc */
140 (Tk_ItemSelectionProc *) NULL, /* selectionProc */
141 (Tk_ItemInsertProc *) NULL, /* insertProc */
142 (Tk_ItemDCharsProc *) NULL, /* dTextProc */
143 (Tk_ItemType *) NULL, /* nextPtr */
144 };
145
146
147 /*
148 * The structure below defines the official type record for the
149 * placer:
150 */
151
152 static Tk_GeomMgr canvasGeomType = {
153 "canvas", /* name */
154 WinItemRequestProc, /* requestProc */
155 WinItemLostSlaveProc, /* lostSlaveProc */
156 };
157
158 /*
159 *--------------------------------------------------------------
160 *
161 * CreateWinItem --
162 *
163 * This procedure is invoked to create a new window
164 * item in a canvas.
165 *
166 * Results:
167 * A standard Tcl return value. If an error occurred in
168 * creating the item, then an error message is left in
169 * the interp's result; in this case itemPtr is
170 * left uninitialized, so it can be safely freed by the
171 * caller.
172 *
173 * Side effects:
174 * A new window item is created.
175 *
176 *--------------------------------------------------------------
177 */
178
179 static int
180 CreateWinItem(interp, canvas, itemPtr, argc, argv)
181 Tcl_Interp *interp; /* Interpreter for error reporting. */
182 Tk_Canvas canvas; /* Canvas to hold new item. */
183 Tk_Item *itemPtr; /* Record to hold new item; header
184 * has been initialized by caller. */
185 int argc; /* Number of arguments in argv. */
186 Tcl_Obj *CONST argv[]; /* Arguments describing window. */
187 {
188 WindowItem *winItemPtr = (WindowItem *) itemPtr;
189 int i;
190
191 if (argc==1) {
192 i = 1;
193 } else {
194 char *arg = Tcl_GetStringFromObj(argv[1], NULL);
195 if (((argc>1) && (arg[0] == '-')
196 && (arg[1] >= 'a') && (arg[1] <= 'z'))) {
197 i = 1;
198 } else {
199 i = 2;
200 }
201 }
202
203 if (argc < i) {
204 Tcl_AppendResult(interp, "wrong # args: should be \"",
205 Tk_PathName(Tk_CanvasTkwin(canvas)), " create ",
206 itemPtr->typePtr->name, " x y ?options?\"",
207 (char *) NULL);
208 return TCL_ERROR;
209 }
210
211 /*
212 * Initialize item's record.
213 */
214
215 winItemPtr->tkwin = NULL;
216 winItemPtr->width = 0;
217 winItemPtr->height = 0;
218 winItemPtr->anchor = TK_ANCHOR_CENTER;
219 winItemPtr->canvas = canvas;
220
221 /*
222 * Process the arguments to fill in the item record.
223 */
224
225 if ((WinItemCoords(interp, canvas, itemPtr, i, argv) != TCL_OK)) {
226 goto error;
227 }
228 if (ConfigureWinItem(interp, canvas, itemPtr, argc-i, argv+i, 0) == TCL_OK) {
229 return TCL_OK;
230 }
231
232 error:
233 DeleteWinItem(canvas, itemPtr, Tk_Display(Tk_CanvasTkwin(canvas)));
234 return TCL_ERROR;
235 }
236
237 /*
238 *--------------------------------------------------------------
239 *
240 * WinItemCoords --
241 *
242 * This procedure is invoked to process the "coords" widget
243 * command on window items. See the user documentation for
244 * details on what it does.
245 *
246 * Results:
247 * Returns TCL_OK or TCL_ERROR, and sets the interp's result.
248 *
249 * Side effects:
250 * The coordinates for the given item may be changed.
251 *
252 *--------------------------------------------------------------
253 */
254
255 static int
256 WinItemCoords(interp, canvas, itemPtr, argc, argv)
257 Tcl_Interp *interp; /* Used for error reporting. */
258 Tk_Canvas canvas; /* Canvas containing item. */
259 Tk_Item *itemPtr; /* Item whose coordinates are to be
260 * read or modified. */
261 int argc; /* Number of coordinates supplied in
262 * argv. */
263 Tcl_Obj *CONST argv[]; /* Array of coordinates: x1, y1,
264 * x2, y2, ... */
265 {
266 WindowItem *winItemPtr = (WindowItem *) itemPtr;
267
268 if (argc == 0) {
269 Tcl_Obj *obj = Tcl_NewObj();
270 Tcl_Obj *subobj = Tcl_NewDoubleObj(winItemPtr->x);
271 Tcl_ListObjAppendElement(interp, obj, subobj);
272 subobj = Tcl_NewDoubleObj(winItemPtr->y);
273 Tcl_ListObjAppendElement(interp, obj, subobj);
274 Tcl_SetObjResult(interp, obj);
275 } else if (argc < 3) {
276 if (argc==1) {
277 if (Tcl_ListObjGetElements(interp, argv[0], &argc,
278 (Tcl_Obj ***) &argv) != TCL_OK) {
279 return TCL_ERROR;
280 } else if (argc != 2) {
281 char buf[64 + TCL_INTEGER_SPACE];
282
283 sprintf(buf, "wrong # coordinates: expected 2, got %d", argc);
284 Tcl_SetResult(interp, buf, TCL_VOLATILE);
285 return TCL_ERROR;
286 }
287 }
288 if ((Tk_CanvasGetCoordFromObj(interp, canvas, argv[0], &winItemPtr->x)
289 != TCL_OK) || (Tk_CanvasGetCoordFromObj(interp, canvas, argv[1],
290 &winItemPtr->y) != TCL_OK)) {
291 return TCL_ERROR;
292 }
293 ComputeWindowBbox(canvas, winItemPtr);
294 } else {
295 char buf[64 + TCL_INTEGER_SPACE];
296
297 sprintf(buf, "wrong # coordinates: expected 0 or 2, got %d", argc);
298 Tcl_SetResult(interp, buf, TCL_VOLATILE);
299 return TCL_ERROR;
300 }
301 return TCL_OK;
302 }
303
304 /*
305 *--------------------------------------------------------------
306 *
307 * ConfigureWinItem --
308 *
309 * This procedure is invoked to configure various aspects
310 * of a window item, such as its anchor position.
311 *
312 * Results:
313 * A standard Tcl result code. If an error occurs, then
314 * an error message is left in the interp's result.
315 *
316 * Side effects:
317 * Configuration information may be set for itemPtr.
318 *
319 *--------------------------------------------------------------
320 */
321
322 static int
323 ConfigureWinItem(interp, canvas, itemPtr, argc, argv, flags)
324 Tcl_Interp *interp; /* Used for error reporting. */
325 Tk_Canvas canvas; /* Canvas containing itemPtr. */
326 Tk_Item *itemPtr; /* Window item to reconfigure. */
327 int argc; /* Number of elements in argv. */
328 Tcl_Obj *CONST argv[]; /* Arguments describing things to configure. */
329 int flags; /* Flags to pass to Tk_ConfigureWidget. */
330 {
331 WindowItem *winItemPtr = (WindowItem *) itemPtr;
332 Tk_Window oldWindow;
333 Tk_Window canvasTkwin;
334
335 oldWindow = winItemPtr->tkwin;
336 canvasTkwin = Tk_CanvasTkwin(canvas);
337 if (Tk_ConfigureWidget(interp, canvasTkwin, configSpecs, argc, (char **) argv,
338 (char *) winItemPtr, flags|TK_CONFIG_OBJS) != TCL_OK) {
339 return TCL_ERROR;
340 }
341
342 /*
343 * A few of the options require additional processing.
344 */
345
346 if (oldWindow != winItemPtr->tkwin) {
347 if (oldWindow != NULL) {
348 Tk_DeleteEventHandler(oldWindow, StructureNotifyMask,
349 WinItemStructureProc, (ClientData) winItemPtr);
350 Tk_ManageGeometry(oldWindow, (Tk_GeomMgr *) NULL,
351 (ClientData) NULL);
352 Tk_UnmaintainGeometry(oldWindow, canvasTkwin);
353 Tk_UnmapWindow(oldWindow);
354 }
355 if (winItemPtr->tkwin != NULL) {
356 Tk_Window ancestor, parent;
357
358 /*
359 * Make sure that the canvas is either the parent of the
360 * window associated with the item or a descendant of that
361 * parent. Also, don't allow a top-level window to be
362 * managed inside a canvas.
363 */
364
365 parent = Tk_Parent(winItemPtr->tkwin);
366 for (ancestor = canvasTkwin; ;
367 ancestor = Tk_Parent(ancestor)) {
368 if (ancestor == parent) {
369 break;
370 }
371 if (((Tk_FakeWin *) (ancestor))->flags & TK_TOP_LEVEL) {
372 badWindow:
373 Tcl_AppendResult(interp, "can't use ",
374 Tk_PathName(winItemPtr->tkwin),
375 " in a window item of this canvas", (char *) NULL);
376 winItemPtr->tkwin = NULL;
377 return TCL_ERROR;
378 }
379 }
380 if (((Tk_FakeWin *) (winItemPtr->tkwin))->flags & TK_TOP_LEVEL) {
381 goto badWindow;
382 }
383 if (winItemPtr->tkwin == canvasTkwin) {
384 goto badWindow;
385 }
386 Tk_CreateEventHandler(winItemPtr->tkwin, StructureNotifyMask,
387 WinItemStructureProc, (ClientData) winItemPtr);
388 Tk_ManageGeometry(winItemPtr->tkwin, &canvasGeomType,
389 (ClientData) winItemPtr);
390 }
391 }
392
393 ComputeWindowBbox(canvas, winItemPtr);
394
395 return TCL_OK;
396 }
397
398 /*
399 *--------------------------------------------------------------
400 *
401 * DeleteWinItem --
402 *
403 * This procedure is called to clean up the data structure
404 * associated with a window item.
405 *
406 * Results:
407 * None.
408 *
409 * Side effects:
410 * Resources associated with itemPtr are released.
411 *
412 *--------------------------------------------------------------
413 */
414
415 static void
416 DeleteWinItem(canvas, itemPtr, display)
417 Tk_Canvas canvas; /* Overall info about widget. */
418 Tk_Item *itemPtr; /* Item that is being deleted. */
419 Display *display; /* Display containing window for
420 * canvas. */
421 {
422 WindowItem *winItemPtr = (WindowItem *) itemPtr;
423 Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);
424
425 if (winItemPtr->tkwin != NULL) {
426 Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,
427 WinItemStructureProc, (ClientData) winItemPtr);
428 Tk_ManageGeometry(winItemPtr->tkwin, (Tk_GeomMgr *) NULL,
429 (ClientData) NULL);
430 if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {
431 Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
432 }
433 Tk_UnmapWindow(winItemPtr->tkwin);
434 }
435 }
436
437 /*
438 *--------------------------------------------------------------
439 *
440 * ComputeWindowBbox --
441 *
442 * This procedure is invoked to compute the bounding box of
443 * all the pixels that may be drawn as part of a window item.
444 * This procedure is where the child window's placement is
445 * computed.
446 *
447 * Results:
448 * None.
449 *
450 * Side effects:
451 * The fields x1, y1, x2, and y2 are updated in the header
452 * for itemPtr.
453 *
454 *--------------------------------------------------------------
455 */
456
457 static void
458 ComputeWindowBbox(canvas, winItemPtr)
459 Tk_Canvas canvas; /* Canvas that contains item. */
460 WindowItem *winItemPtr; /* Item whose bbox is to be
461 * recomputed. */
462 {
463 int width, height, x, y;
464 Tk_State state = winItemPtr->header.state;
465
466 x = (int) (winItemPtr->x + ((winItemPtr->x >= 0) ? 0.5 : - 0.5));
467 y = (int) (winItemPtr->y + ((winItemPtr->y >= 0) ? 0.5 : - 0.5));
468
469 if (state == TK_STATE_NULL) {
470 state = ((TkCanvas *)canvas)->canvas_state;
471 }
472 if ((winItemPtr->tkwin == NULL) || (state == TK_STATE_HIDDEN)) {
473 /*
474 * There is no window for this item yet. Just give it a 1x1
475 * bounding box. Don't give it a 0x0 bounding box; there are
476 * strange cases where this bounding box might be used as the
477 * dimensions of the window, and 0x0 causes problems under X.
478 */
479
480 winItemPtr->header.x1 = x;
481 winItemPtr->header.x2 = winItemPtr->header.x1 + 1;
482 winItemPtr->header.y1 = y;
483 winItemPtr->header.y2 = winItemPtr->header.y1 + 1;
484 return;
485 }
486
487 /*
488 * Compute dimensions of window.
489 */
490
491 width = winItemPtr->width;
492 if (width <= 0) {
493 width = Tk_ReqWidth(winItemPtr->tkwin);
494 if (width <= 0) {
495 width = 1;
496 }
497 }
498 height = winItemPtr->height;
499 if (height <= 0) {
500 height = Tk_ReqHeight(winItemPtr->tkwin);
501 if (height <= 0) {
502 height = 1;
503 }
504 }
505
506 /*
507 * Compute location of window, using anchor information.
508 */
509
510 switch (winItemPtr->anchor) {
511 case TK_ANCHOR_N:
512 x -= width/2;
513 break;
514 case TK_ANCHOR_NE:
515 x -= width;
516 break;
517 case TK_ANCHOR_E:
518 x -= width;
519 y -= height/2;
520 break;
521 case TK_ANCHOR_SE:
522 x -= width;
523 y -= height;
524 break;
525 case TK_ANCHOR_S:
526 x -= width/2;
527 y -= height;
528 break;
529 case TK_ANCHOR_SW:
530 y -= height;
531 break;
532 case TK_ANCHOR_W:
533 y -= height/2;
534 break;
535 case TK_ANCHOR_NW:
536 break;
537 case TK_ANCHOR_CENTER:
538 x -= width/2;
539 y -= height/2;
540 break;
541 }
542
543 /*
544 * Store the information in the item header.
545 */
546
547 winItemPtr->header.x1 = x;
548 winItemPtr->header.y1 = y;
549 winItemPtr->header.x2 = x + width;
550 winItemPtr->header.y2 = y + height;
551 }
552
553 /*
554 *--------------------------------------------------------------
555 *
556 * DisplayWinItem --
557 *
558 * This procedure is invoked to "draw" a window item in a given
559 * drawable. Since the window draws itself, we needn't do any
560 * actual redisplay here. However, this procedure takes care
561 * of actually repositioning the child window so that it occupies
562 * the correct screen position.
563 *
564 * Results:
565 * None.
566 *
567 * Side effects:
568 * The child window's position may get changed. Note: this
569 * procedure gets called both when a window needs to be displayed
570 * and when it ceases to be visible on the screen (e.g. it was
571 * scrolled or moved off-screen or the enclosing canvas is
572 * unmapped).
573 *
574 *--------------------------------------------------------------
575 */
576
577 static void
578 DisplayWinItem(canvas, itemPtr, display, drawable, regionX, regionY,
579 regionWidth, regionHeight)
580 Tk_Canvas canvas; /* Canvas that contains item. */
581 Tk_Item *itemPtr; /* Item to be displayed. */
582 Display *display; /* Display on which to draw item. */
583 Drawable drawable; /* Pixmap or window in which to draw
584 * item. */
585 int regionX, regionY, regionWidth, regionHeight;
586 /* Describes region of canvas that
587 * must be redisplayed (not used). */
588 {
589 WindowItem *winItemPtr = (WindowItem *) itemPtr;
590 int width, height;
591 short x, y;
592 Tk_Window canvasTkwin = Tk_CanvasTkwin(canvas);
593 Tk_State state = itemPtr->state;
594
595 if (winItemPtr->tkwin == NULL) {
596 return;
597 }
598 if(state == TK_STATE_NULL) {
599 state = ((TkCanvas *)canvas)->canvas_state;
600 }
601 if (state == TK_STATE_HIDDEN) {
602 Tk_UnmapWindow(winItemPtr->tkwin);
603 return;
604 }
605 Tk_CanvasWindowCoords(canvas, (double) winItemPtr->header.x1,
606 (double) winItemPtr->header.y1, &x, &y);
607 width = winItemPtr->header.x2 - winItemPtr->header.x1;
608 height = winItemPtr->header.y2 - winItemPtr->header.y1;
609
610 /*
611 * If the window is completely out of the visible area of the canvas
612 * then unmap it. This code used not to be present (why unmap the
613 * window if it isn't visible anyway?) but this could cause the
614 * window to suddenly reappear if the canvas window got resized.
615 */
616
617 if (((x + width) <= 0) || ((y + height) <= 0)
618 || (x >= Tk_Width(canvasTkwin)) || (y >= Tk_Height(canvasTkwin))) {
619 if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
620 Tk_UnmapWindow(winItemPtr->tkwin);
621 } else {
622 Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
623 }
624 return;
625 }
626
627 /*
628 * Reposition and map the window (but in different ways depending
629 * on whether the canvas is the window's parent).
630 */
631
632 if (canvasTkwin == Tk_Parent(winItemPtr->tkwin)) {
633 if ((x != Tk_X(winItemPtr->tkwin)) || (y != Tk_Y(winItemPtr->tkwin))
634 || (width != Tk_Width(winItemPtr->tkwin))
635 || (height != Tk_Height(winItemPtr->tkwin))) {
636 Tk_MoveResizeWindow(winItemPtr->tkwin, x, y, width, height);
637 }
638 Tk_MapWindow(winItemPtr->tkwin);
639 } else {
640 Tk_MaintainGeometry(winItemPtr->tkwin, canvasTkwin, x, y,
641 width, height);
642 }
643 }
644
645 /*
646 *--------------------------------------------------------------
647 *
648 * WinItemToPoint --
649 *
650 * Computes the distance from a given point to a given
651 * window, in canvas units.
652 *
653 * Results:
654 * The return value is 0 if the point whose x and y coordinates
655 * are coordPtr[0] and coordPtr[1] is inside the window. If the
656 * point isn't inside the window then the return value is the
657 * distance from the point to the window.
658 *
659 * Side effects:
660 * None.
661 *
662 *--------------------------------------------------------------
663 */
664
665 static double
666 WinItemToPoint(canvas, itemPtr, pointPtr)
667 Tk_Canvas canvas; /* Canvas containing item. */
668 Tk_Item *itemPtr; /* Item to check against point. */
669 double *pointPtr; /* Pointer to x and y coordinates. */
670 {
671 WindowItem *winItemPtr = (WindowItem *) itemPtr;
672 double x1, x2, y1, y2, xDiff, yDiff;
673
674 x1 = winItemPtr->header.x1;
675 y1 = winItemPtr->header.y1;
676 x2 = winItemPtr->header.x2;
677 y2 = winItemPtr->header.y2;
678
679 /*
680 * Point is outside window.
681 */
682
683 if (pointPtr[0] < x1) {
684 xDiff = x1 - pointPtr[0];
685 } else if (pointPtr[0] >= x2) {
686 xDiff = pointPtr[0] + 1 - x2;
687 } else {
688 xDiff = 0;
689 }
690
691 if (pointPtr[1] < y1) {
692 yDiff = y1 - pointPtr[1];
693 } else if (pointPtr[1] >= y2) {
694 yDiff = pointPtr[1] + 1 - y2;
695 } else {
696 yDiff = 0;
697 }
698
699 return hypot(xDiff, yDiff);
700 }
701
702 /*
703 *--------------------------------------------------------------
704 *
705 * WinItemToArea --
706 *
707 * This procedure is called to determine whether an item
708 * lies entirely inside, entirely outside, or overlapping
709 * a given rectangle.
710 *
711 * Results:
712 * -1 is returned if the item is entirely outside the area
713 * given by rectPtr, 0 if it overlaps, and 1 if it is entirely
714 * inside the given area.
715 *
716 * Side effects:
717 * None.
718 *
719 *--------------------------------------------------------------
720 */
721
722 static int
723 WinItemToArea(canvas, itemPtr, rectPtr)
724 Tk_Canvas canvas; /* Canvas containing item. */
725 Tk_Item *itemPtr; /* Item to check against rectangle. */
726 double *rectPtr; /* Pointer to array of four coordinates
727 * (x1, y1, x2, y2) describing rectangular
728 * area. */
729 {
730 WindowItem *winItemPtr = (WindowItem *) itemPtr;
731
732 if ((rectPtr[2] <= winItemPtr->header.x1)
733 || (rectPtr[0] >= winItemPtr->header.x2)
734 || (rectPtr[3] <= winItemPtr->header.y1)
735 || (rectPtr[1] >= winItemPtr->header.y2)) {
736 return -1;
737 }
738 if ((rectPtr[0] <= winItemPtr->header.x1)
739 && (rectPtr[1] <= winItemPtr->header.y1)
740 && (rectPtr[2] >= winItemPtr->header.x2)
741 && (rectPtr[3] >= winItemPtr->header.y2)) {
742 return 1;
743 }
744 return 0;
745 }
746
747 /*
748 *--------------------------------------------------------------
749 *
750 * xerrorhandler --
751 *
752 * This is a dummy function to catch X11 errors during an
753 * attempt to print a canvas window.
754 *
755 * Results:
756 * None.
757 *
758 * Side effects:
759 * None.
760 *
761 *--------------------------------------------------------------
762 */
763
764 #ifdef X_GetImage
765 static int
766 xerrorhandler(clientData, e)
767 ClientData clientData;
768 XErrorEvent *e;
769 {
770 return 0;
771 }
772 #endif
773
774
775 /*
776 *--------------------------------------------------------------
777 *
778 * WinItemToPostscript --
779 *
780 * This procedure is called to generate Postscript for
781 * window items.
782 *
783 * Results:
784 * The return value is a standard Tcl result. If an error
785 * occurs in generating Postscript then an error message is
786 * left in interp->result, replacing whatever used to be there.
787 * If no error occurs, then Postscript for the item is appended
788 * to the result.
789 *
790 * Side effects:
791 * None.
792 *
793 *--------------------------------------------------------------
794 */
795
796 static int
797 WinItemToPostscript(interp, canvas, itemPtr, prepass)
798 Tcl_Interp *interp; /* Leave Postscript or error message
799 * here. */
800 Tk_Canvas canvas; /* Information about overall canvas. */
801 Tk_Item *itemPtr; /* Item for which Postscript is
802 * wanted. */
803 int prepass; /* 1 means this is a prepass to
804 * collect font information; 0 means
805 * final Postscript is being created.*/
806 {
807 WindowItem *winItemPtr = (WindowItem *)itemPtr;
808
809 double x, y;
810 int width, height;
811 Tk_Window tkwin = winItemPtr->tkwin;
812
813 if (prepass || winItemPtr->tkwin == NULL) {
814 return TCL_OK;
815 }
816
817 width = Tk_Width(tkwin);
818 height = Tk_Height(tkwin);
819
820 /*
821 * Compute the coordinates of the lower-left corner of the window,
822 * taking into account the anchor position for the window.
823 */
824
825 x = winItemPtr->x;
826 y = Tk_CanvasPsY(canvas, winItemPtr->y);
827
828 switch (winItemPtr->anchor) {
829 case TK_ANCHOR_NW: y -= height; break;
830 case TK_ANCHOR_N: x -= width/2.0; y -= height; break;
831 case TK_ANCHOR_NE: x -= width; y -= height; break;
832 case TK_ANCHOR_E: x -= width; y -= height/2.0; break;
833 case TK_ANCHOR_SE: x -= width; break;
834 case TK_ANCHOR_S: x -= width/2.0; break;
835 case TK_ANCHOR_SW: break;
836 case TK_ANCHOR_W: y -= height/2.0; break;
837 case TK_ANCHOR_CENTER: x -= width/2.0; y -= height/2.0; break;
838 }
839
840 return CanvasPsWindow(interp, tkwin, canvas, x, y, width, height);
841 }
842
843 static int
844 CanvasPsWindow(interp, tkwin, canvas, x, y, width, height)
845 Tcl_Interp *interp; /* Leave Postscript or error message
846 * here. */
847 Tk_Window tkwin; /* window to be printed */
848 Tk_Canvas canvas; /* Information about overall canvas. */
849 double x, y; /* origin of window. */
850 int width, height; /* width/height of window. */
851 {
852 char buffer[256];
853 TkWindow *winPtr;
854 XImage *ximage;
855 int result;
856 Tcl_DString buffer1, buffer2;
857 #ifdef X_GetImage
858 Tk_ErrorHandler handle;
859 #endif
860
861 sprintf(buffer, "\n%%%% %s item (%s, %d x %d)\n%.15g %.15g translate\n",
862 Tk_Class(tkwin), Tk_PathName(tkwin), width, height, x, y);
863 Tcl_AppendResult(interp, buffer, (char *) NULL);
864
865 /* first try if the widget has its own "postscript" command. If it
866 * exists, this will produce much better postscript than
867 * when a pixmap is used.
868 */
869
870 Tcl_DStringInit(&buffer1);
871 Tcl_DStringInit(&buffer2);
872 Tcl_DStringGetResult(interp, &buffer2);
873 sprintf (buffer, "%s postscript -prolog 0\n", Tk_PathName(tkwin));
874 result = Tcl_Eval(interp, buffer);
875 Tcl_DStringGetResult(interp, &buffer1);
876 Tcl_DStringResult(interp, &buffer2);
877 Tcl_DStringFree(&buffer2);
878
879 if (result == TCL_OK) {
880 Tcl_AppendResult(interp,
881 "50 dict begin\nsave\ngsave\n",
882 (char *) NULL);
883 sprintf (buffer,
884 "0 %d moveto %d 0 rlineto 0 -%d rlineto -%d",
885 height, width, height, width);
886 Tcl_AppendResult(interp, buffer, (char *) NULL);
887 Tcl_AppendResult(interp, " 0 rlineto closepath\n",
888 "1.000 1.000 1.000 setrgbcolor AdjustColor\nfill\ngrestore\n",
889 Tcl_DStringValue(&buffer1), "\nrestore\nend\n\n\n",
890 (char *) NULL);
891 Tcl_DStringFree(&buffer1);
892
893 for (winPtr = ((TkWindow *) tkwin)->childList; winPtr != NULL;
894 winPtr = winPtr->nextPtr) {
895 if (Tk_IsMapped(winPtr)) {
896 /* printf("child window: %s\n", winPtr->pathName);*/
897 }
898 }
899 return result;
900 }
901 Tcl_DStringFree(&buffer1);
902
903 /*
904 * If the window is off the screen it will generate an BadMatch/XError
905 * We catch any BadMatch errors here
906 */
907 #ifdef X_GetImage
908 handle = Tk_CreateErrorHandler(Tk_Display(tkwin), BadMatch,
909 X_GetImage, -1, xerrorhandler, (ClientData) tkwin);
910 #endif
911
912 /*
913 * Generate an XImage from the window. We can then read pixel
914 * values out of the XImage.
915 */
916
917 ximage = XGetImage(Tk_Display(tkwin), Tk_WindowId(tkwin), 0, 0,
918 (unsigned int)width, (unsigned int)height, AllPlanes, ZPixmap);
919
920 #ifdef X_GetImage
921 Tk_DeleteErrorHandler(handle);
922 #endif
923
924 if (ximage == (XImage*) NULL) {
925 return TCL_OK;
926 }
927
928 result = TkPostscriptImage(interp, tkwin,
929 ((TkCanvas *)canvas)->psInfo, ximage, 0, 0, width, height);
930
931 XDestroyImage(ximage);
932 return result;
933 }
934
935 /*
936 *--------------------------------------------------------------
937 *
938 * ScaleWinItem --
939 *
940 * This procedure is invoked to rescale a window item.
941 *
942 * Results:
943 * None.
944 *
945 * Side effects:
946 * The window referred to by itemPtr is rescaled
947 * so that the following transformation is applied to all
948 * point coordinates:
949 * x' = originX + scaleX*(x-originX)
950 * y' = originY + scaleY*(y-originY)
951 *
952 *--------------------------------------------------------------
953 */
954
955 static void
956 ScaleWinItem(canvas, itemPtr, originX, originY, scaleX, scaleY)
957 Tk_Canvas canvas; /* Canvas containing window. */
958 Tk_Item *itemPtr; /* Window to be scaled. */
959 double originX, originY; /* Origin about which to scale window. */
960 double scaleX; /* Amount to scale in X direction. */
961 double scaleY; /* Amount to scale in Y direction. */
962 {
963 WindowItem *winItemPtr = (WindowItem *) itemPtr;
964
965 winItemPtr->x = originX + scaleX*(winItemPtr->x - originX);
966 winItemPtr->y = originY + scaleY*(winItemPtr->y - originY);
967 if (winItemPtr->width > 0) {
968 winItemPtr->width = (int) (scaleX*winItemPtr->width);
969 }
970 if (winItemPtr->height > 0) {
971 winItemPtr->height = (int) (scaleY*winItemPtr->height);
972 }
973 ComputeWindowBbox(canvas, winItemPtr);
974 }
975
976 /*
977 *--------------------------------------------------------------
978 *
979 * TranslateWinItem --
980 *
981 * This procedure is called to move a window by a given amount.
982 *
983 * Results:
984 * None.
985 *
986 * Side effects:
987 * The position of the window is offset by (xDelta, yDelta),
988 * and the bounding box is updated in the generic part of the
989 * item structure.
990 *
991 *--------------------------------------------------------------
992 */
993
994 static void
995 TranslateWinItem(canvas, itemPtr, deltaX, deltaY)
996 Tk_Canvas canvas; /* Canvas containing item. */
997 Tk_Item *itemPtr; /* Item that is being moved. */
998 double deltaX, deltaY; /* Amount by which item is to be
999 * moved. */
1000 {
1001 WindowItem *winItemPtr = (WindowItem *) itemPtr;
1002
1003 winItemPtr->x += deltaX;
1004 winItemPtr->y += deltaY;
1005 ComputeWindowBbox(canvas, winItemPtr);
1006 }
1007
1008 /*
1009 *--------------------------------------------------------------
1010 *
1011 * WinItemStructureProc --
1012 *
1013 * This procedure is invoked whenever StructureNotify events
1014 * occur for a window that's managed as part of a canvas window
1015 * item. This procudure's only purpose is to clean up when
1016 * windows are deleted.
1017 *
1018 * Results:
1019 * None.
1020 *
1021 * Side effects:
1022 * The window is disassociated from the window item when it is
1023 * deleted.
1024 *
1025 *--------------------------------------------------------------
1026 */
1027
1028 static void
1029 WinItemStructureProc(clientData, eventPtr)
1030 ClientData clientData; /* Pointer to record describing window item. */
1031 XEvent *eventPtr; /* Describes what just happened. */
1032 {
1033 WindowItem *winItemPtr = (WindowItem *) clientData;
1034
1035 if (eventPtr->type == DestroyNotify) {
1036 winItemPtr->tkwin = NULL;
1037 }
1038 }
1039
1040 /*
1041 *--------------------------------------------------------------
1042 *
1043 * WinItemRequestProc --
1044 *
1045 * This procedure is invoked whenever a window that's associated
1046 * with a window canvas item changes its requested dimensions.
1047 *
1048 * Results:
1049 * None.
1050 *
1051 * Side effects:
1052 * The size and location on the screen of the window may change,
1053 * depending on the options specified for the window item.
1054 *
1055 *--------------------------------------------------------------
1056 */
1057
1058 static void
1059 WinItemRequestProc(clientData, tkwin)
1060 ClientData clientData; /* Pointer to record for window item. */
1061 Tk_Window tkwin; /* Window that changed its desired
1062 * size. */
1063 {
1064 WindowItem *winItemPtr = (WindowItem *) clientData;
1065
1066 ComputeWindowBbox(winItemPtr->canvas, winItemPtr);
1067 DisplayWinItem(winItemPtr->canvas, (Tk_Item *) winItemPtr,
1068 (Display *) NULL, (Drawable) None, 0, 0, 0, 0);
1069 }
1070
1071 /*
1072 *--------------------------------------------------------------
1073 *
1074 * WinItemLostSlaveProc --
1075 *
1076 * This procedure is invoked by Tk whenever some other geometry
1077 * claims control over a slave that used to be managed by us.
1078 *
1079 * Results:
1080 * None.
1081 *
1082 * Side effects:
1083 * Forgets all canvas-related information about the slave.
1084 *
1085 *--------------------------------------------------------------
1086 */
1087
1088 /* ARGSUSED */
1089 static void
1090 WinItemLostSlaveProc(clientData, tkwin)
1091 ClientData clientData; /* WindowItem structure for slave window that
1092 * was stolen away. */
1093 Tk_Window tkwin; /* Tk's handle for the slave window. */
1094 {
1095 WindowItem *winItemPtr = (WindowItem *) clientData;
1096 Tk_Window canvasTkwin = Tk_CanvasTkwin(winItemPtr->canvas);
1097
1098 Tk_DeleteEventHandler(winItemPtr->tkwin, StructureNotifyMask,
1099 WinItemStructureProc, (ClientData) winItemPtr);
1100 if (canvasTkwin != Tk_Parent(winItemPtr->tkwin)) {
1101 Tk_UnmaintainGeometry(winItemPtr->tkwin, canvasTkwin);
1102 }
1103 Tk_UnmapWindow(winItemPtr->tkwin);
1104 winItemPtr->tkwin = NULL;
1105 }
1106
1107 /* End of tkcanvwind.c */

Properties

Name Value
svn:keywords Header

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25