|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.