| 1 | greg | 2.25 | /* Copyright (c) 1995 Regents of the University of California */ | 
| 2 | greg | 2.4 |  | 
| 3 | greg | 1.1 | #ifndef lint | 
| 4 |  |  | static char SCCSid[] = "$SunId$ LBL"; | 
| 5 |  |  | #endif | 
| 6 |  |  |  | 
| 7 |  |  | /* | 
| 8 | greg | 2.4 | *  x11.c - driver for X-windows version 11 | 
| 9 | greg | 1.1 | * | 
| 10 | greg | 1.4 | *     Jan 1990 | 
| 11 | greg | 1.1 | */ | 
| 12 |  |  |  | 
| 13 | gregl | 2.27 | #include  "standard.h" | 
| 14 | greg | 1.1 | #include  <sys/ioctl.h> | 
| 15 | greg | 2.23 | #ifdef sparc | 
| 16 |  |  | #include  <sys/conf.h> | 
| 17 |  |  | #include  <sys/file.h> | 
| 18 |  |  | #include  <sys/filio.h> | 
| 19 |  |  | #endif | 
| 20 | greg | 2.25 | #if  !defined(FNDELAY) && defined(O_NONBLOCK) | 
| 21 |  |  | #define  FNDELAY  O_NONBLOCK | 
| 22 |  |  | #endif | 
| 23 | greg | 1.1 |  | 
| 24 |  |  | #include  <X11/Xlib.h> | 
| 25 | greg | 1.4 | #include  <X11/cursorfont.h> | 
| 26 |  |  | #include  <X11/Xutil.h> | 
| 27 | greg | 1.1 |  | 
| 28 |  |  | #include  "color.h" | 
| 29 |  |  | #include  "driver.h" | 
| 30 |  |  | #include  "x11twind.h" | 
| 31 | greg | 1.18 | #include  "x11icon.h" | 
| 32 | greg | 1.1 |  | 
| 33 | greg | 2.6 | #define GAMMA           2.2             /* default exponent correction */ | 
| 34 | greg | 1.1 |  | 
| 35 | greg | 1.6 | #define MINWIDTH        (32*COMCW)      /* minimum graphics window width */ | 
| 36 | greg | 2.9 | #define MINHEIGHT       (MINWIDTH/2)    /* minimum graphics window height */ | 
| 37 | greg | 1.4 |  | 
| 38 | greg | 1.1 | #define BORWIDTH        5               /* border width */ | 
| 39 |  |  | #define COMHEIGHT       (COMLH*COMCH)   /* command line height (pixels) */ | 
| 40 |  |  |  | 
| 41 |  |  | #define COMFN           "8x13"          /* command line font name */ | 
| 42 |  |  | #define COMLH           3               /* number of command lines */ | 
| 43 |  |  | #define COMCW           8               /* approx. character width (pixels) */ | 
| 44 |  |  | #define COMCH           14              /* approx. character height (pixels) */ | 
| 45 |  |  |  | 
| 46 | greg | 1.4 | #define  ourscreen      DefaultScreen(ourdisplay) | 
| 47 |  |  | #define  ourroot        RootWindow(ourdisplay,ourscreen) | 
| 48 |  |  |  | 
| 49 |  |  | #define  levptr(etype)  ((etype *)¤tevent) | 
| 50 | greg | 1.1 |  | 
| 51 | greg | 1.4 | static XEvent  currentevent;            /* current event */ | 
| 52 | greg | 1.1 |  | 
| 53 |  |  | static int  ncolors = 0;                /* color table size */ | 
| 54 | greg | 2.8 | static int  mapped = 0;                 /* window is mapped? */ | 
| 55 | greg | 1.17 | static unsigned long  *pixval = NULL;   /* allocated pixels */ | 
| 56 | greg | 2.3 | static unsigned long  ourblack=0, ourwhite=1; | 
| 57 | greg | 1.1 |  | 
| 58 |  |  | static Display  *ourdisplay = NULL;     /* our display */ | 
| 59 |  |  |  | 
| 60 | greg | 2.2 | static XVisualInfo  ourvinfo;           /* our visual information */ | 
| 61 | greg | 1.6 |  | 
| 62 | greg | 1.1 | static Window  gwind = 0;               /* our graphics window */ | 
| 63 |  |  |  | 
| 64 |  |  | static Cursor  pickcursor = 0;          /* cursor used for picking */ | 
| 65 |  |  |  | 
| 66 | greg | 1.4 | static int  gwidth, gheight;            /* graphics window size */ | 
| 67 | greg | 1.1 |  | 
| 68 | greg | 2.17 | static int  comheight;                  /* desired comline height */ | 
| 69 | greg | 1.1 | static TEXTWIND  *comline = NULL;       /* our command line */ | 
| 70 |  |  |  | 
| 71 |  |  | static char  c_queue[64];               /* input queue */ | 
| 72 |  |  | static int  c_first = 0;                /* first character in queue */ | 
| 73 |  |  | static int  c_last = 0;                 /* last character in queue */ | 
| 74 |  |  |  | 
| 75 |  |  | static GC  ourgc = 0;                   /* our graphics context for drawing */ | 
| 76 |  |  |  | 
| 77 | greg | 1.6 | static Colormap ourmap = 0;             /* our color map */ | 
| 78 | greg | 1.1 |  | 
| 79 | greg | 2.19 | #define IC_X11          0 | 
| 80 |  |  | #define IC_IOCTL        1 | 
| 81 |  |  | #define IC_READ         2 | 
| 82 |  |  |  | 
| 83 |  |  | static int  inpcheck;                   /* whence to check input */ | 
| 84 |  |  |  | 
| 85 | greg | 2.21 | extern char  *malloc(); | 
| 86 | greg | 1.1 |  | 
| 87 | greg | 1.14 | static int  x11_close(), x11_clear(), x11_paintr(), x11_errout(), | 
| 88 | greg | 1.5 | x11_getcur(), x11_comout(), x11_comin(), x11_flush(); | 
| 89 | greg | 1.1 |  | 
| 90 | greg | 2.17 | static int  std_comin(), std_comout(); | 
| 91 |  |  |  | 
| 92 | greg | 1.1 | static struct driver  x11_driver = { | 
| 93 |  |  | x11_close, x11_clear, x11_paintr, x11_getcur, | 
| 94 | greg | 2.17 | NULL, NULL, x11_flush, 1.0 | 
| 95 | greg | 1.1 | }; | 
| 96 |  |  |  | 
| 97 | greg | 2.13 | static int  getpixels(), xnewcolr(), freepixels(), resizewindow(), | 
| 98 |  |  | getevent(), getkey(), fixwindow(), x11_getc(); | 
| 99 | greg | 2.11 | static unsigned long  true_pixel(); | 
| 100 | greg | 1.1 |  | 
| 101 | greg | 2.11 |  | 
| 102 | greg | 1.1 | struct driver * | 
| 103 |  |  | x11_init(name, id)              /* initialize driver */ | 
| 104 |  |  | char  *name, *id; | 
| 105 |  |  | { | 
| 106 | greg | 2.6 | extern char  *getenv(); | 
| 107 |  |  | char  *gv; | 
| 108 | greg | 1.6 | int  nplanes; | 
| 109 | greg | 1.10 | XSetWindowAttributes    ourwinattr; | 
| 110 | greg | 1.4 | XWMHints  ourxwmhints; | 
| 111 | greg | 1.12 | XSizeHints      oursizhints; | 
| 112 | greg | 2.17 | /* open display server */ | 
| 113 | greg | 1.1 | ourdisplay = XOpenDisplay(NULL); | 
| 114 |  |  | if (ourdisplay == NULL) { | 
| 115 | gregl | 2.27 | eputs("cannot open X-windows; DISPLAY variable set?\n"); | 
| 116 | greg | 1.1 | return(NULL); | 
| 117 |  |  | } | 
| 118 | greg | 2.2 | /* find a usable visual */ | 
| 119 | greg | 1.6 | nplanes = DisplayPlanes(ourdisplay, ourscreen); | 
| 120 | greg | 2.4 | if (XMatchVisualInfo(ourdisplay,ourscreen, | 
| 121 | greg | 2.26 | nplanes>12?nplanes:24,TrueColor,&ourvinfo) || | 
| 122 | greg | 2.4 | XMatchVisualInfo(ourdisplay,ourscreen, | 
| 123 | greg | 2.26 | nplanes>12?nplanes:24,DirectColor,&ourvinfo)) { | 
| 124 | greg | 2.4 | ourblack = 0; | 
| 125 |  |  | ourwhite = ourvinfo.red_mask | | 
| 126 |  |  | ourvinfo.green_mask | | 
| 127 |  |  | ourvinfo.blue_mask ; | 
| 128 |  |  | } else { | 
| 129 | greg | 2.2 | if (nplanes < 4) { | 
| 130 | gregl | 2.27 | eputs("not enough colors\n"); | 
| 131 | greg | 1.6 | return(NULL); | 
| 132 | greg | 2.4 | } | 
| 133 |  |  | if (!XMatchVisualInfo(ourdisplay,ourscreen, | 
| 134 | greg | 2.2 | nplanes,PseudoColor,&ourvinfo) && | 
| 135 |  |  | !XMatchVisualInfo(ourdisplay,ourscreen, | 
| 136 |  |  | nplanes,GrayScale,&ourvinfo)) { | 
| 137 | gregl | 2.27 | eputs("unsupported visual type\n"); | 
| 138 | greg | 2.2 | return(NULL); | 
| 139 | greg | 1.6 | } | 
| 140 | greg | 2.3 | ourblack = BlackPixel(ourdisplay,ourscreen); | 
| 141 |  |  | ourwhite = WhitePixel(ourdisplay,ourscreen); | 
| 142 |  |  | } | 
| 143 | greg | 2.6 | /* set gamma */ | 
| 144 | greg | 2.14 | if ((gv = XGetDefault(ourdisplay, "radiance", "gamma")) != NULL | 
| 145 | greg | 2.18 | || (gv = getenv("DISPLAY_GAMMA")) != NULL) | 
| 146 | greg | 2.6 | make_gmap(atof(gv)); | 
| 147 |  |  | else | 
| 148 |  |  | make_gmap(GAMMA); | 
| 149 | greg | 2.17 | /* X11 command line or no? */ | 
| 150 |  |  | if (!strcmp(name, "x11")) | 
| 151 |  |  | comheight = COMHEIGHT; | 
| 152 | greg | 2.25 | else /* "x11d" */ { | 
| 153 | greg | 2.17 | comheight = 0; | 
| 154 | greg | 2.25 | #ifndef  FNDELAY | 
| 155 | gregl | 2.27 | eputs("warning: x11d driver not fully functional on this machine\n"); | 
| 156 | greg | 2.25 | #endif | 
| 157 |  |  | } | 
| 158 | greg | 2.6 | /* open window */ | 
| 159 | greg | 1.12 | ourwinattr.background_pixel = ourblack; | 
| 160 | greg | 1.10 | ourwinattr.border_pixel = ourblack; | 
| 161 | greg | 2.4 | /* this is stupid */ | 
| 162 | greg | 2.2 | ourwinattr.colormap = XCreateColormap(ourdisplay, ourroot, | 
| 163 |  |  | ourvinfo.visual, AllocNone); | 
| 164 | greg | 1.10 | gwind = XCreateWindow(ourdisplay, ourroot, 0, 0, | 
| 165 | greg | 1.4 | DisplayWidth(ourdisplay,ourscreen)-2*BORWIDTH, | 
| 166 |  |  | DisplayHeight(ourdisplay,ourscreen)-2*BORWIDTH, | 
| 167 | greg | 2.2 | BORWIDTH, ourvinfo.depth, InputOutput, ourvinfo.visual, | 
| 168 |  |  | CWBackPixel|CWBorderPixel|CWColormap, &ourwinattr); | 
| 169 | greg | 1.4 | if (gwind == 0) { | 
| 170 | gregl | 2.27 | eputs("cannot create window\n"); | 
| 171 | greg | 1.4 | return(NULL); | 
| 172 |  |  | } | 
| 173 | greg | 2.4 | XStoreName(ourdisplay, gwind, id); | 
| 174 | greg | 1.10 | /* create a cursor */ | 
| 175 |  |  | pickcursor = XCreateFontCursor(ourdisplay, XC_diamond_cross); | 
| 176 | greg | 1.4 | ourgc = XCreateGC(ourdisplay, gwind, 0, NULL); | 
| 177 | greg | 1.18 | ourxwmhints.flags = InputHint|IconPixmapHint; | 
| 178 | greg | 1.4 | ourxwmhints.input = True; | 
| 179 | greg | 1.18 | ourxwmhints.icon_pixmap = XCreateBitmapFromData(ourdisplay, | 
| 180 |  |  | gwind, x11icon_bits, x11icon_width, x11icon_height); | 
| 181 | greg | 1.4 | XSetWMHints(ourdisplay, gwind, &ourxwmhints); | 
| 182 | greg | 1.12 | oursizhints.min_width = MINWIDTH; | 
| 183 | greg | 2.17 | oursizhints.min_height = MINHEIGHT+comheight; | 
| 184 | greg | 1.12 | oursizhints.flags = PMinSize; | 
| 185 |  |  | XSetNormalHints(ourdisplay, gwind, &oursizhints); | 
| 186 | greg | 1.4 | XSelectInput(ourdisplay, gwind, ExposureMask); | 
| 187 |  |  | XMapWindow(ourdisplay, gwind); | 
| 188 | greg | 1.17 | XWindowEvent(ourdisplay, gwind, ExposureMask, levptr(XEvent)); | 
| 189 | greg | 1.4 | gwidth = levptr(XExposeEvent)->width; | 
| 190 | greg | 2.17 | gheight = levptr(XExposeEvent)->height - comheight; | 
| 191 | greg | 1.4 | x11_driver.xsiz = gwidth < MINWIDTH ? MINWIDTH : gwidth; | 
| 192 |  |  | x11_driver.ysiz = gheight < MINHEIGHT ? MINHEIGHT : gheight; | 
| 193 | greg | 1.1 | x11_driver.inpready = 0; | 
| 194 | greg | 2.8 | mapped = 1; | 
| 195 | greg | 2.17 | /* set i/o vectors */ | 
| 196 |  |  | if (comheight) { | 
| 197 |  |  | x11_driver.comin = x11_comin; | 
| 198 |  |  | x11_driver.comout = x11_comout; | 
| 199 | gregl | 2.27 | erract[COMMAND].pf = x11_comout; | 
| 200 |  |  | if (erract[WARNING].pf != NULL) | 
| 201 |  |  | erract[WARNING].pf = x11_errout; | 
| 202 | greg | 2.19 | inpcheck = IC_X11; | 
| 203 | greg | 2.17 | } else { | 
| 204 |  |  | x11_driver.comin = std_comin; | 
| 205 |  |  | x11_driver.comout = std_comout; | 
| 206 | gregl | 2.27 | erract[COMMAND].pf = std_comout; | 
| 207 | greg | 2.19 | inpcheck = IC_IOCTL; | 
| 208 | greg | 2.17 | } | 
| 209 | greg | 1.1 | return(&x11_driver); | 
| 210 |  |  | } | 
| 211 |  |  |  | 
| 212 |  |  |  | 
| 213 |  |  | static | 
| 214 |  |  | x11_close()                     /* close our display */ | 
| 215 |  |  | { | 
| 216 | gregl | 2.27 | erract[COMMAND].pf = NULL;              /* reset error vectors */ | 
| 217 |  |  | if (erract[WARNING].pf != NULL) | 
| 218 |  |  | erract[WARNING].pf = wputs; | 
| 219 | greg | 1.1 | if (ourdisplay == NULL) | 
| 220 |  |  | return; | 
| 221 |  |  | if (comline != NULL) { | 
| 222 |  |  | xt_close(comline); | 
| 223 |  |  | comline = NULL; | 
| 224 |  |  | } | 
| 225 | greg | 1.8 | freepixels(); | 
| 226 |  |  | XFreeGC(ourdisplay, ourgc); | 
| 227 |  |  | XDestroyWindow(ourdisplay, gwind); | 
| 228 |  |  | gwind = 0; | 
| 229 |  |  | ourgc = 0; | 
| 230 | greg | 1.1 | XFreeCursor(ourdisplay, pickcursor); | 
| 231 |  |  | XCloseDisplay(ourdisplay); | 
| 232 |  |  | ourdisplay = NULL; | 
| 233 |  |  | } | 
| 234 |  |  |  | 
| 235 |  |  |  | 
| 236 |  |  | static | 
| 237 |  |  | x11_clear(xres, yres)                   /* clear our display */ | 
| 238 |  |  | int  xres, yres; | 
| 239 |  |  | { | 
| 240 | greg | 1.12 | /* check limits */ | 
| 241 |  |  | if (xres < MINWIDTH) | 
| 242 |  |  | xres = MINWIDTH; | 
| 243 |  |  | if (yres < MINHEIGHT) | 
| 244 |  |  | yres = MINHEIGHT; | 
| 245 |  |  | /* resize window */ | 
| 246 |  |  | if (xres != gwidth || yres != gheight) { | 
| 247 | greg | 1.4 | XSelectInput(ourdisplay, gwind, 0); | 
| 248 | greg | 2.17 | XResizeWindow(ourdisplay, gwind, xres, yres+comheight); | 
| 249 | greg | 1.1 | gwidth = xres; | 
| 250 |  |  | gheight = yres; | 
| 251 | greg | 1.8 | XFlush(ourdisplay); | 
| 252 |  |  | sleep(2);                       /* wait for window manager */ | 
| 253 | greg | 1.4 | XSync(ourdisplay, 1);           /* discard input */ | 
| 254 |  |  | } | 
| 255 | greg | 1.13 | XClearWindow(ourdisplay, gwind); | 
| 256 |  |  | /* reinitialize color table */ | 
| 257 | greg | 2.2 | if (ourvinfo.class == PseudoColor || ourvinfo.class == GrayScale) | 
| 258 | greg | 1.13 | if (getpixels() == 0) | 
| 259 | gregl | 2.27 | eputs("cannot allocate colors\n"); | 
| 260 | greg | 1.13 | else | 
| 261 |  |  | new_ctab(ncolors); | 
| 262 | greg | 1.12 | /* get new command line */ | 
| 263 | greg | 1.13 | if (comline != NULL) | 
| 264 |  |  | xt_close(comline); | 
| 265 | greg | 2.17 | if (comheight) { | 
| 266 |  |  | comline = xt_open(ourdisplay, gwind, 0, gheight, gwidth, | 
| 267 |  |  | comheight, 0, ourblack, ourwhite, COMFN); | 
| 268 |  |  | if (comline == NULL) { | 
| 269 | gregl | 2.27 | eputs("cannot open command line window\n"); | 
| 270 | greg | 2.17 | quit(1); | 
| 271 |  |  | } | 
| 272 |  |  | XSelectInput(ourdisplay, comline->w, ExposureMask); | 
| 273 | greg | 1.12 | /* remove earmuffs */ | 
| 274 | greg | 2.17 | XSelectInput(ourdisplay, gwind, | 
| 275 | greg | 1.4 | StructureNotifyMask|ExposureMask|KeyPressMask|ButtonPressMask); | 
| 276 | greg | 2.17 | } else                                  /* remove earmuffs */ | 
| 277 |  |  | XSelectInput(ourdisplay, gwind, | 
| 278 |  |  | StructureNotifyMask|ExposureMask|ButtonPressMask); | 
| 279 | greg | 1.1 | } | 
| 280 |  |  |  | 
| 281 |  |  |  | 
| 282 |  |  | static | 
| 283 |  |  | x11_paintr(col, xmin, ymin, xmax, ymax)         /* fill a rectangle */ | 
| 284 |  |  | COLOR  col; | 
| 285 |  |  | int  xmin, ymin, xmax, ymax; | 
| 286 |  |  | { | 
| 287 | greg | 1.6 | unsigned long  pixel; | 
| 288 | greg | 1.1 |  | 
| 289 | greg | 2.8 | if (!mapped) | 
| 290 |  |  | return; | 
| 291 | greg | 1.6 | if (ncolors > 0) | 
| 292 |  |  | pixel = pixval[get_pixel(col, xnewcolr)]; | 
| 293 | greg | 2.8 | else | 
| 294 | greg | 1.6 | pixel = true_pixel(col); | 
| 295 |  |  | XSetForeground(ourdisplay, ourgc, pixel); | 
| 296 |  |  | XFillRectangle(ourdisplay, gwind, | 
| 297 |  |  | ourgc, xmin, gheight-ymax, xmax-xmin, ymax-ymin); | 
| 298 | greg | 1.5 | } | 
| 299 |  |  |  | 
| 300 |  |  |  | 
| 301 |  |  | static | 
| 302 |  |  | x11_flush()                     /* flush output */ | 
| 303 |  |  | { | 
| 304 | greg | 2.19 | char    buf[256]; | 
| 305 | greg | 2.15 | int     n; | 
| 306 | greg | 2.16 | /* check for input */ | 
| 307 | greg | 1.10 | XNoOp(ourdisplay); | 
| 308 | greg | 2.16 | n = XPending(ourdisplay);                       /* from X server */ | 
| 309 |  |  | while (n-- > 0) | 
| 310 | greg | 1.5 | getevent(); | 
| 311 | greg | 2.22 | #ifdef FNDELAY | 
| 312 | greg | 2.19 | if (inpcheck == IC_IOCTL) {                     /* from stdin */ | 
| 313 | greg | 2.22 | #ifdef FIONREAD | 
| 314 | greg | 2.17 | if (ioctl(fileno(stdin), FIONREAD, &n) < 0) { | 
| 315 | greg | 2.22 | #else | 
| 316 |  |  | if (1) { | 
| 317 |  |  | #endif | 
| 318 | greg | 2.19 | if (fcntl(fileno(stdin), F_SETFL, FNDELAY) < 0) { | 
| 319 | gregl | 2.27 | eputs("cannot change input mode\n"); | 
| 320 | greg | 2.19 | quit(1); | 
| 321 |  |  | } | 
| 322 |  |  | inpcheck = IC_READ; | 
| 323 |  |  | } else | 
| 324 |  |  | x11_driver.inpready += n; | 
| 325 |  |  | } | 
| 326 |  |  | if (inpcheck == IC_READ) { | 
| 327 |  |  | n = read(fileno(stdin), buf, sizeof(buf)-1); | 
| 328 |  |  | if (n > 0) { | 
| 329 |  |  | buf[n] = '\0'; | 
| 330 | greg | 2.21 | tocombuf(buf, &x11_driver); | 
| 331 | greg | 2.17 | } | 
| 332 | greg | 2.15 | } | 
| 333 | greg | 2.22 | #endif | 
| 334 | greg | 1.1 | } | 
| 335 |  |  |  | 
| 336 |  |  |  | 
| 337 |  |  | static | 
| 338 | greg | 1.3 | x11_comin(inp, prompt)          /* read in a command line */ | 
| 339 |  |  | char  *inp, *prompt; | 
| 340 | greg | 1.1 | { | 
| 341 | greg | 2.15 | if (prompt != NULL) { | 
| 342 |  |  | x11_flush();            /* make sure we get everything */ | 
| 343 | greg | 1.4 | if (fromcombuf(inp, &x11_driver)) | 
| 344 |  |  | return; | 
| 345 | greg | 2.15 | xt_puts(prompt, comline); | 
| 346 |  |  | } | 
| 347 | greg | 1.1 | xt_cursor(comline, TBLKCURS); | 
| 348 |  |  | editline(inp, x11_getc, x11_comout); | 
| 349 |  |  | xt_cursor(comline, TNOCURS); | 
| 350 |  |  | } | 
| 351 |  |  |  | 
| 352 |  |  |  | 
| 353 |  |  | static | 
| 354 | greg | 2.17 | x11_comout(outp)                /* output a string to command line */ | 
| 355 |  |  | char  *outp; | 
| 356 | greg | 1.1 | { | 
| 357 | greg | 1.11 | if (comline == NULL) | 
| 358 |  |  | return; | 
| 359 | greg | 2.17 | xt_puts(outp, comline); | 
| 360 |  |  | if (outp[strlen(outp)-1] == '\n') | 
| 361 | greg | 1.11 | XFlush(ourdisplay); | 
| 362 | greg | 1.1 | } | 
| 363 |  |  |  | 
| 364 |  |  |  | 
| 365 |  |  | static | 
| 366 |  |  | x11_errout(msg)                 /* output an error message */ | 
| 367 |  |  | char  *msg; | 
| 368 |  |  | { | 
| 369 | gregl | 2.27 | eputs(msg);             /* send to stderr also! */ | 
| 370 | greg | 1.1 | x11_comout(msg); | 
| 371 |  |  | } | 
| 372 |  |  |  | 
| 373 |  |  |  | 
| 374 | greg | 2.17 | static | 
| 375 |  |  | std_comin(inp, prompt)          /* read in command line from stdin */ | 
| 376 |  |  | char  *inp, *prompt; | 
| 377 |  |  | { | 
| 378 |  |  | extern char     *gets(); | 
| 379 |  |  |  | 
| 380 |  |  | if (prompt != NULL) { | 
| 381 |  |  | if (fromcombuf(inp, &x11_driver)) | 
| 382 |  |  | return; | 
| 383 |  |  | if (!x11_driver.inpready) | 
| 384 | greg | 2.25 | std_comout(prompt); | 
| 385 | greg | 2.17 | } | 
| 386 | greg | 2.24 | #ifdef FNDELAY | 
| 387 |  |  | if (inpcheck == IC_READ) {      /* turn off FNDELAY */ | 
| 388 |  |  | if (fcntl(fileno(stdin), F_SETFL, 0) < 0) { | 
| 389 | gregl | 2.27 | eputs("cannot change input mode\n"); | 
| 390 | greg | 2.24 | quit(1); | 
| 391 |  |  | } | 
| 392 |  |  | inpcheck = IC_IOCTL; | 
| 393 |  |  | } | 
| 394 |  |  | #endif | 
| 395 | greg | 2.17 | if (gets(inp) == NULL) { | 
| 396 |  |  | strcpy(inp, "quit"); | 
| 397 |  |  | return; | 
| 398 |  |  | } | 
| 399 |  |  | x11_driver.inpready -= strlen(inp) + 1; | 
| 400 |  |  | if (x11_driver.inpready < 0) | 
| 401 |  |  | x11_driver.inpready = 0; | 
| 402 |  |  | } | 
| 403 |  |  |  | 
| 404 |  |  |  | 
| 405 |  |  | static | 
| 406 |  |  | std_comout(outp)                /* write out string to stdout */ | 
| 407 |  |  | char    *outp; | 
| 408 |  |  | { | 
| 409 |  |  | fputs(outp, stdout); | 
| 410 | greg | 2.20 | fflush(stdout); | 
| 411 | greg | 2.17 | } | 
| 412 |  |  |  | 
| 413 |  |  |  | 
| 414 | greg | 1.1 | static int | 
| 415 |  |  | x11_getcur(xp, yp)              /* get cursor position */ | 
| 416 |  |  | int  *xp, *yp; | 
| 417 |  |  | { | 
| 418 |  |  | while (XGrabPointer(ourdisplay, gwind, True, ButtonPressMask, | 
| 419 |  |  | GrabModeAsync, GrabModeAsync, None, pickcursor, | 
| 420 |  |  | CurrentTime) != GrabSuccess) | 
| 421 |  |  | sleep(2); | 
| 422 |  |  |  | 
| 423 |  |  | do | 
| 424 |  |  | getevent(); | 
| 425 |  |  | while (c_last <= c_first && levptr(XEvent)->type != ButtonPress); | 
| 426 |  |  | *xp = levptr(XButtonPressedEvent)->x; | 
| 427 |  |  | *yp = gheight-1 - levptr(XButtonPressedEvent)->y; | 
| 428 |  |  | XUngrabPointer(ourdisplay, CurrentTime); | 
| 429 |  |  | XFlush(ourdisplay);                             /* insure release */ | 
| 430 |  |  | if (c_last > c_first)                   /* key pressed */ | 
| 431 |  |  | return(x11_getc()); | 
| 432 |  |  | /* button pressed */ | 
| 433 | greg | 2.10 | if (levptr(XButtonPressedEvent)->button == Button1) | 
| 434 | greg | 1.1 | return(MB1); | 
| 435 | greg | 2.10 | if (levptr(XButtonPressedEvent)->button == Button2) | 
| 436 | greg | 1.1 | return(MB2); | 
| 437 | greg | 2.10 | if (levptr(XButtonPressedEvent)->button == Button3) | 
| 438 | greg | 1.1 | return(MB3); | 
| 439 |  |  | return(ABORT); | 
| 440 |  |  | } | 
| 441 |  |  |  | 
| 442 |  |  |  | 
| 443 |  |  | static | 
| 444 |  |  | xnewcolr(ndx, r, g, b)          /* enter a color into hardware table */ | 
| 445 |  |  | int  ndx; | 
| 446 |  |  | int  r, g, b; | 
| 447 |  |  | { | 
| 448 |  |  | XColor  xcolor; | 
| 449 |  |  |  | 
| 450 |  |  | xcolor.pixel = pixval[ndx]; | 
| 451 |  |  | xcolor.red = r << 8; | 
| 452 |  |  | xcolor.green = g << 8; | 
| 453 |  |  | xcolor.blue = b << 8; | 
| 454 |  |  | xcolor.flags = DoRed|DoGreen|DoBlue; | 
| 455 |  |  |  | 
| 456 |  |  | XStoreColor(ourdisplay, ourmap, &xcolor); | 
| 457 |  |  | } | 
| 458 |  |  |  | 
| 459 |  |  |  | 
| 460 |  |  | static int | 
| 461 |  |  | getpixels()                             /* get the color map */ | 
| 462 |  |  | { | 
| 463 | greg | 1.16 | XColor  thiscolor; | 
| 464 |  |  | register int  i, j; | 
| 465 |  |  |  | 
| 466 | greg | 1.4 | if (ncolors > 0) | 
| 467 | greg | 2.2 | return(ncolors); | 
| 468 |  |  | if (ourvinfo.visual == DefaultVisual(ourdisplay,ourscreen)) { | 
| 469 | greg | 1.6 | ourmap = DefaultColormap(ourdisplay,ourscreen); | 
| 470 |  |  | goto loop; | 
| 471 |  |  | } | 
| 472 |  |  | newmap: | 
| 473 | greg | 2.2 | ourmap = XCreateColormap(ourdisplay,gwind,ourvinfo.visual,AllocNone); | 
| 474 | greg | 1.6 | loop: | 
| 475 | greg | 2.2 | for (ncolors = ourvinfo.colormap_size; | 
| 476 |  |  | ncolors > ourvinfo.colormap_size/3; | 
| 477 | greg | 1.6 | ncolors = ncolors*.937) { | 
| 478 | greg | 1.17 | pixval = (unsigned long *)malloc(ncolors*sizeof(unsigned long)); | 
| 479 | greg | 1.1 | if (pixval == NULL) | 
| 480 | greg | 1.6 | return(ncolors = 0); | 
| 481 | greg | 2.8 | if (XAllocColorCells(ourdisplay,ourmap,0,NULL,0,pixval,ncolors)) | 
| 482 | greg | 1.6 | break; | 
| 483 | greg | 1.1 | free((char *)pixval); | 
| 484 | greg | 1.6 | pixval = NULL; | 
| 485 | greg | 1.1 | } | 
| 486 | greg | 1.6 | if (pixval == NULL) { | 
| 487 |  |  | if (ourmap == DefaultColormap(ourdisplay,ourscreen)) | 
| 488 |  |  | goto newmap;            /* try it with our map */ | 
| 489 |  |  | else | 
| 490 |  |  | return(ncolors = 0);    /* failed */ | 
| 491 |  |  | } | 
| 492 | greg | 1.16 | if (ourmap != DefaultColormap(ourdisplay,ourscreen)) | 
| 493 |  |  | for (i = 0; i < ncolors; i++) { /* reset black and white */ | 
| 494 | greg | 1.6 | if (pixval[i] != ourblack && pixval[i] != ourwhite) | 
| 495 |  |  | continue; | 
| 496 |  |  | thiscolor.pixel = pixval[i]; | 
| 497 |  |  | thiscolor.flags = DoRed|DoGreen|DoBlue; | 
| 498 |  |  | XQueryColor(ourdisplay, | 
| 499 |  |  | DefaultColormap(ourdisplay,ourscreen), | 
| 500 |  |  | &thiscolor); | 
| 501 |  |  | XStoreColor(ourdisplay, ourmap, &thiscolor); | 
| 502 |  |  | for (j = i; j+1 < ncolors; j++) | 
| 503 |  |  | pixval[j] = pixval[j+1]; | 
| 504 |  |  | ncolors--; | 
| 505 |  |  | i--; | 
| 506 |  |  | } | 
| 507 | greg | 1.16 | XSetWindowColormap(ourdisplay, gwind, ourmap); | 
| 508 | greg | 1.6 | return(ncolors); | 
| 509 | greg | 1.1 | } | 
| 510 |  |  |  | 
| 511 |  |  |  | 
| 512 |  |  | static | 
| 513 |  |  | freepixels()                            /* free our pixels */ | 
| 514 |  |  | { | 
| 515 |  |  | if (ncolors == 0) | 
| 516 |  |  | return; | 
| 517 |  |  | XFreeColors(ourdisplay,ourmap,pixval,ncolors,0L); | 
| 518 | greg | 2.7 | free((char *)pixval); | 
| 519 |  |  | pixval = NULL; | 
| 520 | greg | 1.1 | ncolors = 0; | 
| 521 | greg | 1.8 | if (ourmap != DefaultColormap(ourdisplay,ourscreen)) | 
| 522 | greg | 1.6 | XFreeColormap(ourdisplay, ourmap); | 
| 523 |  |  | ourmap = 0; | 
| 524 | greg | 1.1 | } | 
| 525 |  |  |  | 
| 526 |  |  |  | 
| 527 | greg | 1.6 | static unsigned long | 
| 528 |  |  | true_pixel(col)                 /* return true pixel value for color */ | 
| 529 |  |  | COLOR  col; | 
| 530 |  |  | { | 
| 531 |  |  | unsigned long  rval; | 
| 532 |  |  | BYTE  rgb[3]; | 
| 533 |  |  |  | 
| 534 |  |  | map_color(rgb, col); | 
| 535 | greg | 2.2 | rval = ourvinfo.red_mask*rgb[RED]/255 & ourvinfo.red_mask; | 
| 536 |  |  | rval |= ourvinfo.green_mask*rgb[GRN]/255 & ourvinfo.green_mask; | 
| 537 |  |  | rval |= ourvinfo.blue_mask*rgb[BLU]/255 & ourvinfo.blue_mask; | 
| 538 | greg | 1.6 | return(rval); | 
| 539 |  |  | } | 
| 540 |  |  |  | 
| 541 |  |  |  | 
| 542 | greg | 1.1 | static int | 
| 543 |  |  | x11_getc()                      /* get a command character */ | 
| 544 |  |  | { | 
| 545 |  |  | while (c_last <= c_first) { | 
| 546 |  |  | c_first = c_last = 0;           /* reset */ | 
| 547 |  |  | getevent();                     /* wait for key */ | 
| 548 |  |  | } | 
| 549 |  |  | x11_driver.inpready--; | 
| 550 |  |  | return(c_queue[c_first++]); | 
| 551 |  |  | } | 
| 552 |  |  |  | 
| 553 |  |  |  | 
| 554 |  |  | static | 
| 555 |  |  | getevent()                      /* get next event */ | 
| 556 |  |  | { | 
| 557 |  |  | XNextEvent(ourdisplay, levptr(XEvent)); | 
| 558 |  |  | switch (levptr(XEvent)->type) { | 
| 559 | greg | 1.4 | case ConfigureNotify: | 
| 560 |  |  | resizewindow(levptr(XConfigureEvent)); | 
| 561 |  |  | break; | 
| 562 |  |  | case UnmapNotify: | 
| 563 | greg | 2.8 | mapped = 0; | 
| 564 | greg | 1.4 | freepixels(); | 
| 565 |  |  | break; | 
| 566 |  |  | case MapNotify: | 
| 567 | greg | 2.2 | if (ourvinfo.class == PseudoColor || | 
| 568 |  |  | ourvinfo.class == GrayScale) | 
| 569 | greg | 1.6 | if (getpixels() == 0) | 
| 570 | gregl | 2.27 | eputs("cannot allocate colors\n"); | 
| 571 | greg | 1.6 | else | 
| 572 |  |  | new_ctab(ncolors); | 
| 573 | greg | 2.8 | mapped = 1; | 
| 574 | greg | 1.4 | break; | 
| 575 |  |  | case Expose: | 
| 576 |  |  | fixwindow(levptr(XExposeEvent)); | 
| 577 |  |  | break; | 
| 578 | greg | 1.1 | case KeyPress: | 
| 579 |  |  | getkey(levptr(XKeyPressedEvent)); | 
| 580 |  |  | break; | 
| 581 |  |  | case ButtonPress: | 
| 582 |  |  | break; | 
| 583 |  |  | } | 
| 584 |  |  | } | 
| 585 |  |  |  | 
| 586 |  |  |  | 
| 587 |  |  | static | 
| 588 |  |  | getkey(ekey)                            /* get input key */ | 
| 589 |  |  | register XKeyPressedEvent  *ekey; | 
| 590 |  |  | { | 
| 591 | greg | 1.8 | register int  n; | 
| 592 | greg | 1.7 |  | 
| 593 |  |  | n = XLookupString(ekey, c_queue+c_last, sizeof(c_queue)-c_last, | 
| 594 | greg | 1.1 | NULL, NULL); | 
| 595 | greg | 1.7 | c_last += n; | 
| 596 |  |  | x11_driver.inpready += n; | 
| 597 | greg | 1.1 | } | 
| 598 |  |  |  | 
| 599 |  |  |  | 
| 600 |  |  | static | 
| 601 |  |  | fixwindow(eexp)                         /* repair damage to window */ | 
| 602 |  |  | register XExposeEvent  *eexp; | 
| 603 |  |  | { | 
| 604 | greg | 2.21 | char  buf[80]; | 
| 605 |  |  |  | 
| 606 | greg | 1.4 | if (eexp->window == gwind) { | 
| 607 | greg | 2.21 | sprintf(buf, "repaint %d %d %d %d\n", | 
| 608 | greg | 1.4 | eexp->x, gheight - eexp->y - eexp->height, | 
| 609 | greg | 1.1 | eexp->x + eexp->width, gheight - eexp->y); | 
| 610 | greg | 2.21 | tocombuf(buf, &x11_driver); | 
| 611 | greg | 1.4 | } else if (eexp->window == comline->w) { | 
| 612 |  |  | if (eexp->count == 0) | 
| 613 |  |  | xt_redraw(comline); | 
| 614 |  |  | } | 
| 615 | greg | 1.1 | } | 
| 616 | greg | 1.4 |  | 
| 617 |  |  |  | 
| 618 |  |  | static | 
| 619 |  |  | resizewindow(ersz)                      /* resize window */ | 
| 620 |  |  | register XConfigureEvent  *ersz; | 
| 621 |  |  | { | 
| 622 | greg | 2.17 | if (ersz->width == gwidth && ersz->height-comheight == gheight) | 
| 623 | greg | 1.4 | return; | 
| 624 |  |  |  | 
| 625 |  |  | gwidth = ersz->width; | 
| 626 | greg | 2.17 | gheight = ersz->height-comheight; | 
| 627 | greg | 1.4 | x11_driver.xsiz = gwidth < MINWIDTH ? MINWIDTH : gwidth; | 
| 628 |  |  | x11_driver.ysiz = gheight < MINHEIGHT ? MINHEIGHT : gheight; | 
| 629 |  |  |  | 
| 630 | greg | 2.21 | tocombuf("new\n", &x11_driver); | 
| 631 | greg | 1.4 | } |