]>
cvs.zerfleddert.de Git - micropolis/blob - src/sim/w_x.c
   1 /* w_x.c:  X Window System support 
   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  micropolis@laptop.org. 
   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. 
  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/>. 
  21  *             ADDITIONAL TERMS per GNU GPL Section 7 
  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. 
  29  * Any propagation or conveyance of this program must include this 
  30  * copyright notice and these terms. 
  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. 
  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. 
  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 
  65 struct XDisplay 
*XDisplays 
= NULL
; 
  75 unsigned char ColorIntensities
[] = { 
  76         /* COLOR_WHITE */               255, 
  77         /* COLOR_YELLOW */              170, 
  78         /* COLOR_ORANGE */              127, 
  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, 
  95 ViewToTileCoords(SimView 
*view
, int x
, int y
, int *outx
, int *outy
) 
  97   x 
= (view
->pan_x 
- ((view
->w_width 
>>1) - x
)) >>4; 
  98   y 
= (view
->pan_y 
- ((view
->w_height 
>>1) - y
)) >>4; 
 101   if (x 
>= WORLD_X
) x 
= WORLD_X 
- 1; 
 103   if (y 
>= WORLD_Y
) y 
= WORLD_Y 
- 1; 
 105   if (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
) 
 111   if (y 
>= view
->tile_y 
+ view
->tile_height
) 
 112     y 
= view
->tile_y 
+ view
->tile_height 
- 1; 
 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
; 
 119   *outx 
= x
; *outy 
= y
; 
 123 ViewToPixelCoords(SimView 
*view
, int x
, int y
, int *outx
, int *outy
) 
 125   x 
= view
->pan_x 
- ((view
->w_width 
>>1) - x
); 
 126   y 
= view
->pan_y 
- ((view
->w_height 
>>1) - y
); 
 129   if (x 
>= (WORLD_X 
<<4)) x 
= (WORLD_X 
<<4) - 1; 
 131   if (y 
>= (WORLD_Y 
<<4)) y 
= (WORLD_Y 
<<4) - 1; 
 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; 
 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; 
 147   *outx 
= x
; *outy 
= y
; 
 160     sim_skip 
