|
|
1.1 ! root 1: /* w_x.c: X Window System support ! 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: struct XDisplay *XDisplays = NULL; ! 66: int DisplayCount = 0; ! 67: #ifdef IS_LINUX ! 68: int FlushStyle = 3; ! 69: #else ! 70: int FlushStyle = 4; ! 71: #endif ! 72: int GotXError; ! 73: ! 74: ! 75: unsigned char ColorIntensities[] = { ! 76: /* COLOR_WHITE */ 255, ! 77: /* COLOR_YELLOW */ 170, ! 78: /* COLOR_ORANGE */ 127, ! 79: /* COLOR_RED */ 85, ! 80: /* COLOR_DARKRED */ 63, ! 81: /* COLOR_DARKBLUE */ 76, ! 82: /* COLOR_LIGHTBLUE */ 144, ! 83: /* COLOR_BROWN */ 118, ! 84: /* COLOR_LIGHTGREEN */ 76, ! 85: /* COLOR_DARKGREEN */ 42, ! 86: /* COLOR_OLIVE */ 118, ! 87: /* COLOR_LIGHTBROWN */ 144, ! 88: /* COLOR_LIGHTGRAY */ 191, ! 89: /* COLOR_MEDIUMGRAY */ 127, ! 90: /* COLOR_DARKGRAY */ 63, ! 91: /* COLOR_BLACK */ 0, ! 92: }; ! 93: ! 94: ! 95: ViewToTileCoords(SimView *view, int x, int y, int *outx, int *outy) ! 96: { ! 97: x = (view->pan_x - ((view->w_width >>1) - x)) >>4; ! 98: y = (view->pan_y - ((view->w_height >>1) - y)) >>4; ! 99: ! 100: if (x < 0) x = 0; ! 101: if (x >= WORLD_X) x = WORLD_X - 1; ! 102: if (y < 0) y = 0; ! 103: if (y >= WORLD_Y) y = WORLD_Y - 1; ! 104: ! 105: if (x < view->tile_x) ! 106: x = view->tile_x; ! 107: if (x >= view->tile_x + view->tile_width) ! 108: x = view->tile_x + view->tile_width - 1; ! 109: if (y < view->tile_y) ! 110: y = view->tile_y; ! 111: if (y >= view->tile_y + view->tile_height) ! 112: y = view->tile_y + view->tile_height - 1; ! 113: ! 114: if (view->tool_x_const != -1) ! 115: x = view->tool_x_const; ! 116: if (view->tool_y_const != -1) ! 117: y = view->tool_y_const; ! 118: ! 119: *outx = x; *outy = y; ! 120: } ! 121: ! 122: ! 123: ViewToPixelCoords(SimView *view, int x, int y, int *outx, int *outy) ! 124: { ! 125: x = view->pan_x - ((view->w_width >>1) - x); ! 126: y = view->pan_y - ((view->w_height >>1) - y); ! 127: ! 128: if (x < 0) x = 0; ! 129: if (x >= (WORLD_X <<4)) x = (WORLD_X <<4) - 1; ! 130: if (y < 0) y = 0; ! 131: if (y >= (WORLD_Y <<4)) y = (WORLD_Y <<4) - 1; ! 132: ! 133: if (x < (view->tile_x <<4)) ! 134: x = (view->tile_x <<4); ! 135: if (x >= ((view->tile_x + view->tile_width) <<4)) ! 136: x = ((view->tile_x + view->tile_width) <<4) - 1; ! 137: if (y < (view->tile_y <<4)) ! 138: y = (view->tile_y <<4); ! 139: if (y >= ((view->tile_y + view->tile_height) <<4)) ! 140: y = ((view->tile_y + view->tile_height) <<4) - 1; ! 141: ! 142: if (view->tool_x_const != -1) ! 143: x = (view->tool_x_const <<4) + 8; ! 144: if (view->tool_y_const != -1) ! 145: y = (view->tool_y_const <<4) + 8; ! 146: ! 147: *outx = x; *outy = y; ! 148: } ! 149: ! 150: ! 151: UpdateFlush() ! 152: { ! 153: struct XDisplay *xd; ! 154: ! 155: if (sim_skips > 0) { ! 156: if (sim_skip > 0) { ! 157: sim_skip--; ! 158: return; ! 159: } ! 160: sim_skip = sim_skips; ! 161: } ! 162: ! 163: switch (FlushStyle) { ! 164: ! 165: case 0: ! 166: break; ! 167: ! 168: case 1: ! 169: for (xd = XDisplays; xd != NULL; xd = xd->next) ! 170: XFlush(xd->dpy); ! 171: break; ! 172: ! 173: case 2: ! 174: for (xd = XDisplays; xd != NULL; xd = xd->next) ! 175: XSync(xd->dpy, False); ! 176: break; ! 177: ! 178: case 3: ! 179: if (XDisplays && XDisplays->next) { ! 180: for (xd = XDisplays; xd != NULL; xd = xd->next) { ! 181: XFlush(xd->dpy); ! 182: } ! 183: } ! 184: for (xd = XDisplays; xd != NULL; xd = xd->next) { ! 185: XSync(xd->dpy, False); ! 186: } ! 187: break; ! 188: ! 189: case 4: ! 190: for (xd = XDisplays; xd != NULL; xd = xd->next) { ! 191: #ifndef IS_LINUX ! 192: /* XXX TODO: figure this out for linux and new x libs */ ! 193: if ((xd->request != xd->dpy->request) || ! 194: (xd->last_request_read != xd->dpy->last_request_read)) { ! 195: XSync(xd->dpy, False); ! 196: xd->request = xd->dpy->request; ! 197: xd->last_request_read = xd->dpy->last_request_read; ! 198: } ! 199: #endif ! 200: } ! 201: break; ! 202: ! 203: } ! 204: } ! 205: ! 206: ! 207: int ! 208: CatchXError(Display *dpy, XErrorEvent *err) ! 209: { ! 210: GotXError = 1; ! 211: #if 0 ! 212: printf("GOT X ERROR code %d request code %d %d\n", ! 213: err->error_code, err->request_code, err->minor_code); ! 214: #endif ! 215: return (0); ! 216: } ! 217: ! 218: ! 219: DoStopMicropolis() ! 220: { ! 221: (void)XSetErrorHandler(CatchXError); ! 222: ! 223: StopToolkit(); ! 224: ! 225: if (sim) { ! 226: while (sim->editor != NULL) { ! 227: DestroyView(sim->editor); ! 228: } ! 229: ! 230: while (sim->map != NULL) { ! 231: DestroyView(sim->map); ! 232: } ! 233: ! 234: while (sim->graph != NULL) { ! 235: DestroyGraph(sim->graph); ! 236: } ! 237: ! 238: #ifdef CAM ! 239: while (sim->scam != NULL) { ! 240: DestroyCam(sim->scam); ! 241: } ! 242: #endif ! 243: } ! 244: } ! 245: ! 246: ! 247: DoTimeoutListen() ! 248: { ! 249: while (Tk_DoOneEvent(TK_DONT_WAIT)) ; ! 250: } ! 251: ! 252: ! 253: Sim * ! 254: MakeNewSim() ! 255: { ! 256: Sim *sim; ! 257: ! 258: sim = (Sim *)ckalloc(sizeof(Sim)); ! 259: sim->editors = 0; sim->editor = NULL; ! 260: sim->maps = 0; sim->map = NULL; ! 261: sim->graphs = 0; sim->graph = NULL; ! 262: sim->sprites = 0; sim->sprite = NULL; ! 263: #ifdef CAM ! 264: sim->scams = 0; sim->scam = NULL; ! 265: #endif ! 266: sim->overlay = NULL; ! 267: ! 268: return (sim); ! 269: } ! 270: ! 271: ! 272: XDisplay * ! 273: FindXDisplay(Tk_Window tkwin) ! 274: { ! 275: XDisplay *xd; ! 276: int d = 8; ! 277: unsigned long valuemask = 0; ! 278: XGCValues values; ! 279: XColor rgb, *color; ! 280: Display *dpy = Tk_Display(tkwin); ! 281: Screen *screen = Tk_Screen(tkwin); ! 282: #ifdef IS_LINUX ! 283: char *display = ":0"; /* XXX TODO: fix this for new x libs */ ! 284: #else ! 285: char *display = dpy->display_name; ! 286: #endif ! 287: ! 288: for (xd = XDisplays; ! 289: xd && (xd->screen != screen); ! 290: xd = xd->next) ; ! 291: ! 292: if (xd != NULL) { ! 293: return (xd); ! 294: } else { ! 295: xd = (struct XDisplay *)ckalloc(sizeof (struct XDisplay)); ! 296: ! 297: xd->references = 0; ! 298: xd->dpy = dpy; ! 299: xd->display = (char *)ckalloc(strlen(display) + 1); ! 300: xd->tkDisplay = ((TkWindow *)tkwin)->dispPtr; ! 301: strcpy(xd->display, display); ! 302: xd->screen = screen; ! 303: xd->root = RootWindowOfScreen(xd->screen); ! 304: ! 305: xd->visual = Tk_DefaultVisual(xd->screen); ! 306: xd->depth = Tk_DefaultDepth(xd->screen); ! 307: xd->colormap = Tk_DefaultColormap(xd->screen); ! 308: ! 309: xd->color = (xd->depth != 1); ! 310: ! 311: xd->pixels = (int *)ckalloc(16 * sizeof(int)); ! 312: if (xd->color) { /* Color screen */ ! 313: int GotColor = 1; ! 314: ! 315: #define GETCOLOR(i, name) \ ! 316: if (!GotColor) { \ ! 317: xd->pixels[i] = Rand16() & 255; \ ! 318: } else { \ ! 319: if ((color = Tk_GetColor(tk_mainInterp, tkwin, \ ! 320: None, name)) == NULL) { \ ! 321: xd->pixels[i] = Rand16() & 255; \ ! 322: GotColor = 0; \ ! 323: } else { \ ! 324: switch (xd->depth) { \ ! 325: case 8: \ ! 326: xd->pixels[i] = \ ! 327: color->pixel; \ ! 328: break; \ ! 329: case 15: \ ! 330: xd->pixels[i] = \ ! 331: (((color->red >> (8 + 3)) & 0x1f) << (5 + 5)) | \ ! 332: (((color->green >> (8 + 2)) & 0x1f) << (5)) | \ ! 333: (((color->blue >> (8 + 3)) & 0x1f) << (0)); \ ! 334: break; \ ! 335: case 16: \ ! 336: xd->pixels[i] = \ ! 337: (((color->red >> (8 + 3)) & 0x1f) << (6 + 5)) | \ ! 338: (((color->green >> (8 + 2)) & 0x3f) << (5)) | \ ! 339: (((color->blue >> (8 + 3)) & 0x1f) << (0)); \ ! 340: break; \ ! 341: case 24: \ ! 342: xd->pixels[i] = \ ! 343: ((color->red & 0xff) << 16) | \ ! 344: ((color->green & 0xff) << 8) | \ ! 345: ((color->blue & 0xff) << 0); \ ! 346: break; \ ! 347: case 32: \ ! 348: xd->pixels[i] = \ ! 349: ((color->red & 0xff) << 16) | \ ! 350: ((color->green & 0xff) << 8) | \ ! 351: ((color->blue & 0xff) << 0); \ ! 352: break; \ ! 353: } \ ! 354: } \ ! 355: } ! 356: ! 357: if ((xd->depth == 8) && ! 358: (Tk_DefaultColormap(xd->screen) == ! 359: DefaultColormapOfScreen(xd->screen))) { ! 360: xd->pixels[COLOR_WHITE] = WhitePixelOfScreen(xd->screen); ! 361: xd->pixels[COLOR_BLACK] = BlackPixelOfScreen(xd->screen); ! 362: } else { ! 363: GETCOLOR(COLOR_WHITE, "#ffffff"); ! 364: GETCOLOR(COLOR_BLACK, "#000000"); ! 365: } ! 366: ! 367: GETCOLOR(COLOR_YELLOW, "#ffff00"); ! 368: GETCOLOR(COLOR_ORANGE, "#ff7f00"); ! 369: GETCOLOR(COLOR_RED, "#ff0000"); ! 370: GETCOLOR(COLOR_DARKRED, "#bf0000"); ! 371: GETCOLOR(COLOR_DARKBLUE, "#0000e6"); ! 372: GETCOLOR(COLOR_LIGHTBLUE, "#6666e6"); ! 373: GETCOLOR(COLOR_BROWN, "#cc4c4c"); ! 374: GETCOLOR(COLOR_LIGHTGREEN, "#00e600"); ! 375: GETCOLOR(COLOR_DARKGREEN, "#007f00"); ! 376: GETCOLOR(COLOR_OLIVE, "#997f4c"); ! 377: GETCOLOR(COLOR_LIGHTBROWN, "#cc7f66"); ! 378: GETCOLOR(COLOR_LIGHTGRAY, "#bfbfbf"); ! 379: GETCOLOR(COLOR_MEDIUMGRAY, "#7f7f7f"); ! 380: GETCOLOR(COLOR_DARKGRAY, "#3f3f3f"); ! 381: ! 382: if (!GotColor) { ! 383: fprintf(stderr, ! 384: "Oh, dear. There don't seem to be enough free colors on X display \"%s\".\n", ! 385: xd->display); ! 386: fprintf(stderr, ! 387: "Micropolis will try to run anyway, but might look pretty weird!\n"); ! 388: } ! 389: } else { /* Black and white screen */ ! 390: int white = WhitePixelOfScreen(xd->screen); ! 391: int black = BlackPixelOfScreen(xd->screen); ! 392: ! 393: xd->pixels[COLOR_WHITE] = white; ! 394: xd->pixels[COLOR_BLACK] = black; ! 395: ! 396: xd->pixels[COLOR_YELLOW] = white; ! 397: xd->pixels[COLOR_ORANGE] = white; ! 398: xd->pixels[COLOR_RED] = white; ! 399: xd->pixels[COLOR_DARKRED] = black; ! 400: xd->pixels[COLOR_DARKBLUE] = black; ! 401: xd->pixels[COLOR_LIGHTBLUE] = white; ! 402: xd->pixels[COLOR_BROWN] = black; ! 403: xd->pixels[COLOR_LIGHTGREEN] = white; ! 404: xd->pixels[COLOR_DARKGREEN] = black; ! 405: xd->pixels[COLOR_OLIVE] = black; ! 406: xd->pixels[COLOR_LIGHTBROWN] = white; ! 407: xd->pixels[COLOR_LIGHTGRAY] = white; ! 408: xd->pixels[COLOR_MEDIUMGRAY] = white; ! 409: xd->pixels[COLOR_DARKGRAY] = black; ! 410: } ! 411: ! 412: xd->gc = Tk_DefaultGC(xd->screen); ! 413: XSetForeground(xd->dpy, xd->gc, xd->pixels[COLOR_BLACK]); ! 414: XSetBackground(xd->dpy, xd->gc, xd->pixels[COLOR_WHITE]); ! 415: XSetLineAttributes(xd->dpy, xd->gc, ! 416: 1, LineSolid, CapButt, JoinMiter); ! 417: XSetGraphicsExposures(xd->dpy, xd->gc, False); ! 418: ! 419: #ifndef MSDOS ! 420: { int major, minor, event, error, pixmaps; ! 421: if (WireMode || ! 422: (XQueryExtension(xd->dpy, "MIT-SHM", /* Jeez! */ ! 423: &major, &event, &error) != True) || ! 424: (XShmQueryVersion(xd->dpy, ! 425: &major, &minor, &pixmaps) != True)) { ! 426: fprintf(stderr, ! 427: "Darn, X display \"%s\" doesn't support the shared memory extension.\n", ! 428: xd->display); ! 429: xd->shared = 0; ! 430: } else { ! 431: if (!pixmaps) { ! 432: fprintf(stderr, ! 433: "Darn, X display \"%s\" claims to support the shared memory extension,\n", ! 434: xd->display); ! 435: fprintf(stderr, ! 436: "but is too lame to support shared memory pixmaps, so Micropolis will run slower.\n"); ! 437: fprintf(stderr, ! 438: "Please complain to your X server vendor, %s\n", ! 439: XServerVendor(xd->dpy)); ! 440: xd->shared = -1; ! 441: } else { ! 442: fprintf(stderr, ! 443: "Cool, I found the shared memory extension!\n"); ! 444: xd->shared = 1; ! 445: } ! 446: } ! 447: } ! 448: #else ! 449: xd->shared = 0; ! 450: #endif ! 451: ! 452: xd->request = -1; ! 453: xd->last_request_read = -1; ! 454: xd->big_tile_pixmap = None; ! 455: xd->objects = NULL; ! 456: xd->overlay_gc = NULL; ! 457: xd->gray25_stipple = None; ! 458: xd->gray50_stipple = None; ! 459: xd->gray75_stipple = None; ! 460: xd->vert_stipple = None; ! 461: xd->horiz_stipple = None; ! 462: xd->diag_stipple = None; ! 463: ! 464: xd->big_tile_image = xd->small_tile_image = NULL; ! 465: ! 466: xd->next = XDisplays; XDisplays = xd; ! 467: } ! 468: ! 469: return (xd); ! 470: } ! 471: ! 472: ! 473: IncRefDisplay(XDisplay *xd) ! 474: { ! 475: xd->references++; ! 476: } ! 477: ! 478: ! 479: DecRefDisplay(XDisplay *xd) ! 480: { ! 481: if ((--xd->references) == 0) { ! 482: /* I'd blow it away, but tk may still be using the display */ ! 483: } ! 484: } ! 485: ! 486: ! 487: SimView * ! 488: InitNewView(SimView *view, char *title, int class, int w, int h) ! 489: { ! 490: int type, i; ! 491: int d = 8; ! 492: unsigned long valuemask = 0; ! 493: char *t; ! 494: struct XDisplay *xd; ! 495: XGCValues values; ! 496: XColor rgb, *color; ! 497: ! 498: t = (char *)ckalloc(strlen(title) + 1); ! 499: strcpy(t, title); ! 500: ! 501: view->next = NULL; ! 502: view->title = t; ! 503: view->type = -1; ! 504: view->class = class; ! 505: view->bigtiles = view->smalltiles = NULL; ! 506: view->pixels = NULL; ! 507: view->line_bytes = 0; ! 508: view->line_bytes8 = 0; ! 509: view->pixel_bytes = 0; ! 510: view->depth = 0; ! 511: view->data = NULL; ! 512: view->data8 = NULL; ! 513: view->visible = 0; ! 514: view->invalid = 0; ! 515: view->skips = view->skip = 0; ! 516: view->update = 0; ! 517: view->map_state = ALMAP; ! 518: view->show_editors = 1; ! 519: view->tool_showing = 0; ! 520: view->tool_mode = 0; ! 521: view->tool_x = view->tool_y = 0; ! 522: view->tool_x_const = view->tool_y_const = -1; ! 523: view->tool_state = dozeState; ! 524: view->tool_state_save = -1; ! 525: view->super_user = 0; ! 526: view->show_me = 1; ! 527: view->dynamic_filter = 0; ! 528: view->auto_scroll_token = 0; ! 529: view->tool_event_time = 0; ! 530: view->tool_last_event_time = 0; ! 531: view->w_x = view->w_y = 0; ! 532: view->w_width = view->w_height = 16; ! 533: view->m_width = view->m_height = 0; ! 534: view->i_width = w; view->i_height = h; ! 535: view->pan_x = view->pan_y = 0; ! 536: view->tile_x = view->tile_y = 0; ! 537: view->tile_width = view->tile_height = 0; ! 538: view->screen_x = view->screen_y = 0; ! 539: view->screen_width = view->screen_height = 0; ! 540: view->last_x = view->last_y = view->last_button = 0; ! 541: view->track_info = NULL; ! 542: view->message_var = NULL; ! 543: ! 544: /* This stuff was initialized in our caller (SimViewCmd) */ ! 545: /* view->tkwin = NULL; */ ! 546: /* view->interp = NULL; */ ! 547: /* view->flags = 0; */ ! 548: ! 549: view->x = NULL; ! 550: view->shminfo = NULL; ! 551: view->tiles = NULL; ! 552: view->other_tiles = NULL; ! 553: view->image = NULL; ! 554: view->other_image = NULL; ! 555: view->other_data = NULL; ! 556: view->pixmap = None; ! 557: view->pixmap2 = None; ! 558: view->overlay_pixmap = None; ! 559: view->overlay_valid = 0; ! 560: view->fontPtr = NULL; ! 561: view->updates = 0; ! 562: view->update_real = view->update_user = view->update_system = 0.0; ! 563: view->update_context = 0; ! 564: view->auto_goto = 0; ! 565: view->auto_going = 0; ! 566: view->auto_x_goal = view->auto_x_goal = 0; ! 567: view->auto_speed = 75; ! 568: view->follow = NULL; ! 569: view->sound = 1; ! 570: view->width = 0; view->height = 0; ! 571: view->show_overlay = 1; ! 572: view->overlay_mode = 0; ! 573: ! 574: view->x = FindXDisplay(view->tkwin); ! 575: IncRefDisplay(view->x); ! 576: ! 577: /* view->x->shared is 1 if the shared memory extension is present and ! 578: supports shared memory pixmaps, and -1 if it is present but doesn't. */ ! 579: if (view->x->shared != 1) { ! 580: view->type = X_Wire_View; ! 581: } else { ! 582: view->type = X_Mem_View; ! 583: } ! 584: ! 585: GetPixmaps(view->x); ! 586: view->pixels = view->x->pixels; ! 587: ! 588: if (w == EDITOR_W) w = 256; /* XXX */ ! 589: if (h == EDITOR_H) h = 256; /* XXX */ ! 590: ! 591: view->pan_x = w / 2; view->pan_y = h / 2; ! 592: DoResizeView(view, w, h); ! 593: ! 594: GetViewTiles(view); ! 595: ! 596: return (view); ! 597: } ! 598: ! 599: ! 600: DestroyView(SimView *view) ! 601: { ! 602: SimView **vp; ! 603: ! 604: CancelRedrawView(view); ! 605: ! 606: for (vp = ((view->class == Editor_Class) ? ! 607: (&sim->editor) : (&sim->map)); ! 608: (*vp) != NULL; ! 609: vp = &((*vp)->next)) { ! 610: if ((*vp) == view) { ! 611: (*vp) = view->next; ! 612: if (view->class == Editor_Class) ! 613: sim->editors--; ! 614: else ! 615: sim->maps--; ! 616: ! 617: break; ! 618: } ! 619: } ! 620: ! 621: if (view->title != NULL) { ! 622: ckfree (view->title); ! 623: view->title = NULL; ! 624: } ! 625: ! 626: if (view->pixmap != None) { ! 627: XFreePixmap(view->x->dpy, view->pixmap); ! 628: view->pixmap = None; ! 629: } ! 630: ! 631: if (view->pixmap2 != None) { ! 632: XFreePixmap(view->x->dpy, view->pixmap2); ! 633: view->pixmap2 = None; ! 634: } ! 635: ! 636: if (view->overlay_pixmap != None) { ! 637: XFreePixmap(view->x->dpy, view->overlay_pixmap); ! 638: view->overlay_pixmap = None; ! 639: } ! 640: ! 641: if (view->auto_scroll_token) { ! 642: Tk_DeleteTimerHandler(view->auto_scroll_token); ! 643: view->auto_scroll_token = 0; ! 644: } ! 645: ! 646: #ifndef MSDOS ! 647: if (view->shminfo) { ! 648: XShmDetach(view->x->dpy, view->shminfo); ! 649: shmdt(view->shminfo->shmaddr); ! 650: shmctl(view->shminfo->shmid, IPC_RMID, 0); ! 651: ckfree(view->shminfo); ! 652: view->shminfo = NULL; ! 653: if (view->image) { ! 654: view->image->data = NULL; ! 655: view->data = NULL; ! 656: XDestroyImage(view->image); ! 657: view->image = NULL; ! 658: } ! 659: } else { ! 660: #endif ! 661: if (view->image) { ! 662: if (view->image->data) { ! 663: ckfree(view->image->data); ! 664: view->image->data = NULL; ! 665: } ! 666: view->data = NULL; ! 667: XDestroyImage(view->image); ! 668: view->image = NULL; ! 669: } ! 670: #ifndef MSDOS ! 671: } ! 672: #endif ! 673: ! 674: if (view->other_image) { ! 675: if (view->other_image->data) { ! 676: ckfree(view->other_image->data); ! 677: view->other_image->data = NULL; ! 678: } ! 679: view->other_data = NULL; ! 680: XDestroyImage(view->other_image); ! 681: view->other_image = NULL; ! 682: } ! 683: ! 684: if (view->tiles) ! 685: FreeTiles(view); ! 686: ! 687: DecRefDisplay(view->x); ! 688: ! 689: ckfree((char *) view); ! 690: } ! 691: ! 692: ! 693: unsigned char * ! 694: AllocPixels(int len, unsigned char pixel) ! 695: { ! 696: int i; ! 697: unsigned char *data, *cp; ! 698: ! 699: cp = data = (unsigned char *)ckalloc(len); ! 700: for (i = len; i > 0; i--) { ! 701: *(cp++) = pixel; ! 702: } ! 703: ! 704: return (data); ! 705: } ! 706: ! 707: ! 708: DoResizeView(SimView *view, int w, int h) ! 709: { ! 710: int resize = 0; ! 711: ! 712: view->w_width = w; ! 713: view->w_height = h; ! 714: ! 715: if (view->class == Map_Class) { /* Map_Class */ ! 716: view->m_width = w; ! 717: view->m_height = h; ! 718: ! 719: if (view->pixmap2 == None) { ! 720: ! 721: view->pixmap2 = XCreatePixmap(view->x->dpy, view->x->root, ! 722: w, h, view->x->depth); ! 723: if (view->pixmap2 == None) { ! 724: fprintf(stderr, ! 725: "Sorry, Micropolis can't create a pixmap on X display \"%s\"!\n", ! 726: view->x->display); ! 727: sim_exit(1); // Just sets tkMustExit and ExitReturn ! 728: return; ! 729: } ! 730: } ! 731: ! 732: } else { /* Editor_Class */ ! 733: ! 734: if ((w = (w + 31) & (~15)) > view->m_width) ! 735: view->m_width = w, resize++; ! 736: if ((h = (h + 31) & (~15)) > view->m_height) ! 737: view->m_height = h, resize++; ! 738: ! 739: if (resize || (view->pixmap2 == None)) { ! 740: if (view->pixmap2 != None) { ! 741: XFreePixmap(view->x->dpy, view->pixmap2); ! 742: view->pixmap2 = None; ! 743: } ! 744: view->pixmap2 = XCreatePixmap(view->x->dpy, view->x->root, ! 745: view->m_width, view->m_height, ! 746: view->x->depth); ! 747: if (view->pixmap2 == None) { ! 748: fprintf(stderr, ! 749: "Sorry, Micropolis couldn't create a pixmap on X display \"%s\"!\n", ! 750: view->x->display); ! 751: sim_exit(1); // Just sets tkMustExit and ExitReturn ! 752: return; ! 753: } ! 754: } ! 755: ! 756: if (resize || (view->overlay_pixmap == None)) { ! 757: view->overlay_mode = 0; ! 758: if (view->overlay_pixmap != None) { ! 759: XFreePixmap(view->x->dpy, view->overlay_pixmap); ! 760: view->overlay_pixmap = None; ! 761: } ! 762: view->overlay_pixmap = XCreatePixmap(view->x->dpy, view->x->root, ! 763: view->m_width, view->m_height, ! 764: 1); ! 765: if (view->overlay_pixmap == None) { ! 766: fprintf(stderr, ! 767: "Sorry, Micropolis couldn't create another pixmap on X display \"%s\".\n", ! 768: view->x->display); ! 769: sim_exit(1); // Just sets tkMustExit and ExitReturn ! 770: return; ! 771: } ! 772: if (view->x->overlay_gc == NULL) { ! 773: unsigned long valuemask = 0; ! 774: XGCValues values; ! 775: ! 776: view->x->overlay_gc = ! 777: XCreateGC(view->x->dpy, view->overlay_pixmap, valuemask, &values); ! 778: XSetForeground(view->x->dpy, view->x->overlay_gc, 0); ! 779: XSetBackground(view->x->dpy, view->x->overlay_gc, 1); ! 780: XSetLineAttributes(view->x->dpy, view->x->overlay_gc, ! 781: 1, LineSolid, CapButt, JoinMiter); ! 782: XSetGraphicsExposures(view->x->dpy, view->x->overlay_gc, False); ! 783: } ! 784: } ! 785: ! 786: } ! 787: ! 788: #ifndef MSDOS ! 789: if (view->type != X_Mem_View) { ! 790: goto SPRING_FORWARD; ! 791: } ! 792: ! 793: if (resize || (view->image == NULL)) { ! 794: if (view->shminfo && view->image) { ! 795: if (view->pixmap != None) { ! 796: XFreePixmap(view->x->dpy, view->pixmap); ! 797: view->pixmap = None; ! 798: } ! 799: XShmDetach(view->x->dpy, view->shminfo); ! 800: shmdt(view->shminfo->shmaddr); ! 801: shmctl(view->shminfo->shmid, IPC_RMID, 0); ! 802: view->image->data = NULL; ! 803: if (view->data == view->data8) ! 804: view->data8 = NULL; ! 805: view->data = NULL; ! 806: XDestroyImage(view->image); ! 807: view->image = NULL; ! 808: } ! 809: ! 810: #if 0 ! 811: /* XShmPixmapFormat is documented but does not exist !!! */ ! 812: if (XShmPixmapFormat(view->x->dpy) != ZPixmap) { ! 813: fprintf(stderr, ! 814: "Darn, display \"%s\" has the wrong shared memory format.\n", ! 815: view->x->display); ! 816: goto FALL_BACK; ! 817: } ! 818: #endif ! 819: ! 820: if (!view->shminfo) { ! 821: view->shminfo = (XShmSegmentInfo *)ckalloc(sizeof (XShmSegmentInfo)); ! 822: } ! 823: ! 824: view->image = ! 825: XShmCreateImage(view->x->dpy, view->x->visual, view->x->depth, ! 826: view->x->color ? ZPixmap : XYBitmap, ! 827: NULL, view->shminfo, ! 828: view->m_width, view->m_height); ! 829: ! 830: view->line_bytes = view->image->bytes_per_line; ! 831: ! 832: switch (view->x->depth) { ! 833: ! 834: case 1: ! 835: view->pixel_bytes = 0; ! 836: view->depth = 1; ! 837: break; ! 838: ! 839: case 8: ! 840: view->pixel_bytes = 1; ! 841: view->depth = 8; ! 842: break; ! 843: ! 844: case 15: ! 845: view->pixel_bytes = 2; ! 846: view->depth = 15; ! 847: break; ! 848: ! 849: case 16: ! 850: view->pixel_bytes = 2; ! 851: view->depth = 16; ! 852: break; ! 853: ! 854: case 24: ! 855: /* XXX: TODO: 24 and 32 bit support */ ! 856: view->pixel_bytes = 4; ! 857: //view->pixel_bytes = 3; ! 858: view->depth = 24; ! 859: break; ! 860: ! 861: case 32: ! 862: /* XXX: TODO: 24 and 32 bit support */ ! 863: view->pixel_bytes = 4; ! 864: view->depth = 32; ! 865: break; ! 866: ! 867: default: ! 868: view->pixel_bytes = 0; ! 869: view->depth = 0; ! 870: break; ! 871: ! 872: } // switch ! 873: ! 874: view->shminfo->shmid = shmget(IPC_PRIVATE, ! 875: (view->line_bytes * ! 876: view->m_height), ! 877: (IPC_CREAT | 0777)); ! 878: if (view->shminfo->shmid < 0) { ! 879: perror("shmget"); ! 880: fprintf(stderr, ! 881: "Darn, Micropolis can't share memory with X display \"%s\".\n", ! 882: view->x->display); ! 883: goto FALL_BACK; ! 884: } ! 885: ! 886: view->data = (unsigned char *)shmat(view->shminfo->shmid, 0, 0); ! 887: if ((int)view->data == -1) { ! 888: perror("shmat"); ! 889: fprintf(stderr, ! 890: "Darn, Micropolis can't find any memory to share with display \"%s\".\n", ! 891: view->x->display); ! 892: goto FALL_BACK; ! 893: } ! 894: ! 895: view->image->data = (char *)view->data; ! 896: view->shminfo->shmaddr = (char *)view->data; ! 897: view->shminfo->readOnly = False; ! 898: ! 899: { int (*old)(); ! 900: int result; ! 901: int attached = 0; ! 902: GotXError = 0; ! 903: old = XSetErrorHandler(CatchXError); ! 904: ! 905: result = ! 906: XShmAttach(view->x->dpy, view->shminfo); ! 907: if (result == 0) { ! 908: fprintf(stderr, ! 909: "Darn, the X display \"%s\" can't access Micropolis's shared memory.\n", ! 910: view->x->display); ! 911: GotXError = 1; ! 912: } ! 913: ! 914: XSync(view->x->dpy, False); ! 915: ! 916: if (!GotXError) { ! 917: attached = 1; ! 918: view->pixmap = XShmCreatePixmap(view->x->dpy, view->x->root, ! 919: view->data, view->shminfo, ! 920: view->m_width, view->m_height, ! 921: view->x->depth); ! 922: XSync(view->x->dpy, False); ! 923: ! 924: if (GotXError || ! 925: (view->pixmap == None)) { ! 926: fprintf(stderr, ! 927: "Darn, Micropolis couldn't get a shared memory pixmap on X display \"%s\".\n", ! 928: view->x->display); ! 929: GotXError = 1; ! 930: } ! 931: } ! 932: ! 933: XSetErrorHandler(old); ! 934: ! 935: if (GotXError) { ! 936: view->pixmap = None; ! 937: if (attached) { ! 938: XShmDetach(view->x->dpy, view->shminfo); ! 939: } // if ! 940: result = shmdt(view->shminfo->shmaddr); ! 941: result = shmctl(view->shminfo->shmid, IPC_RMID, 0); ! 942: ckfree(view->shminfo); ! 943: view->shminfo = NULL; ! 944: if (view->image) { ! 945: view->image->data = NULL; ! 946: view->data = NULL; ! 947: XDestroyImage(view->image); ! 948: view->image = NULL; ! 949: } ! 950: goto FALL_BACK; ! 951: } ! 952: ! 953: if (view->x->color) { ! 954: XSetForeground(view->x->dpy, view->x->gc, ! 955: view->pixels[COLOR_LIGHTBROWN]); ! 956: } else { ! 957: XSetForeground(view->x->dpy, view->x->gc, ! 958: view->pixels[COLOR_WHITE]); ! 959: } ! 960: ! 961: XFillRectangle(view->x->dpy, view->pixmap, view->x->gc, ! 962: 0, 0, view->m_width, view->m_height); ! 963: } ! 964: } ! 965: ! 966: goto FINISH; ! 967: ! 968: FALL_BACK: ! 969: ! 970: fprintf(stderr, ! 971: "Falling back to the X network protocol on display \"%s\"...\n", ! 972: view->x->display); ! 973: #endif ! 974: ! 975: view->x->shared = 0; ! 976: view->type = X_Wire_View; ! 977: if (view->pixmap != None) { ! 978: XFreePixmap(view->x->dpy, view->pixmap); ! 979: view->pixmap = None; ! 980: } ! 981: #ifndef MSDOS ! 982: if (view->shminfo) { ! 983: if (view->shminfo->shmid >= 0) { ! 984: if (view->shminfo->shmaddr) { ! 985: shmdt(view->shminfo->shmaddr); ! 986: } ! 987: shmctl(view->shminfo->shmid, IPC_RMID, 0); ! 988: } ! 989: ckfree((char *)view->shminfo); ! 990: view->shminfo = NULL; ! 991: } ! 992: #endif ! 993: if (view->image) { ! 994: view->image->data = NULL; ! 995: XDestroyImage(view->image); ! 996: view->image = NULL; ! 997: } ! 998: view->data = NULL; ! 999: view->line_bytes = 0; ! 1000: view->pixel_bytes = 0; ! 1001: view->depth = 0; ! 1002: ! 1003: SPRING_FORWARD: ! 1004: ! 1005: if (resize || (view->pixmap == None)) { ! 1006: if (view->pixmap != None) { ! 1007: XFreePixmap(view->x->dpy, view->pixmap); ! 1008: view->pixmap = None; ! 1009: } ! 1010: view->pixmap = XCreatePixmap(view->x->dpy, view->x->root, ! 1011: view->m_width, view->m_height, ! 1012: view->x->depth); ! 1013: if (view->pixmap == None) { ! 1014: fprintf(stderr, ! 1015: "Sorry, Micropolis can't create pixmap on X display \"%s\".\n", ! 1016: view->x->display); ! 1017: sim_exit(1); // Just sets tkMustExit and ExitReturn ! 1018: return; ! 1019: } ! 1020: if (view->x->color) { ! 1021: XSetForeground(view->x->dpy, view->x->gc, ! 1022: view->pixels[COLOR_LIGHTBROWN]); ! 1023: } else { ! 1024: XSetForeground(view->x->dpy, view->x->gc, ! 1025: view->pixels[COLOR_WHITE]); ! 1026: } ! 1027: XFillRectangle(view->x->dpy, view->pixmap, view->x->gc, ! 1028: 0, 0, view->m_width, view->m_height); ! 1029: } ! 1030: ! 1031: FINISH: ! 1032: ! 1033: if (view->class == Editor_Class) { ! 1034: ! 1035: AllocTiles(view); ! 1036: DoAdjustPan(view); ! 1037: ! 1038: } else if (view->class == Map_Class) { ! 1039: ! 1040: if (view->type == X_Mem_View) { /* Memory Map */ ! 1041: ! 1042: if (view->x->color) { ! 1043: ! 1044: /* Color, Shared Memory */ ! 1045: ! 1046: view->data8 = view->data; ! 1047: view->line_bytes8 = view->line_bytes; /* XXX: ??? */ ! 1048: ! 1049: switch (view->x->depth) { ! 1050: ! 1051: case 8: ! 1052: view->pixel_bytes = 1; ! 1053: view->depth = 8; ! 1054: break; ! 1055: ! 1056: case 15: ! 1057: view->pixel_bytes = 2; ! 1058: view->depth = 15; ! 1059: break; ! 1060: ! 1061: case 16: ! 1062: view->pixel_bytes = 2; ! 1063: view->depth = 16; ! 1064: break; ! 1065: ! 1066: case 24: ! 1067: /* XXX: TODO: 24 and 32 bit support */ ! 1068: view->pixel_bytes = 4; ! 1069: //view->pixel_bytes = 3; ! 1070: view->depth = 24; ! 1071: break; ! 1072: ! 1073: case 32: ! 1074: /* XXX: TODO: 24 and 32 bit support */ ! 1075: view->pixel_bytes = 4; ! 1076: view->depth = 32; ! 1077: break; ! 1078: ! 1079: default: ! 1080: view->pixel_bytes = 0; ! 1081: view->depth = 0; ! 1082: break; ! 1083: ! 1084: } // switch ! 1085: ! 1086: } else { ! 1087: ! 1088: /* Black and White, Shared Memory */ ! 1089: ! 1090: if (view->other_image != NULL) { ! 1091: XDestroyImage(view->other_image); ! 1092: } ! 1093: ! 1094: view->line_bytes8 = view->m_width; /* XXX: fix depth */ ! 1095: view->pixel_bytes = 0; ! 1096: view->depth = 1; ! 1097: ! 1098: view->other_data = view->data8 = ! 1099: AllocPixels(view->m_height * view->line_bytes8, /* XXX: fix depth */ ! 1100: view->pixels[COLOR_WHITE]); ! 1101: view->other_image = ! 1102: XCreateImage(view->x->dpy, view->x->visual, 8, /* XXX: fix depth */ ! 1103: ZPixmap, 0, (char *)view->other_data, ! 1104: view->m_width, view->m_height, ! 1105: 8, view->line_bytes8); /* XXX: fix depth */ ! 1106: } ! 1107: ! 1108: } else { /* Wire Map */ ! 1109: int bitmap_pad; ! 1110: int bitmap_depth; ! 1111: ! 1112: if (view->image != NULL) { ! 1113: XDestroyImage(view->image); ! 1114: view->image = NULL; ! 1115: } ! 1116: ! 1117: if (view->other_image != NULL) { ! 1118: XDestroyImage(view->other_image); ! 1119: view->other_image = NULL; ! 1120: } ! 1121: ! 1122: if (view->x->color) { ! 1123: ! 1124: /* Color, Wire */ ! 1125: ! 1126: switch (view->x->depth) { ! 1127: ! 1128: case 8: ! 1129: view->pixel_bytes = 1; ! 1130: view->depth = 8; ! 1131: bitmap_pad = 8; ! 1132: bitmap_depth = 8; ! 1133: view->line_bytes8 = ! 1134: ((view->m_width * view->pixel_bytes) + 3) & (~3); ! 1135: break; ! 1136: ! 1137: case 15: ! 1138: view->pixel_bytes = 2; ! 1139: view->depth = 15; ! 1140: bitmap_pad = 16; ! 1141: bitmap_depth = 16; ! 1142: view->line_bytes8 = ! 1143: ((view->m_width * view->pixel_bytes) + 3) & (~3); ! 1144: break; ! 1145: ! 1146: case 16: ! 1147: view->pixel_bytes = 2; ! 1148: view->depth = 16; ! 1149: bitmap_pad = 16; ! 1150: bitmap_depth = 16; ! 1151: view->line_bytes8 = ! 1152: ((view->m_width * view->pixel_bytes) + 3) & (~3); ! 1153: break; ! 1154: ! 1155: case 24: ! 1156: view->pixel_bytes = 4; ! 1157: //view->pixel_bytes = 3; ! 1158: view->depth = 24; ! 1159: bitmap_depth = 32; ! 1160: bitmap_pad = 32; ! 1161: view->line_bytes8 = ! 1162: ((view->m_width * 4) + 3) & (~3); ! 1163: break; ! 1164: ! 1165: case 32: ! 1166: view->pixel_bytes = 4; ! 1167: view->depth = 32; ! 1168: bitmap_pad = 32; ! 1169: bitmap_depth = 32; ! 1170: view->line_bytes8 = ! 1171: ((view->m_width * 4) + 3) & (~3); ! 1172: break; ! 1173: ! 1174: default: ! 1175: assert(0); /* Unknown depth */ ! 1176: break; ! 1177: ! 1178: } // switch ! 1179: ! 1180: view->line_bytes = ! 1181: view->line_bytes8; ! 1182: ! 1183: } else { ! 1184: ! 1185: /* Black and White, Wire */ ! 1186: ! 1187: view->pixel_bytes = 0; ! 1188: view->depth = 1; ! 1189: view->line_bytes8 = ! 1190: (view->m_width + 3) & (~3); /* XXX: handle depth */ ! 1191: view->line_bytes = ! 1192: (view->m_width + 7) >>3; ! 1193: bitmap_pad = 8; ! 1194: bitmap_depth = 8; ! 1195: ! 1196: } ! 1197: ! 1198: view->data = ! 1199: AllocPixels(view->m_height * view->line_bytes, 0); ! 1200: view->image = ! 1201: XCreateImage(view->x->dpy, view->x->visual, ! 1202: bitmap_depth, ! 1203: view->x->color ? ZPixmap : XYBitmap, ! 1204: 0, (char *)view->data, ! 1205: view->m_width, view->m_height, ! 1206: bitmap_pad, ! 1207: view->line_bytes); ! 1208: ! 1209: view->other_data = ! 1210: AllocPixels(view->m_height * view->line_bytes8, 0); ! 1211: view->other_image = ! 1212: XCreateImage(view->x->dpy, view->x->visual, ! 1213: bitmap_depth, ! 1214: ZPixmap, ! 1215: 0, (char *)view->other_data, ! 1216: view->m_width, view->m_height, ! 1217: bitmap_pad, ! 1218: view->line_bytes); ! 1219: ! 1220: if (view->x->color) { ! 1221: view->data8 = view->data; ! 1222: } else { ! 1223: view->data8 = view->other_data; ! 1224: } ! 1225: } ! 1226: } ! 1227: } ! 1228: ! 1229: ! 1230: DoPanBy(struct SimView *view, int dx, int dy) ! 1231: { ! 1232: DoPanTo(view, view->pan_x + dx, view->pan_y + dy); ! 1233: } ! 1234: ! 1235: ! 1236: DoPanTo(struct SimView *view, int x, int y) ! 1237: { ! 1238: if (view->class != Editor_Class) { ! 1239: return; ! 1240: } ! 1241: ! 1242: if (x < 0) x = 0; ! 1243: if (y < 0) y = 0; ! 1244: if (x > view->i_width) x = view->i_width - 1; ! 1245: if (y > view->i_height) y = view->i_height - 1; ! 1246: if ((view->pan_x != x) || ! 1247: (view->pan_y != y)) { ! 1248: view->pan_x = x; ! 1249: view->pan_y = y; ! 1250: DoAdjustPan(view); ! 1251: } ! 1252: } ! 1253: ! 1254: /* #define DEBUG_PAN */ ! 1255: ! 1256: DoAdjustPan(struct SimView *view) ! 1257: { ! 1258: int ww2 = view->w_width >>1, wh2 = view->w_height >>1; ! 1259: int px = view->pan_x, py = view->pan_y; ! 1260: int last_tile_x = view->tile_x, last_tile_y = view->tile_y; ! 1261: int last_tile_width = view->tile_width, last_tile_height = view->tile_height; ! 1262: int total_width = view->m_width >>4, total_height = view->m_height >>4; ! 1263: //fprintf(stderr, "DoAdjustPan\n"); ! 1264: ! 1265: #ifdef DEBUG_PAN ! 1266: printf("AdjustPan window %d %d ww2 %d wh2 %d pan %d %d\n", ! 1267: view->w_width, view->w_height, ww2, wh2, px, py); ! 1268: printf(" last tile %d %d %d %d\n", ! 1269: last_tile_x, last_tile_y, last_tile_width, last_tile_height); ! 1270: #endif ! 1271: ! 1272: if ((view->tile_x = ((px - ww2) >>4)) < 0) ! 1273: view->tile_x = 0; ! 1274: if ((view->tile_y = ((py - wh2) >>4)) < 0) ! 1275: view->tile_y = 0; ! 1276: ! 1277: #ifdef DEBUG_PAN ! 1278: printf(" now tile %d %d\n", view->tile_x, view->tile_y); ! 1279: #endif ! 1280: ! 1281: view->tile_width = ((15 + px + ww2) >>4); ! 1282: view->tile_height = ((15 + py + wh2) >>4); ! 1283: ! 1284: #ifdef DEBUG_PAN ! 1285: printf(" outer tile %d %d\n", view->tile_width, view->tile_height); ! 1286: #endif ! 1287: ! 1288: if (view->tile_width > (view->i_width >>4)) ! 1289: view->tile_width = (view->i_width >>4); ! 1290: view->tile_width -= view->tile_x; ! 1291: if (view->tile_height > (view->i_height >>4)) ! 1292: view->tile_height = (view->i_height >>4); ! 1293: view->tile_height -= view->tile_y; ! 1294: ! 1295: #ifdef DEBUG_PAN ! 1296: printf(" tile size %d %d\n", view->tile_width, view->tile_height); ! 1297: #endif ! 1298: ! 1299: if (view->tile_width > (view->m_width >>4)) ! 1300: view->tile_width = (view->m_width >>4); ! 1301: if (view->tile_height > (view->m_height >>4)) ! 1302: view->tile_height = (view->m_height >>4); ! 1303: ! 1304: #ifdef DEBUG_PAN ! 1305: printf(" clipped size %d %d\n", view->tile_width, view->tile_height); ! 1306: printf(" maximum size %d %d\n", view->m_width >>4, view->m_height >>4); ! 1307: #endif ! 1308: ! 1309: view->screen_x = (ww2 - px) + (view->tile_x <<4); ! 1310: view->screen_y = (wh2 - py) + (view->tile_y <<4); ! 1311: view->screen_width = (view->tile_width <<4); ! 1312: view->screen_height = (view->tile_height <<4); ! 1313: ! 1314: #ifdef DEBUG_PAN ! 1315: printf(" screen %d %d %d %d\n", ! 1316: view->screen_x, view->screen_y, ! 1317: view->screen_width, view->screen_height); ! 1318: #endif ! 1319: ! 1320: view->overlay_mode = 0; ! 1321: // view->skip = 0; ! 1322: view->invalid = 1; ! 1323: if (SimSpeed == 0) { ! 1324: EventuallyRedrawView(view); ! 1325: } ! 1326: /* InvalidateEditors(); */ ! 1327: if (view->show_me) { ! 1328: RedrawMaps(); ! 1329: } ! 1330: /* FixMicropolisTimer(); */ ! 1331: ! 1332: { int dx = last_tile_x - view->tile_x, ! 1333: dy = last_tile_y - view->tile_y; ! 1334: short **want = view->other_tiles, ! 1335: **have = view->tiles; ! 1336: ! 1337: #ifdef DEBUG_PAN ! 1338: printf("scrolling %d %d\n", dx, dy); ! 1339: #endif ! 1340: ! 1341: if ((dx != 0) || (dy != 0)) { ! 1342: int row, col, x, y, ! 1343: width = view->tile_width, ! 1344: height = view->tile_height; ! 1345: ! 1346: for (col = 0; col < width; col++) ! 1347: memcpy(want[col], have[col], (height * sizeof(short))); ! 1348: ! 1349: for (col = 0; col < total_width; col++) { ! 1350: x = col - dx; ! 1351: for (row = 0; row < total_height; row++) { ! 1352: y = row - dy; ! 1353: if ((x >= 0) && (x < width) && ! 1354: (y >= 0) && (y < height)) { ! 1355: have[col][row] = want[x][y]; ! 1356: } else { ! 1357: have[col][row] = -1; ! 1358: } ! 1359: } ! 1360: } ! 1361: ! 1362: XCopyArea(view->x->dpy, view->pixmap, view->pixmap, view->x->gc, ! 1363: 0, 0, view->tile_width <<4, view->tile_height <<4, ! 1364: dx <<4, dy <<4); ! 1365: ! 1366: if (view->type == X_Mem_View) { ! 1367: XSync(view->x->dpy, False); ! 1368: } ! 1369: } ! 1370: } ! 1371: } ! 1372: ! 1373: ! 1374: AllocTiles(SimView *view) ! 1375: { ! 1376: int row, col; ! 1377: short **have, **want; ! 1378: int w = view->m_width / 16, h = view->m_height / 16; ! 1379: int n = (w + 1) * sizeof (short *); ! 1380: ! 1381: if (view->tiles) ! 1382: FreeTiles(view); ! 1383: ! 1384: have = view->tiles = ! 1385: (short **)ckalloc(n); ! 1386: ! 1387: want = view->other_tiles = ! 1388: (short **)ckalloc(n); ! 1389: ! 1390: have[w] = want[w] = NULL; ! 1391: ! 1392: n = h * sizeof(short); ! 1393: for (col = 0; col < w; col++) { ! 1394: ! 1395: have[col] = (short *)ckalloc(n); ! 1396: want[col] = (short *)ckalloc(n); ! 1397: for (row = 0; row < h; row++) { ! 1398: have[col][row] = -1; ! 1399: want[col][row] = -1; ! 1400: } ! 1401: } ! 1402: } ! 1403: ! 1404: ! 1405: FreeTiles(SimView *view) ! 1406: { ! 1407: int col; ! 1408: ! 1409: for (col = 0; view->tiles[col] != NULL; col++) { ! 1410: ckfree ((char *)view->tiles[col]); ! 1411: ckfree ((char *)view->other_tiles[col]); ! 1412: } ! 1413: ckfree ((char *)view->tiles); ! 1414: view->tiles = NULL; ! 1415: ckfree ((char *)view->other_tiles); ! 1416: view->other_tiles = NULL; ! 1417: } ! 1418: ! 1419: ! 1420: #define POINT_BATCH 32 ! 1421: ! 1422: Ink *OldInk = NULL; ! 1423: ! 1424: ! 1425: /* XXX: todo: ink locking so someone doesn't erase ink that's being drawn */ ! 1426: ! 1427: Ink * ! 1428: NewInk() ! 1429: { ! 1430: Ink *ink; ! 1431: ! 1432: if (OldInk) { ! 1433: ink = OldInk; ! 1434: OldInk = OldInk->next; ! 1435: } else { ! 1436: ink = (Ink *)ckalloc(sizeof(Ink)); ! 1437: ink->maxlength = POINT_BATCH; ! 1438: ink->points = (XPoint *)ckalloc(POINT_BATCH * sizeof(XPoint)); ! 1439: } ! 1440: ink->length = 0; ! 1441: ink->color = COLOR_WHITE; ! 1442: ink->next = NULL; ! 1443: ink->left = ink->right = ink->top = ink->bottom = ! 1444: ink->last_x = ink->last_y = -1; ! 1445: return (ink); ! 1446: } ! 1447: ! 1448: ! 1449: FreeInk(Ink *ink) ! 1450: { ! 1451: ink->next = OldInk; ! 1452: OldInk = ink; ! 1453: } ! 1454: ! 1455: ! 1456: StartInk(Ink *ink, int x, int y) ! 1457: { ! 1458: ink->length = 1; ! 1459: ink->left = ink->right = ink->last_x = ink->points[0].x = x; ! 1460: ink->top = ink->bottom = ink->last_y = ink->points[0].y = y; ! 1461: } ! 1462: ! 1463: ! 1464: AddInk(Ink *ink, int x, int y) ! 1465: { ! 1466: int dx = x - ink->last_x; ! 1467: int dy = y - ink->last_y; ! 1468: ! 1469: if ((dx != 0) || (dy != 0)) { ! 1470: /* ! 1471: if (ink->length > 1) { ! 1472: if ((dx == 0) && ! 1473: (ink->points[ink->length - 1].x == 0) && ! 1474: ((ink->points[ink->length - 1].y < 0) ? ! 1475: (dy < 0) : (dy > 0))) { ! 1476: ink->points[ink->length - 1].y += dy; ! 1477: goto ADJUST; ! 1478: } else if ((dy == 0) && ! 1479: (ink->points[ink->length - 1].y == 0) && ! 1480: ((ink->points[ink->length - 1].x < 0) ? ! 1481: (dx < 0) : (dx > 0))) { ! 1482: ink->points[ink->length - 1].x += dx; ! 1483: goto ADJUST; ! 1484: } ! 1485: } ! 1486: */ ! 1487: ! 1488: if (ink->length >= ink->maxlength) { ! 1489: ink->maxlength += POINT_BATCH; ! 1490: ink->points = (XPoint *)realloc((void *)ink->points, ! 1491: ink->maxlength * sizeof(XPoint)); ! 1492: } ! 1493: ink->points[ink->length].x = dx; ! 1494: ink->points[ink->length].y = dy; ! 1495: ink->length++; ! 1496: ! 1497: ADJUST: ! 1498: if (x < ink->left) ! 1499: ink->left = x; ! 1500: if (x > ink->right) ! 1501: ink->right = x; ! 1502: if (y < ink->top) ! 1503: ink->top = y; ! 1504: if (y > ink->bottom) ! 1505: ink->bottom = y; ! 1506: ! 1507: { int left, right, top, bottom; ! 1508: SimView *view; ! 1509: ! 1510: if (ink->last_x < x) { left = ink->last_x; right = x; } ! 1511: else { left = x; right = ink->last_x; } ! 1512: if (ink->last_y < y) { top = ink->last_y; bottom = y; } ! 1513: else { top = y; bottom = ink->last_y; } ! 1514: ! 1515: left -= 5; right += 5; top -= 5; bottom += 5; ! 1516: ! 1517: for (view = sim->editor; view != NULL; view = view->next) { ! 1518: int vleft, vtop; ! 1519: ! 1520: if ((right >= (vleft = view->pan_x - (view->w_width / 2))) && ! 1521: (left <= vleft + view->w_width) && ! 1522: (bottom >= (vtop = view->pan_y - (view->w_height / 2))) && ! 1523: (top <= vtop + view->w_height)) { ! 1524: /* XXX: do studly incremental update instead */ ! 1525: view->overlay_mode = 0; ! 1526: EventuallyRedrawView(view); ! 1527: } ! 1528: } ! 1529: } ! 1530: ink->last_x = x; ink->last_y = y; ! 1531: } ! 1532: } ! 1533: ! 1534: ! 1535: EraseOverlay() ! 1536: { ! 1537: Ink *ink; ! 1538: ! 1539: while (sim->overlay) { ! 1540: ink = sim->overlay; ! 1541: sim->overlay = ink->next; ! 1542: FreeInk(ink); ! 1543: } ! 1544: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.