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