blob: 0206284b2a7181eb00e6726f8a56bf75ef6abeb2 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4: */
2
3/*
4 * Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
5 *
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.
15 *
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.
23 *
24 * Author: Erik M. van der Poel
25 * Software Research Associates, Inc., Tokyo, Japan
26 * erik@sra.co.jp
27 */
28/*
29 * Author's addresses:
30 * erik@sra.co.jp
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
38 */
39
40/*
41 * Heavely modified for Vim by Bram Moolenaar
42 */
43
44#include "vim.h"
45
46/* Only include this when using the file browser */
47
48#ifdef FEAT_BROWSE
49
50/* Weird complication: for "make lint" Text.h doesn't combine with Xm.h */
51#if defined(FEAT_GUI_MOTIF) && defined(FMT8BIT)
52# undef FMT8BIT
53#endif
54
55#ifndef FEAT_GUI_NEXTAW
56# include "gui_at_sb.h"
57#endif
58
59/***************** SFinternal.h */
60
61#include <X11/Intrinsic.h>
62#include <X11/StringDefs.h>
63#include <X11/Xos.h>
64#ifdef FEAT_GUI_NEXTAW
65# include <X11/neXtaw/Text.h>
66# include <X11/neXtaw/AsciiText.h>
67# include <X11/neXtaw/Scrollbar.h>
68#else
69# include <X11/Xaw/Text.h>
70# include <X11/Xaw/AsciiText.h>
71#endif
72
73#define SEL_FILE_CANCEL -1
74#define SEL_FILE_OK 0
75#define SEL_FILE_NULL 1
76#define SEL_FILE_TEXT 2
77
78#define SF_DO_SCROLL 1
79#define SF_DO_NOT_SCROLL 0
80
81typedef struct
82{
83 int statDone;
84 char *real;
85 char *shown;
86} SFEntry;
87
88typedef struct
89{
90 char *dir;
91 char *path;
92 SFEntry *entries;
93 int nEntries;
94 int vOrigin;
95 int nChars;
96 int hOrigin;
97 int changed;
98 int beginSelection;
99 int endSelection;
100 time_t mtime;
101} SFDir;
102
103static char SFstartDir[MAXPATHL],
104 SFcurrentPath[MAXPATHL],
105 SFcurrentDir[MAXPATHL];
106
107static Widget selFile,
108 selFileField,
109 selFileForm,
110 selFileHScroll,
111 selFileHScrolls[3],
112 selFileLists[3],
113 selFileOK,
114 selFileCancel,
115 selFilePrompt,
116 selFileVScrolls[3];
117
118static Display *SFdisplay;
119
120static int SFcharWidth, SFcharAscent, SFcharHeight;
121
122static SFDir *SFdirs = NULL;
123
124static int SFdirEnd;
125static int SFdirPtr;
126
127static Pixel SFfore, SFback;
128
129static Atom SFwmDeleteWindow;
130
131static XSegment SFsegs[2], SFcompletionSegs[2];
132
133static XawTextPosition SFtextPos;
134
135static int SFupperX, SFlowerY, SFupperY;
136
137static int SFtextX, SFtextYoffset;
138
139static int SFentryWidth, SFentryHeight;
140
141static int SFlineToTextH = 3;
142static int SFlineToTextV = 3;
143
144static int SFbesideText = 3;
145static int SFaboveAndBelowText = 2;
146
147static int SFcharsPerEntry = 15;
148
149static int SFlistSize = 10;
150
151static int SFcurrentInvert[3] = { -1, -1, -1 };
152
153static int SFworkProcAdded = 0;
154
155static XtAppContext SFapp;
156
157static int SFpathScrollWidth, SFvScrollHeight, SFhScrollWidth;
158
159#ifdef FEAT_XFONTSET
160static char SFtextBuffer[MAXPATHL*sizeof(wchar_t)];
161#else
162static char SFtextBuffer[MAXPATHL];
163#endif
164
165static int SFbuttonPressed = 0;
166
167static XtIntervalId SFdirModTimerId;
168
169static int (*SFfunc)();
170
171static int SFstatus = SEL_FILE_NULL;
172
173/***************** static functions */
174
175static void SFsetText __ARGS((char *path));
176static void SFtextChanged __ARGS((void));
177static char *SFgetText __ARGS((void));
178static void SFupdatePath __ARGS((void));
179static int SFgetDir __ARGS((SFDir *dir));
180static void SFdrawLists __ARGS((int doScroll));
181static void SFdrawList __ARGS((int n, int doScroll));
182static void SFclearList __ARGS((int n, int doScroll));
183static void SFbuttonPressList __ARGS((Widget w, int n, XButtonPressedEvent *event));
184static void SFbuttonReleaseList __ARGS((Widget w, int n, XButtonReleasedEvent *event));
185static void SFdirModTimer __ARGS((XtPointer cl, XtIntervalId *id));
186static char SFstatChar __ARGS((struct stat *statBuf));
187static void SFdrawStrings __ARGS((Window w, SFDir *dir, int from, int to));
188static int SFnewInvertEntry __ARGS((int n, XMotionEvent *event));
189static void SFinvertEntry __ARGS((int n));
190static void SFenterList __ARGS((Widget w, int n, XEnterWindowEvent *event));
191static void SFleaveList __ARGS((Widget w, int n, XEvent *event));
192static void SFmotionList __ARGS((Widget w, int n, XMotionEvent *event));
193static void SFvFloatSliderMovedCallback __ARGS((Widget w, XtPointer n, XtPointer fnew));
194static void SFvSliderMovedCallback __ARGS((Widget w, int n, int nw));
195static void SFvAreaSelectedCallback __ARGS((Widget w, XtPointer n, XtPointer pnew));
196static void SFhSliderMovedCallback __ARGS((Widget w, XtPointer n, XtPointer nw));
197static void SFhAreaSelectedCallback __ARGS((Widget w, XtPointer n, XtPointer pnew));
198static void SFpathSliderMovedCallback __ARGS((Widget w, XtPointer client_data, XtPointer nw));
199static void SFpathAreaSelectedCallback __ARGS((Widget w, XtPointer client_data, XtPointer pnew));
200static Boolean SFworkProc __ARGS((void));
201static int SFcompareEntries __ARGS((const void *p, const void *q));
202static void SFprepareToReturn __ARGS((void));
203static void SFcreateWidgets __ARGS((Widget toplevel, char *prompt, char *ok, char *cancel));
204static void SFsetColors __ARGS((guicolor_T bg, guicolor_T fg, guicolor_T scroll_bg, guicolor_T scrollfg));
205
206/***************** xstat.h */
207
208#ifndef S_IXUSR
209# define S_IXUSR 0100
210#endif
211#ifndef S_IXGRP
212# define S_IXGRP 0010
213#endif
214#ifndef S_IXOTH
215# define S_IXOTH 0001
216#endif
217
218#define S_ISXXX(m) ((m) & (S_IXUSR | S_IXGRP | S_IXOTH))
219
220/***************** Path.c */
221
222#include <pwd.h>
223
224typedef struct
225{
226 char *name;
227 char *dir;
228} SFLogin;
229
230static int SFdoNotTouchDirPtr = 0;
231
232static int SFdoNotTouchVorigin = 0;
233
234static SFDir SFrootDir, SFhomeDir;
235
236static SFLogin *SFlogins;
237
238static int SFtwiddle = 0;
239
240static int SFchdir __ARGS((char *path));
241
242 static int
243SFchdir(path)
244 char *path;
245{
246 int result;
247
248 result = 0;
249
250 if (strcmp(path, SFcurrentDir))
251 {
252 result = mch_chdir(path);
253 if (!result)
254 (void) strcpy(SFcurrentDir, path);
255 }
256
257 return result;
258}
259
260static void SFfree __ARGS((int i));
261
262 static void
263SFfree(i)
264 int i;
265{
266 SFDir *dir;
267 int j;
268
269 dir = &(SFdirs[i]);
270
271 for (j = dir->nEntries - 1; j >= 0; j--)
272 {
273 if (dir->entries[j].shown != dir->entries[j].real)
274 XtFree(dir->entries[j].shown);
275 XtFree(dir->entries[j].real);
276 }
277
278 XtFree((char *)dir->entries);
279 XtFree(dir->dir);
280
281 dir->dir = NULL;
282}
283
284static void SFstrdup __ARGS((char **s1, char *s2));
285
286 static void
287SFstrdup(s1, s2)
288 char **s1;
289 char *s2;
290{
291 *s1 = strcpy(XtMalloc((unsigned)(strlen(s2) + 1)), s2);
292}
293
294static void SFunreadableDir __ARGS((SFDir *dir));
295
296 static void
297SFunreadableDir(dir)
298 SFDir *dir;
299{
300 char *cannotOpen = _("<cannot open> ");
301
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;
306 dir->nEntries = 1;
307 dir->nChars = strlen(cannotOpen);
308}
309
310static void SFreplaceText __ARGS((SFDir *dir, char *str));
311
312 static void
313SFreplaceText(dir, str)
314 SFDir *dir;
315 char *str;
316{
317 int len;
318
319 *(dir->path) = 0;
320 len = strlen(str);
321 if (str[len - 1] == '/')
322 (void) strcat(SFcurrentPath, str);
323 else
324 (void) strncat(SFcurrentPath, str, len - 1);
325 if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir)))
326 SFsetText(SFcurrentPath);
327 else
328 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
329
330 SFtextChanged();
331}
332
333static void SFexpand __ARGS((char *str));
334
335 static void
336SFexpand(str)
337 char *str;
338{
339 int len;
340 int cmp;
341 char *name, *growing;
342 SFDir *dir;
343 SFEntry *entry, *max;
344
345 len = strlen(str);
346
347 dir = &(SFdirs[SFdirEnd - 1]);
348
349 if (dir->beginSelection == -1)
350 {
351 SFstrdup(&str, str);
352 SFreplaceText(dir, str);
353 XtFree(str);
354 return;
355 }
356 else if (dir->beginSelection == dir->endSelection)
357 {
358 SFreplaceText(dir, dir->entries[dir->beginSelection].shown);
359 return;
360 }
361
362 max = &(dir->entries[dir->endSelection + 1]);
363
364 name = dir->entries[dir->beginSelection].shown;
365 SFstrdup(&growing, name);
366
367 cmp = 0;
368 while (!cmp)
369 {
370 entry = &(dir->entries[dir->beginSelection]);
371 while (entry < max)
372 {
373 if ((cmp = strncmp(growing, entry->shown, len)))
374 break;
375 entry++;
376 }
377 len++;
378 }
379
380 /*
381 * SFreplaceText() expects filename
382 */
383 growing[len - 2] = ' ';
384
385 growing[len - 1] = 0;
386 SFreplaceText(dir, growing);
387 XtFree(growing);
388}
389
390static int SFfindFile __ARGS((SFDir *dir, char *str));
391
392 static int
393SFfindFile(dir, str)
394 SFDir *dir;
395 char *str;
396{
397 int i, last, max;
398 char *name, save;
399 SFEntry *entries;
400 int len;
401 int begin, end;
402 int result;
403
404 len = strlen(str);
405
406 if (str[len - 1] == ' ')
407 {
408 SFexpand(str);
409 return 1;
410 }
411 else if (str[len - 1] == '/')
412 len--;
413
414 max = dir->nEntries;
415
416 entries = dir->entries;
417
418 i = 0;
419 while (i < max)
420 {
421 name = entries[i].shown;
422 last = strlen(name) - 1;
423 save = name[last];
424 name[last] = 0;
425
426 result = strncmp(str, name, len);
427
428 name[last] = save;
429 if (result <= 0)
430 break;
431 i++;
432 }
433 begin = i;
434 while (i < max)
435 {
436 name = entries[i].shown;
437 last = strlen(name) - 1;
438 save = name[last];
439 name[last] = 0;
440
441 result = strncmp(str, name, len);
442
443 name[last] = save;
444 if (result)
445 break;
446 i++;
447 }
448 end = i;
449
450 if (begin != end)
451 {
452 if ((dir->beginSelection != begin) || (dir->endSelection != end - 1))
453 {
454 dir->changed = 1;
455 dir->beginSelection = begin;
456 if (str[strlen(str) - 1] == '/')
457 dir->endSelection = begin;
458 else
459 dir->endSelection = end - 1;
460 }
461 }
462 else if (dir->beginSelection != -1)
463 {
464 dir->changed = 1;
465 dir->beginSelection = -1;
466 dir->endSelection = -1;
467 }
468
469 if (SFdoNotTouchVorigin
470 || ((begin > dir->vOrigin) && (end < dir->vOrigin + SFlistSize)))
471 {
472 SFdoNotTouchVorigin = 0;
473 return 0;
474 }
475
476 i = begin - 1;
477 if (i > max - SFlistSize)
478 i = max - SFlistSize;
479 if (i < 0)
480 i = 0;
481
482 if (dir->vOrigin != i)
483 {
484 dir->vOrigin = i;
485 dir->changed = 1;
486 }
487
488 return 0;
489}
490
491static void SFunselect __ARGS((void));
492
493 static void
494SFunselect()
495{
496 SFDir *dir;
497
498 dir = &(SFdirs[SFdirEnd - 1]);
499 if (dir->beginSelection != -1)
500 dir->changed = 1;
501 dir->beginSelection = -1;
502 dir->endSelection = -1;
503}
504
505static int SFcompareLogins __ARGS((const void *p, const void *q));
506
507 static int
508SFcompareLogins(p, q)
509 const void *p, *q;
510{
511 return strcmp(((SFLogin *)p)->name, ((SFLogin *)q)->name);
512}
513
514static void SFgetHomeDirs __ARGS((void));
515
516 static void
517SFgetHomeDirs()
518{
519 struct passwd *pw;
520 int Alloc;
521 int i;
522 SFEntry *entries = NULL;
523 int len;
524 int maxChars;
525
526 Alloc = 1;
527 i = 1;
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 : "/");
537 maxChars = 0;
538
539 (void) setpwent();
540
541 while ((pw = getpwent()) && (*(pw->pw_name)))
542 {
543 if (i >= Alloc)
544 {
545 Alloc *= 2;
546 entries = (SFEntry *) XtRealloc((char *)entries,
547 (unsigned)(Alloc * sizeof(SFEntry)));
548 SFlogins = (SFLogin *) XtRealloc((char *)SFlogins,
549 (unsigned)(Alloc * sizeof(SFLogin)));
550 }
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;
556 if (len > maxChars)
557 maxChars = len;
558 SFstrdup(&SFlogins[i].name, pw->pw_name);
559 SFstrdup(&SFlogins[i].dir, pw->pw_dir);
560 i++;
561 }
562
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;
574
575 qsort((char *)entries, (size_t)i, sizeof(SFEntry), SFcompareEntries);
576 qsort((char *)SFlogins, (size_t)i, sizeof(SFLogin), SFcompareLogins);
577
578 for (i--; i >= 0; i--)
579 (void)strcat(entries[i].real, "/");
580}
581
582static int SFfindHomeDir __ARGS((char *begin, char *end));
583
584 static int
585SFfindHomeDir(begin, end)
586 char *begin, *end;
587{
588 char save;
589 char *theRest;
590 int i;
591
592 save = *end;
593 *end = 0;
594
595 for (i = SFhomeDir.nEntries - 1; i >= 0; i--)
596 {
597 if (!strcmp(SFhomeDir.entries[i].real, begin))
598 {
599 *end = save;
600 SFstrdup(&theRest, end);
601 (void) strcat(strcat(strcpy(SFcurrentPath,
602 SFlogins[i].dir), "/"), theRest);
603 XtFree(theRest);
604 SFsetText(SFcurrentPath);
605 SFtextChanged();
606 return 1;
607 }
608 }
609
610 *end = save;
611
612 return 0;
613}
614
615 static void
616SFupdatePath()
617{
618 static int Alloc;
619 static int wasTwiddle = 0;
620 char *begin, *end;
621 int i, j;
622 int prevChange;
623 int SFdirPtrSave, SFdirEndSave;
624 SFDir *dir;
625
626 if (!SFdirs)
627 {
628 SFdirs = (SFDir *) XtMalloc((Alloc = 10) * sizeof(SFDir));
629 dir = &(SFdirs[0]);
630 SFstrdup(&dir->dir, "/");
631 (void) SFchdir("/");
632 (void) SFgetDir(dir);
633 for (j = 1; j < Alloc; j++)
634 SFdirs[j].dir = NULL;
635 dir->path = SFcurrentPath + 1;
636 dir->vOrigin = 0;
637 dir->hOrigin = 0;
638 dir->changed = 1;
639 dir->beginSelection = -1;
640 dir->endSelection = -1;
641 SFhomeDir.dir = NULL;
642 }
643
644 SFdirEndSave = SFdirEnd;
645 SFdirEnd = 1;
646
647 SFdirPtrSave = SFdirPtr;
648 SFdirPtr = 0;
649
650 begin = NULL;
651
652 if (SFcurrentPath[0] == '~')
653 {
654 if (!SFtwiddle)
655 {
656 SFtwiddle = 1;
657 dir = &(SFdirs[0]);
658 SFrootDir = *dir;
659 if (!SFhomeDir.dir)
660 SFgetHomeDirs();
661 *dir = SFhomeDir;
662 dir->changed = 1;
663 }
664 end = SFcurrentPath;
665 SFdoNotTouchDirPtr = 1;
666 wasTwiddle = 1;
667 }
668 else
669 {
670 if (SFtwiddle)
671 {
672 SFtwiddle = 0;
673 dir = &(SFdirs[0]);
674 *dir = SFrootDir;
675 dir->changed = 1;
676 }
677 end = SFcurrentPath + 1;
678 }
679
680 i = 0;
681
682 prevChange = 0;
683
684 while (*end)
685 {
686 while (*end++ == '/')
687 ;
688 end--;
689 begin = end;
690 while ((*end) && (*end++ != '/'))
691 ;
692 if ((end - SFcurrentPath <= SFtextPos) && (*(end - 1) == '/'))
693 {
694 SFdirPtr = i - 1;
695 if (SFdirPtr < 0)
696 SFdirPtr = 0;
697 }
698 if (*begin)
699 {
700 if (*(end - 1) == '/')
701 {
702 char save = *end;
703
704 if (SFtwiddle)
705 {
706 if (SFfindHomeDir(begin, end))
707 return;
708 }
709 *end = 0;
710 i++;
711 SFdirEnd++;
712 if (i >= Alloc)
713 {
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;
718 }
719 dir = &(SFdirs[i]);
720 if ((!(dir->dir)) || prevChange || strcmp(dir->dir, begin))
721 {
722 if (dir->dir)
723 SFfree(i);
724 prevChange = 1;
725 SFstrdup(&dir->dir, begin);
726 dir->path = end;
727 dir->vOrigin = 0;
728 dir->hOrigin = 0;
729 dir->changed = 1;
730 dir->beginSelection = -1;
731 dir->endSelection = -1;
732 (void)SFfindFile(dir - 1, begin);
733 if (SFchdir(SFcurrentPath) || SFgetDir(dir))
734 {
735 SFunreadableDir(dir);
736 break;
737 }
738 }
739 *end = save;
740 if (!save)
741 SFunselect();
742 }
743 else
744 {
745 if (SFfindFile(&(SFdirs[SFdirEnd-1]), begin))
746 return;
747 }
748 }
749 else
750 SFunselect();
751 }
752
753 if ((end == SFcurrentPath + 1) && (!SFtwiddle))
754 SFunselect();
755
756 for (i = SFdirEnd; i < Alloc; i++)
757 if (SFdirs[i].dir)
758 SFfree(i);
759
760 if (SFdoNotTouchDirPtr)
761 {
762 if (wasTwiddle)
763 {
764 wasTwiddle = 0;
765 SFdirPtr = SFdirEnd - 2;
766 if (SFdirPtr < 0)
767 SFdirPtr = 0;
768 }
769 else
770 SFdirPtr = SFdirPtrSave;
771 SFdoNotTouchDirPtr = 0;
772 }
773
774 if ((SFdirPtr != SFdirPtrSave) || (SFdirEnd != SFdirEndSave))
775 {
776#ifdef FEAT_GUI_NEXTAW
777 XawScrollbarSetThumb( selFileHScroll,
778 (float) (((double) SFdirPtr) / SFdirEnd),
779 (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
780 SFdirEnd));
781#else
782 vim_XawScrollbarSetThumb( selFileHScroll,
783 (float) (((double) SFdirPtr) / SFdirEnd),
784 (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
785 SFdirEnd),
786 (double)SFdirEnd);
787#endif
788 }
789
790 if (SFdirPtr != SFdirPtrSave)
791 SFdrawLists(SF_DO_SCROLL);
792 else
793 for (i = 0; i < 3; i++)
794 {
795 if (SFdirPtr + i < SFdirEnd)
796 {
797 if (SFdirs[SFdirPtr + i].changed)
798 {
799 SFdirs[SFdirPtr + i].changed = 0;
800 SFdrawList(i, SF_DO_SCROLL);
801 }
802 }
803 else
804 SFclearList(i, SF_DO_SCROLL);
805 }
806}
807
808#ifdef XtNinternational
809 static int
810WcsLen(p)
811 wchar_t *p;
812{
813 int i = 0;
814 while (*p++ != 0)
815 i++;
816 return i;
817}
818#endif
819
820 static void
821SFsetText(path)
822 char *path;
823{
824 XawTextBlock text;
825
826 text.firstPos = 0;
827 text.length = strlen(path);
828 text.ptr = path;
829 text.format = FMT8BIT;
830
831#ifdef XtNinternational
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000832 if ((unsigned long)_XawTextFormat((TextWidget)selFileField) == XawFmtWide)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000833 {
834 XawTextReplace(selFileField, (XawTextPosition)0,
835 (XawTextPosition)WcsLen((wchar_t *)&SFtextBuffer[0]), &text);
836 XawTextSetInsertionPoint(selFileField,
837 (XawTextPosition)WcsLen((wchar_t *)&SFtextBuffer[0]));
838 }
839 else
840 {
841 XawTextReplace(selFileField, (XawTextPosition)0,
842 (XawTextPosition)strlen(SFtextBuffer), &text);
843 XawTextSetInsertionPoint(selFileField,
844 (XawTextPosition)strlen(SFtextBuffer));
845 }
846#else
847 XawTextReplace(selFileField, (XawTextPosition)0,
848 (XawTextPosition)strlen(SFtextBuffer), &text);
849 XawTextSetInsertionPoint(selFileField,
850 (XawTextPosition)strlen(SFtextBuffer));
851#endif
852}
853
Bram Moolenaar071d4272004-06-13 20:20:40 +0000854 static void
855SFbuttonPressList(w, n, event)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000856 Widget w UNUSED;
857 int n UNUSED;
858 XButtonPressedEvent *event UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000859{
860 SFbuttonPressed = 1;
861}
862
Bram Moolenaar071d4272004-06-13 20:20:40 +0000863 static void
864SFbuttonReleaseList(w, n, event)
865 Widget w;
866 int n;
867 XButtonReleasedEvent *event;
868{
869 SFDir *dir;
870
871 SFbuttonPressed = 0;
872
873 if (SFcurrentInvert[n] != -1)
874 {
875 if (n < 2)
876 SFdoNotTouchDirPtr = 1;
877 SFdoNotTouchVorigin = 1;
878 dir = &(SFdirs[SFdirPtr + n]);
879 SFreplaceText(dir,
880 dir->entries[dir->vOrigin + SFcurrentInvert[n]].shown);
881 SFmotionList(w, n, (XMotionEvent *) event);
882 }
883}
884
885static int SFcheckDir __ARGS((int n, SFDir *dir));
886
887 static int
888SFcheckDir(n, dir)
889 int n;
890 SFDir *dir;
891{
892 struct stat statBuf;
893 int i;
894
895 if ((!mch_stat(".", &statBuf)) && (statBuf.st_mtime != dir->mtime))
896 {
897 /*
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.
901 */
902 if (SFcurrentInvert[n] != -1)
903 {
904 XWarpPointer(
905 SFdisplay,
906 None,
907 XtWindow(selFileLists[n]),
908 0,
909 0,
910 0,
911 0,
912 0,
913 0);
914 }
915
916 for (i = dir->nEntries - 1; i >= 0; i--)
917 {
918 if (dir->entries[i].shown != dir->entries[i].real)
919 XtFree(dir->entries[i].shown);
920 XtFree(dir->entries[i].real);
921 }
922 XtFree((char *) dir->entries);
923 if (SFgetDir(dir))
924 SFunreadableDir(dir);
925 if (dir->vOrigin > dir->nEntries - SFlistSize)
926 dir->vOrigin = dir->nEntries - SFlistSize;
927 if (dir->vOrigin < 0)
928 dir->vOrigin = 0;
929 if (dir->hOrigin > dir->nChars - SFcharsPerEntry)
930 dir->hOrigin = dir->nChars - SFcharsPerEntry;
931 if (dir->hOrigin < 0)
932 dir->hOrigin = 0;
933 dir->beginSelection = -1;
934 dir->endSelection = -1;
935 SFdoNotTouchVorigin = 1;
936 if ((dir + 1)->dir)
937 (void) SFfindFile(dir, (dir + 1)->dir);
938 else
939 (void) SFfindFile(dir, dir->path);
940
941 if (!SFworkProcAdded)
942 {
943 (void) XtAppAddWorkProc(SFapp, (XtWorkProc)SFworkProc, NULL);
944 SFworkProcAdded = 1;
945 }
946 return 1;
947 }
948 return 0;
949}
950
951static int SFcheckFiles __ARGS((SFDir *dir));
952
953 static int
954SFcheckFiles(dir)
955 SFDir *dir;
956{
957 int from, to;
958 int result;
959 char oldc, newc;
960 int i;
961 char *str;
962 int last;
963 struct stat statBuf;
964
965 result = 0;
966
967 from = dir->vOrigin;
968 to = dir->vOrigin + SFlistSize;
969 if (to > dir->nEntries)
970 to = dir->nEntries;
971
972 for (i = from; i < to; i++)
973 {
974 str = dir->entries[i].real;
975 last = strlen(str) - 1;
976 oldc = str[last];
977 str[last] = 0;
978 if (mch_stat(str, &statBuf))
979 newc = ' ';
980 else
981 newc = SFstatChar(&statBuf);
982 str[last] = newc;
983 if (newc != oldc)
984 result = 1;
985 }
986
987 return result;
988}
989
Bram Moolenaar071d4272004-06-13 20:20:40 +0000990 static void
991SFdirModTimer(cl, id)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000992 XtPointer cl UNUSED;
993 XtIntervalId *id UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000994{
995 static int n = -1;
996 static int f = 0;
997 char save;
998 SFDir *dir;
999
1000 if ((!SFtwiddle) && (SFdirPtr < SFdirEnd))
1001 {
1002 n++;
1003 if ((n > 2) || (SFdirPtr + n >= SFdirEnd))
1004 {
1005 n = 0;
1006 f++;
1007 if ((f > 2) || (SFdirPtr + f >= SFdirEnd))
1008 f = 0;
1009 }
1010 dir = &(SFdirs[SFdirPtr + n]);
1011 save = *(dir->path);
1012 *(dir->path) = 0;
1013 if (SFchdir(SFcurrentPath))
1014 {
1015 *(dir->path) = save;
1016
1017 /*
1018 * force a re-read
1019 */
1020 *(dir->dir) = 0;
1021
1022 SFupdatePath();
1023 }
1024 else
1025 {
1026 *(dir->path) = save;
1027 if (SFcheckDir(n, dir) || ((f == n) && SFcheckFiles(dir)))
1028 SFdrawList(n, SF_DO_SCROLL);
1029 }
1030 }
1031
1032 SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
1033 SFdirModTimer, (XtPointer) NULL);
1034}
1035
1036/* Return a single character describing what kind of file STATBUF is. */
1037
1038 static char
1039SFstatChar(statBuf)
1040 struct stat *statBuf;
1041{
1042 if (S_ISDIR (statBuf->st_mode))
1043 return '/';
1044 if (S_ISREG (statBuf->st_mode))
1045 return S_ISXXX (statBuf->st_mode) ? '*' : ' ';
1046#ifdef S_ISSOCK
1047 if (S_ISSOCK (statBuf->st_mode))
1048 return '=';
1049#endif /* S_ISSOCK */
1050 return ' ';
1051}
1052
1053/***************** Draw.c */
1054
1055#ifdef FEAT_GUI_NEXTAW
1056# include <X11/neXtaw/Cardinals.h>
1057#else
1058# include <X11/Xaw/Cardinals.h>
1059#endif
1060
1061#ifdef FEAT_XFONTSET
1062# define SF_DEFAULT_FONT "-misc-fixed-medium-r-normal--14-*"
1063#else
1064# define SF_DEFAULT_FONT "9x15"
1065#endif
1066
1067#ifdef ABS
1068# undef ABS
1069#endif
1070#define ABS(x) (((x) < 0) ? (-(x)) : (x))
1071
1072typedef struct
1073{
1074 char *fontname;
1075} TextData;
1076
1077static GC SFlineGC, SFscrollGC, SFinvertGC, SFtextGC;
1078
1079static XtResource textResources[] =
1080{
1081#ifdef FEAT_XFONTSET
1082 {XtNfontSet, XtCFontSet, XtRString, sizeof (char *),
1083 XtOffsetOf(TextData, fontname), XtRString, SF_DEFAULT_FONT},
1084#else
1085 {XtNfont, XtCFont, XtRString, sizeof (char *),
1086 XtOffsetOf(TextData, fontname), XtRString, SF_DEFAULT_FONT},
1087#endif
1088};
1089
1090#ifdef FEAT_XFONTSET
1091static XFontSet SFfont;
1092#else
1093static XFontStruct *SFfont;
1094#endif
1095
1096static int SFcurrentListY;
1097
1098static XtIntervalId SFscrollTimerId;
1099
1100static void SFinitFont __ARGS((void));
1101
1102 static void
1103SFinitFont()
1104{
1105 TextData *data;
1106#ifdef FEAT_XFONTSET
1107 XFontSetExtents *extents;
1108 char **missing, *def_str;
1109 int num_missing;
1110#endif
1111
1112 data = XtNew(TextData);
1113
1114 XtGetApplicationResources(selFileForm, (XtPointer) data, textResources,
1115 XtNumber(textResources), (Arg *) NULL, ZERO);
1116
1117#ifdef FEAT_XFONTSET
1118 SFfont = XCreateFontSet(SFdisplay, data->fontname,
1119 &missing, &num_missing, &def_str);
1120#else
1121 SFfont = XLoadQueryFont(SFdisplay, data->fontname);
1122#endif
1123 if (!SFfont)
1124 {
1125#ifdef FEAT_XFONTSET
1126 SFfont = XCreateFontSet(SFdisplay, SF_DEFAULT_FONT,
1127 &missing, &num_missing, &def_str);
1128#else
1129 SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT);
1130#endif
1131 if (!SFfont)
1132 {
1133 EMSG2(_("E616: vim_SelFile: can't get font %s"), SF_DEFAULT_FONT);
1134 SFstatus = SEL_FILE_CANCEL;
1135 return;
1136 }
1137 }
1138
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;
1144#else
1145 SFcharWidth = (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2;
1146 SFcharAscent = SFfont->max_bounds.ascent;
1147 SFcharHeight = SFcharAscent + SFfont->max_bounds.descent;
1148#endif
1149}
1150
1151static void SFcreateGC __ARGS((void));
1152
1153 static void
1154SFcreateGC()
1155{
1156 XGCValues gcValues;
1157 XRectangle rectangles[1];
1158
1159 gcValues.foreground = SFfore;
1160
1161 SFlineGC = XtGetGC(
1162 selFileLists[0],
1163 (XtGCMask)GCForeground,
1164 &gcValues);
1165
1166 SFscrollGC = XtGetGC(
1167 selFileLists[0],
1168 (XtGCMask)0,
1169 &gcValues);
1170
1171 gcValues.function = GXxor;
1172 gcValues.foreground = SFfore ^ SFback;
1173 gcValues.background = SFfore ^ SFback;
1174
1175 SFinvertGC = XtGetGC(
1176 selFileLists[0],
1177 (XtGCMask)GCFunction | GCForeground | GCBackground,
1178 &gcValues);
1179
1180 gcValues.foreground = SFfore;
1181 gcValues.background = SFback;
1182#ifndef FEAT_XFONTSET
1183 gcValues.font = SFfont->fid;
1184#endif
1185
1186 SFtextGC = XCreateGC(
1187 SFdisplay,
1188 XtWindow(selFileLists[0]),
1189#ifdef FEAT_XFONTSET
1190 (unsigned long)GCForeground | GCBackground,
1191#else
1192 (unsigned long)GCForeground | GCBackground | GCFont,
1193#endif
1194 &gcValues);
1195
1196 rectangles[0].x = SFlineToTextH + SFbesideText;
1197 rectangles[0].y = 0;
1198 rectangles[0].width = SFcharsPerEntry * SFcharWidth;
1199 rectangles[0].height = SFupperY + 1;
1200
1201 XSetClipRectangles(
1202 SFdisplay,
1203 SFtextGC,
1204 0,
1205 0,
1206 rectangles,
1207 1,
1208 Unsorted);
1209}
1210
1211 static void
1212SFclearList(n, doScroll)
1213 int n;
1214 int doScroll;
1215{
1216 SFDir *dir;
1217
1218 SFcurrentInvert[n] = -1;
1219
1220 XClearWindow(SFdisplay, XtWindow(selFileLists[n]));
1221
1222 XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs, 2);
1223
1224 if (doScroll)
1225 {
1226 dir = &(SFdirs[SFdirPtr + n]);
1227
1228 if ((SFdirPtr + n < SFdirEnd) && dir->nEntries && dir->nChars)
1229 {
1230#ifdef FEAT_GUI_NEXTAW
1231 XawScrollbarSetThumb(
1232 selFileVScrolls[n],
1233 (float) (((double) dir->vOrigin) /
1234 dir->nEntries),
1235 (float) (((double) ((dir->nEntries < SFlistSize)
1236 ? dir->nEntries : SFlistSize)) /
1237 dir->nEntries));
1238#else
1239 vim_XawScrollbarSetThumb(
1240 selFileVScrolls[n],
1241 (float) (((double) dir->vOrigin) /
1242 dir->nEntries),
1243 (float) (((double) ((dir->nEntries < SFlistSize)
1244 ? dir->nEntries : SFlistSize)) /
1245 dir->nEntries),
1246 (double)dir->nEntries);
1247#endif
1248
1249#ifdef FEAT_GUI_NEXTAW
1250 XawScrollbarSetThumb(
1251 selFileHScrolls[n],
1252 (float) (((double) dir->hOrigin) / dir->nChars),
1253 (float) (((double) ((dir->nChars <
1254 SFcharsPerEntry) ? dir->nChars :
1255 SFcharsPerEntry)) / dir->nChars));
1256#else
1257 vim_XawScrollbarSetThumb(
1258 selFileHScrolls[n],
1259 (float) (((double) dir->hOrigin) / dir->nChars),
1260 (float) (((double) ((dir->nChars <
1261 SFcharsPerEntry) ? dir->nChars :
1262 SFcharsPerEntry)) / dir->nChars),
1263 (double)dir->nChars);
1264#endif
1265 }
1266 else
1267 {
1268#ifdef FEAT_GUI_NEXTAW
1269 XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
1270 (float) 1.0);
1271#else
1272 vim_XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
1273 (float) 1.0, 1.0);
1274#endif
1275#ifdef FEAT_GUI_NEXTAW
1276 XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
1277 (float) 1.0);
1278#else
1279 vim_XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
1280 (float) 1.0, 1.0);
1281#endif
1282 }
1283 }
1284}
1285
1286static void SFdeleteEntry __ARGS((SFDir *dir, SFEntry *entry));
1287
1288 static void
1289SFdeleteEntry(dir, entry)
1290 SFDir *dir;
1291 SFEntry *entry;
1292{
1293 SFEntry *e;
1294 SFEntry *end;
1295 int n;
1296 int idx;
1297
1298 idx = entry - dir->entries;
1299
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;
1306
1307 if (idx < dir->vOrigin)
1308 dir->vOrigin--;
1309
1310 XtFree(entry->real);
1311
1312 end = &(dir->entries[dir->nEntries - 1]);
1313
1314 for (e = entry; e < end; e++)
1315 *e = *(e + 1);
1316
1317 if (!(--dir->nEntries))
1318 return;
1319
1320 n = dir - &(SFdirs[SFdirPtr]);
1321 if ((n < 0) || (n > 2))
1322 return;
1323
1324#ifdef FEAT_GUI_NEXTAW
1325 XawScrollbarSetThumb(
1326 selFileVScrolls[n],
1327 (float) (((double) dir->vOrigin) / dir->nEntries),
1328 (float) (((double) ((dir->nEntries < SFlistSize) ?
1329 dir->nEntries : SFlistSize)) / dir->nEntries));
1330#else
1331 vim_XawScrollbarSetThumb(
1332 selFileVScrolls[n],
1333 (float) (((double) dir->vOrigin) / dir->nEntries),
1334 (float) (((double) ((dir->nEntries < SFlistSize) ?
1335 dir->nEntries : SFlistSize)) / dir->nEntries),
1336 (double)dir->nEntries);
1337#endif
1338}
1339
1340static void SFwriteStatChar __ARGS((char *name, int last, struct stat *statBuf));
1341
1342 static void
1343SFwriteStatChar(name, last, statBuf)
1344 char *name;
1345 int last;
1346 struct stat *statBuf;
1347{
1348 name[last] = SFstatChar(statBuf);
1349}
1350
1351static int SFstatAndCheck __ARGS((SFDir *dir, SFEntry *entry));
1352
1353 static int
1354SFstatAndCheck(dir, entry)
1355 SFDir *dir;
1356 SFEntry *entry;
1357{
1358 struct stat statBuf;
1359 char save;
1360 int last;
1361
1362 /*
1363 * must be restored before returning
1364 */
1365 save = *(dir->path);
1366 *(dir->path) = 0;
1367
1368 if (!SFchdir(SFcurrentPath))
1369 {
1370 last = strlen(entry->real) - 1;
1371 entry->real[last] = 0;
1372 entry->statDone = 1;
1373 if ((!mch_stat(entry->real, &statBuf))
1374#ifdef S_IFLNK
1375 || (!mch_lstat(entry->real, &statBuf))
1376#endif
1377 )
1378 {
1379 if (SFfunc)
1380 {
1381 char *shown;
1382
1383 shown = NULL;
1384 if (SFfunc(entry->real, &shown, &statBuf))
1385 {
1386 if (shown)
1387 {
1388 int len;
1389
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;
1395 }
1396 }
1397 else
1398 {
1399 SFdeleteEntry(dir, entry);
1400
1401 *(dir->path) = save;
1402 return 1;
1403 }
1404 }
1405 SFwriteStatChar(entry->real, last, &statBuf);
1406 }
1407 else
1408 entry->real[last] = ' ';
1409 }
1410
1411 *(dir->path) = save;
1412 return 0;
1413}
1414
1415
1416 static void
1417SFdrawStrings(w, dir, from, to)
1418 Window w;
1419 SFDir *dir;
1420 int from;
1421 int to;
1422{
1423 int i;
1424 SFEntry *entry;
1425 int x;
1426
1427 x = SFtextX - dir->hOrigin * SFcharWidth;
1428
1429 if (dir->vOrigin + to >= dir->nEntries)
1430 to = dir->nEntries - dir->vOrigin - 1;
1431 for (i = from; i <= to; i++)
1432 {
1433 entry = &(dir->entries[dir->vOrigin + i]);
1434 if (!(entry->statDone))
1435 {
1436 if (SFstatAndCheck(dir, entry))
1437 {
1438 if (dir->vOrigin + to >= dir->nEntries)
1439 to = dir->nEntries - dir->vOrigin - 1;
1440 i--;
1441 continue;
1442 }
1443 }
1444#ifdef FEAT_XFONTSET
1445 XmbDrawImageString(
1446 SFdisplay,
1447 w,
1448 SFfont,
1449 SFtextGC,
1450 x,
1451 SFtextYoffset + i * SFentryHeight,
1452 entry->shown,
1453 strlen(entry->shown));
1454#else
1455 XDrawImageString(
1456 SFdisplay,
1457 w,
1458 SFtextGC,
1459 x,
1460 SFtextYoffset + i * SFentryHeight,
1461 entry->shown,
1462 strlen(entry->shown));
1463#endif
1464 if (dir->vOrigin + i == dir->beginSelection)
1465 {
1466 XDrawLine(
1467 SFdisplay,
1468 w,
1469 SFlineGC,
1470 SFlineToTextH + 1,
1471 SFlowerY + i * SFentryHeight,
1472 SFlineToTextH + SFentryWidth - 2,
1473 SFlowerY + i * SFentryHeight);
1474 }
1475 if ((dir->vOrigin + i >= dir->beginSelection) &&
1476 (dir->vOrigin + i <= dir->endSelection))
1477 {
1478 SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 =
1479 SFlowerY + i * SFentryHeight;
1480 SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 =
1481 SFlowerY + (i + 1) * SFentryHeight - 1;
1482 XDrawSegments(
1483 SFdisplay,
1484 w,
1485 SFlineGC,
1486 SFcompletionSegs,
1487 2);
1488 }
1489 if (dir->vOrigin + i == dir->endSelection)
1490 {
1491 XDrawLine(
1492 SFdisplay,
1493 w,
1494 SFlineGC,
1495 SFlineToTextH + 1,
1496 SFlowerY + (i + 1) * SFentryHeight - 1,
1497 SFlineToTextH + SFentryWidth - 2,
1498 SFlowerY + (i + 1) * SFentryHeight - 1);
1499 }
1500 }
1501}
1502
1503 static void
1504SFdrawList(n, doScroll)
1505 int n;
1506 int doScroll;
1507{
1508 SFDir *dir;
1509 Window w;
1510
1511 SFclearList(n, doScroll);
1512
1513 if (SFdirPtr + n < SFdirEnd)
1514 {
1515 dir = &(SFdirs[SFdirPtr + n]);
1516 w = XtWindow(selFileLists[n]);
1517#ifdef FEAT_XFONTSET
1518 XmbDrawImageString(
1519 SFdisplay,
1520 w,
1521 SFfont,
1522 SFtextGC,
1523 SFtextX - dir->hOrigin * SFcharWidth,
1524 SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
1525 dir->dir,
1526 strlen(dir->dir));
1527#else
1528 XDrawImageString(
1529 SFdisplay,
1530 w,
1531 SFtextGC,
1532 SFtextX - dir->hOrigin * SFcharWidth,
1533 SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
1534 dir->dir,
1535 strlen(dir->dir));
1536#endif
1537 SFdrawStrings(w, dir, 0, SFlistSize - 1);
1538 }
1539}
1540
1541 static void
1542SFdrawLists(doScroll)
1543 int doScroll;
1544{
1545 int i;
1546
1547 for (i = 0; i < 3; i++)
1548 SFdrawList(i, doScroll);
1549}
1550
1551 static void
1552SFinvertEntry(n)
1553 int n;
1554{
1555 XFillRectangle(
1556 SFdisplay,
1557 XtWindow(selFileLists[n]),
1558 SFinvertGC,
1559 SFlineToTextH,
1560 SFcurrentInvert[n] * SFentryHeight + SFlowerY,
1561 SFentryWidth,
1562 SFentryHeight);
1563}
1564
1565static unsigned long SFscrollTimerInterval __ARGS((void));
1566
1567 static unsigned long
1568SFscrollTimerInterval()
1569{
1570 static int maxVal = 200;
1571 static int varyDist = 50;
1572 static int minDist = 50;
1573 int t;
1574 int dist;
1575
1576 if (SFcurrentListY < SFlowerY)
1577 dist = SFlowerY - SFcurrentListY;
1578 else if (SFcurrentListY > SFupperY)
1579 dist = SFcurrentListY - SFupperY;
1580 else
1581 return (unsigned long) 1;
1582
1583 t = maxVal - ((maxVal / varyDist) * (dist - minDist));
1584
1585 if (t < 1)
1586 t = 1;
1587
1588 if (t > maxVal)
1589 t = maxVal;
1590
1591 return (unsigned long)t;
1592}
1593
1594static void SFscrollTimer __ARGS((XtPointer p, XtIntervalId *id));
1595
Bram Moolenaar071d4272004-06-13 20:20:40 +00001596 static void
1597SFscrollTimer(p, id)
1598 XtPointer p;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00001599 XtIntervalId *id UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001600{
1601 SFDir *dir;
1602 int save;
1603 int n;
1604
1605 n = (long)p;
1606
1607 dir = &(SFdirs[SFdirPtr + n]);
1608 save = dir->vOrigin;
1609
1610 if (SFcurrentListY < SFlowerY)
1611 {
1612 if (dir->vOrigin > 0)
1613 SFvSliderMovedCallback(selFileVScrolls[n], n, dir->vOrigin - 1);
1614 }
1615 else if (SFcurrentListY > SFupperY)
1616 {
1617 if (dir->vOrigin < dir->nEntries - SFlistSize)
1618 SFvSliderMovedCallback(selFileVScrolls[n], n, dir->vOrigin + 1);
1619 }
1620
1621 if (dir->vOrigin != save)
1622 {
1623 if (dir->nEntries)
1624 {
1625#ifdef FEAT_GUI_NEXTAW
1626 XawScrollbarSetThumb(
1627 selFileVScrolls[n],
1628 (float) (((double) dir->vOrigin) / dir->nEntries),
1629 (float) (((double) ((dir->nEntries < SFlistSize) ?
1630 dir->nEntries : SFlistSize)) / dir->nEntries));
1631#else
1632 vim_XawScrollbarSetThumb(
1633 selFileVScrolls[n],
1634 (float) (((double) dir->vOrigin) / dir->nEntries),
1635 (float) (((double) ((dir->nEntries < SFlistSize) ?
1636 dir->nEntries : SFlistSize)) / dir->nEntries),
1637 (double)dir->nEntries);
1638#endif
1639 }
1640 }
1641
1642 if (SFbuttonPressed)
1643 SFscrollTimerId = XtAppAddTimeOut(SFapp,
1644 SFscrollTimerInterval(), SFscrollTimer, (XtPointer) n);
1645}
1646
1647 static int
1648SFnewInvertEntry(n, event)
1649 int n;
1650 XMotionEvent *event;
1651{
1652 int x, y;
1653 int nw;
1654 static int SFscrollTimerAdded = 0;
1655
1656 x = event->x;
1657 y = event->y;
1658
1659 if (SFdirPtr + n >= SFdirEnd)
1660 return -1;
1661
1662 if ((x >= 0) && (x <= SFupperX) && (y >= SFlowerY) && (y <= SFupperY))
1663 {
1664 SFDir *dir = &(SFdirs[SFdirPtr + n]);
1665
1666 if (SFscrollTimerAdded)
1667 {
1668 SFscrollTimerAdded = 0;
1669 XtRemoveTimeOut(SFscrollTimerId);
1670 }
1671
1672 nw = (y - SFlowerY) / SFentryHeight;
1673 if (dir->vOrigin + nw >= dir->nEntries)
1674 return -1;
1675 return nw;
1676 }
1677 else
1678 {
1679 if (SFbuttonPressed)
1680 {
1681 SFcurrentListY = y;
1682 if (!SFscrollTimerAdded)
1683 {
1684 SFscrollTimerAdded = 1;
1685 SFscrollTimerId = XtAppAddTimeOut(SFapp,
1686 SFscrollTimerInterval(), SFscrollTimer,
1687 (XtPointer) n);
1688 }
1689 }
1690 return -1;
1691 }
1692}
1693
Bram Moolenaar071d4272004-06-13 20:20:40 +00001694 static void
1695SFenterList(w, n, event)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00001696 Widget w UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001697 int n;
1698 XEnterWindowEvent *event;
1699{
1700 int nw;
1701
1702 /* sanity */
1703 if (SFcurrentInvert[n] != -1)
1704 {
1705 SFinvertEntry(n);
1706 SFcurrentInvert[n] = -1;
1707 }
1708
1709 nw = SFnewInvertEntry(n, (XMotionEvent *) event);
1710 if (nw != -1)
1711 {
1712 SFcurrentInvert[n] = nw;
1713 SFinvertEntry(n);
1714 }
1715}
1716
Bram Moolenaar071d4272004-06-13 20:20:40 +00001717 static void
1718SFleaveList(w, n, event)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00001719 Widget w UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001720 int n;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00001721 XEvent *event UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001722{
1723 if (SFcurrentInvert[n] != -1)
1724 {
1725 SFinvertEntry(n);
1726 SFcurrentInvert[n] = -1;
1727 }
1728}
1729
Bram Moolenaar071d4272004-06-13 20:20:40 +00001730 static void
1731SFmotionList(w, n, event)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00001732 Widget w UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001733 int n;
1734 XMotionEvent *event;
1735{
1736 int nw;
1737
1738 nw = SFnewInvertEntry(n, event);
1739
1740 if (nw != SFcurrentInvert[n])
1741 {
1742 if (SFcurrentInvert[n] != -1)
1743 SFinvertEntry(n);
1744 SFcurrentInvert[n] = nw;
1745 if (nw != -1)
1746 SFinvertEntry(n);
1747 }
1748}
1749
Bram Moolenaar071d4272004-06-13 20:20:40 +00001750 static void
1751SFvFloatSliderMovedCallback(w, n, fnew)
1752 Widget w;
1753 XtPointer n;
1754 XtPointer fnew;
1755{
1756 int nw;
1757
1758 nw = (*(float *)fnew) * SFdirs[SFdirPtr + (int)(long)n].nEntries;
1759 SFvSliderMovedCallback(w, (int)(long)n, nw);
1760}
1761
Bram Moolenaar071d4272004-06-13 20:20:40 +00001762 static void
1763SFvSliderMovedCallback(w, n, nw)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00001764 Widget w UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001765 int n;
1766 int nw;
1767{
1768 int old;
1769 Window win;
1770 SFDir *dir;
1771
1772 dir = &(SFdirs[SFdirPtr + n]);
1773
1774 old = dir->vOrigin;
1775 dir->vOrigin = nw;
1776
1777 if (old == nw)
1778 return;
1779
1780 win = XtWindow(selFileLists[n]);
1781
1782 if (ABS(nw - old) < SFlistSize)
1783 {
1784 if (nw > old)
1785 {
1786 XCopyArea(
1787 SFdisplay,
1788 win,
1789 win,
1790 SFscrollGC,
1791 SFlineToTextH,
1792 SFlowerY + (nw - old) * SFentryHeight,
1793 SFentryWidth + SFlineToTextH,
1794 (SFlistSize - (nw - old)) * SFentryHeight,
1795 SFlineToTextH,
1796 SFlowerY);
1797 XClearArea(
1798 SFdisplay,
1799 win,
1800 SFlineToTextH,
1801 SFlowerY + (SFlistSize - (nw - old)) *
1802 SFentryHeight,
1803 SFentryWidth + SFlineToTextH,
1804 (nw - old) * SFentryHeight,
1805 False);
1806 SFdrawStrings(win, dir, SFlistSize - (nw - old),
1807 SFlistSize - 1);
1808 }
1809 else
1810 {
1811 XCopyArea(
1812 SFdisplay,
1813 win,
1814 win,
1815 SFscrollGC,
1816 SFlineToTextH,
1817 SFlowerY,
1818 SFentryWidth + SFlineToTextH,
1819 (SFlistSize - (old - nw)) * SFentryHeight,
1820 SFlineToTextH,
1821 SFlowerY + (old - nw) * SFentryHeight);
1822 XClearArea(
1823 SFdisplay,
1824 win,
1825 SFlineToTextH,
1826 SFlowerY,
1827 SFentryWidth + SFlineToTextH,
1828 (old - nw) * SFentryHeight,
1829 False);
1830 SFdrawStrings(win, dir, 0, old - nw);
1831 }
1832 }
1833 else
1834 {
1835 XClearArea(
1836 SFdisplay,
1837 win,
1838 SFlineToTextH,
1839 SFlowerY,
1840 SFentryWidth + SFlineToTextH,
1841 SFlistSize * SFentryHeight,
1842 False);
1843 SFdrawStrings(win, dir, 0, SFlistSize - 1);
1844 }
1845}
1846
Bram Moolenaar071d4272004-06-13 20:20:40 +00001847 static void
1848SFvAreaSelectedCallback(w, n, pnew)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00001849 Widget w;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001850 XtPointer n;
1851 XtPointer pnew;
1852{
1853 SFDir *dir;
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001854 int nw = (int)(long)pnew;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001855
1856 dir = &(SFdirs[SFdirPtr + (int)(long)n]);
1857
1858#ifdef FEAT_GUI_NEXTAW
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001859 if (nw < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001860 {
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001861 if (nw > -SFvScrollHeight)
1862 nw = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001863 else
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001864 nw = -SFlistSize;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001865 }
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001866 else if (nw > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001867 {
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001868 if (nw < SFvScrollHeight)
1869 nw = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001870 else
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001871 nw = SFlistSize;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001872 }
1873#endif
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001874 nw += dir->vOrigin;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001875
1876 if (nw > dir->nEntries - SFlistSize)
1877 nw = dir->nEntries - SFlistSize;
1878
1879 if (nw < 0)
1880 nw = 0;
1881
1882 if (dir->nEntries)
1883 {
1884 float f;
1885
1886 f = ((double) nw) / dir->nEntries;
1887
1888#ifdef FEAT_GUI_NEXTAW
1889 XawScrollbarSetThumb(
1890 w,
1891 f,
1892 (float) (((double) ((dir->nEntries < SFlistSize) ?
1893 dir->nEntries : SFlistSize)) / dir->nEntries));
1894#else
1895 vim_XawScrollbarSetThumb(
1896 w,
1897 f,
1898 (float) (((double) ((dir->nEntries < SFlistSize) ?
1899 dir->nEntries : SFlistSize)) / dir->nEntries),
1900 (double)dir->nEntries);
1901#endif
1902 }
1903
1904 SFvSliderMovedCallback(w, (int)(long)n, nw);
1905}
1906
Bram Moolenaar071d4272004-06-13 20:20:40 +00001907 static void
1908SFhSliderMovedCallback(w, n, nw)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00001909 Widget w UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001910 XtPointer n;
1911 XtPointer nw;
1912{
1913 SFDir *dir;
1914 int save;
1915
1916 dir = &(SFdirs[SFdirPtr + (int)(long)n]);
1917 save = dir->hOrigin;
1918 dir->hOrigin = (*(float *)nw) * dir->nChars;
1919 if (dir->hOrigin == save)
1920 return;
1921
1922 SFdrawList((int)(long)n, SF_DO_NOT_SCROLL);
1923}
1924
Bram Moolenaar071d4272004-06-13 20:20:40 +00001925 static void
1926SFhAreaSelectedCallback(w, n, pnew)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00001927 Widget w;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001928 XtPointer n;
1929 XtPointer pnew;
1930{
1931 SFDir *dir;
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001932 int nw = (int)(long)pnew;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001933
1934 dir = &(SFdirs[SFdirPtr + (int)(long)n]);
1935
1936#ifdef FEAT_GUI_NEXTAW
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001937 if (nw < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001938 {
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001939 if (nw > -SFhScrollWidth)
1940 nw = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001941 else
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001942 nw = -SFcharsPerEntry;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001943 }
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001944 else if (nw > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001945 {
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001946 if (nw < SFhScrollWidth)
1947 nw = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001948 else
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001949 nw = SFcharsPerEntry;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001950 }
1951#endif
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001952 nw += dir->hOrigin;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001953
1954 if (nw > dir->nChars - SFcharsPerEntry)
1955 nw = dir->nChars - SFcharsPerEntry;
1956
1957 if (nw < 0)
1958 nw = 0;
1959
1960 if (dir->nChars)
1961 {
1962 float f;
1963
1964 f = ((double) nw) / dir->nChars;
1965
1966#ifdef FEAT_GUI_NEXTAW
1967 XawScrollbarSetThumb(
1968 w,
1969 f,
1970 (float) (((double) ((dir->nChars < SFcharsPerEntry) ?
1971 dir->nChars : SFcharsPerEntry)) / dir->nChars));
1972#else
1973 vim_XawScrollbarSetThumb(
1974 w,
1975 f,
1976 (float) (((double) ((dir->nChars < SFcharsPerEntry) ?
1977 dir->nChars : SFcharsPerEntry)) / dir->nChars),
1978 (double)dir->nChars);
1979#endif
1980
1981 SFhSliderMovedCallback(w, n, (XtPointer)&f);
1982 }
1983}
1984
Bram Moolenaar071d4272004-06-13 20:20:40 +00001985 static void
1986SFpathSliderMovedCallback(w, client_data, nw)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00001987 Widget w UNUSED;
1988 XtPointer client_data UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001989 XtPointer nw;
1990{
1991 SFDir *dir;
1992 int n;
1993 XawTextPosition pos;
1994 int SFdirPtrSave;
1995
1996 SFdirPtrSave = SFdirPtr;
1997 SFdirPtr = (*(float *)nw) * SFdirEnd;
1998 if (SFdirPtr == SFdirPtrSave)
1999 return;
2000
2001 SFdrawLists(SF_DO_SCROLL);
2002
2003 n = 2;
2004 while (SFdirPtr + n >= SFdirEnd)
2005 n--;
2006
2007 dir = &(SFdirs[SFdirPtr + n]);
2008
2009 pos = dir->path - SFcurrentPath;
2010
2011 if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir)))
2012 {
2013 pos -= strlen(SFstartDir);
2014 if (pos < 0)
2015 pos = 0;
2016 }
2017
2018 XawTextSetInsertionPoint(selFileField, pos);
2019}
2020
Bram Moolenaar071d4272004-06-13 20:20:40 +00002021 static void
2022SFpathAreaSelectedCallback(w, client_data, pnew)
2023 Widget w;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002024 XtPointer client_data UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002025 XtPointer pnew;
2026{
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00002027 int nw = (int)(long)pnew;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002028 float f;
2029
2030#ifdef FEAT_GUI_NEXTAW
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00002031 if (nw < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002032 {
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00002033 if (nw > -SFpathScrollWidth)
2034 nw = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002035 else
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00002036 nw = -3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002037 }
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00002038 else if (nw > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002039 {
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00002040 if (nw < SFpathScrollWidth)
2041 nw = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002042 else
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00002043 nw = 3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002044 }
2045#endif
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00002046 nw += SFdirPtr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002047
2048 if (nw > SFdirEnd - 3)
2049 nw = SFdirEnd - 3;
2050
2051 if (nw < 0)
2052 nw = 0;
2053
2054 f = ((double) nw) / SFdirEnd;
2055
2056#ifdef FEAT_GUI_NEXTAW
2057 XawScrollbarSetThumb(
2058 w,
2059 f,
2060 (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) / SFdirEnd));
2061#else
2062 vim_XawScrollbarSetThumb(
2063 w,
2064 f,
2065 (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) / SFdirEnd),
2066 (double)SFdirEnd);
2067#endif
2068
2069 SFpathSliderMovedCallback(w, (XtPointer) NULL, (XtPointer)&f);
2070}
2071
2072 static Boolean
2073SFworkProc()
2074{
2075 SFDir *dir;
2076 SFEntry *entry;
2077
2078 for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--)
2079 {
2080 if (!(dir->nEntries))
2081 continue;
2082 for (entry = &(dir->entries[dir->nEntries - 1]);
2083 entry >= dir->entries;
2084 entry--)
2085 {
2086 if (!(entry->statDone))
2087 {
2088 (void)SFstatAndCheck(dir, entry);
2089 return False;
2090 }
2091 }
2092 }
2093
2094 SFworkProcAdded = 0;
2095
2096 return True;
2097}
2098
2099/***************** Dir.c */
2100
2101 static int
2102SFcompareEntries(p, q)
2103 const void *p;
2104 const void *q;
2105{
2106 return strcmp(((SFEntry *)p)->real, ((SFEntry *)q)->real);
2107}
2108
2109 static int
2110SFgetDir(dir)
2111 SFDir *dir;
2112{
2113 SFEntry *result = NULL;
2114 int Alloc = 0;
2115 int i;
2116 DIR *dirp;
2117 struct dirent *dp;
2118 char *str;
2119 int len;
2120 int maxChars;
2121 struct stat statBuf;
2122
2123 maxChars = strlen(dir->dir) - 1;
2124
2125 dir->entries = NULL;
2126 dir->nEntries = 0;
2127 dir->nChars = 0;
2128
2129 result = NULL;
2130 i = 0;
2131
2132 dirp = opendir(".");
2133 if (!dirp)
2134 return 1;
2135
2136 (void)mch_stat(".", &statBuf);
2137 dir->mtime = statBuf.st_mtime;
2138
2139 while ((dp = readdir(dirp)))
2140 {
2141 /* Ignore "." and ".." */
2142 if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
2143 continue;
2144 if (i >= Alloc)
2145 {
2146 Alloc = 2 * (Alloc + 1);
2147 result = (SFEntry *) XtRealloc((char *) result,
2148 (unsigned) (Alloc * sizeof(SFEntry)));
2149 }
2150 result[i].statDone = 0;
2151 str = dp->d_name;
2152 len = strlen(str);
2153 result[i].real = XtMalloc((unsigned) (len + 2));
2154 (void) strcat(strcpy(result[i].real, str), " ");
2155 if (len > maxChars)
2156 maxChars = len;
2157 result[i].shown = result[i].real;
2158 i++;
2159 }
2160
2161 qsort((char *) result, (size_t) i, sizeof(SFEntry), SFcompareEntries);
2162
2163 dir->entries = result;
2164 dir->nEntries = i;
2165 dir->nChars = maxChars + 1;
2166
2167 closedir(dirp);
2168
2169 return 0;
2170}
2171
2172/***************** SFinternal.h */
2173
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>
2182#else
2183#include <X11/Xaw/Form.h>
2184#include <X11/Xaw/Command.h>
2185#include <X11/Xaw/Label.h>
2186#endif
2187
2188static char *oneLineTextEditTranslations = "\
2189 <Key>Return: redraw-display()\n\
2190 Ctrl<Key>M: redraw-display()\n\
2191";
2192
2193static void SFexposeList __ARGS((Widget w, XtPointer n, XEvent *event, Boolean *cont));
2194
Bram Moolenaar071d4272004-06-13 20:20:40 +00002195 static void
2196SFexposeList(w, n, event, cont)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002197 Widget w UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002198 XtPointer n;
2199 XEvent *event;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002200 Boolean *cont UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002201{
2202 if ((event->type == NoExpose) || event->xexpose.count)
2203 return;
2204
2205 SFdrawList((int)(long)n, SF_DO_NOT_SCROLL);
2206}
2207
2208static void SFmodVerifyCallback __ARGS((Widget w, XtPointer client_data, XEvent *event, Boolean *cont));
2209
Bram Moolenaar071d4272004-06-13 20:20:40 +00002210 static void
2211SFmodVerifyCallback(w, client_data, event, cont)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002212 Widget w UNUSED;
2213 XtPointer client_data UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002214 XEvent *event;
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002215 Boolean *cont UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002216{
2217 char buf[2];
2218
2219 if ((XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) &&
2220 ((*buf) == '\r'))
2221 SFstatus = SEL_FILE_OK;
2222 else
2223 SFstatus = SEL_FILE_TEXT;
2224}
2225
2226static void SFokCallback __ARGS((Widget w, XtPointer cl, XtPointer cd));
2227
Bram Moolenaar071d4272004-06-13 20:20:40 +00002228 static void
2229SFokCallback(w, cl, cd)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002230 Widget w UNUSED;
2231 XtPointer cl UNUSED;
2232 XtPointer cd UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002233{
2234 SFstatus = SEL_FILE_OK;
2235}
2236
2237static XtCallbackRec SFokSelect[] =
2238{
2239 { SFokCallback, (XtPointer) NULL },
2240 { NULL, (XtPointer) NULL },
2241};
2242
2243static void SFcancelCallback __ARGS((Widget w, XtPointer cl, XtPointer cd));
2244
Bram Moolenaar071d4272004-06-13 20:20:40 +00002245 static void
2246SFcancelCallback(w, cl, cd)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002247 Widget w UNUSED;
2248 XtPointer cl UNUSED;
2249 XtPointer cd UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002250{
2251 SFstatus = SEL_FILE_CANCEL;
2252}
2253
2254static XtCallbackRec SFcancelSelect[] =
2255{
2256 { SFcancelCallback, (XtPointer) NULL },
2257 { NULL, (XtPointer) NULL },
2258};
2259
2260static void SFdismissAction __ARGS((Widget w, XEvent *event, String *params, Cardinal *num_params));
2261
Bram Moolenaar071d4272004-06-13 20:20:40 +00002262 static void
2263SFdismissAction(w, event, params, num_params)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002264 Widget w UNUSED;
2265 XEvent *event;
2266 String *params UNUSED;
2267 Cardinal *num_params UNUSED;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002268{
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002269 if (event->type == ClientMessage
2270 && (Atom)event->xclient.data.l[0] != SFwmDeleteWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002271 return;
2272
2273 SFstatus = SEL_FILE_CANCEL;
2274}
2275
2276static char *wmDeleteWindowTranslation = "\
2277 <Message>WM_PROTOCOLS: SelFileDismiss()\n\
2278";
2279
2280static XtActionsRec actions[] =
2281{
2282 {"SelFileDismiss", SFdismissAction},
2283};
2284
2285 static void
2286SFsetColors(bg, fg, scroll_bg, scroll_fg)
2287 guicolor_T bg;
2288 guicolor_T fg;
2289 guicolor_T scroll_bg;
2290 guicolor_T scroll_fg;
2291{
2292 if (selFileForm)
2293 {
2294 XtVaSetValues(selFileForm, XtNbackground, bg,
2295 XtNforeground, fg,
2296 XtNborderColor, bg,
2297 NULL);
2298 }
2299 {
2300 int i;
2301
2302 for (i = 0; i < 3; ++i)
2303 {
2304 if (selFileLists[i])
2305 {
2306 XtVaSetValues(selFileLists[i], XtNbackground, bg,
2307 XtNforeground, fg,
2308 XtNborderColor, fg,
2309 NULL);
2310 }
2311 }
2312 }
2313 if (selFileOK)
2314 {
2315 XtVaSetValues(selFileOK, XtNbackground, bg,
2316 XtNforeground, fg,
2317 XtNborderColor, fg,
2318 NULL);
2319 }
2320 if (selFileCancel)
2321 {
2322 XtVaSetValues(selFileCancel, XtNbackground, bg,
2323 XtNforeground, fg,
2324 XtNborderColor, fg,
2325 NULL);
2326 }
2327 if (selFilePrompt)
2328 {
2329 XtVaSetValues(selFilePrompt, XtNbackground, bg,
2330 XtNforeground, fg,
2331 NULL);
2332 }
2333 if (gui.dpy)
2334 {
2335 XSetBackground(gui.dpy, SFtextGC, bg);
2336 XSetForeground(gui.dpy, SFtextGC, fg);
2337 XSetForeground(gui.dpy, SFlineGC, fg);
2338
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);
2342 }
2343 if (selFileHScroll)
2344 {
2345 XtVaSetValues(selFileHScroll, XtNbackground, scroll_bg,
2346 XtNforeground, scroll_fg,
2347 XtNborderColor, fg,
2348 NULL);
2349 }
2350 {
2351 int i;
2352
2353 for (i = 0; i < 3; i++)
2354 {
2355 XtVaSetValues(selFileVScrolls[i], XtNbackground, scroll_bg,
2356 XtNforeground, scroll_fg,
2357 XtNborderColor, fg,
2358 NULL);
2359 XtVaSetValues(selFileHScrolls[i], XtNbackground, scroll_bg,
2360 XtNforeground, scroll_fg,
2361 XtNborderColor, fg,
2362 NULL);
2363 }
2364 }
2365}
2366
2367 static void
2368SFcreateWidgets(toplevel, prompt, ok, cancel)
2369 Widget toplevel;
2370 char *prompt;
2371 char *ok;
2372 char *cancel;
2373{
2374 Cardinal n;
2375 int listWidth, listHeight;
2376 int listSpacing = 10;
2377 int scrollThickness = 15;
2378 int hScrollX, hScrollY;
2379 int vScrollX, vScrollY;
2380
2381 selFile = XtVaAppCreateShell("selFile", "SelFile",
2382 transientShellWidgetClass, SFdisplay,
2383 XtNtransientFor, toplevel,
2384 XtNtitle, prompt,
2385 NULL);
2386
2387 /* Add WM_DELETE_WINDOW protocol */
2388 XtAppAddActions(XtWidgetToApplicationContext(selFile),
2389 actions, XtNumber(actions));
2390 XtOverrideTranslations(selFile,
2391 XtParseTranslationTable(wmDeleteWindowTranslation));
2392
2393 selFileForm = XtVaCreateManagedWidget("selFileForm",
2394 formWidgetClass, selFile,
2395 XtNdefaultDistance, 30,
2396 XtNforeground, SFfore,
2397 XtNbackground, SFback,
2398 XtNborderColor, SFback,
2399 NULL);
2400
2401 selFilePrompt = XtVaCreateManagedWidget("selFilePrompt",
2402 labelWidgetClass, selFileForm,
2403 XtNlabel, prompt,
2404 XtNresizable, True,
2405 XtNtop, XtChainTop,
2406 XtNbottom, XtChainTop,
2407 XtNleft, XtChainLeft,
2408 XtNright, XtChainLeft,
2409 XtNborderWidth, 0,
2410 XtNforeground, SFfore,
2411 XtNbackground, SFback,
2412 NULL);
2413
2414 /*
2415 XtVaGetValues(selFilePrompt,
2416 XtNforeground, &SFfore,
2417 XtNbackground, &SFback,
2418 NULL);
2419 */
2420
2421 SFinitFont();
2422
2423 SFentryWidth = SFbesideText + SFcharsPerEntry * SFcharWidth +
2424 SFbesideText;
2425 SFentryHeight = SFaboveAndBelowText + SFcharHeight +
2426 SFaboveAndBelowText;
2427
2428 listWidth = SFlineToTextH + SFentryWidth + SFlineToTextH + 1 +
2429 scrollThickness;
2430 listHeight = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
2431 SFlineToTextV + SFlistSize * SFentryHeight +
2432 SFlineToTextV + 1 + scrollThickness;
2433
2434 SFpathScrollWidth = 3 * listWidth + 2 * listSpacing + 4;
2435
2436 hScrollX = -1;
2437 hScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
2438 SFlineToTextV + SFlistSize * SFentryHeight +
2439 SFlineToTextV;
2440 SFhScrollWidth = SFlineToTextH + SFentryWidth + SFlineToTextH;
2441
2442 vScrollX = SFlineToTextH + SFentryWidth + SFlineToTextH;
2443 vScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV;
2444 SFvScrollHeight = SFlineToTextV + SFlistSize * SFentryHeight +
2445 SFlineToTextV;
2446
2447 SFupperX = SFlineToTextH + SFentryWidth + SFlineToTextH - 1;
2448 SFlowerY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
2449 SFlineToTextV;
2450 SFupperY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
2451 SFlineToTextV + SFlistSize * SFentryHeight - 1;
2452
2453 SFtextX = SFlineToTextH + SFbesideText;
2454 SFtextYoffset = SFlowerY + SFaboveAndBelowText + SFcharAscent;
2455
2456 SFsegs[0].x1 = 0;
2457 SFsegs[0].y1 = vScrollY;
2458 SFsegs[0].x2 = vScrollX - 1;
2459 SFsegs[0].y2 = vScrollY;
2460 SFsegs[1].x1 = vScrollX;
2461 SFsegs[1].y1 = 0;
2462 SFsegs[1].x2 = vScrollX;
2463 SFsegs[1].y2 = vScrollY - 1;
2464
2465 SFcompletionSegs[0].x1 = SFcompletionSegs[0].x2 = SFlineToTextH;
2466 SFcompletionSegs[1].x1 = SFcompletionSegs[1].x2 =
2467 SFlineToTextH + SFentryWidth - 1;
2468
2469 selFileField = XtVaCreateManagedWidget("selFileField",
2470 asciiTextWidgetClass, selFileForm,
2471 XtNwidth, 3 * listWidth + 2 * listSpacing + 4,
2472 XtNborderColor, SFfore,
2473 XtNfromVert, selFilePrompt,
2474 XtNvertDistance, 10,
2475 XtNresizable, True,
2476 XtNtop, XtChainTop,
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,
2486 NULL);
2487
2488 XtOverrideTranslations(selFileField,
2489 XtParseTranslationTable(oneLineTextEditTranslations));
2490 XtSetKeyboardFocus(selFileForm, selFileField);
2491
2492 selFileHScroll = XtVaCreateManagedWidget("selFileHScroll",
2493#ifdef FEAT_GUI_NEXTAW
2494 scrollbarWidgetClass, selFileForm,
2495#else
2496 vim_scrollbarWidgetClass, selFileForm,
2497#endif
2498 XtNorientation, XtorientHorizontal,
2499 XtNwidth, SFpathScrollWidth,
2500 XtNheight, scrollThickness,
2501 XtNborderColor, SFfore,
2502 XtNfromVert, selFileField,
2503 XtNvertDistance, 30,
2504 XtNtop, XtChainTop,
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
2511 XtNlimitThumb, 1,
2512#endif
2513 NULL);
2514
2515 XtAddCallback(selFileHScroll, XtNjumpProc,
2516 (XtCallbackProc) SFpathSliderMovedCallback, (XtPointer)NULL);
2517 XtAddCallback(selFileHScroll, XtNscrollProc,
2518 (XtCallbackProc) SFpathAreaSelectedCallback, (XtPointer)NULL);
2519
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,
2529 XtNtop, XtChainTop,
2530 XtNbottom, XtChainTop,
2531 XtNleft, XtChainLeft,
2532 XtNright, XtChainLeft,
2533 NULL);
2534
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,
2546 XtNtop, XtChainTop,
2547 XtNbottom, XtChainTop,
2548 XtNleft, XtChainLeft,
2549 XtNright, XtChainLeft,
2550 NULL);
2551
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,
2563 XtNtop, XtChainTop,
2564 XtNbottom, XtChainTop,
2565 XtNleft, XtChainLeft,
2566 XtNright, XtChainLeft,
2567 NULL);
2568
2569 for (n = 0; n < 3; n++)
2570 {
2571 selFileVScrolls[n] = XtVaCreateManagedWidget("selFileVScroll",
2572#ifdef FEAT_GUI_NEXTAW
2573 scrollbarWidgetClass, selFileLists[n],
2574#else
2575 vim_scrollbarWidgetClass, selFileLists[n],
2576#endif
2577 XtNx, vScrollX,
2578 XtNy, vScrollY,
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
2585 XtNlimitThumb, 1,
2586#endif
2587 NULL);
2588
2589 XtAddCallback(selFileVScrolls[n], XtNjumpProc,
2590 (XtCallbackProc)SFvFloatSliderMovedCallback, (XtPointer)n);
2591 XtAddCallback(selFileVScrolls[n], XtNscrollProc,
2592 (XtCallbackProc)SFvAreaSelectedCallback, (XtPointer)n);
2593
2594 selFileHScrolls[n] = XtVaCreateManagedWidget("selFileHScroll",
2595#ifdef FEAT_GUI_NEXTAW
2596 scrollbarWidgetClass, selFileLists[n],
2597#else
2598 vim_scrollbarWidgetClass, selFileLists[n],
2599#endif
2600 XtNorientation, XtorientHorizontal,
2601 XtNx, hScrollX,
2602 XtNy, hScrollY,
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
2609 XtNlimitThumb, 1,
2610#endif
2611 NULL);
2612
2613 XtAddCallback(selFileHScrolls[n], XtNjumpProc,
2614 (XtCallbackProc)SFhSliderMovedCallback, (XtPointer)n);
2615 XtAddCallback(selFileHScrolls[n], XtNscrollProc,
2616 (XtCallbackProc)SFhAreaSelectedCallback, (XtPointer)n);
2617 }
2618
2619 selFileOK = XtVaCreateManagedWidget("selFileOK",
2620 commandWidgetClass, selFileForm,
2621 XtNlabel, ok,
2622 XtNresizable, True,
2623 XtNcallback, SFokSelect,
2624 XtNforeground, SFfore,
2625 XtNbackground, SFback,
2626 XtNborderColor, SFfore,
2627 XtNfromHoriz, selFileLists[0],
2628 XtNfromVert, selFileLists[0],
2629 XtNvertDistance, 30,
2630 XtNtop, XtChainTop,
2631 XtNbottom, XtChainTop,
2632 XtNleft, XtChainLeft,
2633 XtNright, XtChainLeft,
2634 NULL);
2635
2636 selFileCancel = XtVaCreateManagedWidget("selFileCancel",
2637 commandWidgetClass, selFileForm,
2638 XtNlabel, cancel,
2639 XtNresizable, True,
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,
2648 XtNtop, XtChainTop,
2649 XtNbottom, XtChainTop,
2650 XtNleft, XtChainLeft,
2651 XtNright, XtChainLeft,
2652 NULL);
2653
2654 XtSetMappedWhenManaged(selFile, False);
2655 XtRealizeWidget(selFile);
2656
2657 /* Add WM_DELETE_WINDOW protocol */
2658 SFwmDeleteWindow = XInternAtom(SFdisplay, "WM_DELETE_WINDOW", False);
2659 XSetWMProtocols(SFdisplay, XtWindow(selFile), &SFwmDeleteWindow, 1);
2660
2661 SFcreateGC();
2662
2663 for (n = 0; n < 3; n++)
2664 {
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);
2677 }
2678
2679 XtAddEventHandler(selFileField, KeyPressMask, False,
2680 SFmodVerifyCallback, (XtPointer)NULL);
2681
2682 SFapp = XtWidgetToApplicationContext(selFile);
2683}
2684
2685 static void
2686SFtextChanged()
2687{
2688#if defined(FEAT_XFONTSET) && defined(XtNinternational)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002689 if ((unsigned long)_XawTextFormat((TextWidget)selFileField) == XawFmtWide)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002690 {
2691 wchar_t *wcbuf=(wchar_t *)SFtextBuffer;
2692
2693 if ((wcbuf[0] == L'/') || (wcbuf[0] == L'~'))
2694 {
2695 (void) wcstombs(SFcurrentPath, wcbuf, MAXPATHL);
2696 SFtextPos = XawTextGetInsertionPoint(selFileField);
2697 }
2698 else
2699 {
2700 strcpy(SFcurrentPath, SFstartDir);
2701 (void) wcstombs(SFcurrentPath + strlen(SFcurrentPath), wcbuf, MAXPATHL);
2702
2703 SFtextPos = XawTextGetInsertionPoint(selFileField) + strlen(SFstartDir);
2704 }
2705 }
2706 else
2707#endif
2708 if ((SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~'))
2709 {
2710 (void) strcpy(SFcurrentPath, SFtextBuffer);
2711 SFtextPos = XawTextGetInsertionPoint(selFileField);
2712 }
2713 else
2714 {
2715 (void) strcat(strcpy(SFcurrentPath, SFstartDir), SFtextBuffer);
2716
2717 SFtextPos = XawTextGetInsertionPoint(selFileField) + strlen(SFstartDir);
2718 }
2719
2720 if (!SFworkProcAdded)
2721 {
2722 (void) XtAppAddWorkProc(SFapp, (XtWorkProc)SFworkProc, NULL);
2723 SFworkProcAdded = 1;
2724 }
2725
2726 SFupdatePath();
2727}
2728
2729 static char *
2730SFgetText()
2731{
2732#if defined(FEAT_XFONTSET) && defined(XtNinternational)
2733 char *buf;
2734
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002735 if ((unsigned long)_XawTextFormat((TextWidget)selFileField) == XawFmtWide)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002736 {
2737 wchar_t *wcbuf;
2738 int mbslength;
2739
2740 XtVaGetValues(selFileField,
2741 XtNstring, &wcbuf,
2742 NULL);
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);
2749 return buf;
2750 }
2751#endif
2752 return (char *)vim_strsave((char_u *)SFtextBuffer);
2753}
2754
2755 static void
2756SFprepareToReturn()
2757{
2758 SFstatus = SEL_FILE_NULL;
2759 XtRemoveGrab(selFile);
2760 XtUnmapWidget(selFile);
2761 XtRemoveTimeOut(SFdirModTimerId);
2762 if (SFchdir(SFstartDir))
2763 {
2764 EMSG(_("E614: vim_SelFile: can't return to current directory"));
2765 SFstatus = SEL_FILE_CANCEL;
2766 }
2767}
2768
2769 char *
2770vim_SelFile(toplevel, prompt, init_path, show_entry, x, y, fg, bg, scroll_fg, scroll_bg)
2771 Widget toplevel;
2772 char *prompt;
2773 char *init_path;
2774 int (*show_entry)();
2775 int x, y;
2776 guicolor_T fg, bg;
2777 guicolor_T scroll_fg, scroll_bg; /* The "Scrollbar" group colors */
2778{
2779 static int firstTime = 1;
2780 XEvent event;
2781 char *name_return;
2782
2783 if (prompt == NULL)
2784 prompt = _("Pathname:");
2785 SFfore = fg;
2786 SFback = bg;
2787
2788 if (mch_dirname((char_u *)SFstartDir, MAXPATHL) == FAIL)
2789 {
2790 EMSG(_("E615: vim_SelFile: can't get current directory"));
2791 return NULL;
2792 }
2793
2794 if (firstTime)
2795 {
2796 firstTime = 0;
2797 SFdisplay = XtDisplay(toplevel);
2798 SFcreateWidgets(toplevel, prompt, _("OK"), _("Cancel"));
2799 }
2800 else
2801 {
2802 XtVaSetValues(selFilePrompt, XtNlabel, prompt, NULL);
2803 XtVaSetValues(selFile, XtNtitle, prompt, NULL);
2804 SFsetColors(bg, fg, scroll_bg, scroll_fg);
2805 }
2806
2807 XtVaSetValues(selFile, XtNx, x, XtNy, y, NULL);
2808 XtMapWidget(selFile);
2809
2810 (void)strcat(SFstartDir, "/");
2811 (void)strcpy(SFcurrentDir, SFstartDir);
2812
2813 if (init_path)
2814 {
2815 if (init_path[0] == '/')
2816 {
2817 (void)strcpy(SFcurrentPath, init_path);
2818 if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir)))
2819 SFsetText(SFcurrentPath);
2820 else
2821 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
2822 }
2823 else
2824 {
2825 (void)strcat(strcpy(SFcurrentPath, SFstartDir), init_path);
2826 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
2827 }
2828 }
2829 else
2830 (void)strcpy(SFcurrentPath, SFstartDir);
2831
2832 SFfunc = show_entry;
2833
2834 SFtextChanged();
2835
2836 XtAddGrab(selFile, True, True);
2837
2838 SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
2839 SFdirModTimer, (XtPointer) NULL);
2840
Bram Moolenaara466c992005-07-09 21:03:22 +00002841 for (;;)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002842 {
2843 XtAppNextEvent(SFapp, &event);
2844 XtDispatchEvent(&event);
2845 switch (SFstatus)
2846 {
2847 case SEL_FILE_TEXT:
2848 SFstatus = SEL_FILE_NULL;
2849 SFtextChanged();
2850 break;
2851 case SEL_FILE_OK:
2852 name_return = SFgetText();
2853 SFprepareToReturn();
2854 return name_return;
2855 case SEL_FILE_CANCEL:
2856 SFprepareToReturn();
2857 return NULL;
2858 case SEL_FILE_NULL:
2859 break;
2860 }
2861 }
2862}
2863#endif /* FEAT_BROWSE */