1 /* $Header: /home/yav/xpx/RCS/area.c,v 1.2 1996/04/28 03:19:46 yav Exp $
2  * xpx area 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 "editdef.h"
14 #include "icondef.h"
15 
16 #define PUBLIC_AREA_C
17 #include "extern.h"
18 
19 char rcsid_area[] = "$Id: area.c,v 1.2 1996/04/28 03:19:46 yav Exp $";
20 
21 /* edit.c */
22 extern MENU editmenu2[];
23 /* hold.c */
24 extern AREA hold;
25 
26 
27 #define AREA_COPY	0
28 #define AREA_PASTE	1
29 #define AREA_FLIPV	2
30 #define AREA_SHIFTU	3
31 #define AREA_FLIPH	4
32 #define AREA_SHIFTL	5
33 #define AREA_FACTOR	6
34 #define AREA_SHIFTR	7
35 #define AREA_TURNL	8
36 #define AREA_SHIFTD	9
37 #define AREA_TURNR	10
38 #define AREA_OK	11
39 
40 #define AREAWIDTH	108
41 #define AREAHEIGHT	216
42 
43 #define MW 32
44 #define MH 32
45 
46 int areaev();
47 
48 #define IMASK (ExposureMask|EnterWindowMask|LeaveWindowMask|ButtonPressMask)
49 static MENU areamenu[] = {
50   {
51     AREA_COPY, MenuModeMaskBorder,
52     4, 4, 98, MH,
53     0, IMASK, 0,
54     areaev, NULL, 0, 0, "-> hold"
55   },{
56     AREA_PASTE, MenuModeMaskBorder,
57     4, 4 + MH+BDW, 98, MH,
58     0, IMASK, 0,
59     areaev, NULL, 0, 0, "<- hold"
60   },{
61     AREA_FLIPV, MenuModeMaskBorder,
62     4, 4 + MH+BDW + 4 + MH+BDW, MW, MH,
63     0, IMASK, 0,
64     areaev, NULL, 0, 0, NULL
65   },{
66     AREA_SHIFTU, MenuModeMaskBorder,
67     4 + MW+BDW, 4 + MH+BDW + 4 + + MH+BDW, MW, MH,
68     0, IMASK, 0,
69     areaev, NULL, 0, 0, NULL
70   },{
71     AREA_FLIPH, MenuModeMaskBorder,
72     4 + MW+BDW + MW+BDW, 4 + MH+BDW + 4+ + MH+BDW, MW, MH,
73     0, IMASK, 0,
74     areaev, NULL, 0, 0, NULL
75   },{
76     AREA_SHIFTL, MenuModeMaskBorder,
77     4, 4 + MH+BDW + 4 + MH+BDW + MH+BDW, MW, MH,
78     0, IMASK, 0,
79     areaev, NULL, 0, 0, NULL
80   },{
81     AREA_FACTOR, MenuModeMaskBorder,
82     4 + MW+BDW, 4 + MH+BDW + 4 + MH+BDW + MH+BDW, MW, MH,
83     0, IMASK|KeyPressMask, 0,
84     areaev, NULL, 0, 8, NULL
85   },{
86     AREA_SHIFTR, MenuModeMaskBorder,
87     4 + MW+BDW + MW+BDW, 4 + MH+BDW + 4 + MH+BDW + MH+BDW, MW, MH,
88     0, IMASK, 0,
89     areaev, NULL, 0, 0, NULL
90   },{
91     AREA_TURNL, MenuModeMaskBorder,
92     4, 4 + MH+BDW + 4 + MH+BDW + MH+BDW + MH+BDW, MW, MH,
93     0, IMASK, 0,
94     areaev, NULL, 0, 0, NULL
95   },{
96     AREA_SHIFTD, MenuModeMaskBorder,
97     4 + MW+BDW, 4 + MH+BDW + 4 + MH+BDW + MH+BDW + MH+BDW, MW, MH,
98     0, IMASK, 0,
99     areaev, NULL, 0, 0, NULL
100   },{
101     AREA_TURNR, MenuModeMaskBorder,
102     4 + MW+BDW + MW+BDW, 4 + MH+BDW + 4 + MH+BDW + MH+BDW + MH+BDW, MW, MH,
103     0, IMASK, 0,
104     areaev, NULL, 0, 0, NULL
105   },{
106     AREA_OK, MenuModeMaskBorder,
107     4, 4, 64, 24,
108     0, IMASK, SouthEastGravity,
109     areaev, NULL, 0, 0, "OK"
110   },{
111     -1, 0,
112     0, 0, 0, 0,
113     0, 0, 0,
114     NULL, NULL, 0, 0, NULL
115   }
116 };
117 
118 static Window areawin;
119 static int shiftn = 1;		/* shift factor (pixel) */
120 
create_area_menu()121 int create_area_menu()
122 {
123   create_toplevel_window(&areawin, "area", "",
124 			 AREAWIDTH, AREAHEIGHT);
125   XSelectInput(dsp, areawin, ExposureMask);
126   menuwin_create(areamenu, areawin, 0, 0);
127   return 0;
128 }
129 
unmap_area_window()130 void unmap_area_window()
131 {
132   /* area menu open menu off */
133   XUnmapWindow(dsp, areawin);
134 }
135 
map_area_window()136 void map_area_window()
137 {
138   XMapRaised(dsp, areawin);
139 }
140 
141 /* get image processing area
142  * return != 0: cannot to adjust
143  */
get_area(AREA * p)144 int get_area(AREA *p)
145 {
146   memcpy(p, &area0, sizeof(AREA));
147   little_big(&p->x, &p->w);
148   p->w -= p->x;
149   little_big(&p->y, &p->h);
150   p->h -= p->y;
151   if (p->x < 0 || p->x >= imgfilew || p->w <= 0 ||
152       p->y < 0 || p->y >= imgfileh || p->h <= 0) {
153     p->x = p->y = 0;
154     p->w = imgfilew;
155     p->h = imgfileh;
156   }
157   if (p->x + p->w > imgfilew)
158     p->w = imgfilew - p->x;
159   if (p->y + p->h > imgfileh)
160     p->h = imgfileh - p->y;
161   return (p->w <= 0 || p->h <= 0);
162 }
163 
edit_paste_hold()164 int edit_paste_hold()
165 {
166   int r;
167   AREA ar;
168 
169   if (get_area(&ar))
170     return 1;
171   if (ar.w > hold.w)
172     ar.w = hold.w;
173   if (ar.h > hold.h)
174     ar.h = hold.h;
175   undo_push_area(ar.x, ar.y, ar.w, ar.h);
176   r = load_holdspace(&ar);
177   area_update(ar.x, ar.y, ar.w, ar.h);
178   return r;
179 }
180 
edit_copy_hold()181 int edit_copy_hold()
182 {
183   AREA ar;
184 
185   if (get_area(&ar))
186     return 1;
187   return save_holdspace(&ar);
188 }
189 
190 /* vertical flip */
flipv()191 void flipv()
192 {
193   int c, x, y;
194   AREA ar;
195   unsigned char *pt, *pb;
196 
197   if (get_area(&ar))
198     return;
199   undo_push_area(ar.x, ar.y, ar.w, ar.h);
200   for (y = 0; y < ar.h/2; y++) {
201     pt = imgdata + imgmaxw * (ar.y + y) + ar.x;
202     pb = imgdata + imgmaxw * (ar.y + ar.h - 1 - y) + ar.x;
203     for (x = ar.w; x; --x) {
204       c = *pt;
205       *pt++ = *pb;
206       *pb++ = c;
207     }
208   }
209   update_area(ar.x, ar.y, ar.w, ar.h); /* update XImage */
210   area_update(ar.x, ar.y, ar.w, ar.h);
211 }
212 
213 /* horizontal flip */
fliph()214 void fliph()
215 {
216   int c, x, y;
217   AREA ar;
218   unsigned char *pl, *pr;
219 
220   if (get_area(&ar))
221     return;
222   undo_push_area(ar.x, ar.y, ar.w, ar.h);
223   for (y = ar.y; y < ar.y + ar.h; y++) {
224     pl = imgdata + imgmaxw * y + ar.x;
225     pr = pl + ar.w;
226     for (x = ar.w/2; x; --x) {
227       c = *(--pr);
228       *pr = *pl;
229       *pl++ = c;
230     }
231   }
232   update_area(ar.x, ar.y, ar.w, ar.h); /* update XImage */
233   area_update(ar.x, ar.y, ar.w, ar.h);
234 }
235 
236 /* horizontal shift */
hshift(sh)237 void hshift(sh)
238      int sh;			/* shift pixels (minus:left, plus:right) */
239 {
240   int y;
241   AREA ar;
242   unsigned char *p;
243   unsigned char *lnbuf;
244   int storefrom, storeto, storelen, movefrom, moveto;
245 
246   if (get_area(&ar))
247     return;
248   undo_push_area(ar.x, ar.y, ar.w, ar.h);
249   sh %= ar.w;
250   if (sh < 0) {
251     /* shift left */
252     sh = -sh;
253     storefrom = sh; storeto = 0;
254     movefrom = 0; moveto = ar.w - sh;
255   } else {
256     /* shift right */
257     storefrom = 0; storeto = sh;
258     movefrom = ar.w - sh; moveto = 0;
259   }
260   storelen = ar.w - sh;
261   lnbuf = malloc(storelen);
262   for (y = ar.y; y < ar.y + ar.h; y++) {
263     p = imgdata + imgmaxw * y + ar.x;
264     memcpy(lnbuf, p + storefrom, storelen);
265     memcpy(p + moveto, p + movefrom, sh); /* Not overlap */
266     memcpy(p + storeto, lnbuf, storelen);
267   }
268   free(lnbuf);
269   update_area(ar.x, ar.y, ar.w, ar.h); /* update XImage */
270   area_update(ar.x, ar.y, ar.w, ar.h);
271 }
272 
273 /* vertical shift */
vshift(sh)274 void vshift(sh)
275      int sh;			/* shift pixels (minus:up, plus:down) */
276 {
277   int x, y;
278   AREA ar;
279   unsigned char *p;
280   unsigned char *lnbuf;
281 
282   if (get_area(&ar))
283     return;
284   undo_push_area(ar.x, ar.y, ar.w, ar.h);
285   sh %= ar.h;
286   if (sh < 0) {
287     /* shift up */
288     sh = -sh;
289     lnbuf = malloc(sh);
290     for (x = ar.x; x < ar.x + ar.w; x++) {
291       p = imgdata + imgmaxw * ar.y + x;
292       for (y = 0; y < sh; y++)
293 	*(lnbuf + y) = *(p + imgmaxw * y);
294       for (y = 0; y < ar.h - sh; y++)
295 	*(p + imgmaxw * y) = *(p + imgmaxw * (sh + y));
296       for (y = 0; y < sh; y++)
297 	*(p + imgmaxw * (ar.h - sh + y)) = *(lnbuf + y);
298     }
299   } else {
300     /* shift down */
301     lnbuf = malloc(sh);
302     for (x = ar.x; x < ar.x + ar.w; x++) {
303       p = imgdata + imgmaxw * ar.y + x;
304       for (y = 0; y < sh; y++)
305 	*(lnbuf + y) = *(p + imgmaxw * (ar.h - sh + y));
306       for (y = ar.h - sh - 1; y >= 0; --y)
307 	*(p + imgmaxw * (sh + y)) = *(p + imgmaxw * y);
308       for (y = 0; y < sh; y++)
309 	*(p + imgmaxw * y) = *(lnbuf + y);
310     }
311   }
312   free(lnbuf);
313   update_area(ar.x, ar.y, ar.w, ar.h); /* update XImage */
314   area_update(ar.x, ar.y, ar.w, ar.h);
315 }
316 
turn90r(n)317 void turn90r(n)
318      int n;
319 {
320   int i, c, x, y, w;
321   AREA ar;
322 
323   if (get_area(&ar))
324     return;
325   undo_push_area(ar.x, ar.y, ar.w, ar.h);
326   while (n--) {
327     w = ar.w < ar.h ? ar.w : ar.h;
328     for (x = ar.x, y = ar.y; w > 0; x++, y++, w -= 2) {
329       for (i = 0; i < w-1; i++) {
330 	c = *(imgdata+imgmaxw*y+x+i);
331 	*(imgdata+imgmaxw*y+x+i) = *(imgdata+imgmaxw*(y+w-1-i)+x);
332 	*(imgdata+imgmaxw*(y+w-1-i)+x) = *(imgdata+imgmaxw*(y+w-1)+x+w-1-i);
333 	*(imgdata+imgmaxw*(y+w-1)+x+w-1-i) = *(imgdata+imgmaxw*(y+i)+x+w-1);
334 	*(imgdata+imgmaxw*(y+i)+x+w-1) = c;
335       }
336     }
337   }
338   update_area(ar.x, ar.y, ar.w, ar.h); /* update XImage */
339   area_update(ar.x, ar.y, ar.w, ar.h);
340 }
341 
342 
areaev(p,ev)343 int areaev(p, ev)
344      MENU *p;
345      XEvent *ev;
346 {
347   int i;
348   KeySym key;
349   char buf[16];
350 
351   switch(ev->type) {
352   case Expose:
353     if (ev->xexpose.count)
354       break;
355     switch (p->n) {
356     case AREA_FLIPV:
357       i = ICON_flipv;
358       break;
359     case AREA_SHIFTU:
360       i = ICON_up;
361       break;
362     case AREA_FLIPH:
363       i = ICON_fliph;
364       break;
365     case AREA_SHIFTL:
366       i = ICON_left;
367       break;
368     case AREA_SHIFTR:
369       i = ICON_right;
370       break;
371     case AREA_TURNL:
372       i = ICON_turnl;
373       break;
374     case AREA_SHIFTD:
375       i = ICON_down;
376       break;
377     case AREA_TURNR:
378       i = ICON_turnr;
379       break;
380     default:
381       return 0;
382     }
383     menu_icon_center(p, i);
384     return 1;
385   case ButtonPress:
386     switch (p->n) {
387     case AREA_OK:
388       unmap_area_window();
389       editmenu2[EDIT2_AREA].mode &= ~MenuModeMaskOn;
390       redraw_window(editmenu2[EDIT2_AREA].win);
391       break;
392     case AREA_COPY:
393       edit_copy_hold();
394       break;
395     case AREA_PASTE:
396       edit_paste_hold();
397       break;
398     case AREA_FLIPV:
399       flipv();
400       break;
401     case AREA_FLIPH:
402       fliph();
403       break;
404     case AREA_SHIFTL:
405       hshift(-shiftn);
406       break;
407     case AREA_SHIFTR:
408       hshift(shiftn);
409       break;
410     case AREA_SHIFTU:
411       vshift(-shiftn);
412       break;
413     case AREA_SHIFTD:
414       vshift(shiftn);
415       break;
416     case AREA_TURNL:
417       turn90r(3);
418       break;
419     case AREA_TURNR:
420       turn90r(1);
421       break;
422     }
423     p->mode &= ~MenuModeMaskOn;
424     redraw_window(p->win);
425     return 1;
426   case KeyPress:
427     i = XLookupString((XKeyEvent *)ev, buf, sizeof(buf)-1, &key, NULL);
428     buf[i] = '\0';
429     switch(key) {
430     case XK_KP_Enter:
431     case XK_Return:
432       shiftn = strtol(p->str, NULL, 0);
433       sprintf(p->str, "%d", shiftn);
434       redraw_window(p->win);
435       return 1;
436     }
437     break;
438   }
439   return 0;
440 }
441 
442 /* End of file */
443