Annotation of micropolis/src/sim/w_graph.c, revision 1.1.1.1

1.1       root        1: /* w_graph.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: 
                     65: short NewGraph = 0;
                     66: short AllMax;
                     67: unsigned char *History10[HISTORIES];
                     68: unsigned char *History120[HISTORIES];
                     69: int HistoryInitialized = 0;
                     70: short Graph10Max, Graph120Max;
                     71: Tcl_HashTable GraphCmds;
                     72: int GraphUpdateTime = 100;
                     73: 
                     74: 
                     75: #define DEF_GRAPH_FONT "-Adobe-Helvetica-Bold-R-Normal-*-140-*"
                     76: #define DEF_GRAPH_BG_COLOR     "#b0b0b0"
                     77: #define DEF_GRAPH_BG_MONO      "#ffffff"
                     78: #define DEF_GRAPH_BORDER_WIDTH "0"
                     79: #define DEF_GRAPH_RELIEF       "flat"
                     80: 
                     81: Tk_ConfigSpec GraphConfigSpecs[] = {
                     82:     {TK_CONFIG_FONT, "-font", (char *) NULL, (char *) NULL,
                     83:        DEF_GRAPH_FONT, Tk_Offset(SimGraph, fontPtr), 0},
                     84:     {TK_CONFIG_BORDER, "-background", "background", "Background",
                     85:        DEF_GRAPH_BG_COLOR, Tk_Offset(SimGraph, border),
                     86:        TK_CONFIG_COLOR_ONLY},
                     87:     {TK_CONFIG_BORDER, "-background", "background", "Background",
                     88:        DEF_GRAPH_BG_MONO, Tk_Offset(SimGraph, border),
                     89:        TK_CONFIG_MONO_ONLY},
                     90:     {TK_CONFIG_PIXELS, "-borderwidth", "borderWidth", "BorderWidth",
                     91:        DEF_GRAPH_BORDER_WIDTH, Tk_Offset(SimGraph, borderWidth), 0},
                     92:     {TK_CONFIG_RELIEF, "-relief", "relief", "Relief",
                     93:        DEF_GRAPH_RELIEF, Tk_Offset(SimGraph, relief), 0},
                     94:     {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL,
                     95:        (char *) NULL, 0, 0}
                     96:   };
                     97: 
                     98: 
                     99: XDisplay *FindXDisplay();
                    100: 
                    101: 
                    102: static void
                    103: DisplaySimGraph(ClientData clientData)
                    104: {
                    105:   SimGraph *graph = (SimGraph *) clientData;
                    106:   Tk_Window tkwin = graph->tkwin;
                    107:   Pixmap pm = None;
                    108:   Drawable d;
                    109: 
                    110:   graph->flags &= ~VIEW_REDRAW_PENDING;
                    111: 
                    112: //fprintf(stderr, "DisplaySimGraph token %d\n", graph->draw_graph_token);
                    113: 
                    114:   assert(graph->draw_graph_token != 0);
                    115: 
                    116:   if (graph->draw_graph_token != 0) {
                    117: //    Tk_DeleteTimerHandler(graph->draw_graph_token);
                    118:     graph->draw_graph_token = 0;
                    119:   }
                    120: 
                    121:   if (graph->visible && (tkwin != NULL) && Tk_IsMapped(tkwin)) {
                    122:     DoUpdateGraph(graph);
                    123:   }
                    124: }
                    125: 
                    126: 
                    127: void
                    128: DestroySimGraph(ClientData clientData)
                    129: {
                    130:   SimGraph *graph = (SimGraph *) clientData;
                    131: 
                    132:   DestroyGraph(graph);
                    133: }
                    134: 
                    135: 
                    136: EventuallyRedrawGraph(SimGraph *graph)
                    137: {
                    138:   if (!(graph->flags & VIEW_REDRAW_PENDING)) {
                    139:     assert(graph->draw_graph_token == 0);
                    140:     if (graph->draw_graph_token == 0) {
                    141:       graph->draw_graph_token =
                    142:        Tk_CreateTimerHandler(
                    143:          GraphUpdateTime,
                    144:          DisplaySimGraph,
                    145:          (ClientData) graph);
                    146:       graph->flags |= VIEW_REDRAW_PENDING;
                    147: //fprintf(stderr, "EventuallyRedrawGraph token %d\n", graph->draw_graph_token);
                    148:     }
                    149:   }
                    150: }
                    151: 
                    152: 
                    153: void
                    154: SimGraphEventProc(ClientData clientData, XEvent *eventPtr)
                    155: {
                    156:   SimGraph *graph = (SimGraph *) clientData;
                    157: 
                    158:   if ((eventPtr->type == Expose) && (eventPtr->xexpose.count == 0)) {
                    159:     graph->visible = 1;
                    160:     EventuallyRedrawGraph(graph);
                    161:   } else if (eventPtr->type == MapNotify) {
                    162:     graph->visible = 1;
                    163:   } else if (eventPtr->type == UnmapNotify) {
                    164:     graph->visible = 0;
                    165:   } else if (eventPtr->type == VisibilityNotify) {
                    166:     if (eventPtr->xvisibility.state == VisibilityFullyObscured)
                    167:       graph->visible = 0;
                    168:     else
                    169:       graph->visible = 1;
                    170:   } else if (eventPtr->type == ConfigureNotify) {
                    171:     DoResizeGraph(graph,
                    172:                  eventPtr->xconfigure.width,
                    173:                  eventPtr->xconfigure.height);
                    174:     EventuallyRedrawGraph(graph);
                    175:   } else if (eventPtr->type == DestroyNotify) {
                    176:     Tcl_DeleteCommand(graph->interp, Tk_PathName(graph->tkwin));
                    177:     graph->tkwin = NULL;
                    178:     if (graph->flags & VIEW_REDRAW_PENDING) {
                    179: //fprintf(stderr, "SimGraphEventProc Destroy token %d\n", graph->draw_graph_token);
                    180:       assert(graph->draw_graph_token != 0);
                    181:       if (graph->draw_graph_token != 0) {
                    182:        Tk_DeleteTimerHandler(graph->draw_graph_token);
                    183:        graph->draw_graph_token = 0;
                    184:       }
                    185:       graph->flags &= ~VIEW_REDRAW_PENDING;
                    186:     }
                    187:    Tk_EventuallyFree((ClientData) graph, DestroySimGraph);
                    188:   }
                    189: }
                    190: 
                    191: 
                    192: int GraphCmdconfigure(GRAPH_ARGS)
                    193: {
                    194:   int result = TCL_OK;
                    195: 
                    196:   if (argc == 2) {
                    197:     result = Tk_ConfigureInfo(interp, graph->tkwin, GraphConfigSpecs,
                    198:                              (char *) graph, (char *) NULL, 0);
                    199:   } else if (argc == 3) {
                    200:     result = Tk_ConfigureInfo(interp, graph->tkwin, GraphConfigSpecs,
                    201:                              (char *) graph, argv[2], 0);
                    202:   } else {
                    203:     result = ConfigureSimGraph(interp, graph, argc-2, argv+2,
                    204:                            TK_CONFIG_ARGV_ONLY);
                    205:   }
                    206:   return TCL_OK;
                    207: }
                    208: 
                    209: 
                    210: int GraphCmdposition(GRAPH_ARGS)
                    211: {
                    212:   int result = TCL_OK;
                    213: 
                    214:     if ((argc != 2) && (argc != 4)) {
                    215:       return TCL_ERROR;
                    216:     }
                    217:     if (argc == 4) {
                    218:       if ((Tcl_GetInt(interp, argv[2], &graph->w_x) != TCL_OK)
                    219:          || (Tcl_GetInt(interp, argv[3], &graph->w_y) != TCL_OK)) {
                    220:        return TCL_ERROR;
                    221:       }
                    222:     }
                    223:     sprintf(interp->result, "%d %d", graph->w_x, graph->w_y);
                    224:     return TCL_OK;
                    225: }
                    226: 
                    227: 
                    228: int GraphCmdsize(GRAPH_ARGS)
                    229: {
                    230:   if ((argc != 2) && (argc != 4)) {
                    231:     return TCL_ERROR;
                    232:   }
                    233:   if (argc == 4) {
                    234:     int w, h;
                    235:     
                    236:     if (Tcl_GetInt(interp, argv[2], &w) != TCL_OK) {
                    237:       return TCL_ERROR;
                    238:     }
                    239:     if (Tcl_GetInt(interp, argv[3], &h) != TCL_OK) {
                    240:       return TCL_ERROR;
                    241:     }
                    242:     graph->w_width = w;
                    243:     graph->w_height = h;
                    244:   }
                    245:   sprintf(interp->result, "%d %d", graph->w_width, graph->w_height);
                    246:   return TCL_OK;
                    247: }
                    248: 
                    249: 
                    250: int GraphCmdVisible(GRAPH_ARGS)
                    251: {
                    252:   int visible;
                    253: 
                    254:   if ((argc != 2) && (argc != 3)) {
                    255:     Tcl_AppendResult(interp, "wrong # args", (char *) NULL);
                    256:     return TCL_ERROR;
                    257:   }
                    258: 
                    259:   if (argc == 3) {
                    260:     if ((Tcl_GetInt(interp, argv[2], &visible) != TCL_OK) ||
                    261:        (visible < 0) || (visible > 1)) {
                    262:       Tcl_AppendResult(interp, " bogus args", (char *) NULL);
                    263:       return TCL_ERROR;
                    264:     }
                    265: 
                    266:     graph->visible = visible;
                    267:   }
                    268: 
                    269:   sprintf(interp->result, "%d", graph->visible);
                    270: 
                    271:   return TCL_OK;
                    272: }
                    273: 
                    274: 
                    275: int GraphCmdRange(GRAPH_ARGS)
                    276: {
                    277:   int range;
                    278: 
                    279:   if ((argc != 2) && (argc != 3)) {
                    280:     Tcl_AppendResult(interp, "wrong # args", (char *) NULL);
                    281:     return TCL_ERROR;
                    282:   }
                    283: 
                    284:   if (argc == 3) {
                    285:     if ((Tcl_GetInt(interp, argv[2], &range) != TCL_OK) ||
                    286:        ((range != 10) && (range != 120))) {
                    287:       Tcl_AppendResult(interp, " bogus args", (char *) NULL);
                    288:       return TCL_ERROR;
                    289:     }
                    290: 
                    291:     graph->range = range;
                    292:     NewGraph = 1;
                    293:   }
                    294: 
                    295:   sprintf(interp->result, "%d", graph->range);
                    296: 
                    297:   return TCL_OK;
                    298: }
                    299: 
                    300: 
                    301: int GraphCmdMask(GRAPH_ARGS)
                    302: {
                    303:   int mask;
                    304: 
                    305:   if ((argc != 2) && (argc != 3)) {
                    306:     Tcl_AppendResult(interp, "wrong # args", (char *) NULL);
                    307:     return TCL_ERROR;
                    308:   }
                    309: 
                    310:   if (argc == 3) {
                    311:     if ((Tcl_GetInt(interp, argv[2], &mask) != TCL_OK) ||
                    312:        (mask < 0) || (mask > 63)) {
                    313:       Tcl_AppendResult(interp, " bogus args", (char *) NULL);
                    314:       return TCL_ERROR;
                    315:     }
                    316: 
                    317:     graph->mask = mask;
                    318:     NewGraph = 1;
                    319:   }
                    320: 
                    321:   sprintf(interp->result, "%d", graph->mask);
                    322: 
                    323:   return TCL_OK;
                    324: }
                    325: 
                    326: 
                    327: int
                    328: DoGraphCmd(CLIENT_ARGS)
                    329: {
                    330:   SimGraph *graph = (SimGraph *) clientData;
                    331:   Tcl_HashEntry *ent;
                    332:   int result = TCL_OK;
                    333:   int (*cmd)();
                    334: 
                    335:   if (argc < 2) {
                    336:     return TCL_ERROR;
                    337:   }
                    338: 
                    339:   if (ent = Tcl_FindHashEntry(&GraphCmds, argv[1])) {
                    340:     cmd = (int (*)())ent->clientData;
                    341:     Tk_Preserve((ClientData) graph);
                    342:     result = cmd(graph, interp, argc, argv);
                    343:     Tk_Release((ClientData) graph);
                    344:   } else {
                    345:     Tcl_AppendResult(interp, "unknown command name: \"",
                    346:                     argv[0], " ", argv[1], "\".", (char *) NULL);
                    347:     result = TCL_ERROR;
                    348:   }
                    349:   return result;
                    350: }
                    351: 
                    352: 
                    353: int
                    354: GraphViewCmd(CLIENT_ARGS)
                    355: {
                    356:   SimGraph *graph;
                    357:   Tk_Window tkwin = (Tk_Window) clientData;
                    358: 
                    359:   if (argc < 2) {
                    360:     Tcl_AppendResult(interp, "wrong # args:  should be \"",
                    361:                     argv[0], " pathName ?options?\"", (char *) NULL);
                    362:     return TCL_ERROR;
                    363:   }
                    364: 
                    365:   tkwin = Tk_CreateWindowFromPath(interp, tkwin,
                    366:                                  argv[1], (char *) NULL);
                    367:   if (tkwin == NULL) {
                    368:     return TCL_ERROR;
                    369:   }
                    370: 
                    371:   graph = (SimGraph *)ckalloc(sizeof (SimGraph));
                    372: 
                    373:   graph->tkwin = tkwin;
                    374:   graph->interp = interp;
                    375:   graph->flags = 0;
                    376:   
                    377:   Tk_SetClass(graph->tkwin, "GraphView");
                    378:   Tk_CreateEventHandler(graph->tkwin,
                    379:                        VisibilityChangeMask |
                    380:                        ExposureMask |
                    381:                        StructureNotifyMask,
                    382:                        SimGraphEventProc, (ClientData) graph);
                    383:   Tcl_CreateCommand(interp, Tk_PathName(graph->tkwin),
                    384:                    DoGraphCmd, (ClientData) graph, (void (*)()) NULL);
                    385: 
                    386: /*
                    387:   Tk_MakeWindowExist(graph->tkwin);
                    388: */
                    389:   
                    390:   if (getenv("XSYNCHRONIZE") != NULL) {
                    391:     XSynchronize(Tk_Display(tkwin), 1);
                    392:   }
                    393: 
                    394:   InitNewGraph(graph);
                    395:   DoNewGraph(graph);
                    396: 
                    397:   if (ConfigureSimGraph(interp, graph, argc-2, argv+2, 0) != TCL_OK) {
                    398:     /* XXX: destroy graph */
                    399:     Tk_DestroyWindow(graph->tkwin);
                    400:     return TCL_ERROR;
                    401:   }
                    402: 
                    403:   interp->result = Tk_PathName(graph->tkwin);
                    404:   return TCL_OK;
                    405: }
                    406: 
                    407: 
                    408: int
                    409: ConfigureSimGraph(Tcl_Interp *interp, SimGraph *graph,
                    410:                  int argc, char **argv, int flags)
                    411: {
                    412:   if (Tk_ConfigureWidget(interp, graph->tkwin, GraphConfigSpecs,
                    413:                         argc, argv, (char *) graph, flags) != TCL_OK) {
                    414:     return TCL_ERROR;
                    415:   }
                    416:   
                    417:   Tk_SetBackgroundFromBorder(graph->tkwin, graph->border);
                    418: 
                    419:   EventuallyRedrawGraph(graph);
                    420:   return TCL_OK;
                    421: }
                    422: 
                    423: 
                    424: 
                    425: 
                    426: char *HistName[] = {
                    427:   "Residential", "Commercial", "Industrial",
                    428:   "Cash Flow", "Crime", "Pollution"
                    429: };
                    430: 
                    431: unsigned char HistColor[] = {
                    432:   COLOR_LIGHTGREEN, COLOR_DARKBLUE, COLOR_YELLOW,
                    433:   COLOR_DARKGREEN, COLOR_RED, COLOR_OLIVE
                    434: };
                    435: 
                    436: 
                    437: graph_command_init()
                    438: {
                    439:   int new;
                    440: 
                    441:   Tcl_CreateCommand(tk_mainInterp, "graphview", GraphViewCmd,
                    442:                    (ClientData)MainWindow, (void (*)()) NULL);
                    443: 
                    444:   Tcl_InitHashTable(&GraphCmds, TCL_STRING_KEYS);
                    445: 
                    446: #define GRAPH_CMD(name) HASHED_CMD(Graph, name)
                    447: 
                    448:   GRAPH_CMD(configure);
                    449:   GRAPH_CMD(position);
                    450:   GRAPH_CMD(size);
                    451:   GRAPH_CMD(Visible);
                    452:   GRAPH_CMD(Range);
                    453:   GRAPH_CMD(Mask);
                    454: }
                    455: 
                    456: 
                    457: 
                    458: void
                    459: drawMonth(short *hist, unsigned char *s, float scale)
                    460: {
                    461:   register short val;
                    462:   register short x;
                    463: 
                    464:   for (x = 0; x < 120; x++) {
                    465:     val = hist[x] * scale;
                    466:     if (val < 0) val = 0;
                    467:     if (val > 255) val = 255;
                    468:     s[119 - x] = val;
                    469:   }
                    470: }
                    471: 
                    472: 
                    473: void
                    474: doAllGraphs(void)
                    475: {
                    476:   float scaleValue;
                    477: 
                    478:   AllMax = 0;
                    479:   if (ResHisMax > AllMax) AllMax = ResHisMax;
                    480:   if (ComHisMax > AllMax) AllMax = ComHisMax;
                    481:   if (IndHisMax > AllMax) AllMax = IndHisMax;
                    482:   if (AllMax <= 128) AllMax = 0;
                    483: 
                    484:   if (AllMax) {
                    485:     scaleValue = 128.0 / AllMax;
                    486:   } else {
                    487:     scaleValue = 1.0;
                    488:   }
                    489: 
                    490:   // scaleValue = 0.5; // XXX
                    491: 
                    492:   drawMonth(ResHis, History10[RES_HIST], scaleValue);
                    493:   drawMonth(ComHis, History10[COM_HIST], scaleValue);
                    494:   drawMonth(IndHis, History10[IND_HIST], scaleValue);
                    495:   drawMonth(MoneyHis, History10[MONEY_HIST], 1.0);
                    496:   drawMonth(CrimeHis, History10[CRIME_HIST], 1.0);
                    497:   drawMonth(PollutionHis, History10[POLLUTION_HIST], 1.0);
                    498: 
                    499:   AllMax = 0;
                    500:   if (Res2HisMax > AllMax) AllMax = Res2HisMax;
                    501:   if (Com2HisMax > AllMax) AllMax = Com2HisMax;
                    502:   if (Ind2HisMax > AllMax) AllMax = Ind2HisMax;
                    503:   if (AllMax <= 128) AllMax = 0;
                    504: 
                    505:   if (AllMax) {
                    506:     scaleValue = 128.0 / AllMax;
                    507:   } else {
                    508:     scaleValue = 1.0;
                    509:   }
                    510: 
                    511:   // scaleValue = 0.5; // XXX
                    512: 
                    513:   drawMonth(ResHis + 120, History120[RES_HIST], scaleValue);
                    514:   drawMonth(ComHis + 120, History120[COM_HIST], scaleValue);
                    515:   drawMonth(IndHis + 120, History120[IND_HIST], scaleValue);
                    516:   drawMonth(MoneyHis + 120, History120[MONEY_HIST], 1.0);
                    517:   drawMonth(CrimeHis + 120, History120[CRIME_HIST], 1.0);
                    518:   drawMonth(PollutionHis + 120, History120[POLLUTION_HIST], 1.0);
                    519: }
                    520: 
                    521: 
                    522: void
                    523: ChangeCensus(void)
                    524: {
                    525:   CensusChanged = 1;
                    526: }
                    527: 
                    528: 
                    529: void
                    530: graphDoer(void)
                    531: {
                    532:   SimGraph *graph;
                    533: 
                    534:   if (CensusChanged) {
                    535:     doAllGraphs();
                    536:     NewGraph = 1;
                    537:     CensusChanged = 0;
                    538:   }
                    539: 
                    540:   if (NewGraph) {
                    541:     for (graph = sim->graph; graph != NULL; graph = graph->next) {
                    542:       EventuallyRedrawGraph(graph);
                    543:     }
                    544:     NewGraph = 0;
                    545:   }
                    546: }
                    547: 
                    548: 
                    549: void
                    550: initGraphs(void)
                    551: {
                    552:   int i;
                    553:   SimGraph *graph;
                    554: 
                    555:   for (graph = sim->graph; graph != NULL; graph = graph->next) {
                    556:     graph->range = 10;
                    557:     graph->mask = ALL_HISTORIES;
                    558:   }
                    559: 
                    560:   if (!HistoryInitialized) {
                    561:     HistoryInitialized = 1;
                    562:     for (i = 0; i < HISTORIES; i++) {
                    563:       History10[i] = (unsigned char *)ckalloc(120);
                    564:       History120[i] = (unsigned char *)ckalloc(120);
                    565:     }
                    566:   }
                    567: }
                    568: 
                    569: 
                    570: /* comefrom: InitWillStuff */
                    571: InitGraphMax(void)
                    572: {
                    573:   register x;
                    574: 
                    575:   ResHisMax = 0;
                    576:   ComHisMax = 0;
                    577:   IndHisMax = 0;
                    578:   for (x = 118; x >= 0; x--) {
                    579:     if (ResHis[x] > ResHisMax) ResHisMax = ResHis[x];
                    580:     if (ComHis[x] > ComHisMax) ComHisMax = ComHis[x];
                    581:     if (IndHis[x] > IndHisMax) IndHisMax = IndHis[x];
                    582:     if (ResHis[x] < 0) ResHis[x] = 0;
                    583:     if (ComHis[x] < 0) ComHis[x] = 0;
                    584:     if (IndHis[x] < 0) IndHis[x] = 0;
                    585:   }
                    586:   Graph10Max = ResHisMax;
                    587:   if (ComHisMax > Graph10Max) Graph10Max = ComHisMax;
                    588:   if (IndHisMax > Graph10Max) Graph10Max = IndHisMax;
                    589: 
                    590:   Res2HisMax = 0;
                    591:   Com2HisMax = 0;
                    592:   Ind2HisMax = 0;
                    593:   for (x = 238; x >= 120; x--) {
                    594:     if (ResHis[x] > Res2HisMax) Res2HisMax = ResHis[x];
                    595:     if (ComHis[x] > Com2HisMax) Com2HisMax = ComHis[x];
                    596:     if (IndHis[x] > Ind2HisMax) Ind2HisMax = IndHis[x];
                    597:     if (ResHis[x] < 0) ResHis[x] = 0;
                    598:     if (ComHis[x] < 0) ComHis[x] = 0;
                    599:     if (IndHis[x] < 0) IndHis[x] = 0;
                    600:   }
                    601:   Graph120Max = Res2HisMax;
                    602:   if (Com2HisMax > Graph120Max) Graph120Max = Com2HisMax;
                    603:   if (Ind2HisMax > Graph120Max) Graph120Max = Ind2HisMax;
                    604: }
                    605: 
                    606: 
                    607: InitNewGraph(SimGraph *graph)
                    608: {
                    609:   int d = 8;
                    610:   struct XDisplay *xd;
                    611: 
                    612:   graph->next = NULL;
                    613:   graph->range = 10;
                    614:   graph->mask = ALL_HISTORIES;
                    615: 
                    616: /* This stuff was initialized in our caller (GraphCmd) */
                    617: /*  graph->tkwin = NULL; */
                    618: /*  graph->interp = NULL; */
                    619: /*  graph->flags = 0; */
                    620: 
                    621:   graph->x = NULL;
                    622:   graph->visible = 0;
                    623:   graph->w_x = graph->w_y = 0;
                    624:   graph->w_width = graph->w_height = 0;
                    625:   graph->pixmap = None;
                    626:   graph->pixels = NULL;
                    627:   graph->fontPtr = NULL;
                    628:   graph->border = NULL;
                    629:   graph->borderWidth = 0;
                    630:   graph->relief = TK_RELIEF_FLAT;
                    631:   graph->draw_graph_token = 0;
                    632: //fprintf(stderr, "InitNewGraph token %d\n", graph->draw_graph_token);
                    633: 
                    634:   graph->x = FindXDisplay(graph->tkwin);
                    635:   IncRefDisplay(graph->x);
                    636: 
                    637:   graph->pixels = graph->x->pixels;
                    638:   graph->fontPtr = NULL;
                    639: 
                    640:   DoResizeGraph(graph, 16, 16);
                    641: }
                    642: 
                    643: 
                    644: DestroyGraph(SimGraph *graph)
                    645: {
                    646:   SimGraph **gp;
                    647: 
                    648:   for (gp = &sim->graph;
                    649:        (*gp) != NULL;
                    650:        gp = &((*gp)->next)) {
                    651:     if ((*gp) == graph) {
                    652:       (*gp) = graph->next;
                    653:       sim->graphs--;
                    654:       break;
                    655:     }
                    656:   }
                    657: 
                    658:   if (graph->pixmap != None) {
                    659:     XFreePixmap(graph->x->dpy, graph->pixmap);
                    660:     graph->pixmap = None;
                    661:   }
                    662: 
                    663:   DecRefDisplay(graph->x);
                    664: 
                    665:   ckfree((char *) graph);
                    666: }
                    667: 
                    668: 
                    669: DoResizeGraph(SimGraph *graph, int w, int h)
                    670: {
                    671:   int resize = 0;
                    672: 
                    673:   graph->w_width = w; graph->w_height = h;
                    674: 
                    675:   if (graph->pixmap != None) {
                    676:     XFreePixmap(graph->x->dpy, graph->pixmap);
                    677:     graph->pixmap = None;
                    678:   }
                    679:   graph->pixmap = XCreatePixmap(graph->x->dpy, graph->x->root,
                    680:                                w, h, graph->x->depth);
                    681:   if (graph->pixmap == None) {
                    682:     fprintf(stderr,
                    683:            "Sorry, Micropolis can't create a pixmap on X display \"%s\".\n",
                    684:            graph->x->display);
                    685:     sim_exit(1); // Just sets tkMustExit and ExitReturn
                    686:     return;
                    687:   }
                    688: }
                    689: 
                    690: 
                    691: DoNewGraph(SimGraph *graph)
                    692: {
                    693:   sim->graphs++; graph->next = sim->graph; sim->graph = graph;
                    694: 
                    695:   NewGraph = 1;
                    696: }
                    697: 
                    698: 
                    699: #define BORDER 5
                    700: 
                    701: DoUpdateGraph(SimGraph *graph)
                    702: {
                    703:   Display *dpy;
                    704:   GC gc;
                    705:   Pixmap pm;
                    706:   int *pix;
                    707:   unsigned char **hist;
                    708:   int w, h, mask, i, j, x, y;
                    709:   XPoint points[121];
                    710:   int year = (CityTime / 48) + StartingYear;
                    711:   int month = (CityTime / 4) % 12;
                    712:   int do_top_labels = 0;
                    713:   int do_right_labels = 0;
                    714:   int top_label_height = 30;
                    715:   int right_label_width = 65;
                    716:   int tx, ty;
                    717:   float sx, sy;
                    718: 
                    719:   if (!graph->visible) {
                    720:     return;
                    721:   }
                    722: 
                    723:   if (graph->range == 10) {
                    724:     hist = History10;
                    725:   } else {
                    726:     hist = History120;
                    727:   }
                    728: 
                    729:   dpy = graph->x->dpy;
                    730:   gc = graph->x->gc;
                    731:   pm = graph->pixmap;
                    732:   pix = graph->pixels;
                    733: 
                    734:   w = graph->w_width;
                    735:   h = graph->w_height;
                    736: 
                    737:   XSetFont(graph->x->dpy, graph->x->gc, graph->fontPtr->fid);
                    738:   XSetLineAttributes(dpy, gc, 3, LineSolid, CapButt, JoinBevel);
                    739:   if (graph->x->color) {
                    740:     XSetForeground(dpy, gc, pix[COLOR_LIGHTGRAY]);
                    741:   } else {
                    742:     XSetForeground(dpy, gc, pix[COLOR_WHITE]);
                    743:   }
                    744:   XFillRectangle(dpy, pm, gc, 0, 0, w, h);
                    745: 
                    746:   tx = BORDER; ty = BORDER;
                    747: 
                    748:   if ((w -= (2 * BORDER)) < 1) w = 1;
                    749:   if ((h -= (2 * BORDER)) < 1) h = 1;
                    750: 
                    751:   if (w > (4 * right_label_width)) {
                    752:     w -= right_label_width;
                    753:     do_right_labels = 1;
                    754:   }
                    755: 
                    756:   if (do_right_labels &&
                    757:       (h > (3 * top_label_height))) {
                    758:     ty += top_label_height;
                    759:     h -= top_label_height;
                    760:     do_top_labels = 1;
                    761:   }
                    762: 
                    763:   sx = ((float)w) / 120.0; sy = ((float)h) / 256.0;
                    764: 
                    765:   mask = graph->mask;
                    766:   for (i = 0; i < HISTORIES; i++, mask >>= 1, hist++) {
                    767:     if (mask & 1) {
                    768:       int fg = COLOR_WHITE;
                    769:       int bg = COLOR_BLACK;
                    770:       Pixmap stipple = None;
                    771: 
                    772:       for (j = 0; j < 120; j++) {
                    773:        x = tx + (j * sx);
                    774:        y = ty + ((int)(h - (((float)(*hist)[j]) * sy)));
                    775:        points[j].x = x; points[j].y = y;
                    776:       }
                    777:       x = tx + (j * sx);
                    778:       points[j].x = x; points[j].y = y;
                    779: 
                    780:       if (graph->x->color) {
                    781:        XSetForeground(dpy, gc, pix[HistColor[i]]);
                    782:       } else {
                    783:        switch (i) {
                    784:        case 0: /* res */
                    785:          stipple = graph->x->gray50_stipple;
                    786:          break;
                    787:        case 1: /* com */
                    788:          stipple = graph->x->gray25_stipple;
                    789:          break;
                    790:        case 2: /* ind */
                    791:          stipple = graph->x->gray75_stipple;
                    792:          break;
                    793:        case 3: /* cash */
                    794:          fg = COLOR_BLACK;
                    795:          break;
                    796:        case 4: /* crime */
                    797:          stipple = graph->x->horiz_stipple;
                    798:          break;
                    799:        case 5: /* pol */
                    800:          stipple = graph->x->vert_stipple;
                    801:          break;
                    802:        }
                    803:        if (stipple != None) {
                    804:          XSetStipple(graph->x->dpy, gc, stipple);
                    805:          XSetTSOrigin(graph->x->dpy, gc, 0, 0);
                    806:          XSetForeground(graph->x->dpy, gc, pix[fg]);
                    807:          XSetBackground(graph->x->dpy, gc, pix[bg]);
                    808:          XSetFillStyle(graph->x->dpy, gc, FillOpaqueStippled);
                    809:        } else {
                    810:          XSetForeground(graph->x->dpy, gc, pix[fg]);
                    811:        }
                    812:       }
                    813: 
                    814:       XDrawLines(dpy, pm, gc, points, 121, CoordModeOrigin);
                    815: 
                    816:       if (!graph->x->color && (stipple != None)) {
                    817:        XSetFillStyle(graph->x->dpy, gc, FillSolid);
                    818:       }
                    819: 
                    820:       if (do_right_labels) {
                    821:        if (graph->x->color) {
                    822:          XSetForeground(dpy, gc, pix[HistColor[i]]);
                    823:          XDrawString(graph->x->dpy, pm, graph->x->gc,
                    824:                      x + 4, y + 5,
                    825:                      HistName[i], strlen(HistName[i]));
                    826:          XDrawString(graph->x->dpy, pm, graph->x->gc,
                    827:                      x + 5, y + 4,
                    828:                      HistName[i], strlen(HistName[i]));
                    829: 
                    830:          XSetForeground(dpy, gc, pix[COLOR_BLACK]);
                    831:          XDrawString(graph->x->dpy, pm, graph->x->gc,
                    832:                      x + 5, y + 5,
                    833:                      HistName[i], strlen(HistName[i]));
                    834:        } else {
                    835:          XSetForeground(dpy, gc, pix[COLOR_BLACK]);
                    836:          XDrawString(graph->x->dpy, pm, graph->x->gc,
                    837:                      x + 5, y + 5,
                    838:                      HistName[i], strlen(HistName[i]));
                    839:        }
                    840:       }
                    841:     }
                    842:   }
                    843: 
                    844:   XSetLineAttributes(dpy, gc, 1, LineSolid, CapButt, JoinMiter);
                    845: 
                    846:   XSetForeground(dpy, gc, pix[COLOR_BLACK]);
                    847:   XDrawLine(dpy, pm, gc, tx, ty - 1, tx + w, ty - 1);
                    848:   XDrawLine(dpy, pm, gc, tx, ty + h, tx + w, ty + h);
                    849: 
                    850:   if (graph->range == 10) {
                    851:     for (x = 120 - month; x >= 0; x -= 12) {
                    852:       int xx, yy;
                    853:       xx = tx + (x * sx);
                    854:       XDrawLine(dpy, pm, gc, xx, ty - 1, xx, ty + h);
                    855:       if (do_top_labels) {
                    856:        char buf[256];
                    857: 
                    858:        sprintf(buf, "%d", year--);
                    859:        xx = tx + (x * sx) + 2;
                    860:        yy = ty - ((year & 1) ? 4 : 20);
                    861:        XDrawString(graph->x->dpy, pm, graph->x->gc,
                    862:                    xx, yy, buf, strlen(buf));
                    863:       }
                    864:     }
                    865:   } else {
                    866:     int past;
                    867: 
                    868:     sx /= 10;
                    869:     past = 10 * (year % 10);
                    870:     year /= 10;
                    871: 
                    872:     for (x = 1200 - past; x >= 0; x -= 120) {
                    873:       int xx, yy;
                    874:       xx = tx + (x * sx);
                    875:       XDrawLine(dpy, pm, gc, xx, ty - 1, xx, ty + h);
                    876:       if (do_top_labels) {
                    877:        char buf[256];
                    878: 
                    879:        sprintf(buf, "%d0", year--);
                    880: 
                    881:        xx = tx + (x * sx) + 2;
                    882:        yy = ty - ((year & 1) ? 4 : 20);
                    883:        XDrawString(graph->x->dpy, pm, graph->x->gc,
                    884:                    xx, yy, buf, strlen(buf));
                    885:       }
                    886:     }
                    887:   }
                    888: 
                    889:   XCopyArea(graph->x->dpy, graph->pixmap,
                    890:            Tk_WindowId(graph->tkwin), graph->x->gc,
                    891:            0, 0, graph->w_width, graph->w_height, 0, 0);
                    892: }
                    893: 
                    894: 

unix.superglobalmegacorp.com

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