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