]> git.zerfleddert.de Git - micropolis/blame - src/sim/w_tk.c
Add an SDL sound backend and use it instead of spawning an external
[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);
107int ConfigureTileView(Tcl_Interp *interp, SimView *view,
108 int argc, char **argv, int flags);
109static void TileViewEventProc(ClientData clientData, XEvent *eventPtr);
110static void DestroyTileView(ClientData clientData);
111
112int ConfigureSimGraph(Tcl_Interp *interp, SimGraph *graph,
113 int argc, char **argv, int flags);
114
115static void MicropolisTimerProc(ClientData clientData);
116
117int SimCmd(CLIENT_ARGS);
118int DoEditorCmd(CLIENT_ARGS);
119int DoMapCmd(CLIENT_ARGS);
120int GraphViewCmd(CLIENT_ARGS);
121int DoGraphCmd(CLIENT_ARGS);
122int SpriteCmd(CLIENT_ARGS);
123extern int Tk_PieMenuCmd();
124extern int Tk_IntervalCmd();
125
126
127int
128TileViewCmd(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
223int
224ConfigureTileView(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
244InvalidateMaps()
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
258InvalidateEditors()
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
272RedrawMaps()
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
286RedrawEditors()
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
300static void
301DisplayTileView(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
337EventuallyRedrawView(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
347CancelRedrawView(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
356static void
357TileAutoScrollProc(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
401static void
402TileViewEventProc(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) ||
ce97f582
MG
478 ((view->tool_x >> 4) != (last_x >> 4)) ||
479 ((view->tool_y >> 4) != (last_y >> 4)))) {
6a5fa4e0
MG
480#if 1
481 EventuallyRedrawView(view);
482#else
483 RedrawEditors();
484#endif
485 }
486 }
487}
488
489
490static void
491DestroyTileView(ClientData clientData)
492{
493 SimView *view = (SimView *) clientData;
494
495 DestroyView(view);
496}
497
498
499void
500StdinProc(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
541static void
542StructureProc(ClientData clientData, XEvent *eventPtr)
543{
544 if (eventPtr->type == DestroyNotify) {
545 MainWindow = NULL;
546 }
547}
548
549
550static void
551DelayedMap(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
563DidStopPan(SimView *view)
564{
565 char buf[256];
566 sprintf(buf, "UIDidStopPan %s", Tk_PathName(view->tkwin));
567
568 Eval(buf);
569}
570
571
572static void
573MicropolisTimerProc(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
591void
592ReallyStartMicropolisTimer(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
624StartMicropolisTimer()
625{
626 if (sim_timer_idle == 0) {
627 sim_timer_idle = 1;
628 Tk_DoWhenIdle(
629 ReallyStartMicropolisTimer,
630 NULL);
631 }
632}
633
634
635StopMicropolisTimer()
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
654FixMicropolisTimer()
655{
656 if (sim_timer_set) {
657 StartMicropolisTimer(NULL);
658 }
659}
660
661
662static void
663DelayedUpdate(ClientData clientData)
664{
665//fprintf(stderr, "DelayedUpdate\n");
666 UpdateDelayed = 0;
667 sim_skip = 0;
668 sim_update();
669}
670
671
672Kick()
673{
674 if (!UpdateDelayed) {
675 UpdateDelayed = 1;
676 Tk_DoWhenIdle(DelayedUpdate, (ClientData) NULL);
677 }
678}
679
680
681void
682StopEarthquake()
683{
684 ShakeNow = 0;
685 if (earthquake_timer_set) {
686 Tk_DeleteTimerHandler(earthquake_timer_token);
687 }
688 earthquake_timer_set = 0;
689}
690
691
692DoEarthQuake(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
705StopToolkit()
706{
707 if (tk_mainInterp != NULL) {
708 Eval("catch {DoStopMicropolis}");
709 }
710}
711
712
713Eval(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
727tk_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();
bf4857d3 777 sound_command_init();
6a5fa4e0
MG
778
779#ifdef CAM
780 cam_command_init();
781#endif
782
783 Tcl_CreateCommand(tk_mainInterp, "piemenu", Tk_PieMenuCmd,
784 (ClientData)MainWindow, (void (*)()) NULL);
785 Tcl_CreateCommand(tk_mainInterp, "interval", Tk_IntervalCmd,
786 (ClientData)MainWindow, (void (*)()) NULL);
787
788 sim = MakeNewSim();
789
790 sprintf(initCmd, "source %s/micropolis.tcl", ResourceDir);
791 filename2UNIX(initCmd);
792 if (Eval(initCmd)) {
793 sim_exit(1); // Just sets tkMustExit and ExitReturn
794 goto bail;
795 }
796
797 sim_init();
798
799 buffer = Tcl_CreateCmdBuf();
800
801 if (sim_tty) {
802 Tk_CreateFileHandler(0, TK_READABLE, StdinProc, (ClientData) 0);
803 }
804
805 { char buf[1024];
806
807 sprintf(buf, "UIStartMicropolis {%s} {%s} {%s}",
808 HomeDir, ResourceDir, HostName);
809 filename2UNIX(buf);
810 if (Eval(buf) != TCL_OK) {
811 sim_exit(1); // Just sets tkMustExit and ExitReturn
812 goto bail;
813 }
814 }
815
816 if (sim_tty) {
817 printf("sim:\n");
818 }
819 fflush(stdout);
820
821 Tk_MainLoop();
822
e4f86d1a 823 sim_really_exit(0);
6a5fa4e0
MG
824
825 bail:
826
827 if (buffer != NULL) {
828 Tcl_DeleteCmdBuf(buffer);
829 }
830
831 Tcl_DeleteInterp(tk_mainInterp);
832}
833
Impressum, Datenschutz