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