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