= sim_skips
; 
 163   switch (FlushStyle
) { 
 169     for (xd 
= XDisplays
; xd 
!= NULL
; xd 
= xd
->next
) 
 174     for (xd 
= XDisplays
; xd 
!= NULL
; xd 
= xd
->next
) 
 175       XSync(xd
->dpy
, False
); 
 179     if (XDisplays 
&& XDisplays
->next
) { 
 180       for (xd 
= XDisplays
; xd 
!= NULL
; xd 
= xd
->next
) { 
 184     for (xd 
= XDisplays
; xd 
!= NULL
; xd 
= xd
->next
) { 
 185       XSync(xd
->dpy
, False
); 
 190     for (xd 
= XDisplays
; xd 
!= NULL
; xd 
= xd
->next
) { 
 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
; 
 208 CatchXError(Display 
*dpy
, XErrorEvent 
*err
) 
 212 printf("GOT X ERROR code %d request code %d %d\n", 
 213        err
->error_code
, err
->request_code
, err
->minor_code
); 
 221   (void)XSetErrorHandler(CatchXError
); 
 226     while (sim
->editor 
!= NULL
) { 
 227       DestroyView(sim
->editor
); 
 230     while (sim
->map 
!= NULL
) { 
 231       DestroyView(sim
->map
); 
 234     while (sim
->graph 
!= NULL
) { 
 235       DestroyGraph(sim
->graph
); 
 239     while (sim
->scam 
!= NULL
) { 
 240       DestroyCam(sim
->scam
); 
 249   while (Tk_DoOneEvent(TK_DONT_WAIT
)) ; 
 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
; 
 264   sim
->scams 
= 0; sim
->scam 
= NULL
; 
 273 FindXDisplay(Tk_Window tkwin
) 
 277   unsigned long valuemask 
= 0; 
 280   Display 
*dpy 
= Tk_Display(tkwin
); 
 281   Screen 
*screen 
= Tk_Screen(tkwin
); 
 283   char *display 
= ":0"; /* XXX TODO: fix this for new x libs */ 
 285   char *display 
= dpy
->display_name
; 
 289        xd 
&& (xd
->screen 
!= screen
); 
 295     xd 
= (struct XDisplay 
*)ckalloc(sizeof (struct XDisplay
)); 
 299     xd
->display 
= (char *)ckalloc(strlen(display
) + 1); 
 300     xd
->tkDisplay 
= ((TkWindow 
*)tkwin
)->dispPtr
; 
 301     strcpy(xd
->display
, display
); 
 303     xd
->root 
= RootWindowOfScreen(xd
->screen
); 
 305     xd
->visual 
= Tk_DefaultVisual(xd
->screen
); 
 306     xd
->depth 
= Tk_DefaultDepth(xd
->screen
); 
 307     xd
->colormap 
= Tk_DefaultColormap(xd
->screen
); 
 309     xd
->color 
= (xd
->depth 
!= 1); 
 311     xd
->pixels 
= (int  *)ckalloc(16 * sizeof(int)); 
 312     if (xd
->color
) { /* Color screen */ 
 315 #define GETCOLOR(i, name) \ 
 317         xd->pixels[i] = Rand16() & 255; \ 
 319         if ((color = Tk_GetColor(tk_mainInterp, tkwin, \ 
 320                                  None, name)) == NULL) { \ 
 321           xd->pixels[i] = Rand16() & 255; \ 
 324           switch (xd->depth) { \ 
 331               (((color->red >> (8 + 3)) & 0x1f) << (5 + 5)) | \ 
 332               (((color->green >> (8 + 2)) & 0x1f) << (5)) | \ 
 333               (((color->blue >> (8 + 3)) & 0x1f) << (0)); \ 
 337               (((color->red >> (8 + 3)) & 0x1f) << (6 + 5)) | \ 
 338               (((color->green >> (8 + 2)) & 0x3f) << (5)) | \ 
 339               (((color->blue >> (8 + 3)) & 0x1f) << (0)); \ 
 343               ((color->red & 0xff) << 16) | \ 
 344               ((color->green & 0xff) << 8) | \ 
 345               ((color->blue & 0xff) << 0); \ 
 349               ((color->red & 0xff) << 16) | \ 
 350               ((color->green & 0xff) << 8) | \ 
 351               ((color->blue & 0xff) << 0); \ 
 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
); 
 363         GETCOLOR(COLOR_WHITE
,           "#ffffff"); 
 364         GETCOLOR(COLOR_BLACK
,           "#000000"); 
 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"); 
 384                 "Oh, dear.  There don't seem to be enough free colors on X display \"%s\".\n", 
 387                 "Micropolis will try to run anyway, but might look pretty weird!\n"); 
 389     } else { /* Black and white screen */ 
 390       int white 
= WhitePixelOfScreen(xd
->screen
); 
 391       int black 
= BlackPixelOfScreen(xd
->screen
); 
 393       xd
->pixels
[COLOR_WHITE
] = white
; 
 394       xd
->pixels
[COLOR_BLACK
] = black
; 
 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
; 
 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
); 
 420     { int major
, minor
, event
, error
, pixmaps
; 
 422           (XQueryExtension(xd
->dpy
, "MIT-SHM", /* Jeez! */ 
 423                            &major
, &event
, &error
) != True
) || 
 424           (XShmQueryVersion(xd
->dpy
, 
 425                             &major
, &minor
, &pixmaps
) != True
)) { 
 427                 "Darn, X display \"%s\" doesn't support the shared memory extension.\n", 
 433                   "Darn, X display \"%s\" claims to support the shared memory extension,\n", 
 436                   "but is too lame to support shared memory pixmaps, so Micropolis will run slower.\n"); 
 438                   "Please complain to your X server vendor, %s\n", 
 439                   XServerVendor(xd
->dpy
)); 
 443                   "Cool, I found the shared memory extension!\n"); 
 445                   "Disabled SHM, because it is currently broken!\n"); 
 455     xd
->last_request_read 
= -1; 
 456     xd
->big_tile_pixmap 
= None
; 
 458     xd
->overlay_gc 
= NULL
; 
 459     xd
->gray25_stipple 
= None
; 
 460     xd
->gray50_stipple 
= None
; 
 461     xd
->gray75_stipple 
= None
; 
 462     xd
->vert_stipple 
= None
; 
 463     xd
->horiz_stipple 
= None
; 
 464     xd
->diag_stipple 
= None
; 
 466     xd
->big_tile_image 
= xd
->small_tile_image 
= NULL
; 
 468     xd
->next 
= XDisplays
; XDisplays 
= xd
; 
 475 IncRefDisplay(XDisplay 
*xd
) 
 481 DecRefDisplay(XDisplay 
*xd
) 
 483   if ((--xd
->references
) == 0) { 
 484     /* I'd blow it away, but tk may still be using the display */ 
 490 InitNewView(SimView 
*view
, char *title
, int class, int w
, int h
) 
 495   unsigned long valuemask 
= 0; 
 501   t 
= (char *)ckalloc(strlen(title
) + 1); 
 508   view
->bigtiles 
= view
->smalltiles 
= NULL
; 
 510   view
->line_bytes 
= 0; 
 511   view
->line_bytes8 
= 0; 
 512   view
->pixel_bytes 
= 0; 
 518   view
->skips 
= view
->skip 
= 0; 
 520   view
->map_state 
= ALMAP
; 
 521   view
->show_editors 
= 1; 
 522   view
->tool_showing 
= 0; 
 524   view
->tool_x 
= view
->tool_y 
= 0; 
 525   view
->tool_x_const 
= view
->tool_y_const 
= -1; 
 526   view
->tool_state 
= dozeState
; 
 527   view
->tool_state_save 
= -1; 
 528   view
->super_user 
= 0; 
 530   view
->dynamic_filter 
= 0; 
 531   view
->auto_scroll_token 
= 0; 
 532   view
->tool_event_time 
= 0; 
 533   view
->tool_last_event_time 
= 0; 
 534   view
->w_x 
= view
->w_y 
= 0; 
 535   view
->w_width 
= view
->w_height 
= 16; 
 536   view
->m_width 
= view
->m_height 
= 0; 
 537   view
->i_width 
= w
; view
->i_height 
= h
; 
 538   view
->pan_x 
= view
->pan_y 
= 0; 
 539   view
->tile_x 
= view
->tile_y 
= 0; 
 540   view
->tile_width 
= view
->tile_height 
= 0; 
 541   view
->screen_x 
= view
->screen_y 
= 0; 
 542   view
->screen_width 
= view
->screen_height 
= 0; 
 543   view
->last_x 
= view
->last_y 
= view
->last_button 
= 0; 
 544   view
->track_info 
= NULL
; 
 545   view
->message_var 
= NULL
; 
 547 /* This stuff was initialized in our caller (SimViewCmd) */ 
 548 /*  view->tkwin = NULL; */ 
 549 /*  view->interp = NULL; */ 
 550 /*  view->flags = 0; */ 
 553   view
->shminfo 
= NULL
; 
 555   view
->other_tiles 
= NULL
; 
 557   view
->other_image 
= NULL
; 
 558   view
->other_data 
= NULL
; 
 560   view
->pixmap2 
= None
; 
 561   view
->overlay_pixmap 
= None
; 
 562   view
->overlay_valid 
= 0; 
 563   view
->fontPtr 
= NULL
; 
 565   view
->update_real 
= view
->update_user 
= view
->update_system 
= 0.0; 
 566   view
->update_context 
= 0; 
 568   view
->auto_going 
= 0; 
 569   view
->auto_x_goal 
= view
->auto_x_goal 
= 0; 
 570   view
->auto_speed 
= 75; 
 573   view
->width 
= 0; view
->height 
= 0; 
 574   view
->show_overlay 
= 1; 
 575   view
->overlay_mode 
= 0; 
 577   view
->x 
= FindXDisplay(view
->tkwin
); 
 578   IncRefDisplay(view
->x
); 
 580   /* view->x->shared is 1 if the shared memory extension is present and 
 581      supports shared memory pixmaps, and -1 if it is present but doesn't. */ 
 582   if (view
->x
->shared 
!= 1) { 
 583     view
->type 
= X_Wire_View
; 
 585     view
->type 
= X_Mem_View
; 
 588   view
->x
->needs_swap 
= !(*(unsigned char*) (&test
)); 
 592   view
->pixels 
= view
->x
->pixels
; 
 594   if (w 
== EDITOR_W
) w 
= 256; /* XXX */ 
 595   if (h 
== EDITOR_H
) h 
= 256; /* XXX */ 
 597   view
->pan_x 
= w 
/ 2; view
->pan_y 
= h 
/ 2; 
 598   DoResizeView(view
, w
, h
); 
 606 DestroyView(SimView 
*view
) 
 610   CancelRedrawView(view
); 
 612   for (vp 
= ((view
->class == Editor_Class
) ? 
 613              (&sim
->editor
) : (&sim
->map
)); 
 615        vp 
= &((*vp
)->next
)) { 
 618       if (view
->class == Editor_Class
) 
 627   if (view
->title 
!= NULL
) { 
 628     ckfree (view
->title
); 
 632   if (view
->pixmap 
!= None
) { 
 633     XFreePixmap(view
->x
->dpy
, view
->pixmap
); 
 637   if (view
->pixmap2 
!= None
) { 
 638     XFreePixmap(view
->x
->dpy
, view
->pixmap2
); 
 639     view
->pixmap2 
= None
; 
 642   if (view
->overlay_pixmap 
!= None
) { 
 643     XFreePixmap(view
->x
->dpy
, view
->overlay_pixmap
); 
 644     view
->overlay_pixmap 
= None
; 
 647   if (view
->auto_scroll_token
) { 
 648     Tk_DeleteTimerHandler(view
->auto_scroll_token
); 
 649     view
->auto_scroll_token 
= 0; 
 654     XShmDetach(view
->x
->dpy
, view
->shminfo
); 
 655     shmdt(view
->shminfo
->shmaddr
); 
 656     shmctl(view
->shminfo
->shmid
, IPC_RMID
, 0); 
 657     ckfree(view
->shminfo
); 
 658     view
->shminfo 
= NULL
; 
 660       view
->image
->data 
= NULL
; 
 662       XDestroyImage(view
->image
); 
 668       if (view
->image
->data
) { 
 669         ckfree(view
->image
->data
); 
 670         view
->image
->data 
= NULL
; 
 673       XDestroyImage(view
->image
); 
 680   if (view
->other_image
) { 
 681       if (view
->other_image
->data
) { 
 682         ckfree(view
->other_image
->data
); 
 683         view
->other_image
->data 
= NULL
; 
 685       view
->other_data 
= NULL
; 
 686       XDestroyImage(view
->other_image
); 
 687       view
->other_image 
= NULL
; 
 693   DecRefDisplay(view
->x
); 
 695   ckfree((char *) view
); 
 700 AllocPixels(int len
, unsigned char pixel
) 
 703   unsigned char *data
, *cp
; 
 705   cp 
= data 
= (unsigned char *)ckalloc(len
); 
 706   for (i 
= len
; i 
> 0; i
--) { 
 714 DoResizeView(SimView 
*view
, int w
, int h
) 
 721   if (view
->class == Map_Class
) { /* Map_Class */ 
 725     if (view
->pixmap2 
== None
) { 
 727       view
->pixmap2 
= XCreatePixmap(view
->x
->dpy
, view
->x
->root
, 
 728                                     w
, h
, view
->x
->depth
); 
 729       if (view
->pixmap2 
== None
) { 
 731                 "Sorry, Micropolis can't create a pixmap on X display \"%s\"!\n", 
 733         sim_exit(1); // Just sets tkMustExit and ExitReturn 
 738   } else { /* Editor_Class */ 
 740     if ((w 
= (w 
+ 31) & (~15)) > view
->m_width
) 
 741       view
->m_width 
= w
, resize
++; 
 742     if ((h 
= (h 
+ 31) & (~15)) > view
->m_height
) 
 743       view
->m_height 
= h
, resize
++; 
 745     if (resize 
|| (view
->pixmap2 
== None
)) { 
 746       if (view
->pixmap2 
!= None
) { 
 747         XFreePixmap(view
->x
->dpy
, view
->pixmap2
); 
 748         view
->pixmap2 
= None
; 
 750       view
->pixmap2 
= XCreatePixmap(view
->x
->dpy
, view
->x
->root
, 
 751                                     view
->m_width
, view
->m_height
, 
 753       if (view
->pixmap2 
== None
) { 
 755                 "Sorry, Micropolis couldn't create a pixmap on X display \"%s\"!\n", 
 757         sim_exit(1); // Just sets tkMustExit and ExitReturn 
 762     if (resize 
|| (view
->overlay_pixmap 
== None
)) { 
 763       view
->overlay_mode 
= 0; 
 764       if (view
->overlay_pixmap 
!= None
) { 
 765         XFreePixmap(view
->x
->dpy
, view
->overlay_pixmap
); 
 766         view
->overlay_pixmap 
= None
; 
 768       view
->overlay_pixmap 
= XCreatePixmap(view
->x
->dpy
, view
->x
->root
, 
 769                                            view
->m_width
, view
->m_height
, 
 771       if (view
->overlay_pixmap 
== None
) { 
 773                 "Sorry, Micropolis couldn't create another pixmap on X display \"%s\".\n", 
 775         sim_exit(1); // Just sets tkMustExit and ExitReturn 
 778       if (view
->x
->overlay_gc 
== NULL
) { 
 779         unsigned long valuemask 
= 0; 
 782         view
->x
->overlay_gc 
= 
 783           XCreateGC(view
->x
->dpy
, view
->overlay_pixmap
, valuemask
, &values
); 
 784         XSetForeground(view
->x
->dpy
, view
->x
->overlay_gc
, 0); 
 785         XSetBackground(view
->x
->dpy
, view
->x
->overlay_gc
, 1); 
 786         XSetLineAttributes(view
->x
->dpy
, view
->x
->overlay_gc
,  
 787                            1, LineSolid
, CapButt
, JoinMiter
); 
 788         XSetGraphicsExposures(view
->x
->dpy
, view
->x
->overlay_gc
, False
); 
 795   if (view
->type 
!= X_Mem_View
) { 
 799   if (resize 
|| (view
->image 
== NULL
)) { 
 800     if (view
->shminfo 
&& view
->image
) { 
 801       if (view
->pixmap 
!= None
) { 
 802         XFreePixmap(view
->x
->dpy
, view
->pixmap
); 
 805       XShmDetach(view
->x
->dpy
, view
->shminfo
); 
 806       shmdt(view
->shminfo
->shmaddr
); 
 807       shmctl(view
->shminfo
->shmid
, IPC_RMID
, 0); 
 808       view
->image
->data 
= NULL
; 
 809       if (view
->data 
== view
->data8
) 
 812       XDestroyImage(view
->image
); 
 817     /* XShmPixmapFormat is documented but does not exist !!! */ 
 818     if (XShmPixmapFormat(view
->x
->dpy
) != ZPixmap
) { 
 820               "Darn, display \"%s\" has the wrong shared memory format.\n", 
 826     if (!view
->shminfo
) { 
 827       view
->shminfo 
= (XShmSegmentInfo 
*)ckalloc(sizeof (XShmSegmentInfo
)); 
 831       XShmCreateImage(view
->x
->dpy
, view
->x
->visual
, view
->x
->depth
, 
 832                       view
->x
->color 
? ZPixmap 
: XYBitmap
, 
 834                       view
->m_width
, view
->m_height
); 
 836     view
->line_bytes 
= view
->image
->bytes_per_line
; 
 838     switch (view
->x
->depth
) { 
 841       view
->pixel_bytes 
= 0; 
 846       view
->pixel_bytes 
= 1; 
 851       view
->pixel_bytes 
= 2; 
 856       view
->pixel_bytes 
= 2; 
 861       /* XXX: TODO: 24 and 32 bit support */ 
 862       view
->pixel_bytes 
= 4; 
 863       //view->pixel_bytes = 3; 
 868       /* XXX: TODO: 24 and 32 bit support */ 
 869       view
->pixel_bytes 
= 4; 
 874       view
->pixel_bytes 
= 0; 
 880     view
->shminfo
->shmid 
= shmget(IPC_PRIVATE
, 
 884     if (view
->shminfo
->shmid 
< 0) { 
 887               "Darn, Micropolis can't share memory with X display \"%s\".\n", 
 892     view
->data 
= (unsigned char *)shmat(view
->shminfo
->shmid
, 0, 0); 
 893     if ((int)view
->data 
== -1) { 
 896               "Darn, Micropolis can't find any memory to share with display \"%s\".\n", 
 901     view
->image
->data 
= (char *)view
->data
; 
 902     view
->shminfo
->shmaddr 
= (char *)view
->data
; 
 903     view
->shminfo
->readOnly 
= False
; 
 909       old 
= XSetErrorHandler(CatchXError
); 
 912         XShmAttach(view
->x
->dpy
, view
->shminfo
); 
 915                 "Darn, the X display \"%s\" can't access Micropolis's shared memory.\n", 
 920       XSync(view
->x
->dpy
, False
); 
 924         view
->pixmap 
= XShmCreatePixmap(view
->x
->dpy
, view
->x
->root
, 
 925                                         view
->data
, view
->shminfo
, 
 926                                         view
->m_width
, view
->m_height
, 
 928         XSync(view
->x
->dpy
, False
); 
 931             (view
->pixmap 
== None
)) { 
 933                   "Darn, Micropolis couldn't get a shared memory pixmap on X display \"%s\".\n", 
 939       XSetErrorHandler(old
); 
 944           XShmDetach(view
->x
->dpy
, view
->shminfo
); 
 946         result 
= shmdt(view
->shminfo
->shmaddr
); 
 947         result 
= shmctl(view
->shminfo
->shmid
, IPC_RMID
, 0); 
 948         ckfree(view
->shminfo
); 
 949         view
->shminfo 
= NULL
; 
 951           view
->image
->data 
= NULL
; 
 953           XDestroyImage(view
->image
); 
 959       if (view
->x
->color
) { 
 960         XSetForeground(view
->x
->dpy
, view
->x
->gc
, 
 961                        view
->pixels
[COLOR_LIGHTBROWN
]); 
 963         XSetForeground(view
->x
->dpy
, view
->x
->gc
, 
 964                        view
->pixels
[COLOR_WHITE
]); 
 967       XFillRectangle(view
->x
->dpy
, view
->pixmap
, view
->x
->gc
, 
 968                      0, 0, view
->m_width
, view
->m_height
); 
 977           "Falling back to the X network protocol on display \"%s\"...\n", 
 982   view
->type 
= X_Wire_View
; 
 983   if (view
->pixmap 
!= None
) { 
 984     XFreePixmap(view
->x
->dpy
, view
->pixmap
); 
 989     if (view
->shminfo
->shmid 
>= 0) { 
 990       if (view
->shminfo
->shmaddr
) { 
 991         shmdt(view
->shminfo
->shmaddr
); 
 993       shmctl(view
->shminfo
->shmid
, IPC_RMID
, 0); 
 995     ckfree((char *)view
->shminfo
); 
 996     view
->shminfo 
= NULL
; 
1000     view
->image
->data 
= NULL
; 
1001     XDestroyImage(view
->image
); 
1005   view
->line_bytes 
= 0; 
1006   view
->pixel_bytes 
= 0; 
1011   if (resize 
|| (view
->pixmap 
== None
)) { 
1012     if (view
->pixmap 
!= None
) { 
1013       XFreePixmap(view
->x
->dpy
, view
->pixmap
); 
1014       view
->pixmap 
= None
; 
1016     view
->pixmap 
= XCreatePixmap(view
->x
->dpy
, view
->x
->root
, 
1017                                  view
->m_width
, view
->m_height
, 
1019     if (view
->pixmap 
== None
) { 
1021               "Sorry, Micropolis can't create pixmap on X display \"%s\".\n", 
1023       sim_exit(1); // Just sets tkMustExit and ExitReturn 
1026     if (view
->x
->color
) { 
1027       XSetForeground(view
->x
->dpy
, view
->x
->gc
, 
1028                      view
->pixels
[COLOR_LIGHTBROWN
]); 
1030       XSetForeground(view
->x
->dpy
, view
->x
->gc
, 
1031                      view
->pixels
[COLOR_WHITE
]); 
1033     XFillRectangle(view
->x
->dpy
, view
->pixmap
, view
->x
->gc
, 
1034                      0, 0, view
->m_width
, view
->m_height
); 
1039   if (view
->class == Editor_Class
) { 
1044   } else if (view
->class == Map_Class
) { 
1046     if (view
->type 
== X_Mem_View
) { /* Memory Map */ 
1048       if (view
->x
->color
) { 
1050         /* Color, Shared Memory */ 
1052         view
->data8 
= view
->data
; 
1053         view
->line_bytes8 
= view
->line_bytes
; /* XXX: ??? */ 
1055         switch (view
->x
->depth
) { 
1058           view
->pixel_bytes 
= 1; 
1063           view
->pixel_bytes 
= 2; 
1068           view
->pixel_bytes 
= 2; 
1073           /* XXX: TODO: 24 and 32 bit support */ 
1074           view
->pixel_bytes 
= 4; 
1075           //view->pixel_bytes = 3; 
1080           /* XXX: TODO: 24 and 32 bit support */ 
1081           view
->pixel_bytes 
= 4; 
1086           view
->pixel_bytes 
= 0; 
1094         /* Black and White, Shared Memory */ 
1096         if (view
->other_image 
!= NULL
) { 
1097           XDestroyImage(view
->other_image
); 
1100         view
->line_bytes8 
= view
->m_width
; /* XXX: fix depth */ 
1101         view
->pixel_bytes 
= 0; 
1104         view
->other_data 
= view
->data8 
= 
1105           AllocPixels(view
->m_height 
* view
->line_bytes8
, /* XXX: fix depth */ 
1106                       view
->pixels
[COLOR_WHITE
]); 
1108           XCreateImage(view
->x
->dpy
, view
->x
->visual
, 8, /* XXX: fix depth */ 
1109                        ZPixmap
, 0, (char *)view
->other_data
, 
1110                        view
->m_width
, view
->m_height
, 
1111                        8, view
->line_bytes8
); /* XXX: fix depth */ 
1114     } else { /* Wire Map */ 
1118       if (view
->image 
!= NULL
) { 
1119         XDestroyImage(view
->image
); 
1123       if (view
->other_image 
!= NULL
) { 
1124         XDestroyImage(view
->other_image
); 
1125         view
->other_image 
= NULL
; 
1128       if (view
->x
->color
) { 
1132         switch (view
->x
->depth
) { 
1135           view
->pixel_bytes 
= 1; 
1140             ((view
->m_width 
* view
->pixel_bytes
) + 3) & (~3); 
1144           view
->pixel_bytes 
= 2; 
1149             ((view
->m_width 
* view
->pixel_bytes
) + 3) & (~3); 
1153           view
->pixel_bytes 
= 2; 
1158             ((view
->m_width 
* view
->pixel_bytes
) + 3) & (~3); 
1162           view
->pixel_bytes 
= 4; 
1163           //view->pixel_bytes = 3; 
1168             ((view
->m_width 
* 4) + 3) & (~3); 
1172           view
->pixel_bytes 
= 4; 
1177             ((view
->m_width 
* 4) + 3) & (~3); 
1181           assert(0); /* Unknown depth */ 
1191         /* Black and White, Wire */ 
1193         view
->pixel_bytes 
= 0; 
1196           (view
->m_width 
+ 3) & (~3); /* XXX: handle depth */ 
1198           (view
->m_width 
+ 7) >>3; 
1205         AllocPixels(view
->m_height 
* view
->line_bytes
, 0); 
1207         XCreateImage(view
->x
->dpy
, view
->x
->visual
, 
1209                      view
->x
->color 
? ZPixmap 
: XYBitmap
, 
1210                      0, (char *)view
->data
, 
1211                      view
->m_width
, view
->m_height
, 
1216         AllocPixels(view
->m_height 
* view
->line_bytes8
, 0); 
1218         XCreateImage(view
->x
->dpy
, view
->x
->visual
, 
1221                      0, (char *)view
->other_data
, 
1222                      view
->m_width
, view
->m_height
, 
1226       if (view
->x
->color
) { 
1227         view
->data8 
= view
->data
; 
1229         view
->data8 
= view
->other_data
; 
1236 DoPanBy(struct SimView 
*view
, int dx
, int dy
) 
1238   DoPanTo(view
, view
->pan_x 
+ dx
, view
->pan_y 
+ dy
); 
1242 DoPanTo(struct SimView 
*view
, int x
, int y
) 
1244   if (view
->class != Editor_Class
) { 
1250   if (x 
> view
->i_width
) x 
= view
->i_width 
- 1; 
1251   if (y 
> view
->i_height
) y 
= view
->i_height 
- 1; 
1252   if ((view
->pan_x 
!= x
) || 
1253       (view
->pan_y 
!= y
)) { 
1260 /* #define DEBUG_PAN */ 
1262 DoAdjustPan(struct SimView 
*view
) 
1264   int ww2 
= view
->w_width 
>>1, wh2 
= view
->w_height 
>>1; 
1265   int px 
= view
->pan_x
, py 
= view
->pan_y
; 
1266   int last_tile_x 
= view
->tile_x
, last_tile_y 
= view
->tile_y
; 
1267   int last_tile_width 
= view
->tile_width
, last_tile_height 
= view
->tile_height
; 
1268   int total_width 
= view
->m_width 
>>4, total_height 
= view
->m_height 
>>4; 
1269 //fprintf(stderr, "DoAdjustPan\n"); 
1272   printf("AdjustPan window %d %d  ww2 %d wh2 %d  pan %d %d\n", 
1273          view
->w_width
, view
->w_height
, ww2
, wh2
, px
, py
); 
1274   printf("  last tile %d %d %d %d\n", 
1275          last_tile_x
, last_tile_y
, last_tile_width
, last_tile_height
); 
1278   if ((view
->tile_x 
= ((px 
- ww2
) >>4)) < 0) 
1280   if ((view
->tile_y 
= ((py 
- wh2
) >>4)) < 0) 
1284   printf("  now tile %d %d\n", view
->tile_x
, view
->tile_y
); 
1287   view
->tile_width 
= ((15 + px 
+ ww2
) >>4); 
1288   view
->tile_height 
= ((15 + py 
+ wh2
) >>4); 
1291   printf("    outer tile %d %d\n", view
->tile_width
, view
->tile_height
); 
1294   if (view
->tile_width 
> (view
->i_width 
>>4)) 
1295     view
->tile_width 
= (view
->i_width 
>>4); 
1296   view
->tile_width 
-= view
->tile_x
; 
1297   if (view
->tile_height 
> (view
->i_height 
>>4)) 
1298     view
->tile_height 
= (view
->i_height 
>>4); 
1299   view
->tile_height 
-= view
->tile_y
; 
1302   printf("    tile size %d %d\n", view
->tile_width
, view
->tile_height
); 
1305   if (view
->tile_width 
> (view
->m_width 
>>4)) 
1306     view
->tile_width 
= (view
->m_width 
>>4); 
1307   if (view
->tile_height 
> (view
->m_height 
>>4)) 
1308     view
->tile_height 
= (view
->m_height 
>>4); 
1311   printf("    clipped size %d %d\n", view
->tile_width
, view
->tile_height
); 
1312   printf("    maximum size %d %d\n", view
->m_width 
>>4, view
->m_height 
>>4); 
1315   view
->screen_x 
= (ww2 
- px
) + (view
->tile_x 
<<4); 
1316   view
->screen_y 
= (wh2 
- py
) + (view
->tile_y 
<<4); 
1317   view
->screen_width 
= (view
->tile_width 
<<4); 
1318   view
->screen_height 
= (view
->tile_height 
<<4); 
1321   printf("    screen %d %d %d %d\n", 
1322          view
->screen_x
, view
->screen_y
, 
1323          view
->screen_width
, view
->screen_height
); 
1326   view
->overlay_mode 
= 0; 
1329   if (SimSpeed 
== 0) { 
1330     EventuallyRedrawView(view
); 
1332 /*  InvalidateEditors(); */ 
1333   if (view
->show_me
) { 
1336 /*  FixMicropolisTimer(); */ 
1338   { int dx 
= last_tile_x 
- view
->tile_x
, 
1339         dy 
= last_tile_y 
- view
->tile_y
; 
1340     short **want 
= view
->other_tiles
, 
1341           **have 
= view
->tiles
; 
1344     printf("scrolling %d %d\n", dx
, dy
); 
1347     if ((dx 
!= 0) || (dy 
!= 0)) { 
1349           width 
= view
->tile_width
, 
1350           height 
= view
->tile_height
; 
1352       for (col 
= 0; col 
< width
; col
++) 
1353         memcpy(want
[col
], have
[col
], (height 
* sizeof(short))); 
1355       for (col 
= 0; col 
< total_width
; col
++) { 
1357         for (row 
= 0; row 
< total_height
; row
++) { 
1359           if ((x 
>= 0) && (x 
< width
) && 
1360               (y 
>= 0) && (y 
< height
)) { 
1361             have
[col
][row
] = want
[x
][y
]; 
1363             have
[col
][row
] = -1; 
1368       XCopyArea(view
->x
->dpy
, view
->pixmap
, view
->pixmap
, view
->x
->gc
, 
1369                 0, 0, view
->tile_width 
<<4, view
->tile_height 
<<4, 
1372       if (view
->type 
== X_Mem_View
) { 
1373         XSync(view
->x
->dpy
, False
); 
1380 AllocTiles(SimView 
*view
) 
1383   short **have
, **want
; 
1384   int w 
= view
->m_width 
/ 16, h 
= view
->m_height 
/ 16; 
1385   int n 
= (w 
+ 1) * sizeof (short *); 
1390   have 
= view
->tiles 
= 
1391     (short **)ckalloc(n
); 
1393   want 
= view
->other_tiles 
= 
1394     (short **)ckalloc(n
); 
1396   have
[w
] = want
[w
] = NULL
; 
1398   n 
= h 
* sizeof(short); 
1399   for (col 
= 0; col 
< w
; col
++) { 
1401     have
[col
] = (short *)ckalloc(n
); 
1402     want
[col
] = (short *)ckalloc(n
); 
1403     for (row 
= 0; row 
< h
; row
++) { 
1404       have
[col
][row
] = -1; 
1405       want
[col
][row
] = -1; 
1411 FreeTiles(SimView 
*view
) 
1415   for (col 
= 0; view
->tiles
[col
] != NULL
; col
++) { 
1416     ckfree ((char *)view
->tiles
[col
]); 
1417     ckfree ((char *)view
->other_tiles
[col
]); 
1419   ckfree ((char *)view
->tiles
); 
1421   ckfree ((char *)view
->other_tiles
); 
1422   view
->other_tiles 
= NULL
; 
1426 #define POINT_BATCH 32 
1431 /* XXX: todo: ink locking so someone doesn't erase ink that's being drawn */ 
1440     OldInk 
= OldInk
->next
; 
1442     ink 
= (Ink 
*)ckalloc(sizeof(Ink
)); 
1443     ink
->maxlength 
= POINT_BATCH
; 
1444     ink
->points 
= (XPoint 
*)ckalloc(POINT_BATCH 
* sizeof(XPoint
)); 
1447   ink
->color 
= COLOR_WHITE
; 
1449   ink
->left 
= ink
->right 
= ink
->top 
= ink
->bottom 
= 
1450     ink
->last_x 
= ink
->last_y 
= -1; 
1462 StartInk(Ink 
*ink
, int x
, int y
) 
1465   ink
->left 
= ink
->right 
= ink
->last_x 
= ink
->points
[0].x 
= x
; 
1466   ink
->top 
= ink
->bottom 
= ink
->last_y 
= ink
->points
[0].y 
= y
; 
1470 AddInk(Ink 
*ink
, int x
, int y
) 
1472   int dx 
= x 
- ink
->last_x
; 
1473   int dy 
= y 
- ink
->last_y
; 
1475   if ((dx 
!= 0) || (dy 
!= 0)) { 
1477     if (ink->length > 1) { 
1479           (ink->points[ink->length - 1].x == 0) && 
1480           ((ink->points[ink->length - 1].y < 0) ? 
1481            (dy < 0) : (dy > 0))) { 
1482         ink->points[ink->length - 1].y += dy; 
1484       } else if ((dy == 0) && 
1485                  (ink->points[ink->length - 1].y == 0) && 
1486                  ((ink->points[ink->length - 1].x < 0) ? 
1487                   (dx < 0) : (dx > 0))) { 
1488         ink->points[ink->length - 1].x += dx; 
1494     if (ink
->length 
>= ink
->maxlength
) { 
1495       ink
->maxlength 
+= POINT_BATCH
; 
1496       ink
->points 
= (XPoint 
*)realloc((void *)ink
->points
, 
1497                                       ink
->maxlength 
* sizeof(XPoint
)); 
1499     ink
->points
[ink
->length
].x 
= dx
; 
1500     ink
->points
[ink
->length
].y 
= dy
; 
1510     if (y 
> ink
->bottom
) 
1513     { int left
, right
, top
, bottom
; 
1516       if (ink
->last_x 
< x
) { left 
= ink
->last_x
; right 
= x
; } 
1517       else { left 
= x
; right 
= ink
->last_x
; } 
1518       if (ink
->last_y 
< y
) { top 
= ink
->last_y
; bottom 
= y
; } 
1519       else { top 
= y
; bottom 
= ink
->last_y
; } 
1521       left 
-= 5; right 
+= 5; top 
-= 5; bottom 
+= 5; 
1523       for (view 
= sim
->editor
; view 
!= NULL
; view 
= view
->next
) { 
1526         if ((right 
>= (vleft 
= view
->pan_x 
- (view
->w_width 
/ 2))) && 
1527             (left 
<= vleft 
+ view
->w_width
) && 
1528             (bottom 
>= (vtop 
= view
->pan_y 
- (view
->w_height 
/ 2))) && 
1529             (top 
<= vtop 
+ view
->w_height
)) { 
1530           /* XXX: do studly incremental update instead */ 
1531           view
->overlay_mode 
= 0; 
1532           EventuallyRedrawView(view
); 
1536     ink
->last_x 
= x
; ink
->last_y 
= y
; 
1545   while (sim
->overlay
) { 
1547     sim
->overlay 
= ink
->next
;