1 /* vi:set ts=8 sts=4 sw=4: */
4 * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
6 * Permission to use, copy, modify, and distribute this software and its
7 * documentation for any purpose and without fee is hereby granted, provided
8 * that the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Software Research Associates not be used
11 * in advertising or publicity pertaining to distribution of the software
12 * without specific, written prior permission. Software Research Associates
13 * makes no representations about the suitability of this software for any
14 * purpose. It is provided "as is" without express or implied warranty.
16 * SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
18 * IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
19 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
20 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
21 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
24 * Author: Erik M. van der Poel
25 * Software Research Associates, Inc., Tokyo, Japan
31 * erik%sra.co.jp@uunet.uu.net
32 * erik%sra.co.jp@mcvax.uucp
33 * try junet instead of co.jp
34 * Erik M. van der Poel
35 * Software Research Associates, Inc.
36 * 1-1-1 Hirakawa-cho, Chiyoda-ku
37 * Tokyo 102 Japan. TEL +81-3-234-2692
41 * Heavely modified for Vim by Bram Moolenaar
46 /* Only include this when using the file browser */
50 /* Weird complication: for "make lint" Text.h doesn't combine with Xm.h */
51 #if defined(FEAT_GUI_MOTIF) && defined(FMT8BIT)
55 #ifndef FEAT_GUI_NEXTAW
56 # include "gui_at_sb.h"
59 /***************** SFinternal.h */
61 #include <X11/Intrinsic.h>
62 #include <X11/StringDefs.h>
64 #ifdef FEAT_GUI_NEXTAW
65 # include <X11/neXtaw/Text.h>
66 # include <X11/neXtaw/AsciiText.h>
67 # include <X11/neXtaw/Scrollbar.h>
69 # include <X11/Xaw/Text.h>
70 # include <X11/Xaw/AsciiText.h>
73 #define SEL_FILE_CANCEL -1
75 #define SEL_FILE_NULL 1
76 #define SEL_FILE_TEXT 2
78 #define SF_DO_SCROLL 1
79 #define SF_DO_NOT_SCROLL 0
103 static char SFstartDir
[MAXPATHL
],
104 SFcurrentPath
[MAXPATHL
],
105 SFcurrentDir
[MAXPATHL
];
107 static Widget selFile
,
118 static Display
*SFdisplay
;
120 static int SFcharWidth
, SFcharAscent
, SFcharHeight
;
122 static SFDir
*SFdirs
= NULL
;
127 static Pixel SFfore
, SFback
;
129 static Atom SFwmDeleteWindow
;
131 static XSegment SFsegs
[2], SFcompletionSegs
[2];
133 static XawTextPosition SFtextPos
;
135 static int SFupperX
, SFlowerY
, SFupperY
;
137 static int SFtextX
, SFtextYoffset
;
139 static int SFentryWidth
, SFentryHeight
;
141 static int SFlineToTextH
= 3;
142 static int SFlineToTextV
= 3;
144 static int SFbesideText
= 3;
145 static int SFaboveAndBelowText
= 2;
147 static int SFcharsPerEntry
= 15;
149 static int SFlistSize
= 10;
151 static int SFcurrentInvert
[3] = { -1, -1, -1 };
153 static int SFworkProcAdded
= 0;
155 static XtAppContext SFapp
;
157 static int SFpathScrollWidth
, SFvScrollHeight
, SFhScrollWidth
;
160 static char SFtextBuffer
[MAXPATHL
*sizeof(wchar_t)];
162 static char SFtextBuffer
[MAXPATHL
];
165 static int SFbuttonPressed
= 0;
167 static XtIntervalId SFdirModTimerId
;
169 static int (*SFfunc
)();
171 static int SFstatus
= SEL_FILE_NULL
;
173 /***************** static functions */
175 static void SFsetText
__ARGS((char *path
));
176 static void SFtextChanged
__ARGS((void));
177 static char *SFgetText
__ARGS((void));
178 static void SFupdatePath
__ARGS((void));
179 static int SFgetDir
__ARGS((SFDir
*dir
));
180 static void SFdrawLists
__ARGS((int doScroll
));
181 static void SFdrawList
__ARGS((int n
, int doScroll
));
182 static void SFclearList
__ARGS((int n
, int doScroll
));
183 static void SFbuttonPressList
__ARGS((Widget w
, int n
, XButtonPressedEvent
*event
));
184 static void SFbuttonReleaseList
__ARGS((Widget w
, int n
, XButtonReleasedEvent
*event
));
185 static void SFdirModTimer
__ARGS((XtPointer cl
, XtIntervalId
*id
));
186 static char SFstatChar
__ARGS((struct stat
*statBuf
));
187 static void SFdrawStrings
__ARGS((Window w
, SFDir
*dir
, int from
, int to
));
188 static int SFnewInvertEntry
__ARGS((int n
, XMotionEvent
*event
));
189 static void SFinvertEntry
__ARGS((int n
));
190 static void SFenterList
__ARGS((Widget w
, int n
, XEnterWindowEvent
*event
));
191 static void SFleaveList
__ARGS((Widget w
, int n
, XEvent
*event
));
192 static void SFmotionList
__ARGS((Widget w
, int n
, XMotionEvent
*event
));
193 static void SFvFloatSliderMovedCallback
__ARGS((Widget w
, XtPointer n
, XtPointer fnew
));
194 static void SFvSliderMovedCallback
__ARGS((Widget w
, int n
, int nw
));
195 static void SFvAreaSelectedCallback
__ARGS((Widget w
, XtPointer n
, XtPointer pnew
));
196 static void SFhSliderMovedCallback
__ARGS((Widget w
, XtPointer n
, XtPointer nw
));
197 static void SFhAreaSelectedCallback
__ARGS((Widget w
, XtPointer n
, XtPointer pnew
));
198 static void SFpathSliderMovedCallback
__ARGS((Widget w
, XtPointer client_data
, XtPointer nw
));
199 static void SFpathAreaSelectedCallback
__ARGS((Widget w
, XtPointer client_data
, XtPointer pnew
));
200 static Boolean SFworkProc
__ARGS((void));
201 static int SFcompareEntries
__ARGS((const void *p
, const void *q
));
202 static void SFprepareToReturn
__ARGS((void));
203 static void SFcreateWidgets
__ARGS((Widget toplevel
, char *prompt
, char *ok
, char *cancel
));
204 static void SFsetColors
__ARGS((guicolor_T bg
, guicolor_T fg
, guicolor_T scroll_bg
, guicolor_T scrollfg
));
206 /***************** xstat.h */
209 # define S_IXUSR 0100
212 # define S_IXGRP 0010
215 # define S_IXOTH 0001
218 #define S_ISXXX(m) ((m) & (S_IXUSR | S_IXGRP | S_IXOTH))
220 /***************** Path.c */
230 static int SFdoNotTouchDirPtr
= 0;
232 static int SFdoNotTouchVorigin
= 0;
234 static SFDir SFrootDir
, SFhomeDir
;
236 static SFLogin
*SFlogins
;
238 static int SFtwiddle
= 0;
240 static int SFchdir
__ARGS((char *path
));
250 if (strcmp(path
, SFcurrentDir
))
252 result
= mch_chdir(path
);
254 (void) strcpy(SFcurrentDir
, path
);
260 static void SFfree
__ARGS((int i
));
271 for (j
= dir
->nEntries
- 1; j
>= 0; j
--)
273 if (dir
->entries
[j
].shown
!= dir
->entries
[j
].real
)
274 XtFree(dir
->entries
[j
].shown
);
275 XtFree(dir
->entries
[j
].real
);
278 XtFree((char *)dir
->entries
);
284 static void SFstrdup
__ARGS((char **s1
, char *s2
));
291 *s1
= strcpy(XtMalloc((unsigned)(strlen(s2
) + 1)), s2
);
294 static void SFunreadableDir
__ARGS((SFDir
*dir
));
300 char *cannotOpen
= _("<cannot open> ");
302 dir
->entries
= (SFEntry
*) XtMalloc(sizeof(SFEntry
));
303 dir
->entries
[0].statDone
= 1;
304 SFstrdup(&dir
->entries
[0].real
, cannotOpen
);
305 dir
->entries
[0].shown
= dir
->entries
[0].real
;
307 dir
->nChars
= strlen(cannotOpen
);
310 static void SFreplaceText
__ARGS((SFDir
*dir
, char *str
));
313 SFreplaceText(dir
, str
)
321 if (str
[len
- 1] == '/')
322 (void) strcat(SFcurrentPath
, str
);
324 (void) strncat(SFcurrentPath
, str
, len
- 1);
325 if (strncmp(SFcurrentPath
, SFstartDir
, strlen(SFstartDir
)))
326 SFsetText(SFcurrentPath
);
328 SFsetText(&(SFcurrentPath
[strlen(SFstartDir
)]));
333 static void SFexpand
__ARGS((char *str
));
341 char *name
, *growing
;
343 SFEntry
*entry
, *max
;
347 dir
= &(SFdirs
[SFdirEnd
- 1]);
349 if (dir
->beginSelection
== -1)
352 SFreplaceText(dir
, str
);
356 else if (dir
->beginSelection
== dir
->endSelection
)
358 SFreplaceText(dir
, dir
->entries
[dir
->beginSelection
].shown
);
362 max
= &(dir
->entries
[dir
->endSelection
+ 1]);
364 name
= dir
->entries
[dir
->beginSelection
].shown
;
365 SFstrdup(&growing
, name
);
370 entry
= &(dir
->entries
[dir
->beginSelection
]);
373 if ((cmp
= strncmp(growing
, entry
->shown
, len
)))
381 * SFreplaceText() expects filename
383 growing
[len
- 2] = ' ';
385 growing
[len
- 1] = 0;
386 SFreplaceText(dir
, growing
);
390 static int SFfindFile
__ARGS((SFDir
*dir
, char *str
));
406 if (str
[len
- 1] == ' ')
411 else if (str
[len
- 1] == '/')
416 entries
= dir
->entries
;
421 name
= entries
[i
].shown
;
422 last
= strlen(name
) - 1;
426 result
= strncmp(str
, name
, len
);
436 name
= entries
[i
].shown
;
437 last
= strlen(name
) - 1;
441 result
= strncmp(str
, name
, len
);
452 if ((dir
->beginSelection
!= begin
) || (dir
->endSelection
!= end
- 1))
455 dir
->beginSelection
= begin
;
456 if (str
[strlen(str
) - 1] == '/')
457 dir
->endSelection
= begin
;
459 dir
->endSelection
= end
- 1;
462 else if (dir
->beginSelection
!= -1)
465 dir
->beginSelection
= -1;
466 dir
->endSelection
= -1;
469 if (SFdoNotTouchVorigin
470 || ((begin
> dir
->vOrigin
) && (end
< dir
->vOrigin
+ SFlistSize
)))
472 SFdoNotTouchVorigin
= 0;
477 if (i
> max
- SFlistSize
)
478 i
= max
- SFlistSize
;
482 if (dir
->vOrigin
!= i
)
491 static void SFunselect
__ARGS((void));
498 dir
= &(SFdirs
[SFdirEnd
- 1]);
499 if (dir
->beginSelection
!= -1)
501 dir
->beginSelection
= -1;
502 dir
->endSelection
= -1;
505 static int SFcompareLogins
__ARGS((const void *p
, const void *q
));
508 SFcompareLogins(p
, q
)
511 return strcmp(((SFLogin
*)p
)->name
, ((SFLogin
*)q
)->name
);
514 static void SFgetHomeDirs
__ARGS((void));
522 SFEntry
*entries
= NULL
;
528 entries
= (SFEntry
*)XtMalloc(sizeof(SFEntry
));
529 SFlogins
= (SFLogin
*)XtMalloc(sizeof(SFLogin
));
530 entries
[0].real
= XtMalloc(3);
531 (void) strcpy(entries
[0].real
, "~");
532 entries
[0].shown
= entries
[0].real
;
533 entries
[0].statDone
= 1;
534 SFlogins
[0].name
= "";
535 pw
= getpwuid((int) getuid());
536 SFstrdup(&SFlogins
[0].dir
, pw
? pw
->pw_dir
: "/");
541 while ((pw
= getpwent()) && (*(pw
->pw_name
)))
546 entries
= (SFEntry
*) XtRealloc((char *)entries
,
547 (unsigned)(Alloc
* sizeof(SFEntry
)));
548 SFlogins
= (SFLogin
*) XtRealloc((char *)SFlogins
,
549 (unsigned)(Alloc
* sizeof(SFLogin
)));
551 len
= strlen(pw
->pw_name
);
552 entries
[i
].real
= XtMalloc((unsigned) (len
+ 3));
553 (void) strcat(strcpy(entries
[i
].real
, "~"), pw
->pw_name
);
554 entries
[i
].shown
= entries
[i
].real
;
555 entries
[i
].statDone
= 1;
558 SFstrdup(&SFlogins
[i
].name
, pw
->pw_name
);
559 SFstrdup(&SFlogins
[i
].dir
, pw
->pw_dir
);
563 SFhomeDir
.dir
= XtMalloc(1);
564 SFhomeDir
.dir
[0] = 0;
565 SFhomeDir
.path
= SFcurrentPath
;
566 SFhomeDir
.entries
= entries
;
567 SFhomeDir
.nEntries
= i
;
568 SFhomeDir
.vOrigin
= 0; /* :-) */
569 SFhomeDir
.nChars
= maxChars
+ 2;
570 SFhomeDir
.hOrigin
= 0;
571 SFhomeDir
.changed
= 1;
572 SFhomeDir
.beginSelection
= -1;
573 SFhomeDir
.endSelection
= -1;
575 qsort((char *)entries
, (size_t)i
, sizeof(SFEntry
), SFcompareEntries
);
576 qsort((char *)SFlogins
, (size_t)i
, sizeof(SFLogin
), SFcompareLogins
);
578 for (i
--; i
>= 0; i
--)
579 (void)strcat(entries
[i
].real
, "/");
582 static int SFfindHomeDir
__ARGS((char *begin
, char *end
));
585 SFfindHomeDir(begin
, end
)
595 for (i
= SFhomeDir
.nEntries
- 1; i
>= 0; i
--)
597 if (!strcmp(SFhomeDir
.entries
[i
].real
, begin
))
600 SFstrdup(&theRest
, end
);
601 (void) strcat(strcat(strcpy(SFcurrentPath
,
602 SFlogins
[i
].dir
), "/"), theRest
);
604 SFsetText(SFcurrentPath
);
619 static int wasTwiddle
= 0;
623 int SFdirPtrSave
, SFdirEndSave
;
628 SFdirs
= (SFDir
*) XtMalloc((Alloc
= 10) * sizeof(SFDir
));
630 SFstrdup(&dir
->dir
, "/");
632 (void) SFgetDir(dir
);
633 for (j
= 1; j
< Alloc
; j
++)
634 SFdirs
[j
].dir
= NULL
;
635 dir
->path
= SFcurrentPath
+ 1;
639 dir
->beginSelection
= -1;
640 dir
->endSelection
= -1;
641 SFhomeDir
.dir
= NULL
;
644 SFdirEndSave
= SFdirEnd
;
647 SFdirPtrSave
= SFdirPtr
;
652 if (SFcurrentPath
[0] == '~')
665 SFdoNotTouchDirPtr
= 1;
677 end
= SFcurrentPath
+ 1;
686 while (*end
++ == '/')
690 while ((*end
) && (*end
++ != '/'))
692 if ((end
- SFcurrentPath
<= SFtextPos
) && (*(end
- 1) == '/'))
700 if (*(end
- 1) == '/')
706 if (SFfindHomeDir(begin
, end
))
714 SFdirs
= (SFDir
*) XtRealloc((char *) SFdirs
,
715 (unsigned)((Alloc
*= 2) * sizeof(SFDir
)));
716 for (j
= Alloc
/ 2; j
< Alloc
; j
++)
717 SFdirs
[j
].dir
= NULL
;
720 if ((!(dir
->dir
)) || prevChange
|| strcmp(dir
->dir
, begin
))
725 SFstrdup(&dir
->dir
, begin
);
730 dir
->beginSelection
= -1;
731 dir
->endSelection
= -1;
732 (void)SFfindFile(dir
- 1, begin
);
733 if (SFchdir(SFcurrentPath
) || SFgetDir(dir
))
735 SFunreadableDir(dir
);
745 if (SFfindFile(&(SFdirs
[SFdirEnd
-1]), begin
))
753 if ((end
== SFcurrentPath
+ 1) && (!SFtwiddle
))
756 for (i
= SFdirEnd
; i
< Alloc
; i
++)
760 if (SFdoNotTouchDirPtr
)
765 SFdirPtr
= SFdirEnd
- 2;
770 SFdirPtr
= SFdirPtrSave
;
771 SFdoNotTouchDirPtr
= 0;
774 if ((SFdirPtr
!= SFdirPtrSave
) || (SFdirEnd
!= SFdirEndSave
))
776 #ifdef FEAT_GUI_NEXTAW
777 XawScrollbarSetThumb( selFileHScroll
,
778 (float) (((double) SFdirPtr
) / SFdirEnd
),
779 (float) (((double) ((SFdirEnd
< 3) ? SFdirEnd
: 3)) /
782 vim_XawScrollbarSetThumb( selFileHScroll
,
783 (float) (((double) SFdirPtr
) / SFdirEnd
),
784 (float) (((double) ((SFdirEnd
< 3) ? SFdirEnd
: 3)) /
790 if (SFdirPtr
!= SFdirPtrSave
)
791 SFdrawLists(SF_DO_SCROLL
);
793 for (i
= 0; i
< 3; i
++)
795 if (SFdirPtr
+ i
< SFdirEnd
)
797 if (SFdirs
[SFdirPtr
+ i
].changed
)
799 SFdirs
[SFdirPtr
+ i
].changed
= 0;
800 SFdrawList(i
, SF_DO_SCROLL
);
804 SFclearList(i
, SF_DO_SCROLL
);
808 #ifdef XtNinternational
827 text
.length
= strlen(path
);
829 text
.format
= FMT8BIT
;
831 #ifdef XtNinternational
832 if (_XawTextFormat((TextWidget
)selFileField
) == XawFmtWide
)
834 XawTextReplace(selFileField
, (XawTextPosition
)0,
835 (XawTextPosition
)WcsLen((wchar_t *)&SFtextBuffer
[0]), &text
);
836 XawTextSetInsertionPoint(selFileField
,
837 (XawTextPosition
)WcsLen((wchar_t *)&SFtextBuffer
[0]));
841 XawTextReplace(selFileField
, (XawTextPosition
)0,
842 (XawTextPosition
)strlen(SFtextBuffer
), &text
);
843 XawTextSetInsertionPoint(selFileField
,
844 (XawTextPosition
)strlen(SFtextBuffer
));
847 XawTextReplace(selFileField
, (XawTextPosition
)0,
848 (XawTextPosition
)strlen(SFtextBuffer
), &text
);
849 XawTextSetInsertionPoint(selFileField
,
850 (XawTextPosition
)strlen(SFtextBuffer
));
856 SFbuttonPressList(w
, n
, event
)
859 XButtonPressedEvent
*event
;
866 SFbuttonReleaseList(w
, n
, event
)
869 XButtonReleasedEvent
*event
;
875 if (SFcurrentInvert
[n
] != -1)
878 SFdoNotTouchDirPtr
= 1;
879 SFdoNotTouchVorigin
= 1;
880 dir
= &(SFdirs
[SFdirPtr
+ n
]);
882 dir
->entries
[dir
->vOrigin
+ SFcurrentInvert
[n
]].shown
);
883 SFmotionList(w
, n
, (XMotionEvent
*) event
);
887 static int SFcheckDir
__ARGS((int n
, SFDir
*dir
));
897 if ((!mch_stat(".", &statBuf
)) && (statBuf
.st_mtime
!= dir
->mtime
))
900 * If the pointer is currently in the window that we are about
901 * to update, we must warp it to prevent the user from
902 * accidentally selecting the wrong file.
904 if (SFcurrentInvert
[n
] != -1)
909 XtWindow(selFileLists
[n
]),
918 for (i
= dir
->nEntries
- 1; i
>= 0; i
--)
920 if (dir
->entries
[i
].shown
!= dir
->entries
[i
].real
)
921 XtFree(dir
->entries
[i
].shown
);
922 XtFree(dir
->entries
[i
].real
);
924 XtFree((char *) dir
->entries
);
926 SFunreadableDir(dir
);
927 if (dir
->vOrigin
> dir
->nEntries
- SFlistSize
)
928 dir
->vOrigin
= dir
->nEntries
- SFlistSize
;
929 if (dir
->vOrigin
< 0)
931 if (dir
->hOrigin
> dir
->nChars
- SFcharsPerEntry
)
932 dir
->hOrigin
= dir
->nChars
- SFcharsPerEntry
;
933 if (dir
->hOrigin
< 0)
935 dir
->beginSelection
= -1;
936 dir
->endSelection
= -1;
937 SFdoNotTouchVorigin
= 1;
939 (void) SFfindFile(dir
, (dir
+ 1)->dir
);
941 (void) SFfindFile(dir
, dir
->path
);
943 if (!SFworkProcAdded
)
945 (void) XtAppAddWorkProc(SFapp
, (XtWorkProc
)SFworkProc
, NULL
);
953 static int SFcheckFiles
__ARGS((SFDir
*dir
));
970 to
= dir
->vOrigin
+ SFlistSize
;
971 if (to
> dir
->nEntries
)
974 for (i
= from
; i
< to
; i
++)
976 str
= dir
->entries
[i
].real
;
977 last
= strlen(str
) - 1;
980 if (mch_stat(str
, &statBuf
))
983 newc
= SFstatChar(&statBuf
);
994 SFdirModTimer(cl
, id
)
1003 if ((!SFtwiddle
) && (SFdirPtr
< SFdirEnd
))
1006 if ((n
> 2) || (SFdirPtr
+ n
>= SFdirEnd
))
1010 if ((f
> 2) || (SFdirPtr
+ f
>= SFdirEnd
))
1013 dir
= &(SFdirs
[SFdirPtr
+ n
]);
1014 save
= *(dir
->path
);
1016 if (SFchdir(SFcurrentPath
))
1018 *(dir
->path
) = save
;
1029 *(dir
->path
) = save
;
1030 if (SFcheckDir(n
, dir
) || ((f
== n
) && SFcheckFiles(dir
)))
1031 SFdrawList(n
, SF_DO_SCROLL
);
1035 SFdirModTimerId
= XtAppAddTimeOut(SFapp
, (unsigned long) 1000,
1036 SFdirModTimer
, (XtPointer
) NULL
);
1039 /* Return a single character describing what kind of file STATBUF is. */
1043 struct stat
*statBuf
;
1045 if (S_ISDIR (statBuf
->st_mode
))
1047 if (S_ISREG (statBuf
->st_mode
))
1048 return S_ISXXX (statBuf
->st_mode
) ? '*' : ' ';
1050 if (S_ISSOCK (statBuf
->st_mode
))
1052 #endif /* S_ISSOCK */
1056 /***************** Draw.c */
1058 #ifdef FEAT_GUI_NEXTAW
1059 # include <X11/neXtaw/Cardinals.h>
1061 # include <X11/Xaw/Cardinals.h>
1064 #ifdef FEAT_XFONTSET
1065 # define SF_DEFAULT_FONT "-misc-fixed-medium-r-normal--14-*"
1067 # define SF_DEFAULT_FONT "9x15"
1073 #define ABS(x) (((x) < 0) ? (-(x)) : (x))
1080 static GC SFlineGC
, SFscrollGC
, SFinvertGC
, SFtextGC
;
1082 static XtResource textResources
[] =
1084 #ifdef FEAT_XFONTSET
1085 {XtNfontSet
, XtCFontSet
, XtRString
, sizeof (char *),
1086 XtOffsetOf(TextData
, fontname
), XtRString
, SF_DEFAULT_FONT
},
1088 {XtNfont
, XtCFont
, XtRString
, sizeof (char *),
1089 XtOffsetOf(TextData
, fontname
), XtRString
, SF_DEFAULT_FONT
},
1093 #ifdef FEAT_XFONTSET
1094 static XFontSet SFfont
;
1096 static XFontStruct
*SFfont
;
1099 static int SFcurrentListY
;
1101 static XtIntervalId SFscrollTimerId
;
1103 static void SFinitFont
__ARGS((void));
1109 #ifdef FEAT_XFONTSET
1110 XFontSetExtents
*extents
;
1111 char **missing
, *def_str
;
1115 data
= XtNew(TextData
);
1117 XtGetApplicationResources(selFileForm
, (XtPointer
) data
, textResources
,
1118 XtNumber(textResources
), (Arg
*) NULL
, ZERO
);
1120 #ifdef FEAT_XFONTSET
1121 SFfont
= XCreateFontSet(SFdisplay
, data
->fontname
,
1122 &missing
, &num_missing
, &def_str
);
1124 SFfont
= XLoadQueryFont(SFdisplay
, data
->fontname
);
1128 #ifdef FEAT_XFONTSET
1129 SFfont
= XCreateFontSet(SFdisplay
, SF_DEFAULT_FONT
,
1130 &missing
, &num_missing
, &def_str
);
1132 SFfont
= XLoadQueryFont(SFdisplay
, SF_DEFAULT_FONT
);
1136 EMSG2(_("E616: vim_SelFile: can't get font %s"), SF_DEFAULT_FONT
);
1137 SFstatus
= SEL_FILE_CANCEL
;
1142 #ifdef FEAT_XFONTSET
1143 extents
= XExtentsOfFontSet(SFfont
);
1144 SFcharWidth
= extents
->max_logical_extent
.width
;
1145 SFcharAscent
= -extents
->max_logical_extent
.y
;
1146 SFcharHeight
= extents
->max_logical_extent
.height
;
1148 SFcharWidth
= (SFfont
->max_bounds
.width
+ SFfont
->min_bounds
.width
) / 2;
1149 SFcharAscent
= SFfont
->max_bounds
.ascent
;
1150 SFcharHeight
= SFcharAscent
+ SFfont
->max_bounds
.descent
;
1154 static void SFcreateGC
__ARGS((void));
1160 XRectangle rectangles
[1];
1162 gcValues
.foreground
= SFfore
;
1166 (XtGCMask
)GCForeground
,
1169 SFscrollGC
= XtGetGC(
1174 gcValues
.function
= GXxor
;
1175 gcValues
.foreground
= SFfore
^ SFback
;
1176 gcValues
.background
= SFfore
^ SFback
;
1178 SFinvertGC
= XtGetGC(
1180 (XtGCMask
)GCFunction
| GCForeground
| GCBackground
,
1183 gcValues
.foreground
= SFfore
;
1184 gcValues
.background
= SFback
;
1185 #ifndef FEAT_XFONTSET
1186 gcValues
.font
= SFfont
->fid
;
1189 SFtextGC
= XCreateGC(
1191 XtWindow(selFileLists
[0]),
1192 #ifdef FEAT_XFONTSET
1193 (unsigned long)GCForeground
| GCBackground
,
1195 (unsigned long)GCForeground
| GCBackground
| GCFont
,
1199 rectangles
[0].x
= SFlineToTextH
+ SFbesideText
;
1200 rectangles
[0].y
= 0;
1201 rectangles
[0].width
= SFcharsPerEntry
* SFcharWidth
;
1202 rectangles
[0].height
= SFupperY
+ 1;
1215 SFclearList(n
, doScroll
)
1221 SFcurrentInvert
[n
] = -1;
1223 XClearWindow(SFdisplay
, XtWindow(selFileLists
[n
]));
1225 XDrawSegments(SFdisplay
, XtWindow(selFileLists
[n
]), SFlineGC
, SFsegs
, 2);
1229 dir
= &(SFdirs
[SFdirPtr
+ n
]);
1231 if ((SFdirPtr
+ n
< SFdirEnd
) && dir
->nEntries
&& dir
->nChars
)
1233 #ifdef FEAT_GUI_NEXTAW
1234 XawScrollbarSetThumb(
1236 (float) (((double) dir
->vOrigin
) /
1238 (float) (((double) ((dir
->nEntries
< SFlistSize
)
1239 ? dir
->nEntries
: SFlistSize
)) /
1242 vim_XawScrollbarSetThumb(
1244 (float) (((double) dir
->vOrigin
) /
1246 (float) (((double) ((dir
->nEntries
< SFlistSize
)
1247 ? dir
->nEntries
: SFlistSize
)) /
1249 (double)dir
->nEntries
);
1252 #ifdef FEAT_GUI_NEXTAW
1253 XawScrollbarSetThumb(
1255 (float) (((double) dir
->hOrigin
) / dir
->nChars
),
1256 (float) (((double) ((dir
->nChars
<
1257 SFcharsPerEntry
) ? dir
->nChars
:
1258 SFcharsPerEntry
)) / dir
->nChars
));
1260 vim_XawScrollbarSetThumb(
1262 (float) (((double) dir
->hOrigin
) / dir
->nChars
),
1263 (float) (((double) ((dir
->nChars
<
1264 SFcharsPerEntry
) ? dir
->nChars
:
1265 SFcharsPerEntry
)) / dir
->nChars
),
1266 (double)dir
->nChars
);
1271 #ifdef FEAT_GUI_NEXTAW
1272 XawScrollbarSetThumb(selFileVScrolls
[n
], (float) 0.0,
1275 vim_XawScrollbarSetThumb(selFileVScrolls
[n
], (float) 0.0,
1278 #ifdef FEAT_GUI_NEXTAW
1279 XawScrollbarSetThumb(selFileHScrolls
[n
], (float) 0.0,
1282 vim_XawScrollbarSetThumb(selFileHScrolls
[n
], (float) 0.0,
1289 static void SFdeleteEntry
__ARGS((SFDir
*dir
, SFEntry
*entry
));
1292 SFdeleteEntry(dir
, entry
)
1301 idx
= entry
- dir
->entries
;
1303 if (idx
< dir
->beginSelection
)
1304 dir
->beginSelection
--;
1305 if (idx
<= dir
->endSelection
)
1306 dir
->endSelection
--;
1307 if (dir
->beginSelection
> dir
->endSelection
)
1308 dir
->beginSelection
= dir
->endSelection
= -1;
1310 if (idx
< dir
->vOrigin
)
1313 XtFree(entry
->real
);
1315 end
= &(dir
->entries
[dir
->nEntries
- 1]);
1317 for (e
= entry
; e
< end
; e
++)
1320 if (!(--dir
->nEntries
))
1323 n
= dir
- &(SFdirs
[SFdirPtr
]);
1324 if ((n
< 0) || (n
> 2))
1327 #ifdef FEAT_GUI_NEXTAW
1328 XawScrollbarSetThumb(
1330 (float) (((double) dir
->vOrigin
) / dir
->nEntries
),
1331 (float) (((double) ((dir
->nEntries
< SFlistSize
) ?
1332 dir
->nEntries
: SFlistSize
)) / dir
->nEntries
));
1334 vim_XawScrollbarSetThumb(
1336 (float) (((double) dir
->vOrigin
) / dir
->nEntries
),
1337 (float) (((double) ((dir
->nEntries
< SFlistSize
) ?
1338 dir
->nEntries
: SFlistSize
)) / dir
->nEntries
),
1339 (double)dir
->nEntries
);
1343 static void SFwriteStatChar
__ARGS((char *name
, int last
, struct stat
*statBuf
));
1346 SFwriteStatChar(name
, last
, statBuf
)
1349 struct stat
*statBuf
;
1351 name
[last
] = SFstatChar(statBuf
);
1354 static int SFstatAndCheck
__ARGS((SFDir
*dir
, SFEntry
*entry
));
1357 SFstatAndCheck(dir
, entry
)
1361 struct stat statBuf
;
1366 * must be restored before returning
1368 save
= *(dir
->path
);
1371 if (!SFchdir(SFcurrentPath
))
1373 last
= strlen(entry
->real
) - 1;
1374 entry
->real
[last
] = 0;
1375 entry
->statDone
= 1;
1376 if ((!mch_stat(entry
->real
, &statBuf
))
1378 || (!mch_lstat(entry
->real
, &statBuf
))
1387 if (SFfunc(entry
->real
, &shown
, &statBuf
))
1393 len
= strlen(shown
);
1394 entry
->shown
= XtMalloc((unsigned) (len
+ 2));
1395 (void) strcpy(entry
->shown
, shown
);
1396 SFwriteStatChar(entry
->shown
, len
, &statBuf
);
1397 entry
->shown
[len
+ 1] = 0;
1402 SFdeleteEntry(dir
, entry
);
1404 *(dir
->path
) = save
;
1408 SFwriteStatChar(entry
->real
, last
, &statBuf
);
1411 entry
->real
[last
] = ' ';
1414 *(dir
->path
) = save
;
1420 SFdrawStrings(w
, dir
, from
, to
)
1430 x
= SFtextX
- dir
->hOrigin
* SFcharWidth
;
1432 if (dir
->vOrigin
+ to
>= dir
->nEntries
)
1433 to
= dir
->nEntries
- dir
->vOrigin
- 1;
1434 for (i
= from
; i
<= to
; i
++)
1436 entry
= &(dir
->entries
[dir
->vOrigin
+ i
]);
1437 if (!(entry
->statDone
))
1439 if (SFstatAndCheck(dir
, entry
))
1441 if (dir
->vOrigin
+ to
>= dir
->nEntries
)
1442 to
= dir
->nEntries
- dir
->vOrigin
- 1;
1447 #ifdef FEAT_XFONTSET
1454 SFtextYoffset
+ i
* SFentryHeight
,
1456 strlen(entry
->shown
));
1463 SFtextYoffset
+ i
* SFentryHeight
,
1465 strlen(entry
->shown
));
1467 if (dir
->vOrigin
+ i
== dir
->beginSelection
)
1474 SFlowerY
+ i
* SFentryHeight
,
1475 SFlineToTextH
+ SFentryWidth
- 2,
1476 SFlowerY
+ i
* SFentryHeight
);
1478 if ((dir
->vOrigin
+ i
>= dir
->beginSelection
) &&
1479 (dir
->vOrigin
+ i
<= dir
->endSelection
))
1481 SFcompletionSegs
[0].y1
= SFcompletionSegs
[1].y1
=
1482 SFlowerY
+ i
* SFentryHeight
;
1483 SFcompletionSegs
[0].y2
= SFcompletionSegs
[1].y2
=
1484 SFlowerY
+ (i
+ 1) * SFentryHeight
- 1;
1492 if (dir
->vOrigin
+ i
== dir
->endSelection
)
1499 SFlowerY
+ (i
+ 1) * SFentryHeight
- 1,
1500 SFlineToTextH
+ SFentryWidth
- 2,
1501 SFlowerY
+ (i
+ 1) * SFentryHeight
- 1);
1507 SFdrawList(n
, doScroll
)
1514 SFclearList(n
, doScroll
);
1516 if (SFdirPtr
+ n
< SFdirEnd
)
1518 dir
= &(SFdirs
[SFdirPtr
+ n
]);
1519 w
= XtWindow(selFileLists
[n
]);
1520 #ifdef FEAT_XFONTSET
1526 SFtextX
- dir
->hOrigin
* SFcharWidth
,
1527 SFlineToTextV
+ SFaboveAndBelowText
+ SFcharAscent
,
1535 SFtextX
- dir
->hOrigin
* SFcharWidth
,
1536 SFlineToTextV
+ SFaboveAndBelowText
+ SFcharAscent
,
1540 SFdrawStrings(w
, dir
, 0, SFlistSize
- 1);
1545 SFdrawLists(doScroll
)
1550 for (i
= 0; i
< 3; i
++)
1551 SFdrawList(i
, doScroll
);
1560 XtWindow(selFileLists
[n
]),
1563 SFcurrentInvert
[n
] * SFentryHeight
+ SFlowerY
,
1568 static unsigned long SFscrollTimerInterval
__ARGS((void));
1570 static unsigned long
1571 SFscrollTimerInterval()
1573 static int maxVal
= 200;
1574 static int varyDist
= 50;
1575 static int minDist
= 50;
1579 if (SFcurrentListY
< SFlowerY
)
1580 dist
= SFlowerY
- SFcurrentListY
;
1581 else if (SFcurrentListY
> SFupperY
)
1582 dist
= SFcurrentListY
- SFupperY
;
1584 return (unsigned long) 1;
1586 t
= maxVal
- ((maxVal
/ varyDist
) * (dist
- minDist
));
1594 return (unsigned long)t
;
1597 static void SFscrollTimer
__ARGS((XtPointer p
, XtIntervalId
*id
));
1601 SFscrollTimer(p
, id
)
1611 dir
= &(SFdirs
[SFdirPtr
+ n
]);
1612 save
= dir
->vOrigin
;
1614 if (SFcurrentListY
< SFlowerY
)
1616 if (dir
->vOrigin
> 0)
1617 SFvSliderMovedCallback(selFileVScrolls
[n
], n
, dir
->vOrigin
- 1);
1619 else if (SFcurrentListY
> SFupperY
)
1621 if (dir
->vOrigin
< dir
->nEntries
- SFlistSize
)
1622 SFvSliderMovedCallback(selFileVScrolls
[n
], n
, dir
->vOrigin
+ 1);
1625 if (dir
->vOrigin
!= save
)
1629 #ifdef FEAT_GUI_NEXTAW
1630 XawScrollbarSetThumb(
1632 (float) (((double) dir
->vOrigin
) / dir
->nEntries
),
1633 (float) (((double) ((dir
->nEntries
< SFlistSize
) ?
1634 dir
->nEntries
: SFlistSize
)) / dir
->nEntries
));
1636 vim_XawScrollbarSetThumb(
1638 (float) (((double) dir
->vOrigin
) / dir
->nEntries
),
1639 (float) (((double) ((dir
->nEntries
< SFlistSize
) ?
1640 dir
->nEntries
: SFlistSize
)) / dir
->nEntries
),
1641 (double)dir
->nEntries
);
1646 if (SFbuttonPressed
)
1647 SFscrollTimerId
= XtAppAddTimeOut(SFapp
,
1648 SFscrollTimerInterval(), SFscrollTimer
, (XtPointer
) n
);
1652 SFnewInvertEntry(n
, event
)
1654 XMotionEvent
*event
;
1658 static int SFscrollTimerAdded
= 0;
1663 if (SFdirPtr
+ n
>= SFdirEnd
)
1666 if ((x
>= 0) && (x
<= SFupperX
) && (y
>= SFlowerY
) && (y
<= SFupperY
))
1668 SFDir
*dir
= &(SFdirs
[SFdirPtr
+ n
]);
1670 if (SFscrollTimerAdded
)
1672 SFscrollTimerAdded
= 0;
1673 XtRemoveTimeOut(SFscrollTimerId
);
1676 nw
= (y
- SFlowerY
) / SFentryHeight
;
1677 if (dir
->vOrigin
+ nw
>= dir
->nEntries
)
1683 if (SFbuttonPressed
)
1686 if (!SFscrollTimerAdded
)
1688 SFscrollTimerAdded
= 1;
1689 SFscrollTimerId
= XtAppAddTimeOut(SFapp
,
1690 SFscrollTimerInterval(), SFscrollTimer
,
1700 SFenterList(w
, n
, event
)
1703 XEnterWindowEvent
*event
;
1708 if (SFcurrentInvert
[n
] != -1)
1711 SFcurrentInvert
[n
] = -1;
1714 nw
= SFnewInvertEntry(n
, (XMotionEvent
*) event
);
1717 SFcurrentInvert
[n
] = nw
;
1724 SFleaveList(w
, n
, event
)
1729 if (SFcurrentInvert
[n
] != -1)
1732 SFcurrentInvert
[n
] = -1;
1738 SFmotionList(w
, n
, event
)
1741 XMotionEvent
*event
;
1745 nw
= SFnewInvertEntry(n
, event
);
1747 if (nw
!= SFcurrentInvert
[n
])
1749 if (SFcurrentInvert
[n
] != -1)
1751 SFcurrentInvert
[n
] = nw
;
1759 SFvFloatSliderMovedCallback(w
, n
, fnew
)
1766 nw
= (*(float *)fnew
) * SFdirs
[SFdirPtr
+ (int)(long)n
].nEntries
;
1767 SFvSliderMovedCallback(w
, (int)(long)n
, nw
);
1772 SFvSliderMovedCallback(w
, n
, nw
)
1781 dir
= &(SFdirs
[SFdirPtr
+ n
]);
1789 win
= XtWindow(selFileLists
[n
]);
1791 if (ABS(nw
- old
) < SFlistSize
)
1801 SFlowerY
+ (nw
- old
) * SFentryHeight
,
1802 SFentryWidth
+ SFlineToTextH
,
1803 (SFlistSize
- (nw
- old
)) * SFentryHeight
,
1810 SFlowerY
+ (SFlistSize
- (nw
- old
)) *
1812 SFentryWidth
+ SFlineToTextH
,
1813 (nw
- old
) * SFentryHeight
,
1815 SFdrawStrings(win
, dir
, SFlistSize
- (nw
- old
),
1827 SFentryWidth
+ SFlineToTextH
,
1828 (SFlistSize
- (old
- nw
)) * SFentryHeight
,
1830 SFlowerY
+ (old
- nw
) * SFentryHeight
);
1836 SFentryWidth
+ SFlineToTextH
,
1837 (old
- nw
) * SFentryHeight
,
1839 SFdrawStrings(win
, dir
, 0, old
- nw
);
1849 SFentryWidth
+ SFlineToTextH
,
1850 SFlistSize
* SFentryHeight
,
1852 SFdrawStrings(win
, dir
, 0, SFlistSize
- 1);
1858 SFvAreaSelectedCallback(w
, n
, pnew
)
1864 int nw
= (int)(long)pnew
;
1866 dir
= &(SFdirs
[SFdirPtr
+ (int)(long)n
]);
1868 #ifdef FEAT_GUI_NEXTAW
1871 if (nw
> -SFvScrollHeight
)
1878 if (nw
< SFvScrollHeight
)
1886 if (nw
> dir
->nEntries
- SFlistSize
)
1887 nw
= dir
->nEntries
- SFlistSize
;
1896 f
= ((double) nw
) / dir
->nEntries
;
1898 #ifdef FEAT_GUI_NEXTAW
1899 XawScrollbarSetThumb(
1902 (float) (((double) ((dir
->nEntries
< SFlistSize
) ?
1903 dir
->nEntries
: SFlistSize
)) / dir
->nEntries
));
1905 vim_XawScrollbarSetThumb(
1908 (float) (((double) ((dir
->nEntries
< SFlistSize
) ?
1909 dir
->nEntries
: SFlistSize
)) / dir
->nEntries
),
1910 (double)dir
->nEntries
);
1914 SFvSliderMovedCallback(w
, (int)(long)n
, nw
);
1919 SFhSliderMovedCallback(w
, n
, nw
)
1927 dir
= &(SFdirs
[SFdirPtr
+ (int)(long)n
]);
1928 save
= dir
->hOrigin
;
1929 dir
->hOrigin
= (*(float *)nw
) * dir
->nChars
;
1930 if (dir
->hOrigin
== save
)
1933 SFdrawList((int)(long)n
, SF_DO_NOT_SCROLL
);
1938 SFhAreaSelectedCallback(w
, n
, pnew
)
1944 int nw
= (int)(long)pnew
;
1946 dir
= &(SFdirs
[SFdirPtr
+ (int)(long)n
]);
1948 #ifdef FEAT_GUI_NEXTAW
1951 if (nw
> -SFhScrollWidth
)
1954 nw
= -SFcharsPerEntry
;
1958 if (nw
< SFhScrollWidth
)
1961 nw
= SFcharsPerEntry
;
1966 if (nw
> dir
->nChars
- SFcharsPerEntry
)
1967 nw
= dir
->nChars
- SFcharsPerEntry
;
1976 f
= ((double) nw
) / dir
->nChars
;
1978 #ifdef FEAT_GUI_NEXTAW
1979 XawScrollbarSetThumb(
1982 (float) (((double) ((dir
->nChars
< SFcharsPerEntry
) ?
1983 dir
->nChars
: SFcharsPerEntry
)) / dir
->nChars
));
1985 vim_XawScrollbarSetThumb(
1988 (float) (((double) ((dir
->nChars
< SFcharsPerEntry
) ?
1989 dir
->nChars
: SFcharsPerEntry
)) / dir
->nChars
),
1990 (double)dir
->nChars
);
1993 SFhSliderMovedCallback(w
, n
, (XtPointer
)&f
);
1999 SFpathSliderMovedCallback(w
, client_data
, nw
)
2001 XtPointer client_data
;
2006 XawTextPosition pos
;
2009 SFdirPtrSave
= SFdirPtr
;
2010 SFdirPtr
= (*(float *)nw
) * SFdirEnd
;
2011 if (SFdirPtr
== SFdirPtrSave
)
2014 SFdrawLists(SF_DO_SCROLL
);
2017 while (SFdirPtr
+ n
>= SFdirEnd
)
2020 dir
= &(SFdirs
[SFdirPtr
+ n
]);
2022 pos
= dir
->path
- SFcurrentPath
;
2024 if (!strncmp(SFcurrentPath
, SFstartDir
, strlen(SFstartDir
)))
2026 pos
-= strlen(SFstartDir
);
2031 XawTextSetInsertionPoint(selFileField
, pos
);
2036 SFpathAreaSelectedCallback(w
, client_data
, pnew
)
2038 XtPointer client_data
;
2041 int nw
= (int)(long)pnew
;
2044 #ifdef FEAT_GUI_NEXTAW
2047 if (nw
> -SFpathScrollWidth
)
2054 if (nw
< SFpathScrollWidth
)
2062 if (nw
> SFdirEnd
- 3)
2068 f
= ((double) nw
) / SFdirEnd
;
2070 #ifdef FEAT_GUI_NEXTAW
2071 XawScrollbarSetThumb(
2074 (float) (((double) ((SFdirEnd
< 3) ? SFdirEnd
: 3)) / SFdirEnd
));
2076 vim_XawScrollbarSetThumb(
2079 (float) (((double) ((SFdirEnd
< 3) ? SFdirEnd
: 3)) / SFdirEnd
),
2083 SFpathSliderMovedCallback(w
, (XtPointer
) NULL
, (XtPointer
)&f
);
2092 for (dir
= &(SFdirs
[SFdirEnd
- 1]); dir
>= SFdirs
; dir
--)
2094 if (!(dir
->nEntries
))
2096 for (entry
= &(dir
->entries
[dir
->nEntries
- 1]);
2097 entry
>= dir
->entries
;
2100 if (!(entry
->statDone
))
2102 (void)SFstatAndCheck(dir
, entry
);
2108 SFworkProcAdded
= 0;
2113 /***************** Dir.c */
2116 SFcompareEntries(p
, q
)
2120 return strcmp(((SFEntry
*)p
)->real
, ((SFEntry
*)q
)->real
);
2127 SFEntry
*result
= NULL
;
2135 struct stat statBuf
;
2137 maxChars
= strlen(dir
->dir
) - 1;
2139 dir
->entries
= NULL
;
2146 dirp
= opendir(".");
2150 (void)mch_stat(".", &statBuf
);
2151 dir
->mtime
= statBuf
.st_mtime
;
2153 while ((dp
= readdir(dirp
)))
2155 /* Ignore "." and ".." */
2156 if (strcmp(dp
->d_name
, ".") == 0 || strcmp(dp
->d_name
, "..") == 0)
2160 Alloc
= 2 * (Alloc
+ 1);
2161 result
= (SFEntry
*) XtRealloc((char *) result
,
2162 (unsigned) (Alloc
* sizeof(SFEntry
)));
2164 result
[i
].statDone
= 0;
2167 result
[i
].real
= XtMalloc((unsigned) (len
+ 2));
2168 (void) strcat(strcpy(result
[i
].real
, str
), " ");
2171 result
[i
].shown
= result
[i
].real
;
2175 qsort((char *) result
, (size_t) i
, sizeof(SFEntry
), SFcompareEntries
);
2177 dir
->entries
= result
;
2179 dir
->nChars
= maxChars
+ 1;
2186 /***************** SFinternal.h */
2188 #include <sys/param.h>
2189 #include <X11/cursorfont.h>
2190 #include <X11/Composite.h>
2191 #include <X11/Shell.h>
2192 #ifdef FEAT_GUI_NEXTAW
2193 # include <X11/neXtaw/Form.h>
2194 # include <X11/neXtaw/Command.h>
2195 # include <X11/neXtaw/Label.h>
2197 #include <X11/Xaw/Form.h>
2198 #include <X11/Xaw/Command.h>
2199 #include <X11/Xaw/Label.h>
2202 static char *oneLineTextEditTranslations
= "\
2203 <Key>Return: redraw-display()\n\
2204 Ctrl<Key>M: redraw-display()\n\
2207 static void SFexposeList
__ARGS((Widget w
, XtPointer n
, XEvent
*event
, Boolean
*cont
));
2211 SFexposeList(w
, n
, event
, cont
)
2217 if ((event
->type
== NoExpose
) || event
->xexpose
.count
)
2220 SFdrawList((int)(long)n
, SF_DO_NOT_SCROLL
);
2223 static void SFmodVerifyCallback
__ARGS((Widget w
, XtPointer client_data
, XEvent
*event
, Boolean
*cont
));
2227 SFmodVerifyCallback(w
, client_data
, event
, cont
)
2229 XtPointer client_data
;
2235 if ((XLookupString(&(event
->xkey
), buf
, 2, NULL
, NULL
) == 1) &&
2237 SFstatus
= SEL_FILE_OK
;
2239 SFstatus
= SEL_FILE_TEXT
;
2242 static void SFokCallback
__ARGS((Widget w
, XtPointer cl
, XtPointer cd
));
2246 SFokCallback(w
, cl
, cd
)
2250 SFstatus
= SEL_FILE_OK
;
2253 static XtCallbackRec SFokSelect
[] =
2255 { SFokCallback
, (XtPointer
) NULL
},
2256 { NULL
, (XtPointer
) NULL
},
2259 static void SFcancelCallback
__ARGS((Widget w
, XtPointer cl
, XtPointer cd
));
2263 SFcancelCallback(w
, cl
, cd
)
2267 SFstatus
= SEL_FILE_CANCEL
;
2270 static XtCallbackRec SFcancelSelect
[] =
2272 { SFcancelCallback
, (XtPointer
) NULL
},
2273 { NULL
, (XtPointer
) NULL
},
2276 static void SFdismissAction
__ARGS((Widget w
, XEvent
*event
, String
*params
, Cardinal
*num_params
));
2280 SFdismissAction(w
, event
, params
, num_params
)
2284 Cardinal
*num_params
;
2286 if (event
->type
== ClientMessage
&&
2287 event
->xclient
.data
.l
[0] != SFwmDeleteWindow
)
2290 SFstatus
= SEL_FILE_CANCEL
;
2293 static char *wmDeleteWindowTranslation
= "\
2294 <Message>WM_PROTOCOLS: SelFileDismiss()\n\
2297 static XtActionsRec actions
[] =
2299 {"SelFileDismiss", SFdismissAction
},
2303 SFsetColors(bg
, fg
, scroll_bg
, scroll_fg
)
2306 guicolor_T scroll_bg
;
2307 guicolor_T scroll_fg
;
2311 XtVaSetValues(selFileForm
, XtNbackground
, bg
,
2319 for (i
= 0; i
< 3; ++i
)
2321 if (selFileLists
[i
])
2323 XtVaSetValues(selFileLists
[i
], XtNbackground
, bg
,
2332 XtVaSetValues(selFileOK
, XtNbackground
, bg
,
2339 XtVaSetValues(selFileCancel
, XtNbackground
, bg
,
2346 XtVaSetValues(selFilePrompt
, XtNbackground
, bg
,
2352 XSetBackground(gui
.dpy
, SFtextGC
, bg
);
2353 XSetForeground(gui
.dpy
, SFtextGC
, fg
);
2354 XSetForeground(gui
.dpy
, SFlineGC
, fg
);
2356 /* This is an xor GC, so combine the fg and background */
2357 XSetBackground(gui
.dpy
, SFinvertGC
, fg
^ bg
);
2358 XSetForeground(gui
.dpy
, SFinvertGC
, fg
^ bg
);
2362 XtVaSetValues(selFileHScroll
, XtNbackground
, scroll_bg
,
2363 XtNforeground
, scroll_fg
,
2370 for (i
= 0; i
< 3; i
++)
2372 XtVaSetValues(selFileVScrolls
[i
], XtNbackground
, scroll_bg
,
2373 XtNforeground
, scroll_fg
,
2376 XtVaSetValues(selFileHScrolls
[i
], XtNbackground
, scroll_bg
,
2377 XtNforeground
, scroll_fg
,
2385 SFcreateWidgets(toplevel
, prompt
, ok
, cancel
)
2392 int listWidth
, listHeight
;
2393 int listSpacing
= 10;
2394 int scrollThickness
= 15;
2395 int hScrollX
, hScrollY
;
2396 int vScrollX
, vScrollY
;
2398 selFile
= XtVaAppCreateShell("selFile", "SelFile",
2399 transientShellWidgetClass
, SFdisplay
,
2400 XtNtransientFor
, toplevel
,
2404 /* Add WM_DELETE_WINDOW protocol */
2405 XtAppAddActions(XtWidgetToApplicationContext(selFile
),
2406 actions
, XtNumber(actions
));
2407 XtOverrideTranslations(selFile
,
2408 XtParseTranslationTable(wmDeleteWindowTranslation
));
2410 selFileForm
= XtVaCreateManagedWidget("selFileForm",
2411 formWidgetClass
, selFile
,
2412 XtNdefaultDistance
, 30,
2413 XtNforeground
, SFfore
,
2414 XtNbackground
, SFback
,
2415 XtNborderColor
, SFback
,
2418 selFilePrompt
= XtVaCreateManagedWidget("selFilePrompt",
2419 labelWidgetClass
, selFileForm
,
2423 XtNbottom
, XtChainTop
,
2424 XtNleft
, XtChainLeft
,
2425 XtNright
, XtChainLeft
,
2427 XtNforeground
, SFfore
,
2428 XtNbackground
, SFback
,
2432 XtVaGetValues(selFilePrompt,
2433 XtNforeground, &SFfore,
2434 XtNbackground, &SFback,
2440 SFentryWidth
= SFbesideText
+ SFcharsPerEntry
* SFcharWidth
+
2442 SFentryHeight
= SFaboveAndBelowText
+ SFcharHeight
+
2443 SFaboveAndBelowText
;
2445 listWidth
= SFlineToTextH
+ SFentryWidth
+ SFlineToTextH
+ 1 +
2447 listHeight
= SFlineToTextV
+ SFentryHeight
+ SFlineToTextV
+ 1 +
2448 SFlineToTextV
+ SFlistSize
* SFentryHeight
+
2449 SFlineToTextV
+ 1 + scrollThickness
;
2451 SFpathScrollWidth
= 3 * listWidth
+ 2 * listSpacing
+ 4;
2454 hScrollY
= SFlineToTextV
+ SFentryHeight
+ SFlineToTextV
+ 1 +
2455 SFlineToTextV
+ SFlistSize
* SFentryHeight
+
2457 SFhScrollWidth
= SFlineToTextH
+ SFentryWidth
+ SFlineToTextH
;
2459 vScrollX
= SFlineToTextH
+ SFentryWidth
+ SFlineToTextH
;
2460 vScrollY
= SFlineToTextV
+ SFentryHeight
+ SFlineToTextV
;
2461 SFvScrollHeight
= SFlineToTextV
+ SFlistSize
* SFentryHeight
+
2464 SFupperX
= SFlineToTextH
+ SFentryWidth
+ SFlineToTextH
- 1;
2465 SFlowerY
= SFlineToTextV
+ SFentryHeight
+ SFlineToTextV
+ 1 +
2467 SFupperY
= SFlineToTextV
+ SFentryHeight
+ SFlineToTextV
+ 1 +
2468 SFlineToTextV
+ SFlistSize
* SFentryHeight
- 1;
2470 SFtextX
= SFlineToTextH
+ SFbesideText
;
2471 SFtextYoffset
= SFlowerY
+ SFaboveAndBelowText
+ SFcharAscent
;
2474 SFsegs
[0].y1
= vScrollY
;
2475 SFsegs
[0].x2
= vScrollX
- 1;
2476 SFsegs
[0].y2
= vScrollY
;
2477 SFsegs
[1].x1
= vScrollX
;
2479 SFsegs
[1].x2
= vScrollX
;
2480 SFsegs
[1].y2
= vScrollY
- 1;
2482 SFcompletionSegs
[0].x1
= SFcompletionSegs
[0].x2
= SFlineToTextH
;
2483 SFcompletionSegs
[1].x1
= SFcompletionSegs
[1].x2
=
2484 SFlineToTextH
+ SFentryWidth
- 1;
2486 selFileField
= XtVaCreateManagedWidget("selFileField",
2487 asciiTextWidgetClass
, selFileForm
,
2488 XtNwidth
, 3 * listWidth
+ 2 * listSpacing
+ 4,
2489 XtNborderColor
, SFfore
,
2490 XtNfromVert
, selFilePrompt
,
2491 XtNvertDistance
, 10,
2494 XtNbottom
, XtChainTop
,
2495 XtNleft
, XtChainLeft
,
2496 XtNright
, XtChainLeft
,
2497 XtNstring
, SFtextBuffer
,
2498 XtNlength
, MAXPATHL
,
2499 XtNeditType
, XawtextEdit
,
2500 XtNwrap
, XawtextWrapWord
,
2501 XtNresize
, XawtextResizeHeight
,
2502 XtNuseStringInPlace
, True
,
2505 XtOverrideTranslations(selFileField
,
2506 XtParseTranslationTable(oneLineTextEditTranslations
));
2507 XtSetKeyboardFocus(selFileForm
, selFileField
);
2509 selFileHScroll
= XtVaCreateManagedWidget("selFileHScroll",
2510 #ifdef FEAT_GUI_NEXTAW
2511 scrollbarWidgetClass
, selFileForm
,
2513 vim_scrollbarWidgetClass
, selFileForm
,
2515 XtNorientation
, XtorientHorizontal
,
2516 XtNwidth
, SFpathScrollWidth
,
2517 XtNheight
, scrollThickness
,
2518 XtNborderColor
, SFfore
,
2519 XtNfromVert
, selFileField
,
2520 XtNvertDistance
, 30,
2522 XtNbottom
, XtChainTop
,
2523 XtNleft
, XtChainLeft
,
2524 XtNright
, XtChainLeft
,
2525 XtNforeground
, gui
.scroll_fg_pixel
,
2526 XtNbackground
, gui
.scroll_bg_pixel
,
2527 #ifndef FEAT_GUI_NEXTAW
2532 XtAddCallback(selFileHScroll
, XtNjumpProc
,
2533 (XtCallbackProc
) SFpathSliderMovedCallback
, (XtPointer
)NULL
);
2534 XtAddCallback(selFileHScroll
, XtNscrollProc
,
2535 (XtCallbackProc
) SFpathAreaSelectedCallback
, (XtPointer
)NULL
);
2537 selFileLists
[0] = XtVaCreateManagedWidget("selFileList1",
2538 compositeWidgetClass
, selFileForm
,
2539 XtNwidth
, listWidth
,
2540 XtNheight
, listHeight
,
2541 XtNforeground
, SFfore
,
2542 XtNbackground
, SFback
,
2543 XtNborderColor
, SFfore
,
2544 XtNfromVert
, selFileHScroll
,
2545 XtNvertDistance
, 10,
2547 XtNbottom
, XtChainTop
,
2548 XtNleft
, XtChainLeft
,
2549 XtNright
, XtChainLeft
,
2552 selFileLists
[1] = XtVaCreateManagedWidget("selFileList2",
2553 compositeWidgetClass
, selFileForm
,
2554 XtNwidth
, listWidth
,
2555 XtNheight
, listHeight
,
2556 XtNforeground
, SFfore
,
2557 XtNbackground
, SFback
,
2558 XtNborderColor
, SFfore
,
2559 XtNfromHoriz
, selFileLists
[0],
2560 XtNfromVert
, selFileHScroll
,
2561 XtNhorizDistance
, listSpacing
,
2562 XtNvertDistance
, 10,
2564 XtNbottom
, XtChainTop
,
2565 XtNleft
, XtChainLeft
,
2566 XtNright
, XtChainLeft
,
2569 selFileLists
[2] = XtVaCreateManagedWidget("selFileList3",
2570 compositeWidgetClass
, selFileForm
,
2571 XtNwidth
, listWidth
,
2572 XtNheight
, listHeight
,
2573 XtNforeground
, SFfore
,
2574 XtNbackground
, SFback
,
2575 XtNborderColor
, SFfore
,
2576 XtNfromHoriz
, selFileLists
[1],
2577 XtNfromVert
, selFileHScroll
,
2578 XtNhorizDistance
, listSpacing
,
2579 XtNvertDistance
, 10,
2581 XtNbottom
, XtChainTop
,
2582 XtNleft
, XtChainLeft
,
2583 XtNright
, XtChainLeft
,
2586 for (n
= 0; n
< 3; n
++)
2588 selFileVScrolls
[n
] = XtVaCreateManagedWidget("selFileVScroll",
2589 #ifdef FEAT_GUI_NEXTAW
2590 scrollbarWidgetClass
, selFileLists
[n
],
2592 vim_scrollbarWidgetClass
, selFileLists
[n
],
2596 XtNwidth
, scrollThickness
,
2597 XtNheight
, SFvScrollHeight
,
2598 XtNborderColor
, SFfore
,
2599 XtNforeground
, gui
.scroll_fg_pixel
,
2600 XtNbackground
, gui
.scroll_bg_pixel
,
2601 #ifndef FEAT_GUI_NEXTAW
2606 XtAddCallback(selFileVScrolls
[n
], XtNjumpProc
,
2607 (XtCallbackProc
)SFvFloatSliderMovedCallback
, (XtPointer
)n
);
2608 XtAddCallback(selFileVScrolls
[n
], XtNscrollProc
,
2609 (XtCallbackProc
)SFvAreaSelectedCallback
, (XtPointer
)n
);
2611 selFileHScrolls
[n
] = XtVaCreateManagedWidget("selFileHScroll",
2612 #ifdef FEAT_GUI_NEXTAW
2613 scrollbarWidgetClass
, selFileLists
[n
],
2615 vim_scrollbarWidgetClass
, selFileLists
[n
],
2617 XtNorientation
, XtorientHorizontal
,
2620 XtNwidth
, SFhScrollWidth
,
2621 XtNheight
, scrollThickness
,
2622 XtNborderColor
, SFfore
,
2623 XtNforeground
, gui
.scroll_fg_pixel
,
2624 XtNbackground
, gui
.scroll_bg_pixel
,
2625 #ifndef FEAT_GUI_NEXTAW
2630 XtAddCallback(selFileHScrolls
[n
], XtNjumpProc
,
2631 (XtCallbackProc
)SFhSliderMovedCallback
, (XtPointer
)n
);
2632 XtAddCallback(selFileHScrolls
[n
], XtNscrollProc
,
2633 (XtCallbackProc
)SFhAreaSelectedCallback
, (XtPointer
)n
);
2636 selFileOK
= XtVaCreateManagedWidget("selFileOK",
2637 commandWidgetClass
, selFileForm
,
2640 XtNcallback
, SFokSelect
,
2641 XtNforeground
, SFfore
,
2642 XtNbackground
, SFback
,
2643 XtNborderColor
, SFfore
,
2644 XtNfromHoriz
, selFileLists
[0],
2645 XtNfromVert
, selFileLists
[0],
2646 XtNvertDistance
, 30,
2648 XtNbottom
, XtChainTop
,
2649 XtNleft
, XtChainLeft
,
2650 XtNright
, XtChainLeft
,
2653 selFileCancel
= XtVaCreateManagedWidget("selFileCancel",
2654 commandWidgetClass
, selFileForm
,
2657 XtNcallback
, SFcancelSelect
,
2658 XtNforeground
, SFfore
,
2659 XtNbackground
, SFback
,
2660 XtNborderColor
, SFfore
,
2661 XtNfromHoriz
, selFileOK
,
2662 XtNfromVert
, selFileLists
[0],
2663 XtNhorizDistance
, 30,
2664 XtNvertDistance
, 30,
2666 XtNbottom
, XtChainTop
,
2667 XtNleft
, XtChainLeft
,
2668 XtNright
, XtChainLeft
,
2671 XtSetMappedWhenManaged(selFile
, False
);
2672 XtRealizeWidget(selFile
);
2674 /* Add WM_DELETE_WINDOW protocol */
2675 SFwmDeleteWindow
= XInternAtom(SFdisplay
, "WM_DELETE_WINDOW", False
);
2676 XSetWMProtocols(SFdisplay
, XtWindow(selFile
), &SFwmDeleteWindow
, 1);
2680 for (n
= 0; n
< 3; n
++)
2682 XtAddEventHandler(selFileLists
[n
], ExposureMask
, True
,
2683 (XtEventHandler
)SFexposeList
, (XtPointer
)n
);
2684 XtAddEventHandler(selFileLists
[n
], EnterWindowMask
, False
,
2685 (XtEventHandler
)SFenterList
, (XtPointer
)n
);
2686 XtAddEventHandler(selFileLists
[n
], LeaveWindowMask
, False
,
2687 (XtEventHandler
)SFleaveList
, (XtPointer
)n
);
2688 XtAddEventHandler(selFileLists
[n
], PointerMotionMask
, False
,
2689 (XtEventHandler
)SFmotionList
, (XtPointer
)n
);
2690 XtAddEventHandler(selFileLists
[n
], ButtonPressMask
, False
,
2691 (XtEventHandler
)SFbuttonPressList
, (XtPointer
)n
);
2692 XtAddEventHandler(selFileLists
[n
], ButtonReleaseMask
, False
,
2693 (XtEventHandler
)SFbuttonReleaseList
, (XtPointer
)n
);
2696 XtAddEventHandler(selFileField
, KeyPressMask
, False
,
2697 SFmodVerifyCallback
, (XtPointer
)NULL
);
2699 SFapp
= XtWidgetToApplicationContext(selFile
);
2705 #if defined(FEAT_XFONTSET) && defined(XtNinternational)
2706 if (_XawTextFormat((TextWidget
)selFileField
) == XawFmtWide
)
2708 wchar_t *wcbuf
=(wchar_t *)SFtextBuffer
;
2710 if ((wcbuf
[0] == L
'/') || (wcbuf
[0] == L
'~'))
2712 (void) wcstombs(SFcurrentPath
, wcbuf
, MAXPATHL
);
2713 SFtextPos
= XawTextGetInsertionPoint(selFileField
);
2717 strcpy(SFcurrentPath
, SFstartDir
);
2718 (void) wcstombs(SFcurrentPath
+ strlen(SFcurrentPath
), wcbuf
, MAXPATHL
);
2720 SFtextPos
= XawTextGetInsertionPoint(selFileField
) + strlen(SFstartDir
);
2725 if ((SFtextBuffer
[0] == '/') || (SFtextBuffer
[0] == '~'))
2727 (void) strcpy(SFcurrentPath
, SFtextBuffer
);
2728 SFtextPos
= XawTextGetInsertionPoint(selFileField
);
2732 (void) strcat(strcpy(SFcurrentPath
, SFstartDir
), SFtextBuffer
);
2734 SFtextPos
= XawTextGetInsertionPoint(selFileField
) + strlen(SFstartDir
);
2737 if (!SFworkProcAdded
)
2739 (void) XtAppAddWorkProc(SFapp
, (XtWorkProc
)SFworkProc
, NULL
);
2740 SFworkProcAdded
= 1;
2749 #if defined(FEAT_XFONTSET) && defined(XtNinternational)
2752 if (_XawTextFormat((TextWidget
)selFileField
) == XawFmtWide
)
2757 XtVaGetValues(selFileField
,
2760 mbslength
= wcstombs(NULL
, wcbuf
, 0);
2761 /* Hack: some broken wcstombs() returns zero, just get a large buffer */
2762 if (mbslength
== 0 && wcbuf
!= NULL
&& wcbuf
[0] != 0)
2763 mbslength
= MAXPATHL
;
2764 buf
=(char *)XtMalloc(mbslength
+ 1);
2765 wcstombs(buf
, wcbuf
, mbslength
+1);
2769 return (char *)vim_strsave((char_u
*)SFtextBuffer
);
2775 SFstatus
= SEL_FILE_NULL
;
2776 XtRemoveGrab(selFile
);
2777 XtUnmapWidget(selFile
);
2778 XtRemoveTimeOut(SFdirModTimerId
);
2779 if (SFchdir(SFstartDir
))
2781 EMSG(_("E614: vim_SelFile: can't return to current directory"));
2782 SFstatus
= SEL_FILE_CANCEL
;
2787 vim_SelFile(toplevel
, prompt
, init_path
, show_entry
, x
, y
, fg
, bg
, scroll_fg
, scroll_bg
)
2791 int (*show_entry
)();
2794 guicolor_T scroll_fg
, scroll_bg
; /* The "Scrollbar" group colors */
2796 static int firstTime
= 1;
2801 prompt
= _("Pathname:");
2805 if (mch_dirname((char_u
*)SFstartDir
, MAXPATHL
) == FAIL
)
2807 EMSG(_("E615: vim_SelFile: can't get current directory"));
2814 SFdisplay
= XtDisplay(toplevel
);
2815 SFcreateWidgets(toplevel
, prompt
, _("OK"), _("Cancel"));
2819 XtVaSetValues(selFilePrompt
, XtNlabel
, prompt
, NULL
);
2820 XtVaSetValues(selFile
, XtNtitle
, prompt
, NULL
);
2821 SFsetColors(bg
, fg
, scroll_bg
, scroll_fg
);
2824 XtVaSetValues(selFile
, XtNx
, x
, XtNy
, y
, NULL
);
2825 XtMapWidget(selFile
);
2827 (void)strcat(SFstartDir
, "/");
2828 (void)strcpy(SFcurrentDir
, SFstartDir
);
2832 if (init_path
[0] == '/')
2834 (void)strcpy(SFcurrentPath
, init_path
);
2835 if (strncmp(SFcurrentPath
, SFstartDir
, strlen(SFstartDir
)))
2836 SFsetText(SFcurrentPath
);
2838 SFsetText(&(SFcurrentPath
[strlen(SFstartDir
)]));
2842 (void)strcat(strcpy(SFcurrentPath
, SFstartDir
), init_path
);
2843 SFsetText(&(SFcurrentPath
[strlen(SFstartDir
)]));
2847 (void)strcpy(SFcurrentPath
, SFstartDir
);
2849 SFfunc
= show_entry
;
2853 XtAddGrab(selFile
, True
, True
);
2855 SFdirModTimerId
= XtAppAddTimeOut(SFapp
, (unsigned long) 1000,
2856 SFdirModTimer
, (XtPointer
) NULL
);
2860 XtAppNextEvent(SFapp
, &event
);
2861 XtDispatchEvent(&event
);
2865 SFstatus
= SEL_FILE_NULL
;
2869 name_return
= SFgetText();
2870 SFprepareToReturn();
2872 case SEL_FILE_CANCEL
:
2873 SFprepareToReturn();
2880 #endif /* FEAT_BROWSE */