1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *
11  *      Grabber plugin for the grab-from-grid and autocrop functions.
12  *
13  *      By Shawn Hargreaves.
14  *
15  *      See readme.txt for copyright information.
16  */
17 
18 
19 #include <stdio.h>
20 #include <string.h>
21 
22 #include "allegro.h"
23 #include "../datedit.h"
24 
25 
26 
27 static int gg_text_proc(int msg, DIALOG *d, int c);
28 static int gg_edit_proc(int msg, DIALOG *d, int c);
29 
30 
31 
32 static void *added_item[1024];
33 static int added_count;
34 
35 
36 
37 /* helper for cropping bitmaps */
crop_bitmap(BITMAP * bmp,int * tx,int * ty)38 static BITMAP *crop_bitmap(BITMAP *bmp, int *tx, int *ty)
39 {
40    int tw, th, i, j, c;
41    int changed = FALSE;
42 
43    *tx = 0;
44    *ty = 0;
45    tw = bmp->w;
46    th = bmp->h;
47 
48    if ((tw > 0) && (th > 0)) {
49       c = getpixel(bmp, 0, 0);
50 
51       for (j=*ty; j<(*ty)+th; j++) {       /* top of image */
52 	 for (i=*tx; i<(*tx)+tw; i++) {
53 	    if (getpixel(bmp, i, j) != c)
54 	       goto finishedtop;
55 	 }
56 	 (*ty)++;
57 	 th--;
58 	 changed = TRUE;
59       }
60 
61       finishedtop:
62 
63       for (j=(*ty)+th-1; j>*ty; j--) {     /* bottom of image */
64 	 for (i=*tx; i<(*tx)+tw; i++) {
65 	    if (getpixel(bmp, i, j) != c)
66 	       goto finishedbottom;
67 	 }
68 	 th--;
69 	 changed = TRUE;
70       }
71 
72       finishedbottom:
73 
74       for (j=*tx; j<*(tx)+tw; j++) {       /* left of image */
75 	 for (i=*ty; i<(*ty)+th; i++) {
76 	    if (getpixel(bmp, j, i) != c)
77 	       goto finishedleft;
78 	 }
79 	 (*tx)++;
80 	 tw--;
81 	 changed = TRUE;
82       }
83 
84       finishedleft:
85 
86       for (j=*(tx)+tw-1; j>*tx; j--) {     /* right of image */
87 	 for (i=*ty; i<(*ty)+th; i++) {
88 	    if (getpixel(bmp, j, i) != c)
89 	       goto finishedright;
90 	 }
91 	 tw--;
92 	 changed = TRUE;
93       }
94 
95       finishedright:
96 	 ;
97    }
98 
99    if ((tw != 0) && (th != 0) && (changed)) {
100       BITMAP *b2 = create_bitmap_ex(bitmap_color_depth(bmp), tw, th);
101       clear_to_color(b2, b2->vtable->mask_color);
102       blit(bmp, b2, *tx, *ty, 0, 0, tw, th);
103       destroy_bitmap(bmp);
104       return b2;
105    }
106    else
107       return bmp;
108 }
109 
110 
111 
112 /* worker function for counting bitmap objects */
do_bitmap_check(DATAFILE * dat,int * param,int param2)113 static int do_bitmap_check(DATAFILE *dat, int *param, int param2)
114 {
115    if ((dat->type == DAT_BITMAP) || (dat->type == DAT_RLE_SPRITE) ||
116        (dat->type == DAT_C_SPRITE) || (dat->type == DAT_XC_SPRITE))
117       (*param)++;
118 
119    return D_O_K;
120 }
121 
122 
123 
124 /* checks whether our grab-from-grid command is allowed at the moment */
griddler_query(int popup)125 static int griddler_query(int popup)
126 {
127    DATAFILE *dat;
128    AL_CONST char *s;
129 
130    if (popup) {
131       dat = grabber_single_selection();
132 
133       if (!dat)
134 	 return FALSE;
135 
136       if ((dat->type != DAT_BITMAP) && (dat->type != DAT_RLE_SPRITE) &&
137 	  (dat->type != DAT_C_SPRITE) && (dat->type != DAT_XC_SPRITE))
138 	 return FALSE;
139 
140       s = get_datafile_property(dat, DAT_NAME);
141 
142       if ((s[0]) && (uisdigit(s[strlen(s)-1])))
143 	 return TRUE;
144       else
145 	 return FALSE;
146    }
147 
148    return TRUE;
149 }
150 
151 
152 
153 /* checks whether a bitmap contains any data */
bitmap_is_empty(BITMAP * bmp)154 static int bitmap_is_empty(BITMAP *bmp)
155 {
156    int x, y;
157    int c = getpixel(bmp, 0, 0);
158 
159    for (y=0; y<bmp->h; y++)
160       for (x=0; x<bmp->w; x++)
161 	 if (getpixel(bmp, x, y) != c)
162 	    return FALSE;
163 
164    return TRUE;
165 }
166 
167 
168 
169 /* helper for grabbing images from a grid */
griddlit(DATAFILE ** parent,AL_CONST char * name,int c,int type,int skipempty,int autocrop,int depth,int x,int y,int w,int h)170 static void *griddlit(DATAFILE **parent, AL_CONST char *name, int c, int type, int skipempty, int autocrop, int depth, int x, int y, int w, int h)
171 {
172    DATAFILE *dat;
173    BITMAP *bmp;
174    void *v;
175    char buf[256];
176    RGB tmprgb = datedit_current_palette[0];
177    int tx = 0, ty = 0;
178 
179    if ((type == DAT_RLE_SPRITE) || (type == DAT_C_SPRITE) || (type == DAT_XC_SPRITE)) {
180       datedit_current_palette[0].r = 63;
181       datedit_current_palette[0].g = 0;
182       datedit_current_palette[0].b = 63;
183    }
184    select_palette(datedit_current_palette);
185 
186    bmp = create_bitmap_ex(depth, w, h);
187    clear_to_color(bmp, bmp->vtable->mask_color);
188    blit(grabber_graphic, bmp, x, y, 0, 0, w, h);
189 
190    unselect_palette();
191    datedit_current_palette[0] = tmprgb;
192 
193    if ((skipempty) && (bitmap_is_empty(bmp))) {
194       destroy_bitmap(bmp);
195       return NULL;
196    }
197 
198    if (autocrop)
199       bmp = crop_bitmap(bmp, &tx, &ty);
200 
201    if (type == DAT_RLE_SPRITE) {
202       v = get_rle_sprite(bmp);
203       destroy_bitmap(bmp);
204    }
205    else
206       v = bmp;
207 
208    sprintf(buf, "%s%03d", name, c);
209 
210    *parent = datedit_insert(*parent, &dat, buf, type, v, 0);
211 
212    sprintf(buf, "%d", x);
213    datedit_set_property(dat, DAT_XPOS, buf);
214 
215    sprintf(buf, "%d", y);
216    datedit_set_property(dat, DAT_YPOS, buf);
217 
218    sprintf(buf, "%d", w);
219    datedit_set_property(dat, DAT_XSIZ, buf);
220 
221    sprintf(buf, "%d", h);
222    datedit_set_property(dat, DAT_YSIZ, buf);
223 
224    if (tx || ty) {
225       sprintf(buf, "%d", tx);
226       datedit_set_property(dat, DAT_XCRP, buf);
227 
228       sprintf(buf, "%d", ty);
229       datedit_set_property(dat, DAT_YCRP, buf);
230    }
231 
232    datedit_set_property(dat, DAT_ORIG, grabber_graphic_origin);
233    datedit_set_property(dat, DAT_DATE, grabber_graphic_date);
234 
235    datedit_sort_properties(dat->prop);
236 
237    if (added_count < (int)(sizeof(added_item)/sizeof(added_item[0])))
238       added_item[added_count++] = v;
239 
240    return v;
241 }
242 
243 
244 
245 /* grabs images from a grid, using boxes of color #255 */
box_griddle(DATAFILE ** parent,AL_CONST char * name,int type,int skipempty,int autocrop,int depth)246 static void *box_griddle(DATAFILE **parent, AL_CONST char *name, int type, int skipempty, int autocrop, int depth)
247 {
248    void *ret = NULL;
249    void *item;
250    int x, y, w, h;
251    int c = 0;
252 
253    x = 0;
254    y = 0;
255 
256    datedit_find_character(grabber_graphic, &x, &y, &w, &h);
257 
258    while ((w > 0) && (h > 0)) {
259       item = griddlit(parent, name, c, type, skipempty, autocrop, depth, x+1, y+1, w, h);
260       if (item) {
261 	 c++;
262 	 if (!ret)
263 	    ret = item;
264       }
265 
266       x += w;
267       datedit_find_character(grabber_graphic, &x, &y, &w, &h);
268    }
269 
270    return ret;
271 }
272 
273 
274 
275 /* grabs images from a regular grid */
grid_griddle(DATAFILE ** parent,AL_CONST char * name,int type,int skipempty,int autocrop,int depth,int xgrid,int ygrid)276 static void *grid_griddle(DATAFILE **parent, AL_CONST char *name, int type, int skipempty, int autocrop, int depth, int xgrid, int ygrid)
277 {
278    void *ret = NULL;
279    void *item;
280    int x, y;
281    int c = 0;
282 
283    for (y=0; y+ygrid<=grabber_graphic->h; y+=ygrid) {
284       for (x=0; x+xgrid<=grabber_graphic->w; x+=xgrid) {
285 	 item = griddlit(parent, name, c, type, skipempty, autocrop, depth, x, y, xgrid, ygrid);
286 	 if (item) {
287 	    c++;
288 	    if (!ret)
289 	       ret = item;
290 	 }
291       }
292    }
293 
294    return ret;
295 }
296 
297 
298 
299 static char griddle_xgrid[8] = "32";
300 static char griddle_ygrid[8] = "32";
301 static char griddle_name[256] = "";
302 
303 
304 
305 /* dialog callback for retrieving the contents of the object type list */
typelist_getter(int index,int * list_size)306 static AL_CONST char *typelist_getter(int index, int *list_size)
307 {
308    static char *str[] =
309    {
310       "Bitmap",
311       "RLE Sprite",
312       "Compiled Sprite",
313       "Mode-X Compiled Sprite"
314    };
315 
316    if (index < 0) {
317       if (list_size)
318 	 *list_size = 4;
319       return NULL;
320    }
321 
322    return str[index];
323 }
324 
325 
326 
327 /* dialog callback for retrieving the contents of the color depth list */
depthlist_getter(int index,int * list_size)328 static AL_CONST char *depthlist_getter(int index, int *list_size)
329 {
330    static char *str[] =
331    {
332       "256 color palette",
333       "15 bit hicolor",
334       "16 bit hicolor",
335       "24 bit truecolor",
336       "32 bit truecolor"
337    };
338 
339    if (index < 0) {
340       if (list_size)
341 	 *list_size = 5;
342       return NULL;
343    }
344 
345    return str[index];
346 }
347 
348 
349 
350 static DIALOG griddle_dlg[] =
351 {
352    /* (dialog proc)     (x)   (y)   (w)   (h)   (fg)  (bg)  (key)    (flags)     (d1)           (d2)     (dp)                     (dp2) (dp3) */
353    { d_shadow_box_proc, 0,    0,    277,  305,  0,    0,    0,       0,          0,             0,       NULL,                    NULL, NULL  },
354    { d_ctext_proc,      138,  8,    0,    0,    0,    0,    0,       0,          0,             0,       "Grab from Grid",        NULL, NULL  },
355    { d_radio_proc,      16,   32,   121,  13,   0,    0,    0,       D_SELECTED, 0,             0,       "Use col #255",          NULL, NULL  },
356    { d_radio_proc,      16,   56,   121,  13,   0,    0,    0,       0,          0,             0,       "Regular grid",          NULL, NULL  },
357    { gg_text_proc,      160,  58,   0,    0,    0,    0,    0,       0,          0,             0,       "X-grid:",               NULL, NULL  },
358    { gg_edit_proc,      224,  58,   40,   8,    0,    0,    0,       0,          4,             0,       griddle_xgrid,           NULL, NULL  },
359    { gg_text_proc,      160,  80,   0,    0,    0,    0,    0,       0,          0,             0,       "Y-grid:",               NULL, NULL  },
360    { gg_edit_proc,      224,  82,   40,   8,    0,    0,    0,       0,          4,             0,       griddle_ygrid,           NULL, NULL  },
361    { d_check_proc,      16,   82,   123,  13,   0,    0,    0,       0,          0,             0,       "Skip empties:",         NULL, NULL  },
362    { d_check_proc,      16,   106,  91,   13,   0,    0,    0,       0,          0,             0,       "Autocrop:",             NULL, NULL  },
363    { d_text_proc,       16,   138,  0,    0,    0,    0,    0,       0,          0,             0,       "Name:",                 NULL, NULL  },
364    { d_edit_proc,       64,   138,  204,  8,    0,    0,    0,       0,          255,           0,       griddle_name,            NULL, NULL  },
365    { d_text_proc,       16,   160,  0,    0,    0,    0,    0,       0,          0,             0,       "Type:",                 NULL, NULL  },
366    { d_list_proc,       64,   160,  197,  36,   0,    0,    0,       0,          0,             0,       (void*)typelist_getter,  NULL, NULL  },
367    { d_text_proc,       16,   208,  0,    0,    0,    0,    0,       0,          0,             0,       "Cols:",                 NULL, NULL  },
368    { d_list_proc,       64,   208,  197,  44,   0,    0,    0,       0,          0,             0,       (void*)depthlist_getter, NULL, NULL  },
369    { d_button_proc,     50,   272,  81,   17,   0,    0,    13,      D_EXIT,     0,             0,       "OK",                    NULL, NULL  },
370    { d_button_proc,     146,  272,  81,   17,   0,    0,    27,      D_EXIT,     0,             0,       "Cancel",                NULL, NULL  },
371    { NULL,              0,    0,    0,    0,    0,    0,    0,       0,          0,             0,       NULL,                    NULL, NULL  }
372 };
373 
374 
375 #define GRIDDLE_DLG_BOXES        2
376 #define GRIDDLE_DLG_GRID         3
377 #define GRIDDLE_DLG_XGRID        5
378 #define GRIDDLE_DLG_YGRID        7
379 #define GRIDDLE_DLG_EMPTIES      8
380 #define GRIDDLE_DLG_AUTOCROP     9
381 #define GRIDDLE_DLG_NAME         11
382 #define GRIDDLE_DLG_TYPE         13
383 #define GRIDDLE_DLG_DEPTH        15
384 #define GRIDDLE_DLG_OK           16
385 #define GRIDDLE_DLG_CANCEL       17
386 
387 
388 
389 /* wrapper for d_text_proc, that greys out when invalid */
gg_text_proc(int msg,DIALOG * d,int c)390 static int gg_text_proc(int msg, DIALOG *d, int c)
391 {
392    if (msg == MSG_IDLE) {
393       int valid = (griddle_dlg[GRIDDLE_DLG_BOXES].flags & D_SELECTED) ? 0 : 1;
394       int enabled = (d->flags & D_DISABLED) ? 0 : 1;
395 
396       if (valid != enabled) {
397 	 if (valid)
398 	    d->flags &= ~D_DISABLED;
399 	 else
400 	    d->flags |= D_DISABLED;
401 
402 	 object_message(d, MSG_DRAW, 0);
403       }
404 
405       return D_O_K;
406    }
407    else
408       return d_text_proc(msg, d, c);
409 }
410 
411 
412 
413 /* wrapper for d_edit_proc, that greys out when invalid */
gg_edit_proc(int msg,DIALOG * d,int c)414 static int gg_edit_proc(int msg, DIALOG *d, int c)
415 {
416    if (msg == MSG_IDLE) {
417       int valid = (griddle_dlg[GRIDDLE_DLG_BOXES].flags & D_SELECTED) ? 0 : 1;
418       int enabled = (d->flags & D_DISABLED) ? 0 : 1;
419 
420       if (valid != enabled) {
421 	 if (valid)
422 	    d->flags &= ~D_DISABLED;
423 	 else
424 	    d->flags |= D_DISABLED;
425 
426 	 object_message(d, MSG_DRAW, 0);
427       }
428 
429       return D_O_K;
430    }
431    else
432       return d_edit_proc(msg, d, c);
433 }
434 
435 
436 
437 /* checks whether an object name matches the grid grab base name */
grid_name_matches(AL_CONST char * gn,AL_CONST char * n)438 static int grid_name_matches(AL_CONST char *gn, AL_CONST char *n)
439 {
440    AL_CONST char *s;
441 
442    if (strncmp(gn, n, strlen(gn)) != 0)
443       return FALSE;
444 
445    s = n + strlen(gn);
446    if (*s == 0)
447       return FALSE;
448 
449    while (*s) {
450       if (!uisdigit(*s))
451 	 return FALSE;
452       s++;
453    }
454 
455    return TRUE;
456 }
457 
458 
459 
460 /* handle the griddle command */
griddler(void)461 static int griddler(void)
462 {
463    DATAFILE *dat;
464    DATAFILE **parent;
465    void *selitem;
466    char *s;
467    int c;
468    int xgrid, ygrid;
469    int done, type, skipempty, autocrop;
470    int depth = 8;
471 
472    if (!grabber_graphic) {
473       alert("You must read in a bitmap file",
474 	    "before you can grab data from it",
475 	    NULL, "OK", NULL, 13, 0);
476       return D_O_K;
477    }
478 
479    grabber_get_selection_info(&dat, &parent);
480 
481    if (!dat) {
482       griddle_name[0] = 0;
483       depth = bitmap_color_depth(grabber_graphic);
484    }
485    else {
486       strcpy(griddle_name, get_datafile_property(dat, DAT_NAME));
487       s = griddle_name + strlen(griddle_name) - 1;
488       while ((s >= griddle_name) && (uisdigit(*s))) {
489 	 *s = 0;
490 	 s--;
491       }
492 
493       if (dat->type == DAT_BITMAP) {
494 	 griddle_dlg[GRIDDLE_DLG_TYPE].d1 = 0;
495 	 depth = bitmap_color_depth(dat->dat);
496       }
497       else if (dat->type == DAT_RLE_SPRITE) {
498 	 griddle_dlg[GRIDDLE_DLG_TYPE].d1 = 1;
499 	 depth = ((RLE_SPRITE *)dat->dat)->color_depth;
500       }
501       else if (dat->type == DAT_C_SPRITE) {
502 	 griddle_dlg[GRIDDLE_DLG_TYPE].d1 = 2;
503 	 depth = bitmap_color_depth(dat->dat);
504       }
505       else if (dat->type == DAT_XC_SPRITE) {
506 	 griddle_dlg[GRIDDLE_DLG_TYPE].d1 = 3;
507 	 depth = 8;
508       }
509    }
510 
511    if (depth == 8)
512       griddle_dlg[GRIDDLE_DLG_DEPTH].d1 = 0;
513    else if (depth == 15)
514       griddle_dlg[GRIDDLE_DLG_DEPTH].d1 = 1;
515    else if (depth == 16)
516       griddle_dlg[GRIDDLE_DLG_DEPTH].d1 = 2;
517    else if (depth == 24)
518       griddle_dlg[GRIDDLE_DLG_DEPTH].d1 = 3;
519    else if (depth == 32)
520       griddle_dlg[GRIDDLE_DLG_DEPTH].d1 = 4;
521 
522    centre_dialog(griddle_dlg);
523    set_dialog_color(griddle_dlg, gui_fg_color, gui_bg_color);
524 
525    if (do_dialog(griddle_dlg, GRIDDLE_DLG_NAME) == GRIDDLE_DLG_CANCEL)
526       return D_REDRAW;
527 
528    grabber_sel_palette(grabber_palette);
529 
530    do {
531       done = TRUE;
532 
533       for (c=0; (*parent)[c].type != DAT_END; c++) {
534 	 if (grid_name_matches(griddle_name, get_datafile_property((*parent)+c, DAT_NAME))) {
535 	    *parent = datedit_delete(*parent, c);
536 	    done = FALSE;
537 	    break;
538 	 }
539       }
540    } while (!done);
541 
542    switch (griddle_dlg[GRIDDLE_DLG_TYPE].d1) {
543 
544       case 0:
545       default:
546 	 type = DAT_BITMAP;
547 	 break;
548 
549       case 1:
550 	 type = DAT_RLE_SPRITE;
551 	 break;
552 
553       case 2:
554 	 type = DAT_C_SPRITE;
555 	 break;
556 
557       case 3:
558 	 type = DAT_XC_SPRITE;
559 	 break;
560    }
561 
562    switch (griddle_dlg[GRIDDLE_DLG_DEPTH].d1) {
563 
564       case 0:
565       default:
566 	 depth = 8;
567 	 break;
568 
569       case 1:
570 	 depth = 15;
571 	 break;
572 
573       case 2:
574 	 depth = 16;
575 	 break;
576 
577       case 3:
578 	 depth = 24;
579 	 break;
580 
581       case 4:
582 	 depth = 32;
583 	 break;
584    }
585 
586    skipempty = griddle_dlg[GRIDDLE_DLG_EMPTIES].flags & D_SELECTED;
587    autocrop = griddle_dlg[GRIDDLE_DLG_AUTOCROP].flags & D_SELECTED;
588 
589    added_count = 0;
590 
591    if (griddle_dlg[GRIDDLE_DLG_BOXES].flags & D_SELECTED)
592       selitem = box_griddle(parent, griddle_name, type, skipempty, autocrop, depth);
593    else {
594       xgrid = CLAMP(1, atoi(griddle_xgrid), 0xFFFF);
595       ygrid = CLAMP(1, atoi(griddle_ygrid), 0xFFFF);
596       selitem = grid_griddle(parent, griddle_name, type, skipempty, autocrop, depth, xgrid, ygrid);
597    }
598 
599    datedit_sort_datafile(*parent);
600    grabber_rebuild_list(selitem, TRUE);
601    grabber_select_property(DAT_NAME);
602 
603    for (c=0; c<added_count; c++)
604       grabber_set_selection(added_item[c]);
605 
606    if (selitem) {
607       grabber_sel_palette(grabber_palette);
608       grabber_modified(TRUE);
609    }
610    else
611       alert("No grid found - nothing grabbed!", NULL, NULL, "Hmm...", NULL, 13, 0);
612 
613    set_config_string("grabber", "griddle_xgrid", griddle_xgrid);
614    set_config_string("grabber", "griddle_ygrid", griddle_ygrid);
615 
616    if (griddle_dlg[GRIDDLE_DLG_BOXES].flags & D_SELECTED)
617       set_config_string("grabber", "griddle_mode", "boxes");
618    else
619       set_config_string("grabber", "griddle_mode", "grid");
620 
621    if (griddle_dlg[GRIDDLE_DLG_EMPTIES].flags & D_SELECTED)
622       set_config_string("grabber", "griddle_empties", "y");
623    else
624       set_config_string("grabber", "griddle_empties", "n");
625 
626    if (griddle_dlg[GRIDDLE_DLG_AUTOCROP].flags & D_SELECTED)
627       set_config_string("grabber", "griddle_autocrop", "y");
628    else
629       set_config_string("grabber", "griddle_autocrop", "n");
630 
631    set_config_int("grabber", "griddle_type", griddle_dlg[GRIDDLE_DLG_TYPE].d1);
632 
633    return D_REDRAW;
634 }
635 
636 
637 
638 /* worker function for cropping an image */
do_autocropper(DATAFILE * dat,int * param,int param2)639 static int do_autocropper(DATAFILE *dat, int *param, int param2)
640 {
641    BITMAP *bmp;
642    RLE_SPRITE *spr;
643    char buf[256];
644    int tx, ty;
645 
646    if ((dat->type != DAT_BITMAP) && (dat->type != DAT_RLE_SPRITE) &&
647        (dat->type != DAT_C_SPRITE) && (dat->type != DAT_XC_SPRITE)) {
648       (*param)++;
649       return D_O_K;
650    }
651 
652    if (dat->type == DAT_RLE_SPRITE) {
653       spr = (RLE_SPRITE *)dat->dat;
654       bmp = create_bitmap_ex(spr->color_depth, spr->w, spr->h);
655       clear_to_color(bmp, bmp->vtable->mask_color);
656       draw_rle_sprite(bmp, spr, 0, 0);
657       destroy_rle_sprite(spr);
658       bmp = crop_bitmap(bmp, &tx, &ty);
659       dat->dat = get_rle_sprite(bmp);
660       destroy_bitmap(bmp);
661    }
662    else
663       dat->dat = crop_bitmap((BITMAP *)dat->dat, &tx, &ty);
664 
665    if (tx || ty) {
666       sprintf(buf, "%d", tx);
667       datedit_set_property(dat, DAT_XCRP, buf);
668 
669       sprintf(buf, "%d", ty);
670       datedit_set_property(dat, DAT_YCRP, buf);
671    }
672 
673    grabber_modified(TRUE);
674 
675    return D_REDRAW;
676 }
677 
678 
679 
680 /* checks whether our autocrop command is allowed at the moment */
autocrop_query(int popup)681 static int autocrop_query(int popup)
682 {
683    int n, p;
684 
685    if (popup) {
686       p = 0;
687       grabber_foreach_selection(do_bitmap_check, &n, &p, 0);
688       return (p > 0);
689    }
690 
691    return TRUE;
692 }
693 
694 
695 
696 /* menu hook for the autocrop command */
autocrop(void)697 static int autocrop(void)
698 {
699    char buf[80];
700    int ret, n;
701    int p = 0;
702 
703    ret = grabber_foreach_selection(do_autocropper, &n, &p, 0);
704 
705    if (n <= 0) {
706       alert ("Nothing to crop!", NULL, NULL, "OK", NULL, 13, 0);
707    }
708    else if (p > 0) {
709       sprintf(buf, "%d non-bitmap object%s ignored", p, (p==1) ? " was" : "s were");
710       alert(buf, NULL, NULL, "OK", NULL, 13, 0);
711    }
712 
713    return ret;
714 }
715 
716 
717 
718 /* initialisation code for the grab-from-grid plugin */
datgrid_init(void)719 void datgrid_init(void)
720 {
721    int i;
722 
723    if (screen) {
724       if (SCREEN_H < 400) {
725 	 griddle_dlg[0].h = griddle_dlg[0].h * 2/3;
726 	 for (i=1; griddle_dlg[i].proc; i++) {
727 	    griddle_dlg[i].y = griddle_dlg[i].y * 2/3;
728 	    if (griddle_dlg[i].h > 32)
729 	       griddle_dlg[i].h -= 8;
730 	 }
731       }
732    }
733 
734    sprintf(griddle_xgrid, "%d", get_config_int("grabber", "griddle_xgrid", 32));
735    sprintf(griddle_ygrid, "%d", get_config_int("grabber", "griddle_ygrid", 32));
736 
737    if (stricmp(get_config_string("grabber", "griddle_mode", ""), "grid") == 0) {
738       griddle_dlg[GRIDDLE_DLG_BOXES].flags &= ~D_SELECTED;
739       griddle_dlg[GRIDDLE_DLG_GRID].flags |= D_SELECTED;
740    }
741    else {
742       griddle_dlg[GRIDDLE_DLG_BOXES].flags |= D_SELECTED;
743       griddle_dlg[GRIDDLE_DLG_GRID].flags &= ~D_SELECTED;
744    }
745 
746    if (strpbrk(get_config_string("grabber", "griddle_empties", ""), "yY1"))
747       griddle_dlg[GRIDDLE_DLG_EMPTIES].flags |= D_SELECTED;
748    else
749       griddle_dlg[GRIDDLE_DLG_EMPTIES].flags &= ~D_SELECTED;
750 
751    if (strpbrk(get_config_string("grabber", "griddle_autocrop", ""), "yY1"))
752       griddle_dlg[GRIDDLE_DLG_AUTOCROP].flags |= D_SELECTED;
753    else
754       griddle_dlg[GRIDDLE_DLG_AUTOCROP].flags &= ~D_SELECTED;
755 
756    griddle_dlg[GRIDDLE_DLG_TYPE].d1 = get_config_int("grabber", "griddle_type", 0);
757 }
758 
759 
760 
761 /* hook ourselves into the grabber menu system */
762 static MENU griddler_menu =
763 {
764    "Grab from Grid",
765    griddler,
766    NULL,
767    0,
768    NULL
769 };
770 
771 
772 
773 DATEDIT_MENU_INFO datgrid_griddler_menu =
774 {
775    &griddler_menu,
776    griddler_query,
777    DATEDIT_MENU_FILE | DATEDIT_MENU_POPUP,
778    0,
779    "XPOS;YPOS;XSIZ;YSIZ"
780 };
781 
782 
783 
784 static MENU autocrop_menu =
785 {
786    "Autocrop",
787    autocrop,
788    NULL,
789    0,
790    NULL
791 };
792 
793 
794 
795 DATEDIT_MENU_INFO datgrid_autocrop_menu =
796 {
797    &autocrop_menu,
798    autocrop_query,
799    DATEDIT_MENU_OBJECT | DATEDIT_MENU_POPUP,
800    0,
801    "XCRP;YCRP"
802 };
803 
804