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/choose.c,v 1.11 2011/05/16 16:21:56 william Exp $
19 */
20
21 #define _INCLUDE_FROM_CHOOSE_C_
22
23 #include "tgifdefs.h"
24
25 #include "auxtext.e"
26 #include "button.e"
27 #include "choose.e"
28 #include "cutpaste.e"
29 #include "cursor.e"
30 #include "dialog.e"
31 #include "drawing.e"
32 #include "file.e"
33 #include "font.e"
34 #include "mainloop.e"
35 #include "mainmenu.e"
36 #include "menu.e"
37 #include "msg.e"
38 #include "names.e"
39 #include "raster.e"
40 #include "rect.e"
41 #include "remote.e"
42 #include "ruler.e"
43 #include "scroll.e"
44 #include "setup.e"
45 #include "strtbl.e"
46 #include "util.e"
47
48 GC nameGC=(GC)0, revNameGC=(GC)0;
49
50 typedef struct NamesRec {
51 Window base_win, dsp_base_win, dsp_win, scroll_win;
52 int base_win_w, base_win_h;
53 int dsp_base_win_w, dsp_base_win_h;
54 int dsp_area_w, dsp_area_h, scroll_area_h;
55
56 char **entries;
57 int num_entries;
58 int first_index;
59 int marked_index;
60 int num_btns;
61 struct BBRec btn_bbox[MAXBUTTONS], path_bbox;
62 char btn_str[MAXBUTTONS][40];
63 int btn_id[MAXBUTTONS];
64
65 char inbuf[512];
66 int buf_index, just_clicked, scroll_dir;
67
68 DspList *dsp_ptr;
69 char *title_str, *formatted_title_str;
70
71 struct CheckArrayRec *p_check_array;
72
73 int title_w, title_h, title_num_lines;
74 int a_btn_w, graph_w, btn_start, title_start, graph_start;
75 int btn_w, btn_gap, btn_selected, exposed, screen_w, screen_h;
76 int edit_style, loop_once, dont_free_entries, leading;
77
78 int change_to_root, pop_from_root, faking_dot_dot;
79 int tabbed_from_root, just_tabbed_from_root;
80 int def_btn_id, double_click_btn_id;
81
82 GetEntriesFunc *pf_before_loop;
83 AfterLoopFunc *pf_after_loop;
84 CheckUpdateFunc *pf_check_update; /* called when a checkbox changes state */
85
86 /* used only when edit_style== NAMES_SELECT_FILE */
87 char dir_name[MAXPATHLENGTH+1], saved_dir_name[MAXPATHLENGTH+1];
88 char name[MAXPATHLENGTH+1], saved_name[MAXPATHLENGTH+1];
89 int name_index, remote_file;
90
91 void *userdata;
92 } *NamesRecPtr;
93
94 static struct NamesRec namesInfo;
95
96 static XComposeStatus c_stat;
97
GetWorkingDirectory(buf,buf_sz)98 int GetWorkingDirectory(buf, buf_sz)
99 char *buf;
100 int buf_sz;
101 {
102 char *psz_result=NULL;
103
104 #ifdef VMS
105 psz_result = getcwd(buf, buf_sz, 0);
106 #else /* ~VMS */
107 #ifdef ibm
108 psz_result = getwd(buf, buf_sz);
109 #else /* ~ibm */
110 #ifdef NeXT
111 psz_result = getwd(buf, buf_sz);
112 #else /* ~NeXT */
113 #ifdef luna88k
114 psz_result = getwd(buf);
115 #else /* ~luna88k */
116 #ifdef sequent
117 psz_result = getwd(buf);
118 #else /* ~sequent */
119 psz_result = getcwd(buf, buf_sz);
120 #endif /* sequent */
121 #endif /* luna88k */
122 #endif /* NeXT */
123 #endif /* ibm */
124 #endif /* VMS */
125 if (psz_result == NULL) {
126 UtilStrCpyN(buf, buf_sz, ".");
127 return FALSE;
128 }
129 return TRUE;
130 }
131
SetWorkingDirectory(dir)132 int SetWorkingDirectory(dir)
133 char *dir;
134 {
135 return (chdir(dir) == 0);
136 }
137
138 static
CalcBaseWinWidth(pni)139 void CalcBaseWinWidth(pni)
140 struct NamesRec *pni;
141 {
142 int max_w=max(pni->graph_w,pni->btn_w);
143
144 pni->base_win_w = max_w + (defaultFontWidth<<2);
145 pni->graph_start = ((pni->base_win_w-pni->graph_w)>>1);
146 if (pni->title_num_lines <= 1) {
147 pni->title_start = ((pni->base_win_w-pni->title_w)>>1);
148 } else {
149 pni->title_start = pni->graph_start;
150 }
151 pni->btn_start = ((pni->base_win_w-pni->btn_w)>>1);
152
153 pni->path_bbox.ltx = pni->graph_start;
154 pni->path_bbox.lty = (ROW_HEIGHT<<1)+pni->title_h;
155 /* the path_bbox needs 2 pixels around it */
156 pni->path_bbox.lty -= 2;
157 pni->path_bbox.rbx = pni->path_bbox.ltx + ITEM_LEN*defaultFontWidth+6;
158 pni->path_bbox.rby = pni->path_bbox.lty +
159 ((msgFontSet==NULL && msgFontPtr==NULL) ? defaultFontHeight :
160 msgFontHeight)+1+4;
161 if (boldMsgFontSet == NULL && boldMsgFontPtr == NULL) {
162 pni->base_win_h = (7+ITEM_DSPED)*ROW_HEIGHT + pni->title_h;
163 } else {
164 pni->base_win_h = (6+ITEM_DSPED)*ROW_HEIGHT + boldMsgFontHeight + 1 +
165 pni->title_h;
166 }
167 }
168
CleanUpCheckArray(pCheckArray)169 void CleanUpCheckArray(pCheckArray)
170 /* Does not free pCheckArray */
171 struct CheckArrayRec *pCheckArray;
172 {
173 int i, num_cols=pCheckArray->num_cols;
174
175 if (pCheckArray->col_name != NULL) {
176 /* there's an extra one column here! */
177 for (i=0; i <= num_cols; i++) {
178 if (pCheckArray->col_name[i] != NULL) {
179 UtilFree(pCheckArray->col_name[i]);
180 }
181 }
182 free(pCheckArray->col_name);
183 }
184 if (pCheckArray->value != NULL) {
185 for (i=0; i < num_cols; i++) {
186 if (pCheckArray->value[i] != NULL) {
187 free(pCheckArray->value[i]);
188 }
189 }
190 free(pCheckArray->value);
191 }
192 memset(pCheckArray, 0, sizeof(struct CheckArrayRec));
193 }
194
CopyCheckArray(pCheckArrayTo,pCheckArrayFrom)195 int CopyCheckArray(pCheckArrayTo, pCheckArrayFrom)
196 struct CheckArrayRec *pCheckArrayTo, *pCheckArrayFrom;
197 {
198 int i;
199 int num_cols=pCheckArrayFrom->num_cols, num_rows=pCheckArrayFrom->num_rows;
200
201 memset(pCheckArrayTo, 0, sizeof(struct CheckArrayRec));
202 pCheckArrayTo->num_cols = num_cols;
203 pCheckArrayTo->num_rows = num_rows;
204 if (pCheckArrayFrom->col_name != NULL) {
205 /* there's an extra one column here! */
206 pCheckArrayTo->col_name = (char**)malloc((num_cols+1)*sizeof(char*));
207 if (pCheckArrayTo->col_name == NULL) FailAllocMessage();
208 memset(pCheckArrayTo->col_name, 0, (num_cols+1)*sizeof(char*));
209
210 for (i=0; i <= num_cols; i++) {
211 if (pCheckArrayFrom->col_name[i] != NULL) {
212 pCheckArrayTo->col_name[i] =
213 UtilStrDup(pCheckArrayFrom->col_name[i]);
214 if (pCheckArrayTo->col_name[i] == NULL) FailAllocMessage();
215 }
216 }
217 }
218 if (pCheckArrayFrom->value != NULL) {
219 pCheckArrayTo->value = (int**)malloc(num_cols*sizeof(int*));
220 if (pCheckArrayTo->value == NULL) FailAllocMessage();
221 memset(pCheckArrayTo->value, 0, num_cols*sizeof(int*));
222
223 for (i=0; i < num_cols; i++) {
224 if (pCheckArrayFrom->value[i] != NULL) {
225 pCheckArrayTo->value[i] = (int*)malloc(num_rows*sizeof(int));
226 if (pCheckArrayTo->value[i] == NULL) FailAllocMessage();
227 memcpy(pCheckArrayTo->value[i], pCheckArrayFrom->value[i],
228 num_rows*sizeof(int));
229 }
230 }
231 }
232 return TRUE;
233 }
234
NamesSetTitle(title_str)235 void NamesSetTitle(title_str)
236 char *title_str;
237 {
238 struct NamesRec *pni=(&namesInfo);
239
240 if (pni->title_str != NULL) free(pni->title_str);
241 if (pni->formatted_title_str != NULL) free(pni->formatted_title_str);
242 pni->formatted_title_str = NULL;
243 pni->title_str = UtilStrDup(title_str);
244 if (pni->title_str == NULL) FailAllocMessage();
245
246 if (boldMsgFontSet == NULL && boldMsgFontPtr == NULL) {
247 CalcFormatStringInBox(pni->title_str, defaultFontPtr, defaultFontHeight,
248 pni->graph_w, &pni->title_num_lines, &pni->title_w, &pni->title_h,
249 &pni->formatted_title_str);
250 } else {
251 CalcFormatStringInBox(pni->title_str, boldMsgFontPtr, boldMsgFontHeight,
252 pni->graph_w, &pni->title_num_lines, &pni->title_w, &pni->title_h,
253 &pni->formatted_title_str);
254 }
255 CalcBaseWinWidth(pni);
256 }
257
ResetNamesInfo()258 void ResetNamesInfo()
259 {
260 struct NamesRec *pni=(&namesInfo);
261
262 if (pni->title_str != NULL) {
263 free(pni->title_str);
264 pni->title_str = NULL;
265 }
266 if (pni->formatted_title_str != NULL) {
267 free(pni->formatted_title_str);
268 pni->formatted_title_str = NULL;
269 }
270 if (!pni->dont_free_entries) {
271 if (pni->dsp_ptr != NULL) {
272 free(pni->dsp_ptr);
273 pni->dsp_ptr = NULL;
274 }
275 if (pni->entries != NULL) {
276 free(*(pni->entries));
277 free(pni->entries);
278 pni->entries = NULL;
279 }
280 }
281
282 memset(&namesInfo, 0, sizeof(struct NamesRec));
283
284 pni->num_entries = INVALID;
285 pni->first_index = INVALID;
286 pni->marked_index = INVALID;
287 /* do not translate -- the string is used to measure things */
288 pni->a_btn_w = ButtonWidth("OK", 8, NULL);
289 pni->btn_gap = defaultFontWidth;
290 pni->screen_w = DisplayWidth(mainDisplay, mainScreen);
291 pni->screen_h = DisplayHeight(mainDisplay, mainScreen);
292 pni->dsp_area_w = ITEM_LEN * defaultFontWidth;
293 pni->dsp_area_h = ITEM_DSPED * ROW_HEIGHT;
294 pni->scroll_area_h = pni->dsp_area_h;
295 pni->dsp_base_win_w = pni->dsp_area_w + scrollBarW + (windowPadding<<1) +
296 (brdrW<<2);
297 pni->dsp_base_win_h = pni->dsp_area_h + (windowPadding<<1) + (brdrW<<1);
298 pni->graph_w = pni->dsp_area_w + scrollBarW + (brdrW<<2);
299 NamesSetTitle("");
300 if (boldMsgFontSet == NULL && boldMsgFontPtr == NULL) {
301 pni->base_win_h = (8+ITEM_DSPED)*ROW_HEIGHT;
302 } else {
303 pni->base_win_h = (6+ITEM_DSPED)*ROW_HEIGHT + 2*(boldMsgFontHeight+1);
304 }
305 pni->def_btn_id = BUTTON_OK;
306 pni->double_click_btn_id = BUTTON_OK;
307 pni->tabbed_from_root = TRUE;
308 }
309
InitNamesInfo()310 void InitNamesInfo()
311 {
312 XGCValues values;
313
314 memset(&namesInfo, 0, sizeof(struct NamesRec));
315
316 values.foreground = myFgPixel;
317 values.background = (threeDLook ? myLtGryPixel : myBgPixel);
318 values.fill_style = FillSolid;
319 if (msgFontPtr == NULL) {
320 values.font = defaultFontPtr->fid;
321 } else {
322 values.font = msgFontPtr->fid;
323 }
324 nameGC = XCreateGC(mainDisplay, rootWindow,
325 GCForeground | GCBackground | GCFillStyle | GCFont, &values);
326
327 values.foreground = myBgPixel;
328 values.background = myFgPixel;
329 revNameGC = XCreateGC(mainDisplay, rootWindow,
330 GCForeground | GCBackground | GCFillStyle | GCFont, &values);
331 }
332
CleanUpNamesInfo()333 void CleanUpNamesInfo()
334 {
335 struct NamesRec *pni=(&namesInfo);
336
337 ResetNamesInfo();
338 if (pni->title_str != NULL) free(pni->title_str);
339 pni->title_str = NULL;
340 if (pni->formatted_title_str != NULL) free(pni->formatted_title_str);
341 pni->formatted_title_str = NULL;
342 XFreeGC(mainDisplay, nameGC);
343 XFreeGC(mainDisplay, revNameGC);
344 nameGC = revNameGC = (GC)0;
345 }
346
NamesAddButton(btn_str,btn_id)347 void NamesAddButton(btn_str, btn_id)
348 char *btn_str;
349 int btn_id;
350 {
351 struct NamesRec *pni=(&namesInfo);
352
353 pni->btn_id[pni->num_btns] = btn_id;
354 strcpy(pni->btn_str[pni->num_btns], btn_str);
355 pni->btn_w += ButtonWidth(btn_str, 8, NULL);
356 if (pni->num_btns != 0) {
357 pni->btn_w += pni->btn_gap;
358 }
359 pni->num_btns++;
360 if (pni->num_btns > MAXBUTTONS) {
361 #ifdef _TGIF_DBG /* debug, do not translate */
362 TgAssert(FALSE,
363 "Too many buttons detected in NamesAddButton().", NULL);
364 #endif /* _TGIF_DBG */
365 }
366 CalcBaseWinWidth(pni);
367 }
368
369 static
RedrawNameScrollWin()370 void RedrawNameScrollWin()
371 {
372 struct NamesRec *pni=(&namesInfo);
373 double frac, start_frac;
374 int block_h, block_start;
375
376 start_frac = (pni->num_entries > 0) ?
377 (double)((double)(pni->first_index) /
378 (double)(pni->num_entries)) : ((double)0.0);
379 /* starting pixel */
380 block_start = (int)(pni->scroll_area_h * start_frac);
381
382 if (pni->num_entries > ITEM_DSPED) {
383 frac = (double)((double)ITEM_DSPED / (double)(pni->num_entries));
384 } else {
385 frac = 1.0;
386 }
387 if (pni->first_index+ITEM_DSPED >= pni->num_entries) {
388 block_h = pni->scroll_area_h - block_start;
389 } else {
390 block_h = (int)(pni->scroll_area_h * frac);
391 }
392 TgDrawScrollBar(mainDisplay, pni->scroll_win, VERT_SCROLLBAR,
393 0, 0, scrollBarW, pni->scroll_area_h, start_frac, ITEM_DSPED,
394 pni->num_entries);
395 }
396
397 #include "xbm/check.xbm"
398
DrawCheckbox(dpy,win,gc,x,y,w,h,checked)399 void DrawCheckbox(dpy, win, gc, x, y, w, h, checked)
400 Display *dpy;
401 Window win;
402 GC gc;
403 int x, y, w, h, checked;
404 {
405 if (threeDLook) {
406 struct BBRec bbox;
407
408 SetBBRec(&bbox, x, y, x+w+1, y+h+1);
409 TgDrawThreeDButton(dpy, win, textMenuGC, &bbox, TGBS_LOWRED, 2, FALSE);
410 } else {
411 XDrawRectangle(dpy, win, gc, x, y, w, h);
412 }
413 if (checked) {
414 if (threeDLook) {
415 XGCValues values;
416
417 values.fill_style = FillStippled;
418 values.stipple = checkBitmap;
419 values.ts_x_origin = x+2;
420 values.ts_y_origin = y+2;
421 XChangeGC(dpy, gc,
422 GCFillStyle | GCStipple | GCTileStipXOrigin | GCTileStipYOrigin,
423 &values);
424 XFillRectangle(dpy, win, gc, values.ts_x_origin,
425 values.ts_y_origin, check_width, check_height);
426 values.fill_style = FillSolid;
427 values.ts_x_origin = 0;
428 values.ts_y_origin = 0;
429 XChangeGC(dpy, gc,
430 GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin, &values);
431 } else {
432 XDrawLine(dpy, win, gc, x, y, x+w, y+h);
433 XDrawLine(dpy, win, gc, x, y+h, x+w, y);
434 }
435 }
436 if (check_bits == NULL) { }
437 }
438
439 static
RedrawItem(pni,index)440 void RedrawItem(pni, index)
441 struct NamesRec *pni;
442 int index;
443 {
444 int len=0, top=0, end=0, checkbox_cols=0, text_left=0, box_offset=0, box_w=0;
445 int selected=(index==pni->marked_index);
446
447 if ((msgFontSet==NULL && msgFontPtr==NULL)) {
448 top = defaultFontAsc+1;
449 } else {
450 top = msgFontAsc+1;
451 }
452 if (pni->first_index+ITEM_DSPED > pni->num_entries) {
453 end = pni->num_entries;
454 } else {
455 end = pni->first_index + ITEM_DSPED;
456 }
457 if (pni->p_check_array != NULL && pni->p_check_array->num_cols > 0) {
458 checkbox_cols = pni->p_check_array->num_cols;
459 text_left = checkbox_cols*ROW_HEIGHT;
460 box_offset = 1;
461 box_w = (ROW_HEIGHT-((box_offset+1)<<1));
462 }
463 len = strlen(pni->entries[index]);
464 XFillRectangle(mainDisplay, pni->dsp_win,
465 (selected ? nameGC : revNameGC), 0,
466 (index-pni->first_index)*ROW_HEIGHT, ITEM_LEN*defaultFontWidth,
467 ROW_HEIGHT);
468 DrawMsgString(mainDisplay, pni->dsp_win,
469 (selected ? revNameGC : nameGC), text_left,
470 (index-pni->first_index)*ROW_HEIGHT+top, pni->entries[index], len);
471 if (checkbox_cols > 0) {
472 int col=0, cur_x=0;
473
474 for (col=0; col < pni->p_check_array->num_cols; col++) {
475 DrawCheckbox(mainDisplay, pni->dsp_win,
476 (selected ? revNameGC : nameGC), cur_x+box_offset,
477 (index-pni->first_index)*ROW_HEIGHT+top-box_w,
478 box_w, box_w, pni->p_check_array->value[col][index]);
479 cur_x += ROW_HEIGHT;
480 }
481 }
482 }
483
484 static
RedrawDspWindow()485 void RedrawDspWindow()
486 {
487 struct NamesRec *pni=(&namesInfo);
488 int i, end=0;
489
490 if (pni->first_index+ITEM_DSPED > pni->num_entries) {
491 end = pni->num_entries;
492 } else {
493 end = pni->first_index + ITEM_DSPED;
494 }
495 XFillRectangle(mainDisplay, pni->dsp_win, revNameGC, 0, 0,
496 ITEM_LEN*defaultFontWidth, ITEM_DSPED*ROW_HEIGHT);
497
498 for (i=pni->first_index; i < end; i++) {
499 RedrawItem(pni, i);
500 }
501 }
502
503 static
RedrawDspBaseWindow()504 void RedrawDspBaseWindow()
505 {
506 if (threeDLook) {
507 struct NamesRec *pni=(&namesInfo);
508 struct BBRec bbox;
509
510 SetBBRec(&bbox, 0, 0, pni->dsp_base_win_w, pni->dsp_base_win_h);
511 TgDrawThreeDButton(mainDisplay, pni->dsp_base_win, textMenuGC, &bbox,
512 TGBS_LOWRED, 2, FALSE);
513 }
514 }
515
516 static
RedrawNamePath()517 void RedrawNamePath()
518 {
519 struct NamesRec *pni=(&namesInfo);
520 int len=strlen(pni->inbuf), cursor_x=0, cursor_y, box_w, box_h, x, y;
521 char *c_ptr;
522 struct BBRec bbox;
523
524 if (msgFontPtr == NULL) {
525 XSetFont(mainDisplay, nameGC, defaultFontPtr->fid);
526 } else {
527 XSetFont(mainDisplay, nameGC, msgFontPtr->fid);
528 }
529 x = pni->graph_start;
530 /* the path_bbox has 2 pixels around it */
531 y = pni->path_bbox.lty+2;
532
533 box_w = ITEM_LEN*defaultFontWidth+6+(windowPadding<<1);
534 cursor_y = y;
535 if ((msgFontSet==NULL && msgFontPtr==NULL)) {
536 y += defaultFontAsc;
537 } else {
538 y += msgFontAsc;
539 }
540 box_h = (ROW_HEIGHT+3);
541 if (threeDLook) {
542 XSetForeground(mainDisplay, textMenuGC, myBgPixel);
543 XFillRectangle(mainDisplay, pni->base_win, textMenuGC, x, cursor_y-2,
544 box_w+(windowPadding<<1), box_h+(windowPadding<<1));
545 SetBBRec(&bbox, x, cursor_y-2, x+box_w+(windowPadding<<1),
546 cursor_y-2+box_h+(windowPadding<<1));
547 TgDrawThreeDButton(mainDisplay, pni->base_win, textMenuGC, &bbox,
548 TGBS_LOWRED, 2, FALSE);
549 } else {
550 XClearArea(mainDisplay, pni->base_win, x, cursor_y-2, box_w+1, box_h,
551 False);
552 XDrawRectangle(mainDisplay, pni->base_win, nameGC, x, cursor_y-2,
553 box_w+1, box_h);
554 }
555 if ((msgFontSet==NULL && msgFontPtr==NULL)) {
556 if (len > ITEM_LEN) {
557 c_ptr = &(pni->inbuf[len-ITEM_LEN]);
558 len = ITEM_LEN;
559 } else {
560 c_ptr = pni->inbuf;
561 }
562 cursor_x = x+2+len*defaultFontWidth;
563 } else {
564 int index=0;
565
566 cursor_x = MsgTextWidth(msgFontPtr, pni->inbuf, len);
567 while (cursor_x > box_w-4) {
568 index++;
569 cursor_x = MsgTextWidth(msgFontPtr, &pni->inbuf[index], len-index);
570 }
571 c_ptr = &pni->inbuf[index];
572 len -= index;
573 cursor_x += x+2+1;
574 }
575 DrawMsgString(mainDisplay, pni->base_win, nameGC, x+2+windowPadding,
576 y+1+windowPadding, c_ptr, len);
577 XDrawLine(mainDisplay, pni->base_win, nameGC, cursor_x+windowPadding,
578 cursor_y+1+windowPadding, cursor_x+windowPadding,
579 cursor_y+box_h-5+windowPadding);
580 }
581
582 static
RedrawNameBaseWindow()583 void RedrawNameBaseWindow()
584 {
585 struct NamesRec *pni=(&namesInfo);
586 int i, left, base_line;
587
588 /* draw a frame around the window */
589 if (threeDLook) {
590 if (dialogboxUse3DBorder) {
591 struct BBRec bbox;
592
593 SetBBRec(&bbox, 0, 0, pni->base_win_w, pni->base_win_h);
594 TgDrawThreeDButton(mainDisplay, pni->base_win, textMenuGC, &bbox,
595 TGBS_RAISED, 2, FALSE);
596 }
597 } else {
598 XDrawRectangle(mainDisplay, pni->base_win, nameGC, 0, 0,
599 pni->base_win_w-1, pni->base_win_h-1);
600 }
601 if (boldMsgFontSet == NULL && boldMsgFontPtr == NULL) {
602 base_line = defaultFontAsc+ROW_HEIGHT;
603 XSetFont(mainDisplay, nameGC, defaultFontPtr->fid);
604 } else {
605 base_line = boldMsgFontAsc+ROW_HEIGHT;
606 if (boldMsgFontPtr != NULL) {
607 XSetFont(mainDisplay, nameGC, boldMsgFontPtr->fid);
608 }
609 }
610 /* draw the title */
611 if (pni->tabbed_from_root) {
612 if (pni->title_num_lines <= 1) {
613 DrawBoldMsgString(mainDisplay, pni->base_win, nameGC, pni->title_start,
614 base_line, pni->title_str, strlen(pni->title_str));
615 } else {
616 char *psz_line=pni->formatted_title_str;
617 char *psz=strchr(pni->formatted_title_str, '\n');
618
619 do {
620 if (psz != NULL) *psz = '\0';
621 DrawBoldMsgString(mainDisplay, pni->base_win, nameGC,
622 pni->title_start, base_line, psz_line, strlen(psz_line));
623 base_line += ((boldMsgFontSet==NULL && boldMsgFontPtr==NULL) ?
624 defaultFontHeight : boldMsgFontHeight);
625 if (psz != NULL) {
626 *psz++ = '\n';
627 psz_line = psz;
628 psz = strchr(psz_line, '\n');
629 } else {
630 break;
631 }
632 } while (psz_line != NULL);
633 }
634 } else {
635 int tmp_w, len, tmp_start;
636
637 strcpy(gszMsgBox, TgLoadString(STID_TAB_FOR_FILE_COMPLETION));
638 len = strlen(gszMsgBox);
639 if (boldMsgFontSet == NULL && boldMsgFontPtr == NULL) {
640 tmp_w = defaultFontWidth * len;
641 } else {
642 tmp_w = BoldMsgTextWidth(boldMsgFontPtr, gszMsgBox, len);
643 }
644 tmp_start = ((pni->base_win_w-tmp_w)>>1);
645 DrawBoldMsgString(mainDisplay, pni->base_win, nameGC, tmp_start,
646 base_line, gszMsgBox, len);
647 if (pni->title_str != NULL && *pni->title_str != '\0') {
648 SetStringStatus(pni->title_str);
649 }
650 }
651 if (boldMsgFontSet != NULL || boldMsgFontPtr != NULL) {
652 if (msgFontPtr == NULL) {
653 XSetFont(mainDisplay, nameGC, defaultFontPtr->fid);
654 } else {
655 XSetFont(mainDisplay, nameGC, msgFontPtr->fid);
656 }
657 }
658 RedrawNamePath();
659
660 /* draw the buttons */
661 left = pni->btn_start;
662 for (i=0; i < pni->num_btns; i++) {
663 int len=strlen(pni->btn_str[i]);
664 int button_w=ButtonWidth(pni->btn_str[i], 8, NULL), button_h=0;
665
666 if (boldMsgFontSet == NULL && boldMsgFontPtr == NULL) {
667 button_h = defaultFontHeight + 4;
668 } else {
669 button_h = boldMsgFontHeight + 4;
670 }
671 pni->btn_bbox[i].ltx = left;
672 pni->btn_bbox[i].lty = (5+ITEM_DSPED)*ROW_HEIGHT + pni->title_h;
673 pni->btn_bbox[i].lty -= 1;
674 pni->btn_bbox[i].rbx = pni->btn_bbox[i].ltx+button_w;
675 pni->btn_bbox[i].rby = pni->btn_bbox[i].lty+button_h;
676 DisplayButtonInBBox(pni->base_win, pni->btn_str[i],
677 len, &(pni->btn_bbox[i]), BUTTON_NORMAL, FALSE, 0, NULL);
678 left = pni->btn_bbox[i].rbx + 1 + defaultFontWidth;
679 }
680 }
681
682 static
RedrawNamesWindow()683 void RedrawNamesWindow()
684 {
685 RedrawNameBaseWindow();
686 RedrawNameScrollWin();
687 RedrawDspWindow();
688 RedrawDspBaseWindow();
689 }
690
691 static
ExposeOrMapNames(input)692 int ExposeOrMapNames(input)
693 XEvent *input;
694 {
695 struct NamesRec *pni=(&namesInfo);
696 XEvent ev;
697
698 if ((input->type==MapNotify && input->xany.window==pni->base_win) ||
699 (input->type==Expose && (input->xany.window==pni->base_win ||
700 input->xany.window==pni->scroll_win ||
701 input->xany.window==pni->dsp_win)) || (!pni->exposed &&
702 (XCheckWindowEvent(mainDisplay, pni->base_win, ExposureMask,
703 &ev) || XCheckWindowEvent(mainDisplay, pni->scroll_win,
704 ExposureMask, &ev) || XCheckWindowEvent(mainDisplay, pni->dsp_win,
705 ExposureMask, &ev) || XCheckWindowEvent(mainDisplay,
706 pni->base_win, StructureNotifyMask, &ev)))) {
707 while (XCheckWindowEvent(mainDisplay, pni->base_win,
708 ExposureMask, &ev)) ;
709 while (XCheckWindowEvent(mainDisplay, pni->scroll_win,
710 ExposureMask, &ev)) ;
711 while (XCheckWindowEvent(mainDisplay, pni->dsp_win,
712 ExposureMask, &ev)) ;
713 while (XCheckWindowEvent(mainDisplay, pni->base_win,
714 StructureNotifyMask, &ev)) ;
715
716 RedrawNamesWindow();
717
718 pni->exposed = TRUE;
719 XSync(mainDisplay, False);
720
721 if ((input->type==MapNotify &&
722 input->xany.window==pni->base_win) ||
723 (input->type==Expose &&
724 (input->xany.window==pni->base_win ||
725 input->xany.window==pni->scroll_win ||
726 input->xany.window==pni->dsp_win))) {
727 return TRUE;
728 }
729 }
730 return FALSE;
731 }
732
733 static
CreateNamesWindows(win_name)734 int CreateNamesWindows(win_name)
735 char *win_name;
736 {
737 struct NamesRec *pni=(&namesInfo);
738 int y, base_win_x, base_win_y;
739 int bg_pixel=(threeDLook ? myLtGryPixel : myBgPixel);
740 XWMHints wmhints;
741 XSizeHints sizehints;
742 XSetWindowAttributes win_attrs;
743
744 base_win_x = (pni->base_win_w > pni->screen_w) ? 0 :
745 ((pni->screen_w-pni->base_win_w)>>1);
746 base_win_y = (pni->base_win_h > pni->screen_h) ? 0 :
747 ((pni->screen_h-pni->base_win_h)/3);
748
749 if ((pni->base_win=XCreateSimpleWindow(mainDisplay, rootWindow,
750 base_win_x, base_win_y, pni->base_win_w, pni->base_win_h,
751 brdrW, myBorderPixel, bg_pixel)) == 0) {
752 return FailToCreateWindowMessage("CreateNamesWindows()", NULL, FALSE);
753 }
754 XDefineCursor(mainDisplay, pni->base_win, defaultCursor);
755
756 y = (ROW_HEIGHT<<2)+pni->title_h;
757 if ((pni->dsp_base_win=XCreateSimpleWindow(mainDisplay, pni->base_win,
758 pni->graph_start, y, pni->dsp_base_win_w, pni->dsp_base_win_h,
759 0, myBorderPixel, bg_pixel)) == 0) {
760 XDestroyWindow(mainDisplay, pni->base_win);
761 return FailToCreateWindowMessage("CreateNamesWindows()", NULL, FALSE);
762 }
763 if ((pni->dsp_win=XCreateSimpleWindow(mainDisplay, pni->dsp_base_win,
764 windowPadding, windowPadding, pni->dsp_area_w, pni->dsp_area_h,
765 brdrW, myBorderPixel, bg_pixel)) == 0) {
766 XDestroyWindow(mainDisplay, pni->base_win);
767 return FailToCreateWindowMessage("CreateNamesWindows()", NULL, FALSE);
768 }
769 if ((pni->scroll_win=XCreateSimpleWindow(mainDisplay,
770 pni->dsp_base_win, windowPadding+pni->dsp_area_w+(brdrW<<1),
771 windowPadding, scrollBarW, pni->dsp_area_h,
772 brdrW, myBorderPixel, bg_pixel)) == 0) {
773 XDestroyWindow(mainDisplay, pni->base_win);
774 return FailToCreateWindowMessage("CreateNamesWindows()", NULL, FALSE);
775 }
776 win_attrs.save_under = True;
777 win_attrs.colormap = mainColormap;
778 XChangeWindowAttributes(mainDisplay, pni->base_win,
779 CWSaveUnder | CWColormap, &win_attrs);
780
781 wmhints.flags = InputHint | StateHint;
782 wmhints.input = True;
783 wmhints.initial_state = NormalState;
784 XSetWMHints(mainDisplay, pni->base_win, &wmhints);
785
786 sizehints.flags = PPosition | PSize | USPosition | PMinSize | PMaxSize;
787 sizehints.x = base_win_x;
788 sizehints.y = base_win_y;
789 sizehints.width = sizehints.min_width = sizehints.max_width =
790 pni->base_win_w;
791 sizehints.height = sizehints.min_height = sizehints.max_height =
792 pni->base_win_h;
793 #ifdef NOTR4MODE
794 XSetNormalHints(mainDisplay, pni->base_win, &sizehints);
795 #else
796 XSetWMNormalHints(mainDisplay, pni->base_win, &sizehints);
797 #endif
798 RegisterWM_DELETE_WINDOW(pni->base_win);
799 XStoreName(mainDisplay, pni->base_win, win_name);
800
801 XSetTransientForHint(mainDisplay, pni->base_win, mainWindow);
802
803 #ifdef MAPBEFORESELECT
804 XMapWindow(mainDisplay, pni->base_win);
805 XSelectInput(mainDisplay, pni->base_win,
806 KeyPressMask | ButtonPressMask | ExposureMask | StructureNotifyMask);
807 XMapWindow(mainDisplay, pni->dsp_base_win);
808 XSelectInput(mainDisplay, pni->dsp_base_win, ExposureMask);
809 XMapWindow(mainDisplay, pni->dsp_win);
810 XSelectInput(mainDisplay, pni->dsp_win,
811 KeyPressMask | ButtonPressMask | ExposureMask);
812 XMapWindow(mainDisplay, pni->scroll_win);
813 XSelectInput(mainDisplay, pni->scroll_win,
814 KeyPressMask | ButtonPressMask | ExposureMask);
815 #else
816 XSelectInput(mainDisplay, pni->base_win,
817 KeyPressMask | ButtonPressMask | ExposureMask | StructureNotifyMask);
818 XMapWindow(mainDisplay, pni->base_win);
819 XSelectInput(mainDisplay, pni->dsp_base_win, ExposureMask);
820 XMapWindow(mainDisplay, pni->dsp_base_win);
821 XSelectInput(mainDisplay, pni->dsp_win,
822 KeyPressMask | ButtonPressMask | ExposureMask);
823 XMapWindow(mainDisplay, pni->dsp_win);
824 XSelectInput(mainDisplay, pni->scroll_win,
825 KeyPressMask | ButtonPressMask | ExposureMask);
826 XMapWindow(mainDisplay, pni->scroll_win);
827 #endif
828
829 if (warpToWinCenter) {
830 XWarpPointer(mainDisplay, None, pni->base_win, 0, 0, 0, 0,
831 (pni->base_win_w>>1), (pni->base_win_h>>1));
832 }
833 XSync(mainDisplay, False);
834
835 Msg("");
836
837 return TRUE;
838 }
839
840 static
NamesUpdateIndices()841 void NamesUpdateIndices()
842 {
843 struct NamesRec *pni=(&namesInfo);
844
845 pni->first_index = 0;
846 if (pni->marked_index == INVALID) {
847 if (pni->edit_style != NAMES_SELECT_FILE) {
848 *pni->inbuf = '\0';
849 pni->buf_index = 0;
850 }
851 } else {
852 if (pni->marked_index >= ITEM_DSPED) {
853 if (pni->marked_index < pni->num_entries-ITEM_DSPED) {
854 pni->first_index = pni->marked_index;
855 } else {
856 pni->first_index = pni->num_entries-ITEM_DSPED;
857 }
858 }
859 if (pni->edit_style != NAMES_SELECT_FILE) {
860 strcpy(pni->inbuf, &(pni->entries[pni->marked_index])[pni->leading]);
861 pni->buf_index = strlen(pni->inbuf);;
862 }
863 }
864 }
865
866 static
IsFirstEqChar(s,index)867 int IsFirstEqChar(s, index)
868 char *s;
869 int index;
870 {
871 s = (&s[index]);
872 if (*s != '=') return FALSE;
873 for (--index, --s; index >= 0; index--, s--) {
874 if (*s == '=') {
875 return FALSE;
876 }
877 }
878 return TRUE;
879 }
880
881 static
SetMarkedIndex()882 int SetMarkedIndex()
883 {
884 struct NamesRec *pni=(&namesInfo);
885 int i;
886
887 if (*pni->name == '\0') return FALSE;
888 for (i=0; i < pni->num_entries; i++) {
889 if (strncmp(&(pni->entries[i])[pni->leading],
890 pni->name, pni->name_index) == 0) {
891 break;
892 }
893 }
894 if (i < pni->num_entries) {
895 if (i < pni->first_index) {
896 pni->first_index = i;
897 } else if (i >= pni->first_index+ITEM_DSPED) {
898 if (i < pni->num_entries-ITEM_DSPED) {
899 pni->first_index = i;
900 } else {
901 pni->first_index = pni->num_entries-ITEM_DSPED;
902 }
903 }
904 pni->marked_index = i;
905 return TRUE;
906 } else {
907 return FALSE;
908 }
909 }
910
911 static
BackSpaceInNames(pn_changing,pn_selected_btn_index)912 void BackSpaceInNames(pn_changing, pn_selected_btn_index)
913 int *pn_changing, *pn_selected_btn_index;
914 {
915 struct NamesRec *pni=(&namesInfo);
916 int i;
917
918 switch (pni->edit_style) {
919 case NAMES_SIMPLE_SELECT_NAME: return;
920 case NAMES_COMPLEX_SELECT_NAME:
921 if (pni->marked_index == INVALID || pni->buf_index <= 0) return;
922 pni->inbuf[--pni->buf_index] = '\0';
923 if (pni->buf_index != 0) {
924 int i;
925
926 for (i=0; i < pni->num_entries; i++) {
927 if (strncmp(&(pni->entries[i])[pni->leading],
928 pni->inbuf, pni->buf_index) == 0) {
929 break;
930 }
931 }
932 if (i < pni->num_entries) {
933 if (i < pni->first_index) {
934 pni->first_index = i;
935 } else if (i >= pni->first_index+ITEM_DSPED) {
936 if (i < pni->num_entries-ITEM_DSPED) {
937 pni->first_index = i;
938 } else {
939 pni->first_index = pni->num_entries-ITEM_DSPED;
940 }
941 }
942 pni->marked_index = i;
943 }
944 } else {
945 pni->first_index = 0;
946 pni->marked_index = INVALID;
947 }
948 break;
949 case NAMES_SELECT_FILE:
950 if (pni->name_index > 0) {
951 pni->name[--pni->name_index] = '\0';
952 sprintf(pni->inbuf, "%s%c%s", pni->dir_name, DIR_SEP, pni->name);
953 pni->buf_index = strlen(pni->inbuf);
954 if (pni->tabbed_from_root && pni->name_index != 0) {
955 for (i=0; i < pni->num_entries; i++) {
956 if (strncmp(&(pni->entries[i])[pni->leading],
957 pni->name, pni->name_index) == 0) {
958 pni->marked_index = i;
959 break;
960 }
961 }
962 } else {
963 pni->marked_index = INVALID;
964 }
965 } else if (pni->change_to_root && *pni->dir_name == '\0' &&
966 *pni->saved_dir_name != '\0') {
967 pni->pop_from_root = TRUE;
968 strcpy(pni->dir_name, pni->saved_dir_name);
969 *pni->saved_dir_name = '\0';
970 pni->tabbed_from_root = TRUE;
971 pni->change_to_root = FALSE;
972 sprintf(pni->inbuf, "%s%c%s", pni->dir_name, DIR_SEP, pni->name);
973 pni->buf_index = strlen(pni->inbuf);
974 *pn_changing = FALSE;
975 *pn_selected_btn_index = INVALID;
976 } else {
977 /* fake as if "../" is selected */
978 sprintf(pni->name, "..%c", DIR_SEP);
979 pni->name_index = strlen(pni->name);
980 for (i=0; i < pni->num_entries; i++) {
981 if (strncmp(&(pni->entries[i])[pni->leading],
982 pni->name, pni->name_index) == 0) {
983 pni->marked_index = i;
984 pni->faking_dot_dot = TRUE;
985 *pn_changing = FALSE;
986 *pn_selected_btn_index = i;
987 break;
988 }
989 }
990 }
991 break;
992 case NAMES_EDIT_ATTR:
993 if (pni->marked_index == INVALID || pni->buf_index <= 0) return;
994 if (pni->dsp_ptr == NULL ||
995 !pni->dsp_ptr[pni->marked_index].directory ||
996 !IsFirstEqChar(pni->inbuf, pni->buf_index-1)) {
997 pni->inbuf[--pni->buf_index] = '\0';
998 strcpy(&(pni->entries[pni->marked_index])[pni->leading],
999 pni->inbuf);
1000 }
1001 break;
1002 case NAMES_EDIT_NAME:
1003 if (pni->marked_index == INVALID || pni->buf_index <= 0) return;
1004 pni->inbuf[--pni->buf_index] = '\0';
1005 strcpy(&(pni->entries[pni->marked_index])[pni->leading],
1006 pni->inbuf);
1007 break;
1008 default: break;
1009 }
1010 if (pni->exposed) {
1011 RedrawNamePath();
1012 RedrawDspWindow();
1013 }
1014 }
1015
1016 static
ParseFileName(FullName,DirName,Name)1017 void ParseFileName(FullName, DirName, Name)
1018 char *FullName, *DirName, *Name;
1019 {
1020 int i, len;
1021
1022 len = strlen(FullName);
1023 strcpy(DirName, FullName);
1024 for (i=len-1; i>=0; i--) {
1025 if (DirName[i] == DIR_SEP) {
1026 strcpy(Name, &(DirName[i+1]));
1027 DirName[i] = '\0';
1028 return;
1029 }
1030 }
1031 *DirName = *Name = '\0';
1032 }
1033
1034 static
TabInNames()1035 void TabInNames()
1036 {
1037 struct NamesRec *pni=(&namesInfo);
1038
1039 if (pni->edit_style == NAMES_SELECT_FILE) {
1040 pni->tabbed_from_root = TRUE;
1041 pni->just_tabbed_from_root = TRUE;
1042 if (!FileIsRemote(pni->name)) {
1043 /* saved_name is used for just_tabbed_from_root */
1044 sprintf(pni->inbuf, "%s%c%s", pni->dir_name, DIR_SEP, pni->name);
1045 pni->buf_index = strlen(pni->inbuf);
1046 strcpy(pni->saved_name, pni->name);
1047 ParseFileName(pni->inbuf, pni->dir_name, pni->name);
1048 } else {
1049 pni->remote_file = TRUE;
1050 }
1051 }
1052 }
1053
1054 static
CharInNames(buf,pn_changing,pn_selected_btn_index)1055 void CharInNames(buf, pn_changing, pn_selected_btn_index)
1056 char *buf;
1057 int *pn_changing, *pn_selected_btn_index;
1058 {
1059 struct NamesRec *pni=(&namesInfo);
1060 int i=INVALID;
1061
1062 switch (pni->edit_style) {
1063 case NAMES_SIMPLE_SELECT_NAME:
1064 if (buf[0] == ' ' && buf[1] == '\0' &&
1065 pni->p_check_array != NULL && pni->p_check_array->num_cols == 1) {
1066 i = pni->marked_index;
1067 pni->p_check_array->value[0][i] = !(pni->p_check_array->value[0][i]);
1068 RedrawItem(pni, i);
1069 }
1070 return;
1071
1072 case NAMES_COMPLEX_SELECT_NAME:
1073 if (buf[0] == '$') {
1074 i = pni->num_entries-1;
1075 strcpy(pni->inbuf, &(pni->entries[i])[pni->leading]);
1076 } else if (buf[0] == '^') {
1077 i = 0;
1078 strcpy(pni->inbuf, &(pni->entries[i])[pni->leading]);
1079 } else {
1080 pni->inbuf[pni->buf_index++] = buf[0];
1081 pni->inbuf[pni->buf_index] = '\0';
1082 for (i=0; i < pni->num_entries; i++) {
1083 if (strncmp(&(pni->entries[i])[pni->leading],
1084 pni->inbuf, pni->buf_index) == 0) {
1085 break;
1086 }
1087 }
1088 }
1089 if (i < pni->num_entries) {
1090 if (i < pni->first_index) {
1091 pni->first_index = i;
1092 } else if (i >= pni->first_index+ITEM_DSPED) {
1093 if (i < pni->num_entries-ITEM_DSPED) {
1094 pni->first_index = i;
1095 } else {
1096 pni->first_index = pni->num_entries-ITEM_DSPED;
1097 }
1098 }
1099 pni->marked_index = i;
1100 } else {
1101 pni->inbuf[--pni->buf_index] = '\0';
1102 }
1103 break;
1104 case NAMES_SELECT_FILE:
1105 if (!pni->tabbed_from_root) {
1106 pni->name[pni->name_index++] = buf[0];
1107 pni->name[pni->name_index] = '\0';
1108 sprintf(pni->inbuf, "%s%c%s", pni->dir_name, DIR_SEP, pni->name);
1109 pni->buf_index = strlen(pni->inbuf);
1110 } else if (buf[0] == '$') {
1111 i = pni->num_entries-1;
1112 strcpy(pni->name, &(pni->entries[i])[pni->leading]);
1113 pni->name_index = strlen(pni->name);
1114 } else if (buf[0] == '^') {
1115 i = 0;
1116 strcpy(pni->name, &(pni->entries[i])[pni->leading]);
1117 pni->name_index = strlen(pni->name);
1118 #ifdef apollo
1119 } else if (pni->name_index == 0 && buf[0] == DIR_SEP &&
1120 *pni->dir_name == '\0') {
1121 strcpy(pni->dir_name, DIR_SEP_STR);
1122 pni->name[pni->name_index++] = buf[0];
1123 i = pni->num_entries;
1124 strcpy(pni->inbuf, "//");
1125 #endif /* apollo */
1126 } else if (pni->name_index == 0 && buf[0] == DIR_SEP) {
1127 if (*pni->saved_dir_name == '\0') {
1128 strcpy(pni->saved_dir_name, pni->dir_name);
1129 pni->num_entries = 0;
1130 }
1131 *pn_changing = FALSE;
1132 pni->change_to_root = TRUE;
1133 pni->tabbed_from_root = FALSE;
1134 *pn_selected_btn_index = INVALID;
1135 *pni->dir_name = *pni->name = '\0';
1136 pni->name_index = 0;
1137 sprintf(pni->inbuf, "%s%c%s", pni->dir_name, DIR_SEP, pni->name);
1138 pni->buf_index = strlen(pni->inbuf);
1139 break;
1140 } else {
1141 pni->name[pni->name_index++] = buf[0];
1142 pni->name[pni->name_index] = '\0';
1143 for (i=0; i < pni->num_entries; i++) {
1144 if (strncmp(&(pni->entries[i])[pni->leading],
1145 pni->name, pni->name_index) == 0) {
1146 break;
1147 }
1148 }
1149 }
1150 if (pni->num_entries > 0) {
1151 if (i < pni->num_entries) {
1152 if (i < pni->first_index) {
1153 pni->first_index = i;
1154 } else if (i >= pni->first_index+ITEM_DSPED) {
1155 if (i < pni->num_entries-ITEM_DSPED) {
1156 pni->first_index = i;
1157 } else {
1158 pni->first_index = pni->num_entries-ITEM_DSPED;
1159 }
1160 }
1161 pni->marked_index = i;
1162 sprintf(pni->inbuf, "%s%c%s", pni->dir_name, DIR_SEP, pni->name);
1163 pni->buf_index = strlen(pni->inbuf);
1164 if (buf[0] == DIR_SEP) {
1165 *pn_changing = FALSE;
1166 *pn_selected_btn_index = INVALID;
1167 }
1168 } else {
1169 pni->name[--pni->name_index] = '\0';
1170 }
1171 }
1172 break;
1173 case NAMES_EDIT_ATTR:
1174 if (pni->marked_index == INVALID) return;
1175 pni->inbuf[pni->buf_index++] = buf[0];
1176 pni->inbuf[pni->buf_index] = '\0';
1177 strcpy(&(pni->entries[pni->marked_index])[pni->leading],
1178 pni->inbuf);
1179 break;
1180 case NAMES_EDIT_NAME:
1181 if (pni->marked_index == INVALID) return;
1182 pni->inbuf[pni->buf_index++] = buf[0];
1183 pni->inbuf[pni->buf_index] = '\0';
1184 strcpy(&(pni->entries[pni->marked_index])[pni->leading],
1185 pni->inbuf);
1186 break;
1187 default: break;
1188 }
1189 if (pni->exposed) {
1190 RedrawNamePath();
1191 RedrawDspWindow();
1192 }
1193 }
1194
1195 static
GetNameEntryNum(RowOffset)1196 int GetNameEntryNum(RowOffset)
1197 int RowOffset;
1198 {
1199 struct NamesRec *pni=(&namesInfo);
1200 int index;
1201
1202 index = pni->first_index + RowOffset;
1203 if (index >= pni->num_entries) return INVALID;
1204 return index;
1205 }
1206
1207 static
ScrollItemCallback(pv_userdata)1208 int ScrollItemCallback(pv_userdata)
1209 void *pv_userdata;
1210 /* returns TRUE to cancel scrolling */
1211 {
1212 struct NamesRec *pni=((struct NamesRec *)pv_userdata);
1213
1214 if (pni->scroll_dir == SCRL_UP) {
1215 if (pni->first_index == 0) return FALSE;
1216 pni->first_index--;
1217 } else {
1218 if (pni->num_entries <= ITEM_DSPED ||
1219 pni->first_index+ITEM_DSPED == pni->num_entries) {
1220 return FALSE;
1221 }
1222 pni->first_index++;
1223 }
1224 RedrawNameScrollWin();
1225 RedrawDspWindow();
1226 XSync(mainDisplay, False);
1227
1228 return FALSE;
1229 }
1230
1231 static
ScrollPageCallback(pv_userdata)1232 int ScrollPageCallback(pv_userdata)
1233 void *pv_userdata;
1234 /* returns TRUE to cancel scrolling */
1235 {
1236 struct NamesRec *pni=((struct NamesRec *)pv_userdata);
1237
1238 if (pni->scroll_dir == SCRL_UP) {
1239 if (pni->first_index == 0) return FALSE;
1240 pni->first_index -= ITEM_DSPED;
1241 if (pni->first_index < 0) pni->first_index = 0;
1242 } else {
1243 if (pni->num_entries <= ITEM_DSPED ||
1244 pni->first_index+ITEM_DSPED == pni->num_entries) {
1245 return FALSE;
1246 }
1247 pni->first_index += ITEM_DSPED;
1248 if (pni->first_index+ITEM_DSPED >= pni->num_entries) {
1249 pni->first_index = pni->num_entries-ITEM_DSPED;
1250 }
1251 }
1252 RedrawNameScrollWin();
1253 RedrawDspWindow();
1254 XSync(mainDisplay, False);
1255
1256 return FALSE;
1257 }
1258
1259 static
DoNameBtnScroll(scroll_page,scroll_dir,pbbox,pni)1260 int DoNameBtnScroll(scroll_page, scroll_dir, pbbox, pni)
1261 int scroll_page, scroll_dir;
1262 struct BBRec *pbbox;
1263 struct NamesRec *pni;
1264 /* returns TRUE if done scrolling */
1265 {
1266 ScrollBtnCallbackInfo sbci;
1267
1268 pni->scroll_dir = scroll_dir;
1269 memset(&sbci, 0, sizeof(ScrollBtnCallbackInfo));
1270
1271 if (scroll_page) {
1272 sbci.ms = 200;
1273 sbci.pv_userdata = pni;
1274 sbci.pf_scroll_btn_callback = ScrollPageCallback;
1275 if (TgPressButtonLoop(mainDisplay, pni->scroll_win, NULL,
1276 &sbci)) {
1277 if (scroll_dir == SCRL_UP) {
1278 if (pni->first_index == 0) return TRUE;
1279 pni->first_index -= ITEM_DSPED;
1280 if (pni->first_index < 0) pni->first_index = 0;
1281 } else {
1282 if (pni->num_entries <= ITEM_DSPED ||
1283 pni->first_index+ITEM_DSPED == pni->num_entries) {
1284 return TRUE;
1285 }
1286 pni->first_index += ITEM_DSPED;
1287 if (pni->first_index+ITEM_DSPED >= pni->num_entries) {
1288 pni->first_index = pni->num_entries-ITEM_DSPED;
1289 }
1290 }
1291 }
1292 } else {
1293 sbci.ms = 50;
1294 sbci.pv_userdata = pni;
1295 sbci.pf_scroll_btn_callback = ScrollItemCallback;
1296 if (TgPressButtonLoop(mainDisplay, pni->scroll_win, pbbox, &sbci)) {
1297 if (scroll_dir == SCRL_UP) {
1298 if (pni->first_index == 0) return TRUE;
1299 pni->first_index--;
1300 } else {
1301 if (pni->num_entries <= ITEM_DSPED ||
1302 pni->first_index+ITEM_DSPED == pni->num_entries) {
1303 return TRUE;
1304 }
1305 pni->first_index++;
1306 }
1307 }
1308 }
1309 return FALSE;
1310 }
1311
1312 static
NameScrollHandler(button_ev)1313 void NameScrollHandler(button_ev)
1314 XButtonEvent *button_ev;
1315 {
1316 struct NamesRec *pni=(&namesInfo);
1317 double frac, start_frac;
1318 int block_h, block_start, do_drag=FALSE, btn_offset=0;
1319
1320 if (!threeDLook && button_ev->button == Button3 &&
1321 button_ev->type == ButtonPress) {
1322 if (DoNameBtnScroll(((button_ev->state & (ShiftMask|ControlMask)) != 0),
1323 SCRL_UP, NULL, pni)) {
1324 return;
1325 }
1326 } else if (!threeDLook && button_ev->button == Button1 &&
1327 button_ev->type == ButtonPress) {
1328 if (DoNameBtnScroll(((button_ev->state & (ShiftMask|ControlMask)) != 0),
1329 SCRL_DN, NULL, pni)) {
1330 return;
1331 }
1332 } else if (button_ev->button == Button1 && button_ev->type == ButtonPress) {
1333 if (button_ev->y < scrollBarW ||
1334 button_ev->y >= pni->scroll_area_h-scrollBarW) {
1335 int which=INVALID;
1336 struct BBRec bbox;
1337
1338 if (button_ev->y < scrollBarW) {
1339 which = SCRL_UP;
1340 SetBBRec(&bbox, 0, 0, scrollBarW, scrollBarW);
1341 } else {
1342 which = SCRL_DN;
1343 SetBBRec(&bbox, 0, pni->scroll_area_h-scrollBarW, scrollBarW,
1344 pni->scroll_area_h);
1345 }
1346 if (DoNameBtnScroll(FALSE, which, &bbox, pni)) {
1347 return;
1348 }
1349 } else {
1350 int hit=0;
1351
1352 start_frac = (pni->num_entries > 0) ?
1353 (double)((double)(pni->first_index) /
1354 (double)(pni->num_entries)) : ((double)0.0);
1355 hit = TgGetScrollHit(button_ev->x, button_ev->y, VERT_SCROLLBAR,
1356 scrollBarW, pni->scroll_area_h, start_frac, ITEM_DSPED,
1357 pni->num_entries, &btn_offset);
1358 if (hit == 0) {
1359 do_drag = TRUE;
1360 } else {
1361 if (DoNameBtnScroll(TRUE, (hit < 0 ? SCRL_UP : SCRL_DN), NULL,
1362 pni)) {
1363 return;
1364 }
1365 }
1366 }
1367 } else if (!threeDLook && button_ev->button == Button2 &&
1368 button_ev->type == ButtonPress) {
1369 do_drag = TRUE;
1370 }
1371 if (do_drag) {
1372 int done=FALSE;
1373 XEvent ev;
1374
1375 if (pni->num_entries <= ITEM_DSPED) return;
1376
1377 frac = (double)((double)ITEM_DSPED / (double)(pni->num_entries));
1378 block_h = (int)(pni->scroll_area_h * frac);
1379 if (threeDLook) {
1380 block_start = button_ev->y+btn_offset;;
1381 start_frac = (double)((double)(block_start-scrollBarW) /
1382 (double)(pni->scroll_area_h-(scrollBarW<<1)));
1383 if (block_start+block_h >= pni->scroll_area_h-scrollBarW) {
1384 pni->first_index = pni->num_entries - ITEM_DSPED;
1385 } else {
1386 pni->first_index = (int)(pni->num_entries * start_frac);
1387 }
1388 } else {
1389 block_start = button_ev->y;
1390 start_frac = (double)((double)(block_start) /
1391 (double)(pni->scroll_area_h));
1392 if (block_start+block_h >= pni->scroll_area_h) {
1393 pni->first_index = pni->num_entries - ITEM_DSPED;
1394 } else {
1395 pni->first_index = (int)(pni->num_entries * start_frac);
1396 }
1397 }
1398 RedrawNameScrollWin();
1399 RedrawDspWindow();
1400
1401 XGrabPointer(mainDisplay, pni->scroll_win, False,
1402 PointerMotionMask | ButtonReleaseMask, GrabModeAsync,
1403 GrabModeAsync, None, handCursor, CurrentTime);
1404
1405 while (!done) {
1406 XNextEvent(mainDisplay, &ev);
1407
1408 if (ev.type == Expose || ev.type == VisibilityNotify) {
1409 ExposeEventHandler(&ev, TRUE);
1410 } else if (ev.type == ButtonRelease) {
1411 XUngrabPointer(mainDisplay, CurrentTime);
1412 if (debugNoPointerGrab) XSync(mainDisplay, False);
1413 done = TRUE;
1414 } else if (ev.type == MotionNotify) {
1415 int new_name_first=0, y=ev.xmotion.y;
1416
1417 if (threeDLook) {
1418 y += btn_offset;
1419 start_frac = (double)(((double)(y-scrollBarW)) /
1420 ((double)(pni->scroll_area_h-(scrollBarW<<1))));
1421
1422 if (y <= scrollBarW) {
1423 new_name_first = 0;
1424 } else if (y+block_h >= pni->scroll_area_h-scrollBarW) {
1425 new_name_first = pni->num_entries - ITEM_DSPED;
1426 } else {
1427 new_name_first = (int)(pni->num_entries * start_frac);
1428 }
1429 } else {
1430 start_frac = (double)(((double)y) /
1431 ((double)pni->scroll_area_h));
1432
1433 if (y <= 0) {
1434 new_name_first = 0;
1435 } else if (y+block_h >= pni->scroll_area_h) {
1436 new_name_first = pni->num_entries - ITEM_DSPED;
1437 } else {
1438 new_name_first = (int)(pni->num_entries * start_frac);
1439 }
1440 }
1441 if (pni->first_index != new_name_first) {
1442 pni->first_index = new_name_first;
1443 RedrawNameScrollWin();
1444 RedrawDspWindow();
1445 }
1446 while (XCheckMaskEvent(mainDisplay, PointerMotionMask, &ev)) ;
1447 }
1448 }
1449 return;
1450 }
1451 RedrawNameScrollWin();
1452 RedrawDspWindow();
1453 }
1454
1455 static
NameDspHandler(button_ev)1456 int NameDspHandler(button_ev)
1457 XButtonEvent *button_ev;
1458 {
1459 struct NamesRec *pni=(&namesInfo);
1460 static Time last_click_time;
1461 static int last_name_marked;
1462 Time click_time;
1463 int checkbox_cols=0, box_offset=0, clicked_col=INVALID, check_updated=FALSE;
1464
1465 if (enableMouseWheel &&
1466 (button_ev->button == Button4 || button_ev->button == Button5)) {
1467 int which=INVALID;
1468 struct BBRec bbox;
1469
1470 if (button_ev->button == Button4) {
1471 which = SCRL_UP;
1472 SetBBRec(&bbox, 0, 0, scrollBarW, scrollBarW);
1473 } else if (button_ev->button == Button5) {
1474 which = SCRL_DN;
1475 SetBBRec(&bbox, 0, pni->scroll_area_h-scrollBarW, scrollBarW,
1476 pni->scroll_area_h);
1477 }
1478 if (which != INVALID) {
1479 DoNameBtnScroll(FALSE, which, &bbox, pni);
1480 RedrawNameScrollWin();
1481 RedrawDspWindow();
1482 }
1483 return INVALID;
1484 } else if (button_ev->button != Button1) {
1485 return INVALID;
1486 }
1487 if (pni->p_check_array != NULL && pni->p_check_array->num_cols > 0) {
1488 checkbox_cols = pni->p_check_array->num_cols;
1489 box_offset = 1;
1490 if (button_ev->x < checkbox_cols*ROW_HEIGHT) {
1491 clicked_col = (int)(button_ev->x / ROW_HEIGHT);
1492 }
1493 }
1494 if (pni->marked_index != INVALID &&
1495 pni->marked_index >= pni->first_index &&
1496 pni->marked_index < pni->first_index+ITEM_DSPED) {
1497 int saved_index=pni->marked_index;
1498
1499 pni->marked_index = INVALID;
1500 RedrawItem(pni, saved_index);
1501 pni->marked_index = saved_index;
1502 }
1503 pni->marked_index = GetNameEntryNum((int)(button_ev->y / ROW_HEIGHT));
1504 if (pni->marked_index != INVALID) {
1505 if (clicked_col != INVALID) {
1506 int i=pni->marked_index;
1507
1508 pni->p_check_array->value[clicked_col][i] =
1509 !(pni->p_check_array->value[clicked_col][i]);
1510 if (pni->pf_check_update != NULL) {
1511 /*
1512 * check_udpated set to TRUE if the callback function calls
1513 * SetStringStatus()
1514 */
1515 check_updated = (pni->pf_check_update)(&pni->dsp_ptr,
1516 &pni->entries, &pni->num_entries,
1517 &pni->marked_index, &pni->p_check_array, pni->inbuf,
1518 clicked_col, i, pni->userdata);
1519 }
1520 }
1521 RedrawItem(pni, pni->marked_index);
1522 }
1523 click_time = button_ev->time;
1524 if (pni->just_clicked && pni->marked_index != INVALID &&
1525 last_name_marked == pni->marked_index &&
1526 (click_time-last_click_time) < doubleClickInterval) {
1527 return TRUE;
1528 }
1529 pni->just_clicked = TRUE;
1530 last_click_time = click_time;
1531 last_name_marked = pni->marked_index;
1532
1533 if (!check_updated) {
1534 if (pni->dsp_ptr != NULL && pni->marked_index != INVALID) {
1535 SetStringStatus(pni->dsp_ptr[pni->marked_index].pathstr);
1536 } else {
1537 SetStringStatus("");
1538 }
1539 }
1540 return INVALID;
1541 }
1542
1543 static
ControlChar(key_ev,key_sym)1544 int ControlChar(key_ev, key_sym)
1545 XKeyEvent *key_ev;
1546 KeySym key_sym;
1547 {
1548 register int i;
1549 struct NamesRec *pni=(&namesInfo);
1550
1551 if (key_ev->state & ControlMask) {
1552 switch (key_sym) {
1553 case XK_Left: return (BAD);
1554 case XK_KP_Left: return (BAD);
1555 case XK_Up: key_sym = ((unsigned long)'b')&0xff; break;
1556 case XK_KP_Up: key_sym = ((unsigned long)'b')&0xff; break;
1557 case XK_Right: return (BAD);
1558 case XK_KP_Right: return (BAD);
1559 case XK_Down: key_sym = ((unsigned long)'f')&0xff; break;
1560 case XK_KP_Down: key_sym = ((unsigned long)'f')&0xff; break;
1561 case XK_Page_Up: key_sym = ((unsigned long)'b')&0xff; break;
1562 case XK_KP_Page_Up: key_sym = ((unsigned long)'b')&0xff; break;
1563 case XK_Page_Down: key_sym = ((unsigned long)'f')&0xff; break;
1564 case XK_KP_Page_Down: key_sym = ((unsigned long)'f')&0xff; break;
1565 }
1566 } else {
1567 switch (key_sym) {
1568 case XK_Left: return BAD;
1569 case XK_KP_Left: return BAD;
1570 case XK_Up: key_sym = ((unsigned long)'k')&0xff; break;
1571 case XK_KP_Up: key_sym = ((unsigned long)'k')&0xff; break;
1572 case XK_Right: return BAD;
1573 case XK_KP_Right: return BAD;
1574 case XK_Down: key_sym = ((unsigned long)'j')&0xff; break;
1575 case XK_KP_Down: key_sym = ((unsigned long)'j')&0xff; break;
1576 case XK_Page_Up: key_sym = ((unsigned long)'b')&0xff; break;
1577 case XK_KP_Page_Up: key_sym = ((unsigned long)'b')&0xff; break;
1578 case XK_Page_Down: key_sym = ((unsigned long)'f')&0xff; break;
1579 case XK_KP_Page_Down: key_sym = ((unsigned long)'f')&0xff; break;
1580 }
1581 }
1582 switch (key_sym&0xff) {
1583 case 'w': /* erase */
1584 case 'y':
1585 return INVALID;
1586 case 'n': /* down one */
1587 case 'j':
1588 i = (pni->marked_index < pni->num_entries-1) ?
1589 pni->marked_index+1 : pni->num_entries-1;
1590 break;
1591 case 'p': /* up one */
1592 case 'k':
1593 i = (pni->marked_index>0) ? pni->marked_index-1 : 0;
1594 break;
1595 case 'd': /* down one page */
1596 case 'f':
1597 if (pni->marked_index==INVALID) {
1598 i = (pni->num_entries <= ITEM_DSPED) ?
1599 pni->num_entries-1 : ITEM_DSPED;
1600 } else if (pni->marked_index < pni->num_entries-ITEM_DSPED) {
1601 i = pni->marked_index+ITEM_DSPED;
1602 } else {
1603 i = pni->num_entries-1;
1604 }
1605 break;
1606 case 'u': /* up one page */
1607 case 'b':
1608 i = (pni->marked_index > (ITEM_DSPED-1)) ?
1609 pni->marked_index-ITEM_DSPED : 0;
1610 break;
1611 default: return BAD;
1612 }
1613 return i;
1614 }
1615
1616 static
BackUpOneWord(pn_changing,pn_selected_btn_index)1617 void BackUpOneWord(pn_changing, pn_selected_btn_index)
1618 int *pn_changing, *pn_selected_btn_index;
1619 {
1620 struct NamesRec *pni=(&namesInfo);
1621 int new_dir=FALSE;
1622
1623 if (pni->buf_index == 0) return;
1624
1625 if (pni->inbuf[pni->buf_index-1] == DIR_SEP) {
1626 pni->inbuf[--pni->buf_index] = '\0';
1627 new_dir = TRUE;
1628 } else {
1629 while (pni->buf_index > 0) {
1630 if (pni->inbuf[(pni->buf_index)-1] == DIR_SEP) {
1631 pni->inbuf[pni->buf_index] = '\0';
1632 break;
1633 } else {
1634 pni->buf_index--;
1635 }
1636 }
1637 pni->inbuf[pni->buf_index] = '\0';
1638 }
1639 ParseFileName(pni->inbuf, pni->dir_name, pni->name);
1640 if (new_dir) {
1641 int i;
1642
1643 sprintf(pni->name, "..%c", DIR_SEP);
1644 pni->name_index = strlen(pni->name);
1645 for (i=0; i < pni->num_entries; i++) {
1646 if (strncmp(&(pni->entries[i])[pni->leading],
1647 pni->name, pni->name_index) == 0) {
1648 pni->marked_index = i;
1649 pni->faking_dot_dot = TRUE;
1650 *pn_changing = FALSE;
1651 *pn_selected_btn_index = i;
1652 break;
1653 }
1654 }
1655 } else {
1656 pni->first_index = 0;
1657 pni->marked_index = INVALID;
1658 }
1659 }
1660
1661 static
SpecialKeyInNames(key_ev,key_sym,pn_changing,pn_selected_btn_index)1662 void SpecialKeyInNames(key_ev, key_sym, pn_changing, pn_selected_btn_index)
1663 XKeyEvent *key_ev;
1664 KeySym key_sym;
1665 int *pn_changing, *pn_selected_btn_index;
1666 {
1667 struct NamesRec *pni=(&namesInfo);
1668 int i=ControlChar(key_ev, key_sym);
1669
1670 if (i == BAD) return;
1671
1672 if (i == INVALID) {
1673 if (pni->edit_style == NAMES_SELECT_FILE) {
1674 /* back-up one word */
1675 BackUpOneWord(pn_changing, pn_selected_btn_index);
1676 sprintf(pni->inbuf, "%s%c%s", pni->dir_name, DIR_SEP, pni->name);
1677 pni->buf_index = strlen(pni->inbuf);
1678 } else {
1679 *pni->inbuf = '\0';
1680 pni->buf_index = 0;
1681 pni->first_index = 0;
1682 pni->marked_index = INVALID;
1683 }
1684 } else if (i < pni->num_entries) {
1685 if (pni->edit_style == NAMES_SELECT_FILE) {
1686 strcpy(pni->name, &(pni->entries[i])[pni->leading]);
1687 pni->name_index = strlen(pni->name);
1688 sprintf(pni->inbuf, "%s%c%s", pni->dir_name, DIR_SEP, pni->name);
1689 pni->buf_index = strlen(pni->inbuf);
1690 } else {
1691 strcpy(pni->inbuf, &(pni->entries[i])[pni->leading]);
1692 pni->buf_index = strlen(pni->inbuf);
1693 }
1694 if (i < pni->first_index) {
1695 pni->first_index = i;
1696 } else if (i >= pni->first_index+ITEM_DSPED) {
1697 if (i < pni->num_entries-ITEM_DSPED) {
1698 pni->first_index = i;
1699 } else {
1700 pni->first_index = pni->num_entries-ITEM_DSPED;
1701 }
1702 }
1703 pni->marked_index = i;
1704 }
1705 if (pni->exposed) {
1706 RedrawNamePath();
1707 RedrawNameScrollWin();
1708 RedrawDspWindow();
1709 RedrawDspBaseWindow();
1710 }
1711 if (pni->dsp_ptr != NULL && pni->marked_index != INVALID) {
1712 SetStringStatus(pni->dsp_ptr[pni->marked_index].pathstr);
1713 } else {
1714 SetStringStatus("");
1715 }
1716 }
1717
1718 static
GetBtnIndexFromBtnId(btn_id)1719 int GetBtnIndexFromBtnId(btn_id)
1720 int btn_id;
1721 {
1722 struct NamesRec *pni=(&namesInfo);
1723 int i;
1724
1725 for (i=0; i < pni->num_btns; i++) {
1726 if (pni->btn_id[i] == btn_id) {
1727 return i;
1728 }
1729 }
1730 #ifdef _TGIF_DBG /* debug, do not translate */
1731 sprintf(gszMsgBox, "Programing error!\n\nCannot find a button with id=%1d.",
1732 btn_id);
1733 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1734 #endif /* _TGIF_DBG */
1735 return INVALID;
1736 }
1737
1738 static
KeyPressInNames(key_ev,pn_changing,pn_selected_btn_index)1739 void KeyPressInNames(key_ev, pn_changing, pn_selected_btn_index)
1740 XKeyEvent *key_ev;
1741 int *pn_changing, *pn_selected_btn_index;
1742 {
1743 struct NamesRec *pni=(&namesInfo);
1744 char buf[80];
1745 KeySym key_sym;
1746 int has_ch;
1747
1748 has_ch = XLookupString(key_ev, buf, sizeof(buf), &key_sym, &c_stat);
1749 TranslateKeys(buf, &key_sym);
1750
1751 if ((key_ev->state & ControlMask) && key_sym == XK_j) {
1752 SpecialKeyInNames(key_ev, key_sym, pn_changing, pn_selected_btn_index);
1753 } else if (CharIsCRorLF(key_ev, buf, key_sym, &has_ch)) {
1754 if (pni->edit_style == NAMES_SELECT_FILE) {
1755 if (!pni->tabbed_from_root) {
1756 TabInNames();
1757 }
1758 *pn_changing = FALSE;
1759 *pn_selected_btn_index = GetBtnIndexFromBtnId(pni->def_btn_id);
1760 } else {
1761 if (pni->def_btn_id != INVALID) {
1762 *pn_changing = FALSE;
1763 *pn_selected_btn_index = GetBtnIndexFromBtnId(pni->def_btn_id);
1764 }
1765 }
1766 } else if (CharIsESC(key_ev, buf, key_sym, &has_ch)) {
1767 *pn_changing = FALSE;
1768 *pn_selected_btn_index = GetBtnIndexFromBtnId(BUTTON_CANCEL);
1769 } else if (CharIsBSorDEL(key_ev, buf, key_sym, &has_ch, FALSE)) {
1770 if (pni->edit_style == NAMES_SELECT_FILE &&
1771 (pni->faking_dot_dot || pni->pop_from_root)) {
1772 *pn_changing = FALSE;
1773 *pn_selected_btn_index = INVALID;
1774 } else {
1775 BackSpaceInNames(pn_changing, pn_selected_btn_index);
1776 }
1777 } else if (CharIsTAB(key_ev, buf, key_sym, &has_ch)) {
1778 if (pni->edit_style == NAMES_SELECT_FILE && pni->change_to_root) {
1779 TabInNames();
1780 *pn_changing = FALSE;
1781 *pn_selected_btn_index = INVALID;
1782 }
1783 } else if ((!pni->tabbed_from_root || pni->num_entries != 0) &&
1784 ((key_sym>'\040' && key_sym<='\177' &&
1785 (key_ev->state & ControlMask)) || key_sym==XK_Up ||
1786 key_sym==XK_Down || key_sym==XK_KP_Up || key_sym==XK_KP_Down ||
1787 key_sym==XK_Page_Up || key_sym==XK_KP_Page_Up ||
1788 key_sym==XK_Page_Down || key_sym==XK_KP_Page_Down)) {
1789 SpecialKeyInNames(key_ev, key_sym, pn_changing, pn_selected_btn_index);
1790 } else if (key_sym>='\040' && key_sym<='\177' &&
1791 (!pni->tabbed_from_root || pni->num_entries != 0)) {
1792 CharInNames(buf, pn_changing, pn_selected_btn_index);
1793 }
1794 }
1795
1796 static
ButtonPressInPath(button_ev)1797 void ButtonPressInPath(button_ev)
1798 XButtonEvent *button_ev;
1799 {
1800 struct NamesRec *pni=(&namesInfo);
1801
1802 if (button_ev->button == Button1) {
1803 } else if (button_ev->button == Button2) {
1804 int buf_len=0, from_selection=FALSE;
1805 char *cut_buffer=NULL;
1806
1807 switch (pni->edit_style) {
1808 case NAMES_SIMPLE_SELECT_NAME: return;
1809 case NAMES_COMPLEX_SELECT_NAME: return;
1810 case NAMES_SELECT_FILE:
1811 if (pni->tabbed_from_root) return;
1812 break;
1813 case NAMES_EDIT_ATTR: break;
1814 case NAMES_EDIT_NAME: break;
1815 }
1816 cut_buffer = FetchSelectionOrCutBuffer(&buf_len, &from_selection);
1817 if (cut_buffer != NULL) {
1818 char *c_ptr=cut_buffer;
1819 int max_len;
1820
1821 if (pni->edit_style == NAMES_SELECT_FILE) {
1822 max_len = sizeof(pni->inbuf)-strlen(pni->dir_name)-3;
1823 while (pni->name_index < max_len &&
1824 *c_ptr >= '\040' && *c_ptr < '\177') {
1825 pni->name[pni->name_index++] = (*c_ptr++);
1826 }
1827 pni->name[pni->name_index] = '\0';
1828 sprintf(pni->inbuf, "%s%c%s", pni->dir_name, DIR_SEP, pni->name);
1829 pni->buf_index = strlen(pni->inbuf);
1830 } else {
1831 max_len = sizeof(pni->inbuf)-strlen(pni->inbuf)-3;
1832 while (pni->buf_index < max_len &&
1833 *c_ptr >= '\040' && *c_ptr < '\177') {
1834 pni->inbuf[pni->buf_index++] = (*c_ptr++);
1835 }
1836 pni->inbuf[pni->buf_index] = '\0';
1837 strcpy(&(pni->entries[pni->marked_index])[pni->leading],
1838 pni->inbuf);
1839 }
1840 if (pni->exposed) {
1841 RedrawNamePath();
1842 RedrawDspWindow();
1843 }
1844 FreeSelectionOrCutBuffer(cut_buffer, from_selection);
1845 }
1846 } else if (button_ev->button == Button3) {
1847 }
1848 }
1849
1850 static
ButtonPressInNames(button_ev,pn_changing,pn_selected_btn_index)1851 void ButtonPressInNames(button_ev, pn_changing, pn_selected_btn_index)
1852 XButtonEvent *button_ev;
1853 int *pn_changing, *pn_selected_btn_index;
1854 {
1855 struct NamesRec *pni=(&namesInfo);
1856
1857 if (button_ev->window == pni->base_win) {
1858 int i;
1859
1860 if (PointInBBox(button_ev->x, button_ev->y, pni->path_bbox)) {
1861 ButtonPressInPath(button_ev);
1862 } else {
1863 for (i=0; i < pni->num_btns; i++) {
1864 if (PointInBBox(button_ev->x, button_ev->y,
1865 pni->btn_bbox[i])) {
1866 struct BBRec *bbox=(&(pni->btn_bbox[i]));
1867 char *btn_str=pni->btn_str[i];
1868 int looping=TRUE, selected=TRUE, len=strlen(btn_str);
1869 XEvent ev;
1870
1871 XGrabPointer(mainDisplay, pni->base_win, False,
1872 PointerMotionMask | ButtonReleaseMask, GrabModeAsync,
1873 GrabModeAsync, None, handCursor, CurrentTime);
1874 DisplayButtonInBBox(pni->base_win, btn_str, len,
1875 bbox, BUTTON_INVERT, FALSE, 0, NULL);
1876 while (looping) {
1877 XNextEvent(mainDisplay, &ev);
1878
1879 if (ev.type == ButtonRelease) {
1880 XUngrabPointer(mainDisplay, CurrentTime);
1881 if (debugNoPointerGrab) XSync(mainDisplay, False);
1882 looping = FALSE;
1883 } else if (ev.type == MotionNotify) {
1884 if (PointInBBox(ev.xmotion.x, ev.xmotion.y,
1885 pni->btn_bbox[i])) {
1886 if (!selected) {
1887 selected = TRUE;
1888 DisplayButtonInBBox(pni->base_win, btn_str, len,
1889 bbox, BUTTON_INVERT, FALSE, 0, NULL);
1890 }
1891 } else {
1892 if (selected) {
1893 selected = FALSE;
1894 DisplayButtonInBBox(pni->base_win, btn_str, len,
1895 bbox, BUTTON_NORMAL, FALSE, 0, NULL);
1896 }
1897 }
1898 }
1899 }
1900 if (selected) {
1901 *pn_changing = FALSE;
1902 *pn_selected_btn_index = i;
1903 DisplayButtonInBBox(pni->base_win, btn_str, len, bbox,
1904 BUTTON_NORMAL, FALSE, 0, NULL);
1905 }
1906 break;
1907 }
1908 }
1909 }
1910 } else if (button_ev->window == pni->scroll_win) {
1911 NameScrollHandler(button_ev);
1912 } else if (button_ev->window == pni->dsp_win) {
1913 int double_clicked=(NameDspHandler(button_ev)!=INVALID);
1914
1915 if (pni->marked_index != INVALID) {
1916 if (pni->edit_style == NAMES_SELECT_FILE) {
1917 strcpy(pni->name,
1918 &(pni->entries[pni->marked_index])[pni->leading]);
1919 pni->name_index = strlen(pni->name);
1920 sprintf(pni->inbuf, "%s%c%s", pni->dir_name, DIR_SEP, pni->name);
1921 pni->buf_index = strlen(pni->inbuf);
1922 } else {
1923 strcpy(pni->inbuf,
1924 &(pni->entries[pni->marked_index])[pni->leading]);
1925 pni->buf_index = strlen(pni->inbuf);
1926 }
1927 RedrawNamePath();
1928 if (double_clicked && pni->double_click_btn_id != INVALID) {
1929 *pn_changing = FALSE;
1930 *pn_selected_btn_index =
1931 GetBtnIndexFromBtnId(pni->double_click_btn_id);
1932 }
1933 }
1934 }
1935 }
1936
NamesSetDefaultBtnId(def_btn_id,double_click_btn_id)1937 void NamesSetDefaultBtnId(def_btn_id, double_click_btn_id)
1938 int def_btn_id, double_click_btn_id;
1939 {
1940 struct NamesRec *pni=(&namesInfo);
1941
1942 pni->def_btn_id = def_btn_id;
1943 pni->double_click_btn_id = double_click_btn_id;
1944 }
1945
NamesSetStyle(edit_style,loop_once)1946 void NamesSetStyle(edit_style, loop_once)
1947 int edit_style, loop_once;
1948 {
1949 struct NamesRec *pni=(&namesInfo);
1950
1951 pni->edit_style = edit_style;
1952 pni->loop_once = loop_once;
1953 }
1954
NamesSetEntries(dsp_ptr,entries,num_entries,p_check_array,dont_free_entries,marked_index,leading)1955 void NamesSetEntries(dsp_ptr, entries, num_entries, p_check_array,
1956 dont_free_entries, marked_index, leading)
1957 DspList *dsp_ptr;
1958 char **entries;
1959 int num_entries, dont_free_entries, marked_index, leading;
1960 struct CheckArrayRec *p_check_array;
1961 {
1962 struct NamesRec *pni=(&namesInfo);
1963
1964 pni->dsp_ptr = dsp_ptr;
1965 pni->entries = entries;
1966 pni->num_entries = num_entries;
1967 pni->p_check_array = p_check_array;
1968 pni->dont_free_entries = dont_free_entries;
1969 pni->marked_index = marked_index;
1970 pni->leading = leading;
1971 }
1972
NamesSetCallback(pf_before_loop,pf_after_loop,pf_check_update)1973 void NamesSetCallback(pf_before_loop, pf_after_loop, pf_check_update)
1974 GetEntriesFunc *pf_before_loop;
1975 AfterLoopFunc *pf_after_loop;
1976 CheckUpdateFunc *pf_check_update;
1977 {
1978 struct NamesRec *pni=(&namesInfo);
1979
1980 if (pni->dsp_ptr != NULL || pni->entries != NULL) {
1981 #ifdef _TGIF_DBG /* debug, do not translate */
1982 sprintf(gszMsgBox, "%s.",
1983 "dsp_ptr != NULL || entries != NULL in NamesSetCallback()");
1984 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1985 #endif /* _TGIF_DBG */
1986 if (pni->dsp_ptr != NULL) free(pni->dsp_ptr);
1987 if (pni->entries != NULL) {
1988 free(*(pni->entries));
1989 free(pni->entries);
1990 }
1991 }
1992 pni->dsp_ptr = NULL;
1993 pni->entries = NULL;
1994 pni->num_entries = 0;
1995 pni->pf_before_loop = pf_before_loop;
1996 pni->pf_after_loop = pf_after_loop;
1997 pni->pf_check_update = pf_check_update;
1998 }
1999
NamesSetDir(dir_name)2000 void NamesSetDir(dir_name)
2001 char *dir_name;
2002 {
2003 struct NamesRec *pni=(&namesInfo);
2004
2005 if (pni->edit_style != NAMES_SELECT_FILE) {
2006 #ifdef _TGIF_DBG /* debug, do not translate */
2007 sprintf(gszMsgBox, "%s!\n\nNamesSetDir() called with %s.",
2008 "Programing error", "pni->edit_style != NAMES_SELECT_FILE.");
2009 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
2010 #endif /* _TGIF_DBG */
2011 }
2012 UtilStrCpyN(pni->dir_name, sizeof(pni->dir_name), dir_name);
2013 }
2014
2015 static
BeforeLoopForSelectFile()2016 void BeforeLoopForSelectFile()
2017 {
2018 struct NamesRec *pni=(&namesInfo);
2019
2020 if (pni->faking_dot_dot) {
2021 *pni->name = '\0';
2022 pni->name_index = 0;
2023 } else if (pni->tabbed_from_root &&
2024 !pni->just_tabbed_from_root) {
2025 pni->name[0] = '\0';
2026 pni->name_index = 0;
2027 } else if (pni->tabbed_from_root && pni->just_tabbed_from_root) {
2028 pni->name_index = strlen(pni->name);
2029 if (!SetMarkedIndex()) {
2030 pni->name[0] = '\0';
2031 pni->name_index = 0;
2032 }
2033 }
2034 sprintf(pni->inbuf, "%s%c%s", pni->dir_name, DIR_SEP, pni->name);
2035 pni->buf_index = strlen(pni->inbuf);
2036
2037 if (pni->exposed) {
2038 XClearWindow(mainDisplay, pni->base_win);
2039 RedrawNameBaseWindow();
2040 }
2041 pni->pop_from_root = FALSE;
2042 }
2043
2044 static
GetParentRealDir(dir,buf,buf_sz)2045 int GetParentRealDir(dir, buf, buf_sz)
2046 char *dir, *buf;
2047 int buf_sz;
2048 {
2049 int rc=FALSE;
2050 char saved_cur_dir[MAXPATHLENGTH];
2051
2052 if (!GetWorkingDirectory(saved_cur_dir, sizeof(saved_cur_dir))) {
2053 *saved_cur_dir = '\0';
2054 }
2055 if (SetWorkingDirectory(dir) && SetWorkingDirectory("..")) {
2056 if (GetWorkingDirectory(buf, buf_sz)) {
2057 rc = TRUE;
2058 }
2059 }
2060 if (*saved_cur_dir != '\0') {
2061 SetWorkingDirectory(saved_cur_dir);
2062 }
2063 return rc;
2064 }
2065
2066 static
BreakForSelectFileAfterLoop()2067 int BreakForSelectFileAfterLoop()
2068 {
2069 struct NamesRec *pni=(&namesInfo);
2070
2071 if (pni->marked_index == INVALID && !pni->change_to_root &&
2072 !pni->pop_from_root && !pni->just_tabbed_from_root) {
2073 return TRUE;
2074 } else if (FileIsRemote(pni->name)) {
2075 pni->remote_file = TRUE;
2076 return TRUE;
2077 }
2078 if (pni->inbuf[pni->buf_index-1] != DIR_SEP) {
2079 if (!pni->just_tabbed_from_root) {
2080 return TRUE;
2081 }
2082 } else {
2083 if (pni->name[0] == '.' && pni->name[1] == '.' &&
2084 pni->name[2] == DIR_SEP) {
2085 /* need to find out what's the real directory */
2086 char parent_dir[MAXPATHLENGTH];
2087
2088 if (GetParentRealDir(pni->dir_name, parent_dir, sizeof(parent_dir))) {
2089 int len=0;
2090
2091 len = strlen(parent_dir);
2092 if (len > 0 && parent_dir[len-1] == DIR_SEP) {
2093 parent_dir[--len] = '\0';
2094 }
2095 sprintf(pni->inbuf, "%s%c..", parent_dir, DIR_SEP);
2096 pni->buf_index = strlen(pni->inbuf);
2097 ParseFileName(pni->inbuf, pni->dir_name, pni->name);
2098 return FALSE;
2099 }
2100 }
2101 pni->inbuf[--(pni->buf_index)] = '\0';
2102 if (pni->name[0] == '.' && pni->name[1] == '.' &&
2103 pni->name[2] == DIR_SEP) {
2104 /* saved_name is used for faking_dot_dot */
2105 int i;
2106
2107 for (i=strlen(pni->dir_name)-1;
2108 i >= 0 && pni->dir_name[i] != DIR_SEP; i--) {
2109 }
2110 if (i < 0) {
2111 strcpy(pni->saved_name, pni->dir_name);
2112 *pni->dir_name = '\0';
2113 } else {
2114 strcpy(pni->saved_name, &(pni->dir_name[i+1]));
2115 pni->dir_name[i] = '\0';
2116 }
2117 } else {
2118 strcpy(&pni->inbuf[pni->buf_index++], DIR_SEP_STR);
2119 ParseFileName(pni->inbuf, pni->dir_name, pni->name);
2120 }
2121 }
2122 return FALSE;
2123 }
2124
Names(win_name,pn_selected_index,selected_str,str_sz,p_void)2125 int Names(win_name, pn_selected_index, selected_str, str_sz, p_void)
2126 char *win_name, *selected_str;
2127 int *pn_selected_index, str_sz;
2128 void *p_void;
2129 {
2130 struct NamesRec *pni=(&namesInfo);
2131 int i, looping=TRUE, selected_btn_index=INVALID, left=0;
2132
2133 if (selected_str != NULL) *selected_str = '\0';
2134 if (pn_selected_index != NULL) *pn_selected_index = INVALID;
2135
2136 if (!CreateNamesWindows(win_name)) return INVALID;
2137
2138 EndMeasureTooltip(FALSE);
2139
2140 pni->userdata = p_void;
2141
2142 if (pni->edit_style == NAMES_SELECT_FILE) {
2143 pni->faking_dot_dot = FALSE;
2144 pni->change_to_root = FALSE;
2145 pni->just_tabbed_from_root = FALSE;
2146 *pni->saved_dir_name = '\0';
2147 }
2148 left = pni->btn_start;
2149 for (i=0; i < pni->num_btns; i++) {
2150 int button_w=ButtonWidth(pni->btn_str[i], 8, NULL), button_h=0;
2151
2152 if (boldMsgFontSet == NULL && boldMsgFontPtr == NULL) {
2153 pni->btn_bbox[i].lty = (6+ITEM_DSPED)*ROW_HEIGHT;
2154 button_h = defaultFontHeight + 4;
2155 } else {
2156 pni->btn_bbox[i].lty = (5+ITEM_DSPED)*ROW_HEIGHT +
2157 (boldMsgFontHeight+1);
2158 button_h = boldMsgFontHeight + 4;
2159 }
2160 pni->btn_bbox[i].ltx = left;
2161 pni->btn_bbox[i].lty -= 2;
2162 pni->btn_bbox[i].rbx = pni->btn_bbox[i].ltx+button_w;
2163 pni->btn_bbox[i].rby = pni->btn_bbox[i].lty+button_h;
2164 left = pni->btn_bbox[i].rbx + 1 + defaultFontWidth;
2165 }
2166 SaveStatusStrings();
2167 while (looping) {
2168 int changing=TRUE;
2169
2170 if (pni->edit_style == NAMES_SELECT_FILE) {
2171 BeforeLoopForSelectFile();
2172 }
2173 if (pni->pf_before_loop != NULL) {
2174 int rc;
2175 char saved_ch='\0';
2176
2177 SetWatchCursor(drawWindow);
2178 SetWatchCursor(mainWindow);
2179 SetWatchCursor(pni->base_win);
2180 if (pni->edit_style == NAMES_SELECT_FILE && !pni->tabbed_from_root &&
2181 !pni->just_tabbed_from_root) {
2182 saved_ch = *pni->inbuf;
2183 *pni->inbuf = '\0';
2184 }
2185 rc = (pni->pf_before_loop)(&pni->dsp_ptr,
2186 &pni->entries, &pni->num_entries,
2187 &pni->marked_index, &pni->p_check_array, pni->inbuf, p_void);
2188 if (pni->edit_style == NAMES_SELECT_FILE && !pni->tabbed_from_root &&
2189 !pni->just_tabbed_from_root) {
2190 *pni->inbuf = saved_ch;
2191 }
2192 if (pni->edit_style == NAMES_SELECT_FILE &&
2193 pni->just_tabbed_from_root) {
2194 /* saved_name is used for just_tabbed_from_root */
2195 *pni->dir_name = '\0';
2196 strcpy(pni->name, pni->saved_name);
2197 pni->name_index = strlen(pni->name);
2198 sprintf(pni->inbuf, "%s%c%s", pni->dir_name, DIR_SEP, pni->name);
2199 pni->buf_index = strlen(pni->inbuf);
2200 *pni->saved_name = '\0';
2201 ParseFileName(pni->inbuf, pni->dir_name, pni->name);
2202 pni->name_index = strlen(pni->name);
2203 if (!SetMarkedIndex()) {
2204 pni->name[0] = '\0';
2205 pni->name_index = 0;
2206 }
2207 }
2208 if (pni->edit_style == NAMES_SELECT_FILE && pni->faking_dot_dot) {
2209 /* saved_name is used for faking_dot_dot */
2210 strcpy(pni->name, pni->saved_name);
2211 pni->name_index = strlen(pni->name);
2212 sprintf(pni->inbuf, "%s%c%s", pni->dir_name, DIR_SEP, pni->name);
2213 pni->buf_index = strlen(pni->inbuf);
2214 *pni->saved_name = '\0';
2215 if (!SetMarkedIndex()) {
2216 pni->name[0] = '\0';
2217 pni->name_index = 0;
2218 }
2219 }
2220 SetDefaultCursor(mainWindow);
2221 ShowCursor();
2222 SetDrawCursor(pni->base_win);
2223 if (!rc) break;
2224 }
2225 if (pni->edit_style == NAMES_SELECT_FILE) {
2226 pni->just_tabbed_from_root = FALSE;
2227 pni->faking_dot_dot = FALSE;
2228 }
2229 NamesUpdateIndices();
2230
2231 if (pni->pf_before_loop != NULL && pni->exposed) {
2232 RedrawNamePath();
2233 RedrawNameScrollWin();
2234 RedrawDspWindow();
2235 RedrawDspBaseWindow();
2236 }
2237 if (pni->dsp_ptr != NULL && pni->marked_index != INVALID) {
2238 SetStringStatus(pni->dsp_ptr[pni->marked_index].pathstr);
2239 }
2240 XSync(mainDisplay, False);
2241
2242 selected_btn_index = INVALID;
2243 while (changing) {
2244 XEvent input, ev;
2245
2246 XNextEvent(mainDisplay, &input);
2247
2248 if (ExposeOrMapNames(&input)) {
2249 continue;
2250 }
2251 if (input.type == Expose) {
2252 ExposeEventHandler(&input, FALSE);
2253 } else if (input.type==VisibilityNotify &&
2254 input.xany.window==mainWindow &&
2255 input.xvisibility.state==VisibilityUnobscured) {
2256 int i;
2257
2258 while (XCheckWindowEvent(mainDisplay, mainWindow,
2259 VisibilityChangeMask, &ev)) ;
2260 if (pinnedMainMenu) XMapRaised(mainDisplay, mainMenuWindow);
2261 for (i=0; i < numExtraWins; i++) {
2262 if (extraWinInfo[i].mapped && extraWinInfo[i].raise &&
2263 extraWinInfo[i].window != None) {
2264 XMapRaised(mainDisplay, extraWinInfo[i].window);
2265 }
2266 }
2267 XMapRaised(mainDisplay, pni->base_win);
2268 } else if (input.type == KeyPress) {
2269 KeyPressInNames(&input.xkey, &changing, &selected_btn_index);
2270 } else if (input.type == ButtonPress) {
2271 ButtonPressInNames(&input.xbutton, &changing, &selected_btn_index);
2272 } else if ((input.xany.window==pni->base_win ||
2273 input.xany.window==pni->dsp_base_win ||
2274 input.xany.window==pni->dsp_win ||
2275 input.xany.window==pni->scroll_win) &&
2276 IsWM_DELETE_WINDOW(&input)) {
2277 KeyPressInNames(&input.xkey, &changing, &selected_btn_index);
2278 changing = FALSE;
2279 selected_btn_index = INVALID;
2280 }
2281 }
2282 if (pni->exposed && selected_btn_index != INVALID) {
2283 DisplayButtonInBBox(pni->base_win, pni->btn_str[selected_btn_index],
2284 strlen(pni->btn_str[selected_btn_index]),
2285 &(pni->btn_bbox[selected_btn_index]), BUTTON_INVERT, FALSE, 0,
2286 NULL);
2287 XSync(mainDisplay, False);
2288 }
2289 if (pni->edit_style == NAMES_SELECT_FILE) {
2290 if (pni->marked_index != INVALID) {
2291 strcpy(pni->name,
2292 &(pni->entries[pni->marked_index])[pni->leading]);
2293 pni->name_index = strlen(pni->name);
2294 sprintf(pni->inbuf, "%s%c%s", pni->dir_name, DIR_SEP, pni->name);
2295 pni->buf_index = strlen(pni->inbuf);
2296 }
2297 }
2298 if (pni->pf_after_loop != NULL) {
2299 int btn_id=INVALID;
2300
2301 if (selected_btn_index != INVALID) {
2302 btn_id = pni->btn_id[selected_btn_index];
2303 }
2304 if (!(pni->pf_after_loop)(&pni->dsp_ptr,
2305 &pni->entries, &pni->num_entries,
2306 &pni->marked_index, &pni->p_check_array, pni->inbuf, btn_id,
2307 pni->marked_index, p_void)) {
2308 looping = FALSE;
2309 }
2310 }
2311 if (selected_btn_index != INVALID) {
2312 if (pni->btn_id[selected_btn_index] == BUTTON_CANCEL) {
2313 looping = FALSE;
2314 }
2315 }
2316 if (pni->edit_style == NAMES_SELECT_FILE) {
2317 if (BreakForSelectFileAfterLoop()) {
2318 looping = FALSE;
2319 }
2320 }
2321 if (pni->loop_once == NAMES_LOOP_ONCE) {
2322 looping = FALSE;
2323 }
2324 if (pni->exposed && selected_btn_index != INVALID) {
2325 DisplayButtonInBBox(pni->base_win, pni->btn_str[selected_btn_index],
2326 strlen(pni->btn_str[selected_btn_index]),
2327 &(pni->btn_bbox[selected_btn_index]), BUTTON_NORMAL, FALSE, 0,
2328 NULL);
2329 XSync(mainDisplay, False);
2330 }
2331 }
2332 RestoreStatusStrings();
2333 XDestroyWindow(mainDisplay, pni->base_win);
2334 if (warpToWinCenter) {
2335 XWarpPointer(mainDisplay, None, drawWindow, 0, 0, 0, 0,
2336 (int)(ZOOMED_SIZE(drawWinW)>>1), (int)(ZOOMED_SIZE(drawWinH)>>1));
2337 }
2338 if (selected_str != NULL) {
2339 if (pni->remote_file) {
2340 UtilStrCpyN(selected_str, str_sz, pni->name);
2341 } else {
2342 UtilStrCpyN(selected_str, str_sz, pni->inbuf);
2343 }
2344 }
2345 pni->userdata = NULL;
2346
2347 if (pn_selected_index != NULL) *pn_selected_index = pni->marked_index;
2348 if (selected_btn_index != INVALID) {
2349 return pni->btn_id[selected_btn_index];
2350 }
2351 return INVALID;
2352 }
2353