]> git.lyx.org Git - lyx.git/blob - src/bmtable.C
merge from the string-switch branch and ready for a prelease.
[lyx.git] / src / bmtable.C
1 /*
2  *  File:        bmtable.c
3  *  Purpose:     Implementation of the XForms object bmtable. 
4  *  Author:      Alejandro Aguilar Sierra <asierra@servidor.unam.mx> 
5  *  Created:     November 1995
6  *  Description: A bitmap table uses a single bitmap to simulate a 2d array 
7  *               of bitmap buttons. It can be used to build bitmap menus.
8  *               
9  *  Copyright 1995,1996 Alejandro Aguilar Sierra 
10  *
11  *  You are free to use and modify this code under the terms of
12  *  the GNU General Public Licence version 2 or later. 
13  *  
14  */ 
15
16 #include <config.h>
17
18 #include <cstdlib>
19 #include "bmtable.h"
20 #include XPM_H_LOCATION
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    char* 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 static 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         if (!sp) return;
73         GC gc = fl_state[fl_get_vclass()].gc[0];
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_display, fl_winget(), 
92                                         sp->bdata, sp->bw, sp->bh,
93                                         fl_get_flcolor(ob->lcol), fl_get_flcolor(ob->col1),
94                                         DefaultDepth(fl_display, DefaultScreen(fl_display)));
95                         XFlush(fl_display);
96                 }
97         }
98         if (sp->pix) {
99                 /* Adjust position */ 
100                 if (sp->bx < FL_abs(ob->bw) + 1) {
101                         xx = FL_abs(ob->bw) - sp->bx + 1;
102                         mx = ob->x + FL_abs(ob->bw) + 1;
103                 } else  {
104                         xx =0;
105                         mx = ob->x + sp->bx;
106                 }
107                 if (sp->by < FL_abs(ob->bw) + 1)  {      
108                         yy = FL_abs(ob->bw) - sp->by + 1;
109                         my = ob->y + FL_abs(ob->bw) + 1;
110                 } else   {
111                         yy =0;
112                         my = ob->y + sp->by;
113                 }                 
114                 ww = (mx + sp->bw < ob->x + ob->w - FL_abs(ob->bw)) ? 
115                         sp->bw: ob->x + ob->w - FL_abs(ob->bw) - mx;
116                 hh = (my + sp->bh < ob->y + ob->h - FL_abs(ob->bw)) ?
117                         sp->bh: ob->y + ob->h - FL_abs(ob->bw) - my; 
118       
119                 i = FL_abs(ob->bw);
120                 j = hh - ((lx) ? sp->dy+2*i: 0);
121                 XCopyArea(fl_display, sp->pix, fl_winget(), gc, xx, yy, ww, j, mx, my);
122                 XFlush(fl_display);
123                 if (lx) {
124                         XCopyArea(fl_display, sp->pix, fl_winget(), gc, xx,
125                                           yy+j, lx*sp->dx-2*i, hh-j, mx, my+j);
126                         XFlush(fl_display);
127                 }
128         }
129    
130    
131         /* draw the grid if type > FLAT */
132         if (ob->type > FL_BMTABLE_FLAT)  {
133                 mx = ob->x + ob->w; 
134                 my = ob->y + ob->h; 
135                 ww = ob->w; 
136                 for (yy=ob->y; yy<=my; yy+=sp->dy) {
137                         if (ob->boxtype!=FL_FLAT_BOX && (yy==ob->y || yy>my-sp->dy)) 
138                                 continue;
139                         if (lx>0 && yy>=my-sp->dy - sp->dy/2)
140                                 ww = lx*sp->dx;
141                         fl_diagline(ob->x, yy, ww, 1, FL_BOTTOM_BCOL); 
142                         fl_diagline(ob->x, yy+1, ww-2, 1, FL_TOP_BCOL); 
143                 }          
144                 hh = ob->h;
145                 for (xx=ob->x; xx<=mx; xx+=sp->dx)  {
146                         if (ob->boxtype!=FL_FLAT_BOX && (xx==ob->x || xx>mx-sp->dx))
147                                 continue;
148                         if (lx>0 && xx>=ob->x+lx*sp->dx)
149                                 hh = (sp->ny-1)*sp->dy;
150                         fl_diagline(xx, ob->y, 1, hh, FL_RIGHT_BCOL);
151                         fl_diagline(xx+1, ob->y+1, 1, hh-2, FL_LEFT_BCOL);
152                 }        
153         }  
154    
155         /* Simulate a pushed button */
156         if (ob->pushed && 0 <= sp->i && sp->i < sp->maxi)  {  
157                 i = sp->i % sp->nx;
158                 j = sp->i/sp->nx;
159                 ww = sp->dx-2*FL_abs(ob->bw);
160                 hh = sp->dy-2*FL_abs(ob->bw);
161                 xx = ob->x + sp->dx*i + FL_abs(ob->bw);
162                 yy = ob->y + sp->dy*j + FL_abs(ob->bw);
163                 fl_drw_frame(FL_DOWN_FRAME, xx, yy, ww, hh, ob->col1, ob->bw);
164         }
165 }
166
167
168 static int handle_bitmaptable(FL_OBJECT *ob, int event, FL_Coord mx, 
169                               FL_Coord my, int key, void */*xev*/)
170 {
171         int i, j;
172         BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;
173    
174         switch (event)  {
175     case FL_DRAW: 
176                 draw_bitmaptable(ob);
177                 break;
178     case FL_MOUSE:
179                 if (!ob->belowmouse) {    /* This never happens. Why? */
180                         sp->i = -1;
181                         fl_redraw_object(ob);
182                         break;
183                 }
184                 i = (mx - ob->x)/sp->dx;  j = (my - ob->y)/sp->dy;
185                 if (i>=0 && i< sp->nx && j>=0 && j< sp->ny)   {
186                         i += j*sp->nx;
187                         if (i >= sp->maxi) i = -1;
188                         if (sp->i !=  i)  {
189                                 sp->i = i;
190                                 fl_redraw_object(ob);
191                         }
192                 }
193                 break;        
194     case FL_PUSH:
195                 sp->mousebut = key;
196                 i = (mx - ob->x)/sp->dx + ((my - ob->y)/sp->dy)*sp->nx; 
197                 if (0 <= i && i < sp->maxi)  {
198                         sp->i =  i;
199                         fl_redraw_object(ob);
200                 } else
201                         sp->i =  -1; 
202                 break;
203     case FL_RELEASE:    
204                 fl_redraw_object(ob);
205                 return 1;
206     case FL_FREEMEM:
207             if (sp->pix) {
208                     XFreePixmap(fl_display, sp->pix);
209                     XFlush(fl_display);
210             }
211                 fl_free(((BMTABLE_SPEC*)ob->spec));      
212                 break;
213         }
214         return 0;
215 }
216
217
218 /*
219  * The table has nx columns of dx width each and ny rows of dy height each. 
220  * Initially the position of the firts item is supposed to be the same that
221  * the object position (x, y), and the number of items is supposed to be
222  * exactly nx*ny.
223  * 
224  * The user could change these later. See below.
225  */ 
226 void fl_set_bmtable_data(FL_OBJECT *ob, int nx, int ny, int bw, int bh, 
227                         char *bdata)
228 {
229    BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;
230    if (sp) {
231      sp->nx = nx;
232      sp->ny = ny; 
233      sp->bx = FL_abs(ob->bw);
234      sp->by = FL_abs(ob->bw);
235      sp->dx = ob->w/nx; 
236      sp->dy = ob->h/ny;
237      sp->i = -1;
238      sp->maxi = sp->nx * sp->ny;
239      sp->bw = bw;
240      sp->bh = bh;
241      sp->bdata = bdata;
242    }
243 }
244
245
246 void fl_set_bmtable_pixmap_data(FL_OBJECT *ob, int nx, int ny,
247                         char **pdata)
248 {
249         BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;
250         extern Colormap color_map;
251         if (sp) {
252                 sp->nx = nx;
253                 sp->ny = ny; 
254                 sp->bx = FL_abs(ob->bw);
255                 sp->by = FL_abs(ob->bw);
256                 sp->dx = ob->w/nx; 
257                 sp->dy = ob->h/ny;
258                 sp->i = -1;
259                 sp->maxi = sp->nx * sp->ny;
260                 sp->bdata = 0;
261                 Pixmap dummy_shapemask = 0;
262                 XpmAttributes dumb_attributes= {0};
263                 dumb_attributes.colormap = color_map;
264                 dumb_attributes.closeness = 30000;
265                 dumb_attributes.valuemask = XpmColormap | XpmCloseness;
266                 if (XCreatePixmapFromData(fl_display, fl_winget(), pdata,
267                                           &(sp->pix), &dummy_shapemask,
268                                           &dumb_attributes) == XpmSuccess) {
269                         sp->bw = dumb_attributes.width;
270                         sp->bh = dumb_attributes.height;
271                         XpmFreeAttributes(&dumb_attributes);
272                         if (dummy_shapemask) {
273                                 XFreePixmap(fl_display, dummy_shapemask);
274                         }
275                 }
276                 XFlush(fl_display);
277         }
278 }
279
280
281 /*
282  *  This function works only for X11R6 or later
283  */
284 #if XlibSpecificationRelease > 5 
285
286 void fl_set_bmtable_file(FL_OBJECT *ob, int nx, int ny, char const *filename)
287 {       
288    int bw, bh, xh, yh;
289    char *bdata;
290    
291    if(XReadBitmapFileData(filename, (unsigned int *) &bw, (unsigned int *) &bh,
292         (unsigned char **) &bdata, &xh, &yh)==BitmapSuccess)
293      fl_set_bmtable_data(ob, nx, ny, bw, bh, bdata);
294    XFlush(fl_display);
295 }
296
297 #else
298
299 void fl_set_bmtable_file(FL_OBJECT *, int, int, char const *) 
300 {
301   fprintf(stderr, "Set bmtable file: Sorry, I need X11 release 6 to do " 
302            "work!\n");
303 }
304
305 #endif
306
307
308
309 void fl_set_bmtable_pixmap_file(FL_OBJECT *ob, int nx, int ny, char const *filename)
310 {       
311         extern Colormap color_map;
312         BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;
313         if (sp) {
314                 sp->nx = nx;
315                 sp->ny = ny; 
316                 sp->bx = FL_abs(ob->bw);
317                 sp->by = FL_abs(ob->bw);
318                 sp->dx = ob->w/nx; 
319                 sp->dy = ob->h/ny;
320                 sp->i = -1;
321                 sp->maxi = sp->nx * sp->ny;
322                 sp->bdata = 0;
323
324                 Pixmap dummy_shapemask = 0;
325                 XpmAttributes dumb_attributes= {0};
326                 dumb_attributes.colormap = color_map;
327                 dumb_attributes.closeness = 30000;
328                 dumb_attributes.valuemask = XpmColormap | XpmCloseness;
329    
330                 if (XReadPixmapFile(fl_display, fl_winget(), (char *)filename,
331                                     &(sp->pix), &dummy_shapemask,
332                                     &dumb_attributes) == XpmSuccess) {
333                         sp->bw = dumb_attributes.width;
334                         sp->bh = dumb_attributes.height;
335                         XpmFreeAttributes(&dumb_attributes);
336                         if (dummy_shapemask) {
337                                 XFreePixmap(fl_display, dummy_shapemask);
338                         }
339                 }
340                 XFlush(fl_display);
341         }
342 }
343
344
345 /*
346  * This function allows to adjust the position of the first item and its
347  * size (dx, dy). The input values are incremental, not absolute.
348  */
349 void fl_set_bmtable_adjust(FL_OBJECT *ob, int px, int py, int dx, int dy)
350 {
351    BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;   
352    if (sp) {
353      sp->bx += px;
354      sp->by += py;                         
355      sp->dx += dx;
356      sp->dy += dy;
357    }
358 }
359
360 /* 
361  * This function returns the table's selected position.
362  */
363 int fl_get_bmtable(FL_OBJECT *ob)
364
365    if ((BMTABLE_SPEC *)ob->spec)
366      return  ((BMTABLE_SPEC *)ob->spec)->i;
367    else 
368      return 0;
369 }
370
371
372 /* 
373  * You can change the max number of items if you want.
374  */
375 void fl_set_bmtable_maxitems(FL_OBJECT *ob, int i)
376 {
377    if (i>0 && (BMTABLE_SPEC *)ob->spec)
378      ((BMTABLE_SPEC *)ob->spec)->maxi = i;
379 }   
380
381
382 int fl_get_bmtable_maxitems(FL_OBJECT *ob)
383 {
384    if ((BMTABLE_SPEC *)ob->spec)
385      return  ((BMTABLE_SPEC *)ob->spec)->maxi;
386    else
387      return 0;
388 }
389
390
391 void fl_replace_bmtable_item(FL_OBJECT */*ob*/, int /*id*/, int  /*cw*/, int /*ch*/, char */*data*/)
392 {
393    fprintf(stderr, "Replace bmtable item: Sorry, not yet implemented!\n");
394 }
395
396
397 void fl_get_bmtable_item(FL_OBJECT */*ob*/, int /*id*/, int */*cw*/, int */*ch*/, char */*data*/)
398 {
399    fprintf(stderr, "Get bmtable item: Sorry, not yet implemented!\n");
400 }  
401
402 void fl_set_bmtable(FL_OBJECT *ob, int pushed, int pos)
403 {
404    if ((BMTABLE_SPEC *)ob->spec)
405      ((BMTABLE_SPEC *)ob->spec)->i = (pushed) ? pos: -1;
406 }
407
408
409 int fl_get_bmtable_numb(FL_OBJECT *ob)
410 {
411    if ((BMTABLE_SPEC *)ob->spec)
412      return ((BMTABLE_SPEC *)ob->spec)->mousebut;
413    else
414      return 0;
415 }
416
417
418 Pixmap fl_get_bmtable_pixmap(FL_OBJECT *ob)
419 {
420    if ((BMTABLE_SPEC *)ob->spec)
421      return ((BMTABLE_SPEC *)ob->spec)->pix;
422    else
423      return 0;
424 }
425
426
427 void fl_draw_bmtable_item(FL_OBJECT *ob, int i, Drawable d, int xx, int yy)
428 {
429    int x, y, w, h;
430    GC gc = fl_state[fl_get_vclass()].gc[0];
431    BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;
432    
433    if (sp && sp->pix) {
434       x = (i % sp->nx)*sp->dx + FL_abs(ob->bw);
435       y = (i/sp->nx)*sp->dy + FL_abs(ob->bw);
436       w = sp->dx-2*FL_abs(ob->bw);
437       h = sp->dy-2*FL_abs(ob->bw);       
438       XCopyArea(fl_display, sp->pix, d, gc, x, y, w, h, xx, yy);
439       XFlush(fl_display);
440    }
441 }
442
443 /* Free the current bitmap and pixmap in preparation for installing a new one */
444 void fl_free_bmtable_bitmap(FL_OBJECT *ob)
445 {
446   BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;
447
448   /* dump the temporary pixmap */
449   if (sp && sp->pix) { 
450     XFreePixmap(fl_display, sp->pix);
451     XFlush(fl_display);
452     sp->pix = 0;
453   }
454
455   /* and free the space taken by bdata etc. */
456   if (sp && sp->bdata) {
457     fl_free(sp->bdata);
458     sp->bdata = 0;
459   }
460 }
461
462 /* Free the current pixmap in preparation for installing a new one */
463 /* This is needed when using data instead of files to set bitmaps  */
464 void fl_free_bmtable_pixmap(FL_OBJECT *ob)
465 {
466   BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;
467
468   /* dump the temporary pixmap */
469   if (sp && sp->pix) { 
470     XFreePixmap(fl_display, sp->pix);
471     XFlush(fl_display);
472     sp->pix = 0;
473   }
474 }
475
476