1 /*
2 * xvctrl.c - Control box handling functions
3 *
4 * callable functions:
5 *
6 * CreateCtrl(geom) - creates the ctrlW window. Doesn't map it.
7 * CtrlBox(vis) - random processing based on value of 'vis'
8 * maps/unmaps window, etc.
9 * RedrawCtrl(x,y,w,h) - called by 'expose' events
10 * ClickCtrl(x,y)
11 * DrawCtrlStr() - called to redraw 'ISTR_INFO' string in ctrlW
12 * ScrollToCurrent() - called when list selection is changed
13 *
14 * LSCreate() - creates a listbox
15 * LSRedraw() - redraws 'namelist' box
16 * LSClick() - operates list box
17 * LSChangeData() - like LSNewData(), but tries not to repos list
18 * LSNewData() - called when strings or number of them change
19 * LSKey() - called to handle page up/down, arrows
20 *
21 */
22
23 #include "copyright.h"
24
25 #include "xv.h"
26
27 #include "bits/gray25"
28 #include "bits/gray50"
29 #include "bits/i_fifo"
30 #include "bits/i_chr"
31 #include "bits/i_dir"
32 #include "bits/i_blk"
33 #include "bits/i_lnk"
34 #include "bits/i_sock"
35 #include "bits/i_exe"
36 #include "bits/i_reg"
37 #include "bits/h_rotl"
38 #include "bits/h_rotr"
39 #include "bits/fliph"
40 #include "bits/flipv"
41 #include "bits/p10"
42 #include "bits/m10"
43 #include "bits/cut"
44 #include "bits/copy"
45 #include "bits/clear"
46 #include "bits/paste"
47 #include "bits/padimg"
48 #include "bits/annot"
49 #include "bits/uicon"
50 #include "bits/oicon1"
51 #include "bits/oicon2"
52 #ifdef REGSTR
53 # define OMIT_ICON_BITS
54 # include "bits/icon"
55 #endif
56
57 #define CTRLWIDE 440 /* (fixed) size of control window */
58 #define CTRLHIGH 348 /* 379 */
59
60 #define DBLCLKTIME 500 /* double-click speed in milliseconds */
61
62 #define INACTIVE(lptr, item) ((lptr)->filetypes && (lptr)->dirsonly && \
63 (item) >= 0 && (item) < (lptr)->nstr && \
64 (lptr)->str[(item)][0] != C_DIR && \
65 (lptr)->str[(item)][0] != C_LNK)
66
67 #define NLINES 11 /* # of lines in list control (keep odd) */
68
69 #define BUTTW 71 /* keep odd for 'half' buttons to work */
70 #define BUTTH 24
71 #define SBUTTH 21
72
73 static int ptop; /* y-coord of top of button area in ctrlW */
74
75 static Pixmap fifoPix, chrPix, dirPix, blkPix, lnkPix, sockPix, exePix, regPix;
76 static Pixmap rotlPix, rotrPix, fliphPix, flipvPix, p10Pix, m10Pix;
77 static Pixmap cutPix, copyPix, pastePix, clearPix, oiconPix, uiconPix;
78 static Pixmap padPix, annotPix;
79
80 static XRectangle butrect;
81
82 /* NOTE: make these string arrays match up with their respective #defines
83 in xv.h */
84
85
86 static const char *dispMList[] = { "Raw\tr",
87 "Dithered\td",
88 "Smooth\ts",
89 MBSEP,
90 "Read/Write Colors",
91 MBSEP,
92 "Normal Colors",
93 "Perfect Colors",
94 "Use Own Colormap",
95 "Use Std. Colormap" };
96
97 static const char *rootMList[] = { "Window",
98 "Root: tiled",
99 "Root: integer tiled",
100 "Root: mirrored",
101 "Root: integer mirrored",
102 "Root: center tiled",
103 "Root: centered",
104 "Root: centered, warp",
105 "Root: centered, brick",
106 "Root: symmetrical tiled",
107 "Root: symmetrical mirrored",
108 "Root: upper left corner" };
109
110 static const char *conv24MList[] = { "8-bit mode\t\2448",
111 "24-bit mode\t\2448",
112 MBSEP,
113 "Lock current mode",
114 MBSEP,
115 "Quick 24->8",
116 "Slow 24->8",
117 "Best 24->8" };
118
119 static const char *algMList[] = { "Undo All\t\244u",
120 MBSEP,
121 "Blur...\t\244b",
122 "Sharpen...\t\244s",
123 "Edge Detect\t\244e",
124 "Emboss\t\244m",
125 "Oil Painting\t\244o",
126 "Blend\t\244B",
127 "Copy Rotate...\t\244t",
128 "Clear Rotate...\t\244T",
129 "Pixelize...\t\244p",
130 "Spread...\t\244S",
131 "DeSpeckle...\t\244k"};
132
133 static const char *sizeMList[] = { "Normal\tn",
134 "Max Size\tm",
135 "Maxpect\tM",
136 "Double Size\t>",
137 "Half Size\t<",
138 "10% Larger\t.",
139 "10% Smaller\t,",
140 MBSEP,
141 "Set Size\tS",
142 "Re-Aspect\ta",
143 "4x3\t4",
144 "Int. Expand\tI" };
145
146 static const char *windowMList[] = { "Visual Schnauzer\t^v",
147 "Color Editor\te",
148 "Image Info\ti",
149 "Image Comments\t^c",
150 "Text View\t^t",
151 MBSEP,
152 "About XV\t^a",
153 "XV Keyboard Help"};
154
155
156
157 static void drawSel PARM((LIST *, int));
158 static void RedrawNList PARM((int, SCRL *));
159 static void ls3d PARM((LIST *));
160
161
162 /***************************************************/
CreateCtrl(geom)163 void CreateCtrl(geom)
164 const char *geom;
165 {
166 int listh, topskip;
167 double skip;
168 XSetWindowAttributes xswa;
169 Pixmap oicon1Pix, oicon2Pix;
170
171 ctrlW = CreateWindow("xv controls", "XVcontrols", geom,
172 CTRLWIDE, CTRLHIGH, infofg, infobg, 0);
173 if (!ctrlW) FatalError("can't create controls window!");
174
175 #ifdef BACKING_STORE
176 xswa.backing_store = WhenMapped;
177 XChangeWindowAttributes(theDisp, ctrlW, CWBackingStore, &xswa);
178 #endif
179
180 grayTile = XCreatePixmapFromBitmapData(theDisp, rootW, (char *) gray25_bits,
181 gray25_width, gray25_height, infofg, infobg, dispDEEP);
182
183 dimStip = MakePix1(ctrlW, gray50_bits, gray50_width, gray50_height);
184 fifoPix = MakePix1(ctrlW, i_fifo_bits, i_fifo_width, i_fifo_height);
185 chrPix = MakePix1(ctrlW, i_chr_bits, i_chr_width, i_chr_height);
186 dirPix = MakePix1(ctrlW, i_dir_bits, i_dir_width, i_dir_height);
187 blkPix = MakePix1(ctrlW, i_blk_bits, i_blk_width, i_blk_height);
188 lnkPix = MakePix1(ctrlW, i_lnk_bits, i_lnk_width, i_lnk_height);
189 sockPix = MakePix1(ctrlW, i_sock_bits, i_sock_width, i_sock_height);
190 exePix = MakePix1(ctrlW, i_exe_bits, i_exe_width, i_exe_height);
191 regPix = MakePix1(ctrlW, i_reg_bits, i_reg_width, i_reg_height);
192 rotlPix = MakePix1(ctrlW, h_rotl_bits, h_rotl_width, h_rotl_height);
193 rotrPix = MakePix1(ctrlW, h_rotr_bits, h_rotr_width, h_rotr_height);
194 fliphPix = MakePix1(ctrlW, fliph_bits, fliph_width, fliph_height);
195 flipvPix = MakePix1(ctrlW, flipv_bits, flipv_width, flipv_height);
196 p10Pix = MakePix1(ctrlW, p10_bits, p10_width, p10_height);
197 m10Pix = MakePix1(ctrlW, m10_bits, m10_width, m10_height);
198 cutPix = MakePix1(ctrlW, cut_bits, cut_width, cut_height);
199 copyPix = MakePix1(ctrlW, copy_bits, copy_width, copy_height);
200 pastePix = MakePix1(ctrlW, paste_bits, paste_width, paste_height);
201 clearPix = MakePix1(ctrlW, clear_bits, clear_width, clear_height);
202 uiconPix = MakePix1(ctrlW, uicon_bits, uicon_width, uicon_height);
203 padPix = MakePix1(ctrlW, padimg_bits, padimg_width, padimg_height);
204 annotPix = MakePix1(ctrlW, annot_bits, annot_width, annot_height);
205
206 /* make multi-plane oiconPix pixmap */
207 oiconPix = XCreatePixmap(theDisp,rootW,oicon1_width,oicon1_height,dispDEEP);
208 oicon1Pix = MakePix1(ctrlW, oicon1_bits, oicon1_width, oicon1_height);
209 oicon2Pix = MakePix1(ctrlW, oicon2_bits, oicon2_width, oicon2_height);
210
211 if (!grayTile || !dimStip || !fifoPix || !chrPix || !dirPix ||
212 !blkPix || !lnkPix || !regPix || !rotlPix || !fliphPix ||
213 !flipvPix || !p10Pix || !m10Pix || !cutPix || !copyPix ||
214 !pastePix || !clearPix || !uiconPix || !oiconPix || !oicon1Pix ||
215 !oicon2Pix || !padPix || !annotPix)
216 FatalError("unable to create all pixmaps in CreateCtrl()\n");
217
218
219 /* build multi-color XV pixmap */
220 XSetForeground(theDisp, theGC, infobg);
221 XFillRectangle(theDisp, oiconPix, theGC, 0,0,oicon1_width,oicon1_height);
222 XSetFillStyle(theDisp, theGC, FillStippled);
223 XSetStipple(theDisp, theGC, oicon1Pix);
224 XSetForeground(theDisp, theGC, (ctrlColor) ? locol : infofg);
225 XFillRectangle(theDisp, oiconPix, theGC, 0,0,oicon1_width,oicon1_height);
226 XSetStipple(theDisp, theGC, oicon2Pix);
227 XSetForeground(theDisp, theGC, (ctrlColor) ? infofg : infofg);
228 XFillRectangle(theDisp, oiconPix, theGC, 0,0,oicon1_width,oicon1_height);
229 XSetFillStyle(theDisp, theGC, FillSolid);
230 XFreePixmap(theDisp, oicon1Pix);
231 XFreePixmap(theDisp, oicon2Pix);
232
233
234
235 if (ctrlColor) XSetWindowBackground(theDisp, ctrlW, locol);
236 else XSetWindowBackgroundPixmap(theDisp, ctrlW, grayTile);
237
238 listh = LINEHIGH * NLINES;
239
240 LSCreate(&nList, ctrlW, 5, 52, (CTRLWIDE-BUTTW-18),
241 LINEHIGH*NLINES, NLINES, dispnames, numnames,
242 infofg, infobg, hicol, locol, RedrawNList, 0, 0);
243 nList.selected = 0; /* default to first name selected */
244
245
246 #define BCLS infofg, infobg, hicol, locol
247
248 /* expressions for positioning right-side buttons */
249
250 topskip = nList.y;
251 skip = ((double) (nList.h - (CHIGH+5))) / 6.0;
252 if (skip > SBUTTH+8) {
253 skip = SBUTTH + 7;
254 topskip = nList.y + (nList.h - (6*skip + (CHIGH+5))) / 2;
255 }
256
257 #define R_BW1 BUTTW
258 #define R_BX0 (CTRLWIDE - R_BW1 - 1 - 5)
259 #define R_BY0 (topskip)
260 #define R_BY1 (topskip + (int)(1*skip))
261 #define R_BY2 (topskip + (int)(2*skip))
262 #define R_BY3 (topskip + (int)(3*skip))
263 #define R_BY4 (topskip + (int)(4*skip))
264 #define R_BY5 (topskip + (int)(5*skip))
265
266 BTCreate(&but[BNEXT], ctrlW, R_BX0, R_BY0, R_BW1, SBUTTH, "Next", BCLS);
267 BTCreate(&but[BPREV], ctrlW, R_BX0, R_BY1, R_BW1, SBUTTH, "Prev", BCLS);
268 BTCreate(&but[BLOAD], ctrlW, R_BX0, R_BY2, R_BW1, SBUTTH, "Load", BCLS);
269 BTCreate(&but[BSAVE], ctrlW, R_BX0, R_BY3, R_BW1, SBUTTH, "Save", BCLS);
270 BTCreate(&but[BPRINT], ctrlW, R_BX0, R_BY4, R_BW1, SBUTTH, "Print", BCLS);
271 BTCreate(&but[BDELETE], ctrlW, R_BX0, R_BY5, R_BW1, SBUTTH, "Delete", BCLS);
272
273
274 /* expressions for positioning bottom buttons (6x2 array) */
275
276 #define BXSPACE (BUTTW+1)
277 #define BYSPACE (BUTTH+1)
278
279 ptop = CTRLHIGH - (2*BYSPACE + 5 + 4);
280
281 #define BX0 ((CTRLWIDE - (BXSPACE*6))/2)
282 #define BX1 (BX0 + BXSPACE)
283 #define BX2 (BX0 + BXSPACE*2)
284 #define BX3 (BX0 + BXSPACE*3)
285 #define BX4 (BX0 + BXSPACE*4)
286 #define BX5 (BX0 + BXSPACE*5)
287 #define BY0 (ptop+5)
288 #define BY1 (BY0 + BYSPACE)
289
290 butrect.x = BX0-1; butrect.y = BY0-1;
291 butrect.width = 6*BXSPACE + 1;
292 butrect.height = 2*BYSPACE + 1;
293
294 BTCreate(&but[BCOPY], ctrlW,BX0, BY0,BUTTW/2,BUTTH, "", BCLS);
295 BTCreate(&but[BCUT], ctrlW,BX0+BUTTW/2 + 1,BY0,BUTTW/2,BUTTH, "", BCLS);
296 BTCreate(&but[BPASTE], ctrlW,BX1, BY0,BUTTW/2,BUTTH, "", BCLS);
297 BTCreate(&but[BCLEAR], ctrlW,BX1+BUTTW/2 + 1,BY0,BUTTW/2,BUTTH, "", BCLS);
298 BTCreate(&but[BDN10], ctrlW,BX2, BY0,BUTTW/2,BUTTH, "", BCLS);
299 BTCreate(&but[BUP10], ctrlW,BX2+BUTTW/2 + 1,BY0,BUTTW/2,BUTTH, "", BCLS);
300 BTCreate(&but[BROTL], ctrlW,BX3, BY0,BUTTW/2,BUTTH, "", BCLS);
301 BTCreate(&but[BROTR], ctrlW,BX3+BUTTW/2 + 1,BY0,BUTTW/2,BUTTH, "", BCLS);
302 BTCreate(&but[BFLIPH], ctrlW,BX4, BY0,BUTTW/2,BUTTH, "", BCLS);
303 BTCreate(&but[BFLIPV], ctrlW,BX4+BUTTW/2 + 1,BY0,BUTTW/2,BUTTH, "", BCLS);
304 BTCreate(&but[BGRAB], ctrlW,BX5, BY0,BUTTW, BUTTH, "Grab",BCLS);
305
306
307 BTCreate(&but[BPAD], ctrlW,BX0, BY1,BUTTW/2,BUTTH,"",BCLS);
308 BTCreate(&but[BANNOT], ctrlW,BX0+BUTTW/2+1,BY1,BUTTW/2,BUTTH,"",BCLS);
309
310 BTCreate(&but[BCROP], ctrlW,BX1, BY1,BUTTW,BUTTH,"Crop", BCLS);
311 BTCreate(&but[BUNCROP], ctrlW,BX2, BY1,BUTTW,BUTTH,"UnCrop", BCLS);
312 BTCreate(&but[BACROP], ctrlW,BX3, BY1,BUTTW,BUTTH,"AutoCrop",BCLS);
313 BTCreate(&but[BABOUT], ctrlW,BX4, BY1,BUTTW,BUTTH,"About XV",BCLS);
314 BTCreate(&but[BQUIT], ctrlW,BX5, BY1,BUTTW,BUTTH,"Quit", BCLS);
315
316 BTCreate(&but[BXV], ctrlW,5,5, 100, (u_int) nList.y - 5 - 2 - 5,
317 "", BCLS);
318
319 SetButtPix(&but[BCOPY], copyPix, copy_width, copy_height);
320 SetButtPix(&but[BCUT], cutPix, cut_width, cut_height);
321 SetButtPix(&but[BPASTE], pastePix, paste_width, paste_height);
322 SetButtPix(&but[BCLEAR], clearPix, clear_width, clear_height);
323 SetButtPix(&but[BUP10], p10Pix, p10_width, p10_height);
324 SetButtPix(&but[BDN10], m10Pix, m10_width, m10_height);
325 SetButtPix(&but[BROTL], rotlPix, h_rotl_width, h_rotl_height);
326 SetButtPix(&but[BROTR], rotrPix, h_rotr_width, h_rotr_height);
327 SetButtPix(&but[BFLIPH], fliphPix, fliph_width, fliph_height);
328 SetButtPix(&but[BFLIPV], flipvPix, flipv_width, flipv_height);
329 SetButtPix(&but[BPAD], padPix, padimg_width, padimg_height);
330 SetButtPix(&but[BANNOT], annotPix, annot_width, annot_height);
331
332 #ifdef REGSTR
333 if (ctrlColor) {
334 SetButtPix(&but[BXV], oiconPix, oicon1_width, oicon1_height);
335 but[BXV].colorpix = 1;
336 }
337 else SetButtPix(&but[BXV], iconPix, icon_width, icon_height);
338 #else
339 SetButtPix(&but[BXV], uiconPix, uicon_width, uicon_height);
340 #endif
341
342 XMapSubwindows(theDisp, ctrlW);
343
344
345 /* have to create menu buttons after XMapSubWindows, as we *don't* want
346 the popup menus mapped */
347
348 MBCreate(&dispMB, ctrlW, CTRLWIDE - 8 - 112 - 2*(112+2), 5,112,19,
349 "Display", dispMList, DMB_MAX, BCLS);
350 MBCreate(&conv24MB, ctrlW, CTRLWIDE - 8 - 112 - (112+2), 5,112,19,
351 "24/8 Bit", conv24MList, CONV24_MAX, BCLS);
352 MBCreate(&algMB, ctrlW, CTRLWIDE - 8 - 112, 5,112,19,
353 "Algorithms", algMList, ALG_MAX, BCLS);
354
355 MBCreate(&rootMB, ctrlW, CTRLWIDE - 8 - 112 - 2*(112+2), 5+21,112,19,
356 "Root", rootMList, RMB_MAX, BCLS);
357 MBCreate(&windowMB, ctrlW, CTRLWIDE - 8 - 112 - (112+2), 5+21,112,19,
358 "Windows", windowMList, WMB_MAX, BCLS);
359 MBCreate(&sizeMB, ctrlW, CTRLWIDE - 8 - 112, 5+21,112,19,
360 "Image Size", sizeMList, SZMB_MAX, BCLS);
361
362
363
364 #undef BCLS
365
366
367 /* set up initial state for various controls */
368
369 but[BXV].w = dispMB.x - 5 - but[BXV].x;
370
371 dispMB.flags[DMB_COLRW] = (allocMode == AM_READWRITE);
372 dispMB.flags[colorMapMode + DMB_COLNORM - CM_NORMAL] = 1;
373
374 conv24MB.flags[conv24] = 1;
375
376 if (!useroot) dispMode = RMB_WINDOW;
377 else dispMode = rootMode + (RMB_ROOT - RM_NORMAL);
378 rootMB.flags[dispMode] = 1;
379
380 windowMB.dim[WMB_TEXTVIEW] = (numnames<1);
381
382 BTSetActive(&but[BDELETE], (numnames>=1));
383 }
384
385 /***************************************************/
SetButtPix(bp,pix,w,h)386 void SetButtPix(bp, pix, w,h)
387 BUTT *bp;
388 Pixmap pix;
389 int w,h;
390 {
391 if (!bp) return;
392 bp->pix = pix; bp->pw = w; bp->ph = h;
393 }
394
395
396 /***************************************************/
MakePix1(win,bits,w,h)397 Pixmap MakePix1(win, bits, w, h)
398 Window win;
399 byte *bits;
400 int w,h;
401 {
402 return XCreatePixmapFromBitmapData(theDisp, win, (char *) bits,
403 (u_int) w, (u_int) h, 1L,0L,1);
404 }
405
406
407 /***************************************************/
CtrlBox(vis)408 void CtrlBox(vis)
409 int vis;
410 {
411 if (vis) XMapRaised(theDisp, ctrlW);
412 else XUnmapWindow(theDisp, ctrlW);
413
414 ctrlUp = vis;
415 }
416
417
418 /***************************************************/
RedrawCtrl(x,y,w,h)419 void RedrawCtrl(x,y,w,h)
420 int x,y,w,h;
421 {
422 int i;
423
424 RANGE(w, 0, CTRLWIDE);
425 RANGE(h, 0, CTRLHIGH);
426
427 #ifdef CLIPRECT
428 xr.x = x; xr.y = y; xr.width = w; xr.height = h;
429 XSetClipRectangles(theDisp, theGC, 0,0, &xr, 1, Unsorted);
430 #endif
431
432 DrawCtrlNumFiles();
433
434 XSetForeground(theDisp,theGC,infofg);
435 XDrawRectangles(theDisp, ctrlW, theGC, &butrect, 1);
436
437 for (i=0; i<NBUTTS; i++)
438 BTRedraw(&but[i]);
439
440 MBRedraw(&dispMB);
441 MBRedraw(&conv24MB);
442 MBRedraw(&algMB);
443 MBRedraw(&rootMB);
444 MBRedraw(&windowMB);
445 MBRedraw(&sizeMB);
446
447 DrawCtrlStr();
448
449 #ifdef CLIPRECT
450 XSetClipMask(theDisp, theGC, None);
451 #endif
452 }
453
454
455 /***************************************************/
DrawCtrlNumFiles()456 void DrawCtrlNumFiles()
457 {
458 int x,y,w;
459 char foo[40];
460
461 x = but[BNEXT].x;
462 y = nList.y + nList.h - (CHIGH+5);
463 w = but[BNEXT].w;
464
465 XSetForeground(theDisp, theGC, infofg);
466 XSetBackground(theDisp, theGC, infobg);
467
468 sprintf(foo, "%d file%s", numnames, (numnames==1) ? "" : "s");
469
470 XSetForeground(theDisp, theGC, infobg);
471 XFillRectangle(theDisp,ctrlW, theGC, x+1,y+1, (u_int) w-1, (u_int) CHIGH+5);
472
473 XSetForeground(theDisp,theGC,infofg);
474 XDrawRectangle(theDisp,ctrlW, theGC, x,y, (u_int) w, (u_int) CHIGH+6);
475
476 Draw3dRect(ctrlW, x+1,y+1, (u_int) w-2, (u_int) CHIGH+4,
477 R3D_IN, 2, hicol, locol, infobg);
478
479 XSetForeground(theDisp,theGC,infofg);
480 CenterString(ctrlW, x+w/2, y+(CHIGH+6)/2, foo);
481 }
482
483
484 /***************************************************/
DrawCtrlStr()485 void DrawCtrlStr()
486 {
487 int y;
488 char *st,*st1;
489
490 y = ptop - (CHIGH + 4)*2 - 2;
491 st = GetISTR(ISTR_INFO);
492 st1 = GetISTR(ISTR_WARNING);
493
494 XSetForeground(theDisp, theGC, infobg);
495 XFillRectangle(theDisp, ctrlW, theGC, 0, y+1,
496 CTRLWIDE, (u_int)((CHIGH+4)*2+1));
497
498 XSetForeground(theDisp, theGC, infofg);
499 XDrawLine(theDisp, ctrlW, theGC, 0, y, CTRLWIDE, y);
500 XDrawLine(theDisp, ctrlW, theGC, 0, y+CHIGH+4, CTRLWIDE, y+CHIGH+4);
501 XDrawLine(theDisp, ctrlW, theGC, 0, y+(CHIGH+4)*2, CTRLWIDE, y+(CHIGH+4)*2);
502
503 if (ctrlColor) {
504 XSetForeground(theDisp, theGC, locol);
505 XDrawLine(theDisp, ctrlW, theGC, 0, y+1, CTRLWIDE, y+1);
506 XDrawLine(theDisp, ctrlW, theGC, 0, y+CHIGH+5, CTRLWIDE, y+CHIGH+5);
507 XDrawLine(theDisp, ctrlW, theGC, 0, y+(CHIGH+4)*2+1,
508 CTRLWIDE, y+(CHIGH+4)*2+1);
509 }
510
511 if (ctrlColor) XSetForeground(theDisp, theGC, hicol);
512 XDrawLine(theDisp, ctrlW, theGC, 0, y+2, CTRLWIDE, y+2);
513 XDrawLine(theDisp, ctrlW, theGC, 0, y+CHIGH+6, CTRLWIDE, y+CHIGH+6);
514 if (ctrlColor) XSetForeground(theDisp, theGC, infobg);
515 XDrawLine(theDisp, ctrlW, theGC, 0, ptop, CTRLWIDE, ptop);
516
517 XSetForeground(theDisp, theGC, infofg);
518 DrawString(ctrlW, 10, y+ASCENT+3, st);
519 DrawString(ctrlW, 10, y+ASCENT+CHIGH+7, st1);
520 }
521
522
523 /***************************************************/
ClickCtrl(x,y)524 int ClickCtrl(x,y)
525 int x,y;
526 {
527 BUTT *bp;
528 int i;
529
530 for (i=0; i<NBUTTS; i++) {
531 bp = &but[i];
532 if (PTINRECT(x, y, bp->x, bp->y, bp->w, bp->h)) break;
533 }
534
535 if (i<NBUTTS) { /* found one */
536 if (BTTrack(bp)) return (i); /* and it was clicked */
537 }
538
539 return -1;
540 }
541
542
543
544 /***************************************************/
ScrollToCurrent(lst)545 void ScrollToCurrent(lst)
546 LIST *lst;
547 {
548 /* called when selected item on list is changed. Makes the selected
549 item visible. If it already is, nothing happens. Otherwise, it
550 attempts to scroll so that the selection appears in the middle of
551 the list window */
552
553 int halfway;
554
555 if (lst->selected < 0) return; /* no selection, do nothing */
556
557 if (lst->selected > lst->scrl.val &&
558 lst->selected < lst->scrl.val + lst->nlines-1) LSRedraw(lst, 0);
559 else {
560 halfway = (lst->nlines)/2; /* offset to the halfway pt. of the list */
561 if (!SCSetVal(&lst->scrl, lst->selected - halfway)) LSRedraw(lst, 0);
562 }
563 }
564
565
566 /***************************************************/
RedrawNList(delta,sptr)567 static void RedrawNList(delta, sptr)
568 int delta;
569 SCRL *sptr;
570 {
571 LSRedraw(&nList, delta);
572 }
573
574
575
576
577 /***************** LIST STUFF *********************/
578
579 /***************************************************/
LSCreate(lp,win,x,y,w,h,nlines,strlist,nstr,fg,bg,hi,lo,fptr,typ,donly)580 void LSCreate(lp, win, x, y, w, h, nlines, strlist, nstr, fg, bg, hi, lo,
581 fptr, typ, donly)
582 LIST *lp;
583 Window win;
584 int x,y,w,h,nlines,nstr,typ,donly;
585 unsigned long fg, bg, hi, lo;
586 char **strlist; /* a pointer to a list of strings */
587
588 void (*fptr)PARM((int,SCRL *));
589
590 {
591 if (ctrlColor) h += 4;
592
593 lp->win = XCreateSimpleWindow(theDisp,win,x,y,(u_int) w, (u_int) h,1,fg,bg);
594 if (!lp->win) FatalError("can't create list window!");
595
596 lp->x = x; lp->y = y;
597 lp->w = w; lp->h = h;
598 lp->fg = fg; lp->bg = bg;
599 lp->hi = hi; lp->lo = lo;
600 lp->str = strlist;
601 lp->nstr = nstr;
602 lp->selected = -1; /* no initial selection */
603 lp->nlines = nlines;
604 lp->filetypes= typ;
605 lp->dirsonly = donly;
606
607 XSelectInput(theDisp, lp->win, ExposureMask | ButtonPressMask);
608
609 SCCreate(&lp->scrl, lp->win, w-20, -1, 1, h, 0,
610 nstr-nlines, 0, nlines-1, fg, bg, hi, lo, fptr);
611
612 XMapSubwindows(theDisp, lp->win);
613 }
614
615
616
617 /***************************************************/
LSChangeData(lp,strlist,nstr)618 void LSChangeData(lp, strlist, nstr)
619 LIST *lp;
620 char **strlist;
621 int nstr;
622 {
623 /* tries to keep list selection and scrollbar in same place, if possible */
624
625 lp->str = strlist;
626 lp->nstr = nstr;
627 if (lp->selected >= nstr) lp->selected = -1;
628
629 RANGE(lp->scrl.val, 0, nstr - lp->nlines);
630 SCSetRange(&lp->scrl, 0, nstr - lp->nlines, lp->scrl.val, lp->nlines-1);
631 }
632
633
634 /***************************************************/
LSNewData(lp,strlist,nstr)635 void LSNewData(lp, strlist, nstr)
636 LIST *lp;
637 char **strlist;
638 int nstr;
639 {
640 lp->str = strlist;
641 lp->nstr = nstr;
642 lp->selected = -1; /* no initial selection */
643 SCSetRange(&lp->scrl, 0, nstr - lp->nlines, 0, lp->nlines-1);
644 }
645
646
647 /***************************************************/
ls3d(lp)648 static void ls3d(lp)
649 LIST *lp;
650 {
651 /* redraws lists 3d-effect, which can be trounced by drawSel() */
652 Draw3dRect(lp->win, 0, 0, lp->w-1, lp->h-1, R3D_IN, 2,
653 lp->hi, lp->lo, lp->bg);
654 }
655
656
657 /***************************************************/
drawSel(lp,j)658 static void drawSel(lp,j)
659 LIST *lp;
660 int j;
661 {
662 int i, inactive, x0,y0,wide, selected;
663 unsigned long fg, bg;
664
665 x0 = 0; y0 = 0; wide = lp->w;
666 if (ctrlColor) { x0 = y0 = 2; wide -= 6; }
667
668 inactive = INACTIVE(lp,j);
669
670 i = j - lp->scrl.val;
671 if (i<0 || i>=lp->nlines) return; /* off screen */
672
673 selected = (j == lp->selected && !inactive && j<lp->nstr);
674 if (selected) { /* inverse colors */
675 if (ctrlColor) { fg = lp->fg; bg = lp->lo; }
676 else { fg = lp->bg; bg = lp->fg; }
677 }
678 else { fg = lp->fg; bg = lp->bg; }
679
680 XSetForeground(theDisp, theGC, bg);
681 XFillRectangle(theDisp, lp->win, theGC, x0, y0+i*LINEHIGH,
682 (u_int) wide+1, (u_int) LINEHIGH);
683
684 if (j>=0 && j<lp->nstr) { /* only draw string if valid */
685 XSetForeground(theDisp, theGC, fg);
686 XSetBackground(theDisp, theGC, bg);
687
688 if (!lp->filetypes)
689 DrawString(lp->win, x0+3, y0+i*LINEHIGH + ASCENT + 1, lp->str[j]);
690 else {
691 int ypos = y0 + i*LINEHIGH + (LINEHIGH - i_fifo_height)/2;
692
693 if (lp->str[j][0] == C_FIFO)
694 XCopyPlane(theDisp, fifoPix, lp->win, theGC, 0, 0,
695 i_fifo_width, i_fifo_height, x0+3, ypos, 1L);
696
697 else if (lp->str[j][0] == C_CHR)
698 XCopyPlane(theDisp, chrPix, lp->win, theGC, 0, 0,
699 i_chr_width, i_chr_height, x0+3, ypos, 1L);
700
701 else if (lp->str[j][0] == C_DIR)
702 XCopyPlane(theDisp, dirPix, lp->win, theGC, 0, 0,
703 i_dir_width, i_dir_height, x0+3, ypos, 1L);
704
705 else if (lp->str[j][0] == C_BLK)
706 XCopyPlane(theDisp, blkPix, lp->win, theGC, 0, 0,
707 i_blk_width, i_blk_height, x0+3, ypos, 1L);
708
709 else if (lp->str[j][0] == C_LNK)
710 XCopyPlane(theDisp, lnkPix, lp->win, theGC, 0, 0,
711 i_lnk_width, i_lnk_height, x0+3, ypos, 1L);
712
713 else if (lp->str[j][0] == C_SOCK)
714 XCopyPlane(theDisp, sockPix, lp->win, theGC, 0, 0,
715 i_sock_width, i_sock_height, x0+3, ypos, 1L);
716
717 else if (lp->str[j][0] == C_EXE)
718 XCopyPlane(theDisp, exePix, lp->win, theGC, 0, 0,
719 i_exe_width, i_exe_height, x0+3, ypos, 1L);
720
721 else /* lp->str[j][0] == C_REG */
722 XCopyPlane(theDisp, regPix, lp->win, theGC, 0, 0,
723 i_reg_width, i_reg_height, x0+3, ypos, 1L);
724
725
726 DrawString(lp->win, x0+3 + i_fifo_width + 3,
727 y0+i*LINEHIGH + ASCENT + 1,
728 lp->str[j]+1);
729 }
730 }
731 }
732
733
734 /***************************************************/
LSRedraw(lp,delta)735 void LSRedraw(lp, delta)
736 LIST *lp;
737 int delta;
738 {
739 int i;
740
741 for (i = lp->scrl.val; i < lp->scrl.val + lp->nlines; i++)
742 drawSel(lp,i);
743 ls3d(lp);
744 }
745
746
747 /***************************************************/
LSClick(lp,ev)748 int LSClick(lp,ev)
749 LIST *lp;
750 XButtonEvent *ev;
751 {
752 /* returns '-1' normally. returns 0 -> numnames-1 for a goto */
753
754 Window rW, cW;
755 int rx, ry, x, y, sel, oldsel, y0, high;
756 unsigned int mask;
757 static Time lasttime=0;
758 static int lastsel = -1;
759
760 y0 = (ctrlColor) ? 2 : 0;
761 high = (ctrlColor) ? lp->h - 4 : lp->h;
762
763 x = ev->x; y = ev->y;
764 sel = lp->scrl.val + (y-y0)/LINEHIGH;
765 if (sel >= lp->nstr) sel = lp->selected;
766
767 /* see if it's a double click */
768 if (ev->time - lasttime < DBLCLKTIME && sel==lastsel
769 && (lp->scrl.val + (y-y0)/LINEHIGH) < lp->nstr
770 && !INACTIVE(lp,sel)) {
771 return (sel);
772 }
773
774 lasttime = ev->time; lastsel = sel;
775
776 /* if not clicked on selected, turn off selected and select new one */
777 if (sel != lp->selected) {
778 oldsel = lp->selected;
779 lp->selected = sel;
780 drawSel(lp,sel); drawSel(lp,oldsel);
781 ls3d(lp);
782 XFlush(theDisp);
783 }
784
785 while (XQueryPointer(theDisp,lp->win,&rW,&cW,&rx,&ry,&x,&y,&mask)) {
786 if (!(mask & Button1Mask)) break; /* button released */
787
788 if (y<y0) { /* scroll up in list */
789 if (lp->scrl.val > lp->scrl.min) {
790 lp->selected = lp->scrl.val - 1;
791 SCSetVal(&lp->scrl, lp->scrl.val - 1);
792 Timer(100);
793 }
794 }
795
796 else if (y>high) { /* scroll down in list */
797 if (lp->scrl.val < lp->scrl.max) {
798 lp->selected = lp->scrl.val + lp->nlines;
799 if (lp->selected >= lp->nstr) lp->selected = lp->nstr - 1;
800 SCSetVal(&lp->scrl, lp->scrl.val + 1);
801 Timer(100);
802 }
803 }
804
805 else {
806 sel = lp->scrl.val + (y-y0)/LINEHIGH;
807 if (sel >= lp->nstr) sel = lp->nstr - 1;
808
809 if (sel != lp->selected && sel >= lp->scrl.val &&
810 sel < lp->scrl.val + lp->nlines) {
811 /* dragged to another on current page */
812 oldsel = lp->selected;
813 lp->selected = sel;
814 drawSel(lp, sel); drawSel(lp, oldsel);
815 ls3d(lp);
816 XFlush(theDisp);
817 }
818 }
819 }
820
821 return(-1);
822 }
823
824
825
826 /***************************************************/
LSKey(lp,key)827 void LSKey(lp, key)
828 LIST *lp;
829 int key;
830 {
831 if (key==LS_PAGEUP) SCSetVal(&lp->scrl,lp->scrl.val - (lp->nlines-1));
832 else if (key==LS_PAGEDOWN) SCSetVal(&lp->scrl,lp->scrl.val + (lp->nlines-1));
833 else if (key==LS_HOME) SCSetVal(&lp->scrl,lp->scrl.min);
834 else if (key==LS_END) SCSetVal(&lp->scrl,lp->scrl.max);
835
836 else if (key==LS_LINEUP) {
837 /* if the selected item visible, but not the top line */
838 if (lp->selected > lp->scrl.val &&
839 lp->selected <= lp->scrl.val + lp->nlines - 1) {
840 /* then just move it */
841 lp->selected--;
842 drawSel(lp, lp->selected); drawSel(lp, lp->selected+1);
843 ls3d(lp);
844 }
845
846 /* if it's the top line... */
847 else if (lp->selected == lp->scrl.val) {
848 if (lp->selected > 0) {
849 lp->selected--;
850 SCSetVal(&lp->scrl, lp->selected);
851 }
852 }
853
854 /* if it's not visible, put it on the bottom line */
855 else {
856 lp->selected = lp->scrl.val + lp->nlines - 1;
857 if (lp->selected >= lp->nstr) lp->selected = lp->nstr - 1;
858 drawSel(lp, lp->selected);
859 ls3d(lp);
860 }
861 }
862
863 else if (key==LS_LINEDOWN) {
864 /* if the selected item visible, but not the bottom line */
865 if (lp->selected >= lp->scrl.val &&
866 lp->selected < lp->scrl.val + lp->nlines - 1) {
867 if (lp->selected < lp->nstr-1) {
868 /* then just move it */
869 lp->selected++;
870 drawSel(lp, lp->selected); drawSel(lp, lp->selected-1);
871 ls3d(lp);
872 }
873 }
874
875 /* if it's the bottom line... */
876 else if (lp->selected == lp->scrl.val + lp->nlines - 1) {
877 if (lp->selected < lp->nstr-1) {
878 lp->selected++;
879 SCSetVal(&lp->scrl, lp->scrl.val+1);
880 }
881 }
882
883 /* if it's not visible, put it on the top line */
884 else {
885 lp->selected = lp->scrl.val;
886 drawSel(lp, lp->selected);
887 ls3d(lp);
888 }
889 }
890 }
891
892