]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/bmtable.c
ditch FileInfo -> use boost.filesystem
[lyx.git] / src / frontends / xforms / bmtable.c
1 /**
2  * \file bmtable.c
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Alejandro Aguilar Sierra
7  *
8  * Full author contact details are available in file CREDITS
9  */
10
11 #include <config.h>
12
13 #include <stdlib.h>
14 #include "bmtable.h"
15 #include "lyx_xpm.h"
16
17 #if defined(__cplusplus)
18 extern "C"
19 {
20 #endif
21
22 typedef struct   {
23         int nx, ny;     /**< Dimensions of the table */
24         int dx, dy;     /**< Size of each item */
25         int bx, by;      /**< Bitmap's position */
26         int bw, bh;      /**< Bitmap dimensions */
27         unsigned char const * bdata;     /**< Bitmap data */
28         int maxi;        /**< Number of items */
29         int i;   /**< Current position */
30         int mousebut; /**< mouse button pushed */
31         Pixmap pix;      /**< Pixmap from data (temporal) */
32 } BMTABLE_SPEC;
33
34
35 int handle_bitmaptable(FL_OBJECT * ob, int event, FL_Coord mx,
36                        FL_Coord my, int key, void * xev);
37
38
39 FL_OBJECT * fl_create_bmtable(int type, FL_Coord x, FL_Coord y,
40                               FL_Coord w, FL_Coord h, char const * label)
41 {
42         FL_OBJECT * ob;
43
44         ob = fl_make_object(FL_BMTABLE, type, x, y, w, h, label, handle_bitmaptable);
45         ob->boxtype = FL_BMTABLE_BOXTYPE;
46         ob->spec = fl_calloc(1, sizeof(BMTABLE_SPEC));
47         ((BMTABLE_SPEC *)ob->spec)->pix = 0;
48         ((BMTABLE_SPEC *)ob->spec)->bdata = 0;
49         ((BMTABLE_SPEC *)ob->spec)->mousebut = -1;
50         return ob;
51 }
52
53
54 FL_OBJECT *fl_add_bmtable(int type, FL_Coord x, FL_Coord y,
55                           FL_Coord w, FL_Coord h, char const *label)
56 {
57         FL_OBJECT *ob;
58
59         ob = fl_create_bmtable(type, x, y, w, h, label);
60         fl_add_object(fl_current_form, ob);
61
62         return ob;
63 }
64
65
66 static void draw_bitmaptable(FL_OBJECT *ob)
67 {
68         int i, j, lx;
69         FL_Coord mx, my;
70         FL_Coord xx, yy, ww, hh;
71         BMTABLE_SPEC * sp = (BMTABLE_SPEC *)ob->spec;
72         GC gc = fl_state[fl_get_vclass()].gc[0];
73         if (!sp) return;
74
75         /* draw the bounding box first */
76         lx = sp->maxi % sp->nx;
77         fl_drw_box(ob->boxtype, ob->x, ob->y, ob->w, ob->h, ob->col1, ob->bw);
78         if (lx) {
79                 i = FL_abs(ob->bw);
80                 xx = ob->x + sp->dx * lx + i;
81                 yy = ob->y + (sp->ny - 1) * sp->dy + i;
82                 ww = ob->x + ob->w - xx - i;
83                 hh = ob->y + ob->h - yy - i;
84                 fl_drw_frame(FL_DOWN_FRAME, xx, yy, ww, hh, ob->col1, ob->bw);
85                 fl_rectf(xx, yy, ww + i, hh + i, ob->col1);
86         }
87
88         /* draw the background bitmap */
89         if (sp->bdata)  {
90                 if (!sp->pix) {
91                         sp->pix = XCreatePixmapFromBitmapData(fl_get_display(), fl_winget(),
92                                                               (char*)sp->bdata,
93                                                               sp->bw, sp->bh,
94                                                               fl_get_flcolor(ob->lcol), fl_get_flcolor(ob->col1),
95                                                               /*DefaultDepth(fl_get_display(), DefaultScreen(fl_get_display()))*/ fl_state[fl_get_vclass()].depth);
96                         XFlush(fl_get_display());
97                 }
98         }
99         if (sp->pix) {
100                 /* Adjust position */
101                 if (sp->bx < FL_abs(ob->bw) + 1) {
102                         xx = FL_abs(ob->bw) - sp->bx + 1;
103                         mx = ob->x + FL_abs(ob->bw) + 1;
104                 } else  {
105                         xx = 0;
106                         mx = ob->x + sp->bx;
107                 }
108                 if (sp->by < FL_abs(ob->bw) + 1)  {
109                         yy = FL_abs(ob->bw) - sp->by + 1;
110                         my = ob->y + FL_abs(ob->bw) + 1;
111                 } else   {
112                         yy = 0;
113                         my = ob->y + sp->by;
114                 }
115                 ww = (mx + sp->bw < ob->x + ob->w - FL_abs(ob->bw)) ?
116                         sp->bw: ob->x + ob->w - FL_abs(ob->bw) - mx;
117                 hh = (my + sp->bh < ob->y + ob->h - FL_abs(ob->bw)) ?
118                         sp->bh: ob->y + ob->h - FL_abs(ob->bw) - my;
119
120                 i = FL_abs(ob->bw);
121                 j = hh - ((lx) ? sp->dy+2*i: 0);
122                 XCopyArea(fl_get_display(), sp->pix, fl_winget(), gc, xx, yy, ww, j, mx, my);
123                 XFlush(fl_get_display());
124                 if (lx) {
125                         XCopyArea(fl_get_display(), sp->pix, fl_winget(), gc, xx,
126                                   yy+j, lx*sp->dx-2*i, hh-j, mx, my+j);
127                         XFlush(fl_get_display());
128                 }
129         }
130
131
132         /* draw the grid if type > FLAT */
133         if (ob->type > FL_BMTABLE_FLAT)  {
134                 mx = ob->x + ob->w;
135                 my = ob->y + ob->h;
136                 ww = ob->w;
137                 for (yy= ob->y; yy<= my; yy+= sp->dy) {
138                         if (ob->boxtype!= FL_FLAT_BOX && (yy == ob->y || yy>my-sp->dy))
139                                 continue;
140                         if (lx>0 && yy>= my-sp->dy - sp->dy/2)
141                                 ww = lx*sp->dx;
142                         fl_diagline(ob->x, yy, ww, 1, FL_BOTTOM_BCOL);
143                         fl_diagline(ob->x, yy+1, ww-2, 1, FL_TOP_BCOL);
144                 }
145                 hh = ob->h;
146                 for (xx= ob->x; xx<= mx; xx+= sp->dx)  {
147                         if (ob->boxtype!= FL_FLAT_BOX && (xx == ob->x || xx>mx-sp->dx))
148                                 continue;
149                         if (lx>0 && xx>= ob->x + lx * sp->dx)
150                                 hh = (sp->ny - 1) * sp->dy;
151                         fl_diagline(xx, ob->y, 1, hh, FL_RIGHT_BCOL);
152                         fl_diagline(xx+1, ob->y + 1, 1, hh - 2, FL_LEFT_BCOL);
153                 }
154         }
155
156         /* Simulate a pushed button */
157         if (ob->pushed && 0 <= sp->i && sp->i < sp->maxi)  {
158                 i = sp->i % sp->nx;
159                 j = sp->i/sp->nx;
160                 ww = sp->dx-2*FL_abs(ob->bw);
161                 hh = sp->dy-2*FL_abs(ob->bw);
162                 xx = ob->x + sp->dx*i + FL_abs(ob->bw);
163                 yy = ob->y + sp->dy*j + FL_abs(ob->bw);
164                 fl_drw_frame(FL_DOWN_FRAME, xx, yy, ww, hh, ob->col1, ob->bw);
165         }
166 }
167
168
169 int handle_bitmaptable(FL_OBJECT * ob, int event, FL_Coord mx,
170                        FL_Coord my, int key, void * xev)
171 {
172         /* Silence warning about unused parameter */
173         (void) xev;
174
175         int i, j;
176         BMTABLE_SPEC * sp = (BMTABLE_SPEC *)ob->spec;
177
178         switch (event)  {
179         case FL_DRAW:
180                 draw_bitmaptable(ob);
181                 break;
182         case FL_MOUSE:
183                 if (!ob->belowmouse) {    /* This never happens. Why? */
184                         sp->i = -1;
185                         fl_redraw_object(ob);
186                         break;
187                 }
188                 i = (mx - ob->x)/sp->dx;  j = (my - ob->y)/sp->dy;
189                 if (i>= 0 && i< sp->nx && j>= 0 && j< sp->ny)   {
190                         i += j*sp->nx;
191                         if (i >= sp->maxi) i = -1;
192                         if (sp->i !=  i)  {
193                                 sp->i = i;
194                                 fl_redraw_object(ob);
195                         }
196                 }
197                 break;
198         case FL_PUSH:
199                 sp->mousebut = key;
200                 i = (mx - ob->x)/sp->dx + ((my - ob->y)/sp->dy)*sp->nx;
201                 if (0 <= i && i < sp->maxi)  {
202                         sp->i =  i;
203                         fl_redraw_object(ob);
204                 } else
205                         sp->i =  -1;
206                 break;
207         case FL_RELEASE:
208                 fl_redraw_object(ob);
209                 return 1;
210         case FL_FREEMEM:
211                 if (sp->pix) {
212                         XFreePixmap(fl_get_display(), sp->pix);
213                         XFlush(fl_get_display());
214                 }
215                 fl_free(((BMTABLE_SPEC*)ob->spec));
216                 break;
217         }
218         return 0;
219 }
220
221
222 /*
223  * The table has nx columns of dx width each and ny rows of dy height each.
224  * Initially the position of the firts item is supposed to be the same that
225  * the object position (x, y), and the number of items is supposed to be
226  * exactly nx*ny.
227  *
228  * The user could change these later. See below.
229  */
230 void fl_set_bmtable_data(FL_OBJECT * ob, int nx, int ny, int bw, int bh,
231                          unsigned char const * bdata)
232 {
233         BMTABLE_SPEC * sp = (BMTABLE_SPEC *)ob->spec;
234         if (sp) {
235                 sp->nx = nx;
236                 sp->ny = ny;
237                 sp->bx = FL_abs(ob->bw);
238                 sp->by = FL_abs(ob->bw);
239                 sp->dx = ob->w/nx;
240                 sp->dy = ob->h/ny;
241                 sp->i = -1;
242                 sp->maxi = sp->nx * sp->ny;
243                 sp->bw = bw;
244                 sp->bh = bh;
245                 sp->bdata = bdata;
246         }
247 }
248
249
250 void fl_set_bmtable_pixmap_data(FL_OBJECT * ob, int nx, int ny,
251                                 char ** pdata)
252 {
253         BMTABLE_SPEC * sp = (BMTABLE_SPEC *)ob->spec;
254         if (sp) {
255                 Pixmap dummy_shapemask = 0;
256                 XpmAttributes dumb_attributes;
257                 sp->nx = nx;
258                 sp->ny = ny;
259                 sp->bx = FL_abs(ob->bw);
260                 sp->by = FL_abs(ob->bw);
261                 sp->dx = ob->w/nx;
262                 sp->dy = ob->h/ny;
263                 sp->i = -1;
264                 sp->maxi = sp->nx * sp->ny;
265                 sp->bdata = 0;
266                 dumb_attributes.colormap = fl_state[fl_get_vclass()].colormap;
267                 dumb_attributes.closeness = 30000;
268                 dumb_attributes.valuemask = XpmColormap | XpmCloseness;
269                 if (XCreatePixmapFromData(fl_get_display(), fl_winget(), pdata,
270                                           &(sp->pix), &dummy_shapemask,
271                                           &dumb_attributes) == XpmSuccess) {
272                         sp->bw = dumb_attributes.width;
273                         sp->bh = dumb_attributes.height;
274                         XpmFreeAttributes(&dumb_attributes);
275                         if (dummy_shapemask) {
276                                 XFreePixmap(fl_get_display(), dummy_shapemask);
277                         }
278                 }
279         }
280 }
281
282
283 /*
284  *  This function works only for X11R6 or later
285  */
286 #if XlibSpecificationRelease > 5
287
288 void fl_set_bmtable_file(FL_OBJECT * ob, int nx, int ny, char const * filename)
289 {
290         int xh;
291         int yh;
292         unsigned int bw;
293         unsigned int bh;
294         unsigned char * bdata;
295
296         if (XReadBitmapFileData(filename, &bw, &bh,
297                                 &bdata, &xh, &yh) == BitmapSuccess)
298                 fl_set_bmtable_data(ob, nx, ny, bw, bh, bdata);
299         XFlush(fl_get_display());
300 }
301
302 #else
303
304 void fl_set_bmtable_file(FL_OBJECT * ob, int nx, int ny, char const * filename)
305 {
306         fprintf(stderr, "Set bmtable file: Sorry, I need X11 release 6 to do "
307                 "work!\n");
308 }
309
310 #endif
311
312
313
314 void fl_set_bmtable_pixmap_file(FL_OBJECT *ob, int nx, int ny, char const *filename)
315 {
316         /* extern Colormap color_map; */
317         BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;
318         if (sp) {
319                 Pixmap dummy_shapemask = 0;
320                 XpmAttributes dumb_attributes;
321                 XpmColorSymbol xpm_col;
322                 sp->nx = nx;
323                 sp->ny = ny;
324                 sp->bx = FL_abs(ob->bw);
325                 sp->by = FL_abs(ob->bw);
326                 sp->dx = ob->w/nx;
327                 sp->dy = ob->h/ny;
328                 sp->i = -1;
329                 sp->maxi = sp->nx * sp->ny;
330                 sp->bdata = 0;
331
332                 xpm_col.name = NULL;
333                 xpm_col.value = "None";
334                 xpm_col.pixel = fl_get_flcolor(ob->col1);
335                 dumb_attributes.colormap = fl_state[fl_get_vclass()].colormap;
336                 dumb_attributes.numsymbols = 1;
337                 dumb_attributes.colorsymbols = &xpm_col;
338                 dumb_attributes.closeness = 30000;
339                 dumb_attributes.valuemask = XpmColormap | XpmCloseness | XpmColorSymbols;
340
341                 if (XReadPixmapFile(fl_get_display(), fl_winget(), (char *)filename,
342                                     &(sp->pix), &dummy_shapemask,
343                                     &dumb_attributes) == XpmSuccess) {
344                         sp->bw = dumb_attributes.width;
345                         sp->bh = dumb_attributes.height;
346                         XpmFreeAttributes(&dumb_attributes);
347                         if (dummy_shapemask) {
348                                 XFreePixmap(fl_get_display(), dummy_shapemask);
349                         }
350                 }
351                 /* XFlush(fl_get_display()); */
352         }
353 }
354
355
356 /*
357  * This function allows to adjust the position of the first item and its
358  * size (dx, dy). The input values are incremental, not absolute.
359  */
360 void fl_set_bmtable_adjust(FL_OBJECT *ob, int px, int py, int dx, int dy)
361 {
362         BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;
363         if (sp) {
364                 sp->bx += px;
365                 sp->by += py;
366                 sp->dx += dx;
367                 sp->dy += dy;
368         }
369 }
370
371 /*
372  * This function returns the table's selected position.
373  */
374 int fl_get_bmtable(FL_OBJECT *ob)
375 {
376         if ((BMTABLE_SPEC *)ob->spec)
377                 return  ((BMTABLE_SPEC *)ob->spec)->i;
378         else
379                 return 0;
380 }
381
382
383 /*
384  * You can change the max number of items if you want.
385  */
386 void fl_set_bmtable_maxitems(FL_OBJECT * ob, int i)
387 {
388         if (i > 0 && (BMTABLE_SPEC *)ob->spec)
389                 ((BMTABLE_SPEC *)ob->spec)->maxi = i;
390 }
391
392
393 int fl_get_bmtable_maxitems(FL_OBJECT * ob)
394 {
395         if ((BMTABLE_SPEC *)ob->spec)
396                 return  ((BMTABLE_SPEC *)ob->spec)->maxi;
397         else
398                 return 0;
399 }
400
401
402 void fl_replace_bmtable_item(FL_OBJECT * ob, int id, int cw, int ch, char * data)
403 {
404         /* Silence warnings about unused parameters */
405         (void) ob;
406         (void) id;
407         (void) cw;
408         (void) ch;
409         (void) data;
410
411         fprintf(stderr, "Replace bmtable item: Sorry, not yet implemented!\n");
412 }
413
414
415 void fl_get_bmtable_item(FL_OBJECT * ob, int id, int * cw, int * ch, char * data)
416 {
417         /* Silence warnings about unused parameters */
418         (void) ob;
419         (void) id;
420         (void) cw;
421         (void) ch;
422         (void) data;
423
424         fprintf(stderr, "Get bmtable item: Sorry, not yet implemented!\n");
425 }
426
427 void fl_set_bmtable(FL_OBJECT * ob, int pushed, int pos)
428 {
429         if ((BMTABLE_SPEC *)ob->spec)
430                 ((BMTABLE_SPEC *)ob->spec)->i = (pushed) ? pos: -1;
431 }
432
433
434 int fl_get_bmtable_numb(FL_OBJECT *ob)
435 {
436         if ((BMTABLE_SPEC *)ob->spec)
437                 return ((BMTABLE_SPEC *)ob->spec)->mousebut;
438         else
439                 return 0;
440 }
441
442
443 Pixmap fl_get_bmtable_pixmap(FL_OBJECT * ob)
444 {
445         if ((BMTABLE_SPEC *)ob->spec)
446                 return ((BMTABLE_SPEC *)ob->spec)->pix;
447         else
448                 return 0;
449 }
450
451
452 void fl_draw_bmtable_item(FL_OBJECT * ob, int i, Drawable d, int xx, int yy)
453 {
454         int x;
455         int y;
456         int w;
457         int h;
458         GC gc = fl_state[fl_get_vclass()].gc[0];
459         BMTABLE_SPEC * sp = (BMTABLE_SPEC *)ob->spec;
460
461         if (sp && sp->pix) {
462                 x = (i % sp->nx)*sp->dx + FL_abs(ob->bw);
463                 y = (i/sp->nx)*sp->dy + FL_abs(ob->bw);
464                 w = sp->dx-2*FL_abs(ob->bw);
465                 h = sp->dy-2*FL_abs(ob->bw);
466                 XCopyArea(fl_get_display(), sp->pix, d, gc, x, y, w, h, xx, yy);
467                 XFlush(fl_get_display());
468         }
469 }
470
471 /* Free the current bitmap and pixmap in preparation for installing a new one */
472 void fl_free_bmtable_bitmap(FL_OBJECT * ob)
473 {
474         BMTABLE_SPEC * sp = (BMTABLE_SPEC *)ob->spec;
475
476         /* dump the temporary pixmap */
477         if (sp && sp->pix) {
478                 XFreePixmap(fl_get_display(), sp->pix);
479                 XFlush(fl_get_display());
480                 sp->pix = 0;
481         }
482
483         /* and free the space taken by bdata etc. */
484         if (sp && sp->bdata) {
485                 fl_free((void*)sp->bdata);
486                 sp->bdata = 0;
487         }
488 }
489
490 /* Free the current pixmap in preparation for installing a new one */
491 /* This is needed when using data instead of files to set bitmaps */
492 void fl_free_bmtable_pixmap(FL_OBJECT *ob)
493 {
494         BMTABLE_SPEC * sp = (BMTABLE_SPEC *)ob->spec;
495
496         /* dump the temporary pixmap */
497         if (sp && sp->pix) {
498                 XFreePixmap(fl_get_display(), sp->pix);
499                 XFlush(fl_get_display());
500                 sp->pix = 0;
501         }
502 }
503
504 #if defined(__cplusplus)
505 }
506 #endif