Main Page | Data Structures | Directories | File List | Data Fields | Globals

lcx11.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------- *
00002  * lcx11.c
00003  * This file is part of lincity.
00004  * Lincity is copyright (c) I J Peters 1995-1997, (c) Greg Sharp 1997-2001.
00005  * ---------------------------------------------------------------------- */
00006 #include "lcconfig.h"
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include <assert.h>
00010 #include <math.h>
00011 #include "lcstring.h"
00012 #include "lcintl.h"
00013 #include "fileutil.h"
00014 #include "lclib.h"
00015 
00016 #include <X11/Xlib.h>
00017 #include <X11/Xatom.h>
00018 #include <X11/Xutil.h>
00019 #include <X11/keysym.h>
00020 #include <X11/keysymdef.h>
00021 #include "lin-city.h"
00022 #include "lctypes.h"
00023 #include "cliglobs.h"
00024 #include "lcx11.h"
00025 #include "pixmap.h"
00026 #include "mouse.h"
00027 #include "screen.h"
00028 
00029 #ifndef M_PI
00030 #define M_PI            3.14159265358979323846
00031 #endif
00032 
00033 #define USE_IMAGES 1
00034 
00035 #define DEBUG_X11_MOUSE
00036 #undef DEBUG_X11_MOUSE
00037 
00038 void
00039 set_pointer_confinement (void)
00040 {
00041     if (confine_flag) {
00042         XGrabPointer (display.dpy, display.win, 0,
00043                       ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
00044                       GrabModeAsync, GrabModeAsync, 
00045                       display.win, None, CurrentTime);
00046     } else {
00047         XUngrabPointer (display.dpy, CurrentTime);
00048     }
00049 }
00050 
00051 static int pointer_confined;
00052 
00053 int 
00054 confine_pointer (int x, int y, int w, int h) 
00055 {
00056 
00057     if (display.pointer_confined)
00058         return 0;
00059 
00060     display.confinewin = 
00061         XCreateSimpleWindow(display.dpy, display.win, 
00062                             10, 10, w, h,
00063                             0, 0, 0);
00064 
00065     XMapWindow(display.dpy, display.confinewin);
00066 
00067     XGrabPointer(display.dpy, display.root, 1,
00068                  ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
00069                  GrabModeAsync, GrabModeAsync, display.confinewin,
00070                  None, CurrentTime);
00071 
00072 
00073     display.pointer_confined = 1;
00074     return 1;
00075 
00076 }
00077     
00078 
00079 void 
00080 unconfine_pointer (void)
00081 {
00082     XUngrabPointer(display.dpy, CurrentTime);
00083     XDestroyWindow(display.dpy, display.confinewin);
00084     display.pointer_confined = 0;
00085 }
00086 
00087 void
00088 setcustompalette (void)
00089 {
00090   char s[100];
00091   int n, r, g, b, i, flag[256];
00092   XColor pal[256];
00093   FILE *inf;
00094   for (i = 0; i < 256; i++)
00095     flag[i] = 0;
00096   if ((inf = fopen (colour_pal_file, "r")) == 0)
00097     HandleError ("Can't find the colour pallet file", FATAL);
00098 
00099   while (feof (inf) == 0)
00100     {
00101       fgets (s, 99, inf);
00102       if (sscanf (s, "%d %d %d %d", &n, &r, &g, &b) == 4)
00103         {
00104           pal[n].red = r;
00105           pal[n].green = g;
00106           pal[n].blue = b;
00107           pal[n].flags = DoRed | DoGreen | DoBlue;
00108           pal[n].pixel = colour_table[n];       /* ??? */
00109 
00110           flag[n] = 1;
00111         }
00112     }
00113   fclose (inf);
00114   for (i = 0; i < 256; i++)
00115     {
00116       if (flag[i] == 0)
00117         {
00118           printf ("Colour %d not loaded\n", i);
00119           HandleError ("Can't continue", FATAL);
00120         }
00121       pal[i].red = (unsigned char) ((pal[i].red
00122                   * (1 - gamma_correct_red)) + (64 * sin ((float) pal[i].red
00123                                         * M_PI / 128)) * gamma_correct_red);
00124 
00125       pal[i].green = (unsigned char) ((pal[i].green
00126               * (1 - gamma_correct_green)) + (64 * sin ((float) pal[i].green
00127                                       * M_PI / 128)) * gamma_correct_green);
00128 
00129       pal[i].blue = (unsigned char) ((pal[i].blue
00130                 * (1 - gamma_correct_blue)) + (64 * sin ((float) pal[i].blue
00131                                        * M_PI / 128)) * gamma_correct_blue);
00132     }
00133 
00134   do_setcustompalette (pal);
00135 }
00136 
00137 void
00138 open_setcustompalette (XColor * inpal)
00139 {
00140     do_setcustompalette (inpal);
00141 }
00142 
00143 void
00144 do_setcustompalette (XColor * inpal)
00145 {
00146   int i, n, me = 0, flag[256], vid;
00147   int depth;
00148   long unsigned int plane_masks[3];
00149   XColor pal[256];
00150   int writeable_p;
00151 
00152   display.cmap = XDefaultColormap (display.dpy, display.screen);
00153   depth = DefaultDepth (display.dpy, display.screen);
00154 
00155   /* Decide, if the colormap is writable */
00156   {
00157     Visual *visual = DefaultVisual (display.dpy, display.screen);
00158 #if defined(__cplusplus) || defined(c_plusplus)
00159     int visual_class = visual->c_class;
00160 #else
00161     int visual_class = visual->class;
00162 #endif
00163     writeable_p = (visual_class == PseudoColor || visual_class == GrayScale);
00164   }
00165 
00166   if (writeable_p)
00167     {
00168       if (XAllocColorCells (display.dpy, display.cmap, 0
00169                             ,plane_masks, 0, colour_table, 256) == 0)
00170         {
00171           me = (*DefaultVisual (display.dpy, display.screen)).map_entries;
00172           vid = (*DefaultVisual (display.dpy, display.screen)).visualid;
00173           display.cmap = XCreateColormap (display.dpy, display.win
00174                                 ,DefaultVisual (display.dpy, display.screen)
00175           /*      ,PseudoColor */
00176                                           ,AllocNone);
00177           if (me == 256 && depth != 24)
00178             {
00179               if (XAllocColorCells (display.dpy, display.cmap, 0
00180                                     ,plane_masks, 0, colour_table, 256) != 0) {
00181                   /* printf ("Allocated 256 cells\n"); */
00182               }
00183               else {
00184                   printf ("Couldn't allocate 256 cells\n");
00185               }
00186             }
00187           else
00188             for (i = 0; i < 256; i++)
00189               colour_table[i] = i;
00190         }
00191       if (!display.cmap)
00192         HandleError ("No default colour map", FATAL);
00193     }
00194 
00195   for (i = 0; i < 256; i++)
00196     flag[i] = 0;
00197 
00198   for (n = 0; n < 256; n++)
00199     {
00200       pal[n].red = inpal[n].red << 10;
00201       pal[n].green = inpal[n].green << 10;
00202       pal[n].blue = inpal[n].blue << 10;
00203       pal[n].flags = DoRed | DoGreen | DoBlue;
00204       if (writeable_p)
00205         pal[n].pixel = colour_table[n];
00206       else
00207         {
00208           if (XAllocColor (display.dpy
00209                            ,display.cmap, &(pal[n])) == 0)
00210             HandleError ("alloc colour failed"
00211                          ,FATAL);
00212           colour_table[n] = pal[n].pixel;
00213           XSetForeground (display.dpy
00214                           ,display.pixcolour_gc[n]
00215                           ,colour_table[n]);
00216         }
00217       flag[n] = 1;
00218     }
00219 
00220   if (writeable_p)
00221     {
00222       XStoreColors (display.dpy, display.cmap, pal, 256);
00223       XFlush (display.dpy);
00224     }
00225   XSetWindowColormap (display.dpy, display.win, display.cmap);
00226 }
00227 
00228 #if defined (commentout)
00229 void
00230 initfont ()
00231 {
00232   int i;
00233   FILE *finf;
00234   if ((finf = fopen (fontfile, "r")) == 0)
00235     HandleError ("Can't open the font file", FATAL);
00236   for (i = 0; i < 256 * 8; i++)
00237     myfont[i] = fgetc (finf);
00238   fclose (finf);
00239 }
00240 #endif
00241 
00242 void
00243 Fgl_setfontcolors (int bg, int fg)
00244 {
00245   text_fg = fg;
00246   text_bg = bg;
00247 }
00248 
00249 void
00250 Fgl_setfont (int fw, int fh, void *fp)
00251 {
00252   open_font = fp;
00253   open_font_height = fh;
00254 }
00255 
00256 void
00257 parse_xargs (int argc, char **argv, char **geometry)
00258 {
00259     int option;
00260     extern char *optarg;
00261 
00262 #ifdef ALLOW_PIX_DOUBLING
00263     char* option_string = "vbrndg:wR:G:B:D";
00264 #else
00265     char* option_string = "vbrng:wR:G:B:D";
00266 #endif
00267     while ((option = getopt (argc, argv, option_string)) != EOF) {
00268         switch (option)
00269         {
00270         case 'v':
00271             verbose = TRUE;
00272             break;
00273         case 'g':
00274             *geometry = optarg;
00275             break;
00276 #ifdef ALLOW_PIX_DOUBLING
00277         case 'd':
00278             pix_double = 1;
00279             /* Fall through.  We are not allowed a border with pix doubling */
00280 #endif
00281         case 'b':
00282             borderx = 0;
00283             bordery = 0;
00284             break;
00285         case 'r':
00286             borderx = BORDERX;
00287             bordery = BORDERY;
00288             break;
00289         case 'n':
00290             no_init_help = TRUE;
00291             break;
00292         case 'w':
00293             gamma_correct_red = GAMMA_CORRECT_RED;
00294             gamma_correct_green = GAMMA_CORRECT_GREEN;
00295             gamma_correct_blue = GAMMA_CORRECT_BLUE;
00296             break;
00297         case 'R':
00298             sscanf (optarg, "%f", &gamma_correct_red);
00299             break;
00300         case 'G':
00301             sscanf (optarg, "%f", &gamma_correct_green);
00302             break;
00303         case 'B':
00304             sscanf (optarg, "%f", &gamma_correct_blue);
00305             break;
00306         case 'D':
00307             command_line_debug = 1;
00308             break;
00309         }
00310     }
00311     if (verbose)
00312         printf (_("Version %s\n"), VERSION);
00313     if (!(display.dpy = XOpenDisplay (display.dname)))
00314     {
00315         printf (" Can't open the dispay!\n");
00316         HandleError ("Cannot open display.\n", FATAL);
00317         exit (-1);
00318     }
00319     /* Record the screen number and root window. */
00320     display.screen = DefaultScreen (display.dpy);
00321     display.root = RootWindow (display.dpy, display.screen);
00322 
00323     display.winW = WINWIDTH + borderx * 2 + pix_double * WINWIDTH;
00324     display.winH = WINHEIGHT + bordery * 2 + pix_double * WINHEIGHT;
00325     winX = (DisplayWidth (display.dpy, display.screen) - display.winW) / 2;
00326     winY = (DisplayHeight (display.dpy, display.screen) - display.winH) / 2;
00327     if (*geometry != NULL)
00328         XParseGeometry (*geometry, &winX, &winY, &display.winW, &display.winH);
00329 }
00330 
00331 
00332 void
00333 Create_Window (char *geometry)
00334 {
00335     short q;
00336     Visual *vid;
00337     XSetWindowAttributes xswa;
00338     XSizeHints sizehint;
00339     XWMHints wmhints;
00340     int depth;
00341     unsigned char wname[256];   /* Window Name */
00342     unsigned long vmask = CWEventMask | CWBackPixel | CWBackingStore;
00343 
00344     depth = DefaultDepth (display.dpy, display.screen);
00345     xswa.event_mask = 0;
00346     xswa.background_pixel = display.bg;
00347     xswa.backing_store = Always;
00348     debug_printf ("DefaultVisual id=%d bp-rgb=%d map-entries=%d\n",
00349                   (int) (*DefaultVisual (display.dpy, display.screen)).visualid,
00350                   (*DefaultVisual (display.dpy, display.screen)).bits_per_rgb,
00351                   (*DefaultVisual (display.dpy, display.screen)).map_entries);
00352     vid = DefaultVisual (display.dpy, display.screen);
00353     display.cmap
00354             = XDefaultColormap (display.dpy, display.screen);
00355     display.win = XCreateWindow (display.dpy, display.root,
00356                                  winX, winY,
00357                                  display.winW, display.winH, 0, depth,
00358                                  InputOutput,   /* vid , */
00359                                  DefaultVisual (display.dpy, display.screen),
00360                                  /*      PseudoColor,  */
00361                                  vmask, &xswa);
00362 
00363     sizehint.x = winX - 100;
00364     sizehint.y = winY;
00365     sizehint.width = display.winW;
00366     sizehint.height = display.winH;
00367     sizehint.min_width = display.winW;
00368     sizehint.min_height = display.winH;
00369     sizehint.max_width = display.winW;
00370     sizehint.max_height = display.winH;
00371     /* GCS FIX:  Be careful about resizing the opening screen */
00372     /* WCK: Fixed.  We lock it now, and unlock it after the opening screen.
00373        not gorgeous, but it works for now.  Still need to clean up.*/
00374 #define NO_RESIZABLE_WINDOWS 1
00375     if (geometry != NULL) {
00376 #if defined (NO_RESIZABLE_WINDOWS)
00377         sizehint.flags = USPosition | USSize | PMinSize | PMaxSize;
00378 #else
00379         sizehint.flags = USPosition | USSize | PMinSize;
00380 #endif
00381     } else {
00382 #if defined (NO_RESIZABLE_WINDOWS)
00383         sizehint.flags = PPosition | PSize | PMinSize | PMaxSize;
00384 #else
00385         sizehint.flags = PPosition | PSize | PMinSize;
00386 #endif
00387     }
00388     XSetNormalHints (display.dpy, display.win, &sizehint);
00389 
00390     display.protocol_atom = XInternAtom (display.dpy, "WM_PROTOCOLS",
00391                                          False);
00392     display.kill_atom = XInternAtom (display.dpy, "WM_DELETE_WINDOW",
00393                                      False);
00394 
00395     /* Title */
00396     sprintf ((char *) wname,
00397              _("xlincity, Version %s, "
00398              "(Copyright) IJ Peters - copying policy GNU GPL"),
00399              VERSION);
00400     XChangeProperty (display.dpy, display.win,
00401                      XA_WM_NAME, XA_STRING, 8, PropModeReplace, wname,
00402                      strlen ((char *) wname));
00403 
00404     /* Window Manager Hints (This is supposed to make input work.) */
00405     wmhints.flags = InputHint;
00406     wmhints.input = True;
00407     XSetWMHints (display.dpy, display.win, &wmhints);
00408 
00409     /* GCS - 2003/08/15 - Cygwin doesn't generate the MapEvent unless
00410        the mask enabled before XMapWindow is called.  Therefore, 
00411        XSelectInput needs to be called before XMapWindow */
00412     XSelectInput (display.dpy, display.win,
00413                   KeyPressMask | ButtonPressMask | ButtonReleaseMask
00414                   | ExposureMask | StructureNotifyMask);
00415 
00416     XMapWindow (display.dpy, display.win);
00417     
00418     for (q = 0; q < 256; q++)
00419     {
00420         display.pixcolour_gc[q] = XCreateGC (display.dpy
00421                                              ,display.win, 0, NULL);
00422         XSetForeground (display.dpy, display.pixcolour_gc[q], q);
00423         XSetBackground (display.dpy, display.pixcolour_gc[q],
00424                         display.bg);
00425         XSetGraphicsExposures (display.dpy, display.pixcolour_gc[q],
00426                                False);
00427     }
00428 }
00429 
00430 void 
00431 unlock_window_size (void) 
00432 {
00433     XSizeHints sizehint;
00434 
00435     sizehint.x = winX - 100;
00436     sizehint.y = winY;
00437     sizehint.width = display.winW;
00438     sizehint.height = display.winH;
00439     sizehint.min_width = display.winW;
00440     sizehint.min_height = display.winH;
00441     sizehint.max_width = display.winW;
00442     sizehint.max_height = display.winH;
00443 
00444     sizehint.flags = USPosition | USSize | PMinSize;
00445 
00446     XSetNormalHints (display.dpy, display.win, &sizehint);
00447 }
00448 
00449 
00450 
00451 void
00452 HandleError (char *description, int degree)
00453 {
00454   fprintf (stderr,
00455            _("An error has occurred.  The description is below...\n"));
00456   fprintf (stderr, "%s\n", description);
00457 
00458   if (degree == FATAL) {
00459       fprintf (stderr, _("Program aborting...\n"));
00460       exit (-1);
00461     }
00462 }
00463 
00464 void
00465 Fgl_setpixel (int x, int y, int col)
00466 {
00467     int i;
00468     if (clipping_flag)
00469         if (x < xclip_x1 || x > xclip_x2 || y < xclip_y1 || y > xclip_y2)
00470             return;
00471     col &= 0xff;
00472 
00473     i = pixmap_index(x,y);
00474 
00475 #ifdef ALLOW_PIX_DOUBLING
00476     if (pix_double) {
00477         if ((int) pixmap[i] != col)
00478         {
00479             pixmap[i] = (unsigned char) col;
00480             XFillRectangle (display.dpy, display.win,
00481                             display.pixcolour_gc[col], x * 2, y * 2, 2, 2);
00482         }
00483     } else {
00484 #endif
00485         if ((int) pixmap[i] != col)
00486         {
00487             pixmap[i] = (unsigned char) col;
00488             XDrawPoint (display.dpy, display.win,
00489                         display.pixcolour_gc[col], x + borderx, y + bordery);
00490         }
00491 #ifdef ALLOW_PIX_DOUBLING
00492     }
00493 #endif
00494 }
00495 
00496 int
00497 Fgl_getpixel (int x, int y)
00498 {
00499     return pixmap_getpixel (x, y);
00500 }
00501 
00502 void
00503 Fgl_hline (int x1, int y1, int x2, int col)
00504 {
00505     col &= 0xff;
00506     pixmap_hline (x1, y1, x2, col);
00507 #ifdef ALLOW_PIX_DOUBLING
00508     if (pix_double)
00509         XFillRectangle (display.dpy, display.win
00510                         ,display.pixcolour_gc[col], x1 * 2, y1 * 2
00511                         ,(x2 - x1) * 2 + 1, 2);
00512     else
00513 #endif
00514         XDrawLine (display.dpy, display.win
00515                    ,display.pixcolour_gc[col], x1 + borderx
00516                    ,y1 + bordery, x2 + borderx, y1 + bordery);
00517 }
00518 
00519 void
00520 Fgl_line (int x1, int y1, int dummy, int y2, int col)
00521      /* vertical lines only. */
00522 {
00523     col &= 0xff;
00524     pixmap_vline (x1, y1, y2, col);
00525 #ifdef ALLOW_PIX_DOUBLING
00526     if (pix_double)
00527         XFillRectangle (display.dpy, display.win
00528                         ,display.pixcolour_gc[col], x1 * 2, y1 * 2
00529                         ,2, (y2 - y1) * 2 + 1);
00530     else
00531 #endif
00532         XDrawLine (display.dpy, display.win
00533                    ,display.pixcolour_gc[col], x1 + borderx
00534                    ,y1 + bordery, x1 + borderx, y2 + bordery);
00535 }
00536 
00537 void
00538 Fgl_write (int x, int y, char *s)
00539 {
00540   int i;
00541   for (i = 0; i < (int) (strlen (s)); i++)
00542     my_x_putchar (x + i * 8, y, s[i]);
00543 }
00544 
00545 void
00546 open_write (int x, int y, char *s)
00547 {
00548   int i;
00549   for (i = 0; i < (int) (strlen (s)); i++)
00550     open_x_putchar (x + i * 8, y, s[i]);
00551 }
00552 
00553 void
00554 my_x_putchar (int xx, int yy, unsigned char c)
00555 {
00556   int x, y, b;
00557   for (y = 0; y < 8; y++)
00558     {
00559       b = main_font[c * 8 + y];
00560       for (x = 0; x < 8; x++)
00561         {
00562           if ((b & 0x80) == 0)
00563             Fgl_setpixel (xx + x, yy + y, text_bg);
00564           else
00565             Fgl_setpixel (xx + x, yy + y, text_fg);
00566           b = b << 1;
00567         }
00568     }
00569 }
00570 
00571 void
00572 open_x_putchar (int xx, int yy, unsigned char c)
00573 {
00574   int x, y, b;
00575   for (y = 0; y < open_font_height; y++)
00576     {
00577       b = open_font[c * open_font_height + y];
00578       for (x = 0; x < 8; x++)
00579         {
00580           if ((b & 0x80) == 0)
00581             Fgl_setpixel (xx + x, yy + y, text_bg);
00582           else
00583             Fgl_setpixel (xx + x, yy + y, text_fg);
00584           b = b << 1;
00585         }
00586     }
00587 }
00588 
00589 void
00590 Fgl_fillbox (int x1, int y1, int w, int h, int col)
00591 {
00592     if (clipping_flag) {
00593         if (x1 < xclip_x1)
00594             x1 = xclip_x1;
00595         if (x1 + w - 1 > xclip_x2)
00596             w = xclip_x2 - x1 + 1;
00597         if (y1 < xclip_y1)
00598             y1 = xclip_y1;
00599         if (y1 + h - 1 > xclip_y2)
00600             h = xclip_y2 - y1 + 1;
00601     }
00602     col &= 0xff;
00603     pixmap_fillbox (x1, y1, w, h, col);
00604 
00605 #ifdef ALLOW_PIX_DOUBLING
00606     if (pix_double)
00607         XFillRectangle (display.dpy, display.win,
00608                         display.pixcolour_gc[col], x1 * 2, y1 * 2, w * 2, h * 2);
00609     else
00610 #endif
00611         XFillRectangle (display.dpy, display.win,
00612                         display.pixcolour_gc[col], x1 + borderx, y1 + bordery, w, h);
00613 }
00614 
00615 #ifdef USE_IMAGES
00616 
00617 /*
00618  * Instead of transfering a pixmap pixel by pixel, it is much more
00619  * efficient to build an XImage in core and send it in one piece off
00620  * to the X server.
00621  *
00622  * -- GB.
00623  */
00624 
00625 static int
00626 clamp (int x, int low, int high)
00627      /* clamp x to the interval [low, high] */
00628 {
00629   if (x < low)
00630     x = low;
00631   else if (x > high)
00632     x = high;
00633   return x;
00634 }
00635 
00636 /*
00637  * Copy the the sub-image (src_x, src_y, w, h) to the screen at 
00638  * (x0 + x1, y0 + y1).
00639  * `src' is a pointer to the array of pixels.
00640  * `bpl' is the width of that array.
00641  * No clipping performed.
00642  */
00643 void
00644 Fgl_putbox_low (Drawable dst, int x0, int y0, int x1, int y1,
00645                 int w, int h, unsigned char *src, int bpl,
00646                 int src_x, int src_y)
00647 {
00648     XImage *im;
00649     int x, y;
00650 
00651 #ifdef ALLOW_PIX_DOUBLING
00652     const int pmult = pix_double ? 2 : 1;
00653 #else
00654     const int pmult = 1;
00655 #endif
00656 
00657     im = XCreateImage (display.dpy, 0,  /* display and visual */
00658                        DefaultDepth (display.dpy, display.screen),      /* depth */
00659                        ZPixmap, /* format */
00660                        0,               /* offset */
00661                        0,               /* data */
00662                        pmult * w, pmult * h,    /* width and height */
00663                        32, 0);  /* bitmap_pad and bytes_per_line */
00664     /* XXX: assert is not the right way to check for errors - wck */
00665     assert (im != 0);
00666     im->data = (char *) malloc (im->bytes_per_line * pmult * h);
00667     assert (im->data != 0);
00668 
00669     src += src_x + src_y * bpl;
00670 
00671     if (pmult == 1) {
00672         for (y = 0; y < h; y++)
00673             for (x = 0; x < w; x++)
00674                 XPutPixel (im, x, y, colour_table[src[x + y * bpl]]);
00675     } else {
00676         for (y = 0; y < h; y++)
00677             for (x = 0; x < w; x++)
00678             {
00679                 unsigned long c = colour_table[src[x + y * bpl]];
00680 
00681                 XPutPixel (im, 2 * x + 0, 2 * y + 0, c);
00682                 XPutPixel (im, 2 * x + 0, 2 * y + 1, c);
00683                 XPutPixel (im, 2 * x + 1, 2 * y + 0, c);
00684                 XPutPixel (im, 2 * x + 1, 2 * y + 1, c);
00685             }
00686     }
00687 
00688     if (dst == display.win) {
00689         pixmap_putbox (src, 0, 0, bpl, x1, y1, w, h);
00690     }
00691 
00692     XPutImage (display.dpy, dst, display.pixcolour_gc[0], im, 0, 0,
00693                x0 + pmult * x1, y0 + pmult * y1, pmult * w, pmult * h);
00694 
00695     XDestroyImage (im);
00696 }
00697 
00698 void
00699 Fgl_putbox (int x, int y, int w, int h, void *buf)
00700 {
00701     int c_x0 = clipping_flag ? xclip_x1 : 0;
00702     int c_x1 = clipping_flag ? xclip_x2 : display.winW - 1;
00703     int c_y0 = clipping_flag ? xclip_y1 : 0;
00704     int c_y1 = clipping_flag ? xclip_y2 : display.winH - 1;
00705     int x1 = clamp (x, c_x0, c_x1);
00706     int y1 = clamp (y, c_y0, c_y1);
00707     int x2 = clamp (x + w, c_x0, c_x1 + 1);
00708     int y2 = clamp (y + h, c_y0, c_y1 + 1);
00709 
00710     if (x2 > x1 && y2 > y1)
00711         Fgl_putbox_low (display.win, borderx, bordery, x1, y1, x2 - x1, 
00712                         y2 - y1, (unsigned char *) buf, w, x1 - x, y1 - y);
00713 }
00714 
00715 #else
00716 
00717 void
00718 Fgl_putbox (int x1, int y1, int w, int h, void *buf)
00719 {
00720     unsigned char *b;
00721     b = (unsigned char *) buf;
00722     int x, y;
00723     for (y = y1; y < y1 + h; y++)
00724         for (x = x1; x < x1 + w; x++)
00725             Fgl_setpixel (x, y, *(b++));
00726 }
00727 
00728 #endif
00729 
00730 void
00731 Fgl_getbox (int x1, int y1, int w, int h, void *buf)
00732 {
00733     unsigned char *b;
00734     int x, y;
00735     b = (unsigned char *) buf;
00736     for (y = y1; y < y1 + h; y++)
00737         for (x = x1; x < x1 + w; x++)
00738             *(b++) = (unsigned char) Fgl_getpixel (x, y);
00739 }
00740 
00741 void
00742 HandleEvent (XEvent * event)
00743 {
00744     XEvent loop_ev; /* for clearing the queue of events */
00745 
00746     switch (event->type)
00747     {
00748     case KeyPress:
00749         {
00750             XKeyEvent *key_event = (XKeyEvent *) event;
00751             char buf[128];
00752             KeySym ks;
00753             XComposeStatus status;
00754             XLookupString (key_event, buf, 128, &ks, &status);
00755             x_key_shifted = ShiftMask & key_event->state;
00756             x_key_value = buf[0];
00757             switch (ks) {
00758             case XK_Left:
00759                 x_key_value = 1;
00760                 break;
00761             case XK_Down:
00762                 x_key_value = 2;
00763                 break;
00764             case XK_Up:
00765                 x_key_value = 3;
00766                 break;
00767             case XK_Right:
00768                 x_key_value = 4;
00769                 break;
00770 #if defined (commentout)
00771                 /* GCS:  What the hell is this??? */
00772             case 'C':
00773                 if (!confine_pointer(-10,-10,200,200))
00774                     unconfine_pointer();
00775                 break;
00776 #endif
00777             case XK_BackSpace:
00778             case XK_Delete:
00779                 x_key_value = 127;
00780                 break;
00781             }
00782         }
00783         break;
00784 
00785     case MotionNotify: 
00786         {
00787             XMotionEvent *ev = (XMotionEvent *) event;
00788 
00789             while (XCheckMaskEvent(display.dpy,PointerMotionMask,&loop_ev)) {
00790                 ev = (XMotionEvent *) &loop_ev;
00791             }
00792 #ifdef DEBUG_X11_MOUSE
00793             printf("pointer motion event\n");
00794 #endif
00795             if (ev->state & Button2Mask)
00796                 drag_screen();
00797 
00798         }
00799         break;
00800 
00801     case ButtonPress:
00802         {
00803             XButtonEvent *ev = (XButtonEvent *) event;
00804             if ((ev->state & ShiftMask) != 0)
00805                 cs_mouse_shifted = 1;
00806             else
00807                 cs_mouse_shifted = 0;
00808 #ifdef DEBUG_X11_MOUSE
00809             printf("button press: ev->button = %d\n",ev->button);
00810 #endif
00811 #if defined (commentout)
00812             mouse_button = ev->button;
00813 #endif
00814             switch (ev->button) {
00815             case Button1:
00816                 mouse_button = LC_MOUSE_LEFTBUTTON | LC_MOUSE_PRESS;
00817                 break;
00818             case Button2:
00819                 mouse_button = LC_MOUSE_MIDDLEBUTTON | LC_MOUSE_PRESS;
00820                 break;
00821             case Button3:
00822                 mouse_button = LC_MOUSE_RIGHTBUTTON | LC_MOUSE_PRESS;
00823                 break;
00824 
00825             /* Wheel mouse support 
00826                Move further for Shift (in main.c: process_keystrokes() ),
00827                left to right instead of up and down for Control */
00828 
00829             case Button4:  /* Up (3); Left (1) if Control */
00830                 x_key_shifted = ShiftMask & ev->state;
00831                 x_key_value = (ControlMask & ev->state) ? 1 : 3; 
00832                 break; 
00833             case Button5: /* Down (4); Right (2) if control */
00834                 x_key_shifted = ShiftMask & ev->state;
00835                 x_key_value = (ControlMask & ev->state) ? 4 : 2;
00836                 break;
00837 
00838             /* XFree86-3 only supports 5 buttons, no Button6 or higher */
00839 
00840             }
00841             cs_mouse_handler (mouse_button, 0, 0);
00842             mouse_button = 0;
00843         }
00844         break;
00845 
00846     case ButtonRelease:
00847         {
00848             XButtonEvent *ev = (XButtonEvent *) event;
00849             mouse_button = ev->button; 
00850 #ifdef DEBUG_X11_MOUSE
00851             printf("button release: ev->button = %d\n",ev->button);
00852 #endif
00853             switch (ev->button) {
00854             case Button1:
00855                 mouse_button = LC_MOUSE_LEFTBUTTON | LC_MOUSE_RELEASE;
00856                 break;
00857             case Button2:
00858                 mouse_button = LC_MOUSE_MIDDLEBUTTON | LC_MOUSE_RELEASE;
00859                 break;
00860             case Button3:
00861                 mouse_button = LC_MOUSE_RIGHTBUTTON | LC_MOUSE_RELEASE;
00862                 break;
00863             }
00864             cs_mouse_handler (mouse_button, 0, 0);
00865             mouse_button = 0;
00866         }
00867         break;
00868 
00869     case Expose:
00870         {
00871             XExposeEvent *ev = (XExposeEvent *) event;
00872             int gx1,gy1,gx2,gy2;
00873             gx1 = ev->x;
00874             gy1 = ev->y;
00875             gx2 = ev->x + ev->width;
00876             gy2 = ev->y + ev->height;
00877 
00878             /* Coalesce waiting exposes into single redraw */
00879             while (XCheckMaskEvent(display.dpy,ExposureMask,&loop_ev)) {
00880                 ev = (XExposeEvent *) &loop_ev;
00881                 gx1 = min_int (gx1,ev->x);
00882                 gy1 = min_int (gy1,ev->y);
00883                 gx2 = max_int (gx2,ev->x + ev->width);
00884                 gy2 = max_int (gy2,ev->y + ev->height);
00885             }
00886             if (suppress_next_expose) {
00887                 suppress_next_expose = 0;
00888                 break;
00889             }
00890             refresh_screen (gx1,gy1,gx2,gy2);
00891         }
00892         break;
00893 
00894     case ConfigureNotify:
00895         {
00896             XConfigureEvent *ev = (XConfigureEvent *) event;
00897 
00898             while (XCheckTypedEvent(display.dpy, ConfigureNotify, &loop_ev)) {
00899                 ev = (XConfigureEvent *) &loop_ev;
00900             }
00901             resize_geometry (ev->width, ev->height);
00902         }
00903         break;
00904     }
00905     //fprintf(stderr,"Handler fell through, event->type = %d\n",event->type);
00906 }
00907 
00908 #undef DEBUG_X11_MOUSE
00909 
00910 void
00911 refresh_screen (int x1, int y1, int x2, int y2)         /* bounds of refresh area */
00912 {
00913 #ifdef USE_IMAGES
00914   int wx1 = x1-borderx < 0 ? 0 : x1-borderx;
00915   int wy1 = y1-bordery < 0 ? 0 : y1-bordery;
00916   int wx2 = x2-borderx > pixmap_width ? pixmap_width : x2-borderx;
00917   int wy2 = y2-bordery > pixmap_height ? pixmap_height : y2-bordery;
00918   if (wx2-wx1 <= 0 || wy2-wy1 <= 0) {
00919       /* Note: the "< 0" part can happen for when x1 is in the right border, 
00920          or when y1 is in the left border. */
00921       return;
00922   }
00923   Fgl_putbox_low (display.win, borderx, bordery, wx1, wy1, 
00924                   wx2 - wx1, wy2 - wy1, (unsigned char*) pixmap, 
00925                   pixmap_width, wx1, wy1);
00926 #else
00927   int x, y;
00928 #ifdef ALLOW_PIX_DOUBLING
00929   if (pix_double)
00930     {
00931       for (y = y1; y < y2; y++)
00932         for (x = x1; x < x2; x++)
00933           XFillRectangle (display.dpy, display.win
00934                           ,display.pixcolour_gc[*(pixmap + x + y
00935                             * (640 + BORDERX)) & 0xff], x * 2, y * 2, 2, 2);
00936     }
00937   else
00938     {
00939 #endif
00940       for (y = y1; y < y2; y++)
00941         for (x = x1; x < x2; x++)
00942           XDrawPoint (display.dpy, display.win
00943                       ,display.pixcolour_gc[*(pixmap
00944                                   + x + y * (640 + BORDERX)) & 0xff], x, y);
00945 #ifdef ALLOW_PIX_DOUBLING
00946     }
00947 #endif /* ALLOW_PIX_DOUBLING */
00948 #endif /* USE_IMAGES */
00949 }
00950 
00951 void
00952 Fgl_enableclipping (void)
00953 {
00954   clipping_flag = 1;
00955 }
00956 
00957 void
00958 Fgl_setclippingwindow (int x1, int y1, int x2, int y2)
00959 {
00960   xclip_x1 = x1;
00961   xclip_y1 = y1;
00962   xclip_x2 = x2;
00963   xclip_y2 = y2;
00964 }
00965 
00966 void
00967 Fgl_disableclipping (void)
00968 {
00969   clipping_flag = 0;
00970 }
00971 
00972 void
00973 do_call_event (int wait)
00974 {
00975   int dummy_int, x, y;
00976   Window dummy_win;
00977   XEvent xev;
00978   if (XPending (display.dpy))
00979     {
00980       XNextEvent (display.dpy, &xev);
00981       HandleEvent (&xev);
00982     }
00983   else if (wait)
00984     lc_usleep (1000);
00985 
00986   /* WCK: this could possibly be better handled with a MotionEvent */
00987   XQueryPointer (display.dpy, display.win, &dummy_win, &dummy_win
00988               ,&dummy_int, &dummy_int, &x, &y, (unsigned int *) &dummy_int);
00989 #ifdef ALLOW_PIX_DOUBLING
00990   if (pix_double)
00991     {
00992       x /= 2;
00993       y /= 2;
00994     }
00995   else
00996     {
00997 #endif
00998       x -= borderx;
00999       y -= bordery;
01000 #ifdef ALLOW_PIX_DOUBLING
01001     }
01002 #endif
01003   if (x != cs_mouse_x || y != cs_mouse_y)
01004   cs_mouse_handler (0, x - cs_mouse_x, y - cs_mouse_y);  
01005   /* WCK: no longer passing mouse_button, 0 used instead. Presses are handled
01006    in the event loop */
01007 }
01008 
01009 void
01010 call_event (void)
01011 {
01012   do_call_event (0);
01013 }
01014 
01015 void
01016 call_wait_event (void)
01017 {
01018   do_call_event (1);
01019 }
01020 
01021 int 
01022 lc_get_keystroke (void)
01023 {
01024     int q;
01025     call_event ();
01026     q = x_key_value;
01027     x_key_value = 0;
01028     return q;
01029 }
01030 
01031 
01032 /* init_full_mouse is called just before the main client loop. */
01033 
01034 /* XXX: This needs a much better name */
01035 /* GCS: Yes it does, b/c it means something different for svgalib */
01036 void 
01037 init_x_mouse (void) 
01038 {
01039   XSelectInput (display.dpy, display.win,
01040                 KeyPressMask | ButtonPressMask | ButtonReleaseMask
01041                 | ExposureMask | StructureNotifyMask | ButtonMotionMask);
01042 }
01043 
01044 void
01045 draw_border (void)
01046 {
01047     int col = TEXT_BG_COLOUR & 0xff;
01048     int pd = pix_double + 1;
01049     if (borderx > 0) {
01050         XFillRectangle (display.dpy, display.win, display.pixcolour_gc[col],
01051                         0, bordery, borderx, display.winH - 2*bordery);
01052         XFillRectangle (display.dpy, display.win, display.pixcolour_gc[col],
01053                         display.winW - borderx, bordery,
01054                         borderx, display.winH - 2*bordery);
01055     }
01056     if (bordery > 0) {
01057         XFillRectangle (display.dpy, display.win, display.pixcolour_gc[col],
01058                         0, 0, display.winW, bordery);
01059         XFillRectangle (display.dpy, display.win, display.pixcolour_gc[col],
01060                         0, display.winH - bordery, display.winW, bordery);
01061     }
01062 }
01063 
01064 #ifdef USE_PIXMAPS
01065 
01066 void
01067 init_icon_pixmap (short type)
01068 {
01069     unsigned char *g;
01070 #if !defined USE_IMAGES
01071     int x, y;
01072 #endif
01073     int grp;
01074 
01075     grp = get_group_of_type(type);
01076 
01077 #ifdef ALLOW_PIX_DOUBLING
01078     if (pix_double) {
01079         icon_pixmap[type] 
01080                 = XCreatePixmap (display.dpy, display.win,
01081                                  main_groups[grp].size * 16 * 2,
01082                                  main_groups[grp].size * 16 * 2,
01083                                  DefaultDepth (display.dpy,
01084                                                display.screen));
01085     } else {
01086 #endif
01087         icon_pixmap[type] 
01088                 = XCreatePixmap (display.dpy, display.win,
01089                                  main_groups[grp].size * 16,
01090                                  main_groups[grp].size * 16,
01091                                  DefaultDepth (display.dpy,
01092                                                display.screen));
01093 #ifdef ALLOW_PIX_DOUBLING
01094     }
01095 #endif
01096 
01097     g = (unsigned char *) main_types[type].graphic;
01098 
01099 #ifdef USE_IMAGES
01100     Fgl_putbox_low (icon_pixmap[type],
01101                     0, 0, 0, 0, main_groups[grp].size * 16, 
01102                     main_groups[grp].size * 16,
01103                     g, main_groups[grp].size * 16,
01104                     0, 0);
01105 #else
01106 #ifdef ALLOW_PIX_DOUBLING
01107     if (pix_double)     {
01108         for (y = 0; y < main_groups[grp].size * 16; y++)
01109             for (x = 0; x < main_groups[grp].size * 16; x++)
01110                 XFillRectangle (display.dpy, icon_pixmap[type]
01111                                 ,display.pixcolour_gc[*(g++)]
01112                                 ,x * 2, y * 2, 2, 2);
01113     } else {
01114 #endif
01115         for (y = 0; y < main_groups[grp].size * 16; y++)
01116             for (x = 0; x < main_groups[grp].size * 16; x++)
01117                 XDrawPoint (display.dpy, icon_pixmap[type]
01118                             ,display.pixcolour_gc[*(g++)], x, y);
01119 #ifdef ALLOW_PIX_DOUBLING
01120     }
01121 #endif /* ALLOW_PIX_DOUBLING */
01122 #endif /* USE_IMAGES */
01123 }
01124 
01125 #endif /* USE_PIXMAPS */

Generated on Sun Dec 26 11:23:25 2004 for lincity by  doxygen 1.3.9.1