|
|
1.1 root 1: /* w_editor.c
2: *
3: * Micropolis, Unix Version. This game was released for the Unix platform
4: * in or about 1990 and has been modified for inclusion in the One Laptop
5: * Per Child program. Copyright (C) 1989 - 2007 Electronic Arts Inc. If
6: * you need assistance with this program, you may contact:
7: * http://wiki.laptop.org/go/Micropolis or email [email protected].
8: *
9: * This program is free software: you can redistribute it and/or modify
10: * it under the terms of the GNU General Public License as published by
11: * the Free Software Foundation, either version 3 of the License, or (at
12: * your option) any later version.
13: *
14: * This program is distributed in the hope that it will be useful, but
15: * WITHOUT ANY WARRANTY; without even the implied warranty of
16: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17: * General Public License for more details. You should have received a
18: * copy of the GNU General Public License along with this program. If
19: * not, see <http://www.gnu.org/licenses/>.
20: *
21: * ADDITIONAL TERMS per GNU GPL Section 7
22: *
23: * No trademark or publicity rights are granted. This license does NOT
24: * give you any right, title or interest in the trademark SimCity or any
25: * other Electronic Arts trademark. You may not distribute any
26: * modification of this program using the trademark SimCity or claim any
27: * affliation or association with Electronic Arts Inc. or its employees.
28: *
29: * Any propagation or conveyance of this program must include this
30: * copyright notice and these terms.
31: *
32: * If you convey this program (or any modifications of it) and assume
33: * contractual liability for the program to recipients of it, you agree
34: * to indemnify Electronic Arts for any liability that those contractual
35: * assumptions impose on Electronic Arts.
36: *
37: * You may not misrepresent the origins of this program; modified
38: * versions of the program must be marked as such and not identified as
39: * the original program.
40: *
41: * This disclaimer supplements the one included in the General Public
42: * License. TO THE FULLEST EXTENT PERMISSIBLE UNDER APPLICABLE LAW, THIS
43: * PROGRAM IS PROVIDED TO YOU "AS IS," WITH ALL FAULTS, WITHOUT WARRANTY
44: * OF ANY KIND, AND YOUR USE IS AT YOUR SOLE RISK. THE ENTIRE RISK OF
45: * SATISFACTORY QUALITY AND PERFORMANCE RESIDES WITH YOU. ELECTRONIC ARTS
46: * DISCLAIMS ANY AND ALL EXPRESS, IMPLIED OR STATUTORY WARRANTIES,
47: * INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY,
48: * FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF THIRD PARTY
49: * RIGHTS, AND WARRANTIES (IF ANY) ARISING FROM A COURSE OF DEALING,
50: * USAGE, OR TRADE PRACTICE. ELECTRONIC ARTS DOES NOT WARRANT AGAINST
51: * INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM; THAT THE PROGRAM WILL
52: * MEET YOUR REQUIREMENTS; THAT OPERATION OF THE PROGRAM WILL BE
53: * UNINTERRUPTED OR ERROR-FREE, OR THAT THE PROGRAM WILL BE COMPATIBLE
54: * WITH THIRD PARTY SOFTWARE OR THAT ANY ERRORS IN THE PROGRAM WILL BE
55: * CORRECTED. NO ORAL OR WRITTEN ADVICE PROVIDED BY ELECTRONIC ARTS OR
56: * ANY AUTHORIZED REPRESENTATIVE SHALL CREATE A WARRANTY. SOME
57: * JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF OR LIMITATIONS ON IMPLIED
58: * WARRANTIES OR THE LIMITATIONS ON THE APPLICABLE STATUTORY RIGHTS OF A
59: * CONSUMER, SO SOME OR ALL OF THE ABOVE EXCLUSIONS AND LIMITATIONS MAY
60: * NOT APPLY TO YOU.
61: */
62: #include "sim.h"
63:
64:
65: Tcl_HashTable EditorCmds;
66: int DoOverlay = 2;
67: int BobHeight = 8;
68:
69:
70: extern Tk_ConfigSpec TileViewConfigSpecs[];
71:
72:
73: int EditorCmdconfigure(VIEW_ARGS)
74: {
75: int result = TCL_OK;
76:
77: if (argc == 2) {
78: result = Tk_ConfigureInfo(interp, view->tkwin, TileViewConfigSpecs,
79: (char *) view, (char *) NULL, 0);
80: } else if (argc == 3) {
81: result = Tk_ConfigureInfo(interp, view->tkwin, TileViewConfigSpecs,
82: (char *) view, argv[2], 0);
83: } else {
84: result = ConfigureTileView(interp, view, argc-2, argv+2,
85: TK_CONFIG_ARGV_ONLY);
86: }
87: return TCL_OK;
88: }
89:
90:
91: int EditorCmdposition(VIEW_ARGS)
92: {
93: if ((argc != 2) && (argc != 4)) {
94: return TCL_ERROR;
95: }
96: if (argc == 4) {
97: if ((Tcl_GetInt(interp, argv[2], &view->w_x) != TCL_OK) ||
98: (Tcl_GetInt(interp, argv[3], &view->w_y) != TCL_OK)) {
99: return TCL_ERROR;
100: }
101: }
102: sprintf(interp->result, "%d %d", view->w_x, view->w_y);
103: return TCL_OK;
104: }
105:
106:
107: int EditorCmdsize(VIEW_ARGS)
108: {
109: if ((argc != 2) && (argc != 4)) {
110: return TCL_ERROR;
111: }
112: if (argc == 4) {
113: int w, h;
114:
115: if (Tcl_GetInt(interp, argv[2], &w) != TCL_OK) {
116: return TCL_ERROR;
117: }
118: if (Tcl_GetInt(interp, argv[3], &h) != TCL_OK) {
119: return TCL_ERROR;
120: }
121: view->w_width = w;
122: view->w_height = h;
123: }
124: sprintf(interp->result, "%d %d", view->w_width, view->w_height);
125: return TCL_OK;
126: }
127:
128:
129: int EditorCmdAutoGoto(VIEW_ARGS)
130: {
131: if ((argc != 2) && (argc != 3)) {
132: return TCL_ERROR;
133: }
134: if (argc == 3) {
135: int val;
136:
137: if (Tcl_GetInt(interp, argv[2], &val) != TCL_OK) {
138: return TCL_ERROR;
139: }
140: view->auto_goto = val;
141: view->auto_going = view->auto_x_goal = view->auto_y_goal = 0;
142: }
143: sprintf(interp->result, "%d", view->auto_goto);
144: return TCL_OK;
145: }
146:
147:
148: int EditorCmdSound(VIEW_ARGS)
149: {
150: if ((argc != 2) && (argc != 3)) {
151: return TCL_ERROR;
152: }
153: if (argc == 3) {
154: int val;
155:
156: if (Tcl_GetInt(interp, argv[2], &val) != TCL_OK) {
157: return TCL_ERROR;
158: }
159: view->sound = val;
160: view->auto_going = view->auto_x_goal = view->auto_y_goal = 0;
161: }
162: sprintf(interp->result, "%d", view->sound);
163: return TCL_OK;
164: }
165:
166:
167: int EditorCmdSkip(VIEW_ARGS)
168: {
169: if ((argc != 2) && (argc != 3)) {
170: return TCL_ERROR;
171: }
172: if (argc == 3) {
173: int val;
174:
175: if (Tcl_GetInt(interp, argv[2], &val) != TCL_OK) {
176: return TCL_ERROR;
177: }
178: view->skip = view->skips = val; // XXX? why setting skips too?
179: }
180: sprintf(interp->result, "%d", view->skips);
181: return TCL_OK;
182: }
183:
184:
185: int EditorCmdUpdate(VIEW_ARGS)
186: {
187: if (argc != 2) {
188: return TCL_ERROR;
189: }
190: view->skip = 0;
191: return TCL_OK;
192: }
193:
194:
195: int EditorCmdPan(VIEW_ARGS)
196: {
197: if ((argc != 2) && (argc != 4)) {
198: return TCL_ERROR;
199: }
200: if (argc == 4) {
201: int x, y;
202:
203: if (Tcl_GetInt(interp, argv[2], &x) != TCL_OK) {
204: return TCL_ERROR;
205: }
206: if (Tcl_GetInt(interp, argv[3], &y) != TCL_OK) {
207: return TCL_ERROR;
208: }
209: DoPanTo(view, x, y); Kick();
210: }
211: sprintf(interp->result, "%d %d", view->pan_x, view->pan_y);
212: return TCL_OK;
213: }
214:
215:
216: int EditorCmdToolConstrain(VIEW_ARGS)
217: {
218: int x = -1, y = -1, tx, ty;
219:
220: if (argc != 4) {
221: return TCL_ERROR;
222: }
223:
224: if (Tcl_GetInt(interp, argv[2], &x) != TCL_OK) {
225: return TCL_ERROR;
226: }
227: if (Tcl_GetInt(interp, argv[3], &y) != TCL_OK) {
228: return TCL_ERROR;
229: }
230: view->tool_x_const = -1; view->tool_y_const = -1;
231: ViewToTileCoords(view, x, y, &tx, &ty);
232: view->tool_x_const = (x == -1) ? -1 : tx;
233: view->tool_y_const = (y == -1) ? -1 : ty;
234: return TCL_OK;
235: }
236:
237:
238: int EditorCmdToolState(VIEW_ARGS)
239: {
240: if ((argc != 2) && (argc != 3)) {
241: return TCL_ERROR;
242: }
243: if (argc == 3) {
244: int state;
245:
246: if (Tcl_GetInt(interp, argv[2], &state) != TCL_OK) {
247: return TCL_ERROR;
248: }
249: setWandState(view, state);
250: }
251: sprintf(interp->result, "%d", view->tool_state);
252: return TCL_OK;
253: }
254:
255:
256: int EditorCmdToolMode(VIEW_ARGS)
257: {
258: if ((argc != 2) && (argc != 3)) {
259: return TCL_ERROR;
260: }
261: if (argc == 3) {
262: int mode;
263:
264: if (Tcl_GetInt(interp, argv[2], &mode) != TCL_OK) {
265: return TCL_ERROR;
266: }
267: view->tool_mode = mode;
268: }
269: sprintf(interp->result, "%d", view->tool_mode);
270: return TCL_OK;
271: }
272:
273:
274: int EditorCmdDoTool(VIEW_ARGS)
275: {
276: int tool, x, y;
277:
278: if (argc != 5) {
279: return TCL_ERROR;
280: }
281:
282: if ((Tcl_GetInt(interp, argv[2], &tool) != TCL_OK) ||
283: (tool < 0) ||
284: (tool > lastState) ||
285: (Tcl_GetInt(interp, argv[3], &x) != TCL_OK) ||
286: (Tcl_GetInt(interp, argv[4], &y) != TCL_OK)) {
287: return TCL_ERROR;
288: }
289:
290: DoTool(view, tool, x, y); Kick();
291: return TCL_OK;
292: }
293:
294:
295: int EditorCmdToolDown(VIEW_ARGS)
296: {
297: int x, y;
298:
299: if (argc != 4) {
300: return TCL_ERROR;
301: }
302:
303: if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) ||
304: (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
305: return TCL_ERROR;
306: }
307:
308: ToolDown(view, x, y); Kick();
309: return TCL_OK;
310: }
311:
312:
313: int EditorCmdToolDrag(VIEW_ARGS)
314: {
315: int x, y;
316:
317: if (argc != 4) {
318: return TCL_ERROR;
319: }
320:
321: if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) ||
322: (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
323: return TCL_ERROR;
324: }
325:
326: ToolDrag(view, x, y); Kick();
327: return TCL_OK;
328: }
329:
330:
331: int EditorCmdToolUp(VIEW_ARGS)
332: {
333: int x, y;
334:
335: if (argc != 4) {
336: return TCL_ERROR;
337: }
338:
339: if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) ||
340: (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
341: return TCL_ERROR;
342: }
343:
344: ToolUp(view, x, y); Kick();
345: return TCL_OK;
346: }
347:
348:
349: int EditorCmdPanStart(VIEW_ARGS)
350: {
351: int x, y;
352:
353: if (argc != 4) {
354: return TCL_ERROR;
355: }
356:
357: if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) ||
358: (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
359: return TCL_ERROR;
360: }
361:
362: view->last_x = x;
363: view->last_y = y;
364: return TCL_OK;
365: }
366:
367:
368: int EditorCmdPanTo(VIEW_ARGS)
369: {
370: int x, y, dx, dy;
371:
372: if (argc != 4) {
373: return TCL_ERROR;
374: }
375:
376: if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) ||
377: (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
378: return TCL_ERROR;
379: }
380:
381: dx = (view->tool_x_const == -1) ? (view->last_x - x) : 0;
382: dy = (view->tool_y_const == -1) ? (view->last_y - y) : 0;
383: if (dx || dy) {
384: view->last_x = x;
385: view->last_y = y;
386: DoPanBy(view, dx, dy); Kick();
387: }
388: return TCL_OK;
389: }
390:
391:
392: int EditorCmdPanBy(VIEW_ARGS)
393: {
394: int dx, dy;
395:
396: if (argc != 4) {
397: return TCL_ERROR;
398: }
399:
400: if ((Tcl_GetInt(interp, argv[2], &dx) != TCL_OK) ||
401: (Tcl_GetInt(interp, argv[3], &dy) != TCL_OK)) {
402: return TCL_ERROR;
403: }
404:
405: DoPanBy(view, dx, dy); Kick();
406: return TCL_OK;
407: }
408:
409:
410: int EditorCmdTweakCursor(VIEW_ARGS)
411: {
412: int x, y;
413:
414: XWarpPointer (view->x->dpy, None, None, 0, 0, 0, 0, 0, 0);
415:
416: return TCL_OK;
417: }
418:
419:
420: int EditorCmdVisible(VIEW_ARGS)
421: {
422: int visible;
423:
424: if ((argc != 2) && (argc != 3)) {
425: return TCL_ERROR;
426: }
427:
428: if (argc == 3) {
429: if ((Tcl_GetInt(interp, argv[2], &visible) != TCL_OK) ||
430: (visible < 0) || (visible > 1)) {
431: return TCL_ERROR;
432: }
433:
434: visible = visible && Tk_IsMapped(view->tkwin);
435: view->visible = visible;
436: }
437:
438: sprintf(interp->result, "%d", view->visible);
439: return TCL_OK;
440: }
441:
442:
443: int EditorCmdKeyDown(VIEW_ARGS)
444: {
445:
446: if (argc != 3) {
447: return TCL_ERROR;
448: }
449:
450: doKeyDown(view, argv[2][0]);
451: return TCL_OK;
452: }
453:
454:
455: int EditorCmdKeyUp(VIEW_ARGS)
456: {
457:
458: if (argc != 3) {
459: return TCL_ERROR;
460: }
461:
462: doKeyUp(view, argv[2][0]);
463: return TCL_OK;
464: }
465:
466:
467: int EditorCmdTileCoord(VIEW_ARGS)
468: {
469: int x, y;
470:
471: if ((argc != 2) && (argc != 4)) {
472: return TCL_ERROR;
473: }
474:
475: if (Tcl_GetInt(interp, argv[2], &x) != TCL_OK) {
476: return TCL_ERROR;
477: }
478: if (Tcl_GetInt(interp, argv[3], &y) != TCL_OK) {
479: return TCL_ERROR;
480: }
481:
482: ViewToTileCoords(view, x, y, &x, &y);
483:
484: sprintf(interp->result, "%d %d", x, y);
485: return TCL_OK;
486: }
487:
488:
489: int EditorCmdChalkStart(VIEW_ARGS)
490: {
491: int x, y;
492:
493: if (argc != 4) {
494: return TCL_ERROR;
495: }
496:
497: if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) ||
498: (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
499: return TCL_ERROR;
500: }
501:
502: ChalkStart(view, x, y, COLOR_WHITE);
503: return TCL_OK;
504: }
505:
506:
507: int EditorCmdChalkTo(VIEW_ARGS)
508: {
509: int x, y;
510:
511: if (argc != 4) {
512: return TCL_ERROR;
513: }
514:
515: if ((Tcl_GetInt(interp, argv[2], &x) != TCL_OK) ||
516: (Tcl_GetInt(interp, argv[3], &y) != TCL_OK)) {
517: return TCL_ERROR;
518: }
519:
520: ChalkTo(view, x, y);
521: return TCL_OK;
522: }
523:
524:
525: int EditorCmdAutoGoing(VIEW_ARGS)
526: {
527: int flag;
528:
529: if ((argc != 2) && (argc != 3)) {
530: return TCL_ERROR;
531: }
532:
533: if (argc == 3) {
534: if ((Tcl_GetInt(interp, argv[2], &flag) != TCL_OK)) {
535: return TCL_ERROR;
536: }
537:
538: view->auto_going = flag;
539: if (view->auto_goto == -1)
540: view->auto_goto = 0;
541: }
542:
543: sprintf(interp->result, "%d", view->auto_going);
544: return TCL_OK;
545: }
546:
547:
548: int EditorCmdAutoSpeed(VIEW_ARGS)
549: {
550: int speed;
551:
552: if ((argc != 2) && (argc != 3)) {
553: return TCL_ERROR;
554: }
555:
556: if (argc == 3) {
557: if ((Tcl_GetInt(interp, argv[2], &speed) != TCL_OK) ||
558: (speed < 1)) {
559: return TCL_ERROR;
560: }
561:
562: view->auto_speed = speed;
563: }
564:
565: sprintf(interp->result, "%d", view->auto_speed);
566: return TCL_OK;
567: }
568:
569:
570: int EditorCmdAutoGoal(VIEW_ARGS)
571: {
572: if ((argc != 2) && (argc != 4)) {
573: return TCL_ERROR;
574: }
575: if (argc == 4) {
576: int x, y, dx, dy;
577:
578: if (Tcl_GetInt(interp, argv[2], &x) != TCL_OK) {
579: return TCL_ERROR;
580: }
581: if (Tcl_GetInt(interp, argv[3], &y) != TCL_OK) {
582: return TCL_ERROR;
583: }
584: view->auto_x_goal = x;
585: view->auto_y_goal = y;
586: /* actually go there if more than a block away */
587: dx = view->pan_x - x;
588: dy = view->pan_y - y;
589: view->auto_going = (((dx * dx) + (dy * dy)) > (64 * 64));
590: if ((view->auto_going != 0) &&
591: (view->auto_goto == 0))
592: view->auto_goto = -1;
593: }
594:
595: sprintf(interp->result, "%d %d", view->auto_x_goal, view->auto_y_goal);
596: return TCL_OK;
597: }
598:
599:
600: int EditorCmdSU(VIEW_ARGS)
601: {
602: int su;
603:
604: if ((argc != 2) && (argc != 4)) {
605: return TCL_ERROR;
606: }
607:
608: if (argc == 4) {
609: if ((strcmp(argv[3], "xyzzy") != 0) ||
610: (Tcl_GetInt(interp, argv[2], &su) != TCL_OK)) {
611: return TCL_ERROR;
612: }
613:
614: view->super_user = su;
615: }
616:
617: sprintf(interp->result, "%d", view->super_user);
618: return TCL_OK;
619: }
620:
621:
622: int EditorCmdShowMe(VIEW_ARGS)
623: {
624: int flag;
625:
626: if ((argc != 2) && (argc != 3)) {
627: return TCL_ERROR;
628: }
629:
630: if (argc == 3) {
631: if (Tcl_GetInt(interp, argv[2], &flag) != TCL_OK) {
632: return TCL_ERROR;
633: }
634:
635: view->show_me = flag;
636: }
637:
638: sprintf(interp->result, "%d", view->show_me);
639: return TCL_OK;
640: }
641:
642:
643: int EditorCmdFollow(VIEW_ARGS)
644: {
645: int id;
646: SimSprite *sprite;
647:
648: if ((argc != 2) && (argc != 3)) {
649: return TCL_ERROR;
650: }
651:
652: if (argc == 3) {
653: view->follow = NULL;
654: if (argv[2][0] != '\0') {
655: for (sprite = sim->sprite; sprite != NULL; sprite = sprite->next) {
656: if (strcmp(sprite->name, argv[2]) == 0) {
657: view->follow = sprite;
658: break;
659: }
660: }
661: }
662:
663: if (view->follow != NULL) {
664: HandleAutoGoto(view);
665: }
666: }
667:
668: sprintf(interp->result, "%s",
669: (view->follow == NULL) ? "" : view->follow->name);
670: return TCL_OK;
671: }
672:
673:
674: int EditorCmdShowOverlay(VIEW_ARGS)
675: {
676: int flag;
677:
678: if ((argc != 2) && (argc != 3)) {
679: return TCL_ERROR;
680: }
681:
682: if (argc == 3) {
683: if ((Tcl_GetInt(interp, argv[2], &flag) != TCL_OK)) {
684: return TCL_ERROR;
685: }
686:
687: view->show_overlay = flag;
688: }
689:
690: sprintf(interp->result, "%d", view->show_overlay);
691: return TCL_OK;
692: }
693:
694:
695: int EditorCmdOverlayMode(VIEW_ARGS)
696: {
697: int flag;
698:
699: if ((argc != 2) && (argc != 3)) {
700: return TCL_ERROR;
701: }
702:
703: if (argc == 3) {
704: if ((Tcl_GetInt(interp, argv[2], &flag) != TCL_OK)) {
705: return TCL_ERROR;
706: }
707:
708: view->overlay_mode = flag;
709: }
710:
711: sprintf(interp->result, "%d", view->overlay_mode);
712: return TCL_OK;
713: }
714:
715:
716: int EditorCmdDynamicFilter(VIEW_ARGS)
717: {
718: int val;
719:
720: if ((argc != 2) && (argc != 3)) {
721: return TCL_ERROR;
722: }
723:
724: if (argc == 3) {
725: if ((Tcl_GetInt(interp, argv[2], &val) != TCL_OK)) {
726: return TCL_ERROR;
727: }
728:
729: view->dynamic_filter = val;
730: }
731:
732: sprintf(interp->result, "%d", view->dynamic_filter);
733: return TCL_OK;
734: }
735:
736:
737: int EditorCmdWriteJpeg(VIEW_ARGS)
738: {
739: int val;
740: char *fileName = argv[2];
741:
742: if (argc != 3) {
743: return TCL_ERROR;
744: }
745:
746: // Write a jpeg file of this view.
747:
748: return TCL_OK;
749: }
750:
751:
752: editor_command_init()
753: {
754: int new;
755: extern int TileViewCmd(CLIENT_ARGS);
756:
757: Tcl_CreateCommand(tk_mainInterp, "editorview", TileViewCmd,
758: (ClientData)MainWindow, (void (*)()) NULL);
759:
760: Tcl_InitHashTable(&EditorCmds, TCL_STRING_KEYS);
761:
762: #define EDITOR_CMD(name) HASHED_CMD(Editor, name)
763:
764: EDITOR_CMD(configure);
765: EDITOR_CMD(position);
766: EDITOR_CMD(size);
767: EDITOR_CMD(AutoGoto);
768: EDITOR_CMD(Sound);
769: EDITOR_CMD(Skip);
770: EDITOR_CMD(Update);
771: EDITOR_CMD(Pan);
772: EDITOR_CMD(ToolConstrain);
773: EDITOR_CMD(ToolState);
774: EDITOR_CMD(ToolMode);
775: EDITOR_CMD(DoTool);
776: EDITOR_CMD(ToolDown);
777: EDITOR_CMD(ToolDrag);
778: EDITOR_CMD(ToolUp);
779: EDITOR_CMD(PanStart);
780: EDITOR_CMD(PanTo);
781: EDITOR_CMD(PanBy);
782: EDITOR_CMD(TweakCursor);
783: EDITOR_CMD(Visible);
784: EDITOR_CMD(KeyDown);
785: EDITOR_CMD(KeyUp);
786: EDITOR_CMD(TileCoord);
787: EDITOR_CMD(ChalkStart);
788: EDITOR_CMD(ChalkTo);
789: EDITOR_CMD(AutoGoing);
790: EDITOR_CMD(AutoSpeed);
791: EDITOR_CMD(AutoGoal);
792: EDITOR_CMD(SU);
793: EDITOR_CMD(ShowMe);
794: EDITOR_CMD(Follow);
795: EDITOR_CMD(ShowOverlay);
796: EDITOR_CMD(OverlayMode);
797: EDITOR_CMD(DynamicFilter);
798: }
799:
800:
801: int
802: DoEditorCmd(CLIENT_ARGS)
803: {
804: SimView *view = (SimView *) clientData;
805: Tcl_HashEntry *ent;
806: int result = TCL_OK;
807: int (*cmd)();
808:
809: if (argc < 2) {
810: return TCL_ERROR;
811: }
812:
813: if (ent = Tcl_FindHashEntry(&EditorCmds, argv[1])) {
814: cmd = (int (*)())ent->clientData;
815: Tk_Preserve((ClientData) view);
816: result = cmd(view, interp, argc, argv);
817: Tk_Release((ClientData) view);
818: } else {
819: Tcl_AppendResult(interp, "unknown command name: \"",
820: argv[0], " ", argv[1], "\".", (char *) NULL);
821: result = TCL_ERROR;
822: }
823: return result;
824: }
825:
826:
827:
828: /*************************************************************************/
829:
830:
831: DoNewEditor(SimView *view)
832: {
833: sim->editors++; view->next = sim->editor; sim->editor = view;
834: view->invalid = 1;
835: }
836:
837:
838: DoUpdateEditor(SimView *view)
839: {
840: int dx, dy, i;
841:
842: view->updates++;
843:
844: if (!view->visible) {
845: return;
846: }
847:
848: if ((!ShakeNow) &&
849: // (!view->invalid) &&
850: (!view->update) &&
851: (sim_skips ||
852: view->skips)) {
853: if (sim_skips) {
854: if (sim_skip > 0) {
855: return 0;
856: }
857: } else {
858: if (view->skip > 0) {
859: --view->skip;
860: return 0;
861: } else {
862: view->skip = view->skips;
863: }
864: }
865: }
866:
867: view->skips = 0;
868: view->update = 0;
869:
870: HandleAutoGoto(view);
871:
872: if (DoAnimation && SimSpeed && !heat_steps && !TilesAnimated) {
873: TilesAnimated = 1;
874: animateTiles();
875: }
876:
877: if (view->invalid) {
878:
879: switch (view->type) {
880:
881: case X_Mem_View:
882: MemDrawBeegMapRect(view, view->tile_x, view->tile_y,
883: view->tile_width, view->tile_height);
884: break;
885:
886: case X_Wire_View:
887: WireDrawBeegMapRect(view, view->tile_x, view->tile_y,
888: view->tile_width, view->tile_height);
889: break;
890:
891: }
892:
893: XCopyArea(view->x->dpy, view->pixmap, view->pixmap2, view->x->gc,
894: 0, 0, view->screen_width, view->screen_height,
895: view->screen_x, view->screen_y);
896: DrawOutside(view);
897: if (PendingTool != -1) {
898: DrawPending(view);
899: }
900: DrawObjects(view);
901: if (view->show_overlay) {
902: DrawOverlay(view);
903: }
904: }
905:
906: for (dx = dy = i = 0; i < ShakeNow; i++) {
907: dx += Rand(16) - 8;
908: dy += Rand(16) - 8;
909: }
910:
911: XCopyArea(view->x->dpy, view->pixmap2,
912: Tk_WindowId(view->tkwin), view->x->gc,
913: 0, 0, view->w_width, view->w_height, dx, dy);
914:
915: DrawCursor(view);
916:
917: view->invalid = 0;
918: }
919:
920:
921: HandleAutoGoto(SimView *view)
922: {
923: if (view->follow != NULL) {
924: int x = view->follow->x + view->follow->x_hot,
925: y = view->follow->y + view->follow->y_hot;
926:
927: if ((x != view->pan_x) ||
928: (y != view->pan_y)) {
929: DoPanTo(view, x, y);
930: }
931: } else if (view->auto_goto &&
932: view->auto_going &&
933: (view->tool_mode == 0)) {
934: int dx, dy;
935: int panx, pany, speed;
936: double dist, sloth;
937:
938: speed = view->auto_speed;
939:
940: if (view->auto_going < 5) {
941: sloth = ((double)view->auto_going) / 5.0;
942: } else {
943: sloth = 1.0;
944: }
945:
946: dx = view->auto_x_goal - view->pan_x;
947: dy = view->auto_y_goal - view->pan_y;
948:
949: dist = sqrt((double)((dx * dx) + (dy * dy)));
950:
951: if (dist < (speed * sloth)) {
952: view->auto_going = 0;
953: if (view->auto_goto == -1)
954: view->auto_goto = 0;
955: DoPanTo(view, view->auto_x_goal, view->auto_y_goal);
956: NewMap = 1;
957: DidStopPan(view);
958: } else {
959: double atan2(), cos(), sin();
960: double direction, vx, vy;
961: double co, si;
962:
963: direction = (double)atan2((double)dy, (double)dx);
964: co = (double)cos(direction);
965: si = (double)sin(direction);
966: vx = co * (double)speed;
967: vy = si * (double)speed;
968:
969: vx *= sloth; vy *= sloth;
970: speed *= sloth;
971:
972: vx += 0.5; vy += 0.5;
973:
974: DoPanBy(view, (int)(vx), (int)(vy));
975: view->auto_going++;
976: }
977: }
978: }
979:
980: DrawOutside(SimView *view)
981: {
982: Pixmap pm = view->pixmap2;
983: int left = (view->w_width / 2) - view->pan_x;
984: int right = left + view->i_width;
985: int top = (view->w_height / 2) - view->pan_y;
986: int bottom = top + view->i_height;
987:
988: if ((top > 0) || (bottom < view->w_height) ||
989: (left > 0) || (right < view->w_width)) {
990: if (view->x->color) {
991: XSetForeground(view->x->dpy, view->x->gc,
992: view->pixels[COLOR_BLACK]);
993: } else {
994: XSetForeground(view->x->dpy, view->x->gc,
995: view->pixels[COLOR_WHITE]);
996: }
997:
998: if (top > 0)
999: XFillRectangle(view->x->dpy, pm, view->x->gc,
1000: 0, 0, view->w_width, top);
1001: if (bottom < view->w_height)
1002: XFillRectangle(view->x->dpy, pm, view->x->gc,
1003: 0, bottom, view->w_width,
1004: view->w_height - bottom);
1005: if (left > 0)
1006: XFillRectangle(view->x->dpy, pm, view->x->gc,
1007: 0, top, left, bottom - top);
1008: if (right < view->w_width)
1009: XFillRectangle(view->x->dpy, pm, view->x->gc,
1010: right, top, view->w_width - right, bottom - top);
1011: }
1012: }
1013:
1014:
1015: char CursorDashes[] = { 4, 4 };
1016:
1017: DrawPending(SimView *view)
1018: {
1019: Pixmap pm = view->pixmap2;
1020: int left = (view->w_width / 2) - view->pan_x;
1021: int top = (view->w_height / 2) - view->pan_y;
1022: int x, y, size;
1023: char *iconname = NULL;
1024:
1025: x = (PendingX - toolOffset[PendingTool]) <<4;
1026: y = (PendingY - toolOffset[PendingTool]) <<4;
1027: size = toolSize[PendingTool] <<4;
1028: x += left; y += top;
1029:
1030: XSetStipple(view->x->dpy, view->x->gc, view->x->gray50_stipple);
1031: XSetTSOrigin(view->x->dpy, view->x->gc, 0, 0);
1032: XSetForeground(view->x->dpy, view->x->gc, view->x->pixels[COLOR_BLACK]);
1033: XSetFillStyle(view->x->dpy, view->x->gc, FillStippled);
1034: XFillRectangle(view->x->dpy, pm, view->x->gc,
1035: x, y, size, size);
1036: XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);
1037:
1038: switch (PendingTool) {
1039: case residentialState:
1040: iconname = "@images/res.xpm"; break;
1041: case commercialState:
1042: iconname = "@images/com.xpm"; break;
1043: case industrialState:
1044: iconname = "@images/ind.xpm"; break;
1045: case fireState:
1046: iconname = "@images/fire.xpm"; break;
1047: case policeState:
1048: iconname = "@images/police.xpm"; break;
1049: case stadiumState:
1050: iconname = "@images/stadium.xpm"; break;
1051: case seaportState:
1052: iconname = "@images/seaport.xpm"; break;
1053: case powerState:
1054: iconname = "@images/coal.xpm"; break;
1055: case nuclearState:
1056: iconname = "@images/nuclear.xpm"; break;
1057: case airportState:
1058: iconname = "@images/airport.xpm"; break;
1059: default:
1060: break;
1061: }
1062:
1063: if (iconname != NULL) {
1064: Pixmap icon = Tk_GetPixmap(view->interp, view->tkwin, iconname);
1065: float f;
1066: int i;
1067:
1068: gettimeofday(&now_time, NULL);
1069: f = (2 * now_time.tv_usec / 1000000.0);
1070: if (f > 1.0) f = 2.0 - f;
1071: i = (int)(f * BobHeight * (Players - Votes));
1072:
1073: if (icon != None) {
1074: XCopyArea(view->x->dpy, icon, pm, view->x->gc,
1075: 0, 0, size, size, x + i, y - i);
1076: }
1077: }
1078: }
1079:
1080:
1081: DrawCursor(SimView *view)
1082: {
1083: Pixmap pm = Tk_WindowId(view->tkwin);
1084: int left = (view->w_width / 2) - view->pan_x;
1085: int top = (view->w_height / 2) - view->pan_y;
1086: int x, y, mode, size, offset, fg, bg, light, dark;
1087: SimView *v;
1088:
1089: for (v = sim->editor; v != NULL; v = v->next) {
1090: mode = v->tool_mode;
1091: if ((v->show_me != 0) &&
1092: ((mode == -1) || v->tool_showing)) {
1093: x = v->tool_x; y = v->tool_y;
1094: if (mode == -1) { /* pan cursor */
1095:
1096: x += left; y += top;
1097:
1098: XSetLineAttributes(view->x->dpy, view->x->gc, 3,
1099: LineSolid, CapRound, JoinMiter);
1100: XSetForeground(view->x->dpy, view->x->gc,
1101: view->pixels[COLOR_BLACK]);
1102: XDrawLine(view->x->dpy, pm, view->x->gc,
1103: x - 6, y - 6, x + 6, y + 6);
1104: XDrawLine(view->x->dpy, pm, view->x->gc,
1105: x - 6, y + 6, x + 6, y - 6);
1106: XDrawLine(view->x->dpy, pm, view->x->gc,
1107: x - 8, y, x + 8, y);
1108: XDrawLine(view->x->dpy, pm, view->x->gc,
1109: x, y + 8, x, y - 8);
1110: XSetLineAttributes(view->x->dpy, view->x->gc, 1,
1111: LineSolid, CapRound, JoinMiter);
1112: XSetForeground(view->x->dpy, view->x->gc,
1113: view->pixels[COLOR_WHITE]);
1114: XDrawLine(view->x->dpy, pm, view->x->gc,
1115: x - 6, y - 6, x + 6, y + 6);
1116: XDrawLine(view->x->dpy, pm, view->x->gc,
1117: x - 6, y + 6, x + 6, y - 6);
1118: XDrawLine(view->x->dpy, pm, view->x->gc,
1119: x - 8, y, x + 8, y);
1120: XDrawLine(view->x->dpy, pm, view->x->gc,
1121: x, y + 8, x, y - 8);
1122: XSetLineAttributes(view->x->dpy, view->x->gc, 1,
1123: LineSolid, CapButt, JoinMiter);
1124:
1125: } else { /* edit cursor */
1126:
1127: size = toolSize[v->tool_state];
1128: fg = toolColors[v->tool_state] & 0xff;
1129: light = COLOR_WHITE;
1130: dark = COLOR_BLACK;
1131: if (mode == 1) {
1132: int temp = dark;
1133: dark = light;
1134: light = temp;
1135: }
1136: switch (v->tool_state) {
1137:
1138: case chalkState:
1139: x += left; y += top;
1140: if (mode == 1) {
1141: offset = 2;
1142: } else {
1143: offset = 0;
1144:
1145: if (view->x->color) {
1146: XSetForeground(view->x->dpy, view->x->gc,
1147: view->pixels[COLOR_MEDIUMGRAY]);
1148: XFillArc(view->x->dpy, pm, view->x->gc,
1149: x - 8, y + 7, 7, 7, 0, 360 * 64);
1150: } else {
1151: XSetStipple(view->x->dpy, view->x->gc,
1152: view->x->gray50_stipple);
1153: XSetTSOrigin(view->x->dpy, view->x->gc, 0, 0);
1154: XSetForeground(view->x->dpy, view->x->gc,
1155: view->x->pixels[COLOR_BLACK]);
1156: XSetBackground(view->x->dpy, view->x->gc,
1157: view->x->pixels[COLOR_WHITE]);
1158: XSetFillStyle(view->x->dpy, view->x->gc, FillOpaqueStippled);
1159: XFillArc(view->x->dpy, pm, view->x->gc,
1160: x - 8, y + 7, 7, 7, 0, 360 * 64);
1161: XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);
1162: }
1163: }
1164:
1165: if (view->x->color) {
1166: XSetLineAttributes(view->x->dpy, view->x->gc, 3,
1167: LineSolid, CapRound, JoinMiter);
1168: XSetForeground(view->x->dpy, view->x->gc,
1169: view->pixels[COLOR_LIGHTGRAY]);
1170: XFillArc(view->x->dpy, pm, view->x->gc,
1171: x - 6 - offset, y + 5 + offset, 7, 7, 0, 360 * 64);
1172: XDrawLine(view->x->dpy, pm, view->x->gc,
1173: x + 13 - offset, y - 5 + offset,
1174: x - 1 - offset, y + 9 + offset);
1175: XSetForeground(view->x->dpy, view->x->gc,
1176: view->pixels[COLOR_WHITE]);
1177: XDrawLine(view->x->dpy, pm, view->x->gc,
1178: x + 11 - offset, y - 7 + offset,
1179: x - 3 - offset, y + 7 + offset);
1180: XFillArc(view->x->dpy, pm, view->x->gc,
1181: x + 8 - offset, y - 9 + offset, 7, 7, 0, 360 * 64);
1182: XSetLineAttributes(view->x->dpy, view->x->gc, 1,
1183: LineSolid, CapButt, JoinMiter);
1184: } else {
1185: XSetLineAttributes(view->x->dpy, view->x->gc, 3,
1186: LineSolid, CapRound, JoinMiter);
1187: XSetStipple(view->x->dpy, view->x->gc,
1188: view->x->gray25_stipple);
1189: XSetTSOrigin(view->x->dpy, view->x->gc, 0, 0);
1190: XSetForeground(view->x->dpy, view->x->gc,
1191: view->x->pixels[COLOR_BLACK]);
1192: XSetBackground(view->x->dpy, view->x->gc,
1193: view->x->pixels[COLOR_WHITE]);
1194: XSetFillStyle(view->x->dpy, view->x->gc, FillOpaqueStippled);
1195: XFillArc(view->x->dpy, pm, view->x->gc,
1196: x - 6 - offset, y + 5 + offset, 7, 7, 0, 360 * 64);
1197: XDrawLine(view->x->dpy, pm, view->x->gc,
1198: x + 13 - offset, y - 5 + offset,
1199: x - 1 - offset, y + 9 + offset);
1200: XSetStipple(view->x->dpy, view->x->gc,
1201: view->x->gray75_stipple);
1202: XDrawLine(view->x->dpy, pm, view->x->gc,
1203: x + 11 - offset, y - 7 + offset,
1204: x - 3 - offset, y + 7 + offset);
1205: XFillArc(view->x->dpy, pm, view->x->gc,
1206: x + 8 - offset, y - 9 + offset, 7, 7, 0, 360 * 64);
1207: XSetLineAttributes(view->x->dpy, view->x->gc, 1,
1208: LineSolid, CapButt, JoinMiter);
1209: XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);
1210: }
1211:
1212: break;
1213:
1214: case eraserState:
1215: x += left; y += top;
1216: if (mode == 1) {
1217: offset = 0;
1218: } else {
1219: offset = 2;
1220:
1221: if (view->x->color) {
1222: XSetForeground(view->x->dpy, view->x->gc,
1223: view->pixels[COLOR_MEDIUMGRAY]);
1224: XFillRectangle(view->x->dpy, pm, view->x->gc,
1225: x - 8, y - 8, 16, 16);
1226: } else {
1227: XSetStipple(view->x->dpy, view->x->gc,
1228: view->x->gray50_stipple);
1229: XSetTSOrigin(view->x->dpy, view->x->gc, 0, 0);
1230: XSetForeground(view->x->dpy, view->x->gc,
1231: view->x->pixels[COLOR_BLACK]);
1232: XSetBackground(view->x->dpy, view->x->gc,
1233: view->x->pixels[COLOR_WHITE]);
1234: XSetFillStyle(view->x->dpy, view->x->gc, FillOpaqueStippled);
1235: XFillRectangle(view->x->dpy, pm, view->x->gc,
1236: x - 8, y - 8, 16, 16);
1237: XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);
1238: }
1239: }
1240:
1241: if (view->x->color) {
1242: XSetForeground(view->x->dpy, view->x->gc,
1243: view->pixels[COLOR_LIGHTGRAY]);
1244: } else {
1245: XSetStipple(view->x->dpy, view->x->gc,
1246: view->x->gray75_stipple);
1247: XSetTSOrigin(view->x->dpy, view->x->gc, 0, 0);
1248: XSetForeground(view->x->dpy, view->x->gc,
1249: view->x->pixels[COLOR_BLACK]);
1250: XSetBackground(view->x->dpy, view->x->gc,
1251: view->x->pixels[COLOR_WHITE]);
1252: XSetFillStyle(view->x->dpy, view->x->gc, FillOpaqueStippled);
1253: }
1254:
1255: /* top */
1256: XDrawLine(view->x->dpy, pm, view->x->gc,
1257: x - 8 + offset, y - 8 - offset,
1258: x + 8 + offset, y - 8 - offset);
1259: XDrawLine(view->x->dpy, pm, view->x->gc,
1260: x - 7 + offset, y - 7 - offset,
1261: x + 7 + offset, y - 7 - offset);
1262: XDrawLine(view->x->dpy, pm, view->x->gc,
1263: x - 6 + offset, y - 6 - offset,
1264: x + 6 + offset, y - 6 - offset);
1265:
1266: /* left */
1267: XDrawLine(view->x->dpy, pm, view->x->gc,
1268: x - 8 + offset, y - 8 - offset,
1269: x - 8 + offset, y + 8 - offset);
1270: XDrawLine(view->x->dpy, pm, view->x->gc,
1271: x - 7 + offset, y - 7 - offset,
1272: x - 7 + offset, y + 7 - offset);
1273: XDrawLine(view->x->dpy, pm, view->x->gc,
1274: x - 6 + offset, y - 6 - offset,
1275: x - 6 + offset, y + 6 - offset);
1276:
1277: if (view->x->color) {
1278: XSetForeground(view->x->dpy, view->x->gc,
1279: view->pixels[COLOR_BLACK]);
1280: } else {
1281: XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);
1282: }
1283:
1284: /* bottom */
1285: XDrawLine(view->x->dpy, pm, view->x->gc,
1286: x - 7 + offset, y + 7 - offset,
1287: x + 8 + offset, y + 7 - offset);
1288: XDrawLine(view->x->dpy, pm, view->x->gc,
1289: x - 6 + offset, y + 6 - offset,
1290: x + 7 + offset, y + 6 - offset);
1291: XDrawLine(view->x->dpy, pm, view->x->gc,
1292: x - 5 + offset, y + 5 - offset,
1293: x + 6 + offset, y + 5 - offset);
1294:
1295: /* right */
1296: XDrawLine(view->x->dpy, pm, view->x->gc,
1297: x + 7 + offset, y + 8 - offset,
1298: x + 7 + offset, y - 7 - offset);
1299: XDrawLine(view->x->dpy, pm, view->x->gc,
1300: x + 6 + offset, y + 7 - offset,
1301: x + 6 + offset, y - 6 - offset);
1302: XDrawLine(view->x->dpy, pm, view->x->gc,
1303: x + 5 + offset, y + 6 - offset,
1304: x + 5 + offset, y - 5 - offset);
1305:
1306: if (view->x->color) {
1307: XSetForeground(view->x->dpy, view->x->gc,
1308: view->pixels[COLOR_DARKGRAY]);
1309: XFillRectangle(view->x->dpy, pm, view->x->gc,
1310: x - 5 + offset, y - 5 - offset, 10, 10);
1311: } else {
1312: XSetStipple(view->x->dpy, view->x->gc,
1313: view->x->gray50_stipple);
1314: XSetForeground(view->x->dpy, view->x->gc,
1315: view->x->pixels[COLOR_BLACK]);
1316: XSetBackground(view->x->dpy, view->x->gc,
1317: view->x->pixels[COLOR_WHITE]);
1318: XSetFillStyle(view->x->dpy, view->x->gc, FillOpaqueStippled);
1319: XFillRectangle(view->x->dpy, pm, view->x->gc,
1320: x - 5 + offset, y - 5 - offset, 10, 10);
1321: XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);
1322: }
1323:
1324: break;
1325:
1326: default:
1327: offset = toolOffset[v->tool_state];
1328:
1329: bg = (toolColors[v->tool_state] >> 8) & 0xff;
1330:
1331: x = (x & ~15) - (offset <<4);
1332: y = (y & ~15) - (offset <<4);
1333: size <<= 4;
1334: x += left; y += top;
1335:
1336: XSetForeground(view->x->dpy, view->x->gc,
1337: view->pixels[dark]);
1338: XDrawRectangle(view->x->dpy, pm, view->x->gc,
1339: x - 1, y - 1, size + 4, size + 4);
1340: XDrawLine(view->x->dpy, pm, view->x->gc,
1341: x - 3, y + size + 3,
1342: x - 1, y + size + 3);
1343: XDrawLine(view->x->dpy, pm, view->x->gc,
1344: x + size + 3, y - 3,
1345: x + size + 3, y - 1);
1346:
1347: XSetForeground(view->x->dpy, view->x->gc,
1348: view->pixels[light]);
1349: XDrawRectangle(view->x->dpy, pm, view->x->gc,
1350: x - 4, y - 4, size + 4, size + 4);
1351: XDrawLine(view->x->dpy, pm, view->x->gc,
1352: x - 4, y + size + 1,
1353: x - 4, y + size + 3);
1354: XDrawLine(view->x->dpy, pm, view->x->gc,
1355: x + size + 1, y - 4,
1356: x + size + 3, y - 4);
1357:
1358: if (view->x->color) {
1359: if (fg == bg) {
1360: XSetForeground(view->x->dpy, view->x->gc,
1361: view->x->pixels[fg]);
1362: XSetLineAttributes(view->x->dpy, view->x->gc, 2,
1363: LineSolid, CapButt, JoinMiter);
1364: } else {
1365: XSetForeground(view->x->dpy, view->x->gc,
1366: view->x->pixels[fg]);
1367: XSetBackground(view->x->dpy, view->x->gc,
1368: view->pixels[bg]);
1369:
1370: XSetLineAttributes(view->x->dpy, view->x->gc, 2,
1371: LineDoubleDash, CapButt, JoinMiter);
1372: XSetDashes(view->x->dpy, view->x->gc, 0, CursorDashes, 2);
1373: }
1374: } else {
1375: XSetStipple(view->x->dpy, view->x->gc,
1376: view->x->gray50_stipple);
1377: XSetForeground(view->x->dpy, view->x->gc,
1378: view->x->pixels[COLOR_BLACK]);
1379: XSetBackground(view->x->dpy, view->x->gc,
1380: view->x->pixels[COLOR_WHITE]);
1381: XSetFillStyle(view->x->dpy, view->x->gc, FillOpaqueStippled);
1382: XSetLineAttributes(view->x->dpy, view->x->gc, 2,
1383: LineSolid, CapButt, JoinMiter);
1384: }
1385:
1386: XDrawLine(view->x->dpy, pm, view->x->gc,
1387: x - 2, y - 1, x - 2, y + size + 3);
1388: XDrawLine(view->x->dpy, pm, view->x->gc,
1389: x - 1, y + size + 2, x + size + 3, y + size + 2);
1390: XDrawLine(view->x->dpy, pm, view->x->gc,
1391: x + size + 2, y + size + 1, x + size + 2, y - 3);
1392: XDrawLine(view->x->dpy, pm, view->x->gc,
1393: x + size + 1, y - 2, x - 3, y - 2);
1394:
1395: if (!view->x->color) {
1396: XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);
1397: }
1398: XSetLineAttributes(view->x->dpy, view->x->gc, 1,
1399: LineSolid, CapButt, JoinMiter);
1400:
1401: break;
1402: }
1403: }
1404: }
1405: }
1406: }
1407:
1408:
1409: TimeElapsed(struct timeval *elapsed,
1410: struct timeval *start,
1411: struct timeval *finish)
1412: {
1413: int usec = finish->tv_usec - start->tv_usec;
1414: int sec = finish->tv_sec - start->tv_sec;
1415:
1416: while (usec < 0) {
1417: usec += 1000000;
1418: sec--;
1419: }
1420: elapsed->tv_usec = usec;
1421: elapsed->tv_sec = sec;
1422: }
1423:
1424:
1425:
1426: DrawOverlay(SimView *view)
1427: {
1428: int width = view->w_width;
1429: int height = view->w_height;
1430: int left = view->pan_x - (width / 2);
1431: int top = view->pan_y - (height / 2);
1432: int right = left + width;
1433: int bottom = top + height;
1434: int showing = 0;
1435: Ink *ink;
1436: struct timeval start, finished, elapsed;
1437:
1438: for (ink = sim->overlay; ink != NULL; ink = ink->next) {
1439: if ((ink->bottom >= top) && (ink->top <= bottom) &&
1440: (ink->right >= left) && (ink->left <= right)) {
1441: showing = 1;
1442: break;
1443: }
1444: }
1445:
1446: if (!showing) return;
1447:
1448: /* overlay_mode state machine:
1449: 0 => overlay invalid:
1450: draw lines to pm => 1
1451: 1 => overlay stable:
1452: sync, time draw lines to pm => 2
1453: 2 => overlay stable:
1454: draw lines to ol,
1455: sync, time clip ol to pm,
1456: lines faster? => 3,
1457: clipping faster? => 4
1458: 3 => lines faster:
1459: draw lines to pm => 3
1460: 4 => clipping faster:
1461: clip ol to pm => 4
1462: */
1463:
1464: switch (view->overlay_mode) {
1465: case 0:
1466: DrawTheOverlay(view, view->x->gc,
1467: view->pixmap2, view->pixels[COLOR_WHITE],
1468: top, bottom, left, right, 0);
1469: view->overlay_mode = 1;
1470: break;
1471: case 1:
1472: XSync(view->x->dpy, False);
1473: gettimeofday(&start, NULL);
1474: DrawTheOverlay(view, view->x->gc,
1475: view->pixmap2, view->pixels[COLOR_WHITE],
1476: top, bottom, left, right, 0);
1477: XSync(view->x->dpy, False);
1478: gettimeofday(&finished, NULL);
1479: TimeElapsed(&view->overlay_time, &start, &finished);
1480: view->overlay_mode = 2;
1481: break;
1482: case 2:
1483: XSetForeground(view->x->dpy, view->x->overlay_gc, 0);
1484: XFillRectangle(view->x->dpy, view->overlay_pixmap, view->x->overlay_gc,
1485: 0, 0, view->m_width, view->m_height);
1486: DrawTheOverlay(view, view->x->overlay_gc,
1487: view->overlay_pixmap, 1,
1488: top, bottom, left, right, 1);
1489: XSync(view->x->dpy, False);
1490: gettimeofday(&start, NULL);
1491: ClipTheOverlay(view);
1492: XSync(view->x->dpy, False);
1493: gettimeofday(&finished, NULL);
1494: TimeElapsed(&elapsed, &start, &finished);
1495: if ((elapsed.tv_sec > view->overlay_time.tv_sec) ||
1496: ((elapsed.tv_sec == view->overlay_time.tv_sec) &&
1497: ((elapsed.tv_usec > view->overlay_time.tv_usec)))) {
1498: view->overlay_mode = 3;
1499: } else {
1500: view->overlay_mode = 4;
1501: }
1502: break;
1503: case 3:
1504: DrawTheOverlay(view, view->x->gc,
1505: view->pixmap2, view->pixels[COLOR_WHITE],
1506: top, bottom, left, right, 0);
1507: break;
1508: case 4:
1509: ClipTheOverlay(view);
1510: break;
1511: }
1512: }
1513:
1514:
1515: DrawTheOverlay(SimView *view, GC gc, Pixmap pm, int color,
1516: int top, int bottom, int left, int right,
1517: int onoverlay)
1518: {
1519: Ink *ink;
1520:
1521: if (view->x->color) {
1522: XSetForeground(view->x->dpy, gc, color);
1523: XSetLineAttributes(view->x->dpy, gc, 3,
1524: LineSolid, CapButt, JoinBevel);
1525: } else {
1526: if (!onoverlay) {
1527: XSetStipple(view->x->dpy, gc, view->x->gray50_stipple);
1528: XSetTSOrigin(view->x->dpy, gc, view->updates & 1, 0);
1529: XSetBackground(view->x->dpy, gc, 0);
1530: XSetFillStyle(view->x->dpy, gc, FillOpaqueStippled);
1531: }
1532: XSetForeground(view->x->dpy, gc, 1);
1533: XSetLineAttributes(view->x->dpy, gc, 3,
1534: LineSolid, CapButt, JoinBevel);
1535: }
1536: for (ink = sim->overlay; ink != NULL; ink = ink->next) {
1537: if ((ink->bottom >= top) && (ink->top <= bottom) &&
1538: (ink->right >= left) && (ink->left <= right)) {
1539: if (ink->length <= 1) {
1540: XFillArc(view->x->dpy, pm, gc,
1541: ink->x - 3, ink->y - 3, 6, 6, 0, 360 * 64);
1542: } else {
1543: ink->points[0].x = ink->x - left;
1544: ink->points[0].y = ink->y - top;
1545: XDrawLines(view->x->dpy, pm, gc,
1546: ink->points, ink->length, CoordModePrevious);
1547: }
1548: }
1549: }
1550: if (!view->x->color) {
1551: XSetFillStyle(view->x->dpy, gc, FillSolid);
1552: }
1553: XSetLineAttributes(view->x->dpy, gc, 1,
1554: LineSolid, CapButt, JoinMiter);
1555: }
1556:
1557:
1558: ClipTheOverlay(SimView *view)
1559: {
1560: if (view->x->color) {
1561: XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_WHITE]);
1562: XSetFillStyle(view->x->dpy, view->x->gc, FillStippled);
1563: XSetStipple(view->x->dpy, view->x->gc, view->overlay_pixmap);
1564: XSetTSOrigin(view->x->dpy, view->x->gc, 0, 0);
1565: XFillRectangle(view->x->dpy, view->pixmap2, view->x->gc,
1566: 0, 0, view->w_width, view->w_height);
1567: XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);
1568: } else {
1569: XSetStipple(view->x->dpy, view->x->gc, view->x->gray50_stipple);
1570: XSetTSOrigin(view->x->dpy, view->x->gc, view->updates & 1, 0);
1571: XSetForeground(view->x->dpy, view->x->gc, view->pixels[COLOR_WHITE]);
1572: XSetBackground(view->x->dpy, view->x->gc, view->pixels[COLOR_BLACK]);
1573: XSetFillStyle(view->x->dpy, view->x->gc, FillOpaqueStippled);
1574: XSetLineAttributes(view->x->dpy, view->x->gc, 3,
1575: LineSolid, CapButt, JoinBevel);
1576: XSetClipOrigin(view->x->dpy, view->x->gc, 0, 0);
1577: XSetClipMask(view->x->dpy, view->x->gc, view->overlay_pixmap);
1578: XFillRectangle(view->x->dpy, view->pixmap2, view->x->gc,
1579: 0, 0, view->w_width, view->w_height);
1580: XSetFillStyle(view->x->dpy, view->x->gc, FillSolid);
1581: XSetClipMask(view->x->dpy, view->x->gc, None);
1582: }
1583: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.