1 /*-------------------------------------------------------------------------*/
2 /* filelist.c --- Xcircuit routines for the filelist widget */
3 /* Copyright (c) 2002 Tim Edwards, Johns Hopkins University */
4 /*-------------------------------------------------------------------------*/
10 #include <sys/types.h>
11 #include <ctype.h> /* For isspace() */
17 #elif !defined(_MSC_VER)
26 #include <X11/Intrinsic.h>
27 #include <X11/StringDefs.h>
28 #include <X11/Shell.h>
29 #include <X11/Xutil.h>
30 #include <X11/cursorfont.h>
37 #include "Xw/WorkSpace.h"
38 #include "Xw/TextEdit.h"
39 #include "Xw/Toggle.h"
43 #if defined(XC_WIN32) && defined(TCL_WRAPPER)
45 #include <X11/Xutil.h>
46 #include <X11/cursorfont.h>
50 /*-------------------------------------------------------------------------*/
52 /*-------------------------------------------------------------------------*/
54 #include "colordefs.h"
57 /*----------------------------------------------------------------------*/
58 /* Function prototype declarations */
59 /*----------------------------------------------------------------------*/
60 #include "prototypes.h"
62 /*-------------------------------------------------------------------------*/
63 /* Local definitions */
64 /*-------------------------------------------------------------------------*/
68 /*-------------------------------------------------------------------------*/
69 /* Global Variable definitions */
70 /*-------------------------------------------------------------------------*/
73 extern Tcl_Interp
*xcinterp
;
77 extern XCWindowData
*areawin
;
78 extern ApplicationData appdata
;
79 extern colorindex
*colorlist
;
80 extern short popups
; /* total number of popup windows */
81 extern char _STR2
[250];
82 extern char _STR
[150];
83 extern Globaldata xobjs
;
85 Pixmap flistpix
= (Pixmap
)NULL
; /* For file-selection widget */
86 short flstart
, flfiles
, flcurrent
;
89 GC hgc
= NULL
, sgc
= NULL
;
91 fileliststruct
*files
;
93 #if !defined(XC_WIN32) || defined(TCL_WRAPPER)
95 /*-------------------------------------------------------------------------*/
96 /* Compare two filenames (for use by qsort()) */
97 /*-------------------------------------------------------------------------*/
99 int fcompare(const void *a
, const void *b
)
101 return (strcmp((char *)(((fileliststruct
*)a
)->filename
),
102 (char *)(((fileliststruct
*)b
)->filename
)));
105 /*-------------------------------------------------------------------------*/
106 /* Routines for drawing a box around the currently selected file */
107 /*-------------------------------------------------------------------------*/
109 void dragfilebox(xcWidget w
, caddr_t clientdata
, XMotionEvent
*event
)
113 Window lwin
= xcWindow(w
);
115 filenum
= (event
->y
- 10 + FILECHARHEIGHT
) / FILECHARHEIGHT
+ flstart
- 1;
116 if (filenum
< 0) filenum
= 0;
117 else if (filenum
>= flfiles
) filenum
= flfiles
- 1;
119 if (filenum
== flcurrent
) return;
121 if (flcurrent
>= 0) /* erase previous box */
122 XDrawRectangle(dpy
, lwin
, areawin
->gc
, 5,
123 10 + FILECHARHEIGHT
* (flcurrent
124 - flstart
), flcurwidth
+ 10, FILECHARHEIGHT
);
126 if (files
== NULL
) return;
128 twidth
= XTextWidth(appdata
.filefont
, files
[filenum
].filename
,
129 strlen(files
[filenum
].filename
));
130 XDrawRectangle(dpy
, lwin
, areawin
->gc
, 5,
131 10 + FILECHARHEIGHT
* (filenum
132 - flstart
), twidth
+ 10, FILECHARHEIGHT
);
138 /*-------------------------------------------------------------------------*/
139 /* Begin tracking the cursor position relative to the files in the list */
140 /*-------------------------------------------------------------------------*/
142 void startfiletrack(xcWidget w
, caddr_t clientdata
, XCrossingEvent
*event
)
145 Tk_CreateEventHandler(w
, PointerMotionMask
,
146 (Tk_EventProc
*)xctk_dragfilebox
, (ClientData
)w
);
148 xcAddEventHandler(w
, PointerMotionMask
, False
, (xcEventHandler
)dragfilebox
, NULL
);
151 XSetFunction(dpy
, areawin
->gc
, GXcopy
);
152 XSetForeground(dpy
, areawin
->gc
, colorlist
[AUXCOLOR
].color
.pixel
);
153 XSetLineAttributes(dpy
, areawin
->gc
, 1, LineSolid
, CapRound
, JoinMiter
);
155 /* draw initial box */
158 dragfilebox(w
, NULL
, (XMotionEvent
*)event
);
160 XSetFunction(dpy
, areawin
->gc
, GXxor
);
161 XSetForeground(dpy
, areawin
->gc
, colorlist
[AUXCOLOR
].color
.pixel
^
162 colorlist
[BACKGROUND
].color
.pixel
);
165 /*-------------------------------------------------------------------------*/
166 /* Stop tracking the cursor and return to default state */
167 /*-------------------------------------------------------------------------*/
169 void endfiletrack(xcWidget w
, caddr_t clientdata
, XCrossingEvent
*event
)
171 Window lwin
= xcWindow(w
);
173 XDrawRectangle(dpy
, lwin
, areawin
->gc
, 5,
174 10 + FILECHARHEIGHT
* (flcurrent
175 - flstart
), flcurwidth
+ 10, FILECHARHEIGHT
);
178 Tk_DeleteEventHandler(w
, PointerMotionMask
,
179 (Tk_EventProc
*)xctk_dragfilebox
, (ClientData
)w
);
181 xcRemoveEventHandler(w
, PointerMotionMask
, False
,
182 (xcEventHandler
)dragfilebox
, NULL
);
185 /* Restore graphics state values */
186 XSetForeground(dpy
, areawin
->gc
, colorlist
[areawin
->gccolor
].color
.pixel
);
187 XSetFunction(dpy
, areawin
->gc
, GXcopy
);
192 /*----------------------------------------------------------------------*/
193 /* Read a crash file to find the name of the original file. */
194 /*----------------------------------------------------------------------*/
196 char *getcrashfilename()
200 char *retstr
= NULL
, *tpos
, *spos
;
203 if ((fi
= fopen(_STR2
, "r")) != NULL
) {
204 while (fgets(temp
, 255, fi
) != NULL
) {
205 if ((tpos
= strstr(temp
, "Title:")) != NULL
) {
208 if ((spos
= strrchr(temp
, '/')) != NULL
)
210 retstr
= (char *)malloc(1 + strlen(tpos
));
211 strcpy(retstr
, tpos
);
213 else if ((tpos
= strstr(temp
, "CreationDate:")) != NULL
) {
216 slen
= strlen(retstr
);
217 retstr
= (char *)realloc(retstr
, 4 + slen
+ strlen(tpos
));
218 sprintf(retstr
+ slen
, " (%s)", tpos
);
227 /*----------------------------------------------------------------------*/
228 /* Crash recovery: load the file, and link the tempfile name to it. */
229 /*----------------------------------------------------------------------*/
233 if (xobjs
.tempfile
!= NULL
) {
234 unlink(xobjs
.tempfile
);
235 free(xobjs
.tempfile
);
236 xobjs
.tempfile
= NULL
;
238 if (strlen(_STR2
) == 0) {
239 Wprintf("Error: No temp file name for crash recovery!");
242 xobjs
.tempfile
= strdup(_STR2
);
247 /*----------------------------------------------------------------------*/
248 /* Look for any files left over from a crash. */
249 /*----------------------------------------------------------------------*/
251 void findcrashfiles()
257 uid_t userid
= getuid();
263 cwd
= opendir(xobjs
.tempdir
);
264 if (cwd
== NULL
) return; /* No tmp directory, no tmp files! */
266 while ((dp
= readdir(cwd
)) != NULL
) {
267 sprintf(_STR
, "%s/%s", xobjs
.tempdir
, dp
->d_name
);
268 snptr
= _STR
+ strlen(xobjs
.tempdir
) + 1;
269 if (!strncmp(snptr
, "XC", 2)) {
270 char *dotptr
= strchr(snptr
, '.');
272 if (dotptr
&& dotptr
> snptr
+ 2) {
274 if (sscanf(snptr
+ 2, "%d", &pid
) != 1)
278 if ((!stat(_STR
, &sbuf
))
280 && (sbuf
.st_uid
== userid
)
283 if ((recent
== 0) || (sbuf
.st_ctime
> recent
)) {
285 /* Check if the PID belongs to an active process */
286 /* by sending a CONT signal and checking if */
287 /* there was no error result. */
291 if (kill((pid_t
)pid
, SIGCONT
) == 0)
295 recent
= sbuf
.st_ctime
;
303 if (recent
> 0) { /* There exists at least one temporary file */
304 /* belonging to this user. Ask to recover */
305 /* the most recent one. */
307 /* Warn user of existing tempfile, and ask user if file */
308 /* should be recovered immediately. */
311 char *cfile
= getcrashfilename();
313 sprintf(_STR
, ".query.title.field configure -text "
314 "\"Recover file \'%s\'?\"",
315 (cfile
== NULL
) ? "(unknown)" : cfile
);
316 Tcl_Eval(xcinterp
, _STR
);
317 Tcl_Eval(xcinterp
, ".query.bbar.okay configure -command "
318 "{filerecover; wm withdraw .query}; wm deiconify .query");
319 if (cfile
!= NULL
) free(cfile
);
321 getfile(NULL
, (pointertype
)RECOVER
, NULL
); /* Crash recovery mode */
326 /*----------------------------------------------------------------------*/
327 /* Match a filename extension against the file filter list. */
328 /*----------------------------------------------------------------------*/
330 #if !defined(XC_WIN32) || defined(TCL_WRAPPER)
332 Boolean
match_filter(char *fname
, char *filter
)
334 char *dotptr
= strrchr(fname
, '.');
335 char *filtptr
, *endptr
;
338 if (filter
== NULL
) return False
;
339 if (dotptr
== NULL
) return False
;
341 /* New 11/08: Empty string for filter is a wildcard match, the same */
342 /* as turning off the filter. */
344 if (filter
[0] == '\0') return True
;
347 extlen
= strlen(dotptr
);
350 while (*filtptr
!= '\0') {
352 while (*endptr
!= '\0' && !isspace(*endptr
)) endptr
++;
353 filtlen
= (int)(endptr
- filtptr
);
354 if (filtlen
== extlen
)
355 if (!strncmp(dotptr
, filtptr
, extlen
))
359 while (*filtptr
!= '\0' && isspace(*filtptr
)) filtptr
++;
364 /*----------------------------------------------------------------------*/
365 /* Make a list of the files in the list widget window */
366 /*----------------------------------------------------------------------*/
368 void listfiles(xcWidget w
, popupstruct
*okaystruct
, caddr_t calldata
)
376 Window lwin
= xcWindow(w
);
377 short allocd
= INITDIRS
;
382 Dimension textwidth
, textheight
;
384 filter
= okaystruct
->filter
;
387 values
.foreground
= colorlist
[FOREGROUND
].color
.pixel
;
388 values
.font
= appdata
.filefont
->fid
;
389 values
.function
= GXcopy
;
390 values
.graphics_exposures
= False
;
391 sgc
= XCreateGC(dpy
, lwin
, GCForeground
| GCFont
| GCFunction
392 | GCGraphicsExposures
, &values
);
396 textwidth
= Tk_Width(w
);
397 textheight
= Tk_Height(w
);
399 XtnSetArg(XtNwidth
, &textwidth
);
400 XtnSetArg(XtNheight
, &textheight
);
401 XtGetValues(w
, wargs
, n
);
404 /* Generate a new flistpix pixmap if currently nonexistent */
408 /* get list of files in the current directory (cwd) */
411 if (cwdname
== NULL
) {
412 cwdname
= (char *) malloc (sizeof(char));
415 if (cwdname
[0] == '\0')
418 cwd
= opendir(cwdname
);
420 /* If current directory cannot be accessed for some reason, */
421 /* print "Invalid Directory" to the file list window. */
424 XSetForeground(dpy
, sgc
, colorlist
[BACKGROUND
].color
.pixel
);
425 XFillRectangle(dpy
, lwin
, sgc
, 0, 0, textwidth
, textheight
);
426 XSetForeground(dpy
, sgc
, colorlist
[AUXCOLOR
].color
.pixel
);
427 XDrawString(dpy
, lwin
, sgc
, 10, textheight
/ 2,
428 "(Invalid Directory)", 19);
433 files
= (fileliststruct
*) malloc (INITDIRS
* sizeof(fileliststruct
));
435 /* write the contents of the current directory into the */
436 /* array "filenames[]" (except for current directory ".") */
438 while ((dp
= readdir(cwd
)) != NULL
) {
439 /* don't put current directory in list */
440 if (!strcmp(dp
->d_name
, ".")) continue;
442 /* record the type of file */
444 sprintf(_STR2
, "%s%s", cwdname
, dp
->d_name
);
445 if (stat(_STR2
, &statbuf
)) continue;
446 if ((statbuf
.st_mode
& S_IFDIR
) != 0) /* is a directory */
447 files
[flfiles
].filetype
= DIRECTORY
;
448 else if (match_filter(dp
->d_name
, filter
))
449 files
[flfiles
].filetype
= MATCH
;
451 if (xobjs
.filefilter
)
454 files
[flfiles
].filetype
= NONMATCH
;
457 /* save the filename */
459 files
[flfiles
].filename
= (char *) malloc ((strlen(dp
->d_name
) +
460 ((files
[flfiles
].filetype
== DIRECTORY
) ? 2 : 1)) * sizeof(char));
461 strcpy(files
[flfiles
].filename
, dp
->d_name
);
462 if (files
[flfiles
].filetype
== DIRECTORY
)
463 strcat(files
[flfiles
].filename
, "/");
464 if (++flfiles
== allocd
) {
466 files
= (fileliststruct
*) realloc(files
,
467 allocd
* sizeof(fileliststruct
));
473 /* sort the files[] array into alphabetical order (like "ls") */
475 qsort((void *)files
, (size_t)flfiles
, sizeof(fileliststruct
), fcompare
);
477 pixheight
= flfiles
* FILECHARHEIGHT
+ 25;
478 if (pixheight
< textheight
) pixheight
= textheight
;
480 flistpix
= XCreatePixmap(dpy
, areawin
->window
, textwidth
, pixheight
,
481 DefaultDepthOfScreen(xcScreen(w
)));
483 /* Write the filenames onto the pixmap */
485 XSetForeground(dpy
, sgc
, colorlist
[BACKGROUND
].color
.pixel
);
486 XFillRectangle(dpy
, flistpix
, sgc
, 0, 0, textwidth
, pixheight
);
487 XSetForeground(dpy
, sgc
, colorlist
[FOREGROUND
].color
.pixel
);
488 for (n
= 0; n
< flfiles
; n
++) {
489 switch (files
[n
].filetype
) {
491 XSetForeground(dpy
, sgc
, colorlist
[SELECTCOLOR
].color
.pixel
);
494 XSetForeground(dpy
, sgc
, colorlist
[FILTERCOLOR
].color
.pixel
);
497 XSetForeground(dpy
, sgc
, colorlist
[FOREGROUND
].color
.pixel
);
500 XDrawString(dpy
, flistpix
, sgc
, 10, 10 + FILECHARASCENT
+ n
* FILECHARHEIGHT
,
501 files
[n
].filename
, strlen(files
[n
].filename
));
505 /* Copy the pixmap of filenames into the file list window */
507 XSetForeground(dpy
, sgc
, colorlist
[BACKGROUND
].color
.pixel
);
508 XFillRectangle(dpy
, lwin
, sgc
, 0, 0, textwidth
, textheight
);
509 XCopyArea(dpy
, flistpix
, lwin
, sgc
, 0, flstart
* FILECHARHEIGHT
,
510 textwidth
, textheight
, 0, 0);
513 /*-------------------------------------------------------------------------*/
514 /* Generate a new pixmap for writing the filelist and set the scrollbar */
515 /* size accordingly. */
516 /*-------------------------------------------------------------------------*/
518 void newfilelist(xcWidget w
, popupstruct
*okaystruct
)
525 char *cstr
= (char *)Tcl_GetVar2(xcinterp
, "XCOps", "filter", 0);
527 Wprintf("Error: No variable $XCOps(filter) in Tcl!");
530 result
= Tcl_GetBoolean(xcinterp
, cstr
, &bval
);
531 if (result
!= TCL_OK
) {
532 Wprintf("Error: Bad variable $XCOps(filter) in Tcl!");
535 xobjs
.filefilter
= bval
;
537 xcWidget textw
= okaystruct
->textw
;
540 for (n
= 0; n
< flfiles
; n
++)
541 free(files
[n
].filename
);
543 if (flistpix
!= (Pixmap
)NULL
) XFreePixmap(dpy
, flistpix
);
545 flistpix
= (Pixmap
)NULL
;
547 listfiles(w
, okaystruct
, NULL
);
549 showlscroll(Tk_NameToWindow(xcinterp
, ".filelist.listwin.sb", w
), NULL
, NULL
);
550 Tcl_Eval(xcinterp
, ".filelist.textent.txt delete 0 end");
551 sprintf(_STR2
, ".filelist.textent.txt insert 0 %s", cwdname
);
552 Tcl_Eval(xcinterp
, _STR2
);
554 showlscroll(XtNameToWidget(xcParent(w
), "LScroll"), NULL
, NULL
);
555 XwTextClearBuffer(textw
);
556 XwTextInsert(textw
, cwdname
);
561 /*-------------------------------------------------------------------------*/
562 /* Button press handler for file list window */
563 /*-------------------------------------------------------------------------*/
565 void fileselect(xcWidget w
, popupstruct
*okaystruct
, XButtonEvent
*event
)
567 Window lwin
= xcWindow(w
);
568 Dimension textwidth
, textheight
;
573 textwidth
= Tk_Width(w
);
574 textheight
= Tk_Height(w
);
578 xcWidget textw
= okaystruct
->textw
;
580 XtnSetArg(XtNwidth
, &textwidth
);
581 XtnSetArg(XtNheight
, &textheight
);
582 XtGetValues(w
, wargs
, n
);
587 if (files
== NULL
) return; /* shouldn't happen */
589 /* third mouse button cancels selection and reverts buffer to cwd name */
591 if (event
->button
== Button3
) {
592 newfilelist(w
, okaystruct
);
596 filenum
= (event
->y
- 10 + FILECHARHEIGHT
) / FILECHARHEIGHT
+ flstart
- 1;
597 if (filenum
< 0) filenum
= 0;
598 else if (filenum
>= flfiles
) filenum
= flfiles
- 1;
600 /* Attempt to enter invalid directory. . . treat like button 3 */
603 newfilelist(w
, okaystruct
);
607 /* check if this file is a directory or not */
609 if (strchr(files
[filenum
].filename
, '/') == NULL
) {
611 /* highlight the entry. . . */
613 XSetForeground(dpy
, sgc
, colorlist
[AUXCOLOR
].color
.pixel
);
614 XDrawString(dpy
, flistpix
, sgc
, 10, 10 + FILECHARASCENT
+ filenum
* FILECHARHEIGHT
,
615 files
[filenum
].filename
, strlen(files
[filenum
].filename
));
616 XCopyArea(dpy
, flistpix
, lwin
, sgc
, 0, flstart
* FILECHARHEIGHT
,
617 textwidth
, textheight
, 0, 0);
619 /* . . .and append it to the text field */
622 Tcl_Eval(xcinterp
, ".filelist.textent.txt get");
623 ebuf
= (char *)Tcl_GetStringResult(xcinterp
);
624 tbuf
= (char *)malloc((strlen(ebuf
) +
625 strlen(files
[filenum
].filename
) + 6) * sizeof(char));
627 ebuf
= (char *)XwTextCopyBuffer(textw
);
628 tbuf
= (char *)malloc((XwTextGetLastPos(textw
)
629 + strlen(files
[filenum
].filename
) + 5) * sizeof(char));
633 /* add a comma if there is already text in the destination buffer */
635 if (tbuf
[0] != '\0') {
636 if (tbuf
[strlen(tbuf
) - 1] != '/') strcat(tbuf
, ",");
639 if (cwdname
!= NULL
) {
640 if (cwdname
[0] != '\0') {
641 tbuf
= (char *)realloc(tbuf
, (strlen(cwdname
) +
642 strlen(files
[filenum
].filename
) + 5) * sizeof(char));
643 strcpy(tbuf
, cwdname
);
647 strcat(tbuf
, files
[filenum
].filename
);
649 Tcl_Eval(xcinterp
, ".filelist.textent.txt delete 0 end");
650 sprintf(_STR2
, ".filelist.textent.txt insert 0 %s", tbuf
);
651 Tcl_Eval(xcinterp
, _STR2
);
653 XwTextClearBuffer(textw
);
654 XwTextInsert(textw
, tbuf
);
659 else { /* move to new directory */
661 if (!strcmp(files
[filenum
].filename
, "../")) {
662 char *cptr
, *sptr
= cwdname
;
663 if (!strcmp(cwdname
, "/")) return; /* no way up from root dir. */
664 while(strstr(sptr
, "../") != NULL
) sptr
+= 3;
665 if ((cptr
= strrchr(sptr
, '/')) != NULL
) {
667 if ((cptr
= strrchr(sptr
, '/')) != NULL
) *(cptr
+ 1) = '\0';
671 cwdname
= (char *)realloc(cwdname
, (strlen(cwdname
) +
673 strcat(cwdname
, "../");
677 cwdname
= (char *)realloc(cwdname
, (strlen(cwdname
) +
678 strlen(files
[filenum
].filename
) + 1) * sizeof(char));
679 strcat(cwdname
, files
[filenum
].filename
);
681 newfilelist(w
, okaystruct
);
685 /*-------------------------------------------------------------------------*/
686 /* Scrollbar handler for file list widget */
687 /*-------------------------------------------------------------------------*/
689 void showlscroll(xcWidget w
, caddr_t clientdata
, caddr_t calldata
)
691 Window swin
= xcWindow(w
);
692 Dimension swidth
, sheight
;
693 int pstart
, pheight
, finscr
;
696 swidth
= Tk_Width(w
);
697 sheight
= Tk_Height(w
);
703 XtnSetArg(XtNwidth
, &swidth
);
704 XtnSetArg(XtNheight
, &sheight
);
705 XtGetValues(w
, wargs
, n
);
708 XClearWindow(dpy
, swin
);
710 if (flfiles
> 0) { /* no files, no bar */
712 finscr
= sheight
/ FILECHARHEIGHT
;
713 if (finscr
> flfiles
) finscr
= flfiles
;
715 pstart
= (flstart
* sheight
) / flfiles
;
716 pheight
= (finscr
* sheight
) / flfiles
;
718 XSetForeground(dpy
, sgc
, colorlist
[BARCOLOR
].color
.pixel
);
719 XFillRectangle(dpy
, swin
, sgc
, 0, pstart
, swidth
, pheight
);
724 /*-------------------------------------------------------------------------*/
725 /* Button Motion handler for moving the scrollbar up and down */
726 /*-------------------------------------------------------------------------*/
728 void draglscroll(xcWidget w
, popupstruct
*okaystruct
, XButtonEvent
*event
)
731 int phheight
, finscr
, flsave
= flstart
;
732 xcWidget filew
= okaystruct
->filew
;
735 sheight
= Tk_Height(w
);
740 XtnSetArg(XtNheight
, &sheight
);
741 XtGetValues(w
, wargs
, n
);
744 finscr
= sheight
/ FILECHARHEIGHT
;
745 if (finscr
> flfiles
) finscr
= flfiles
;
747 /* center scrollbar on pointer vertical position */
749 phheight
= (finscr
* sheight
) / (flfiles
* 2);
750 flstart
= (event
->y
> phheight
) ? ((event
->y
- phheight
) * flfiles
) / sheight
: 0;
751 if (flstart
> (flfiles
- finscr
+ 2)) flstart
= (flfiles
- finscr
+ 2);
753 if (flstart
!= flsave
) {
754 showlscroll(w
, NULL
, NULL
);
755 listfiles(filew
, okaystruct
, NULL
);
759 /*----------------------------------------------------------------------*/
760 /* Set/unset the file filtering function */
761 /*----------------------------------------------------------------------*/
765 void setfilefilter(xcWidget w
, popupstruct
*okaystruct
, caddr_t calldata
)
767 xobjs
.filefilter
= (xobjs
.filefilter
) ? False
: True
;
769 /* Force regeneration of the file list */
771 newfilelist(okaystruct
->filew
, okaystruct
);
776 /*----------------------------------------------------------------------*/
777 /* Generate the file list window */
778 /*----------------------------------------------------------------------*/
782 void genfilelist(xcWidget parent
, popupstruct
*okaystruct
, Dimension width
)
784 xcWidget listarea
, lscroll
, entertext
;
786 entertext
= okaystruct
->textw
;
787 listarea
= Tk_NameToWindow(xcinterp
, ".filelist.listwin.win", parent
);
789 xcAddEventHandler(listarea
, ButtonPressMask
, False
,
790 (xcEventHandler
)fileselect
, okaystruct
);
791 xcAddEventHandler(listarea
, EnterWindowMask
, False
,
792 (xcEventHandler
)startfiletrack
, NULL
);
793 xcAddEventHandler(listarea
, LeaveWindowMask
, False
,
794 (xcEventHandler
)endfiletrack
, NULL
);
796 okaystruct
->filew
= listarea
;
798 lscroll
= Tk_NameToWindow(xcinterp
, ".filelist.listwin.sb", parent
);
800 Tk_CreateEventHandler(lscroll
, Button1MotionMask
| Button2MotionMask
,
801 (Tk_EventProc
*)xctk_draglscroll
, (ClientData
)okaystruct
);
803 /* force new file list, in case the highlight filter changed */
805 if (flistpix
!= (Pixmap
)NULL
) XFreePixmap(dpy
, flistpix
);
806 flistpix
= (Pixmap
)NULL
;
811 void genfilelist(xcWidget parent
, popupstruct
*okaystruct
, Dimension width
)
814 xcWidget listarea
, lscroll
, entertext
, dofilter
;
821 scale
= Tcl_GetVar2(xcinterp
, "XCOps", "scale", TCL_GLOBAL_ONLY
);
822 sbarsize
= SBARSIZE
* atoi(scale
);
828 XtnSetArg(XtNy
, FILECHARHEIGHT
- 10);
829 XtnSetArg(XtNwidth
, width
- sbarsize
- 40);
830 XtnSetArg(XtNheight
, LISTHEIGHT
- FILECHARHEIGHT
);
831 XtnSetArg(XtNfont
, appdata
.filefont
);
833 entertext
= okaystruct
->textw
;
835 listarea
= XtCreateManagedWidget("Filelist", XwworkSpaceWidgetClass
,
836 parent
, wargs
, n
); n
= 0;
837 XtAddCallback(listarea
, XtNexpose
, (XtCallbackProc
)listfiles
, okaystruct
);
839 xcAddEventHandler(listarea
, ButtonPressMask
, False
,
840 (xcEventHandler
)fileselect
, okaystruct
);
841 xcAddEventHandler(listarea
, EnterWindowMask
, False
,
842 (xcEventHandler
)startfiletrack
, NULL
);
843 xcAddEventHandler(listarea
, LeaveWindowMask
, False
,
844 (xcEventHandler
)endfiletrack
, NULL
);
846 okaystruct
->filew
= listarea
;
848 XtnSetArg(XtNx
, width
- sbarsize
- 20);
849 XtnSetArg(XtNy
, FILECHARHEIGHT
- 10);
850 XtnSetArg(XtNwidth
, sbarsize
);
851 XtnSetArg(XtNheight
, LISTHEIGHT
- FILECHARHEIGHT
);
852 XtnSetArg(XtNfont
, appdata
.xcfont
);
854 lscroll
= XtCreateManagedWidget("LScroll", XwworkSpaceWidgetClass
,
855 parent
, wargs
, n
); n
= 0;
857 XtAddCallback(lscroll
, XtNexpose
, (XtCallbackProc
)showlscroll
, NULL
);
858 xcAddEventHandler(lscroll
, Button1MotionMask
| Button2MotionMask
,
859 False
, (xcEventHandler
)draglscroll
, okaystruct
);
861 /* Add a toggle widget to turn file filtering on/off */
863 wwidth
= XTextWidth(appdata
.xcfont
, "filter", strlen("filter"));
864 XtnSetArg(XtNx
, width
- wwidth
- 50);
865 XtnSetArg(XtNy
, LISTHEIGHT
+ 10);
866 XtnSetArg(XtNset
, xobjs
.filefilter
);
867 XtnSetArg(XtNsquare
, True
);
868 XtnSetArg(XtNborderWidth
, 0);
869 XtnSetArg(XtNfont
, appdata
.xcfont
);
870 XtnSetArg(XtNlabelLocation
, XwLEFT
);
871 dofilter
= XtCreateManagedWidget("Filter", XwtoggleWidgetClass
,
872 parent
, wargs
, n
); n
= 0;
873 XtAddCallback(dofilter
, XtNselect
, (XtCallbackProc
)setfilefilter
, okaystruct
);
874 XtAddCallback(dofilter
, XtNrelease
, (XtCallbackProc
)setfilefilter
, okaystruct
);
876 /* force new file list, in case the highlight filter changed */
878 if (flistpix
!= (Pixmap
)NULL
) XFreePixmap(dpy
, flistpix
);
879 flistpix
= (Pixmap
)NULL
;
882 #endif /* TCL_WRAPPER */
886 /*-------------------------------------------------------------------------*/
887 /* Look for a directory name in a string and update cwdname accordingly */
888 /*-------------------------------------------------------------------------*/
890 int lookdirectory(char *lstring
, int nchars
)
895 xc_tilde_expand(lstring
, nchars
);
896 slen
= strlen(lstring
);
898 if (lstring
[slen
- 1] == '/' || ((cwd
=opendir(lstring
)) != NULL
)) {
899 if (cwd
) closedir(cwd
);
900 if (lstring
[slen
- 1] != '/') strcat(lstring
, "/");
901 cwdname
= (char *)realloc(cwdname
, (slen
+ 2) * sizeof(char));
902 strcpy(cwdname
, lstring
);
908 /*-------------------------------------------------------------------------*/