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
, (XtPointer
) n
);
1648 SFnewInvertEntry(n
, event
)
1650 XMotionEvent
*event
;
1654 static int SFscrollTimerAdded
= 0;
1659 if (SFdirPtr
+ n
>= SFdirEnd
)
1662 if ((x
>= 0) && (x
<= SFupperX
) && (y
>= SFlowerY
) && (y
<= SFupperY
))
1664 SFDir
*dir
= &(SFdirs
[SFdirPtr
+ n
]);
1666 if (SFscrollTimerAdded
)
1668 SFscrollTimerAdded
= 0;
1669 XtRemoveTimeOut(SFscrollTimerId
);
1672 nw
= (y
- SFlowerY
) / SFentryHeight
;
1673 if (dir
->vOrigin
+ nw
>= dir
->nEntries
)
1679 if (SFbuttonPressed
)
1682 if (!SFscrollTimerAdded
)
1684 SFscrollTimerAdded
= 1;
1685 SFscrollTimerId
= XtAppAddTimeOut(SFapp
,
1686 SFscrollTimerInterval(), SFscrollTimer
,
1695 SFenterList(w
, n
, event
)
1698 XEnterWindowEvent
*event
;
1703 if (SFcurrentInvert
[n
] != -1)
1706 SFcurrentInvert
[n
] = -1;
1709 nw
= SFnewInvertEntry(n
, (XMotionEvent
*) event
);
1712 SFcurrentInvert
[n
] = nw
;
1718 SFleaveList(w
, n
, event
)
1721 XEvent
*event UNUSED
;
1723 if (SFcurrentInvert
[n
] != -1)
1726 SFcurrentInvert
[n
] = -1;
1731 SFmotionList(w
, n
, event
)
1734 XMotionEvent
*event
;
1738 nw
= SFnewInvertEntry(n
, event
);
1740 if (nw
!= SFcurrentInvert
[n
])
1742 if (SFcurrentInvert
[n
] != -1)
1744 SFcurrentInvert
[n
] = nw
;
1751 SFvFloatSliderMovedCallback(w
, n
, fnew
)
1758 nw
= (*(float *)fnew
) * SFdirs
[SFdirPtr
+ (int)(long)n
].nEntries
;
1759 SFvSliderMovedCallback(w
, (int)(long)n
, nw
);
1763 SFvSliderMovedCallback(w
, n
, nw
)
1772 dir
= &(SFdirs
[SFdirPtr
+ n
]);
1780 win
= XtWindow(selFileLists
[n
]);
1782 if (ABS(nw
- old
) < SFlistSize
)
1792 SFlowerY
+ (nw
- old
) * SFentryHeight
,
1793 SFentryWidth
+ SFlineToTextH
,
1794 (SFlistSize
- (nw
- old
)) * SFentryHeight
,
1801 SFlowerY
+ (SFlistSize
- (nw
- old
)) *
1803 SFentryWidth
+ SFlineToTextH
,
1804 (nw
- old
) * SFentryHeight
,
1806 SFdrawStrings(win
, dir
, SFlistSize
- (nw
- old
),
1818 SFentryWidth
+ SFlineToTextH
,
1819 (SFlistSize
- (old
- nw
)) * SFentryHeight
,
1821 SFlowerY
+ (old
- nw
) * SFentryHeight
);
1827 SFentryWidth
+ SFlineToTextH
,
1828 (old
- nw
) * SFentryHeight
,
1830 SFdrawStrings(win
, dir
, 0, old
- nw
);
1840 SFentryWidth
+ SFlineToTextH
,
1841 SFlistSize
* SFentryHeight
,
1843 SFdrawStrings(win
, dir
, 0, SFlistSize
- 1);
1848 SFvAreaSelectedCallback(w
, n
, pnew
)
1854 int nw
= (int)(long)pnew
;
1856 dir
= &(SFdirs
[SFdirPtr
+ (int)(long)n
]);
1858 #ifdef FEAT_GUI_NEXTAW
1861 if (nw
> -SFvScrollHeight
)
1868 if (nw
< SFvScrollHeight
)
1876 if (nw
> dir
->nEntries
- SFlistSize
)
1877 nw
= dir
->nEntries
- SFlistSize
;
1886 f
= ((double) nw
) / dir
->nEntries
;
1888 #ifdef FEAT_GUI_NEXTAW
1889 XawScrollbarSetThumb(
1892 (float) (((double) ((dir
->nEntries
< SFlistSize
) ?
1893 dir
->nEntries
: SFlistSize
)) / dir
->nEntries
));
1895 vim_XawScrollbarSetThumb(
1898 (float) (((double) ((dir
->nEntries
< SFlistSize
) ?
1899 dir
->nEntries
: SFlistSize
)) / dir
->nEntries
),
1900 (double)dir
->nEntries
);
1904 SFvSliderMovedCallback(w
, (int)(long)n
, nw
);
1908 SFhSliderMovedCallback(w
, n
, nw
)
1916 dir
= &(SFdirs
[SFdirPtr
+ (int)(long)n
]);
1917 save
= dir
->hOrigin
;
1918 dir
->hOrigin
= (*(float *)nw
) * dir
->nChars
;
1919 if (dir
->hOrigin
== save
)
1922 SFdrawList((int)(long)n
, SF_DO_NOT_SCROLL
);
1926 SFhAreaSelectedCallback(w
, n
, pnew
)
1932 int nw
= (int)(long)pnew
;
1934 dir
= &(SFdirs
[SFdirPtr
+ (int)(long)n
]);
1936 #ifdef FEAT_GUI_NEXTAW
1939 if (nw
> -SFhScrollWidth
)
1942 nw
= -SFcharsPerEntry
;
1946 if (nw
< SFhScrollWidth
)
1949 nw
= SFcharsPerEntry
;
1954 if (nw
> dir
->nChars
- SFcharsPerEntry
)
1955 nw
= dir
->nChars
- SFcharsPerEntry
;
1964 f
= ((double) nw
) / dir
->nChars
;
1966 #ifdef FEAT_GUI_NEXTAW
1967 XawScrollbarSetThumb(
1970 (float) (((double) ((dir
->nChars
< SFcharsPerEntry
) ?
1971 dir
->nChars
: SFcharsPerEntry
)) / dir
->nChars
));
1973 vim_XawScrollbarSetThumb(
1976 (float) (((double) ((dir
->nChars
< SFcharsPerEntry
) ?
1977 dir
->nChars
: SFcharsPerEntry
)) / dir
->nChars
),
1978 (double)dir
->nChars
);
1981 SFhSliderMovedCallback(w
, n
, (XtPointer
)&f
);
1986 SFpathSliderMovedCallback(w
, client_data
, nw
)
1988 XtPointer client_data UNUSED
;
1993 XawTextPosition pos
;
1996 SFdirPtrSave
= SFdirPtr
;
1997 SFdirPtr
= (*(float *)nw
) * SFdirEnd
;
1998 if (SFdirPtr
== SFdirPtrSave
)
2001 SFdrawLists(SF_DO_SCROLL
);
2004 while (SFdirPtr
+ n
>= SFdirEnd
)
2007 dir
= &(SFdirs
[SFdirPtr
+ n
]);
2009 pos
= dir
->path
- SFcurrentPath
;
2011 if (!strncmp(SFcurrentPath
, SFstartDir
, strlen(SFstartDir
)))
2013 pos
-= strlen(SFstartDir
);
2018 XawTextSetInsertionPoint(selFileField
, pos
);
2022 SFpathAreaSelectedCallback(w
, client_data
, pnew
)
2024 XtPointer client_data UNUSED
;
2027 int nw
= (int)(long)pnew
;
2030 #ifdef FEAT_GUI_NEXTAW
2033 if (nw
> -SFpathScrollWidth
)
2040 if (nw
< SFpathScrollWidth
)
2048 if (nw
> SFdirEnd
- 3)
2054 f
= ((double) nw
) / SFdirEnd
;
2056 #ifdef FEAT_GUI_NEXTAW
2057 XawScrollbarSetThumb(
2060 (float) (((double) ((SFdirEnd
< 3) ? SFdirEnd
: 3)) / SFdirEnd
));
2062 vim_XawScrollbarSetThumb(
2065 (float) (((double) ((SFdirEnd
< 3) ? SFdirEnd
: 3)) / SFdirEnd
),
2069 SFpathSliderMovedCallback(w
, (XtPointer
) NULL
, (XtPointer
)&f
);
2078 for (dir
= &(SFdirs
[SFdirEnd
- 1]); dir
>= SFdirs
; dir
--)
2080 if (!(dir
->nEntries
))
2082 for (entry
= &(dir
->entries
[dir
->nEntries
- 1]);
2083 entry
>= dir
->entries
;
2086 if (!(entry
->statDone
))
2088 (void)SFstatAndCheck(dir
, entry
);
2094 SFworkProcAdded
= 0;
2099 /***************** Dir.c */
2102 SFcompareEntries(p
, q
)
2106 return strcmp(((SFEntry
*)p
)->real
, ((SFEntry
*)q
)->real
);
2113 SFEntry
*result
= NULL
;
2121 struct stat statBuf
;
2123 maxChars
= strlen(dir
->dir
) - 1;
2125 dir
->entries
= NULL
;
2132 dirp
= opendir(".");
2136 (void)mch_stat(".", &statBuf
);
2137 dir
->mtime
= statBuf
.st_mtime
;
2139 while ((dp
= readdir(dirp
)))
2141 /* Ignore "." and ".." */
2142 if (strcmp(dp
->d_name
, ".") == 0 || strcmp(dp
->d_name
, "..") == 0)
2146 Alloc
= 2 * (Alloc
+ 1);
2147 result
= (SFEntry
*) XtRealloc((char *) result
,
2148 (unsigned) (Alloc
* sizeof(SFEntry
)));
2150 result
[i
].statDone
= 0;
2153 result
[i
].real
= XtMalloc((unsigned) (len
+ 2));
2154 (void) strcat(strcpy(result
[i
].real
, str
), " ");
2157 result
[i
].shown
= result
[i
].real
;
2161 qsort((char *) result
, (size_t) i
, sizeof(SFEntry
), SFcompareEntries
);
2163 dir
->entries
= result
;
2165 dir
->nChars
= maxChars
+ 1;
2172 /***************** SFinternal.h */
2174 #include <sys/param.h>
2175 #include <X11/cursorfont.h>
2176 #include <X11/Composite.h>
2177 #include <X11/Shell.h>
2178 #ifdef FEAT_GUI_NEXTAW
2179 # include <X11/neXtaw/Form.h>
2180 # include <X11/neXtaw/Command.h>
2181 # include <X11/neXtaw/Label.h>
2183 #include <X11/Xaw/Form.h>
2184 #include <X11/Xaw/Command.h>
2185 #include <X11/Xaw/Label.h>
2188 static char *oneLineTextEditTranslations
= "\
2189 <Key>Return: redraw-display()\n\
2190 Ctrl<Key>M: redraw-display()\n\
2193 static void SFexposeList
__ARGS((Widget w
, XtPointer n
, XEvent
*event
, Boolean
*cont
));
2196 SFexposeList(w
, n
, event
, cont
)
2200 Boolean
*cont UNUSED
;
2202 if ((event
->type
== NoExpose
) || event
->xexpose
.count
)
2205 SFdrawList((int)(long)n
, SF_DO_NOT_SCROLL
);
2208 static void SFmodVerifyCallback
__ARGS((Widget w
, XtPointer client_data
, XEvent
*event
, Boolean
*cont
));
2211 SFmodVerifyCallback(w
, client_data
, event
, cont
)
2213 XtPointer client_data UNUSED
;
2215 Boolean
*cont UNUSED
;
2219 if ((XLookupString(&(event
->xkey
), buf
, 2, NULL
, NULL
) == 1) &&
2221 SFstatus
= SEL_FILE_OK
;
2223 SFstatus
= SEL_FILE_TEXT
;
2226 static void SFokCallback
__ARGS((Widget w
, XtPointer cl
, XtPointer cd
));
2229 SFokCallback(w
, cl
, cd
)
2231 XtPointer cl UNUSED
;
2232 XtPointer cd UNUSED
;
2234 SFstatus
= SEL_FILE_OK
;
2237 static XtCallbackRec SFokSelect
[] =
2239 { SFokCallback
, (XtPointer
) NULL
},
2240 { NULL
, (XtPointer
) NULL
},
2243 static void SFcancelCallback
__ARGS((Widget w
, XtPointer cl
, XtPointer cd
));
2246 SFcancelCallback(w
, cl
, cd
)
2248 XtPointer cl UNUSED
;
2249 XtPointer cd UNUSED
;
2251 SFstatus
= SEL_FILE_CANCEL
;
2254 static XtCallbackRec SFcancelSelect
[] =
2256 { SFcancelCallback
, (XtPointer
) NULL
},
2257 { NULL
, (XtPointer
) NULL
},
2260 static void SFdismissAction
__ARGS((Widget w
, XEvent
*event
, String
*params
, Cardinal
*num_params
));
2263 SFdismissAction(w
, event
, params
, num_params
)
2266 String
*params UNUSED
;
2267 Cardinal
*num_params UNUSED
;
2269 if (event
->type
== ClientMessage
2270 && (Atom
)event
->xclient
.data
.l
[0] != SFwmDeleteWindow
)
2273 SFstatus
= SEL_FILE_CANCEL
;
2276 static char *wmDeleteWindowTranslation
= "\
2277 <Message>WM_PROTOCOLS: SelFileDismiss()\n\
2280 static XtActionsRec actions
[] =
2282 {"SelFileDismiss", SFdismissAction
},
2286 SFsetColors(bg
, fg
, scroll_bg
, scroll_fg
)
2289 guicolor_T scroll_bg
;
2290 guicolor_T scroll_fg
;
2294 XtVaSetValues(selFileForm
, XtNbackground
, bg
,
2302 for (i
= 0; i
< 3; ++i
)
2304 if (selFileLists
[i
])
2306 XtVaSetValues(selFileLists
[i
], XtNbackground
, bg
,
2315 XtVaSetValues(selFileOK
, XtNbackground
, bg
,
2322 XtVaSetValues(selFileCancel
, XtNbackground
, bg
,
2329 XtVaSetValues(selFilePrompt
, XtNbackground
, bg
,
2335 XSetBackground(gui
.dpy
, SFtextGC
, bg
);
2336 XSetForeground(gui
.dpy
, SFtextGC
, fg
);
2337 XSetForeground(gui
.dpy
, SFlineGC
, fg
);
2339 /* This is an xor GC, so combine the fg and background */
2340 XSetBackground(gui
.dpy
, SFinvertGC
, fg
^ bg
);
2341 XSetForeground(gui
.dpy
, SFinvertGC
, fg
^ bg
);
2345 XtVaSetValues(selFileHScroll
, XtNbackground
, scroll_bg
,
2346 XtNforeground
, scroll_fg
,
2353 for (i
= 0; i
< 3; i
++)
2355 XtVaSetValues(selFileVScrolls
[i
], XtNbackground
, scroll_bg
,
2356 XtNforeground
, scroll_fg
,
2359 XtVaSetValues(selFileHScrolls
[i
], XtNbackground
, scroll_bg
,
2360 XtNforeground
, scroll_fg
,
2368 SFcreateWidgets(toplevel
, prompt
, ok
, cancel
)
2375 int listWidth
, listHeight
;
2376 int listSpacing
= 10;
2377 int scrollThickness
= 15;
2378 int hScrollX
, hScrollY
;
2379 int vScrollX
, vScrollY
;
2381 selFile
= XtVaAppCreateShell("selFile", "SelFile",
2382 transientShellWidgetClass
, SFdisplay
,
2383 XtNtransientFor
, toplevel
,
2387 /* Add WM_DELETE_WINDOW protocol */
2388 XtAppAddActions(XtWidgetToApplicationContext(selFile
),
2389 actions
, XtNumber(actions
));
2390 XtOverrideTranslations(selFile
,
2391 XtParseTranslationTable(wmDeleteWindowTranslation
));
2393 selFileForm
= XtVaCreateManagedWidget("selFileForm",
2394 formWidgetClass
, selFile
,
2395 XtNdefaultDistance
, 30,
2396 XtNforeground
, SFfore
,
2397 XtNbackground
, SFback
,
2398 XtNborderColor
, SFback
,
2401 selFilePrompt
= XtVaCreateManagedWidget("selFilePrompt",
2402 labelWidgetClass
, selFileForm
,
2406 XtNbottom
, XtChainTop
,
2407 XtNleft
, XtChainLeft
,
2408 XtNright
, XtChainLeft
,
2410 XtNforeground
, SFfore
,
2411 XtNbackground
, SFback
,
2415 XtVaGetValues(selFilePrompt,
2416 XtNforeground, &SFfore,
2417 XtNbackground, &SFback,
2423 SFentryWidth
= SFbesideText
+ SFcharsPerEntry
* SFcharWidth
+
2425 SFentryHeight
= SFaboveAndBelowText
+ SFcharHeight
+
2426 SFaboveAndBelowText
;
2428 listWidth
= SFlineToTextH
+ SFentryWidth
+ SFlineToTextH
+ 1 +
2430 listHeight
= SFlineToTextV
+ SFentryHeight
+ SFlineToTextV
+ 1 +
2431 SFlineToTextV
+ SFlistSize
* SFentryHeight
+
2432 SFlineToTextV
+ 1 + scrollThickness
;
2434 SFpathScrollWidth
= 3 * listWidth
+ 2 * listSpacing
+ 4;
2437 hScrollY
= SFlineToTextV
+ SFentryHeight
+ SFlineToTextV
+ 1 +
2438 SFlineToTextV
+ SFlistSize
* SFentryHeight
+
2440 SFhScrollWidth
= SFlineToTextH
+ SFentryWidth
+ SFlineToTextH
;
2442 vScrollX
= SFlineToTextH
+ SFentryWidth
+ SFlineToTextH
;
2443 vScrollY
= SFlineToTextV
+ SFentryHeight
+ SFlineToTextV
;
2444 SFvScrollHeight
= SFlineToTextV
+ SFlistSize
* SFentryHeight
+
2447 SFupperX
= SFlineToTextH
+ SFentryWidth
+ SFlineToTextH
- 1;
2448 SFlowerY
= SFlineToTextV
+ SFentryHeight
+ SFlineToTextV
+ 1 +
2450 SFupperY
= SFlineToTextV
+ SFentryHeight
+ SFlineToTextV
+ 1 +
2451 SFlineToTextV
+ SFlistSize
* SFentryHeight
- 1;
2453 SFtextX
= SFlineToTextH
+ SFbesideText
;
2454 SFtextYoffset
= SFlowerY
+ SFaboveAndBelowText
+ SFcharAscent
;
2457 SFsegs
[0].y1
= vScrollY
;
2458 SFsegs
[0].x2
= vScrollX
- 1;
2459 SFsegs
[0].y2
= vScrollY
;
2460 SFsegs
[1].x1
= vScrollX
;
2462 SFsegs
[1].x2
= vScrollX
;
2463 SFsegs
[1].y2
= vScrollY
- 1;
2465 SFcompletionSegs
[0].x1
= SFcompletionSegs
[0].x2
= SFlineToTextH
;
2466 SFcompletionSegs
[1].x1
= SFcompletionSegs
[1].x2
=
2467 SFlineToTextH
+ SFentryWidth
- 1;
2469 selFileField
= XtVaCreateManagedWidget("selFileField",
2470 asciiTextWidgetClass
, selFileForm
,
2471 XtNwidth
, 3 * listWidth
+ 2 * listSpacing
+ 4,
2472 XtNborderColor
, SFfore
,
2473 XtNfromVert
, selFilePrompt
,
2474 XtNvertDistance
, 10,
2477 XtNbottom
, XtChainTop
,
2478 XtNleft
, XtChainLeft
,
2479 XtNright
, XtChainLeft
,
2480 XtNstring
, SFtextBuffer
,
2481 XtNlength
, MAXPATHL
,
2482 XtNeditType
, XawtextEdit
,
2483 XtNwrap
, XawtextWrapWord
,
2484 XtNresize
, XawtextResizeHeight
,
2485 XtNuseStringInPlace
, True
,
2488 XtOverrideTranslations(selFileField
,
2489 XtParseTranslationTable(oneLineTextEditTranslations
));
2490 XtSetKeyboardFocus(selFileForm
, selFileField
);
2492 selFileHScroll
= XtVaCreateManagedWidget("selFileHScroll",
2493 #ifdef FEAT_GUI_NEXTAW
2494 scrollbarWidgetClass
, selFileForm
,
2496 vim_scrollbarWidgetClass
, selFileForm
,
2498 XtNorientation
, XtorientHorizontal
,
2499 XtNwidth
, SFpathScrollWidth
,
2500 XtNheight
, scrollThickness
,
2501 XtNborderColor
, SFfore
,
2502 XtNfromVert
, selFileField
,
2503 XtNvertDistance
, 30,
2505 XtNbottom
, XtChainTop
,
2506 XtNleft
, XtChainLeft
,
2507 XtNright
, XtChainLeft
,
2508 XtNforeground
, gui
.scroll_fg_pixel
,
2509 XtNbackground
, gui
.scroll_bg_pixel
,
2510 #ifndef FEAT_GUI_NEXTAW
2515 XtAddCallback(selFileHScroll
, XtNjumpProc
,
2516 (XtCallbackProc
) SFpathSliderMovedCallback
, (XtPointer
)NULL
);
2517 XtAddCallback(selFileHScroll
, XtNscrollProc
,
2518 (XtCallbackProc
) SFpathAreaSelectedCallback
, (XtPointer
)NULL
);
2520 selFileLists
[0] = XtVaCreateManagedWidget("selFileList1",
2521 compositeWidgetClass
, selFileForm
,
2522 XtNwidth
, listWidth
,
2523 XtNheight
, listHeight
,
2524 XtNforeground
, SFfore
,
2525 XtNbackground
, SFback
,
2526 XtNborderColor
, SFfore
,
2527 XtNfromVert
, selFileHScroll
,
2528 XtNvertDistance
, 10,
2530 XtNbottom
, XtChainTop
,
2531 XtNleft
, XtChainLeft
,
2532 XtNright
, XtChainLeft
,
2535 selFileLists
[1] = XtVaCreateManagedWidget("selFileList2",
2536 compositeWidgetClass
, selFileForm
,
2537 XtNwidth
, listWidth
,
2538 XtNheight
, listHeight
,
2539 XtNforeground
, SFfore
,
2540 XtNbackground
, SFback
,
2541 XtNborderColor
, SFfore
,
2542 XtNfromHoriz
, selFileLists
[0],
2543 XtNfromVert
, selFileHScroll
,
2544 XtNhorizDistance
, listSpacing
,
2545 XtNvertDistance
, 10,
2547 XtNbottom
, XtChainTop
,
2548 XtNleft
, XtChainLeft
,
2549 XtNright
, XtChainLeft
,
2552 selFileLists
[2] = XtVaCreateManagedWidget("selFileList3",
2553 compositeWidgetClass
, selFileForm
,
2554 XtNwidth
, listWidth
,
2555 XtNheight
, listHeight
,
2556 XtNforeground
, SFfore
,
2557 XtNbackground
, SFback
,
2558 XtNborderColor
, SFfore
,
2559 XtNfromHoriz
, selFileLists
[1],
2560 XtNfromVert
, selFileHScroll
,
2561 XtNhorizDistance
, listSpacing
,
2562 XtNvertDistance
, 10,
2564 XtNbottom
, XtChainTop
,
2565 XtNleft
, XtChainLeft
,
2566 XtNright
, XtChainLeft
,
2569 for (n
= 0; n
< 3; n
++)
2571 selFileVScrolls
[n
] = XtVaCreateManagedWidget("selFileVScroll",
2572 #ifdef FEAT_GUI_NEXTAW
2573 scrollbarWidgetClass
, selFileLists
[n
],
2575 vim_scrollbarWidgetClass
, selFileLists
[n
],
2579 XtNwidth
, scrollThickness
,
2580 XtNheight
, SFvScrollHeight
,
2581 XtNborderColor
, SFfore
,
2582 XtNforeground
, gui
.scroll_fg_pixel
,
2583 XtNbackground
, gui
.scroll_bg_pixel
,
2584 #ifndef FEAT_GUI_NEXTAW
2589 XtAddCallback(selFileVScrolls
[n
], XtNjumpProc
,
2590 (XtCallbackProc
)SFvFloatSliderMovedCallback
, (XtPointer
)n
);
2591 XtAddCallback(selFileVScrolls
[n
], XtNscrollProc
,
2592 (XtCallbackProc
)SFvAreaSelectedCallback
, (XtPointer
)n
);
2594 selFileHScrolls
[n
] = XtVaCreateManagedWidget("selFileHScroll",
2595 #ifdef FEAT_GUI_NEXTAW
2596 scrollbarWidgetClass
, selFileLists
[n
],
2598 vim_scrollbarWidgetClass
, selFileLists
[n
],
2600 XtNorientation
, XtorientHorizontal
,
2603 XtNwidth
, SFhScrollWidth
,
2604 XtNheight
, scrollThickness
,
2605 XtNborderColor
, SFfore
,
2606 XtNforeground
, gui
.scroll_fg_pixel
,
2607 XtNbackground
, gui
.scroll_bg_pixel
,
2608 #ifndef FEAT_GUI_NEXTAW
2613 XtAddCallback(selFileHScrolls
[n
], XtNjumpProc
,
2614 (XtCallbackProc
)SFhSliderMovedCallback
, (XtPointer
)n
);
2615 XtAddCallback(selFileHScrolls
[n
], XtNscrollProc
,
2616 (XtCallbackProc
)SFhAreaSelectedCallback
, (XtPointer
)n
);
2619 selFileOK
= XtVaCreateManagedWidget("selFileOK",
2620 commandWidgetClass
, selFileForm
,
2623 XtNcallback
, SFokSelect
,
2624 XtNforeground
, SFfore
,
2625 XtNbackground
, SFback
,
2626 XtNborderColor
, SFfore
,
2627 XtNfromHoriz
, selFileLists
[0],
2628 XtNfromVert
, selFileLists
[0],
2629 XtNvertDistance
, 30,
2631 XtNbottom
, XtChainTop
,
2632 XtNleft
, XtChainLeft
,
2633 XtNright
, XtChainLeft
,
2636 selFileCancel
= XtVaCreateManagedWidget("selFileCancel",
2637 commandWidgetClass
, selFileForm
,
2640 XtNcallback
, SFcancelSelect
,
2641 XtNforeground
, SFfore
,
2642 XtNbackground
, SFback
,
2643 XtNborderColor
, SFfore
,
2644 XtNfromHoriz
, selFileOK
,
2645 XtNfromVert
, selFileLists
[0],
2646 XtNhorizDistance
, 30,
2647 XtNvertDistance
, 30,
2649 XtNbottom
, XtChainTop
,
2650 XtNleft
, XtChainLeft
,
2651 XtNright
, XtChainLeft
,
2654 XtSetMappedWhenManaged(selFile
, False
);
2655 XtRealizeWidget(selFile
);
2657 /* Add WM_DELETE_WINDOW protocol */
2658 SFwmDeleteWindow
= XInternAtom(SFdisplay
, "WM_DELETE_WINDOW", False
);
2659 XSetWMProtocols(SFdisplay
, XtWindow(selFile
), &SFwmDeleteWindow
, 1);
2663 for (n
= 0; n
< 3; n
++)
2665 XtAddEventHandler(selFileLists
[n
], ExposureMask
, True
,
2666 (XtEventHandler
)SFexposeList
, (XtPointer
)n
);
2667 XtAddEventHandler(selFileLists
[n
], EnterWindowMask
, False
,
2668 (XtEventHandler
)SFenterList
, (XtPointer
)n
);
2669 XtAddEventHandler(selFileLists
[n
], LeaveWindowMask
, False
,
2670 (XtEventHandler
)SFleaveList
, (XtPointer
)n
);
2671 XtAddEventHandler(selFileLists
[n
], PointerMotionMask
, False
,
2672 (XtEventHandler
)SFmotionList
, (XtPointer
)n
);
2673 XtAddEventHandler(selFileLists
[n
], ButtonPressMask
, False
,
2674 (XtEventHandler
)SFbuttonPressList
, (XtPointer
)n
);
2675 XtAddEventHandler(selFileLists
[n
], ButtonReleaseMask
, False
,
2676 (XtEventHandler
)SFbuttonReleaseList
, (XtPointer
)n
);
2679 XtAddEventHandler(selFileField
, KeyPressMask
, False
,
2680 SFmodVerifyCallback
, (XtPointer
)NULL
);
2682 SFapp
= XtWidgetToApplicationContext(selFile
);
2688 #if defined(FEAT_XFONTSET) && defined(XtNinternational)
2689 if ((unsigned long)_XawTextFormat((TextWidget
)selFileField
) == XawFmtWide
)
2691 wchar_t *wcbuf
=(wchar_t *)SFtextBuffer
;
2693 if ((wcbuf
[0] == L
'/') || (wcbuf
[0] == L
'~'))
2695 (void) wcstombs(SFcurrentPath
, wcbuf
, MAXPATHL
);
2696 SFtextPos
= XawTextGetInsertionPoint(selFileField
);
2700 strcpy(SFcurrentPath
, SFstartDir
);
2701 (void) wcstombs(SFcurrentPath
+ strlen(SFcurrentPath
), wcbuf
, MAXPATHL
);
2703 SFtextPos
= XawTextGetInsertionPoint(selFileField
) + strlen(SFstartDir
);
2708 if ((SFtextBuffer
[0] == '/') || (SFtextBuffer
[0] == '~'))
2710 (void) strcpy(SFcurrentPath
, SFtextBuffer
);
2711 SFtextPos
= XawTextGetInsertionPoint(selFileField
);
2715 (void) strcat(strcpy(SFcurrentPath
, SFstartDir
), SFtextBuffer
);
2717 SFtextPos
= XawTextGetInsertionPoint(selFileField
) + strlen(SFstartDir
);
2720 if (!SFworkProcAdded
)
2722 (void) XtAppAddWorkProc(SFapp
, (XtWorkProc
)SFworkProc
, NULL
);
2723 SFworkProcAdded
= 1;
2732 #if defined(FEAT_XFONTSET) && defined(XtNinternational)
2735 if ((unsigned long)_XawTextFormat((TextWidget
)selFileField
) == XawFmtWide
)
2740 XtVaGetValues(selFileField
,
2743 mbslength
= wcstombs(NULL
, wcbuf
, 0);
2744 /* Hack: some broken wcstombs() returns zero, just get a large buffer */
2745 if (mbslength
== 0 && wcbuf
!= NULL
&& wcbuf
[0] != 0)
2746 mbslength
= MAXPATHL
;
2747 buf
=(char *)XtMalloc(mbslength
+ 1);
2748 wcstombs(buf
, wcbuf
, mbslength
+1);
2752 return (char *)vim_strsave((char_u
*)SFtextBuffer
);
2758 SFstatus
= SEL_FILE_NULL
;
2759 XtRemoveGrab(selFile
);
2760 XtUnmapWidget(selFile
);
2761 XtRemoveTimeOut(SFdirModTimerId
);
2762 if (SFchdir(SFstartDir
))
2764 EMSG(_("E614: vim_SelFile: can't return to current directory"));
2765 SFstatus
= SEL_FILE_CANCEL
;
2770 vim_SelFile(toplevel
, prompt
, init_path
, show_entry
, x
, y
, fg
, bg
, scroll_fg
, scroll_bg
)
2774 int (*show_entry
)();
2777 guicolor_T scroll_fg
, scroll_bg
; /* The "Scrollbar" group colors */
2779 static int firstTime
= 1;
2784 prompt
= _("Pathname:");
2788 if (mch_dirname((char_u
*)SFstartDir
, MAXPATHL
) == FAIL
)
2790 EMSG(_("E615: vim_SelFile: can't get current directory"));
2797 SFdisplay
= XtDisplay(toplevel
);
2798 SFcreateWidgets(toplevel
, prompt
, _("OK"), _("Cancel"));
2802 XtVaSetValues(selFilePrompt
, XtNlabel
, prompt
, NULL
);
2803 XtVaSetValues(selFile
, XtNtitle
, prompt
, NULL
);
2804 SFsetColors(bg
, fg
, scroll_bg
, scroll_fg
);
2807 XtVaSetValues(selFile
, XtNx
, x
, XtNy
, y
, NULL
);
2808 XtMapWidget(selFile
);
2810 (void)strcat(SFstartDir
, "/");
2811 (void)strcpy(SFcurrentDir
, SFstartDir
);
2815 if (init_path
[0] == '/')
2817 (void)strcpy(SFcurrentPath
, init_path
);
2818 if (strncmp(SFcurrentPath
, SFstartDir
, strlen(SFstartDir
)))
2819 SFsetText(SFcurrentPath
);
2821 SFsetText(&(SFcurrentPath
[strlen(SFstartDir
)]));
2825 (void)strcat(strcpy(SFcurrentPath
, SFstartDir
), init_path
);
2826 SFsetText(&(SFcurrentPath
[strlen(SFstartDir
)]));
2830 (void)strcpy(SFcurrentPath
, SFstartDir
);
2832 SFfunc
= show_entry
;
2836 XtAddGrab(selFile
, True
, True
);
2838 SFdirModTimerId
= XtAppAddTimeOut(SFapp
, (unsigned long) 1000,
2839 SFdirModTimer
, (XtPointer
) NULL
);
2843 XtAppNextEvent(SFapp
, &event
);
2844 XtDispatchEvent(&event
);
2848 SFstatus
= SEL_FILE_NULL
;
2852 name_return
= SFgetText();
2853 SFprepareToReturn();
2855 case SEL_FILE_CANCEL
:
2856 SFprepareToReturn();
2863 #endif /* FEAT_BROWSE */