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