|
|
1.1 root 1: /* w_tk.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: #ifdef MSDOS
65: #define filename2UNIX(name) \
66: { char *p; for (p = name; *p; p++) if (*p == '\\') *p = '/'; }
67: #else
68: #define filename2UNIX(name) /**/
69: #endif
70:
71:
72: Tcl_Interp *tk_mainInterp = NULL;
73: Tcl_CmdBuf buffer = NULL;
74: Tk_TimerToken sim_timer_token = 0;
75: int sim_timer_idle = 0;
76: int sim_timer_set = 0;
77: Tk_Window MainWindow;
78: int UpdateDelayed = 0;
79: int AutoScrollEdge = 16;
80: int AutoScrollStep = 16;
81: int AutoScrollDelay = 10;
82: Tk_TimerToken earthquake_timer_token;
83: int earthquake_timer_set = 0;
84: int earthquake_delay = 3000;
85: int PerformanceTiming;
86: double FlushTime;
87: int NeedRest = 0;
88:
89:
90: #define DEF_VIEW_FONT "-Adobe-Helvetica-Bold-R-Normal-*-140-*"
91:
92: Tk_ConfigSpec TileViewConfigSpecs[] = {
93: {TK_CONFIG_FONT, "-font", (char *) NULL, (char *) NULL,
94: DEF_VIEW_FONT, Tk_Offset(SimView, fontPtr), 0},
95: {TK_CONFIG_STRING, "-messagevar", (char *) NULL, (char *) NULL,
96: NULL, Tk_Offset(SimView, message_var), 0},
97: {TK_CONFIG_PIXELS, "-width", "width", "Width",
98: 0, Tk_Offset(SimView, width), 0},
99: {TK_CONFIG_PIXELS, "-height", "height", "Height",
100: 0, Tk_Offset(SimView, height), 0},
101: {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
102: (char *) NULL, 0, 0}
103: };
104:
105:
106: int TileViewCmd(CLIENT_ARGS);
107: int ConfigureTileView(Tcl_Interp *interp, SimView *view,
108: int argc, char **argv, int flags);
109: static void TileViewEventProc(ClientData clientData, XEvent *eventPtr);
110: static void DestroyTileView(ClientData clientData);
111:
112: int ConfigureSimGraph(Tcl_Interp *interp, SimGraph *graph,
113: int argc, char **argv, int flags);
114:
115: static void MicropolisTimerProc(ClientData clientData);
116:
117: int SimCmd(CLIENT_ARGS);
118: int DoEditorCmd(CLIENT_ARGS);
119: int DoMapCmd(CLIENT_ARGS);
120: int GraphViewCmd(CLIENT_ARGS);
121: int DoGraphCmd(CLIENT_ARGS);
122: int SpriteCmd(CLIENT_ARGS);
123: extern int Tk_PieMenuCmd();
124: extern int Tk_IntervalCmd();
125:
126:
127: int
128: TileViewCmd(CLIENT_ARGS)
129: {
130: Tk_Window tkwin = (Tk_Window) clientData;
131: SimView *view;
132: int viewclass;
133:
134: if (argc < 2) {
135: Tcl_AppendResult(interp, "wrong # args: should be \"",
136: argv[0], " pathName ?options?\"", (char *) NULL);
137: return TCL_ERROR;
138: }
139:
140: if (strcmp(argv[0], "editorview") == 0)
141: viewclass = Editor_Class;
142: else if (strcmp(argv[0], "mapview") == 0)
143: viewclass = Map_Class;
144: else {
145: return TCL_ERROR;
146: }
147:
148: tkwin = Tk_CreateWindowFromPath(interp, tkwin,
149: argv[1], (char *) NULL);
150: if (tkwin == NULL) {
151: return TCL_ERROR;
152: }
153:
154: view = (SimView *)ckalloc(sizeof (SimView));
155:
156: view->tkwin = tkwin;
157: view->interp = interp;
158: view->flags = 0;
159:
160: if (viewclass == Editor_Class) {
161: Tk_SetClass(view->tkwin, "EditorView");
162:
163: Tk_CreateEventHandler(view->tkwin,
164: VisibilityChangeMask |
165: ExposureMask |
166: StructureNotifyMask |
167: EnterWindowMask |
168: LeaveWindowMask |
169: PointerMotionMask,
170: TileViewEventProc, (ClientData) view);
171: Tcl_CreateCommand(interp, Tk_PathName(view->tkwin),
172: DoEditorCmd, (ClientData) view, (void (*)()) NULL);
173: } else {
174: Tk_SetClass(view->tkwin, "MapView");
175:
176: Tk_CreateEventHandler(view->tkwin,
177: VisibilityChangeMask |
178: ExposureMask |
179: StructureNotifyMask /* |
180: EnterWindowMask |
181: LeaveWindowMask |
182: PointerMotionMask */ ,
183: TileViewEventProc, (ClientData) view);
184: Tcl_CreateCommand(interp, Tk_PathName(view->tkwin),
185: DoMapCmd, (ClientData) view, (void (*)()) NULL);
186: }
187:
188: Tk_MakeWindowExist(view->tkwin);
189:
190: if (getenv("XSYNCHRONIZE") != NULL) {
191: XSynchronize(Tk_Display(tkwin), 1);
192: }
193:
194: if (viewclass == Editor_Class) {
195: InitNewView(view, "MicropolisEditor", Editor_Class, EDITOR_W, EDITOR_H);
196: DoNewEditor(view);
197: } else {
198: InitNewView(view, "MicropolisMap", Map_Class, MAP_W, MAP_H);
199: DoNewMap(view);
200: }
201:
202: if (ConfigureTileView(interp, view, argc-2, argv+2, 0) != TCL_OK) {
203: /* XXX: destroy view */
204: Tk_DestroyWindow(view->tkwin);
205: return TCL_ERROR;
206: }
207:
208: switch (view->class) {
209: case Editor_Class:
210: break;
211: case Map_Class:
212: view->invalid = 1;
213: view->update = 1;
214: DoUpdateMap(view);
215: break;
216: }
217:
218: interp->result = Tk_PathName(view->tkwin);
219: return TCL_OK;
220: }
221:
222:
223: int
224: ConfigureTileView(Tcl_Interp *interp, SimView *view,
225: int argc, char **argv, int flags)
226: {
227: if (Tk_ConfigureWidget(interp, view->tkwin, TileViewConfigSpecs,
228: argc, argv, (char *) view, flags) != TCL_OK) {
229: return TCL_ERROR;
230: }
231:
232: if (view->class == Map_Class) {
233: Tk_GeometryRequest(view->tkwin, MAP_W, MAP_H);
234: } else {
235: if (view->width || view->height) {
236: Tk_GeometryRequest(view->tkwin, view->width, view->height);
237: }
238: }
239: EventuallyRedrawView(view);
240: return TCL_OK;
241: }
242:
243:
244: InvalidateMaps()
245: {
246: SimView *view;
247:
248: //fprintf(stderr, "InvalidateMaps\n");
249: for (view = sim->map; view != NULL; view = view->next) {
250: view->invalid = 1;
251: view->skip = 0;
252: EventuallyRedrawView(view);
253: }
254: sim_skip = 0;
255: }
256:
257:
258: InvalidateEditors()
259: {
260: SimView *view;
261:
262: //fprintf(stderr, "InvalidateEditors\n");
263: for (view = sim->editor; view != NULL; view = view->next) {
264: view->invalid = 1;
265: view->skip = 0;
266: EventuallyRedrawView(view);
267: }
268: sim_skip = 0;
269: }
270:
271:
272: RedrawMaps()
273: {
274: SimView *view;
275:
276: //fprintf(stderr, "RedrawMaps\n");
277:
278: for (view = sim->map; view != NULL; view = view->next) {
279: view->skip = 0;
280: EventuallyRedrawView(view);
281: }
282: sim_skip = 0;
283: }
284:
285:
286: RedrawEditors()
287: {
288: SimView *view;
289:
290: //fprintf(stderr, "RedrawEditors\n");
291:
292: for (view = sim->editor; view != NULL; view = view->next) {
293: view->skip = 0;
294: EventuallyRedrawView(view);
295: }
296: sim_skip = 0;
297: }
298:
299:
300: static void
301: DisplayTileView(ClientData clientData)
302: {
303: SimView *view = (SimView *) clientData;
304: Tk_Window tkwin = view->tkwin;
305: Pixmap pm = None;
306: Drawable d;
307:
308: view->flags &= ~VIEW_REDRAW_PENDING;
309: if (view->visible && (tkwin != NULL) && Tk_IsMapped(tkwin)) {
310: switch (view->class) {
311: case Editor_Class:
312: view->skip = 0;
313: view->update = 1;
314: DoUpdateEditor(view);
315: break;
316: case Map_Class:
317: //fprintf(stderr, "DisplayTileView\n");
318: view->skip = 0;
319: view->update = 1;
320: DoUpdateMap(view);
321: break;
322: }
323: }
324: }
325:
326:
327: /* comefrom:
328: ConfigureTileView
329: TileViewEventProc expose configure motion
330: InvalidateMaps
331: EraserTo
332: DoSetMapState
333: AddInk
334: EraserTo
335: */
336:
337: EventuallyRedrawView(SimView *view)
338: {
339: if (!(view->flags & VIEW_REDRAW_PENDING)) {
340: Tk_DoWhenIdle(DisplayTileView, (ClientData) view);
341: view->flags |= VIEW_REDRAW_PENDING;
342: }
343:
344: }
345:
346:
347: CancelRedrawView(SimView *view)
348: {
349: if (view->flags & VIEW_REDRAW_PENDING) {
350: Tk_CancelIdleCall(DisplayTileView, (ClientData) view);
351: }
352: view->flags &= ~VIEW_REDRAW_PENDING;
353: }
354:
355:
356: static void
357: TileAutoScrollProc(ClientData clientData)
358: {
359: SimView *view = (SimView *)clientData;
360: char buf[256];
361:
362: if (view->tool_mode != 0) {
363: int dx = 0, dy = 0;
364: int result, root_x, root_y, x, y;
365: unsigned int key_buttons;
366: Window root, child;
367:
368: XQueryPointer(Tk_Display(view->tkwin), Tk_WindowId(view->tkwin),
369: &root, &child, &root_x, &root_y, &x, &y, &key_buttons);
370:
371: if (x < AutoScrollEdge)
372: dx = -AutoScrollStep;
373: else if (x > (view->w_width - AutoScrollEdge))
374: dx = AutoScrollStep;
375: if (y < AutoScrollEdge)
376: dy = -AutoScrollStep;
377: else if (y > (view->w_height - AutoScrollEdge))
378: dy = AutoScrollStep;
379:
380: if (dx || dy) {
381: int px = view->pan_x, py = view->pan_y;
382:
383: if (view->tool_mode == -1) {
384: dx = -dx; dy = -dy;
385: }
386:
387: DoPanBy(view, dx, dy);
388: view->tool_x += view->pan_x - px;
389: view->tool_y += view->pan_y - py;
390: view->auto_scroll_token =
391: Tk_CreateTimerHandler(AutoScrollDelay, TileAutoScrollProc,
392: (ClientData) view);
393:
394: sprintf(buf, "UIDidPan %s %d %d", Tk_PathName(view->tkwin), x, y);
395: Eval(buf);
396: }
397: }
398: }
399:
400:
401: static void
402: TileViewEventProc(ClientData clientData, XEvent *eventPtr)
403: {
404: SimView *view = (SimView *) clientData;
405:
406: if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
407: view->visible = 1;
408: EventuallyRedrawView(view);
409: } else if (eventPtr->type == MapNotify) {
410: view->visible = 1;
411: } else if (eventPtr->type == UnmapNotify) {
412: view->visible = 0;
413: } else if (eventPtr->type == VisibilityNotify) {
414: if (eventPtr->xvisibility.state == VisibilityFullyObscured)
415: view->visible = 0;
416: else
417: view->visible = 1;
418: } else if (eventPtr->type == ConfigureNotify) {
419: if (view->class == Editor_Class)
420: DoResizeView(view,
421: eventPtr->xconfigure.width,
422: eventPtr->xconfigure.height);
423: EventuallyRedrawView(view);
424: } else if (eventPtr->type == DestroyNotify) {
425: Tcl_DeleteCommand(view->interp, Tk_PathName(view->tkwin));
426: view->tkwin = NULL;
427: CancelRedrawView(view);
428: Tk_EventuallyFree((ClientData) view, DestroyTileView);
429: } else if ((view->class == Editor_Class) &&
430: (view->show_me != 0) &&
431: ((eventPtr->type == EnterNotify) ||
432: (eventPtr->type == LeaveNotify) ||
433: (eventPtr->type == MotionNotify))) {
434: int last_x = view->tool_x, last_y = view->tool_y,
435: last_showing = view->tool_showing;
436: int x, y, showing, autoscroll;
437:
438: if (eventPtr->type == EnterNotify) {
439: showing = 1;
440: x = eventPtr->xcrossing.x; y = eventPtr->xcrossing.y;
441: } else if (eventPtr->type == LeaveNotify) {
442: showing = 0;
443: x = eventPtr->xcrossing.x; y = eventPtr->xcrossing.y;
444: } else {
445: showing = 1;
446: x = eventPtr->xmotion.x; y = eventPtr->xmotion.y;
447: }
448:
449: if (view->tool_mode != 0) {
450:
451: if ((x < AutoScrollEdge) ||
452: (x > (view->w_width - AutoScrollEdge)) ||
453: (y < AutoScrollEdge) ||
454: (y > (view->w_height - AutoScrollEdge))) {
455: if (!view->auto_scroll_token) {
456: view->auto_scroll_token =
457: Tk_CreateTimerHandler(AutoScrollDelay, TileAutoScrollProc,
458: (ClientData) view);
459: }
460: } else {
461: if (view->auto_scroll_token) {
462: Tk_DeleteTimerHandler(view->auto_scroll_token);
463: view->auto_scroll_token = 0;
464: }
465: }
466: }
467:
468: ViewToPixelCoords(view, x, y, &x, &y);
469: view->tool_showing = showing;
470:
471: if (view->tool_mode != -1) {
472: view->tool_x = x; view->tool_y = y;
473: }
474:
475: /* XXX: redraw all views showing cursor */
476: /* XXX: also, make sure switching tools works w/out moving */
477: if (((view->tool_showing != last_showing) ||
478: (view->tool_x != last_x) ||
479: (view->tool_y != last_y))) {
480: #if 1
481: EventuallyRedrawView(view);
482: #else
483: RedrawEditors();
484: #endif
485: }
486: }
487: }
488:
489:
490: static void
491: DestroyTileView(ClientData clientData)
492: {
493: SimView *view = (SimView *) clientData;
494:
495: DestroyView(view);
496: }
497:
498:
499: void
500: StdinProc(ClientData clientData, int mask)
501: {
502: char line[200];
503: static int gotPartial = 0;
504: char *cmd;
505: int result;
506:
507: if (mask & TK_READABLE) {
508: if (fgets(line, 200, stdin) == NULL) {
509: if (!gotPartial) {
510: if (sim_tty) {
511: sim_exit(0); // Just sets tkMustExit and ExitReturn
512: return;
513: } else {
514: Tk_DeleteFileHandler(0);
515: }
516: return;
517: } else {
518: line[0] = 0;
519: }
520: }
521: cmd = Tcl_AssembleCmd(buffer, line);
522: if (cmd == NULL) {
523: gotPartial = 1;
524: return;
525: }
526: gotPartial = 0;
527: result = Tcl_RecordAndEval(tk_mainInterp, cmd, 0);
528: if (*tk_mainInterp->result != 0) {
529: if ((result != TCL_OK) || sim_tty) {
530: printf("%s\n", tk_mainInterp->result);
531: }
532: }
533: if (sim_tty) {
534: printf("sim:\n");
535: fflush(stdout);
536: }
537: }
538: }
539:
540:
541: static void
542: StructureProc(ClientData clientData, XEvent *eventPtr)
543: {
544: if (eventPtr->type == DestroyNotify) {
545: MainWindow = NULL;
546: }
547: }
548:
549:
550: static void
551: DelayedMap(ClientData clientData)
552: {
553: while (Tk_DoOneEvent(TK_IDLE_EVENTS) != 0) {
554: /* Empty loop body. */
555: }
556: if (MainWindow == NULL) {
557: return;
558: }
559: Tk_MapWindow(MainWindow);
560: }
561:
562:
563: DidStopPan(SimView *view)
564: {
565: char buf[256];
566: sprintf(buf, "UIDidStopPan %s", Tk_PathName(view->tkwin));
567:
568: Eval(buf);
569: }
570:
571:
572: static void
573: MicropolisTimerProc(ClientData clientData)
574: {
575: sim_timer_token = NULL;
576: sim_timer_set = 0;
577:
578: if (NeedRest > 0) {
579: NeedRest--;
580: }
581:
582: if (SimSpeed) {
583: sim_loop(1);
584: StartMicropolisTimer();
585: } else {
586: StopMicropolisTimer();
587: }
588: }
589:
590:
591: void
592: ReallyStartMicropolisTimer(ClientData clientData)
593: {
594: int delay = sim_delay;
595: XDisplay *xd = XDisplays;
596:
597: StopMicropolisTimer();
598:
599: while (xd != NULL) {
600: if ((NeedRest > 0) ||
601: ShakeNow ||
602: (xd->tkDisplay->buttonWinPtr != NULL) ||
603: (xd->tkDisplay->grabWinPtr != NULL)) {
604: if (ShakeNow || NeedRest) {
605: if (delay < 50000) delay = 50000;
606: } else {
607: }
608: break;
609: }
610: xd = xd->next;
611: }
612:
613: sim_timer_token =
614: Tk_CreateMicroTimerHandler(
615: 0,
616: delay,
617: MicropolisTimerProc,
618: (ClientData)0);
619:
620: sim_timer_set = 1;
621: }
622:
623:
624: StartMicropolisTimer()
625: {
626: if (sim_timer_idle == 0) {
627: sim_timer_idle = 1;
628: Tk_DoWhenIdle(
629: ReallyStartMicropolisTimer,
630: NULL);
631: }
632: }
633:
634:
635: StopMicropolisTimer()
636: {
637: if (sim_timer_idle != 0) {
638: sim_timer_idle = 0;
639: Tk_CancelIdleCall(
640: ReallyStartMicropolisTimer,
641: NULL);
642: }
643:
644: if (sim_timer_set) {
645: if (sim_timer_token != 0) {
646: Tk_DeleteTimerHandler(sim_timer_token);
647: sim_timer_token = 0;
648: }
649: sim_timer_set = 0;
650: }
651: }
652:
653:
654: FixMicropolisTimer()
655: {
656: if (sim_timer_set) {
657: StartMicropolisTimer(NULL);
658: }
659: }
660:
661:
662: static void
663: DelayedUpdate(ClientData clientData)
664: {
665: //fprintf(stderr, "DelayedUpdate\n");
666: UpdateDelayed = 0;
667: sim_skip = 0;
668: sim_update();
669: }
670:
671:
672: Kick()
673: {
674: if (!UpdateDelayed) {
675: UpdateDelayed = 1;
676: Tk_DoWhenIdle(DelayedUpdate, (ClientData) NULL);
677: }
678: }
679:
680:
681: void
682: StopEarthquake()
683: {
684: ShakeNow = 0;
685: if (earthquake_timer_set) {
686: Tk_DeleteTimerHandler(earthquake_timer_token);
687: }
688: earthquake_timer_set = 0;
689: }
690:
691:
692: DoEarthQuake(void)
693: {
694: MakeSound("city", "Explosion-Low");
695: Eval("UIEarthQuake");
696: ShakeNow++;
697: if (earthquake_timer_set) {
698: Tk_DeleteTimerHandler(earthquake_timer_token);
699: }
700: Tk_CreateTimerHandler(earthquake_delay, (void (*)())StopEarthquake, (ClientData) 0);
701: earthquake_timer_set = 1;
702: }
703:
704:
705: StopToolkit()
706: {
707: if (tk_mainInterp != NULL) {
708: Eval("catch {DoStopMicropolis}");
709: }
710: }
711:
712:
713: Eval(char *buf)
714: {
715: int result = Tcl_Eval(tk_mainInterp, buf, 0, (char **) NULL);
716: if (result != TCL_OK) {
717: char *errorinfo = Tcl_GetVar(tk_mainInterp, "errorInfo",
718: TCL_GLOBAL_ONLY);
719: if (errorinfo == NULL) errorinfo = "<no backtrace>";
720: fprintf(stderr, "Micropolis: error in TCL code: %s\n%s\n",
721: tk_mainInterp->result, errorinfo);
722: }
723: return (result);
724: }
725:
726:
727: tk_main()
728: {
729: char *p, *msg;
730: char buf[20];
731: char initCmd[256];
732: Tk_3DBorder border;
733:
734: tk_mainInterp = Tcl_CreateExtendedInterp();
735:
736: #if 0
737: /* XXX: Figure out Extended TCL */
738: tclAppName = "Wish";
739: tclAppLongname = "Wish - Tk Shell";
740: tclAppVersion = TK_VERSION;
741: Tcl_ShellEnvInit (interp, TCLSH_ABORT_STARTUP_ERR,
742: name,
743: 0, NULL, /* argv var already set */
744: fileName == NULL, /* interactive? */
745: NULL); /* Standard default file */
746: #endif
747:
748: MainWindow = Tk_CreateMainWindow(tk_mainInterp, FirstDisplay, "Micropolis");
749: if (MainWindow == NULL) {
750: fprintf(stderr, "%s\n", tk_mainInterp->result);
751: sim_really_exit(1); // Just sets tkMustExit and ExitReturn
752: }
753: Tk_SetClass(MainWindow, "Tk");
754: Tk_CreateEventHandler(MainWindow, StructureNotifyMask,
755: StructureProc, (ClientData) NULL);
756: /* Tk_DoWhenIdle(DelayedMap, (ClientData) NULL); */
757:
758: Tk_GeometryRequest(MainWindow, 256, 256);
759: border = Tk_Get3DBorder(tk_mainInterp, MainWindow, None, "gray75");
760: if (border == NULL) {
761: Tcl_SetResult(tk_mainInterp, (char *) NULL, TCL_STATIC);
762: Tk_SetWindowBackground(MainWindow,
763: WhitePixelOfScreen(Tk_Screen(MainWindow)));
764: } else {
765: Tk_SetBackgroundFromBorder(MainWindow, border);
766: }
767: XSetForeground(Tk_Display(MainWindow),
768: DefaultGCOfScreen(Tk_Screen(MainWindow)),
769: BlackPixelOfScreen(Tk_Screen(MainWindow)));
770:
771: sim_command_init();
772: map_command_init();
773: editor_command_init();
774: graph_command_init();
775: date_command_init();
776: sprite_command_init();
777:
778: #ifdef CAM
779: cam_command_init();
780: #endif
781:
782: Tcl_CreateCommand(tk_mainInterp, "piemenu", Tk_PieMenuCmd,
783: (ClientData)MainWindow, (void (*)()) NULL);
784: Tcl_CreateCommand(tk_mainInterp, "interval", Tk_IntervalCmd,
785: (ClientData)MainWindow, (void (*)()) NULL);
786:
787: sim = MakeNewSim();
788:
789: sprintf(initCmd, "source %s/micropolis.tcl", ResourceDir);
790: filename2UNIX(initCmd);
791: if (Eval(initCmd)) {
792: sim_exit(1); // Just sets tkMustExit and ExitReturn
793: goto bail;
794: }
795:
796: sim_init();
797:
798: buffer = Tcl_CreateCmdBuf();
799:
800: if (sim_tty) {
801: Tk_CreateFileHandler(0, TK_READABLE, StdinProc, (ClientData) 0);
802: }
803:
804: { char buf[1024];
805:
806: sprintf(buf, "UIStartMicropolis {%s} {%s} {%s}",
807: HomeDir, ResourceDir, HostName);
808: filename2UNIX(buf);
809: if (Eval(buf) != TCL_OK) {
810: sim_exit(1); // Just sets tkMustExit and ExitReturn
811: goto bail;
812: }
813: }
814:
815: if (sim_tty) {
816: printf("sim:\n");
817: }
818: fflush(stdout);
819:
820: Tk_MainLoop();
821:
822: sim_exit(0); // Just sets tkMustExit and ExitReturn
823:
824: bail:
825:
826: if (buffer != NULL) {
827: Tcl_DeleteCmdBuf(buffer);
828: }
829:
830: Tcl_DeleteInterp(tk_mainInterp);
831: }
832:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.