1 /* $Header: /home/yav/xpx/RCS/colset.c,v 1.35 1996/04/26 17:22:47 yav Exp $
2  * color edit
3  * written by yav (UHD98984@pcvan.or.jp)
4  */
5 
6 #include <X11/Xlib.h>
7 #include <X11/Xutil.h>
8 #include <X11/keysym.h>
9 
10 #include "headers.h"
11 #include "xpx.h"
12 #include "work.h"
13 #include "cursdef.h"
14 #define PUBLIC_COLSET_C
15 #include "extern.h"
16 
17 
18 #define COLSETW 64
19 #define COLSETH 18
20 #define COLBOXH (COLSETH-2)	/* < COLSETH */
21 #define COLBOXW COLBOXH		/* < COLSETW */
22 
23 #define COLEDX	400
24 #define COLEDY	50
25 #define COLEDDX	20
26 #define COLEDDY	32
27 
28 #define COLBARH	16
29 #define COLEDW	380
30 #define COLEDH	(COLBARH*3+BDW*2)
31 #define COLED_COLOR	0
32 #define COLED_NRED	1
33 #define COLED_NGREEN	2
34 #define COLED_NBLUE	3
35 #define COLED_RED	4
36 #define COLED_GREEN	5
37 #define COLED_BLUE	6
38 #define COLED_OK	7
39 
40 #define coled_num(p)	(get_top_menu(p)->cursor)
41 #define coled_colnum(p)	(current_pal*MAXCOLSET+coled_num(p))
42 #define coled_col(p)	(color_buf+coled_colnum(p))
43 
44 char rcsid_colset[] = "$Id: colset.c,v 1.35 1996/04/26 17:22:47 yav Exp $";
45 
46 static Bool coledopened[MAXCOLSET];
47 static Window coledwin[MAXCOLSET];
48 static MENU *coledmn[MAXCOLSET];
49 static unsigned long rgb_pixel[3];
50 static GC gc_rgb[3];
51 static Window colorbarwin[MAXCOLSET][3];
52 static char color_digit_initstr[] = "?";
53 
54 int coledev();
55 int colednev();
56 char *coledstr();
57 
58 #define IMASK	\
59 (ExposureMask|ButtonPressMask|EnterWindowMask|LeaveWindowMask|ButtonMotionMask)
60 static MENU coledmenu[] = {
61   {
62     COLED_COLOR,	MenuModeMaskBorder,
63     2, 2, 32, COLEDH-BDW*2-4,
64     0, ExposureMask|ButtonPressMask|EnterWindowMask|LeaveWindowMask, 0,
65     coledev, NULL, 0, 0, ""},
66   {
67     COLED_NRED,	MenuModeMaskBorder,
68     48, 0, 32, COLBARH-BDW,
69     0, ExposureMask|KeyPressMask|EnterWindowMask|LeaveWindowMask, 0,
70     colednev, coledstr, 0, 8, NULL},
71   {
72     COLED_NGREEN,	MenuModeMaskBorder,
73     48, COLBARH, 32, COLBARH-BDW,
74     0, ExposureMask|KeyPressMask|EnterWindowMask|LeaveWindowMask, 0,
75     colednev, coledstr, 0, 8, NULL},
76   {
77     COLED_NBLUE,	MenuModeMaskBorder,
78     48, COLBARH*2, 32, COLBARH-BDW,
79     0, ExposureMask|KeyPressMask|EnterWindowMask|LeaveWindowMask, 0,
80     colednev, coledstr, 0, 8, NULL},
81   {
82     COLED_RED,	MenuModeMaskBorder,
83     48+32, 0, 256+2, COLBARH-BDW,
84     0, IMASK, 0,
85     coledev, NULL, 0, 0, ""},
86   {
87     COLED_GREEN,	MenuModeMaskBorder,
88     48+32, COLBARH, 256+2, COLBARH-BDW,
89     0, IMASK, 0,
90     coledev, NULL, 0, 0, ""},
91   {
92     COLED_BLUE,	MenuModeMaskBorder,
93     48+32, COLBARH*2, 256+2, COLBARH-BDW,
94     0, IMASK, 0,
95     coledev, NULL, 0, 0, ""},
96   {
97     COLED_OK,	MenuModeMaskBorder,
98     BDW*2+2, BDW*2+2, 32, 20,
99     0, ExposureMask|ButtonPressMask|EnterWindowMask|LeaveWindowMask,
100     SouthEastGravity,
101     coledev, NULL, 0, 0, "OK"},
102   {
103     -1,	0,
104     0, 0, 0, 0,
105     0, 0, 0,
106     NULL, NULL, 0, 0, NULL}
107 };
108 
redraw_col(p)109 char *redraw_col(p)
110      MENU *p;
111 {
112   int len, w, ww;
113   GC g;
114   COL *cp;
115   char buf[256];
116 
117   cp = color_buf+current_pal*MAXCOLSET+p->n;
118   if (!(coltbl[p->n] & CM_ALLOCED))
119     return "None";
120   sprintf(buf, "%x%c%x%x%x", p->n, (coltbl[p->n]&CM_PRIVATE?':':'.'),
121 	  cp->rgb.green>>4, cp->rgb.red>>4, cp->rgb.blue>>4);
122   len = strlen(buf);
123   ww = COLSETW-COLBOXW;
124   XFillRectangle(dsp, p->win, colgc[p->n], 1, 1, COLBOXW, COLBOXH);
125   if (*(colmask+current_pal*MAXCOLSET+p->n)) {
126     XDrawLine(dsp, p->win, gc1, 1, 1, COLBOXW-1, COLBOXH-1);
127     XDrawLine(dsp, p->win, gc0, COLBOXW-1, 1, 1, COLBOXH-1);
128   }
129   if (p->mode & MenuModeMaskOn) {
130     XFillRectangle(dsp, p->win, gc0, COLBOXW, 1, ww, COLBOXH);
131     g = gc1;
132   } else {
133     g = gc0;
134   }
135   w = XTextWidth(fs0, buf, len);
136   XDrawImageString(dsp, p->win, g, COLBOXW+(ww-w)/2, COLSETH-5, buf, len);
137   menu_highlight(p);
138   return NULL;
139 }
140 
set_current_color(n)141 void set_current_color(n)
142      int n;
143 {
144   int oldcol;
145 
146   if (n != current_col) {
147     oldcol = current_col;
148     current_col = n;
149     if (oldcol >= 0 && oldcol < MAXCOLSET) {
150       colmenu[oldcol].mode &= ~MenuModeMaskOn;
151       redraw_window(colmenu[oldcol].win);
152     }
153     if (n >= 0 && n < MAXCOLSET) {
154       colmenu[n].mode |= MenuModeMaskOn;
155       redraw_window(colmenu[n].win);
156     }
157     redraw_window(cursmenu[CURS_CURC].win);
158   }
159 }
160 
unmap_coled_window(n)161 void unmap_coled_window(n)
162      int n;
163 {
164   XUnmapWindow(dsp, coledwin[n]);
165   coledopened[n] = False;
166 }
167 
clear_color_digits(p)168 void clear_color_digits(p)
169      MENU *p;
170 {
171   strcpy((p+COLED_NRED)->str, color_digit_initstr);
172   strcpy((p+COLED_NGREEN)->str, color_digit_initstr);
173   strcpy((p+COLED_NBLUE)->str, color_digit_initstr);
174 }
175 
create_coledit_window(n)176 int create_coledit_window(n)
177      int n;
178 {
179   MENU *p;
180   int i;
181   char name[256];
182   char buf[256];
183 
184   if (n >= MAXCOLSET) {
185     error("coledit: color %d!", n);
186     return 1;
187   }
188   if (coledwin[n]) {
189     XMapWindow(dsp, coledwin[n]);
190     coledopened[n] = True;
191     return 0;
192   }
193   sprintf(name, "%s color %d", myname, n);
194   sprintf(buf, "%dx%d+%d+%d",
195 	  COLEDW, COLEDH, COLEDX+COLEDDX*n, COLEDY+COLEDDY*n);
196   create_toplevel_window(&coledwin[n], name, buf, COLEDW, COLEDH);
197   XSelectInput(dsp, coledwin[n], ExposureMask);
198   XMapRaised(dsp, coledwin[n]);
199   p = (MENU *)malloc(sizeof(coledmenu));
200   if (p == NULL) {
201     error("more core!");
202     return 1;
203   }
204   memcpy(p, coledmenu, sizeof(coledmenu));
205   p->cursor = n;		/* color edit window number */
206   menuwin_create(p, coledwin[n], 0, 0);
207   clear_color_digits(p);
208   coledmn[n] = p;
209   for (i = 0; i < 3; i++) {
210     static int ntbl[3] = {COLED_RED, COLED_GREEN, COLED_BLUE};
211     colorbarwin[n][i] = XCreateSimpleWindow(dsp, (p+ntbl[i])->win,
212 					    BDW, BDW, 100, COLBARH-BDW*3,
213 					    0, fg, rgb_pixel[i]);
214     XSelectInput(dsp, colorbarwin[n][i], ExposureMask|EnterWindowMask|LeaveWindowMask);
215     XMapWindow(dsp, colorbarwin[n][i]);
216   }
217   coledopened[n] = True;
218   return 0;
219 }
220 
221 /* alternate color mask on/off */
color_mask_alt(n)222 void color_mask_alt(n)
223      int n;
224 {
225   *(colmask+current_pal*MAXCOLSET+n) ^= 1;
226   redraw_window(colmenu[n].win);
227 }
228 
color_mask_alt_all()229 void color_mask_alt_all()
230 {
231   int i;
232 
233   for (i = 0; i < MAXCOLSET; i++)
234     color_mask_alt(i);
235 }
236 
237 
colev(p,ev)238 int colev(p, ev)
239      MENU *p;
240      XEvent *ev;
241 {
242   static int copy_src = -1;
243 
244   switch(ev->type) {
245   case ButtonPress:
246     switch(ev->xbutton.button) {
247     case Button1:
248       copy_src = p->n;
249       if (double_clicked) {
250 	if (coledopened[p->n])
251 	  unmap_coled_window(p->n);
252 	else
253 	  create_coledit_window(p->n);
254       } else {
255 	set_current_color(p->n);
256       }
257       return 1;
258     case Button2:
259     case Button3:
260       /* mask on/off */
261       color_mask_alt(p->n);
262       return 1;
263     }
264     break;
265   case ButtonRelease:
266     if (copy_src >= 0 && copy_src != p->n) {
267       if (debug_mode)
268 	fprintf(stderr, "colev: copy color %d -> %d\n", copy_src, p->n);
269       undo_push_color(current_pal*MAXCOLSET+p->n, 1);
270       memcpy(
271 	     color_buf+current_pal*MAXCOLSET+p->n,
272 	     color_buf+current_pal*MAXCOLSET+copy_src,
273 	     sizeof(COL));
274       colchanged = 1;
275       change_color(current_pal*MAXCOLSET+p->n);
276     }
277     copy_src = -1;
278     return 1;
279   case LeaveNotify:
280     break;
281   }
282   return 0;
283 }
284 
get_rgb_gc()285 void get_rgb_gc()
286 {
287   int i;
288   XColor col;
289   static char *name[3] = {"red", "green", "blue"};
290 
291   for (i = 0; i < 3; i++) {
292     gc_rgb[i] = XCreateGC(dsp, win, 0, 0);
293     XSetBackground(dsp, gc_rgb[i], bg);
294     XSetForeground(dsp, gc_rgb[i], fg);
295     if (parse_color(&col, name[i]) == 0) {
296       rgb_pixel[i] = col.pixel;
297       XSetForeground(dsp, gc_rgb[i], col.pixel);
298     }
299   }
300 }
301 
create_colset_window(win,x,y)302 int create_colset_window(win, x, y)
303      Window win;
304      int x;
305      int y;
306 {
307   int i;
308   MENU *p;
309 
310   p = colmenu;
311   for (i = 0; i < MAXCOLSET; i++) {
312     bzero(p, sizeof(*p));
313     p->n = i;
314     p->y = (COLSETH+BDW)*i;
315     p->w = COLSETW;
316     p->h = COLSETH;
317     p->im = ExposureMask|EnterWindowMask|LeaveWindowMask|ButtonPressMask|ButtonReleaseMask|OwnerGrabButtonMask;
318     p->mode = MenuModeMaskBorder;
319     p->event = colev;
320     p->strfunc = redraw_col;
321     p++;
322   }
323   p->n = -1;
324   topmenuwin_create(colmenu, x, y);
325   for (i = 0; i < MAXCOLSET; i++)
326     colgc[i] = XCreateGC(dsp, colmenu[i].win, 0, 0);
327   bzero(coledmn, sizeof(coledmn));
328   bzero(coledopened, sizeof(coledopened));
329   get_rgb_gc();
330   return 0;
331 }
332 
update_coled_sub(n)333 void update_coled_sub(n)
334      int n;
335 {
336   MENU *p;
337 
338   if (coledwin[n]) {
339     redraw_window(coledwin[n]);
340     p = coledmn[n];
341     clear_color_digits(p);
342     while (p->n >= 0) {
343       redraw_window(p->win);
344       p++;
345     }
346   }
347 }
348 
update_coled_window()349 void update_coled_window()
350 {
351   int i;
352 
353   for (i = 0; i < MAXCOLSET; i++)
354     update_coled_sub(i);
355 }
356 
update_colmenu(n)357 void update_colmenu(n)
358      int n;
359 {
360   update_coled_sub(n);
361   redraw_window(colmenu[n].win);
362 }
363 
364 
coledstr(p)365 char *coledstr(p)
366      MENU *p;
367 {
368   int i;
369 
370   switch(p->n) {
371   case COLED_NRED:
372     i = coled_col(p)->rgb.red;
373     break;
374   case COLED_NGREEN:
375     i = coled_col(p)->rgb.green;
376     break;
377   case COLED_NBLUE:
378     i = coled_col(p)->rgb.blue;
379     break;
380   }
381   if (strcmp(p->str, color_digit_initstr) == 0)
382     sprintf(p->str, "%d", i);
383   return p->str;
384 }
385 
draw_rgb_bar(p)386 void draw_rgb_bar(p)
387      MENU *p;
388 {
389   int i, w;
390   COL *col;
391 
392   col = coled_col(p);
393   switch(p->n) {
394   case COLED_RED:
395     i = 0;
396     w = col->rgb.red;
397     break;
398   case COLED_GREEN:
399     i = 1;
400     w = col->rgb.green;
401     break;
402   case COLED_BLUE:
403     i = 2;
404     w = col->rgb.blue;
405     break;
406   }
407   XClearWindow(dsp, p->win);
408   XResizeWindow(dsp, colorbarwin[coled_num(p)][i], w<1?1:w, COLBARH-BDW*3);
409   XFillRectangle(dsp, p->win, gc0, BDW+w, BDW, 1, p->h-BDW*2);
410 }
411 
412 /* update color
413  * input: color_buf[current_pal*MAXCOLSET+n]
414  *        pixtbl[n]
415  */
change_color(n)416 void change_color(n)
417      int n;			/* color number */
418 {
419   XColor col;
420 
421   if (*(coltbl+n) & CM_PRIVATE) {
422     calcol(&col, color_buf+n);
423     col.pixel = pixtbl[n];
424     XStoreColor(dsp, cmap, &col);
425   }
426   n %= MAXCOLSET;
427   redraw_window(colmenu[n].win);
428   if (coledopened[n]) {
429     clear_color_digits(coledmn[n]);
430     redraw_window(coledmn[n][COLED_RED].win);
431     redraw_window(coledmn[n][COLED_GREEN].win);
432     redraw_window(coledmn[n][COLED_BLUE].win);
433     redraw_window(coledmn[n][COLED_NRED].win);
434     redraw_window(coledmn[n][COLED_NGREEN].win);
435     redraw_window(coledmn[n][COLED_NBLUE].win);
436   }
437   color_update_all();
438 }
439 
440 static char *color_pushed = NULL;
441 
reset_color_pushed(n)442 void reset_color_pushed(n)
443      int n;
444 {
445   if (debug_mode)
446     fprintf(stderr, "reset_color_pushed(%d)\n", n);
447   if (color_pushed != NULL) {
448     if (n < 0)
449       bzero(color_pushed, MAXCOLSET);
450     else
451       color_pushed[n] = 0;
452   }
453 }
454 
coledev(p,ev)455 int coledev(p, ev)
456      MENU *p;
457      XEvent *ev;
458 {
459   int i;
460 
461   switch(ev->type) {
462   case Expose:
463     switch(p->n) {
464     case COLED_COLOR:
465       XFillRectangle(dsp, p->win, colgc[p->cursor],
466 		     ev->xexpose.x, ev->xexpose.y,
467 		     ev->xexpose.width, ev->xexpose.height);
468       break;
469     case COLED_RED:
470     case COLED_GREEN:
471     case COLED_BLUE:
472       if (ev->xexpose.count == 0)
473 	draw_rgb_bar(p);
474       break;
475     }
476     break;
477   case ButtonPress:
478     if (debug_mode)
479       fprintf(stderr, "coledev: ButtonPress\n");
480     switch(p->n) {
481     case COLED_OK:
482       if (color_pushed != NULL) {
483 	if (debug_mode)
484 	  fprintf(stderr, "coledev: clear color_pushed[%d]\n", coled_num(p));
485 	reset_color_pushed(coled_num(p));
486       }
487       unmap_coled_window(coled_num(p));
488       return 1;
489     case COLED_COLOR:
490       XRaiseWindow(dsp, coledwin[coled_num(p)]);
491       return 1;
492     }
493     if (color_pushed == NULL) {
494       if (debug_mode)
495 	fprintf(stderr, "coledev: malloc color_pushed\n");
496       color_pushed = malloc(MAXCOLSET);
497       bzero(color_pushed, MAXCOLSET);
498     }
499     if (debug_mode)
500       fprintf(stderr, "coledev: check color_pushed[%d]\n", coled_num(p));
501     if (!color_pushed[coled_num(p)]) {
502       color_pushed[coled_num(p)] = 1;
503       if (debug_mode)
504 	fprintf(stderr, "coledev: undo_push_color(%d)\n",
505 		current_pal*MAXCOLSET+coled_num(p));
506       undo_push_color(current_pal*MAXCOLSET+coled_num(p), 1);
507     }
508     if (debug_mode)
509       fprintf(stderr, "coledev: press operation done\n");
510     /* FALL THROUGH */
511   case MotionNotify:
512     if (!(coltbl[coled_num(p)] & CM_PRIVATE))
513       return 1;
514     switch(ev->type) {
515     case MotionNotify:
516       i = ev->xmotion.x;
517       break;
518     case ButtonPress:
519       i = ev->xbutton.x;
520       break;
521     default:
522       if (debug_mode)
523 	fprintf(stderr, "unknown colev %d\n", ev->type);
524       break;
525     }
526     if (i < 0)
527       i = 0;
528     if (i > 255)
529       i = 255;
530     switch(p->n) {
531     case COLED_RED:
532       if (coled_col(p)->rgb.red != i) {
533 	colchanged = 1;
534 	coled_col(p)->rgb.red = i;
535       }
536       break;
537     case COLED_GREEN:
538       if (coled_col(p)->rgb.green != i) {
539 	colchanged = 1;
540 	coled_col(p)->rgb.green = i;
541       }
542       break;
543     case COLED_BLUE:
544       if (coled_col(p)->rgb.blue != i) {
545 	colchanged = 1;
546 	coled_col(p)->rgb.blue = i;
547       }
548       break;
549     }
550     change_color(coled_colnum(p));
551     return 1;
552   }
553   return 0;
554 }
555 
colednev(p,ev)556 int colednev(p, ev)
557      MENU *p;
558      XEvent *ev;
559 {
560   int i;
561   KeySym key;
562   char buf[16];
563 
564   switch(ev->type) {
565   case KeyPress:
566     i = XLookupString((XKeyEvent *)ev, buf, sizeof(buf)-1, &key, NULL);
567     buf[i] = '\0';
568     switch(key) {
569     case XK_KP_Enter:
570     case XK_Return:
571       switch(p->n) {
572       case COLED_NRED:
573 	undo_push_color(current_pal*MAXCOLSET+coled_num(p), 1);
574 	coled_col(p)->rgb.red = strtol(p->str, NULL, 0);
575 	break;
576       case COLED_NGREEN:
577 	undo_push_color(current_pal*MAXCOLSET+coled_num(p), 1);
578 	coled_col(p)->rgb.green = strtol(p->str, NULL, 0);
579 	break;
580       case COLED_NBLUE:
581 	undo_push_color(current_pal*MAXCOLSET+coled_num(p), 1);
582 	coled_col(p)->rgb.blue = strtol(p->str, NULL, 0);
583 	break;
584       }
585       colchanged = 1;
586       change_color(coled_colnum(p));
587       break;
588     }
589     break;
590   }
591   return 0;			/* continue to defalut event operation */
592 }
593 
594 /* End of file */
595