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