|
|
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.