1 /*
2  * Author:      William Chia-Wei Cheng (bill.cheng@acm.org)
3  *
4  * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5  *
6  * This file may be distributed under the terms of the Q Public License
7  * as defined by Trolltech AS of Norway and appearing in the file
8  * LICENSE.QPL included in the packaging of this file.
9  *
10  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11  * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12  * PURPOSE.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  * @(#)$Header: /mm2/home/cvs/bc-src/tgif/tdgtbmpl.c,v 1.7 2011/05/16 16:21:59 william Exp $
19  */
20 
21 #define _INCLUDE_FROM_TDGTBMPL_C_
22 
23 #include "tgifdefs.h"
24 #include "patchlvl.h"
25 
26 #include "auxtext.e"
27 #include "choose.e"
28 #include "color.e"
29 #include "cursor.e"
30 #include "dialog.e"
31 #include "font.e"
32 #include "mainloop.e"
33 #include "menu.e"
34 #include "msg.e"
35 #include "names.e"
36 #include "pattern.e"
37 #include "raster.e"
38 #include "rect.e"
39 #include "scroll.e"
40 #include "setup.e"
41 #include "strtbl.e"
42 #include "tdgtbmpl.e"
43 #include "text.e"
44 #include "tidget.e"
45 #include "util.e"
46 
47 /*
48  * A BmpList control looks like the following:
49  *
50  *         +----------------------------------------------+
51  *         | +-------------------------------------+----+ |
52  *         | |                                     |    | |
53  *         | |               dsp_win               |scr | |
54  *         | |                                     |_win| |
55  *         | |                                     |    | |
56  *         | +-------------------------------------+----+ |
57  *         +----------------------------------------------+
58  *
59  * The outside is windowPadding+[vh]_pad.
60  * The inside windows have no decorations.  The left one is the
61  *         dsp_win and the right one is scr_win.
62  * The width of scr_win is 18 in 3D mode.  This includes a 2-pixel
63  *         decoration all around.
64  * The width of dsp_win is gap+(bmp_w+gap)*num_cols and the height of dsp_win
65  *         is gap+(bmp_h+gap)*num_visible_lines.
66  */
67 
68 static void RedrawTdgtBmpList ARGS_DECL((TidgetInfo *pti));
69 static int TdgtBmpListEventHandler ARGS_DECL((TidgetInfo *pti, XEvent *input,
70 		TidgetInfo *handling_pti));
71 static int IsTdgtBmpListEvent ARGS_DECL((TidgetInfo *pti, XEvent *input,
72 		TidgetInfo **ppti_handler_tidget_return));
73 static void DestroyTdgtBmpList ARGS_DECL((TidgetInfo *pti));
74 static void MapTdgtBmpList ARGS_DECL((TidgetInfo *pti));
75 static void TdgtBmpListMoveResize ARGS_DECL((TidgetInfo *pti, int x, int y,
76 		int w, int h));
77 static int TdgtBmpListSendCmd ARGS_DECL((TidgetInfo *pti, int cmd_type,
78 		int cmd_arg, void *pv_cmd_userdata));
79 
80 /* --------------------- Utility Functions --------------------- */
81 
82 static
FreeBmpListItemInfo(pblii)83 void FreeBmpListItemInfo(pblii)
84    BmpListItemInfo *pblii;
85 {
86    if (pblii->pf_free_callback != NULL) {
87       /* the callback function must also free pblii */
88       (pblii->pf_free_callback)(pblii);
89    } else {
90       if (pblii->pixmap != None) {
91          XFreePixmap(mainDisplay, pblii->pixmap);
92       }
93       free(pblii);
94    }
95 }
96 
97 static
TdgtBmpListGetNumRows(pTdgtBmpList)98 int TdgtBmpListGetNumRows(pTdgtBmpList)
99    TdgtBmpList *pTdgtBmpList;
100 {
101    int num_bitmaps=ListLength(&pTdgtBmpList->list);
102    int num_cols=pTdgtBmpList->num_cols;
103 
104    if ((num_bitmaps % num_cols) == 0) {
105       return (int)(num_bitmaps / num_cols);
106    } else {
107       return 1+(int)(num_bitmaps / num_cols);
108    }
109 }
110 
111 /* --------------------- RedrawTdgtBmpList() --------------------- */
112 
113 static
RedrawTdgtBmpListItem(pTdgtBmpList,index,x,y,pblii)114 void RedrawTdgtBmpListItem(pTdgtBmpList, index, x, y, pblii)
115    TdgtBmpList *pTdgtBmpList;
116    int index, x, y;
117    BmpListItemInfo *pblii;
118 {
119    XGCValues values;
120 
121    if (pblii->depth == 1) {
122       values.foreground = myFgPixel;
123       values.background = myBgPixel;
124       values.function = GXcopy;
125       values.fill_style = FillStippled;
126       values.ts_x_origin = x;
127       values.ts_y_origin = y;
128       values.stipple = pblii->pixmap;
129       XChangeGC(mainDisplay, gTidgetManager.gc, GCForeground | GCBackground |
130             GCFunction | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin |
131             GCStipple, &values);
132 
133       XFillRectangle(mainDisplay, pTdgtBmpList->dsp_win, gTidgetManager.gc,
134             x, y, pblii->width, pblii->height);
135 
136       if (index == pTdgtBmpList->marked_index) {
137          values.foreground = myFgPixel^myBgPixel;
138          values.fill_style = FillSolid;
139          values.function = GXxor;
140          XChangeGC(mainDisplay, gTidgetManager.gc,
141                GCForeground | GCFillStyle | GCFunction,
142                &values);
143          XFillRectangle(mainDisplay, pTdgtBmpList->dsp_win, gTidgetManager.gc,
144                x, y, pblii->width, pblii->height);
145       }
146       TidgetManagerResetGC();
147    } else {
148 #ifdef _TGIF_DBG /* debug, do not translate */
149       sprintf(gszMsgBox, "Bitmap depth of %1d not supported in %s().\n",
150             pblii->depth, "RedrawTdgtBmpListItem");
151       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
152 #endif /* _TGIF_DBG */
153    }
154 }
155 
156 static
RedrawTdgtBmpListScrollWindow(pTdgtBmpList)157 void RedrawTdgtBmpListScrollWindow(pTdgtBmpList)
158    TdgtBmpList *pTdgtBmpList;
159 {
160    double frac=(double)0, start_frac=(double)0;
161    int block_h=0, block_start=0, scr_area_h=pTdgtBmpList->scr_win_info.h;
162    int num_rows=TdgtBmpListGetNumRows(pTdgtBmpList);
163    int first_visible_row=(pTdgtBmpList->first_index/pTdgtBmpList->num_cols);
164 
165    start_frac = (num_rows > 0) ?  (double)(((double)first_visible_row) /
166          ((double)num_rows)) : (((double)0));
167    /* starting pixel */
168    block_start = (int)(scr_area_h * start_frac);
169 
170    if (num_rows > pTdgtBmpList->num_visible_lines) {
171       frac = (double)(((double)pTdgtBmpList->num_visible_lines) /
172             ((double)num_rows));
173    } else {
174       frac = (double)1;
175    }
176    if (pTdgtBmpList->first_index+pTdgtBmpList->num_visible_lines >= num_rows) {
177       block_h = scr_area_h - block_start;
178    } else {
179       block_h = (int)(scr_area_h * frac);
180    }
181    TgDrawScrollBar(mainDisplay, pTdgtBmpList->scr_win, VERT_SCROLLBAR, 0, 0,
182          scrollBarW, scr_area_h, start_frac, pTdgtBmpList->num_visible_lines,
183          num_rows);
184 }
185 
186 static
RedrawTdgtBmpListDspWindow(pTdgtBmpList)187 void RedrawTdgtBmpListDspWindow(pTdgtBmpList)
188    TdgtBmpList *pTdgtBmpList;
189 {
190    int i=0, x=0, y=0, gap=pTdgtBmpList->gap;
191    CVListElem *pElem=NULL, *pNextElem=NULL;
192 
193    XClearWindow(mainDisplay, pTdgtBmpList->dsp_win);
194 
195    for (i=0, pElem=ListFirst(&pTdgtBmpList->list); pElem != NULL;
196          pElem=ListNext(&pTdgtBmpList->list, pElem), i++) {
197       if (i == pTdgtBmpList->first_index) {
198          break;
199       }
200    }
201    if (pElem == NULL) return;
202 
203    x = y = gap;
204    for ( ; pElem != NULL; pElem=pNextElem, i++) {
205       BmpListItemInfo *pblii=(BmpListItemInfo*)(pElem->obj);
206       BmpListItemInfo *pblii_next=NULL;
207 
208       RedrawTdgtBmpListItem(pTdgtBmpList, i, x, y, pblii);
209 
210       x += pTdgtBmpList->one_bmp_w + gap;
211       pNextElem = ListNext(&pTdgtBmpList->list, pElem);
212       if (pNextElem != NULL) {
213          pblii_next = (BmpListItemInfo*)(pNextElem->obj);
214          if (x+pTdgtBmpList->one_bmp_w > pTdgtBmpList->dsp_win_info.w) {
215             x = gap;
216             y += pTdgtBmpList->one_bmp_h+gap;
217             if (y >= pTdgtBmpList->dsp_win_info.h) {
218                break;
219             }
220          }
221       }
222    }
223 }
224 
225 static
RedrawTdgtBmpListBaseWindow(pTdgtBmpList)226 void RedrawTdgtBmpListBaseWindow(pTdgtBmpList)
227    TdgtBmpList *pTdgtBmpList;
228 {
229    if (threeDLook) {
230       struct BBRec bbox;
231 
232       SetBBRec(&bbox, 0, 0, pTdgtBmpList->pti->tci.win_info.w,
233             pTdgtBmpList->pti->tci.win_info.h);
234       TgDrawThreeDButton(mainDisplay, pTdgtBmpList->pti->tci.win,
235             gTidgetManager.gc, &bbox, TGBS_LOWRED, 2, FALSE);
236       TidgetManagerResetGC();
237    }
238 }
239 
240 static
RedrawTdgtBmpList(pti)241 void RedrawTdgtBmpList(pti)
242    TidgetInfo *pti;
243 {
244    TdgtBmpList *pTdgtBmpList=(TdgtBmpList*)(pti->tidget);
245    XEvent ev;
246 
247    RedrawTdgtBmpListScrollWindow(pTdgtBmpList);
248    RedrawTdgtBmpListDspWindow(pTdgtBmpList);
249    RedrawTdgtBmpListBaseWindow(pTdgtBmpList);
250 
251    while (XCheckWindowEvent(mainDisplay, pTdgtBmpList->pti->tci.win,
252          ExposureMask, &ev)) ;
253 }
254 
255 /* --------------------- TdgtBmpListEventHandler() --------------------- */
256 
257 static
TdgtBmpListScrollItemCallback(pv_userdata)258 int TdgtBmpListScrollItemCallback(pv_userdata)
259    void *pv_userdata;
260    /* returns TRUE to cancel scrolling */
261 {
262    TdgtBmpList *pTdgtBmpList=((TdgtBmpList*)pv_userdata);
263    int num_visible_lines=pTdgtBmpList->num_visible_lines;
264    int num_cols=pTdgtBmpList->num_cols;
265    int length=ListLength(&pTdgtBmpList->list);
266 
267    if (pTdgtBmpList->scr_dir == SCRL_UP) {
268       if (pTdgtBmpList->first_index == 0) return FALSE;
269       pTdgtBmpList->first_index -= num_cols;
270    } else {
271       if (length <= num_visible_lines ||
272             pTdgtBmpList->first_index+num_visible_lines == length) {
273          return FALSE;
274       }
275       pTdgtBmpList->first_index += num_cols;
276    }
277    RedrawTidget(pTdgtBmpList->pti);
278    XSync(mainDisplay, False);
279 
280    return FALSE;
281 }
282 
283 static
TdgtBmpListScrollPageCallback(pv_userdata)284 int TdgtBmpListScrollPageCallback(pv_userdata)
285    void *pv_userdata;
286    /* returns TRUE to cancel scrolling */
287 {
288    TdgtBmpList *pTdgtBmpList=((TdgtBmpList*)pv_userdata);
289    int num_visible_lines=pTdgtBmpList->num_visible_lines;
290    int length=ListLength(&pTdgtBmpList->list);
291 
292    if (pTdgtBmpList->scr_dir == SCRL_UP) {
293       if (pTdgtBmpList->first_index == 0) return FALSE;
294       pTdgtBmpList->first_index -= num_visible_lines;
295       if (pTdgtBmpList->first_index < 0) pTdgtBmpList->first_index = 0;
296    } else {
297       if (length <= num_visible_lines ||
298             pTdgtBmpList->first_index+num_visible_lines == length) {
299          return FALSE;
300       }
301       pTdgtBmpList->first_index += num_visible_lines;
302       if (pTdgtBmpList->first_index+num_visible_lines >= length) {
303          pTdgtBmpList->first_index = length-num_visible_lines;
304       }
305    }
306    RedrawTidget(pTdgtBmpList->pti);
307    XSync(mainDisplay, False);
308 
309    return FALSE;
310 }
311 
312 static
DoTdgtBmpListBtnScroll(pTdgtBmpList,scroll_page,scr_dir,pbbox)313 int DoTdgtBmpListBtnScroll(pTdgtBmpList, scroll_page, scr_dir, pbbox)
314    TdgtBmpList *pTdgtBmpList;
315    int scroll_page, scr_dir;
316    struct BBRec *pbbox;
317    /* returns TRUE if the done scrolling */
318 {
319    int num_visible_lines=pTdgtBmpList->num_visible_lines;
320    int num_rows=TdgtBmpListGetNumRows(pTdgtBmpList);
321    int num_cols=pTdgtBmpList->num_cols;
322    ScrollBtnCallbackInfo sbci;
323 
324    pTdgtBmpList->scr_dir = scr_dir;
325    memset(&sbci, 0, sizeof(ScrollBtnCallbackInfo));
326 
327    if (scroll_page) {
328       sbci.ms = 200;
329       sbci.pv_userdata = pTdgtBmpList;
330       sbci.pf_scroll_btn_callback = TdgtBmpListScrollPageCallback;
331       if (TgPressButtonLoop(mainDisplay, pTdgtBmpList->scr_win, NULL,
332             &sbci)) {
333          if (scr_dir == SCRL_UP) {
334             if (pTdgtBmpList->first_index == 0) return TRUE;
335             pTdgtBmpList->first_index -= num_visible_lines;
336             if (pTdgtBmpList->first_index < 0) pTdgtBmpList->first_index = 0;
337          } else {
338             if (num_rows <= num_visible_lines ||
339                   (pTdgtBmpList->first_index/num_cols)+num_visible_lines ==
340                   num_rows) {
341                return TRUE;
342             }
343             pTdgtBmpList->first_index += num_visible_lines;
344             if ((pTdgtBmpList->first_index/num_cols)+num_visible_lines >=
345                   num_rows) {
346                pTdgtBmpList->first_index =
347                      (num_rows-num_visible_lines)*num_cols;
348             }
349          }
350       }
351    } else {
352       sbci.ms = 50;
353       sbci.pv_userdata = pTdgtBmpList;
354       sbci.pf_scroll_btn_callback = TdgtBmpListScrollItemCallback;
355       if (TgPressButtonLoop(mainDisplay, pTdgtBmpList->scr_win, pbbox, &sbci)) {
356          if (scr_dir == SCRL_UP) {
357             if (pTdgtBmpList->first_index == 0) return TRUE;
358             pTdgtBmpList->first_index -= num_cols;
359          } else {
360             if (num_rows <= num_visible_lines ||
361                   (pTdgtBmpList->first_index/num_cols)+num_visible_lines ==
362                   num_rows) {
363                return TRUE;
364             }
365             pTdgtBmpList->first_index += num_cols;
366          }
367       }
368    }
369    return FALSE;
370 }
371 
372 static
DoDragInTdgtBmpList(pTdgtBmpList,button_ev,btn_y,btn_offset)373 void DoDragInTdgtBmpList(pTdgtBmpList, button_ev, btn_y, btn_offset)
374    TdgtBmpList *pTdgtBmpList;
375    XButtonEvent *button_ev;
376    int btn_y, btn_offset;
377 {
378    int num_rows=TdgtBmpListGetNumRows(pTdgtBmpList);
379    int num_visible_lines=pTdgtBmpList->num_visible_lines;
380    double frac=(double)0, start_frac=(double)0;
381    int block_h=0, block_start=0, done=FALSE;
382    int scr_area_h=pTdgtBmpList->scr_win_info.h;
383 
384    if (num_rows <= num_visible_lines) return;
385 
386    frac = (double)((double)num_visible_lines / (double)(num_rows));
387    block_h = (int)(scr_area_h * frac);
388 
389    if (num_rows > pTdgtBmpList->num_visible_lines) {
390       frac = (double)((double)pTdgtBmpList->num_visible_lines /
391             (double)(num_rows));
392       block_h = (int)(((double)(scr_area_h-(scrollBarW<<1))) *
393             frac);
394    } else {
395       frac = 1.0;
396       block_h = scr_area_h-(scrollBarW<<1);
397    }
398    if (threeDLook) {
399       block_start = button_ev->y+btn_offset;;
400       start_frac = (double)((double)(block_start-scrollBarW) /
401             (double)(scr_area_h-(scrollBarW<<1)));
402       if (block_start+block_h >= scr_area_h-scrollBarW) {
403          pTdgtBmpList->first_index = (num_rows - num_visible_lines) *
404                pTdgtBmpList->num_cols;
405       } else {
406          pTdgtBmpList->first_index = (int)(num_rows * start_frac) *
407                pTdgtBmpList->num_cols;
408       }
409    } else {
410       block_start = button_ev->y;
411       start_frac = (double)((double)(block_start) / (double)(scr_area_h));
412       if (block_start+block_h >= scr_area_h) {
413          pTdgtBmpList->first_index = (num_rows - num_visible_lines) *
414                pTdgtBmpList->num_cols;
415       } else {
416          pTdgtBmpList->first_index = (int)(num_rows * start_frac) *
417                pTdgtBmpList->num_cols;
418       }
419    }
420    RedrawTidget(pTdgtBmpList->pti);
421 
422    XGrabPointer(mainDisplay, pTdgtBmpList->scr_win, False,
423          PointerMotionMask | ButtonReleaseMask, GrabModeAsync,
424          GrabModeAsync, None, handCursor, CurrentTime);
425 
426    while (!done) {
427       XEvent ev;
428 
429       XNextEvent(mainDisplay, &ev);
430 
431       if (ev.type == Expose || ev.type == VisibilityNotify) {
432          ExposeEventHandler(&ev, TRUE);
433       } else if (ev.type == ButtonRelease) {
434          XUngrabPointer(mainDisplay, CurrentTime);
435          if (debugNoPointerGrab) XSync(mainDisplay, False);
436          done = TRUE;
437       } else if (ev.type == MotionNotify) {
438          int new_name_first=0, y=ev.xmotion.y;
439 
440          if (threeDLook) {
441             y += btn_offset;
442             start_frac = (double)(((double)(y-scrollBarW)) /
443                  ((double)(scr_area_h-(scrollBarW<<1))));
444 
445             if (y <= scrollBarW) {
446                new_name_first = 0;
447             } else if (y+block_h >= scr_area_h-scrollBarW) {
448                new_name_first = (num_rows - num_visible_lines) *
449                      pTdgtBmpList->num_cols;
450             } else {
451                new_name_first = (int)(num_rows * start_frac) *
452                      pTdgtBmpList->num_cols;
453             }
454          } else {
455             start_frac = (double)(((double)y) / ((double)scr_area_h));
456 
457             if (y <= 0) {
458                new_name_first = 0;
459             } else if (y+block_h >= scr_area_h) {
460                new_name_first = (num_rows - num_visible_lines) *
461                      pTdgtBmpList->num_cols;
462             } else {
463                new_name_first = (int)(num_rows * start_frac) *
464                      pTdgtBmpList->num_cols;
465             }
466          }
467          if (pTdgtBmpList->first_index != new_name_first) {
468             pTdgtBmpList->first_index = new_name_first;
469             RedrawTidget(pTdgtBmpList->pti);
470          }
471          while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
472       }
473    }
474 }
475 
476 static
TdgtBmpListScrollHandler(pTdgtBmpList,button_ev)477 void TdgtBmpListScrollHandler(pTdgtBmpList, button_ev)
478    TdgtBmpList *pTdgtBmpList;
479    XButtonEvent *button_ev;
480 {
481    int do_drag=FALSE, btn_offset=0, scr_area_h=pTdgtBmpList->scr_win_info.h;
482 
483    if (!threeDLook && button_ev->button == Button3 &&
484          button_ev->type == ButtonPress) {
485       if (DoTdgtBmpListBtnScroll(pTdgtBmpList,
486             ((button_ev->state & (ShiftMask|ControlMask)) != 0),
487             SCRL_UP, NULL)) {
488          return;
489       }
490    } else if (!threeDLook && button_ev->button == Button1 &&
491          button_ev->type == ButtonPress) {
492       if (DoTdgtBmpListBtnScroll(pTdgtBmpList,
493             ((button_ev->state & (ShiftMask|ControlMask)) != 0),
494             SCRL_DN, NULL)) {
495          return;
496       }
497    } else if (button_ev->button == Button1 && button_ev->type == ButtonPress) {
498       if (button_ev->y < scrollBarW ||
499             button_ev->y >= scr_area_h-scrollBarW) {
500          int which=0;
501          struct BBRec bbox;
502 
503          if (button_ev->y < scrollBarW) {
504             which = SCRL_UP;
505             SetBBRec(&bbox, 0, 0, scrollBarW, scrollBarW);
506          } else {
507             which = SCRL_DN;
508             SetBBRec(&bbox, 0, scr_area_h-scrollBarW, scrollBarW, scr_area_h);
509          }
510          if (DoTdgtBmpListBtnScroll(pTdgtBmpList, FALSE, which, &bbox)) {
511             return;
512          }
513       } else {
514          double start_frac=(double)0;
515          int hit=0;
516          int num_rows=TdgtBmpListGetNumRows(pTdgtBmpList);
517          int first_visible_row=
518                (pTdgtBmpList->first_index/pTdgtBmpList->num_cols);
519 
520          start_frac = (num_rows > 0) ?
521                ((double)(((double)first_visible_row) / (double)num_rows)) :
522                ((double)0);
523          hit = TgGetScrollHit(button_ev->x, button_ev->y, VERT_SCROLLBAR,
524                scrollBarW, scr_area_h, start_frac,
525                pTdgtBmpList->num_visible_lines, num_rows, &btn_offset);
526          if (hit == 0) {
527             do_drag = TRUE;
528          } else {
529             if (DoTdgtBmpListBtnScroll(pTdgtBmpList, TRUE,
530                   (hit < 0 ? SCRL_UP : SCRL_DN), NULL)) {
531                return;
532             }
533          }
534       }
535    } else if (!threeDLook && button_ev->button == Button2 &&
536          button_ev->type == ButtonPress) {
537       do_drag = TRUE;
538    }
539    if (do_drag) {
540       DoDragInTdgtBmpList(pTdgtBmpList, button_ev, button_ev->y, btn_offset);
541    } else {
542       RedrawTidget(pTdgtBmpList->pti);
543    }
544 }
545 
546 static
TdgtBmpListControlChar(pTdgtBmpList,key_ev,key_sym)547 int TdgtBmpListControlChar(pTdgtBmpList, key_ev, key_sym)
548    TdgtBmpList *pTdgtBmpList;
549    XKeyEvent *key_ev;
550    KeySym key_sym;
551 {
552    int length=ListLength(&pTdgtBmpList->list);
553    int num_visible_lines=pTdgtBmpList->num_visible_lines;
554    int num_cols=pTdgtBmpList->num_cols;
555    int i=0;
556 
557    if (key_ev->state & ControlMask) {
558       switch (key_sym) {
559       case XK_Left: return (BAD);
560       case XK_KP_Left: return (BAD);
561       case XK_Up: key_sym = ((unsigned long)'b')&0xff; break;
562       case XK_KP_Up: key_sym = ((unsigned long)'b')&0xff; break;
563       case XK_Right: return (BAD);
564       case XK_KP_Right: return (BAD);
565       case XK_Down: key_sym = ((unsigned long)'f')&0xff; break;
566       case XK_KP_Down: key_sym = ((unsigned long)'f')&0xff; break;
567       case XK_Page_Up: key_sym = ((unsigned long)'b')&0xff; break;
568       case XK_KP_Page_Up: key_sym = ((unsigned long)'b')&0xff; break;
569       case XK_Page_Down: key_sym = ((unsigned long)'f')&0xff; break;
570       case XK_KP_Page_Down: key_sym = ((unsigned long)'f')&0xff; break;
571       }
572    } else {
573       switch (key_sym) {
574       case XK_Left: return BAD;
575       case XK_KP_Left: return BAD;
576       case XK_Up: key_sym = ((unsigned long)'k')&0xff; break;
577       case XK_KP_Up: key_sym = ((unsigned long)'k')&0xff; break;
578       case XK_Right: return BAD;
579       case XK_KP_Right: return BAD;
580       case XK_Down: key_sym = ((unsigned long)'j')&0xff; break;
581       case XK_KP_Down: key_sym = ((unsigned long)'j')&0xff; break;
582       case XK_Page_Up: key_sym = ((unsigned long)'b')&0xff; break;
583       case XK_KP_Page_Up: key_sym = ((unsigned long)'b')&0xff; break;
584       case XK_Page_Down: key_sym = ((unsigned long)'f')&0xff; break;
585       case XK_KP_Page_Down: key_sym = ((unsigned long)'f')&0xff; break;
586       }
587    }
588    switch (key_sym&0xff) {
589    case 'w': /* erase */
590    case 'y':
591       return INVALID;
592    case 'n': /* down one */
593    case 'j':
594       if (pTdgtBmpList->can_select) {
595          /*
596           * i = (pni->marked_index < length-1) ?
597           *       pni->marked_index+1 : length-1;
598           */
599       } else {
600          if (length > num_visible_lines) {
601             if (pTdgtBmpList->first_index+num_visible_lines < length) {
602                pTdgtBmpList->first_index += num_cols;
603             }
604          }
605       }
606       break;
607    case 'p': /* up one */
608    case 'k':
609       if (pTdgtBmpList->can_select) {
610          /*
611           * i = (pni->marked_index>0) ? pni->marked_index-1 : 0;
612           */
613       } else {
614          if (length > num_visible_lines) {
615             if (pTdgtBmpList->first_index > 0) {
616                pTdgtBmpList->first_index -= num_cols;
617             }
618          }
619       }
620       break;
621    case 'd': /* down one page */
622    case 'f':
623       if (pTdgtBmpList->can_select) {
624          /*
625           * if (pni->marked_index==INVALID) {
626           *    i = (length <= num_visible_lines) ?  length-1 :
627           *          num_visible_lines;
628           * } else if (pni->marked_index < length-num_visible_lines) {
629           *    i = pni->marked_index+num_visible_lines;
630           * } else {
631           *    i = length-1;
632           * }
633           */
634       } else {
635          if (length > num_visible_lines) {
636             if (pTdgtBmpList->first_index+num_visible_lines < length) {
637                pTdgtBmpList->first_index += num_visible_lines;
638                if (pTdgtBmpList->first_index + num_visible_lines > length) {
639                   pTdgtBmpList->first_index = length - num_visible_lines;
640                }
641             }
642          }
643       }
644       break;
645    case 'u': /* up one page */
646    case 'b':
647       if (pTdgtBmpList->can_select) {
648          /*
649           * i = (pni->marked_index > (num_visible_lines-1)) ?
650           *       pni->marked_index-num_visible_lines : 0;
651           */
652       } else {
653          pTdgtBmpList->first_index -= num_visible_lines;
654          if (pTdgtBmpList->first_index < 0) pTdgtBmpList->first_index = 0;
655       }
656       break;
657    default: return BAD;
658    }
659    return i;
660 }
661 
662 static
SpecialKeyInTdgtBmpList(pTdgtBmpList,key_ev,key_sym,pn_changing,pn_selected_btn_index)663 void SpecialKeyInTdgtBmpList(pTdgtBmpList, key_ev, key_sym, pn_changing,
664       pn_selected_btn_index)
665    TdgtBmpList *pTdgtBmpList;
666    XKeyEvent *key_ev;
667    KeySym key_sym;
668    int *pn_changing, *pn_selected_btn_index;
669 {
670    int saved_first=pTdgtBmpList->first_index;
671    int saved_marked=pTdgtBmpList->marked_index;
672    int rc=TdgtBmpListControlChar(pTdgtBmpList, key_ev, key_sym);
673 
674    if (rc == BAD || rc == INVALID) return;
675 
676    if (saved_first != pTdgtBmpList->first_index ||
677          saved_marked != pTdgtBmpList->marked_index) {
678       RedrawTidget(pTdgtBmpList->pti);
679    }
680 }
681 
682 static XComposeStatus c_stat;
683 
684 static
KeyPressInTdgtBmpList(pTdgtBmpList,key_ev,pn_changing,pn_selected_btn_index)685 int KeyPressInTdgtBmpList(pTdgtBmpList, key_ev, pn_changing,
686       pn_selected_btn_index)
687    TdgtBmpList *pTdgtBmpList;
688    XKeyEvent *key_ev;
689    int *pn_changing, *pn_selected_btn_index;
690 {
691    int length=ListLength(&pTdgtBmpList->list);
692    char buf[80];
693    KeySym key_sym;
694    int has_ch=FALSE;
695 
696    has_ch = XLookupString(key_ev, buf, sizeof(buf), &key_sym, &c_stat);
697    TranslateKeys(buf, &key_sym);
698 
699    if ((key_ev->state & ControlMask) && key_sym == XK_j) {
700       SpecialKeyInTdgtBmpList(pTdgtBmpList, key_ev, key_sym, pn_changing,
701             pn_selected_btn_index);
702    } else if (CharIsCRorLF(key_ev, buf, key_sym, &has_ch)) {
703       if (pTdgtBmpList->marked_index != INVALID) {
704          TidgetControlNotify(pTdgtBmpList->pti, TDGTNF_LIST_DBL_CLICKED,
705                pTdgtBmpList->marked_index, 0);
706          return TRUE;
707       }
708    } else if (CharIsESC(key_ev, buf, key_sym, &has_ch)) {
709       if (pTdgtBmpList->can_select) {
710          /*
711           * *pn_changing = FALSE;
712           * *pn_selected_btn_index = GetBtnIndexFromBtnId(BUTTON_CANCEL);
713           */
714       }
715    } else if (CharIsBSorDEL(key_ev, buf, key_sym, &has_ch, FALSE)) {
716       if (pTdgtBmpList->can_select) {
717          /*
718           * if (pni->edit_style == NAMES_SELECT_FILE &&
719           *       (pni->faking_dot_dot || pni->pop_from_root)) {
720           *    *pn_changing = FALSE;
721           *    *pn_selected_btn_index = INVALID;
722           * } else {
723           *    BackSpaceInNames(pn_changing, pn_selected_btn_index);
724           * }
725           */
726       }
727    } else if (CharIsTAB(key_ev, buf, key_sym, &has_ch)) {
728       if (pTdgtBmpList->can_select) {
729          /* should tab out of focus?! */
730       }
731    } else if (length != 0 && ((key_sym>'\040' && key_sym<='\177' &&
732          (key_ev->state & ControlMask)) || key_sym==XK_Up ||
733          key_sym==XK_Down || key_sym==XK_KP_Up || key_sym==XK_KP_Down ||
734          key_sym==XK_Page_Up || key_sym==XK_KP_Page_Up ||
735          key_sym==XK_Page_Down || key_sym==XK_KP_Page_Down)) {
736       SpecialKeyInTdgtBmpList(pTdgtBmpList, key_ev, key_sym, pn_changing,
737             pn_selected_btn_index);
738    } else if (key_sym>='\040' && key_sym<='\177' && length != 0) {
739       if (pTdgtBmpList->can_select) {
740          /*
741           * CharInNames(buf, pn_changing, pn_selected_btn_index);
742           */
743       }
744       return FALSE;
745    }
746    return FALSE;
747 }
748 
749 static
TdgtBmpListDspHandler(pTdgtBmpList,button_ev)750 int TdgtBmpListDspHandler(pTdgtBmpList, button_ev)
751    TdgtBmpList *pTdgtBmpList;
752    XButtonEvent *button_ev;
753 {
754    int gap=pTdgtBmpList->gap;
755    int btn_x=button_ev->x, btn_y=button_ev->y;
756    int first_index=pTdgtBmpList->first_index;
757    int num_cols=pTdgtBmpList->num_cols;
758    int row_index=(btn_y-gap)/(pTdgtBmpList->one_bmp_h+gap);
759    int col_index=(btn_x-gap)/(pTdgtBmpList->one_bmp_w+gap);
760    int index=first_index+(row_index*num_cols)+col_index;
761    int prev_marked_index=pTdgtBmpList->marked_index;
762    Time click_time=button_ev->time;
763 
764    if (index >= ListLength(&pTdgtBmpList->list)) {
765       pTdgtBmpList->marked_index = INVALID;
766    } else {
767       pTdgtBmpList->marked_index = index;
768    }
769    if (prev_marked_index != pTdgtBmpList->marked_index) {
770       RedrawTdgtBmpListDspWindow(pTdgtBmpList);
771       /* send notifications */
772    }
773    TidgetControlNotify(pTdgtBmpList->pti, TDGTNF_LIST_CLICKED,
774          pTdgtBmpList->marked_index, button_ev->button);
775 
776    /* now check for double-click */
777    if (pTdgtBmpList->marked_index != INVALID &&
778          pTdgtBmpList->last_selected_index == pTdgtBmpList->marked_index &&
779          (click_time-pTdgtBmpList->last_clicked_time) < doubleClickInterval) {
780       /* send notifications */
781       TidgetControlNotify(pTdgtBmpList->pti, TDGTNF_LIST_DBL_CLICKED,
782             pTdgtBmpList->marked_index, 0);
783    }
784    memcpy(&pTdgtBmpList->last_clicked_time, &click_time, sizeof(Time));
785    pTdgtBmpList->last_selected_index = pTdgtBmpList->marked_index;
786 
787    return TRUE;
788 }
789 
790 static
ButtonPressInTdgtBmpList(pTdgtBmpList,button_ev)791 int ButtonPressInTdgtBmpList(pTdgtBmpList, button_ev)
792    TdgtBmpList *pTdgtBmpList;
793    XButtonEvent *button_ev;
794 {
795    if (button_ev->window == pTdgtBmpList->scr_win) {
796       TdgtBmpListScrollHandler(pTdgtBmpList, button_ev);
797       return TRUE;
798    } else if (button_ev->window == pTdgtBmpList->dsp_win) {
799       if (pTdgtBmpList->can_select != 0) {
800          if ((button_ev->button == Button1 &&
801                (pTdgtBmpList->can_select & Button1Mask) == Button1Mask) ||
802              (button_ev->button == Button2 &&
803                (pTdgtBmpList->can_select & Button2Mask) == Button2Mask) ||
804              (button_ev->button == Button3 &&
805                (pTdgtBmpList->can_select & Button3Mask) == Button3Mask)) {
806             return TdgtBmpListDspHandler(pTdgtBmpList, button_ev);
807          }
808       }
809    }
810    return FALSE;
811 }
812 
813 static
TdgtBmpListEventHandler(pti,input,handling_pti)814 int TdgtBmpListEventHandler(pti, input, handling_pti)
815    TidgetInfo *pti, *handling_pti;
816    XEvent *input;
817 {
818    TdgtBmpList *pTdgtBmpList=(TdgtBmpList*)(pti->tidget);
819 
820    if (pti != handling_pti) return FALSE;
821 
822    if (input->type == Expose) {
823       RedrawTidget(pTdgtBmpList->pti);
824    } else if (input->type == EnterNotify) {
825       if (pTdgtBmpList->mosi.one_line_status) {
826          SetStringStatus(pTdgtBmpList->mosi.one_line_str);
827       } else {
828          MouseOverStatusInfo *pmosi=(&pTdgtBmpList->mosi);
829 
830          SetMouseStatus(pmosi->btn_str[0], pmosi->btn_str[1],
831                pmosi->btn_str[2]);
832       }
833    } else if (input->type == LeaveNotify) {
834       SetMouseStatus("", "", "");
835    } else if (input->type == KeyPress) {
836       if (pTdgtBmpList->can_select) {
837          /*
838           * KeyPressInTdgtBmpList(pTdgtBmpList, &changing,
839           *         &selected_btn_index);
840           */
841       } else {
842          return KeyPressInTdgtBmpList(pTdgtBmpList, &input->xkey, NULL,
843                NULL);
844       }
845    } else if (input->type == ButtonPress) {
846       return ButtonPressInTdgtBmpList(pTdgtBmpList, &input->xbutton);
847    }
848    return FALSE;
849 }
850 
851 /* --------------------- IsTdgtBmpListEvent() --------------------- */
852 
853 static
IsTdgtBmpListEvent(pti,input,ppti_handler_tidget_return)854 int IsTdgtBmpListEvent(pti, input, ppti_handler_tidget_return)
855    TidgetInfo *pti, **ppti_handler_tidget_return;
856    XEvent *input;
857 {
858    TdgtBmpList *pTdgtBmpList=(TdgtBmpList*)(pti->tidget);
859 
860    if (input->xany.window == pTdgtBmpList->dsp_win ||
861          input->xany.window == pTdgtBmpList->scr_win) {
862       *ppti_handler_tidget_return = pti;
863       return TRUE;
864    }
865    return FALSE;
866 }
867 
868 /* --------------------- DestroyTdgtBmpList() --------------------- */
869 
870 static
DestroyTdgtBmpList(pti)871 void DestroyTdgtBmpList(pti)
872    TidgetInfo *pti;
873 {
874    TdgtBmpList *pTdgtBmpList=(TdgtBmpList*)(pti->tidget);
875 
876    TdgtBmpListReset(pTdgtBmpList);
877 
878    free(pTdgtBmpList);
879 }
880 
881 /* --------------------- MapTdgtBmpList() --------------------- */
882 
883 static
MapTdgtBmpList(pti)884 void MapTdgtBmpList(pti)
885    TidgetInfo *pti;
886 {
887    TdgtBmpList *pTdgtBmpList=(TdgtBmpList*)(pti->tidget);
888 
889 #ifdef MAPBEFORESELECT
890    XMapWindow(mainDisplay, pTdgtBmpList->pti->tci.win);
891    XSelectInput(mainDisplay, pTdgtBmpList->pti->tci.win, ExposureMask);
892 
893    XMapWindow(mainDisplay, pTdgtBmpList->dsp_win);
894    XSelectInput(mainDisplay, pTdgtBmpList->dsp_win, KeyPressMask |
895          ButtonPressMask | KeyPressMask | ExposureMask |
896          EnterWindowMask | LeaveWindowMask);
897 
898    XMapWindow(mainDisplay, pTdgtBmpList->scr_win);
899    XSelectInput(mainDisplay, pTdgtBmpList->scr_win, KeyPressMask |
900          ButtonPressMask | ExposureMask);
901 #else
902    XSelectInput(mainDisplay, pTdgtBmpList->pti->tci.win, ExposureMask);
903    XMapWindow(mainDisplay, pTdgtBmpList->pti->tci.win);
904 
905    XSelectInput(mainDisplay, pTdgtBmpList->dsp_win, KeyPressMask |
906          ButtonPressMask | KeyPressMask | ExposureMask |
907          EnterWindowMask | LeaveWindowMask);
908    XMapWindow(mainDisplay, pTdgtBmpList->dsp_win);
909 
910    XSelectInput(mainDisplay, pTdgtBmpList->scr_win, KeyPressMask |
911          ButtonPressMask | ExposureMask);
912    XMapWindow(mainDisplay, pTdgtBmpList->scr_win);
913 #endif
914 }
915 
916 /* --------------------- TdgtBmpListMoveResize() --------------------- */
917 
918 static
TdgtBmpListMoveResize(pti,x,y,w,h)919 void TdgtBmpListMoveResize(pti, x, y, w, h)
920    TidgetInfo *pti;
921    int x, y, w, h;
922 {
923    TdgtBmpList *pTdgtBmpList=(TdgtBmpList*)(pti->tidget);
924 
925    pTdgtBmpList->pti->tci.win_info.x = x;
926    pTdgtBmpList->pti->tci.win_info.y = y;
927    pTdgtBmpList->pti->tci.win_info.w = w;
928    pTdgtBmpList->pti->tci.win_info.h = h;
929    XMoveResizeWindow(mainDisplay, pTdgtBmpList->pti->tci.win, x, y, w, h);
930 
931    pTdgtBmpList->dsp_win_info.x = windowPadding;
932    pTdgtBmpList->dsp_win_info.y = windowPadding;
933    pTdgtBmpList->dsp_win_info.w = w-(windowPadding<<1)-scrollBarW;
934    pTdgtBmpList->dsp_win_info.h = h-(windowPadding<<1);
935    XMoveResizeWindow(mainDisplay, pTdgtBmpList->dsp_win,
936          pTdgtBmpList->dsp_win_info.x, pTdgtBmpList->dsp_win_info.y,
937          pTdgtBmpList->dsp_win_info.w, pTdgtBmpList->dsp_win_info.h);
938 
939    pTdgtBmpList->scr_win_info.x = w-windowPadding-scrollBarW;
940    pTdgtBmpList->scr_win_info.y = windowPadding;
941    pTdgtBmpList->scr_win_info.w = scrollBarW;
942    pTdgtBmpList->scr_win_info.h = h-(windowPadding<<1);
943    XMoveResizeWindow(mainDisplay, pTdgtBmpList->scr_win,
944          pTdgtBmpList->scr_win_info.x, pTdgtBmpList->scr_win_info.y,
945          pTdgtBmpList->scr_win_info.w, pTdgtBmpList->scr_win_info.h);
946 }
947 
948 /* --------------------- TdgtBmpListSendCmd() --------------------- */
949 
950 static
HandleSelectNext(pTdgtBmpList,cmd_arg)951 int HandleSelectNext(pTdgtBmpList, cmd_arg)
952    TdgtBmpList *pTdgtBmpList;
953    int cmd_arg; /* one of TDGTARG_MOVE_* */
954 {
955    int prev_marked_index=pTdgtBmpList->marked_index;
956    int num_items=ListLength(&pTdgtBmpList->list);
957    int num_cols=pTdgtBmpList->num_cols;
958    int col=(prev_marked_index%num_cols);
959    int last_row_first_item_index=0, this_row_first_item_index=0;
960    int this_row_is_last_row=TRUE;
961 
962    if (num_items == 0) return TRUE;
963 
964    if (num_items%num_cols == 0) {
965       last_row_first_item_index = num_cols * (round(((double)num_items) /
966             ((double)num_cols))-1);
967    } else {
968       last_row_first_item_index = num_cols * ((int)(num_items / num_cols));
969    }
970    if (prev_marked_index%num_cols == 0) {
971       this_row_first_item_index = num_cols *
972             round(((double)prev_marked_index) / ((double)num_cols));
973    } else {
974       this_row_first_item_index = num_cols * ((int)(prev_marked_index /
975             num_cols));
976    }
977    this_row_is_last_row = (this_row_first_item_index+num_cols >= num_items);
978    switch (cmd_arg) {
979    case TDGTARG_MOVE_UP:
980       if (prev_marked_index == INVALID) {
981          pTdgtBmpList->marked_index = num_items-1;
982       } else if (num_items <= num_cols) {
983          /* do nothing */
984       } else {
985          pTdgtBmpList->marked_index -= num_cols;
986          if (pTdgtBmpList->marked_index < 0) {
987             pTdgtBmpList->marked_index = last_row_first_item_index+col;
988          }
989       }
990       break;
991    case TDGTARG_MOVE_DOWN:
992       if (prev_marked_index == INVALID) {
993          pTdgtBmpList->marked_index = 0;
994       } else if (num_items <= num_cols) {
995          /* do nothing */
996       } else {
997          pTdgtBmpList->marked_index += num_cols;
998          if (pTdgtBmpList->marked_index >= num_items) {
999             pTdgtBmpList->marked_index = col;
1000          }
1001       }
1002       break;
1003    case TDGTARG_MOVE_RIGHT:
1004       if (prev_marked_index == INVALID) {
1005          pTdgtBmpList->marked_index = 0;
1006       } else if (this_row_is_last_row) {
1007          if (prev_marked_index == num_items-1) {
1008             pTdgtBmpList->marked_index = this_row_first_item_index;
1009          } else {
1010             pTdgtBmpList->marked_index++;
1011          }
1012       } else if (col == num_cols-1) {
1013          pTdgtBmpList->marked_index = this_row_first_item_index;
1014       } else {
1015          pTdgtBmpList->marked_index++;
1016       }
1017       break;
1018    case TDGTARG_MOVE_LEFT:
1019       if (prev_marked_index == INVALID) {
1020          pTdgtBmpList->marked_index = 0;
1021       } else if (this_row_is_last_row) {
1022          if (col == 0) {
1023             pTdgtBmpList->marked_index = num_items-1;
1024          } else {
1025             pTdgtBmpList->marked_index--;
1026          }
1027       } else if (col == 0) {
1028          pTdgtBmpList->marked_index = this_row_first_item_index+num_cols-1;
1029       } else {
1030          pTdgtBmpList->marked_index--;
1031       }
1032       break;
1033    }
1034    RedrawTdgtBmpListDspWindow(pTdgtBmpList);
1035 
1036    return TRUE;
1037 }
1038 
1039 static
HandleGetCurSel(pTdgtBmpList,pn_selected_index)1040 int HandleGetCurSel(pTdgtBmpList, pn_selected_index)
1041    TdgtBmpList *pTdgtBmpList;
1042    int *pn_selected_index;
1043 {
1044    if (pn_selected_index != NULL) {
1045       *pn_selected_index = pTdgtBmpList->marked_index;
1046    }
1047    return TRUE;
1048 }
1049 
1050 static
HandleGetItem(pTdgtBmpList,index,ppblii)1051 int HandleGetItem(pTdgtBmpList, index, ppblii)
1052    TdgtBmpList *pTdgtBmpList;
1053    int index;
1054    BmpListItemInfo **ppblii;
1055 {
1056    int i=0;
1057    CVListElem *pElem=NULL;
1058 
1059    if (index == INVALID) return FALSE;
1060 
1061    for (i=0, pElem=ListFirst(&pTdgtBmpList->list); pElem != NULL;
1062          pElem=ListNext(&pTdgtBmpList->list, pElem), i++) {
1063       if (i == index) {
1064          BmpListItemInfo *pblii=(BmpListItemInfo*)(pElem->obj);
1065 
1066          if (ppblii != NULL) {
1067             *ppblii = pblii;
1068          }
1069          return TRUE;
1070       } else if (i > index) {
1071          break;
1072       }
1073    }
1074    return FALSE;
1075 }
1076 
TdgtBmpListSendCmd(pti,cmd_type,cmd_arg,pv_cmd_userdata)1077 int TdgtBmpListSendCmd(pti, cmd_type, cmd_arg, pv_cmd_userdata)
1078    TidgetInfo *pti;
1079    int cmd_type, cmd_arg;
1080    void *pv_cmd_userdata;
1081 {
1082    TdgtBmpList *pTdgtBmpList=(TdgtBmpList*)(pti->tidget);
1083 
1084    switch (cmd_type) {
1085    case TDGTCMD_LIST_SEL_NEXT:
1086       return HandleSelectNext(pTdgtBmpList, cmd_arg);
1087    case TDGTCMD_LIST_RESETCONTENT:
1088       TdgtBmpListCleanUpEntries(pTdgtBmpList);
1089       RedrawTidget(pTdgtBmpList->pti);
1090       return TRUE;
1091    case TDGTCMD_LIST_GETCURSEL:
1092       return HandleGetCurSel(pTdgtBmpList, (int*)pv_cmd_userdata);
1093    case TDGTCMD_LIST_GETITEM:
1094       return HandleGetItem(pTdgtBmpList, cmd_arg,
1095             (BmpListItemInfo**)pv_cmd_userdata);
1096    }
1097    return FALSE;
1098 }
1099 
1100 /* --------------------- TdgtBmpListReset() --------------------- */
1101 
TdgtBmpListReset(pTdgtBmpList)1102 void TdgtBmpListReset(pTdgtBmpList)
1103    TdgtBmpList *pTdgtBmpList;
1104 {
1105    TdgtBmpListCleanUpEntries(pTdgtBmpList);
1106 
1107    FreeDynStrBuf(&pTdgtBmpList->pti->tci.dyn_str);
1108 }
1109 
1110 /* --------------------- CreateTdgtBmpList() --------------------- */
1111 
1112 static
TdgtBmpListCalcGeom(bmp_w,bmp_h,num_cols,num_visible_lines,gap,pn_content_w,pn_content_h)1113 void TdgtBmpListCalcGeom(bmp_w, bmp_h, num_cols, num_visible_lines, gap,
1114       pn_content_w, pn_content_h)
1115    int bmp_w, bmp_h, num_cols, num_visible_lines, gap;
1116    int *pn_content_w, *pn_content_h;
1117    /*
1118     * The content area includes the bitmap display area and the scrollbar.
1119     */
1120 {
1121    int w=gap+((bmp_w+gap)*num_cols), h=gap+((bmp_h+gap)*num_visible_lines);
1122 
1123    /*
1124     * Display area has *no* windowPadding around it (scrollBarW includes
1125     *         (windowPadding<<1) already).
1126     */
1127    w += scrollBarW;
1128 
1129    if (pn_content_w != NULL) *pn_content_w = w;
1130    if (pn_content_h != NULL) *pn_content_h = h;
1131 }
1132 
CreateTdgtBmpList(parent_win,parent_tidgetinfo,ctl_id,x,y,h_pad,v_pad,bmp_w,bmp_h,num_cols,num_visible_lines,gap,can_select,pmosi)1133 TdgtBmpList *CreateTdgtBmpList(parent_win, parent_tidgetinfo, ctl_id, x, y,
1134       h_pad, v_pad, bmp_w, bmp_h, num_cols, num_visible_lines, gap, can_select,
1135       pmosi)
1136    Window parent_win;
1137    TidgetInfo *parent_tidgetinfo;
1138    int ctl_id, x, y, h_pad, v_pad, bmp_w, bmp_h, num_cols, num_visible_lines;
1139    int gap, can_select;
1140    MouseOverStatusInfo *pmosi;
1141 {
1142    int bg_pixel=(threeDLook ? myLtGryPixel : myBgPixel), w=0, h=0;
1143    int content_w=0, content_h=0;
1144    TdgtBmpList *pTdgtBmpList=NULL;
1145 
1146    TdgtBmpListCalcGeom(bmp_w, bmp_h, num_cols, num_visible_lines, gap,
1147          &content_w, &content_h);
1148    w = content_w + (windowPadding<<1) + (h_pad<<1);
1149    h = content_h + (windowPadding<<1) + (v_pad<<1);
1150 
1151    pTdgtBmpList = (TdgtBmpList*)malloc(sizeof(TdgtBmpList));
1152    if (pTdgtBmpList == NULL) FailAllocMessage();
1153    memset(pTdgtBmpList, 0, sizeof(TdgtBmpList));
1154 
1155    pTdgtBmpList->pti = NewTidgetInfo(parent_tidgetinfo, TIDGET_TYPE_BMPL,
1156          pTdgtBmpList, ctl_id, NULL);
1157    if ((pTdgtBmpList->pti->tci.win=XCreateSimpleWindow(mainDisplay, parent_win,
1158          x, y, w, h, brdrW, myBorderPixel, bg_pixel)) == 0) {
1159       FailToCreateWindowMessage("CreateTdgtBmpList()", NULL, TRUE);
1160    }
1161    XSelectInput(mainDisplay, pTdgtBmpList->pti->tci.win, ExposureMask);
1162    SetTidgetInfoBasic(pTdgtBmpList->pti, TIDGET_TYPE_BMPL, pTdgtBmpList,
1163          parent_win, x, y, w, h, v_pad, h_pad, TGBS_NORMAL, "");
1164    TidgetSetCallbacks(pTdgtBmpList->pti,
1165          RedrawTdgtBmpList, TdgtBmpListEventHandler, IsTdgtBmpListEvent,
1166          DestroyTdgtBmpList, MapTdgtBmpList, TdgtBmpListMoveResize,
1167          TdgtBmpListSendCmd);
1168 
1169    CVListInit(&pTdgtBmpList->list);
1170    if (pmosi != NULL) {
1171       memcpy(&pTdgtBmpList->mosi, pmosi, sizeof(MouseOverStatusInfo));
1172    }
1173    /* Note: scrollBarW accounts for windowPadding */
1174    if ((pTdgtBmpList->dsp_win=XCreateSimpleWindow(mainDisplay,
1175          pTdgtBmpList->pti->tci.win, windowPadding, windowPadding,
1176          w-(windowPadding<<1)-scrollBarW, h-(windowPadding<<1), brdrW,
1177          myBorderPixel, myBgPixel)) == 0) {
1178       FailToCreateWindowMessage("CreateTdgtBmpList()", NULL, TRUE);
1179    }
1180    XSelectInput(mainDisplay, pTdgtBmpList->dsp_win, KeyPressMask |
1181          ButtonPressMask | KeyPressMask | ExposureMask |
1182          EnterWindowMask | LeaveWindowMask);
1183    pTdgtBmpList->dsp_win_info.x = windowPadding;
1184    pTdgtBmpList->dsp_win_info.y = windowPadding;
1185    pTdgtBmpList->dsp_win_info.w = w-(windowPadding<<1)-scrollBarW;
1186    pTdgtBmpList->dsp_win_info.h = h-(windowPadding<<1);
1187 
1188    if ((pTdgtBmpList->scr_win=XCreateSimpleWindow(mainDisplay,
1189          pTdgtBmpList->pti->tci.win, w-windowPadding-scrollBarW, windowPadding,
1190          scrollBarW, h-(windowPadding<<1), brdrW, myBorderPixel, bg_pixel)) ==
1191          0) {
1192       FailToCreateWindowMessage("CreateTdgtBmpList()", NULL, TRUE);
1193    }
1194    XSelectInput(mainDisplay, pTdgtBmpList->scr_win, KeyPressMask |
1195          ButtonPressMask | ExposureMask);
1196    pTdgtBmpList->scr_win_info.x = w-windowPadding-scrollBarW;
1197    pTdgtBmpList->scr_win_info.y = windowPadding;
1198    pTdgtBmpList->scr_win_info.w = scrollBarW;
1199    pTdgtBmpList->scr_win_info.h = h-(windowPadding<<1);
1200 
1201    pTdgtBmpList->can_select = can_select;
1202 
1203    pTdgtBmpList->one_bmp_w = bmp_w;
1204    pTdgtBmpList->one_bmp_h = bmp_h;
1205    pTdgtBmpList->gap = gap;
1206 
1207    pTdgtBmpList->first_index = 0;
1208    pTdgtBmpList->marked_index = INVALID;
1209 
1210    pTdgtBmpList->num_cols = num_cols;
1211    pTdgtBmpList->num_visible_lines = num_visible_lines;
1212 
1213    return pTdgtBmpList;
1214 }
1215 
1216 /* --------------------- TdgtBmpListCleanUpEntries() --------------------- */
1217 
TdgtBmpListCleanUpEntries(pTdgtBmpList)1218 int TdgtBmpListCleanUpEntries(pTdgtBmpList)
1219    TdgtBmpList *pTdgtBmpList;
1220 {
1221    CVListElem *pElem=NULL;
1222 
1223    if (ListLength(&pTdgtBmpList->list) > 0) {
1224       TidgetSetDirty(pTdgtBmpList->pti, TRUE);
1225    }
1226    for (pElem=ListFirst(&pTdgtBmpList->list); pElem != NULL;
1227          pElem=ListNext(&pTdgtBmpList->list, pElem)) {
1228       BmpListItemInfo *pblii=(BmpListItemInfo*)(pElem->obj);
1229 
1230       FreeBmpListItemInfo(pblii);
1231    }
1232    ListUnlinkAll(&pTdgtBmpList->list);
1233 
1234    pTdgtBmpList->first_index = 0;
1235    pTdgtBmpList->marked_index = INVALID;
1236 
1237    return TRUE;
1238 }
1239 
1240 /* --------------------- TdgtBmpListScrollToBottom() --------------------- */
1241 
TdgtBmpListScrollToBottom(pTdgtBmpList)1242 int TdgtBmpListScrollToBottom(pTdgtBmpList)
1243    TdgtBmpList *pTdgtBmpList;
1244 {
1245    int length=ListLength(&pTdgtBmpList->list);
1246 
1247    if (pTdgtBmpList->num_visible_lines < length) {
1248       pTdgtBmpList->first_index = length - pTdgtBmpList->num_visible_lines;
1249    } else {
1250       pTdgtBmpList->first_index = 0;
1251    }
1252    return TRUE;
1253 }
1254 
1255 /* --------------------- TdgtBmpListAddItem() --------------------- */
1256 
TdgtBmpListAddItem(pTdgtBmpList,pblii)1257 int TdgtBmpListAddItem(pTdgtBmpList, pblii)
1258    TdgtBmpList *pTdgtBmpList;
1259    BmpListItemInfo *pblii;
1260 {
1261    ListAppend(&pTdgtBmpList->list, pblii);
1262 
1263    TidgetSetDirty(pTdgtBmpList->pti, TRUE);
1264 
1265    RedrawTidget(pTdgtBmpList->pti);
1266 
1267    return TRUE;
1268 }
1269 
1270 /* --------------------- Init & Clean Up --------------------- */
1271 
InitTdgtBmpList()1272 int InitTdgtBmpList()
1273 {
1274    return TRUE;
1275 }
1276 
CleanUpTdgtBmpList()1277 void CleanUpTdgtBmpList()
1278 {
1279 }
1280 
1281