1 /* windCmdSZ.c -
2 *
3 * This file contains Magic command routines for those commands
4 * that are valid in all windows.
5 *
6 * *********************************************************************
7 * * Copyright (C) 1985, 1990 Regents of the University of California. *
8 * * Permission to use, copy, modify, and distribute this *
9 * * software and its documentation for any purpose and without *
10 * * fee is hereby granted, provided that the above copyright *
11 * * notice appear in all copies. The University of California *
12 * * makes no representations about the suitability of this *
13 * * software for any purpose. It is provided "as is" without *
14 * * express or implied warranty. Export of this software outside *
15 * * of the United States of America may require an export license. *
16 * *********************************************************************
17 */
18
19 #ifndef lint
20 static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/windows/windCmdSZ.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
21 #endif /* not lint */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h> /* for sleep() */
26 #include <string.h>
27 #include <math.h>
28
29 #include "tcltk/tclmagic.h"
30 #include "utils/magic.h"
31 #include "textio/textio.h"
32 #include "utils/geometry.h"
33 #include "tiles/tile.h"
34 #include "windows/windows.h"
35 #include "graphics/glyphs.h"
36 #include "windows/windInt.h"
37 #include "utils/undo.h"
38 #include "utils/utils.h"
39 #include "utils/signals.h"
40 #include "textio/txcommands.h"
41 #include "utils/hash.h"
42 #include "database/database.h"
43 #include "dbwind/dbwind.h"
44 #include "graphics/graphics.h"
45
46
47 /*
48 * ----------------------------------------------------------------------------
49 *
50 * windScrollCmd --
51 *
52 * Scroll the view around
53 *
54 * Usage:
55 * scroll dir [amount [units]]
56 *
57 * Results:
58 * None.
59 *
60 * Side effects:
61 * The window underneath the cursor is changed.
62 * Note: behavior has been changed from original. To have "amount"
63 * parsed as a fractional scroll amount, "units" *must* be declared
64 * as "w". Otherwise, no units implies that "amount" is an absolute
65 * value.
66 *
67 *
68 * ----------------------------------------------------------------------------
69 */
70
71 void
windScrollCmd(w,cmd)72 windScrollCmd(w, cmd)
73 MagWindow *w;
74 TxCommand *cmd;
75 {
76 Rect r;
77 int xsize, ysize;
78 Point p;
79 int pos, locargc = cmd->tx_argc;
80 float amount;
81 bool doFractional = FALSE;
82
83 if ( (cmd->tx_argc < 2) || (cmd->tx_argc > 4) )
84 {
85 TxError("Usage: %s direction [amount [units]]\n", cmd->tx_argv[0]);
86 return;
87 }
88
89 if (w == NULL)
90 {
91 TxError("Point to a window first.\n");
92 return;
93 }
94
95 if ((w->w_flags & WIND_SCROLLABLE) == 0) {
96 TxError("Sorry, can't scroll this window.\n");
97 return;
98 };
99
100 pos = GeoNameToPos(cmd->tx_argv[1], FALSE, TRUE);
101 if (pos < 0 || pos == GEO_CENTER)
102 return;
103
104 if (cmd->tx_argc == 2) /* default = half-screen pan */
105 {
106 r = w->w_screenArea;
107 amount = 0.5;
108 doFractional = TRUE;
109 }
110 else if (cmd->tx_argc == 4)
111 {
112 char unitc = cmd->tx_argv[3][0];
113
114 if (unitc == 'w')
115 r = w->w_screenArea;
116 else if (unitc == 'l')
117 r = *(w->w_bbox);
118 else
119 {
120 TxError("Usage: %s direction [amount [units]]\n", cmd->tx_argv[0]);
121 TxError(" 'units' must be one of 'w' (window) or 'l' (layout);\n");
122 return;
123 }
124
125 if (sscanf(cmd->tx_argv[2], "%f", &amount) != 1)
126 {
127 TxError("Usage: %s direction [amount [units]]\n", cmd->tx_argv[0]);
128 TxError(" 'amount' is a fractional value.\n");
129 return;
130 }
131 doFractional = TRUE;
132 }
133
134 if (doFractional)
135 {
136 xsize = (r.r_xtop - r.r_xbot) * amount;
137 ysize = (r.r_ytop - r.r_ybot) * amount;
138 }
139 else
140 {
141 /* Alternate syntax: parse for integer coordinate amount to scroll */
142 xsize = cmdParseCoord(w, cmd->tx_argv[2], TRUE, TRUE);
143 ysize = cmdParseCoord(w, cmd->tx_argv[2], TRUE, FALSE);
144 }
145
146 p.p_x = 0;
147 p.p_y = 0;
148
149 switch (pos)
150 {
151 case GEO_NORTH:
152 p.p_y = -ysize;
153 break;
154 case GEO_SOUTH:
155 p.p_y = ysize;
156 break;
157 case GEO_EAST:
158 p.p_x = -xsize;
159 break;
160 case GEO_WEST:
161 p.p_x = xsize;
162 break;
163 case GEO_NORTHEAST:
164 p.p_x = -xsize;
165 p.p_y = -ysize;
166 break;
167 case GEO_NORTHWEST:
168 p.p_x = xsize;
169 p.p_y = -ysize;
170 break;
171 case GEO_SOUTHEAST:
172 p.p_x = -xsize;
173 p.p_y = ysize;
174 break;
175 case GEO_SOUTHWEST:
176 p.p_x = xsize;
177 p.p_y = ysize;
178 break;
179 }
180
181 if (doFractional)
182 WindScroll(w, (Point *) NULL, &p);
183 else
184 {
185 /* Direction is reversed w/respect to above call to WindScroll() */
186 p.p_x = -p.p_x;
187 p.p_y = -p.p_y;
188 WindScroll(w, &p, (Point *) NULL);
189 }
190
191 return;
192 }
193
194 /*
195 * ----------------------------------------------------------------------------
196 * windSetpointCmd --
197 *
198 * Use the x, y specified as the location of the point tool for the
199 * next command.
200 *
201 * Results:
202 * None. Under the Tcl interpreter, returns the screen and layout
203 * coordinates as a list of four integers: sx sy lx ly.
204 *
205 * Side effects:
206 * global variables.
207 * ----------------------------------------------------------------------------
208 */
209
210 void
windSetpointCmd(w,cmd)211 windSetpointCmd(w, cmd)
212 MagWindow *w;
213 TxCommand *cmd;
214 {
215 int wid;
216 Point rootPoint;
217 #ifdef MAGIC_WRAPPER
218 char *ptstr;
219 #endif
220
221 if ((cmd->tx_argc != 4) && (cmd->tx_argc != 3) && (cmd->tx_argc != 1))
222 goto usage;
223 if ((cmd->tx_argc != 1) && !
224 (StrIsInt(cmd->tx_argv[1]) && StrIsInt(cmd->tx_argv[2])) )
225 goto usage;
226
227 if (cmd->tx_argc == 4) {
228 if (StrIsInt(cmd->tx_argv[3]))
229 wid = atoi(cmd->tx_argv[3]);
230 else if (GrWindowIdPtr)
231 wid = (*GrWindowIdPtr)(cmd->tx_argv[3]);
232 else
233 wid = WIND_UNKNOWN_WINDOW;
234 }
235 else if (w != NULL)
236 wid = w->w_wid;
237 else {
238 windCheckOnlyWindow(&w, DBWclientID);
239 if (w != NULL)
240 wid = w->w_wid;
241 else
242 wid = WIND_UNKNOWN_WINDOW;
243 }
244
245 /* Ensure a valid window, if possible */
246 if (w == NULL) w = WindSearchWid(wid);
247
248 if (cmd->tx_argc == 1)
249 {
250 if (w != (MagWindow *) NULL)
251 {
252 WindPointToSurface(w, &cmd->tx_p, &rootPoint, (Rect *) NULL);
253
254 #ifdef MAGIC_WRAPPER
255 ptstr = (char *)Tcl_Alloc(50);
256 sprintf(ptstr, "%d %d %d %d", cmd->tx_p.p_x, cmd->tx_p.p_y,
257 rootPoint.p_x, rootPoint.p_y);
258 Tcl_SetResult(magicinterp, ptstr, TCL_DYNAMIC);
259 #else
260 TxPrintf("Point is at screen coordinates (%d, %d) in window %d.\n",
261 cmd->tx_p.p_x, cmd->tx_p.p_y, w->w_wid);
262 TxPrintf("Point is at layout coordinates (%d, %d)\n",
263 rootPoint.p_x, rootPoint.p_y);
264 #endif
265 } else {
266 TxPrintf("Point is at screen coordinates (%d, %d).\n",
267 cmd->tx_p.p_x, cmd->tx_p.p_y);
268 }
269 }
270 else {
271 int yval;
272
273 yval = atoi(cmd->tx_argv[2]);
274
275 /* Reinterpret coordinates according to the graphics package */
276 switch (WindPackageType)
277 {
278 case WIND_X_WINDOWS:
279 /* Windows have origin at lower-left corner */
280 yval = w->w_allArea.r_ytop - yval;
281 break;
282 }
283 TxSetPoint(atoi(cmd->tx_argv[1]), yval, wid);
284 }
285 return;
286
287 usage:
288 TxError("Usage: %s [x y [window ID|name]]\n", cmd->tx_argv[0]);
289 }
290
291 int
windSetPrintProc(name,val)292 windSetPrintProc(name, val)
293 char *name;
294 char *val;
295 {
296 TxPrintf("%s = \"%s\"\n", name, val);
297 return 0;
298 }
299
300
301 /*
302 * ----------------------------------------------------------------------------
303 * windSleepCmd --
304 *
305 * Take a nap.
306 *
307 * Results:
308 * None.
309 *
310 * Side effects:
311 * None.
312 * ----------------------------------------------------------------------------
313 */
314
315 void
windSleepCmd(w,cmd)316 windSleepCmd(w, cmd)
317 MagWindow *w;
318 TxCommand *cmd;
319 {
320 int time;
321
322 if (cmd->tx_argc != 2)
323 {
324 TxError("Usage: %s seconds\n", cmd->tx_argv[0]);
325 return;
326 }
327
328 time = atoi(cmd->tx_argv[1]);
329 for ( ; time > 1; time--)
330 {
331 sleep(1);
332 if (SigInterruptPending) return;
333 }
334 }
335
336 #ifndef MAGIC_WRAPPER
337
338
339 /*
340 * ----------------------------------------------------------------------------
341 *
342 * windSourceCmd --
343 *
344 * Implement the "source" command.
345 * Process a file as a list of commands.
346 *
347 * Usage:
348 * source filename
349 *
350 * Results:
351 * None.
352 *
353 * Side effects:
354 * Whatever the commands request.
355 *
356 * ----------------------------------------------------------------------------
357 */
358
359 void
windSourceCmd(w,cmd)360 windSourceCmd(w, cmd)
361 MagWindow *w;
362 TxCommand *cmd;
363 {
364 FILE *f;
365
366 if (cmd->tx_argc != 2)
367 {
368 TxError("Usage: %s filename\n", cmd->tx_argv[0]);
369 return;
370 }
371
372 f = PaOpen(cmd->tx_argv[1], "r", (char *) NULL, ".",
373 SysLibPath, (char **) NULL);
374 if (f == NULL)
375 TxError("Couldn't read from %s.\n", cmd->tx_argv[1]);
376 else {
377 TxDispatch(f);
378 (void) fclose(f);
379 };
380 }
381
382 #endif
383
384 /*
385 * ----------------------------------------------------------------------------
386 * windSpecialOpenCmd --
387 *
388 * Open a new window at the cursor position. Give it a default size,
389 * and take the client's name from the command line. Pass the rest of
390 * the command arguments off to the client.
391 *
392 * Results:
393 * None.
394 *
395 * Side effects:
396 * None.
397 * ----------------------------------------------------------------------------
398 */
399
400 void
windSpecialOpenCmd(w,cmd)401 windSpecialOpenCmd(w, cmd)
402 MagWindow *w;
403 TxCommand *cmd;
404 {
405 WindClient wc;
406 Rect area;
407 bool haveCoords;
408 char *client;
409
410 haveCoords = FALSE;
411
412 if (cmd->tx_argc < 2) goto usage;
413 haveCoords = StrIsInt(cmd->tx_argv[1]);
414 if (haveCoords && (
415 (cmd->tx_argc < 6) ||
416 !StrIsInt(cmd->tx_argv[2]) ||
417 !StrIsInt(cmd->tx_argv[3]) ||
418 !StrIsInt(cmd->tx_argv[4])
419 )) goto usage;
420 if (haveCoords)
421 client = cmd->tx_argv[5];
422 else
423 client = cmd->tx_argv[1];
424
425 wc = WindGetClient(client, FALSE);
426 /* clients whose names begin with '*' are hidden */
427 if ((wc == (WindClient) NULL) || (client[0] == '*')) goto usage;
428
429 if (haveCoords) {
430 windCheckOnlyWindow(&w, wc);
431
432 area.r_xbot = atoi(cmd->tx_argv[1]);
433 area.r_ybot = atoi(cmd->tx_argv[2]);
434 area.r_xtop = MAX(atoi(cmd->tx_argv[3]), area.r_xbot + WIND_MIN_WIDTH);
435 area.r_ytop = MAX(atoi(cmd->tx_argv[4]), area.r_ybot + WIND_MIN_HEIGHT);
436 /* Assume that the client will print an error message if it fails */
437 (void) WindCreate(wc, &area, FALSE, cmd->tx_argc - 6, cmd->tx_argv + 6);
438 }
439 else {
440 area.r_xbot = cmd->tx_p.p_x - CREATE_WIDTH/2;
441 area.r_xtop = cmd->tx_p.p_x + CREATE_WIDTH/2;
442 area.r_ybot = cmd->tx_p.p_y - CREATE_HEIGHT/2;
443 area.r_ytop = cmd->tx_p.p_y + CREATE_HEIGHT/2;
444 /* Assume that the client will print an error message if it fails */
445 (void) WindCreate(wc, &area, TRUE, cmd->tx_argc - 2, cmd->tx_argv + 2);
446 }
447
448 return;
449
450 usage:
451 TxPrintf("Usage: specialopen [leftx bottomy rightx topy] type [args]\n");
452 TxPrintf("Valid window types are:\n");
453 WindPrintClientList(FALSE);
454 return;
455 }
456
457 /*
458 * ----------------------------------------------------------------------------
459 * windNamesCmd --
460 *
461 * Register or retrieve the name associated with the layout window
462 *
463 * Results:
464 * Returns the name as a Tcl string result. If "all" is selected,
465 * or if w is NULL and cannot be determined, returns a list of all
466 * window names. The first argument may also be a window client
467 * type, in which case only windows of that type are returned.
468 *
469 * Note:
470 * This routine can easily be made "generic", not Tcl-specific.
471 * However, of the graphics interfaces available, only Tcl/Tk keeps
472 * track of windows by name.
473 *
474 * ----------------------------------------------------------------------------
475 */
476
477 void
windNamesCmd(w,cmd)478 windNamesCmd(w, cmd)
479 MagWindow *w;
480 TxCommand *cmd;
481 {
482 bool doforall = FALSE;
483 WindClient wc = (WindClient)NULL;
484 MagWindow *sw;
485
486 if (cmd->tx_argc > 2)
487 {
488 TxError("Usage: windownames [all | client_type]\n");
489 return;
490 }
491 if (cmd->tx_argc == 2)
492 {
493 if (!strncmp(cmd->tx_argv[1], "all", 3))
494 doforall = TRUE;
495 #ifndef THREE_D
496 else if (!strncmp(cmd->tx_argv[1], "wind3d", 6))
497 {
498 return; // do nothing
499 }
500 #endif /* THREE_D */
501 else
502 {
503 wc = WindGetClient(cmd->tx_argv[1], FALSE);
504 if (wc == (WindClient) NULL)
505 {
506 TxError("Usage: windownames [all | client_type]\n");
507 TxPrintf("Valid window types are:\n");
508 WindPrintClientList(FALSE);
509 return;
510 }
511 doforall = TRUE;
512 }
513 }
514
515 if (cmd->tx_argc == 1)
516 {
517 wc = DBWclientID;
518 windCheckOnlyWindow(&w, wc);
519 if (w == (MagWindow *)NULL)
520 doforall = TRUE;
521 }
522
523 #ifdef MAGIC_WRAPPER
524 if (doforall == TRUE)
525 {
526 Tcl_Obj *tlist;
527
528 tlist = Tcl_NewListObj(0, NULL);
529 for (sw = windTopWindow; sw != NULL; sw = sw->w_nextWindow)
530 if ((wc == NULL) || (sw->w_client == wc))
531 {
532 if (GrWindowNamePtr)
533 Tcl_ListObjAppendElement(magicinterp, tlist,
534 Tcl_NewStringObj((*GrWindowNamePtr)(sw), -1));
535 else
536 Tcl_ListObjAppendElement(magicinterp, tlist,
537 Tcl_NewIntObj(sw->w_wid));
538 }
539 Tcl_SetObjResult(magicinterp, tlist);
540 }
541 else
542 {
543 if (GrWindowNamePtr)
544 Tcl_SetResult(magicinterp, (*GrWindowNamePtr)(w), NULL);
545 else
546 Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(w->w_wid));
547 }
548 #else
549 if (doforall == TRUE)
550 {
551 if (GrWindowNamePtr)
552 TxPrintf("Window ID Window Name\n");
553 else
554 TxPrintf("Window ID\n");
555 for (sw = windTopWindow; sw != NULL; sw = sw->w_nextWindow)
556 if ((wc == (WindClient)NULL) || (sw->w_client == wc))
557 {
558 if (GrWindowNamePtr)
559 TxPrintf("%d %s\n", sw->w_wid, (*GrWindowNamePtr)(sw));
560 else
561 TxPrintf("%d\n", sw->w_wid);
562 }
563 }
564 else
565 {
566 if (GrWindowNamePtr)
567 TxPrintf("Window ID = %d, Name = %s\n", w->w_wid,
568 (*GrWindowNamePtr)(w));
569 else
570 TxPrintf("Window ID = %d\n", w->w_wid);
571 }
572 #endif /* !MAGIC_WRAPPER */
573 }
574
575
576 /*
577 * ----------------------------------------------------------------------------
578 * windUnderCmd --
579 *
580 * Move a window underneath the other windows.
581 *
582 * Results:
583 * None.
584 *
585 * Side effects:
586 * Screen updates.
587 * ----------------------------------------------------------------------------
588 */
589
590 void
windUnderCmd(w,cmd)591 windUnderCmd(w, cmd)
592 MagWindow *w;
593 TxCommand *cmd;
594 {
595 if (cmd->tx_argc != 1)
596 {
597 TxError("Usage: %s\n", cmd->tx_argv[0]);
598 }
599 if (w == NULL)
600 {
601 TxError("Point to a window first.\n");
602 return;
603 }
604 WindUnder(w);
605 }
606
607
608 /*
609 * ----------------------------------------------------------------------------
610 *
611 * windUndoCmd
612 *
613 * Implement the "undo" command.
614 *
615 * Usage:
616 * undo [count]
617 *
618 * If a count is supplied, the last count events are undone. The default
619 * count if none is given is 1.
620 *
621 * Results:
622 * None.
623 *
624 * Side effects:
625 * Calls the undo module.
626 *
627 * ----------------------------------------------------------------------------
628 */
629
630 void
windUndoCmd(w,cmd)631 windUndoCmd(w, cmd)
632 MagWindow *w;
633 TxCommand *cmd;
634 {
635 int count;
636
637 if (cmd->tx_argc > 3)
638 {
639 TxError("Usage: undo [count]\n");
640 TxError(" undo print [count]\n");
641 TxError(" undo enable|disable\n");
642 return;
643 }
644 else if (cmd->tx_argc == 3)
645 {
646 if (strncmp(cmd->tx_argv[1], "print", 5))
647 {
648 TxError("Usage: undo print count\n");
649 return;
650 }
651 else if (!StrIsInt(cmd->tx_argv[2]))
652 {
653 TxError("Usage: undo print count\n");
654 return;
655 }
656 else
657 {
658 /* Implement undo stack trace */
659 UndoStackTrace((-1) - atoi(cmd->tx_argv[2]));
660 return;
661 }
662 }
663 else if (cmd->tx_argc == 2)
664 {
665 if (!StrIsInt(cmd->tx_argv[1]))
666 {
667 if (!strcmp(cmd->tx_argv[1], "enable"))
668 UndoEnable();
669 else if (!strcmp(cmd->tx_argv[1], "disable"))
670 UndoDisable();
671 else
672 TxError("Option must be a count (integer)\n");
673 return;
674 }
675 count = atoi(cmd->tx_argv[1]);
676 if (count < 0)
677 {
678 TxError("Count must be a positive integer\n");
679 return;
680 }
681 }
682 else
683 count = 1;
684
685 if (count == 0)
686 {
687 UndoEnable();
688 }
689 else
690 {
691 if (UndoBackward(count) == 0)
692 TxPrintf("Nothing more to undo\n");
693 }
694 }
695
696
697 /*
698 * ----------------------------------------------------------------------------
699 * windUpdateCmd --
700 *
701 * Force an update of the graphics screen. This is usually only called
702 * from command scripts.
703 *
704 * Results:
705 * None.
706 *
707 * Side effects:
708 * Display updates.
709 * ----------------------------------------------------------------------------
710 */
711
712 void
windUpdateCmd(w,cmd)713 windUpdateCmd(w, cmd)
714 MagWindow *w;
715 TxCommand *cmd;
716 {
717 if (cmd->tx_argc == 1)
718 WindUpdate();
719 #ifdef MAGIC_WRAPPER
720 else if (cmd->tx_argc > 2)
721 goto badusage;
722 else if (!strcmp(cmd->tx_argv[1], "suspend"))
723 GrDisplayStatus = DISPLAY_SUSPEND;
724 else if (!strcmp(cmd->tx_argv[1], "resume"))
725 GrDisplayStatus = DISPLAY_IDLE;
726 else
727 goto badusage;
728 #else
729 else if (cmd->tx_argc >= 2)
730 goto badusage;
731 #endif
732 return;
733
734 badusage:
735 TxError("Usage: %s [suspend | resume]\n", cmd->tx_argv[0]);
736 return;
737 }
738
739 /*
740 * ----------------------------------------------------------------------------
741 *
742 * windVersionCmd --
743 *
744 * Print version information.
745 *
746 * Usage:
747 * version
748 *
749 * Results:
750 * None.
751 *
752 * Side effects:
753 * Prints on stdout.
754 *
755 * ----------------------------------------------------------------------------
756 */
757
758 void
windVersionCmd(w,cmd)759 windVersionCmd(w, cmd)
760 MagWindow *w;
761 TxCommand *cmd;
762 {
763 if (cmd->tx_argc != 1) {
764 TxError("Usage: %s\n", cmd->tx_argv[0]);
765 return;
766 }
767
768 TxPrintf("Version %s revision %s. Compiled on %s.\n",
769 MagicVersion, MagicRevision, MagicCompileTime);
770 }
771
772 /*
773 * ----------------------------------------------------------------------------
774 *
775 * windViewCmd --
776 *
777 * Implement the "View" command.
778 * Change the view in the selected window so everything is visible.
779 *
780 * Usage:
781 * view
782 *
783 * Results:
784 * None.
785 *
786 * Side effects:
787 * The window underneath the cursor is changed.
788 * In Tcl version, if supplied with the argument "get", the
789 * interpreter return value is set to the current view position.
790 *
791 * ----------------------------------------------------------------------------
792 */
793
794 void
windViewCmd(w,cmd)795 windViewCmd(w, cmd)
796 MagWindow *w;
797 TxCommand *cmd;
798 {
799 if (w == NULL)
800 return;
801
802 if (cmd->tx_argc == 1)
803 {
804 if ((w->w_flags & WIND_SCROLLABLE) == 0) {
805 TxError("Sorry, can't zoom out this window.\n");
806 return;
807 }
808 WindView(w);
809 }
810 else if (cmd->tx_argc == 2)
811 {
812 #ifdef MAGIC_WRAPPER
813 Tcl_Obj *listxy, *fval;
814
815 listxy = Tcl_NewListObj(0, NULL);
816 #endif
817
818 if (!strncmp(cmd->tx_argv[1], "get", 3))
819 {
820 #ifndef MAGIC_WRAPPER
821 TxPrintf("(%d, %d) to (%d, %d)\n",
822 w->w_surfaceArea.r_xbot, w->w_surfaceArea.r_ybot,
823 w->w_surfaceArea.r_xtop, w->w_surfaceArea.r_ytop);
824 #else
825 Tcl_ListObjAppendElement(magicinterp, listxy,
826 Tcl_NewIntObj((int)w->w_surfaceArea.r_xbot));
827 Tcl_ListObjAppendElement(magicinterp, listxy,
828 Tcl_NewIntObj((int)w->w_surfaceArea.r_ybot));
829 Tcl_ListObjAppendElement(magicinterp, listxy,
830 Tcl_NewIntObj((int)w->w_surfaceArea.r_xtop));
831 Tcl_ListObjAppendElement(magicinterp, listxy,
832 Tcl_NewIntObj((int)w->w_surfaceArea.r_ytop));
833 Tcl_SetObjResult(magicinterp, listxy);
834 #endif
835 }
836 else if (!strncmp(cmd->tx_argv[1], "bbox", 4))
837 {
838 #ifndef MAGIC_WRAPPER
839 TxPrintf("(%d, %d) to (%d, %d)\n",
840 w->w_bbox->r_xbot, w->w_bbox->r_ybot,
841 w->w_bbox->r_xtop, w->w_bbox->r_ytop);
842 #else
843 Tcl_ListObjAppendElement(magicinterp, listxy,
844 Tcl_NewIntObj((int)w->w_bbox->r_xbot));
845 Tcl_ListObjAppendElement(magicinterp, listxy,
846 Tcl_NewIntObj((int)w->w_bbox->r_ybot));
847 Tcl_ListObjAppendElement(magicinterp, listxy,
848 Tcl_NewIntObj((int)w->w_bbox->r_xtop));
849 Tcl_ListObjAppendElement(magicinterp, listxy,
850 Tcl_NewIntObj((int)w->w_bbox->r_ytop));
851 Tcl_SetObjResult(magicinterp, listxy);
852 #endif
853 }
854 else
855 {
856 char *sptr, *pptr;
857 Rect r;
858
859 // Parse out coordinates where all coordinates have been
860 // put into a single string argument, as happens when the
861 // coordinates are a Tcl list, e.g., from "[box values]"
862
863 sptr = cmd->tx_argv[1];
864 if ((pptr = strchr(sptr, ' ')) == NULL) return;
865 *pptr++ = '\0';
866 r.r_xbot = cmdParseCoord(w, sptr, FALSE, TRUE);
867
868 sptr = pptr;
869 if ((pptr = strchr(sptr, ' ')) == NULL) return;
870 *pptr++ = '\0';
871 r.r_ybot = cmdParseCoord(w, sptr, FALSE, TRUE);
872
873 sptr = pptr;
874 if ((pptr = strchr(sptr, ' ')) == NULL) return;
875 *pptr++ = '\0';
876 r.r_xtop = cmdParseCoord(w, sptr, FALSE, TRUE);
877 r.r_ytop = cmdParseCoord(w, pptr, FALSE, TRUE);
878
879 /* Redisplay */
880 WindMove(w, &r);
881 }
882 }
883 else if (cmd->tx_argc == 5)
884 {
885 Rect r;
886 r.r_xbot = cmdParseCoord(w, cmd->tx_argv[1], FALSE, TRUE);
887 r.r_ybot = cmdParseCoord(w, cmd->tx_argv[2], FALSE, FALSE);
888 r.r_xtop = cmdParseCoord(w, cmd->tx_argv[3], FALSE, TRUE);
889 r.r_ytop = cmdParseCoord(w, cmd->tx_argv[4], FALSE, FALSE);
890
891 /* Redisplay */
892 WindMove(w, &r);
893 }
894 else
895 {
896 TxError("Usage: view [get|bbox|llx lly urx ury]\n");
897 }
898 }
899
900
901 /*
902 * ----------------------------------------------------------------------------
903 *
904 * windXviewCmd --
905 *
906 * Implement the "Xview" command.
907 * Change the view in the selected window so everything is visible, but
908 * not expanded.
909 *
910 * Usage:
911 * xview
912 *
913 * Results:
914 * None.
915 *
916 * Side effects:
917 * The window underneath the cursor is changed. The root cell of the
918 * window is unexpanded.
919 *
920 * ----------------------------------------------------------------------------
921 */
922
923 void
windXviewCmd(w,cmd)924 windXviewCmd(w, cmd)
925 MagWindow *w;
926 TxCommand *cmd;
927 {
928 CellUse *celluse;
929 int ViewUnexpandFunc();
930
931 if (w == NULL)
932 return;
933
934 if ((w->w_flags & WIND_SCROLLABLE) == 0) {
935 TxError("Sorry, can't zoom out this window.\n");
936 return;
937 };
938
939 celluse = (CellUse *) (w->w_surfaceID);
940 DBExpandAll(celluse, &(celluse->cu_bbox),
941 ((DBWclientRec *)w->w_clientData)->dbw_bitmask, FALSE,
942 ViewUnexpandFunc,
943 (ClientData)(pointertype) (((DBWclientRec *)w->w_clientData)->dbw_bitmask));
944
945 WindView(w);
946 }
947
948 /* This function is called for each cell whose expansion status changed.
949 * It forces the cells area to be redisplayed, then returns 0 to keep
950 * looking for more cells to unexpand.
951 */
952
953 int
ViewUnexpandFunc(use,windowMask)954 ViewUnexpandFunc(use, windowMask)
955 CellUse *use; /* Use that was just unexpanded. */
956 int windowMask; /* Window where it was unexpanded. */
957 {
958 if (use->cu_parent == NULL) return 0;
959 DBWAreaChanged(use->cu_parent, &use->cu_bbox, windowMask,
960 (TileTypeBitMask *) NULL);
961 return 0;
962 }
963
964
965 /*
966 * ----------------------------------------------------------------------------
967 *
968 * windScrollBarsCmd --
969 *
970 * Change the flag which says whether new windows will have scroll bars.
971 *
972 * Usage:
973 * windscrollbars [on|off]
974 *
975 * Results:
976 * None.
977 *
978 * Side effects:
979 * A flag is changed.
980 *
981 * ----------------------------------------------------------------------------
982 */
983
984 void
windScrollBarsCmd(w,cmd)985 windScrollBarsCmd(w, cmd)
986 MagWindow *w;
987 TxCommand *cmd;
988 {
989 int place;
990 static char *onoff[] = {"on", "off", 0};
991 static bool truth[] = {TRUE, FALSE};
992
993 if (cmd->tx_argc != 2) goto usage;
994
995 place = Lookup(cmd->tx_argv[1], onoff);
996 if (place < 0) goto usage;
997
998 if (truth[place])
999 {
1000 WindDefaultFlags |= WIND_SCROLLBARS;
1001 TxPrintf("New windows will have scroll bars.\n");
1002 }
1003 else
1004 {
1005 WindDefaultFlags &= ~WIND_SCROLLBARS;
1006 TxPrintf("New windows will not have scroll bars.\n");
1007 }
1008 return;
1009
1010 usage:
1011 TxError("Usage: %s [on|off]\n", cmd->tx_argv[0]);
1012 return;
1013 }
1014
1015 #ifndef MAGIC_WRAPPER
1016
1017
1018 /*
1019 * ----------------------------------------------------------------------------
1020 *
1021 * windSendCmd --
1022 *
1023 * Send a command to a certain window type. If possible we will pass a
1024 * arbitrarily chosen window of that type down to the client.
1025 *
1026 * Usage:
1027 * send type command
1028 *
1029 * Results:
1030 * None.
1031 *
1032 * Side effects:
1033 * Whatever the client does
1034 *
1035 * ----------------------------------------------------------------------------
1036 */
1037
1038 void
windSendCmd(w,cmd)1039 windSendCmd(w, cmd)
1040 MagWindow *w;
1041 TxCommand *cmd;
1042 {
1043 MagWindow *toWindow;
1044 WindClient client;
1045 TxCommand newcmd;
1046 extern int windSendCmdFunc();
1047
1048 if (cmd->tx_argc < 3) goto usage;
1049 if (cmd->tx_argv[1][0] == '*') goto usage; /* hidden window client */
1050
1051 client = WindGetClient(cmd->tx_argv[1], FALSE);
1052 if (client == (WindClient) NULL) goto usage;
1053 toWindow = (MagWindow *) NULL;
1054 (void) WindSearch(client, (ClientData) NULL, (Rect *) NULL,
1055 windSendCmdFunc, (ClientData) &toWindow);
1056 {
1057 int i;
1058 newcmd = *cmd;
1059 newcmd.tx_argc -= 2;
1060 for (i = 0; i < newcmd.tx_argc; i++) {
1061 newcmd.tx_argv[i] = newcmd.tx_argv[i + 2];
1062 };
1063 }
1064 newcmd.tx_wid = WIND_UNKNOWN_WINDOW;
1065 if (toWindow != NULL) newcmd.tx_wid = toWindow->w_wid;
1066 (void) WindSendCommand(toWindow, &newcmd, FALSE);
1067 return;
1068
1069 usage:
1070 TxError("Usage: send type command\n");
1071 TxPrintf("Valid window types are:\n");
1072 WindPrintClientList(FALSE);
1073 return;
1074 }
1075
1076 int
windSendCmdFunc(w,cd)1077 windSendCmdFunc(w, cd)
1078 MagWindow *w;
1079 ClientData cd;
1080 {
1081 *((MagWindow **) cd) = w;
1082 return 1;
1083 }
1084
1085 #endif
1086
1087 /* Structure used by "position" command to pass to WindSearch */
1088 /* as client data. */
1089
1090 typedef struct _cdwpos {
1091 FILE *file;
1092 bool doFrame;
1093 } cdwpos;
1094
1095
1096 /*
1097 * ----------------------------------------------------------------------------
1098 *
1099 * windPositionsCmd --
1100 *
1101 * Print out the positions of the windows.
1102 *
1103 * Usage:
1104 * windowpositions [file]
1105 *
1106 * Results:
1107 * None.
1108 *
1109 * Side effects:
1110 * A file is written.
1111 *
1112 * ----------------------------------------------------------------------------
1113 */
1114
1115 void
windPositionsCmd(w,cmd)1116 windPositionsCmd(w, cmd)
1117 MagWindow *w;
1118 TxCommand *cmd;
1119 {
1120 extern int windPositionsFunc();
1121 char *filename = NULL;
1122 cdwpos windpos;
1123
1124 windpos.doFrame = FALSE;
1125 windpos.file = stdout;
1126
1127 if (cmd->tx_argc > 3) goto usage;
1128 if (cmd->tx_argc > 1)
1129 {
1130 if (!strncmp(cmd->tx_argv[1], "frame", 5))
1131 {
1132 windpos.doFrame = TRUE;
1133 if (cmd->tx_argc == 3)
1134 filename = cmd->tx_argv[2];
1135 }
1136 else if (cmd->tx_argc == 2)
1137 filename = cmd->tx_argv[1];
1138 else
1139 goto usage;
1140 }
1141
1142 if (filename) {
1143 windpos.file = fopen(filename, "w");
1144 if (windpos.file == (FILE *) NULL)
1145 {
1146 TxError("Could not open file %s for writing.\n", filename);
1147 return;
1148 };
1149 }
1150 (void) WindSearch((WindClient) NULL, (ClientData) NULL, (Rect *) NULL,
1151 windPositionsFunc, (ClientData) &windpos);
1152 if (filename) (void) fclose(windpos.file);
1153 return;
1154
1155 usage:
1156 TxError("Usage: windowpositions [file]\n");
1157 return;
1158 }
1159
1160 int
windPositionsFunc(w,cdata)1161 windPositionsFunc(w, cdata)
1162 MagWindow *w;
1163 ClientData cdata;
1164 {
1165 cdwpos *windpos = (cdwpos *)cdata;
1166 Rect r;
1167
1168 if (windpos->doFrame)
1169 r = w->w_frameArea;
1170 else
1171 r = w->w_screenArea;
1172
1173 if (windpos->file == stdout)
1174 #ifdef MAGIC_WRAPPER
1175 {
1176 Tcl_Obj *lobj;
1177
1178 lobj = Tcl_NewListObj(0, NULL);
1179
1180 Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewIntObj((int)r.r_xbot));
1181 Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewIntObj((int)r.r_ybot));
1182 Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewIntObj((int)r.r_xtop));
1183 Tcl_ListObjAppendElement(magicinterp, lobj, Tcl_NewIntObj((int)r.r_ytop));
1184 Tcl_ListObjAppendElement(magicinterp, lobj,
1185 Tcl_NewStringObj(((clientRec *)w->w_client)->w_clientName,
1186 strlen(((clientRec *)w->w_client)->w_clientName)));
1187 Tcl_SetObjResult(magicinterp, lobj);
1188 }
1189 #else
1190 TxPrintf("specialopen %d %d %d %d %s\n",
1191 r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop,
1192 ((clientRec *) w->w_client)->w_clientName);
1193 #endif
1194 else
1195 fprintf((FILE *)cdata, "specialopen %d %d %d %d %s\n",
1196 r.r_xbot, r.r_ybot, r.r_xtop, r.r_ytop,
1197 ((clientRec *) w->w_client)->w_clientName);
1198 return 0;
1199 }
1200
1201
1202 /*
1203 * ----------------------------------------------------------------------------
1204 *
1205 * windZoomCmd --
1206 *
1207 * Implement the "zoom" command.
1208 * Change the view in the selected window by the given scale factor.
1209 *
1210 * Usage:
1211 * zoom amount
1212 *
1213 * Results:
1214 * None.
1215 *
1216 * Side effects:
1217 * The window underneath the cursor is changed.
1218 *
1219 * ----------------------------------------------------------------------------
1220 */
1221
1222 void
windZoomCmd(w,cmd)1223 windZoomCmd(w, cmd)
1224 MagWindow *w;
1225 TxCommand *cmd;
1226 {
1227 float factor;
1228
1229 if (w == NULL)
1230 return;
1231
1232 if ((w->w_flags & WIND_SCROLLABLE) == 0) {
1233 TxError("Sorry, can't zoom this window.\n");
1234 return;
1235 };
1236
1237 if (cmd->tx_argc != 2)
1238 {
1239 TxError("Usage: %s factor\n", cmd->tx_argv[0]);
1240 return;
1241 }
1242
1243 factor = MagAtof(cmd->tx_argv[1]);
1244 if ((factor <= 0) || (factor >= 20))
1245 {
1246 TxError("zoom factor must be between 0 and 20.\n");
1247 return;
1248 }
1249
1250 WindZoom(w, factor);
1251 }
1252