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 ((unsigned long)_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));
855 SFbuttonPressList(w, n, event)
858 XButtonPressedEvent *event UNUSED;
864 SFbuttonReleaseList(w, n, event)
867 XButtonReleasedEvent *event;
873 if (SFcurrentInvert[n] != -1)
876 SFdoNotTouchDirPtr = 1;
877 SFdoNotTouchVorigin = 1;
878 dir = &(SFdirs[SFdirPtr + n]);
880 dir->entries[dir->vOrigin + SFcurrentInvert[n]].shown);
881 SFmotionList(w, n, (XMotionEvent *) event);
885 static int SFcheckDir __ARGS((int n, SFDir *dir));
895 if ((!mch_stat(".", &statBuf)) && (statBuf.st_mtime != dir->mtime))
898 * If the pointer is currently in the window that we are about
899 * to update, we must warp it to prevent the user from
900 * accidentally selecting the wrong file.
902 if (SFcurrentInvert[n] != -1)
907 XtWindow(selFileLists[n]),
916 for (i = dir->nEntries - 1; i >= 0; i--)
918 if (dir->entries[i].shown != dir->entries[i].real)
919 XtFree(dir->entries[i].shown);
920 XtFree(dir->entries[i].real);
922 XtFree((char *) dir->entries);
924 SFunreadableDir(dir);
925 if (dir->vOrigin > dir->nEntries - SFlistSize)
926 dir->vOrigin = dir->nEntries - SFlistSize;
927 if (dir->vOrigin < 0)
929 if (dir->hOrigin > dir->nChars - SFcharsPerEntry)
930 dir->hOrigin = dir->nChars - SFcharsPerEntry;
931 if (dir->hOrigin < 0)
933 dir->beginSelection = -1;
934 dir->endSelection = -1;
935 SFdoNotTouchVorigin = 1;
937 (void) SFfindFile(dir, (dir + 1)->dir);
939 (void) SFfindFile(dir, dir->path);
941 if (!SFworkProcAdded)
943 (void) XtAppAddWorkProc(SFapp, (XtWorkProc)SFworkProc, NULL);
951 static int SFcheckFiles __ARGS((SFDir *dir));
968 to = dir->vOrigin + SFlistSize;
969 if (to > dir->nEntries)
972 for (i = from; i < to; i++)
974 str = dir->entries[i].real;
975 last = strlen(str) - 1;
978 if (mch_stat(str, &statBuf))
981 newc = SFstatChar(&statBuf);
991 SFdirModTimer(cl, id)
993 XtIntervalId *id UNUSED;
1000 if ((!SFtwiddle) && (SFdirPtr < SFdirEnd))
1003 if ((n > 2) || (SFdirPtr + n >= SFdirEnd))
1007 if ((f > 2) || (SFdirPtr + f >= SFdirEnd))
1010 dir = &(SFdirs[SFdirPtr + n]);
1011 save = *(dir->path);
1013 if (SFchdir(SFcurrentPath))
1015 *(dir->path) = save;
1026 *(dir->path) = save;
1027 if (SFcheckDir(n, dir) || ((f == n) && SFcheckFiles(dir)))
1028 SFdrawList(n, SF_DO_SCROLL);
1032 SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
1033 SFdirModTimer, (XtPointer) NULL);
1036 /* Return a single character describing what kind of file STATBUF is. */
1040 struct stat *statBuf;
1042 if (S_ISDIR (statBuf->st_mode))
1044 if (S_ISREG (statBuf->st_mode))
1045 return S_ISXXX (statBuf->st_mode) ? '*' : ' ';
1047 if (S_ISSOCK (statBuf->st_mode))
1049 #endif /* S_ISSOCK */
1053 /***************** Draw.c */
1055 #ifdef FEAT_GUI_NEXTAW
1056 # include <X11/neXtaw/Cardinals.h>
1058 # include <X11/Xaw/Cardinals.h>
1061 #ifdef FEAT_XFONTSET
1062 # define SF_DEFAULT_FONT "-misc-fixed-medium-r-normal--14-*"
1064 # define SF_DEFAULT_FONT "9x15"
1070 #define ABS(x) (((x) < 0) ? (-(x)) : (x))
1077 static GC SFlineGC, SFscrollGC, SFinvertGC, SFtextGC;
1079 static XtResource textResources[] =
1081 #ifdef FEAT_XFONTSET
1082 {XtNfontSet, XtCFontSet, XtRString, sizeof (char *),
1083 XtOffsetOf(TextData, fontname), XtRString, SF_DEFAULT_FONT},
1085 {XtNfont, XtCFont, XtRString, sizeof (char *),
1086 XtOffsetOf(TextData, fontname), XtRString, SF_DEFAULT_FONT},
1090 #ifdef FEAT_XFONTSET
1091 static XFontSet SFfont;
1093 static XFontStruct *SFfont;
1096 static int SFcurrentListY;
1098 static XtIntervalId SFscrollTimerId;
1100 static void SFinitFont __ARGS((void));
1106 #ifdef FEAT_XFONTSET
1107 XFontSetExtents *extents;
1108 char **missing, *def_str;
1112 data = XtNew(TextData);
1114 XtGetApplicationResources(selFileForm, (XtPointer) data, textResources,
1115 XtNumber(textResources), (Arg *) NULL, ZERO);
1117 #ifdef FEAT_XFONTSET
1118 SFfont = XCreateFontSet(SFdisplay, data->fontname,
1119 &missing, &num_missing, &def_str);
1121 SFfont = XLoadQueryFont(SFdisplay, data->fontname);
1125 #ifdef FEAT_XFONTSET
1126 SFfont = XCreateFontSet(SFdisplay, SF_DEFAULT_FONT,
1127 &missing, &num_missing, &def_str);
1129 SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT);
1133 EMSG2(_("E616: vim_SelFile: can't get font %s"), SF_DEFAULT_FONT);
1134 SFstatus = SEL_FILE_CANCEL;
1139 #ifdef FEAT_XFONTSET
1140 extents = XExtentsOfFontSet(SFfont);
1141 SFcharWidth = extents->max_logical_extent.width;
1142 SFcharAscent = -extents->max_logical_extent.y;
1143 SFcharHeight = extents->max_logical_extent.height;
1145 SFcharWidth = (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2;
1146 SFcharAscent = SFfont->max_bounds.ascent;
1147 SFcharHeight = SFcharAscent + SFfont->max_bounds.descent;
1151 static void SFcreateGC __ARGS((void));
1157 XRectangle rectangles[1];
1159 gcValues.foreground = SFfore;
1163 (XtGCMask)GCForeground,
1166 SFscrollGC = XtGetGC(
1171 gcValues.function = GXxor;
1172 gcValues.foreground = SFfore ^ SFback;
1173 gcValues.background = SFfore ^ SFback;
1175 SFinvertGC = XtGetGC(
1177 (XtGCMask)GCFunction | GCForeground | GCBackground,
1180 gcValues.foreground = SFfore;
1181 gcValues.background = SFback;
1182 #ifndef FEAT_XFONTSET
1183 gcValues.font = SFfont->fid;
1186 SFtextGC = XCreateGC(
1188 XtWindow(selFileLists[0]),
1189 #ifdef FEAT_XFONTSET
1190 (unsigned long)GCForeground | GCBackground,
1192 (unsigned long)GCForeground | GCBackground | GCFont,
1196 rectangles[0].x = SFlineToTextH + SFbesideText;
1197 rectangles[0].y = 0;
1198 rectangles[0].width = SFcharsPerEntry * SFcharWidth;
1199 rectangles[0].height = SFupperY + 1;
1212 SFclearList(n, doScroll)
1218 SFcurrentInvert[n] = -1;
1220 XClearWindow(SFdisplay, XtWindow(selFileLists[n]));
1222 XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs, 2);
1226 dir = &(SFdirs[SFdirPtr + n]);
1228 if ((SFdirPtr + n < SFdirEnd) && dir->nEntries && dir->nChars)
1230 #ifdef FEAT_GUI_NEXTAW
1231 XawScrollbarSetThumb(
1233 (float) (((double) dir->vOrigin) /
1235 (float) (((double) ((dir->nEntries < SFlistSize)
1236 ? dir->nEntries : SFlistSize)) /
1239 vim_XawScrollbarSetThumb(
1241 (float) (((double) dir->vOrigin) /
1243 (float) (((double) ((dir->nEntries < SFlistSize)
1244 ? dir->nEntries : SFlistSize)) /
1246 (double)dir->nEntries);
1249 #ifdef FEAT_GUI_NEXTAW
1250 XawScrollbarSetThumb(
1252 (float) (((double) dir->hOrigin) / dir->nChars),
1253 (float) (((double) ((dir->nChars <
1254 SFcharsPerEntry) ? dir->nChars :
1255 SFcharsPerEntry)) / dir->nChars));
1257 vim_XawScrollbarSetThumb(
1259 (float) (((double) dir->hOrigin) / dir->nChars),
1260 (float) (((double) ((dir->nChars <
1261 SFcharsPerEntry) ? dir->nChars :
1262 SFcharsPerEntry)) / dir->nChars),
1263 (double)dir->nChars);
1268 #ifdef FEAT_GUI_NEXTAW
1269 XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
1272 vim_XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
1275 #ifdef FEAT_GUI_NEXTAW
1276 XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
1279 vim_XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
1286 static void SFdeleteEntry __ARGS((SFDir *dir, SFEntry *entry));
1289 SFdeleteEntry(dir, entry)
1298 idx = entry - dir->entries;
1300 if (idx < dir->beginSelection)
1301 dir->beginSelection--;
1302 if (idx <= dir->endSelection)
1303 dir->endSelection--;
1304 if (dir->beginSelection > dir->endSelection)
1305 dir->beginSelection = dir->endSelection = -1;
1307 if (idx < dir->vOrigin)
1310 XtFree(entry->real);
1312 end = &(dir->entries[dir->nEntries - 1]);
1314 for (e = entry; e < end; e++)
1317 if (!(--dir->nEntries))
1320 n = dir - &(SFdirs[SFdirPtr]);
1321 if ((n < 0) || (n > 2))
1324 #ifdef FEAT_GUI_NEXTAW
1325 XawScrollbarSetThumb(
1327 (float) (((double) dir->vOrigin) / dir->nEntries),
1328 (float) (((double) ((dir->nEntries < SFlistSize) ?
1329 dir->nEntries : SFlistSize)) / dir->nEntries));
1331 vim_XawScrollbarSetThumb(
1333 (float) (((double) dir->vOrigin) / dir->nEntries),
1334 (float) (((double) ((dir->nEntries < SFlistSize) ?
1335 dir->nEntries : SFlistSize)) / dir->nEntries),
1336 (double)dir->nEntries);
1340 static void SFwriteStatChar __ARGS((char *name, int last, struct stat *statBuf));
1343 SFwriteStatChar(name, last, statBuf)
1346 struct stat *statBuf;
1348 name[last] = SFstatChar(statBuf);
1351 static int SFstatAndCheck __ARGS((SFDir *dir, SFEntry *entry));
1354 SFstatAndCheck(dir, entry)
1358 struct stat statBuf;
1363 * must be restored before returning
1365 save = *(dir->path);
1368 if (!SFchdir(SFcurrentPath))
1370 last = strlen(entry->real) - 1;
1371 entry->real[last] = 0;
1372 entry->statDone = 1;
1373 if ((!mch_stat(entry->real, &statBuf))
1375 || (!mch_lstat(entry->real, &statBuf))
1384 if (SFfunc(entry->real, &shown, &statBuf))
1390 len = strlen(shown);
1391 entry->shown = XtMalloc((unsigned) (len + 2));
1392 (void) strcpy(entry->shown, shown);
1393 SFwriteStatChar(entry->shown, len, &statBuf);
1394 entry->shown[len + 1] = 0;
1399 SFdeleteEntry(dir, entry);
1401 *(dir->path) = save;
1405 SFwriteStatChar(entry->real, last, &statBuf);
1408 entry->real[last] = ' ';
1411 *(dir->path) = save;
1417 SFdrawStrings(w, dir, from, to)
1427 x = SFtextX - dir->hOrigin * SFcharWidth;
1429 if (dir->vOrigin + to >= dir->nEntries)
1430 to = dir->nEntries - dir->vOrigin - 1;
1431 for (i = from; i <= to; i++)
1433 entry = &(dir->entries[dir->vOrigin + i]);
1434 if (!(entry->statDone))
1436 if (SFstatAndCheck(dir, entry))
1438 if (dir->vOrigin + to >= dir->nEntries)
1439 to = dir->nEntries - dir->vOrigin - 1;
1444 #ifdef FEAT_XFONTSET
1451 SFtextYoffset + i * SFentryHeight,
1453 strlen(entry->shown));
1460 SFtextYoffset + i * SFentryHeight,
1462 strlen(entry->shown));
1464 if (dir->vOrigin + i == dir->beginSelection)
1471 SFlowerY + i * SFentryHeight,
1472 SFlineToTextH + SFentryWidth - 2,
1473 SFlowerY + i * SFentryHeight);
1475 if ((dir->vOrigin + i >= dir->beginSelection) &&
1476 (dir->vOrigin + i <= dir->endSelection))
1478 SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 =
1479 SFlowerY + i * SFentryHeight;
1480 SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 =
1481 SFlowerY + (i + 1) * SFentryHeight - 1;
1489 if (dir->vOrigin + i == dir->endSelection)
1496 SFlowerY + (i + 1) * SFentryHeight - 1,
1497 SFlineToTextH + SFentryWidth - 2,
1498 SFlowerY + (i + 1) * SFentryHeight - 1);
1504 SFdrawList(n, doScroll)
1511 SFclearList(n, doScroll);
1513 if (SFdirPtr + n < SFdirEnd)
1515 dir = &(SFdirs[SFdirPtr + n]);
1516 w = XtWindow(selFileLists[n]);
1517 #ifdef FEAT_XFONTSET
1523 SFtextX - dir->hOrigin * SFcharWidth,
1524 SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
1532 SFtextX - dir->hOrigin * SFcharWidth,
1533 SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
1537 SFdrawStrings(w, dir, 0, SFlistSize - 1);
1542 SFdrawLists(doScroll)
1547 for (i = 0; i < 3; i++)
1548 SFdrawList(i, doScroll);
1557 XtWindow(selFileLists[n]),
1560 SFcurrentInvert[n] * SFentryHeight + SFlowerY,
1565 static unsigned long SFscrollTimerInterval __ARGS((void));
1567 static unsigned long
1568 SFscrollTimerInterval()
1570 static int maxVal = 200;
1571 static int varyDist = 50;
1572 static int minDist = 50;
1576 if (SFcurrentListY < SFlowerY)
1577 dist = SFlowerY - SFcurrentListY;
1578 else if (SFcurrentListY > SFupperY)
1579 dist = SFcurrentListY - SFupperY;
1581 return (unsigned long) 1;
1583 t = maxVal - ((maxVal / varyDist) * (dist - minDist));
1591 return (unsigned long)t;
1594 static void SFscrollTimer __ARGS((XtPointer p, XtIntervalId *id));
1597 SFscrollTimer(p, id)
1599 XtIntervalId *id UNUSED;
1607 dir = &(SFdirs[SFdirPtr + n]);
1608 save = dir->vOrigin;
1610 if (SFcurrentListY < SFlowerY)
1612 if (dir->vOrigin > 0)
1613 SFvSliderMovedCallback(selFileVScrolls[n], n, dir->vOrigin - 1);
1615 else if (SFcurrentListY > SFupperY)
1617 if (dir->vOrigin < dir->nEntries - SFlistSize)
1618 SFvSliderMovedCallback(selFileVScrolls[n], n, dir->vOrigin + 1);
1621 if (dir->vOrigin != save)
1625 #ifdef FEAT_GUI_NEXTAW
1626 XawScrollbarSetThumb(
1628 (float) (((double) dir->vOrigin) / dir->nEntries),
1629 (float) (((double) ((dir->nEntries < SFlistSize) ?
1630 dir->nEntries : SFlistSize)) / dir->nEntries));
1632 vim_XawScrollbarSetThumb(
1634 (float) (((double) dir->vOrigin) / dir->nEntries),
1635 (float) (((double) ((dir->nEntries < SFlistSize) ?
1636 dir->nEntries : SFlistSize)) / dir->nEntries),
1637 (double)dir->nEntries);
1642 if (SFbuttonPressed)
1643 SFscrollTimerId = XtAppAddTimeOut(SFapp,
1644 SFscrollTimerInterval(), SFscrollTimer,
1645 (XtPointer)(long_u)n);
1649 SFnewInvertEntry(n, event)
1651 XMotionEvent *event;
1655 static int SFscrollTimerAdded = 0;
1660 if (SFdirPtr + n >= SFdirEnd)
1663 if ((x >= 0) && (x <= SFupperX) && (y >= SFlowerY) && (y <= SFupperY))
1665 SFDir *dir = &(SFdirs[SFdirPtr + n]);
1667 if (SFscrollTimerAdded)
1669 SFscrollTimerAdded = 0;
1670 XtRemoveTimeOut(SFscrollTimerId);
1673 nw = (y - SFlowerY) / SFentryHeight;
1674 if (dir->vOrigin + nw >= dir->nEntries)
1680 if (SFbuttonPressed)
1683 if (!SFscrollTimerAdded)
1685 SFscrollTimerAdded = 1;
1686 SFscrollTimerId = XtAppAddTimeOut(SFapp,
1687 SFscrollTimerInterval(), SFscrollTimer,
1688 (XtPointer)(long_u)n);
1696 SFenterList(w, n, event)
1699 XEnterWindowEvent *event;
1704 if (SFcurrentInvert[n] != -1)
1707 SFcurrentInvert[n] = -1;
1710 nw = SFnewInvertEntry(n, (XMotionEvent *) event);
1713 SFcurrentInvert[n] = nw;
1719 SFleaveList(w, n, event)
1722 XEvent *event UNUSED;
1724 if (SFcurrentInvert[n] != -1)
1727 SFcurrentInvert[n] = -1;
1732 SFmotionList(w, n, event)
1735 XMotionEvent *event;
1739 nw = SFnewInvertEntry(n, event);
1741 if (nw != SFcurrentInvert[n])
1743 if (SFcurrentInvert[n] != -1)
1745 SFcurrentInvert[n] = nw;
1752 SFvFloatSliderMovedCallback(w, n, fnew)
1759 nw = (*(float *)fnew) * SFdirs[SFdirPtr + (int)(long)n].nEntries;
1760 SFvSliderMovedCallback(w, (int)(long)n, nw);
1764 SFvSliderMovedCallback(w, n, nw)
1773 dir = &(SFdirs[SFdirPtr + n]);
1781 win = XtWindow(selFileLists[n]);
1783 if (ABS(nw - old) < SFlistSize)
1793 SFlowerY + (nw - old) * SFentryHeight,
1794 SFentryWidth + SFlineToTextH,
1795 (SFlistSize - (nw - old)) * SFentryHeight,
1802 SFlowerY + (SFlistSize - (nw - old)) *
1804 SFentryWidth + SFlineToTextH,
1805 (nw - old) * SFentryHeight,
1807 SFdrawStrings(win, dir, SFlistSize - (nw - old),
1819 SFentryWidth + SFlineToTextH,
1820 (SFlistSize - (old - nw)) * SFentryHeight,
1822 SFlowerY + (old - nw) * SFentryHeight);
1828 SFentryWidth + SFlineToTextH,
1829 (old - nw) * SFentryHeight,
1831 SFdrawStrings(win, dir, 0, old - nw);
1841 SFentryWidth + SFlineToTextH,
1842 SFlistSize * SFentryHeight,
1844 SFdrawStrings(win, dir, 0, SFlistSize - 1);
1849 SFvAreaSelectedCallback(w, n, pnew)
1855 int nw = (int)(long)pnew;
1857 dir = &(SFdirs[SFdirPtr + (int)(long)n]);
1859 #ifdef FEAT_GUI_NEXTAW
1862 if (nw > -SFvScrollHeight)
1869 if (nw < SFvScrollHeight)
1877 if (nw > dir->nEntries - SFlistSize)
1878 nw = dir->nEntries - SFlistSize;
1887 f = ((double) nw) / dir->nEntries;
1889 #ifdef FEAT_GUI_NEXTAW
1890 XawScrollbarSetThumb(
1893 (float) (((double) ((dir->nEntries < SFlistSize) ?
1894 dir->nEntries : SFlistSize)) / dir->nEntries));
1896 vim_XawScrollbarSetThumb(
1899 (float) (((double) ((dir->nEntries < SFlistSize) ?
1900 dir->nEntries : SFlistSize)) / dir->nEntries),
1901 (double)dir->nEntries);
1905 SFvSliderMovedCallback(w, (int)(long)n, nw);
1909 SFhSliderMovedCallback(w, n, nw)
1917 dir = &(SFdirs[SFdirPtr + (int)(long)n]);
1918 save = dir->hOrigin;
1919 dir->hOrigin = (*(float *)nw) * dir->nChars;
1920 if (dir->hOrigin == save)
1923 SFdrawList((int)(long)n, SF_DO_NOT_SCROLL);
1927 SFhAreaSelectedCallback(w, n, pnew)
1933 int nw = (int)(long)pnew;
1935 dir = &(SFdirs[SFdirPtr + (int)(long)n]);
1937 #ifdef FEAT_GUI_NEXTAW
1940 if (nw > -SFhScrollWidth)
1943 nw = -SFcharsPerEntry;
1947 if (nw < SFhScrollWidth)
1950 nw = SFcharsPerEntry;
1955 if (nw > dir->nChars - SFcharsPerEntry)
1956 nw = dir->nChars - SFcharsPerEntry;
1965 f = ((double) nw) / dir->nChars;
1967 #ifdef FEAT_GUI_NEXTAW
1968 XawScrollbarSetThumb(
1971 (float) (((double) ((dir->nChars < SFcharsPerEntry) ?
1972 dir->nChars : SFcharsPerEntry)) / dir->nChars));
1974 vim_XawScrollbarSetThumb(
1977 (float) (((double) ((dir->nChars < SFcharsPerEntry) ?
1978 dir->nChars : SFcharsPerEntry)) / dir->nChars),
1979 (double)dir->nChars);
1982 SFhSliderMovedCallback(w, n, (XtPointer)&f);
1987 SFpathSliderMovedCallback(w, client_data, nw)
1989 XtPointer client_data UNUSED;
1994 XawTextPosition pos;
1997 SFdirPtrSave = SFdirPtr;
1998 SFdirPtr = (*(float *)nw) * SFdirEnd;
1999 if (SFdirPtr == SFdirPtrSave)
2002 SFdrawLists(SF_DO_SCROLL);
2005 while (SFdirPtr + n >= SFdirEnd)
2008 dir = &(SFdirs[SFdirPtr + n]);
2010 pos = dir->path - SFcurrentPath;
2012 if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir)))
2014 pos -= strlen(SFstartDir);
2019 XawTextSetInsertionPoint(selFileField, pos);
2023 SFpathAreaSelectedCallback(w, client_data, pnew)
2025 XtPointer client_data UNUSED;
2028 int nw = (int)(long)pnew;
2031 #ifdef FEAT_GUI_NEXTAW
2034 if (nw > -SFpathScrollWidth)
2041 if (nw < SFpathScrollWidth)
2049 if (nw > SFdirEnd - 3)
2055 f = ((double) nw) / SFdirEnd;
2057 #ifdef FEAT_GUI_NEXTAW
2058 XawScrollbarSetThumb(
2061 (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) / SFdirEnd));
2063 vim_XawScrollbarSetThumb(
2066 (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) / SFdirEnd),
2070 SFpathSliderMovedCallback(w, (XtPointer) NULL, (XtPointer)&f);
2079 for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--)
2081 if (!(dir->nEntries))
2083 for (entry = &(dir->entries[dir->nEntries - 1]);
2084 entry >= dir->entries;
2087 if (!(entry->statDone))
2089 (void)SFstatAndCheck(dir, entry);
2095 SFworkProcAdded = 0;
2100 /***************** Dir.c */
2103 SFcompareEntries(p, q)
2107 return strcmp(((SFEntry *)p)->real, ((SFEntry *)q)->real);
2114 SFEntry *result = NULL;
2122 struct stat statBuf;
2124 maxChars = strlen(dir->dir) - 1;
2126 dir->entries = NULL;
2133 dirp = opendir(".");
2137 (void)mch_stat(".", &statBuf);
2138 dir->mtime = statBuf.st_mtime;
2140 while ((dp = readdir(dirp)))
2142 /* Ignore "." and ".." */
2143 if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
2147 Alloc = 2 * (Alloc + 1);
2148 result = (SFEntry *) XtRealloc((char *) result,
2149 (unsigned) (Alloc * sizeof(SFEntry)));
2151 result[i].statDone = 0;
2154 result[i].real = XtMalloc((unsigned) (len + 2));
2155 (void) strcat(strcpy(result[i].real, str), " ");
2158 result[i].shown = result[i].real;
2162 qsort((char *) result, (size_t) i, sizeof(SFEntry), SFcompareEntries);
2164 dir->entries = result;
2166 dir->nChars = maxChars + 1;
2173 /***************** SFinternal.h */
2175 #include <sys/param.h>
2176 #include <X11/cursorfont.h>
2177 #include <X11/Composite.h>
2178 #include <X11/Shell.h>
2179 #ifdef FEAT_GUI_NEXTAW
2180 # include <X11/neXtaw/Form.h>
2181 # include <X11/neXtaw/Command.h>
2182 # include <X11/neXtaw/Label.h>
2184 #include <X11/Xaw/Form.h>
2185 #include <X11/Xaw/Command.h>
2186 #include <X11/Xaw/Label.h>
2189 static char *oneLineTextEditTranslations = "\
2190 <Key>Return: redraw-display()\n\
2191 Ctrl<Key>M: redraw-display()\n\
2194 static void SFexposeList __ARGS((Widget w, XtPointer n, XEvent *event, Boolean *cont));
2197 SFexposeList(w, n, event, cont)
2201 Boolean *cont UNUSED;
2203 if ((event->type == NoExpose) || event->xexpose.count)
2206 SFdrawList((int)(long)n, SF_DO_NOT_SCROLL);
2209 static void SFmodVerifyCallback __ARGS((Widget w, XtPointer client_data, XEvent *event, Boolean *cont));
2212 SFmodVerifyCallback(w, client_data, event, cont)
2214 XtPointer client_data UNUSED;
2216 Boolean *cont UNUSED;
2220 if ((XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) &&
2222 SFstatus = SEL_FILE_OK;
2224 SFstatus = SEL_FILE_TEXT;
2227 static void SFokCallback __ARGS((Widget w, XtPointer cl, XtPointer cd));
2230 SFokCallback(w, cl, cd)
2232 XtPointer cl UNUSED;
2233 XtPointer cd UNUSED;
2235 SFstatus = SEL_FILE_OK;
2238 static XtCallbackRec SFokSelect[] =
2240 { SFokCallback, (XtPointer) NULL },
2241 { NULL, (XtPointer) NULL },
2244 static void SFcancelCallback __ARGS((Widget w, XtPointer cl, XtPointer cd));
2247 SFcancelCallback(w, cl, cd)
2249 XtPointer cl UNUSED;
2250 XtPointer cd UNUSED;
2252 SFstatus = SEL_FILE_CANCEL;
2255 static XtCallbackRec SFcancelSelect[] =
2257 { SFcancelCallback, (XtPointer) NULL },
2258 { NULL, (XtPointer) NULL },
2261 static void SFdismissAction __ARGS((Widget w, XEvent *event, String *params, Cardinal *num_params));
2264 SFdismissAction(w, event, params, num_params)
2267 String *params UNUSED;
2268 Cardinal *num_params UNUSED;
2270 if (event->type == ClientMessage
2271 && (Atom)event->xclient.data.l[0] != SFwmDeleteWindow)
2274 SFstatus = SEL_FILE_CANCEL;
2277 static char *wmDeleteWindowTranslation = "\
2278 <Message>WM_PROTOCOLS: SelFileDismiss()\n\
2281 static XtActionsRec actions[] =
2283 {"SelFileDismiss", SFdismissAction},
2287 SFsetColors(bg, fg, scroll_bg, scroll_fg)
2290 guicolor_T scroll_bg;
2291 guicolor_T scroll_fg;
2295 XtVaSetValues(selFileForm, XtNbackground, bg,
2303 for (i = 0; i < 3; ++i)
2305 if (selFileLists[i])
2307 XtVaSetValues(selFileLists[i], XtNbackground, bg,
2316 XtVaSetValues(selFileOK, XtNbackground, bg,
2323 XtVaSetValues(selFileCancel, XtNbackground, bg,
2330 XtVaSetValues(selFilePrompt, XtNbackground, bg,
2336 XSetBackground(gui.dpy, SFtextGC, bg);
2337 XSetForeground(gui.dpy, SFtextGC, fg);
2338 XSetForeground(gui.dpy, SFlineGC, fg);
2340 /* This is an xor GC, so combine the fg and background */
2341 XSetBackground(gui.dpy, SFinvertGC, fg ^ bg);
2342 XSetForeground(gui.dpy, SFinvertGC, fg ^ bg);
2346 XtVaSetValues(selFileHScroll, XtNbackground, scroll_bg,
2347 XtNforeground, scroll_fg,
2354 for (i = 0; i < 3; i++)
2356 XtVaSetValues(selFileVScrolls[i], XtNbackground, scroll_bg,
2357 XtNforeground, scroll_fg,
2360 XtVaSetValues(selFileHScrolls[i], XtNbackground, scroll_bg,
2361 XtNforeground, scroll_fg,
2369 SFcreateWidgets(toplevel, prompt, ok, cancel)
2376 int listWidth, listHeight;
2377 int listSpacing = 10;
2378 int scrollThickness = 15;
2379 int hScrollX, hScrollY;
2380 int vScrollX, vScrollY;
2382 selFile = XtVaAppCreateShell("selFile", "SelFile",
2383 transientShellWidgetClass, SFdisplay,
2384 XtNtransientFor, toplevel,
2388 /* Add WM_DELETE_WINDOW protocol */
2389 XtAppAddActions(XtWidgetToApplicationContext(selFile),
2390 actions, XtNumber(actions));
2391 XtOverrideTranslations(selFile,
2392 XtParseTranslationTable(wmDeleteWindowTranslation));
2394 selFileForm = XtVaCreateManagedWidget("selFileForm",
2395 formWidgetClass, selFile,
2396 XtNdefaultDistance, 30,
2397 XtNforeground, SFfore,
2398 XtNbackground, SFback,
2399 XtNborderColor, SFback,
2402 selFilePrompt = XtVaCreateManagedWidget("selFilePrompt",
2403 labelWidgetClass, selFileForm,
2407 XtNbottom, XtChainTop,
2408 XtNleft, XtChainLeft,
2409 XtNright, XtChainLeft,
2411 XtNforeground, SFfore,
2412 XtNbackground, SFback,
2416 XtVaGetValues(selFilePrompt,
2417 XtNforeground, &SFfore,
2418 XtNbackground, &SFback,
2424 SFentryWidth = SFbesideText + SFcharsPerEntry * SFcharWidth +
2426 SFentryHeight = SFaboveAndBelowText + SFcharHeight +
2427 SFaboveAndBelowText;
2429 listWidth = SFlineToTextH + SFentryWidth + SFlineToTextH + 1 +
2431 listHeight = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
2432 SFlineToTextV + SFlistSize * SFentryHeight +
2433 SFlineToTextV + 1 + scrollThickness;
2435 SFpathScrollWidth = 3 * listWidth + 2 * listSpacing + 4;
2438 hScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
2439 SFlineToTextV + SFlistSize * SFentryHeight +
2441 SFhScrollWidth = SFlineToTextH + SFentryWidth + SFlineToTextH;
2443 vScrollX = SFlineToTextH + SFentryWidth + SFlineToTextH;
2444 vScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV;
2445 SFvScrollHeight = SFlineToTextV + SFlistSize * SFentryHeight +
2448 SFupperX = SFlineToTextH + SFentryWidth + SFlineToTextH - 1;
2449 SFlowerY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
2451 SFupperY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
2452 SFlineToTextV + SFlistSize * SFentryHeight - 1;
2454 SFtextX = SFlineToTextH + SFbesideText;
2455 SFtextYoffset = SFlowerY + SFaboveAndBelowText + SFcharAscent;
2458 SFsegs[0].y1 = vScrollY;
2459 SFsegs[0].x2 = vScrollX - 1;
2460 SFsegs[0].y2 = vScrollY;
2461 SFsegs[1].x1 = vScrollX;
2463 SFsegs[1].x2 = vScrollX;
2464 SFsegs[1].y2 = vScrollY - 1;
2466 SFcompletionSegs[0].x1 = SFcompletionSegs[0].x2 = SFlineToTextH;
2467 SFcompletionSegs[1].x1 = SFcompletionSegs[1].x2 =
2468 SFlineToTextH + SFentryWidth - 1;
2470 selFileField = XtVaCreateManagedWidget("selFileField",
2471 asciiTextWidgetClass, selFileForm,
2472 XtNwidth, 3 * listWidth + 2 * listSpacing + 4,
2473 XtNborderColor, SFfore,
2474 XtNfromVert, selFilePrompt,
2475 XtNvertDistance, 10,
2478 XtNbottom, XtChainTop,
2479 XtNleft, XtChainLeft,
2480 XtNright, XtChainLeft,
2481 XtNstring, SFtextBuffer,
2482 XtNlength, MAXPATHL,
2483 XtNeditType, XawtextEdit,
2484 XtNwrap, XawtextWrapWord,
2485 XtNresize, XawtextResizeHeight,
2486 XtNuseStringInPlace, True,
2489 XtOverrideTranslations(selFileField,
2490 XtParseTranslationTable(oneLineTextEditTranslations));
2491 XtSetKeyboardFocus(selFileForm, selFileField);
2493 selFileHScroll = XtVaCreateManagedWidget("selFileHScroll",
2494 #ifdef FEAT_GUI_NEXTAW
2495 scrollbarWidgetClass, selFileForm,
2497 vim_scrollbarWidgetClass, selFileForm,
2499 XtNorientation, XtorientHorizontal,
2500 XtNwidth, SFpathScrollWidth,
2501 XtNheight, scrollThickness,
2502 XtNborderColor, SFfore,
2503 XtNfromVert, selFileField,
2504 XtNvertDistance, 30,
2506 XtNbottom, XtChainTop,
2507 XtNleft, XtChainLeft,
2508 XtNright, XtChainLeft,
2509 XtNforeground, gui.scroll_fg_pixel,
2510 XtNbackground, gui.scroll_bg_pixel,
2511 #ifndef FEAT_GUI_NEXTAW
2516 XtAddCallback(selFileHScroll, XtNjumpProc,
2517 (XtCallbackProc) SFpathSliderMovedCallback, (XtPointer)NULL);
2518 XtAddCallback(selFileHScroll, XtNscrollProc,
2519 (XtCallbackProc) SFpathAreaSelectedCallback, (XtPointer)NULL);
2521 selFileLists[0] = XtVaCreateManagedWidget("selFileList1",
2522 compositeWidgetClass, selFileForm,
2523 XtNwidth, listWidth,
2524 XtNheight, listHeight,
2525 XtNforeground, SFfore,
2526 XtNbackground, SFback,
2527 XtNborderColor, SFfore,
2528 XtNfromVert, selFileHScroll,
2529 XtNvertDistance, 10,
2531 XtNbottom, XtChainTop,
2532 XtNleft, XtChainLeft,
2533 XtNright, XtChainLeft,
2536 selFileLists[1] = XtVaCreateManagedWidget("selFileList2",
2537 compositeWidgetClass, selFileForm,
2538 XtNwidth, listWidth,
2539 XtNheight, listHeight,
2540 XtNforeground, SFfore,
2541 XtNbackground, SFback,
2542 XtNborderColor, SFfore,
2543 XtNfromHoriz, selFileLists[0],
2544 XtNfromVert, selFileHScroll,
2545 XtNhorizDistance, listSpacing,
2546 XtNvertDistance, 10,
2548 XtNbottom, XtChainTop,
2549 XtNleft, XtChainLeft,
2550 XtNright, XtChainLeft,
2553 selFileLists[2] = XtVaCreateManagedWidget("selFileList3",
2554 compositeWidgetClass, selFileForm,
2555 XtNwidth, listWidth,
2556 XtNheight, listHeight,
2557 XtNforeground, SFfore,
2558 XtNbackground, SFback,
2559 XtNborderColor, SFfore,
2560 XtNfromHoriz, selFileLists[1],
2561 XtNfromVert, selFileHScroll,
2562 XtNhorizDistance, listSpacing,
2563 XtNvertDistance, 10,
2565 XtNbottom, XtChainTop,
2566 XtNleft, XtChainLeft,
2567 XtNright, XtChainLeft,
2570 for (n = 0; n < 3; n++)
2572 selFileVScrolls[n] = XtVaCreateManagedWidget("selFileVScroll",
2573 #ifdef FEAT_GUI_NEXTAW
2574 scrollbarWidgetClass, selFileLists[n],
2576 vim_scrollbarWidgetClass, selFileLists[n],
2580 XtNwidth, scrollThickness,
2581 XtNheight, SFvScrollHeight,
2582 XtNborderColor, SFfore,
2583 XtNforeground, gui.scroll_fg_pixel,
2584 XtNbackground, gui.scroll_bg_pixel,
2585 #ifndef FEAT_GUI_NEXTAW
2590 XtAddCallback(selFileVScrolls[n], XtNjumpProc,
2591 (XtCallbackProc)SFvFloatSliderMovedCallback,
2592 (XtPointer)(long_u)n);
2593 XtAddCallback(selFileVScrolls[n], XtNscrollProc,
2594 (XtCallbackProc)SFvAreaSelectedCallback, (XtPointer)n);
2596 selFileHScrolls[n] = XtVaCreateManagedWidget("selFileHScroll",
2597 #ifdef FEAT_GUI_NEXTAW
2598 scrollbarWidgetClass, selFileLists[n],
2600 vim_scrollbarWidgetClass, selFileLists[n],
2602 XtNorientation, XtorientHorizontal,
2605 XtNwidth, SFhScrollWidth,
2606 XtNheight, scrollThickness,
2607 XtNborderColor, SFfore,
2608 XtNforeground, gui.scroll_fg_pixel,
2609 XtNbackground, gui.scroll_bg_pixel,
2610 #ifndef FEAT_GUI_NEXTAW
2615 XtAddCallback(selFileHScrolls[n], XtNjumpProc,
2616 (XtCallbackProc)SFhSliderMovedCallback,
2617 (XtPointer)(long_u)n);
2618 XtAddCallback(selFileHScrolls[n], XtNscrollProc,
2619 (XtCallbackProc)SFhAreaSelectedCallback, (XtPointer)n);
2622 selFileOK = XtVaCreateManagedWidget("selFileOK",
2623 commandWidgetClass, selFileForm,
2626 XtNcallback, SFokSelect,
2627 XtNforeground, SFfore,
2628 XtNbackground, SFback,
2629 XtNborderColor, SFfore,
2630 XtNfromHoriz, selFileLists[0],
2631 XtNfromVert, selFileLists[0],
2632 XtNvertDistance, 30,
2634 XtNbottom, XtChainTop,
2635 XtNleft, XtChainLeft,
2636 XtNright, XtChainLeft,
2639 selFileCancel = XtVaCreateManagedWidget("selFileCancel",
2640 commandWidgetClass, selFileForm,
2643 XtNcallback, SFcancelSelect,
2644 XtNforeground, SFfore,
2645 XtNbackground, SFback,
2646 XtNborderColor, SFfore,
2647 XtNfromHoriz, selFileOK,
2648 XtNfromVert, selFileLists[0],
2649 XtNhorizDistance, 30,
2650 XtNvertDistance, 30,
2652 XtNbottom, XtChainTop,
2653 XtNleft, XtChainLeft,
2654 XtNright, XtChainLeft,
2657 XtSetMappedWhenManaged(selFile, False);
2658 XtRealizeWidget(selFile);
2660 /* Add WM_DELETE_WINDOW protocol */
2661 SFwmDeleteWindow = XInternAtom(SFdisplay, "WM_DELETE_WINDOW", False);
2662 XSetWMProtocols(SFdisplay, XtWindow(selFile), &SFwmDeleteWindow, 1);
2666 for (n = 0; n < 3; n++)
2668 XtAddEventHandler(selFileLists[n], ExposureMask, True,
2669 (XtEventHandler)SFexposeList, (XtPointer)(long_u)n);
2670 XtAddEventHandler(selFileLists[n], EnterWindowMask, False,
2671 (XtEventHandler)SFenterList, (XtPointer)(long_u)n);
2672 XtAddEventHandler(selFileLists[n], LeaveWindowMask, False,
2673 (XtEventHandler)SFleaveList, (XtPointer)(long_u)n);
2674 XtAddEventHandler(selFileLists[n], PointerMotionMask, False,
2675 (XtEventHandler)SFmotionList, (XtPointer)(long_u)n);
2676 XtAddEventHandler(selFileLists[n], ButtonPressMask, False,
2677 (XtEventHandler)SFbuttonPressList, (XtPointer)(long_u)n);
2678 XtAddEventHandler(selFileLists[n], ButtonReleaseMask, False,
2679 (XtEventHandler)SFbuttonReleaseList, (XtPointer)(long_u)n);
2682 XtAddEventHandler(selFileField, KeyPressMask, False,
2683 SFmodVerifyCallback, (XtPointer)NULL);
2685 SFapp = XtWidgetToApplicationContext(selFile);
2691 #if defined(FEAT_XFONTSET) && defined(XtNinternational)
2692 if ((unsigned long)_XawTextFormat((TextWidget)selFileField) == XawFmtWide)
2694 wchar_t *wcbuf=(wchar_t *)SFtextBuffer;
2696 if ((wcbuf[0] == L'/') || (wcbuf[0] == L'~'))
2698 (void) wcstombs(SFcurrentPath, wcbuf, MAXPATHL);
2699 SFtextPos = XawTextGetInsertionPoint(selFileField);
2703 strcpy(SFcurrentPath, SFstartDir);
2704 (void) wcstombs(SFcurrentPath + strlen(SFcurrentPath), wcbuf, MAXPATHL);
2706 SFtextPos = XawTextGetInsertionPoint(selFileField) + strlen(SFstartDir);
2711 if ((SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~'))
2713 (void) strcpy(SFcurrentPath, SFtextBuffer);
2714 SFtextPos = XawTextGetInsertionPoint(selFileField);
2718 (void) strcat(strcpy(SFcurrentPath, SFstartDir), SFtextBuffer);
2720 SFtextPos = XawTextGetInsertionPoint(selFileField) + strlen(SFstartDir);
2723 if (!SFworkProcAdded)
2725 (void) XtAppAddWorkProc(SFapp, (XtWorkProc)SFworkProc, NULL);
2726 SFworkProcAdded = 1;
2735 #if defined(FEAT_XFONTSET) && defined(XtNinternational)
2738 if ((unsigned long)_XawTextFormat((TextWidget)selFileField) == XawFmtWide)
2743 XtVaGetValues(selFileField,
2746 mbslength = wcstombs(NULL, wcbuf, 0);
2747 /* Hack: some broken wcstombs() returns zero, just get a large buffer */
2748 if (mbslength == 0 && wcbuf != NULL && wcbuf[0] != 0)
2749 mbslength = MAXPATHL;
2750 buf=(char *)XtMalloc(mbslength + 1);
2751 wcstombs(buf, wcbuf, mbslength +1);
2755 return (char *)vim_strsave((char_u *)SFtextBuffer);
2761 SFstatus = SEL_FILE_NULL;
2762 XtRemoveGrab(selFile);
2763 XtUnmapWidget(selFile);
2764 XtRemoveTimeOut(SFdirModTimerId);
2765 if (SFchdir(SFstartDir))
2767 EMSG(_("E614: vim_SelFile: can't return to current directory"));
2768 SFstatus = SEL_FILE_CANCEL;
2773 vim_SelFile(toplevel, prompt, init_path, show_entry, x, y, fg, bg, scroll_fg, scroll_bg)
2777 int (*show_entry)();
2780 guicolor_T scroll_fg, scroll_bg; /* The "Scrollbar" group colors */
2782 static int firstTime = 1;
2787 prompt = _("Pathname:");
2791 if (mch_dirname((char_u *)SFstartDir, MAXPATHL) == FAIL)
2793 EMSG(_("E615: vim_SelFile: can't get current directory"));
2800 SFdisplay = XtDisplay(toplevel);
2801 SFcreateWidgets(toplevel, prompt, _("OK"), _("Cancel"));
2805 XtVaSetValues(selFilePrompt, XtNlabel, prompt, NULL);
2806 XtVaSetValues(selFile, XtNtitle, prompt, NULL);
2807 SFsetColors(bg, fg, scroll_bg, scroll_fg);
2810 XtVaSetValues(selFile, XtNx, x, XtNy, y, NULL);
2811 XtMapWidget(selFile);
2813 (void)strcat(SFstartDir, "/");
2814 (void)strcpy(SFcurrentDir, SFstartDir);
2818 if (init_path[0] == '/')
2820 (void)strcpy(SFcurrentPath, init_path);
2821 if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir)))
2822 SFsetText(SFcurrentPath);
2824 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
2828 (void)strcat(strcpy(SFcurrentPath, SFstartDir), init_path);
2829 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
2833 (void)strcpy(SFcurrentPath, SFstartDir);
2835 SFfunc = show_entry;
2839 XtAddGrab(selFile, True, True);
2841 SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
2842 SFdirModTimer, (XtPointer) NULL);
2846 XtAppNextEvent(SFapp, &event);
2847 XtDispatchEvent(&event);
2851 SFstatus = SEL_FILE_NULL;
2855 name_return = SFgetText();
2856 SFprepareToReturn();
2858 case SEL_FILE_CANCEL:
2859 SFprepareToReturn();
2866 #endif /* FEAT_BROWSE */