Annotation of micropolis/src/sim/w_tk.c, revision 1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.