This commit was manufactured by cvs2svn to create tag
[lyx.git] / src / bmtable.C
blobffc064d2b3f7c6c18de8ac9782c42cad52f6977f
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  */ 
16 #include <config.h>
18 #include <cstdlib>
19 #include "bmtable.h"
20 #include XPM_H_LOCATION
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 * 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                  
35 extern "C" int handle_bitmaptable(FL_OBJECT *ob, int event, FL_Coord mx, 
36                                   FL_Coord my, int key, void *xev);
39 FL_OBJECT *fl_create_bmtable(int type, FL_Coord x, FL_Coord y, 
40                                  FL_Coord w, FL_Coord h, char const *label)
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;
54 FL_OBJECT *fl_add_bmtable(int type, FL_Coord x, FL_Coord y, 
55                               FL_Coord w, FL_Coord h, char const *label)
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;
66 static void draw_bitmaptable(FL_OBJECT *ob)
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                                         reinterpret_cast<char*>(sp->bdata),
93                                                                sp->bw, sp->bh,
94                                         fl_get_flcolor(ob->lcol), fl_get_flcolor(ob->col1),
95                                         DefaultDepth(fl_display, DefaultScreen(fl_display)));
96                         XFlush(fl_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_display, sp->pix, fl_winget(), gc, xx, yy, ww, j, mx, my);
123                 XFlush(fl_display);
124                 if (lx) {
125                         XCopyArea(fl_display, sp->pix, fl_winget(), gc, xx,
126                                           yy+j, lx*sp->dx-2*i, hh-j, mx, my+j);
127                         XFlush(fl_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         }
169 extern "C" int handle_bitmaptable(FL_OBJECT *ob, int event, FL_Coord mx, 
170                                   FL_Coord my, int key, void */*xev*/)
172         int i, j;
173         BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;
174    
175         switch (event)  {
176     case FL_DRAW: 
177                 draw_bitmaptable(ob);
178                 break;
179     case FL_MOUSE:
180                 if (!ob->belowmouse) {    /* This never happens. Why? */
181                         sp->i = -1;
182                         fl_redraw_object(ob);
183                         break;
184                 }
185                 i = (mx - ob->x)/sp->dx;  j = (my - ob->y)/sp->dy;
186                 if (i>=0 && i< sp->nx && j>=0 && j< sp->ny)   {
187                         i += j*sp->nx;
188                         if (i >= sp->maxi) i = -1;
189                         if (sp->i !=  i)  {
190                                 sp->i = i;
191                                 fl_redraw_object(ob);
192                         }
193                 }
194                 break;        
195     case FL_PUSH:
196                 sp->mousebut = key;
197                 i = (mx - ob->x)/sp->dx + ((my - ob->y)/sp->dy)*sp->nx; 
198                 if (0 <= i && i < sp->maxi)  {
199                         sp->i =  i;
200                         fl_redraw_object(ob);
201                 } else
202                         sp->i =  -1; 
203                 break;
204     case FL_RELEASE:    
205                 fl_redraw_object(ob);
206                 return 1;
207     case FL_FREEMEM:
208             if (sp->pix) {
209                     XFreePixmap(fl_display, sp->pix);
210                     XFlush(fl_display);
211             }
212                 fl_free(((BMTABLE_SPEC*)ob->spec));      
213                 break;
214         }
215         return 0;
220  * The table has nx columns of dx width each and ny rows of dy height each. 
221  * Initially the position of the firts item is supposed to be the same that
222  * the object position (x, y), and the number of items is supposed to be
223  * exactly nx*ny.
224  * 
225  * The user could change these later. See below.
226  */ 
227 void fl_set_bmtable_data(FL_OBJECT *ob, int nx, int ny, int bw, int bh, 
228                         unsigned char * bdata)
230    BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;
231    if (sp) {
232      sp->nx = nx;
233      sp->ny = ny; 
234      sp->bx = FL_abs(ob->bw);
235      sp->by = FL_abs(ob->bw);
236      sp->dx = ob->w/nx; 
237      sp->dy = ob->h/ny;
238      sp->i = -1;
239      sp->maxi = sp->nx * sp->ny;
240      sp->bw = bw;
241      sp->bh = bh;
242      sp->bdata = bdata;
243    }
247 void fl_set_bmtable_pixmap_data(FL_OBJECT *ob, int nx, int ny,
248                         char **pdata)
250         BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;
251         extern Colormap color_map;
252         if (sp) {
253                 sp->nx = nx;
254                 sp->ny = ny; 
255                 sp->bx = FL_abs(ob->bw);
256                 sp->by = FL_abs(ob->bw);
257                 sp->dx = ob->w/nx; 
258                 sp->dy = ob->h/ny;
259                 sp->i = -1;
260                 sp->maxi = sp->nx * sp->ny;
261                 sp->bdata = 0;
262                 Pixmap dummy_shapemask = 0;
263                 XpmAttributes dumb_attributes= {0};
264                 dumb_attributes.colormap = color_map;
265                 dumb_attributes.closeness = 30000;
266                 dumb_attributes.valuemask = XpmColormap | XpmCloseness;
267                 if (XCreatePixmapFromData(fl_display, fl_winget(), pdata,
268                                           &(sp->pix), &dummy_shapemask,
269                                           &dumb_attributes) == XpmSuccess) {
270                         sp->bw = dumb_attributes.width;
271                         sp->bh = dumb_attributes.height;
272                         XpmFreeAttributes(&dumb_attributes);
273                         if (dummy_shapemask) {
274                                 XFreePixmap(fl_display, dummy_shapemask);
275                         }
276                 }
277                 XFlush(fl_display);
278         }
283  *  This function works only for X11R6 or later
284  */
285 #if XlibSpecificationRelease > 5 
287 void fl_set_bmtable_file(FL_OBJECT *ob, int nx, int ny, char const *filename)
288 {       
289    int xh, yh;
290    unsigned int bw, bh;
291    unsigned char *bdata;
292    
293    if(XReadBitmapFileData(filename, &bw, &bh,
294                           &bdata, &xh, &yh)==BitmapSuccess)
295      fl_set_bmtable_data(ob, nx, ny, bw, bh, bdata);
296    XFlush(fl_display);
299 #else
301 void fl_set_bmtable_file(FL_OBJECT *, int, int, char const *) 
303   fprintf(stderr, "Set bmtable file: Sorry, I need X11 release 6 to do " 
304            "work!\n");
307 #endif
311 void fl_set_bmtable_pixmap_file(FL_OBJECT *ob, int nx, int ny, char const *filename)
312 {       
313         extern Colormap color_map;
314         BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;
315         if (sp) {
316                 sp->nx = nx;
317                 sp->ny = ny; 
318                 sp->bx = FL_abs(ob->bw);
319                 sp->by = FL_abs(ob->bw);
320                 sp->dx = ob->w/nx; 
321                 sp->dy = ob->h/ny;
322                 sp->i = -1;
323                 sp->maxi = sp->nx * sp->ny;
324                 sp->bdata = 0;
326                 Pixmap dummy_shapemask = 0;
327                 XpmAttributes dumb_attributes= {0};
328                 dumb_attributes.colormap = color_map;
329                 dumb_attributes.closeness = 30000;
330                 dumb_attributes.valuemask = XpmColormap | XpmCloseness;
331    
332                 if (XReadPixmapFile(fl_display, fl_winget(), (char *)filename,
333                                     &(sp->pix), &dummy_shapemask,
334                                     &dumb_attributes) == XpmSuccess) {
335                         sp->bw = dumb_attributes.width;
336                         sp->bh = dumb_attributes.height;
337                         XpmFreeAttributes(&dumb_attributes);
338                         if (dummy_shapemask) {
339                                 XFreePixmap(fl_display, dummy_shapemask);
340                         }
341                 }
342                 XFlush(fl_display);
343         }
348  * This function allows to adjust the position of the first item and its
349  * size (dx, dy). The input values are incremental, not absolute.
350  */
351 void fl_set_bmtable_adjust(FL_OBJECT *ob, int px, int py, int dx, int dy)
353    BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;   
354    if (sp) {
355      sp->bx += px;
356      sp->by += py;                         
357      sp->dx += dx;
358      sp->dy += dy;
359    }
362 /* 
363  * This function returns the table's selected position.
364  */
365 int fl_get_bmtable(FL_OBJECT *ob)
367    if ((BMTABLE_SPEC *)ob->spec)
368      return  ((BMTABLE_SPEC *)ob->spec)->i;
369    else 
370      return 0;
374 /* 
375  * You can change the max number of items if you want.
376  */
377 void fl_set_bmtable_maxitems(FL_OBJECT *ob, int i)
379    if (i>0 && (BMTABLE_SPEC *)ob->spec)
380      ((BMTABLE_SPEC *)ob->spec)->maxi = i;
381 }   
384 int fl_get_bmtable_maxitems(FL_OBJECT *ob)
386    if ((BMTABLE_SPEC *)ob->spec)
387      return  ((BMTABLE_SPEC *)ob->spec)->maxi;
388    else
389      return 0;
393 void fl_replace_bmtable_item(FL_OBJECT */*ob*/, int /*id*/, int  /*cw*/, int /*ch*/, char */*data*/)
395    fprintf(stderr, "Replace bmtable item: Sorry, not yet implemented!\n");
399 void fl_get_bmtable_item(FL_OBJECT */*ob*/, int /*id*/, int */*cw*/, int */*ch*/, char */*data*/)
401    fprintf(stderr, "Get bmtable item: Sorry, not yet implemented!\n");
402 }  
404 void fl_set_bmtable(FL_OBJECT *ob, int pushed, int pos)
406    if ((BMTABLE_SPEC *)ob->spec)
407      ((BMTABLE_SPEC *)ob->spec)->i = (pushed) ? pos: -1;
411 int fl_get_bmtable_numb(FL_OBJECT *ob)
413    if ((BMTABLE_SPEC *)ob->spec)
414      return ((BMTABLE_SPEC *)ob->spec)->mousebut;
415    else
416      return 0;
420 Pixmap fl_get_bmtable_pixmap(FL_OBJECT *ob)
422    if ((BMTABLE_SPEC *)ob->spec)
423      return ((BMTABLE_SPEC *)ob->spec)->pix;
424    else
425      return 0;
429 void fl_draw_bmtable_item(FL_OBJECT *ob, int i, Drawable d, int xx, int yy)
431    int x, y, w, h;
432    GC gc = fl_state[fl_get_vclass()].gc[0];
433    BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;
434    
435    if (sp && sp->pix) {
436       x = (i % sp->nx)*sp->dx + FL_abs(ob->bw);
437       y = (i/sp->nx)*sp->dy + FL_abs(ob->bw);
438       w = sp->dx-2*FL_abs(ob->bw);
439       h = sp->dy-2*FL_abs(ob->bw);       
440       XCopyArea(fl_display, sp->pix, d, gc, x, y, w, h, xx, yy);
441       XFlush(fl_display);
442    }
445 /* Free the current bitmap and pixmap in preparation for installing a new one */
446 void fl_free_bmtable_bitmap(FL_OBJECT *ob)
448   BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;
450   /* dump the temporary pixmap */
451   if (sp && sp->pix) { 
452     XFreePixmap(fl_display, sp->pix);
453     XFlush(fl_display);
454     sp->pix = 0;
455   }
457   /* and free the space taken by bdata etc. */
458   if (sp && sp->bdata) {
459     fl_free(sp->bdata);
460     sp->bdata = 0;
461   }
464 /* Free the current pixmap in preparation for installing a new one */
465 /* This is needed when using data instead of files to set bitmaps  */
466 void fl_free_bmtable_pixmap(FL_OBJECT *ob)
468   BMTABLE_SPEC *sp = (BMTABLE_SPEC *)ob->spec;
470   /* dump the temporary pixmap */
471   if (sp && sp->pix) { 
472     XFreePixmap(fl_display, sp->pix);
473     XFlush(fl_display);
474     sp->pix = 0;
475   }