00001
00002
00003
00004
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
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
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
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
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
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];
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,
00359 DefaultVisual (display.dpy, display.screen),
00360
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
00372
00373
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
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
00405 wmhints.flags = InputHint;
00406 wmhints.input = True;
00407 XSetWMHints (display.dpy, display.win, &wmhints);
00408
00409
00410
00411
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
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
00619
00620
00621
00622
00623
00624
00625 static int
00626 clamp (int x, int low, int high)
00627
00628 {
00629 if (x < low)
00630 x = low;
00631 else if (x > high)
00632 x = high;
00633 return x;
00634 }
00635
00636
00637
00638
00639
00640
00641
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,
00658 DefaultDepth (display.dpy, display.screen),
00659 ZPixmap,
00660 0,
00661 0,
00662 pmult * w, pmult * h,
00663 32, 0);
00664
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;
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
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
00826
00827
00828
00829 case Button4:
00830 x_key_shifted = ShiftMask & ev->state;
00831 x_key_value = (ControlMask & ev->state) ? 1 : 3;
00832 break;
00833 case Button5:
00834 x_key_shifted = ShiftMask & ev->state;
00835 x_key_value = (ControlMask & ev->state) ? 4 : 2;
00836 break;
00837
00838
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
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
00906 }
00907
00908 #undef DEBUG_X11_MOUSE
00909
00910 void
00911 refresh_screen (int x1, int y1, int x2, int y2)
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
00920
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
00948 #endif
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
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
01006
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
01033
01034
01035
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
01122 #endif
01123 }
01124
01125 #endif