1 /* $Header: /home/yav/xpx/RCS/edit.c,v 1.32 1996/04/26 17:22:47 yav Exp $
2  * xpx image 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 #ifdef HAVE_MATH_H
12 #include <math.h>
13 #endif
14 #include "xpx.h"
15 #include "work.h"
16 #include "editdef.h"
17 #include "menudef.h"
18 #include "cursdef.h"
19 #define PUBLIC_EDIT_C
20 #include "extern.h"
21 
22 
23 #define AUTOSAVETIME 30
24 
25 #define EDMW	64
26 #define EDMH	24
27 
28 #define EDITWINW 214
29 #define EDITWINH (EDITWINH2+8+(BDW+EDMH+BDW)+2+(BDW+EDMH+BDW)+4)
30 #define EDITWINH2 ((EDMH+BDW)*EDIT_PEN+BDW+8+(BDW+EDMH+BDW))
31 
32 char rcsid_edit[] = "$Id: edit.c,v 1.32 1996/04/26 17:22:47 yav Exp $";
33 
34 
35 /* work */
36 static Window editfuncwin[3];
37 static int edit_mode[3] = {EDIT_PLOT, EDIT_GETCOLOR, EDIT_GETCOLOR};
38 static int area_mode = 0;
39 static int circle_mode = 0;
40 static int line_mode = 0;
41 static POS copypos0, copysrc0, copysrc1;
42 static AREA copydst;
43 static int penno[3] = {0, 0, 0};
44 static int penwidthtbl[] = {1, 2, 3, 5, 7, 0};
45 
46 
47 int edev();
48 int edev2();
49 
edevpenstr(p)50 char *edevpenstr(p)
51      MENU *p;
52 {
53   sprintf(p->str, "width %d", penwidthtbl[penno[get_top_menu(p)->cursor]]);
54   return p->str;
55 }
56 
edevpen(p,ev)57 int edevpen(p, ev)
58      MENU *p;
59      XEvent *ev;
60 {
61   int i;
62 
63   switch (ev->type) {
64   case ButtonPress:
65     i = get_top_menu(p)->cursor;
66     ++penno[i];
67     if (!penwidthtbl[penno[i]])
68       penno[i] = 0;
69     redraw_window(p->win);
70     return 1;
71   }
72   return 0;
73 }
74 
75 #define IMASK (ExposureMask|EnterWindowMask|LeaveWindowMask|ButtonPressMask)
76 #define EMSTRUC(num,name) \
77 { (num), MenuModeMaskBorder,\
78   0, (EDMH+BDW)*(num), EDMW, EDMH,\
79   0, IMASK, 0,\
80   edev, NULL, 0, 0, name}
81 
82 static MENU menutbl[] = {
83   {
84     EDIT_dummy,	0,
85     0, 0, EDMW, EDMH,
86     0, ExposureMask, 0,
87     NULL, NULL, 0, 0, "Button?"},
88   EMSTRUC(EDIT_PLOT,	"plot"),
89   EMSTRUC(EDIT_COPY,	"copy"),
90   EMSTRUC(EDIT_FILL,	"boxfull"),
91   EMSTRUC(EDIT_LINE,	"line"),
92   EMSTRUC(EDIT_CIRCLE,	"circle"),
93   EMSTRUC(EDIT_ELLIPSE,	"ellipse"),
94   EMSTRUC(EDIT_PAINT,	"paint"),
95   EMSTRUC(EDIT_GETCOLOR,"get"),
96   EMSTRUC(EDIT_SCROLL,	"scroll"),
97   EMSTRUC(EDIT_HOTSPOT,	"hotspot"),
98   EMSTRUC(EDIT_GRID,	"grid"),
99   EMSTRUC(EDIT_CANCEL,	"cancel"),
100   {
101     EDIT_ONGRID,	MenuModeMaskBorder,
102     0, (EDMH+BDW)*EDIT_ONGRID+BDW+4, EDMW, EDMH,
103     0, IMASK, 0,
104     NULL, NULL, 0, 0, "on grid"},
105   {
106     EDIT_PEN,	MenuModeMaskBorder,
107     0, (EDMH+BDW)*EDIT_PEN+BDW+4, EDMW, EDMH,
108     0, IMASK, 0,
109     edevpen, edevpenstr, 0, 16, NULL},
110   {
111     -1,	0,
112     0, 0, 0, 0,
113     0, 0, 0,
114     NULL, NULL, 0, 0, NULL}};
115 
116 char *edev2str();
117 MENU editmenu2[] = {
118   {
119     EDIT2_UNDO,	MenuModeMaskBorder,
120     4, 6+ BDW*2+4 + EDMH+BDW*2, 70, EDMH,
121     0, IMASK, SouthWestGravity,
122     edev2, edev2str, 0, 16, NULL},
123   {
124     EDIT2_IGNPIX,	0,
125     4 + 70+BDW*2 + 8, 6+ BDW*2+4 + EDMH+BDW*2, 78, EDMH,
126     0, ExposureMask, SouthWestGravity,
127     NULL, NULL, 0, 0, "nocopypix:"},
128   {
129     EDIT2_IGNPIXN,	MenuModeMaskBorder,
130     4 + 70+BDW*2 + 8 + 78, 6+ BDW*2+4 + EDMH+BDW*2, 40, EDMH,
131     0, IMASK|KeyPressMask, SouthWestGravity,
132     edev2, NULL, 0, 8, NULL},
133   {
134     EDIT2_AREA,	MenuModeMaskBorder,
135     4, BDW*2+4, EDMW, EDMH,
136     0, IMASK, SouthWestGravity,
137     edev2, NULL, 0, 0, "Area"},
138   {
139     EDIT2_OK,	MenuModeMaskBorder,
140     BDW*2+4, BDW*2+4, EDMW, EDMH,
141     0, IMASK, SouthEastGravity,
142     edev2, NULL, 0, 0, "OK"},
143   {
144     -1,	0,
145     0, 0, 0, 0,
146     0, 0, 0,
147     NULL, NULL, 0, 0, NULL}};
148 MENU *menutblp[3];
149 
150 static int *ptsbuf = NULL;
151 
152 
create_edit_window()153 int create_edit_window()
154 {
155   int i;
156   MENU *p;
157   static char *titles[3] = {"Button1", "Button2", "Button3"};
158 
159   ptsbuf = (int*)malloc(sizeof(int)*8*(imgmaxw+imgmaxh));
160 
161   create_toplevel_window(&editwin, "edit", str_edit_geom, EDITWINW, EDITWINH);
162   XSelectInput(dsp, editwin, ExposureMask);
163   for (i = 0; i < 3; i++) {
164     editfuncwin[i] =
165       XCreateSimpleWindow(dsp, editwin,
166 			  4+(EDMW+BDW*2+4)*i, 0, EDMW+BDW*2, EDITWINH2,
167 			  0, fg, bg);
168     XSelectInput(dsp, editfuncwin[i], ExposureMask);
169     XMapWindow(dsp, editfuncwin[i]);
170     p = (MENU *)malloc(sizeof(menutbl));
171     memcpy(p, menutbl, sizeof(menutbl));
172     p->str = titles[i];
173     p->cursor = i;
174     if (i == 0) {
175       /* short cut key initial */
176       (p+EDIT_PLOT)->str = "plOt";
177       (p+EDIT_COPY)->str = "Copy";
178       (p+EDIT_FILL)->str = "Boxfull";
179       (p+EDIT_LINE)->str = "liNe";
180       (p+EDIT_PAINT)->str = "Paint";
181     }
182     (p+edit_mode[i])->mode |= MenuModeMaskOn;
183     menuwin_create(p, editfuncwin[i], 0, 0);
184     menutblp[i] = p;
185   }
186   menuwin_create(editmenu2, editwin, 0, 0);
187   /* Area edit menu */
188   create_area_menu();
189   return 0;
190 }
191 
map_edit_window()192 void map_edit_window()
193 {
194   XMapRaised(dsp, editwin);
195 }
196 
unmap_edit_window()197 void unmap_edit_window()
198 {
199   XUnmapWindow(dsp, editwin);
200 }
201 
close_edit_window()202 void close_edit_window()
203 {
204   XDestroyWindow(dsp, editwin);
205 }
206 
area_mode_reset()207 void area_mode_reset()
208 {
209   area_flag = False;
210   area_mode = line_mode = circle_mode = 0;
211   copy_area_expose();
212 }
213 
edit_mode_change2(btn,mode)214 void edit_mode_change2(btn, mode)
215      int btn;		/* 0:Button1 1:Button2 2:Button3 */
216      int mode;
217 {
218   MENU *p;
219 
220   area_mode_reset();
221   p = menutblp[btn]+edit_mode[btn];
222   if (mode != edit_mode[btn]) {
223     p->mode &= ~MenuModeMaskOn;
224     redraw_window(p->win);
225     edit_mode[btn] = mode;
226     p = menutblp[btn]+mode;
227     p->mode |= MenuModeMaskOn;
228     redraw_window(p->win);
229   }
230 }
231 
edit_mode_change(n)232 void edit_mode_change(n)
233      int n;
234 {
235   edit_mode_change2(0, n);
236 }
237 
edev(p,ev)238 int edev(p, ev)
239      MENU *p;
240      XEvent *ev;
241 {
242   switch(ev->type) {
243   case ButtonPress:
244     edit_mode_change2(get_top_menu(p)->cursor, p->n);
245     return 1;
246   }
247   return 0;
248 }
249 
edit_undo()250 void edit_undo()
251 {
252   cursor_busy();
253   undo_pull();
254 }
255 
edev2(p,ev)256 int edev2(p, ev)
257      MENU *p;
258      XEvent *ev;
259 {
260   int i;
261   KeySym key;
262   char buf[16];
263 
264   switch(ev->type) {
265   case ButtonPress:
266     switch(p->n) {
267     case EDIT2_UNDO:
268       edit_undo();
269       p->mode &= ~MenuModeMaskOn;
270       redraw_window(p->win);
271       return 1;
272     case EDIT2_AREA:
273       p->mode ^= MenuModeMaskOn;
274       if (p->mode & MenuModeMaskOn)
275 	map_area_window();
276       else
277 	unmap_area_window();
278       redraw_window(p->win);
279       return 1;
280     case EDIT2_OK:
281       p->mode &= ~MenuModeMaskOn;
282       menu_stat_change(MENU_EDIT, 0);
283       return 1;
284     case EDIT2_IGNPIXN:
285       p->mode ^= MenuModeMaskOn;
286       nocopypixel_mode = p->mode & MenuModeMaskOn ? True : False;
287       redraw_window(p->win);
288       return 1;
289     }
290   case KeyPress:
291     i = XLookupString((XKeyEvent *)ev, buf, sizeof(buf)-1, &key, NULL);
292     buf[i] = '\0';
293     switch(key) {
294     case XK_KP_Enter:
295     case XK_Return:
296       i = strtol(p->str, NULL, 0);
297       if (i >= 0 && i < 256) {
298 	nocopypixel = i;
299 	sprintf(p->str, "%d", i);
300 	p->mode |= MenuModeMaskOn;
301 	nocopypixel_mode = True;
302       } else {
303 	p->mode &= ~MenuModeMaskOn;
304 	nocopypixel_mode = False;
305       }
306       redraw_window(p->win);
307       return 1;
308     }
309     break;
310   }
311   return 0;
312 }
313 
edev2str(p)314 char *edev2str(p)
315      MENU *p;
316 {
317   switch(p->n) {
318   case EDIT2_UNDO:
319     if (undo_cnt >= MAXUNDO)
320       strcpy(p->str, "Undo MAX");
321     else
322       sprintf(p->str, "Undo %d", undo_cnt);
323     break;
324   }
325   return p->str;
326 }
327 
edit_undo_update()328 void edit_undo_update()
329 {
330   static int last_undo_cnt = -1;
331 
332   if (undo_cnt != last_undo_cnt) {
333     redraw_window(editmenu2[EDIT2_UNDO].win);
334     last_undo_cnt = undo_cnt;
335   }
336 }
337 
338 /*********************************
339  * image edit function
340  */
341 
area_img_expose(x,y,w,h)342 void area_img_expose(x, y, w, h)
343      int x;
344      int y;
345      int w;
346      int h;
347 {
348   calc_img_area(&x, &y, &w, &h);
349   img_expose(x, y, w, h);
350 }
351 
plot(x,y,c)352 void plot(x, y, c)
353      int x;
354      int y;
355      int c;
356 {
357   setpixelcolor(x, y, c);
358   if (vimg != NULL)
359     XClearArea(dsp, viewwin, x, y, 1, 1, True);
360   img_expose(x*zoomfactor-imgofsx, y*zoomfactor-imgofsy,
361 	     zoomfactor, zoomfactor);
362 }
363 
364 /* Window update */
area_update(x,y,w,h)365 void area_update(x, y, w, h)
366      int x;
367      int y;
368      int w;
369      int h;
370 {
371   if (vimg != NULL)
372     XClearArea(dsp, viewwin, x, y, w, h, True);
373   area_img_expose(x, y, w, h);
374   copy_area_expose();
375 }
376 
copy(dstx,dsty,srcx,srcy,w,h)377 void copy(dstx, dsty, srcx, srcy, w, h)
378      int dstx;
379      int dsty;
380      int srcx;
381      int srcy;
382      int w;
383      int h;
384 {
385   if (w > 0 && h > 0) {
386     undo_push_area(dstx, dsty, w, h);
387     copy_area(dstx, dsty, srcx, srcy, w, h);
388     area_update(dstx, dsty, w, h);
389   }
390 }
391 
392 
fill(x,y,w,h,c)393 void fill(x, y, w, h, c)
394      int x;
395      int y;
396      int w;
397      int h;
398      int c;
399 {
400   if (w > 0 && h > 0) {
401     undo_push_area(x, y, w, h);
402     fill_area(x, y, w, h, c);
403     area_update(x, y, w, h);
404   }
405 }
406 
edit_plot(x,y,pen)407 void edit_plot(x, y, pen)
408      int x;
409      int y;
410      int pen;			/* pen width (pixel) */
411 {
412   static int lastpen = -1;
413   static int lastcol = -1;
414 
415   switch (pen) {
416   case 1:
417     if (current_col >= 0 && *(imgdata+y*imgmaxw+x) != current_col) {
418       undo_push_plot(x, y, *(imgdata+y*imgmaxw+x), current_col);
419       plot(x, y, current_col);
420     }
421     break;
422   default:
423     if (pen != lastpen || current_col != lastcol) {
424       cursor_busy();
425       undo_push_area(0, 0, imgfilew, imgfileh);
426       lastpen = pen;
427       lastcol = current_col;
428     }
429     fill_area(x-(pen-1)/2, y-(pen-1)/2, pen, pen, current_col);
430     area_update(x-(pen-1)/2, y-(pen-1)/2, pen, pen);
431     break;
432   }
433 }
434 
edit_copy_and_fill(x,y,type,btn)435 void edit_copy_and_fill(x, y, type, btn)
436      int x;
437      int y;
438      int type;			/* event type */
439      int btn;			/* 0:Button1 1:Button2 2:Button3 */
440 {
441   switch (type) {
442   case ButtonPress:
443     switch(area_mode) {
444     case 2:
445       if (inarea(x, 1, copysrc0.x, copysrc1.x)&&
446 	  inarea(y, 1, copysrc0.y, copysrc1.y)) {
447 	/* area catch */
448 	copydst.x = x - copysrc0.x;
449 	copydst.y = y - copysrc0.y;
450 	copydst.w = copysrc1.x - copysrc0.x;
451 	copydst.h = copysrc1.y - copysrc0.y;
452 	area_mode = 3;
453 	break;
454       }
455       /* FALL THROUGH */
456     case 0:
457       /* area mark start */
458       copypos0.x = x;
459       copypos0.y = y;
460       area_mode = 1;
461       break;
462     }
463     break;
464   case ButtonRelease:
465     switch(area_mode) {
466     case 3:
467       /* paste */
468       copy(area0.x, area0.y, copysrc0.x, copysrc0.y,
469 	   copysrc1.x - copysrc0.x, copysrc1.y - copysrc0.y);
470       /* FALL THROUGH */
471     case 1:
472       /* area mark end */
473       copysrc0.x = area0.x;
474       copysrc0.y = area0.y;
475       copysrc1.x = area0.w;
476       copysrc1.y = area0.h;
477       little_big(&copysrc0.x, &copysrc1.x);
478       little_big(&copysrc0.y, &copysrc1.y);
479       switch(edit_mode[btn]) {
480       case EDIT_FILL:
481 	erase_last_area();
482 	area_flag = False;
483 	area_mode = 0;
484 	fill(copysrc0.x, copysrc0.y,
485 	     copysrc1.x-copysrc0.x, copysrc1.y-copysrc0.y, current_col);
486 	break;
487       case EDIT_COPY:
488 	area_mode = 2;
489 	break;
490       }
491       break;
492     }
493     break;
494   case MotionNotify:
495     switch(area_mode) {
496     case 1:
497       /* area size update */
498       if (x != area0.w || y != area0.h) {
499 	area0.w = x;
500 	area0.h = y;
501 	area0.x = copypos0.x;
502 	area0.y = copypos0.y;
503 	area_flag = True;
504 	copy_area_expose();
505       }
506       break;
507     case 3:
508       /* drug area */
509       x -= copydst.x;
510       if (x < 0)
511 	x = 0;
512       if (x + copydst.w > imgfilew)
513 	x = imgfilew - copydst.w;
514       y -= copydst.y;
515       if (y < 0)
516 	y = 0;
517       if (y + copydst.h > imgfileh)
518 	y = imgfileh - copydst.h;
519       if (x != area0.x || y != area0.y) {
520 	area0.x = x;
521 	area0.y = y;
522 	area0.w = x + copydst.w;
523 	area0.h = y + copydst.h;
524 	copy_area_expose();
525       }
526       break;
527     }
528     break;
529   }
530 }
531 
532 #ifndef abs
533 #define abs(x) ((x)<0?-(x):(x))
534 #endif
535 
plots(p,n,pen)536 void plots(p, n, pen)
537      int *p;
538      int n;
539      int pen;			/* pen width (pixel) */
540 {
541   int x, y, x0, y0, x1, y1;
542   int xs, ys, xe, ye;
543   int d0, d1;
544 
545   if (current_col < 0 || n <= 0)
546     return;
547   /* check update area */
548   max_area(&x0, &y0, &x1, &y1, n, p);
549   d0 = (pen-1) / 2;
550   if ((x0 -= d0) < 0)
551     x0 = 0;
552   if ((y0 -= d0) < 0)
553     y0 = 0;
554   d1 = pen / 2;
555   if ((x1 += d1) >= imgmaxw)
556     x1 = imgmaxw - 1;
557   if ((y1 += d1) >= imgmaxh)
558     y1 = imgmaxh - 1;
559   undo_push_area(x0, y0, x1-x0+1, y1-y0+1);
560   while (n--) {
561     xs = xe = *p++;
562     ys = ye = *p++;
563     if ((xs -= d0) < 0)
564       xs = 0;
565     if ((xe += d1) >= imgmaxw)
566       xe = imgmaxw - 1;
567     if ((ys -= d0) < 0)
568       ys = 0;
569     if ((ye += d1) >= imgmaxh)
570       ye = imgmaxh - 1;
571     for (y = ys; y <= ye; y++) {
572       for (x = xs; x <= xe; x++) {
573 	setpixelcolor(x, y, current_col);
574       }
575     }
576   }
577   if (vimg != NULL)
578     XClearArea(dsp, viewwin, x0, y0, x1-x0+1, y1-y0+1, True);
579   img_expose(x0*zoomfactor-imgofsx, y0*zoomfactor-imgofsy,
580 	     (x1-x0+1)*zoomfactor, (y1-y0+1)*zoomfactor);
581 }
582 
edit_line(x,y,ev,btn)583 void edit_line(x, y, ev, btn)
584      int x;
585      int y;
586      int ev;			/* event type */
587      int btn;			/* 0:Button1 1:Button2 2:Button3 */
588 {
589   int i;
590   static int x0, y0, x1, y1;
591 
592   switch(ev) {
593   case ButtonPress:
594     x0 = x;
595     y0 = y;
596     x1 = y1 = -1;
597     line_mode = 1;
598     break;
599   case ButtonRelease:
600     if (line_mode == 1) {
601       i = line(ptsbuf, x0, y0, x, y);
602       mark_flag = False;
603       mark_pts_expose();
604       plots(ptsbuf, i, penwidthtbl[penno[btn]]);
605       line_mode = 0;
606     }
607     break;
608   case MotionNotify:
609     if (line_mode == 1 && (x != x1 || y != y1)) {
610       mark_flag = False;
611       mark_pts_expose();
612       i = line(ptsbuf, x0, y0, x, y);
613       mark_pts_set(i, ptsbuf);
614       mark_flag = True;
615       mark_pts_expose();
616       x1 = x;
617       y1 = y;
618     }
619     break;
620   }
621 }
622 
edit_circle_and_ellipse(x,y,ev,btn)623 void edit_circle_and_ellipse(x, y, ev, btn)
624      int x;
625      int y;
626      int ev;			/* event type */
627      int btn;			/* 0:Button1 1:Button2 2:Button3 */
628 {
629   int i, rx, ry;
630   static int x0, y0, x1, y1;
631 
632   switch(ev) {
633   case ButtonPress:
634     x0 = x;
635     y0 = y;
636     x1 = y1 = -1;
637     circle_mode = 1;
638     break;
639   case ButtonRelease:
640     if (circle_mode == 1) {
641       rx = abs(x-x0);
642       ry = abs(y-y0);
643       if (edit_mode[btn] == EDIT_CIRCLE)
644 	ry = rx = ry>rx?ry:rx;
645       if (rx > 0 && ry > 0) {
646 	if (edit_mode[btn] == EDIT_CIRCLE)
647 	  i = circle(ptsbuf, x0, y0, rx);
648 	else
649 	  i = ellipse(ptsbuf, x0, y0, rx, ry);
650 	mark_flag = False;
651 	mark_pts_expose();
652 	plots(ptsbuf, i, penwidthtbl[penno[btn]]);
653       }
654       area_flag = False;
655       copy_area_expose();
656       circle_mode = 0;
657     }
658     break;
659   case MotionNotify:
660     if (circle_mode == 1 && (x != x1 || y != y1)) {
661       rx = abs(x-x0);
662       ry = abs(y-y0);
663       if (edit_mode[btn] == EDIT_CIRCLE)
664 	ry = rx = ry>rx?ry:rx;
665       if (rx > 0 && ry > 0) {
666 	mark_flag = False;
667 	mark_pts_expose();
668 	if (edit_mode[btn] == EDIT_CIRCLE)
669 	  i = circle(ptsbuf, x0, y0, rx);
670 	else
671 	  i = ellipse(ptsbuf, x0, y0, rx, ry);
672 	mark_pts_set(i, ptsbuf);
673 	mark_flag = True;
674 	mark_pts_expose();
675       }
676       x1 = x;
677       y1 = y;
678     }
679     break;
680   }
681 }
682 
683 
edit_paint(x,y,type)684 void edit_paint(x, y, type)
685      int x;
686      int y;
687      int type;
688 {
689   switch(type) {
690   case ButtonPress:
691     cursor_busy();
692     painted_pixel = *(imgdata+y*imgmaxw+x);
693     if (painted_pixel != current_col) {
694       undo_push_area(0, 0, imgfilew, imgfileh);
695       paint(x, y);
696       area_update(0, 0, imgfilew, imgfileh);
697     }
698     break;
699   case ButtonRelease:
700     break;
701   }
702 }
703 
img_button_sub(x,y,type,btn,ox,oy)704 void img_button_sub(x, y, type, btn, ox, oy)
705      int x;
706      int y;
707      int type;
708      int btn;			/* 0:Button1 1:Button2 2:Button3 */
709      int ox;
710      int oy;
711 {
712   switch (edit_mode[btn]) {
713   case EDIT_GETCOLOR:
714     set_current_color(*(imgdata+y*imgmaxw+x));
715     break;
716   case EDIT_PLOT:
717     edit_plot(x, y, penwidthtbl[penno[btn]]);
718     break;
719   case EDIT_COPY:
720   case EDIT_FILL:
721     edit_copy_and_fill(x, y, type, btn);
722     break;
723   case EDIT_LINE:
724     edit_line(x, y, type, btn);
725     break;
726   case EDIT_CIRCLE:
727   case EDIT_ELLIPSE:
728     edit_circle_and_ellipse(x, y, type, btn);
729     break;
730   case EDIT_PAINT:
731     edit_paint(x, y, type);
732     break;
733   case EDIT_SCROLL:
734     switch(type) {
735     case ButtonPress:
736       /* set background scroll */
737       if (ox < imgwinwidth/3)
738 	scroll_ax = -1;
739       if (ox >= imgwinwidth*2/3)
740 	scroll_ax = 1;
741       if (oy < imgwinheight/3)
742 	scroll_ay = -1;
743       if (oy >= imgwinheight*2/3)
744 	scroll_ay = 1;
745       break;
746     case ButtonRelease:
747       /* reset background scroll */
748       scroll_dx = scroll_dy = 0;
749       scroll_ax = scroll_ay = 0;
750       break;
751     }
752     break;
753   case EDIT_GRID:
754     if (type == ButtonPress) {
755       grid_ofsx = x % grid_size;
756       grid_ofsy = y % grid_size;
757       set_image_size(-1, -1);
758       area_mode_reset();
759     }
760     break;
761   case EDIT_HOTSPOT:
762     if (type == ButtonPress) {
763       if (x == hotspotx && y == hotspoty)
764 	x = y = -1;
765       hotspotx = x;
766       hotspoty = y;
767       set_image_size(-1, -1);
768     }
769     /* continue to next case */
770   case EDIT_CANCEL:
771   default:
772     if (type == ButtonPress)
773       area_mode_reset();
774     mark_pts_expose();
775     return;
776   }
777 }
778 
img_button(type,ox,oy,button,st)779 void img_button(type, ox, oy, button, st)
780      int type;
781      int ox;
782      int oy;
783      int button;
784      unsigned int st;
785 {
786   int x, y, dx, dy, btn;
787 
788   x = (ox + imgofsx) / zoomfactor;
789   y = (oy + imgofsy) / zoomfactor;
790   switch(button) {
791   case Button1:
792     btn = 0;
793     break;
794   case Button2:
795     btn = 1;
796     break;
797   case Button3:
798     btn = 2;
799     break;
800   }
801   if ((menutblp[btn]+EDIT_ONGRID)->mode & MenuModeMaskOn) {
802     dx = (x - grid_ofsx) % grid_size;
803     x -= dx;
804     if (dx > grid_size/2)
805       x += grid_size;
806     dy = (y - grid_ofsy) % grid_size;
807     y -= dy;
808     if (dy > grid_size/2)
809       y += grid_size;
810   }
811   if (x < 0)
812     x = 0;
813   if (x >= imgfilew)
814     x = imgfilew;
815   if (y < 0)
816     y = 0;
817   if (y >= imgfileh)
818     y = imgfileh;
819   if (x != curx) {
820     curx = x;
821     redraw_window(cursmenu[CURS_CURX].win);
822   }
823   if (y != cury) {
824     cury = y;
825     redraw_window(cursmenu[CURS_CURY].win);
826   }
827   img_button_sub(x, y, type, btn, ox, oy);
828 }
829 
edit_event(ev)830 void edit_event(ev)
831      XEvent *ev;
832 {
833   int x, y, button;
834   static int savecnt = 0;
835 
836   if (get_event_window(ev) != imgwin)
837     return;
838   switch (ev->type) {
839   case MotionNotify:
840     x = ev->xmotion.x;
841     y = ev->xmotion.y;
842     if (ev->xmotion.state & Button1Mask)
843       img_button(ev->type, x, y, Button1);
844     if (ev->xmotion.state & Button2Mask)
845       img_button(ev->type, x, y, Button2);
846     if (ev->xmotion.state & Button3Mask)
847       img_button(ev->type, x, y, Button3);
848     break;
849   case ButtonRelease:
850     if (++savecnt >= AUTOSAVETIME) {
851       autosave();
852       savecnt = 0;
853     }
854   case ButtonPress:
855     button = ev->xbutton.button;
856     img_button(ev->type, ev->xbutton.x, ev->xbutton.y, ev->xbutton.button);
857     break;
858   }
859 }
860 
861 /* End of file */
862