1 /*
2  * xcmap.c - shows the contents of the colormap on 4, 6, or 8-bit X11 displays
3  *
4  *  Author:    John Bradley, University of Pennsylvania
5  *                (bradley@cis.upenn.edu)
6  */
7 
8 #define REVDATE   "Rev: 2/13/89"
9 
10 /* include files */
11 #include <stdio.h>
12 #ifdef __STDC__
13 #  include <stdlib.h>   /* exit(), abs() */
14 #endif
15 #include <sys/types.h>
16 #include <ctype.h>
17 
18 #include <X11/Xos.h>
19 #include <X11/Xlib.h>
20 #include <X11/Xutil.h>
21 #include <X11/cursorfont.h>
22 
23 #ifdef VMS
24 #  define index strchr
25 #endif
26 
27 typedef unsigned char byte;
28 
29 /* text centering macros for X11 */
30 #define CENTERX(f,x,str) ((x)-XTextWidth(f,str,strlen(str))/2)
31 #define CENTERY(f,y) ((y)-((f->ascent+f->descent)/2)+f->ascent)
32 
33 #undef PARM
34 #ifdef __STDC__
35 #  define PARM(a) a
36 #else
37 #  define PARM(a) ()
38 #endif
39 
40 #define FONT "8x13"
41 
42 
43 /* X stuff */
44 Display       *theDisp;
45 int           theScreen, dispcells;
46 Colormap      theCmap;
47 Window        rootW, mainW;
48 GC            theGC;
49 unsigned long fcol,bcol;
50 Font          mfont;
51 XFontStruct   *mfinfo;
52 Visual        *theVisual;
53 
54 
55 /* global vars */
56 int            WIDE,HIGH,cWIDE,cHIGH,nxcells,nycells, pvalup;
57 XColor         defs[256];
58 char          *cmd, tmpstr[128];
59 
60 
61        int  main             PARM((int, char **));
62 static void HandleEvent      PARM((XEvent *));
63 static void Syntax           PARM((void));
64 static void FatalError       PARM((const char *));
65 static void Quit             PARM((void));
66 static void CreateMainWindow PARM((char *, char *, int, char **));
67 static void DrawWindow       PARM((int,int,int,int));
68 static void Resize           PARM((int,int));
69 static void TrackMouse       PARM((int,int));
70 static void DrawPixValue     PARM((int,int));
71 
72 /*******************************************/
main(argc,argv)73 int main(argc, argv)
74      int   argc;
75      char *argv[];
76 /*******************************************/
77 {
78   int        i;
79   char      *display, *geom;
80   XEvent     event;
81 
82   cmd = argv[0];
83   display = geom = NULL;
84 
85 
86   /*********************Options*********************/
87 
88   for (i = 1; i < argc; i++) {
89     char *strind;
90 
91     if (!strncmp(argv[i],"-g", (size_t)2)) {	/* geometry */
92       i++;
93       geom = argv[i];
94       continue;
95     }
96 
97     if (argv[i][0] == '=') {		/* old-style geometry */
98       geom = argv[i];
99       continue;
100     }
101 
102     if (!strncmp(argv[i],"-d",(size_t) 2)) {	/* display */
103       i++;
104       display = argv[i];
105       continue;
106     }
107 
108     strind = (char *) index(argv[i], ':');	/* old-style display */
109     if(strind != NULL) {
110       display = argv[i];
111       continue;
112     }
113 
114     Syntax();
115   }
116 
117 
118   /*****************************************************/
119 
120   /* Open up the display. */
121 
122   if ( (theDisp=XOpenDisplay(display)) == NULL)
123     FatalError("can't open display");
124 
125   theScreen = DefaultScreen(theDisp);
126   theCmap   = DefaultColormap(theDisp, theScreen);
127   rootW     = RootWindow(theDisp,theScreen);
128   theGC     = DefaultGC(theDisp,theScreen);
129   fcol      = WhitePixel(theDisp,theScreen);
130   bcol      = BlackPixel(theDisp,theScreen);
131   theVisual = DefaultVisual(theDisp,theScreen);
132 
133   dispcells = DisplayCells(theDisp, theScreen);
134 
135   if (dispcells>256) {
136     sprintf(tmpstr,"dispcells = %d.  %s",
137 	    dispcells, "This program can only deal with <= 8-bit displays.");
138     FatalError(tmpstr);
139   }
140   else if (dispcells>64)
141     nxcells = nycells = 16;
142   else if (dispcells>16)
143     nxcells = nycells = 8;
144   else if (dispcells>4)
145     nxcells = nycells = 4;
146   else if (dispcells>2)
147     nxcells = nycells = 2;
148   else
149   {
150     nxcells = 2;
151     nycells = 1;
152   }
153 
154   /**************** Create/Open X Resources ***************/
155   if ((mfinfo = XLoadQueryFont(theDisp,FONT))==NULL) {
156     sprintf(tmpstr,"couldn't open '%s' font",FONT);
157     FatalError(tmpstr);
158   }
159 
160   mfont=mfinfo->fid;
161   XSetFont(theDisp,theGC,mfont);
162   XSetForeground(theDisp,theGC,fcol);
163   XSetBackground(theDisp,theGC,bcol);
164 
165   CreateMainWindow(cmd,geom,argc,argv);
166   Resize((int)WIDE,(int)HIGH);
167 
168   XSelectInput(theDisp, mainW, ExposureMask | KeyPressMask
169 	       | StructureNotifyMask | ButtonPressMask);
170   XMapWindow(theDisp,mainW);
171 
172   /**************** Main loop *****************/
173   while (1) {
174     XNextEvent(theDisp, &event);
175     HandleEvent(&event);
176   }
177 }
178 
179 
180 
181 /************************************************/
HandleEvent(event)182 static void HandleEvent(event)
183      XEvent *event;
184 {
185   switch (event->type) {
186   case Expose: {
187     XExposeEvent *exp_event = (XExposeEvent *) event;
188 
189     if (exp_event->window==mainW)
190       DrawWindow(exp_event->x,exp_event->y,
191 		 exp_event->width, exp_event->height);
192   }
193     break;
194 
195   case ButtonPress: {
196     XButtonEvent *but_event = (XButtonEvent *) event;
197 
198     if (but_event->window == mainW && but_event->button == Button1)
199       TrackMouse(but_event->x, but_event->y);
200   }
201     break;
202 
203   case KeyPress: {
204     XKeyEvent *key_event = (XKeyEvent *) event;
205     KeySym ks;
206     XComposeStatus status;
207 
208     XLookupString(key_event,tmpstr,128,&ks,&status);
209     if (tmpstr[0]=='q' || tmpstr[0]=='Q') Quit();
210   }
211     break;
212 
213   case ConfigureNotify: {
214     XConfigureEvent *conf_event = (XConfigureEvent *) event;
215     int w = conf_event->width, h = conf_event->height;
216 
217     if (conf_event->window == mainW && (w != WIDE || h != HIGH))
218       Resize((int)(w ? w : WIDE), (int)(h ? h : HIGH));
219   }
220     break;
221 
222 
223   case CirculateNotify:
224   case MapNotify:
225   case DestroyNotify:
226   case GravityNotify:
227   case ReparentNotify:
228   case UnmapNotify:
229   case MappingNotify:
230   case ClientMessage:         break;
231 
232   default:		/* ignore unexpected events */
233     break;
234   }  /* end of switch */
235 }
236 
237 
238 /***********************************/
Syntax()239 static void Syntax()
240 {
241   printf("Usage: %s filename [=geom | -geometry geom] [ [-display] disp]\n",
242 	 cmd);
243   exit(1);
244 }
245 
246 
247 /***********************************/
FatalError(identifier)248 static void FatalError(identifier)
249      const char *identifier;
250 {
251   fprintf(stderr, "%s: %s\n", cmd, identifier);
252   exit(-1);
253 }
254 
255 
256 /***********************************/
Quit()257 static void Quit()
258 {
259   exit(0);
260 }
261 
262 
263 /***********************************/
CreateMainWindow(name,geom,argc,argv)264 static void CreateMainWindow(name,geom,argc,argv)
265      char *name,*geom,**argv;
266      int   argc;
267 {
268   XSetWindowAttributes xswa;
269   unsigned long xswamask;
270   XSizeHints hints;
271   int i,x,y;
272   unsigned int w,h;
273 
274   WIDE = HIGH = 256;			/* default window size */
275 
276   x=y=w=h=1;
277   hints.flags = 0;
278 
279   i=XParseGeometry(geom,&x,&y,&w,&h);
280   if (i&WidthValue)
281   {
282     WIDE = (int) w;
283     hints.flags |= USSize;
284   }
285   if (i&HeightValue)
286   {
287     HIGH = (int) h;
288     hints.flags |= USSize;
289   }
290 
291   if (i&XValue || i&YValue)
292   {
293     if (i&XNegative)
294       x = XDisplayWidth(theDisp,theScreen)-WIDE-abs(x);
295     if (i&YNegative)
296       y = XDisplayHeight(theDisp,theScreen)-HIGH-abs(y);
297     hints.flags |= USPosition;
298   }
299 
300   hints.x=x;             hints.y=y;
301   hints.width  = WIDE;   hints.height = HIGH;
302   hints.max_width  = DisplayWidth(theDisp,theScreen);
303   hints.max_height = DisplayHeight(theDisp,theScreen);
304   hints.min_width  = 16;
305   hints.min_height = 16;
306   hints.width_inc = hints.height_inc = 16;
307   hints.flags |= PMaxSize | PMinSize | PResizeInc;
308 
309   xswa.background_pixel = bcol;
310   xswa.border_pixel     = fcol;
311   xswa.cursor = XCreateFontCursor (theDisp, XC_top_left_arrow);
312   xswamask = CWBackPixel | CWBorderPixel | CWCursor;
313 
314   mainW = XCreateWindow(theDisp,rootW,x,y,(unsigned int) WIDE,
315 			(unsigned int) HIGH, 2, 0,
316 			(unsigned int) CopyFromParent,
317 			CopyFromParent, xswamask, &xswa);
318 
319   XSetStandardProperties(theDisp,mainW,"xcmap","xcmap",None,
320 			 argv,argc,&hints);
321 
322   if (!mainW) FatalError("Can't open main window");
323 
324 }
325 
326 
327 /***********************************/
DrawWindow(x,y,w,h)328 static void DrawWindow(x,y,w,h)
329      int x,y,w,h;
330 {
331   int i,j,x1,y1,x2,y2;
332 
333   x1 = x / cWIDE;      y1 = y / cHIGH;	/* (x1,y1) (x2,y2): bounding */
334   x2 = ((x+w) + cWIDE - 1) / cWIDE;		/*       rect in cell coords */
335   y2 = ((y+h) + cHIGH - 1) / cHIGH;
336 
337   for (i=y1; i<y2; i++) {
338     for (j=x1; j<x2; j++) {
339       XSetForeground(theDisp,theGC,(unsigned long) (i*nycells+j) );
340       XFillRectangle(theDisp,mainW,theGC,j*cWIDE,i*cHIGH,
341 		     (unsigned int) cWIDE, (unsigned int) cHIGH);
342     }
343   }
344 }
345 
346 
347 /***********************************/
Resize(w,h)348 static void Resize(w,h)
349      int w,h;
350 {
351   cWIDE = (w + nxcells - 1) / nxcells;
352   cHIGH = (h + nycells - 1) / nycells;
353   WIDE = w;  HIGH = h;
354 }
355 
356 
357 /***********************************/
TrackMouse(mx,my)358 static void TrackMouse(mx,my)
359      int mx,my;
360 {
361   /* called when there's a button press in the window.  draws the pixel
362      value, and loops until button is released */
363 
364   Window        rootW,childW;
365   int           rx,ry,x,y;
366   unsigned int  mask;
367 
368   pvalup = 0;
369   DrawPixValue(mx,my);
370 
371   while (1) {
372     if (XQueryPointer(theDisp,mainW,&rootW,&childW,&rx,&ry,&x,&y,&mask)) {
373       if (!(mask & Button1Mask)) break;    /* button released */
374 
375       DrawPixValue(x,y);
376     }
377   }
378 }
379 
380 
381 /***********************************/
DrawPixValue(x,y)382 static void DrawPixValue(x,y)
383      int x,y;
384 {
385   static unsigned long pix, lastpix;
386   static int           pvaly;
387 
388   if (x<0) x=0;  if (x>=WIDE) x=WIDE-1;
389   if (y<0) y=0;  if (y>=HIGH) y=HIGH-1;
390 
391   if (!pvalup) {	/* it's not up.  make it so */
392     if (y >= HIGH/2) pvaly = 0;  else pvaly = HIGH - 12;
393     pvalup = 1;
394     lastpix = 0xffff;		/* kludge to force redraw on first */
395     XClearArea(theDisp,mainW,0,pvaly,
396 	       (unsigned int) WIDE, (unsigned int) 13,True);
397   }
398 
399   x /= cWIDE;  y /= cHIGH;
400 
401   pix = y * nxcells + x;
402 
403   if (pix != lastpix) {
404     XColor def;
405     char  *sp;
406 
407     XSetForeground(theDisp,theGC,fcol);
408     lastpix = def.pixel = pix;
409     if (pix<dispcells) {
410       XQueryColor(theDisp, theCmap, &def);
411       sprintf(tmpstr, "Pix %3ld = ($%04x, $%04x, $%04x)",
412 	      pix, def.red, def.green, def.blue);
413 
414       /* make the hex uppercase */
415       for (sp=tmpstr+4; *sp; sp++)
416 	if (islower(*sp)) *sp = toupper(*sp);
417     }
418     else {
419       sprintf(tmpstr, "Pix %3ld is out of legal range. ", pix);
420     }
421 
422     XDrawImageString(theDisp,mainW,theGC,5,pvaly+10,tmpstr,
423 		     (int) strlen(tmpstr));
424   }
425 }
426 
427 
428 
429 
430 
431 
432 
433 
434