blob: e89e853ca8624b393c679bc1be26c7a5a522508b [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
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100175static void SFsetText(char *path);
176static void SFtextChanged(void);
177static char *SFgetText(void);
178static void SFupdatePath(void);
179static int SFgetDir(SFDir *dir);
180static void SFdrawLists(int doScroll);
181static void SFdrawList(int n, int doScroll);
182static void SFclearList(int n, int doScroll);
183static void SFbuttonPressList(Widget w, int n, XButtonPressedEvent *event);
184static void SFbuttonReleaseList(Widget w, int n, XButtonReleasedEvent *event);
185static void SFdirModTimer(XtPointer cl, XtIntervalId *id);
Bram Moolenaar8767f522016-07-01 17:17:39 +0200186static char SFstatChar(stat_T *statBuf);
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100187static void SFdrawStrings(Window w, SFDir *dir, int from, int to);
188static int SFnewInvertEntry(int n, XMotionEvent *event);
189static void SFinvertEntry(int n);
190static void SFenterList(Widget w, int n, XEnterWindowEvent *event);
191static void SFleaveList(Widget w, int n, XEvent *event);
192static void SFmotionList(Widget w, int n, XMotionEvent *event);
193static void SFvFloatSliderMovedCallback(Widget w, XtPointer n, XtPointer fnew);
194static void SFvSliderMovedCallback(Widget w, int n, int nw);
195static void SFvAreaSelectedCallback(Widget w, XtPointer n, XtPointer pnew);
196static void SFhSliderMovedCallback(Widget w, XtPointer n, XtPointer nw);
197static void SFhAreaSelectedCallback(Widget w, XtPointer n, XtPointer pnew);
198static void SFpathSliderMovedCallback(Widget w, XtPointer client_data, XtPointer nw);
199static void SFpathAreaSelectedCallback(Widget w, XtPointer client_data, XtPointer pnew);
200static Boolean SFworkProc(void);
201static int SFcompareEntries(const void *p, const void *q);
202static void SFprepareToReturn(void);
203static void SFcreateWidgets(Widget toplevel, char *prompt, char *ok, char *cancel);
204static void SFsetColors(guicolor_T bg, guicolor_T fg, guicolor_T scroll_bg, guicolor_T scrollfg);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000205
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
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100240static int SFchdir(char *path);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000241
242 static int
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100243SFchdir(char *path)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000244{
245 int result;
246
247 result = 0;
248
249 if (strcmp(path, SFcurrentDir))
250 {
251 result = mch_chdir(path);
252 if (!result)
253 (void) strcpy(SFcurrentDir, path);
254 }
255
256 return result;
257}
258
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100259static void SFfree(int i);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000260
261 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100262SFfree(int i)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000263{
264 SFDir *dir;
265 int j;
266
267 dir = &(SFdirs[i]);
268
269 for (j = dir->nEntries - 1; j >= 0; j--)
270 {
271 if (dir->entries[j].shown != dir->entries[j].real)
272 XtFree(dir->entries[j].shown);
273 XtFree(dir->entries[j].real);
274 }
275
276 XtFree((char *)dir->entries);
277 XtFree(dir->dir);
278
279 dir->dir = NULL;
280}
281
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100282static void SFstrdup(char **s1, char *s2);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000283
284 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100285SFstrdup(char **s1, char *s2)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000286{
287 *s1 = strcpy(XtMalloc((unsigned)(strlen(s2) + 1)), s2);
288}
289
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100290static void SFunreadableDir(SFDir *dir);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000291
292 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100293SFunreadableDir(SFDir *dir)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000294{
295 char *cannotOpen = _("<cannot open> ");
296
297 dir->entries = (SFEntry *) XtMalloc(sizeof(SFEntry));
298 dir->entries[0].statDone = 1;
299 SFstrdup(&dir->entries[0].real, cannotOpen);
300 dir->entries[0].shown = dir->entries[0].real;
301 dir->nEntries = 1;
302 dir->nChars = strlen(cannotOpen);
303}
304
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100305static void SFreplaceText(SFDir *dir, char *str);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000306
307 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100308SFreplaceText(SFDir *dir, char *str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000309{
310 int len;
311
312 *(dir->path) = 0;
313 len = strlen(str);
314 if (str[len - 1] == '/')
315 (void) strcat(SFcurrentPath, str);
316 else
317 (void) strncat(SFcurrentPath, str, len - 1);
318 if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir)))
319 SFsetText(SFcurrentPath);
320 else
321 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
322
323 SFtextChanged();
324}
325
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100326static void SFexpand(char *str);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000327
328 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100329SFexpand(char *str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000330{
331 int len;
332 int cmp;
333 char *name, *growing;
334 SFDir *dir;
335 SFEntry *entry, *max;
336
337 len = strlen(str);
338
339 dir = &(SFdirs[SFdirEnd - 1]);
340
341 if (dir->beginSelection == -1)
342 {
343 SFstrdup(&str, str);
344 SFreplaceText(dir, str);
345 XtFree(str);
346 return;
347 }
348 else if (dir->beginSelection == dir->endSelection)
349 {
350 SFreplaceText(dir, dir->entries[dir->beginSelection].shown);
351 return;
352 }
353
354 max = &(dir->entries[dir->endSelection + 1]);
355
356 name = dir->entries[dir->beginSelection].shown;
357 SFstrdup(&growing, name);
358
359 cmp = 0;
360 while (!cmp)
361 {
362 entry = &(dir->entries[dir->beginSelection]);
363 while (entry < max)
364 {
365 if ((cmp = strncmp(growing, entry->shown, len)))
366 break;
367 entry++;
368 }
369 len++;
370 }
371
372 /*
373 * SFreplaceText() expects filename
374 */
375 growing[len - 2] = ' ';
376
377 growing[len - 1] = 0;
378 SFreplaceText(dir, growing);
379 XtFree(growing);
380}
381
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100382static int SFfindFile(SFDir *dir, char *str);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000383
384 static int
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100385SFfindFile(SFDir *dir, char *str)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000386{
387 int i, last, max;
388 char *name, save;
389 SFEntry *entries;
390 int len;
391 int begin, end;
392 int result;
393
394 len = strlen(str);
395
396 if (str[len - 1] == ' ')
397 {
398 SFexpand(str);
399 return 1;
400 }
401 else if (str[len - 1] == '/')
402 len--;
403
404 max = dir->nEntries;
405
406 entries = dir->entries;
407
408 i = 0;
409 while (i < max)
410 {
411 name = entries[i].shown;
412 last = strlen(name) - 1;
413 save = name[last];
414 name[last] = 0;
415
416 result = strncmp(str, name, len);
417
418 name[last] = save;
419 if (result <= 0)
420 break;
421 i++;
422 }
423 begin = i;
424 while (i < max)
425 {
426 name = entries[i].shown;
427 last = strlen(name) - 1;
428 save = name[last];
429 name[last] = 0;
430
431 result = strncmp(str, name, len);
432
433 name[last] = save;
434 if (result)
435 break;
436 i++;
437 }
438 end = i;
439
440 if (begin != end)
441 {
442 if ((dir->beginSelection != begin) || (dir->endSelection != end - 1))
443 {
444 dir->changed = 1;
445 dir->beginSelection = begin;
446 if (str[strlen(str) - 1] == '/')
447 dir->endSelection = begin;
448 else
449 dir->endSelection = end - 1;
450 }
451 }
452 else if (dir->beginSelection != -1)
453 {
454 dir->changed = 1;
455 dir->beginSelection = -1;
456 dir->endSelection = -1;
457 }
458
459 if (SFdoNotTouchVorigin
460 || ((begin > dir->vOrigin) && (end < dir->vOrigin + SFlistSize)))
461 {
462 SFdoNotTouchVorigin = 0;
463 return 0;
464 }
465
466 i = begin - 1;
467 if (i > max - SFlistSize)
468 i = max - SFlistSize;
469 if (i < 0)
470 i = 0;
471
472 if (dir->vOrigin != i)
473 {
474 dir->vOrigin = i;
475 dir->changed = 1;
476 }
477
478 return 0;
479}
480
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100481static void SFunselect(void);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000482
483 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100484SFunselect(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000485{
486 SFDir *dir;
487
488 dir = &(SFdirs[SFdirEnd - 1]);
489 if (dir->beginSelection != -1)
490 dir->changed = 1;
491 dir->beginSelection = -1;
492 dir->endSelection = -1;
493}
494
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100495static int SFcompareLogins(const void *p, const void *q);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000496
497 static int
Bram Moolenaar02fdaea2016-01-30 18:13:55 +0100498SFcompareLogins(const void *p, const void *q)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000499{
500 return strcmp(((SFLogin *)p)->name, ((SFLogin *)q)->name);
501}
502
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100503static void SFgetHomeDirs(void);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000504
505 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100506SFgetHomeDirs(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000507{
508 struct passwd *pw;
509 int Alloc;
510 int i;
511 SFEntry *entries = NULL;
512 int len;
513 int maxChars;
514
515 Alloc = 1;
516 i = 1;
517 entries = (SFEntry *)XtMalloc(sizeof(SFEntry));
518 SFlogins = (SFLogin *)XtMalloc(sizeof(SFLogin));
519 entries[0].real = XtMalloc(3);
520 (void) strcpy(entries[0].real, "~");
521 entries[0].shown = entries[0].real;
522 entries[0].statDone = 1;
523 SFlogins[0].name = "";
524 pw = getpwuid((int) getuid());
525 SFstrdup(&SFlogins[0].dir, pw ? pw->pw_dir : "/");
526 maxChars = 0;
527
528 (void) setpwent();
529
530 while ((pw = getpwent()) && (*(pw->pw_name)))
531 {
532 if (i >= Alloc)
533 {
534 Alloc *= 2;
535 entries = (SFEntry *) XtRealloc((char *)entries,
536 (unsigned)(Alloc * sizeof(SFEntry)));
537 SFlogins = (SFLogin *) XtRealloc((char *)SFlogins,
538 (unsigned)(Alloc * sizeof(SFLogin)));
539 }
540 len = strlen(pw->pw_name);
541 entries[i].real = XtMalloc((unsigned) (len + 3));
542 (void) strcat(strcpy(entries[i].real, "~"), pw->pw_name);
543 entries[i].shown = entries[i].real;
544 entries[i].statDone = 1;
545 if (len > maxChars)
546 maxChars = len;
547 SFstrdup(&SFlogins[i].name, pw->pw_name);
548 SFstrdup(&SFlogins[i].dir, pw->pw_dir);
549 i++;
550 }
551
552 SFhomeDir.dir = XtMalloc(1);
553 SFhomeDir.dir[0] = 0;
554 SFhomeDir.path = SFcurrentPath;
555 SFhomeDir.entries = entries;
556 SFhomeDir.nEntries = i;
557 SFhomeDir.vOrigin = 0; /* :-) */
558 SFhomeDir.nChars = maxChars + 2;
559 SFhomeDir.hOrigin = 0;
560 SFhomeDir.changed = 1;
561 SFhomeDir.beginSelection = -1;
562 SFhomeDir.endSelection = -1;
563
564 qsort((char *)entries, (size_t)i, sizeof(SFEntry), SFcompareEntries);
565 qsort((char *)SFlogins, (size_t)i, sizeof(SFLogin), SFcompareLogins);
566
567 for (i--; i >= 0; i--)
568 (void)strcat(entries[i].real, "/");
569}
570
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100571static int SFfindHomeDir(char *begin, char *end);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000572
573 static int
Bram Moolenaar02fdaea2016-01-30 18:13:55 +0100574SFfindHomeDir(char *begin, char *end)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000575{
576 char save;
577 char *theRest;
578 int i;
579
580 save = *end;
581 *end = 0;
582
583 for (i = SFhomeDir.nEntries - 1; i >= 0; i--)
584 {
585 if (!strcmp(SFhomeDir.entries[i].real, begin))
586 {
587 *end = save;
588 SFstrdup(&theRest, end);
589 (void) strcat(strcat(strcpy(SFcurrentPath,
590 SFlogins[i].dir), "/"), theRest);
591 XtFree(theRest);
592 SFsetText(SFcurrentPath);
593 SFtextChanged();
594 return 1;
595 }
596 }
597
598 *end = save;
599
600 return 0;
601}
602
603 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100604SFupdatePath(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000605{
606 static int Alloc;
607 static int wasTwiddle = 0;
608 char *begin, *end;
609 int i, j;
610 int prevChange;
611 int SFdirPtrSave, SFdirEndSave;
612 SFDir *dir;
613
614 if (!SFdirs)
615 {
616 SFdirs = (SFDir *) XtMalloc((Alloc = 10) * sizeof(SFDir));
617 dir = &(SFdirs[0]);
618 SFstrdup(&dir->dir, "/");
619 (void) SFchdir("/");
620 (void) SFgetDir(dir);
621 for (j = 1; j < Alloc; j++)
622 SFdirs[j].dir = NULL;
623 dir->path = SFcurrentPath + 1;
624 dir->vOrigin = 0;
625 dir->hOrigin = 0;
626 dir->changed = 1;
627 dir->beginSelection = -1;
628 dir->endSelection = -1;
629 SFhomeDir.dir = NULL;
630 }
631
632 SFdirEndSave = SFdirEnd;
633 SFdirEnd = 1;
634
635 SFdirPtrSave = SFdirPtr;
636 SFdirPtr = 0;
637
638 begin = NULL;
639
640 if (SFcurrentPath[0] == '~')
641 {
642 if (!SFtwiddle)
643 {
644 SFtwiddle = 1;
645 dir = &(SFdirs[0]);
646 SFrootDir = *dir;
647 if (!SFhomeDir.dir)
648 SFgetHomeDirs();
649 *dir = SFhomeDir;
650 dir->changed = 1;
651 }
652 end = SFcurrentPath;
653 SFdoNotTouchDirPtr = 1;
654 wasTwiddle = 1;
655 }
656 else
657 {
658 if (SFtwiddle)
659 {
660 SFtwiddle = 0;
661 dir = &(SFdirs[0]);
662 *dir = SFrootDir;
663 dir->changed = 1;
664 }
665 end = SFcurrentPath + 1;
666 }
667
668 i = 0;
669
670 prevChange = 0;
671
672 while (*end)
673 {
674 while (*end++ == '/')
675 ;
676 end--;
677 begin = end;
678 while ((*end) && (*end++ != '/'))
679 ;
680 if ((end - SFcurrentPath <= SFtextPos) && (*(end - 1) == '/'))
681 {
682 SFdirPtr = i - 1;
683 if (SFdirPtr < 0)
684 SFdirPtr = 0;
685 }
686 if (*begin)
687 {
688 if (*(end - 1) == '/')
689 {
690 char save = *end;
691
692 if (SFtwiddle)
693 {
694 if (SFfindHomeDir(begin, end))
695 return;
696 }
697 *end = 0;
698 i++;
699 SFdirEnd++;
700 if (i >= Alloc)
701 {
702 SFdirs = (SFDir *) XtRealloc((char *) SFdirs,
703 (unsigned)((Alloc *= 2) * sizeof(SFDir)));
704 for (j = Alloc / 2; j < Alloc; j++)
705 SFdirs[j].dir = NULL;
706 }
707 dir = &(SFdirs[i]);
708 if ((!(dir->dir)) || prevChange || strcmp(dir->dir, begin))
709 {
710 if (dir->dir)
711 SFfree(i);
712 prevChange = 1;
713 SFstrdup(&dir->dir, begin);
714 dir->path = end;
715 dir->vOrigin = 0;
716 dir->hOrigin = 0;
717 dir->changed = 1;
718 dir->beginSelection = -1;
719 dir->endSelection = -1;
720 (void)SFfindFile(dir - 1, begin);
721 if (SFchdir(SFcurrentPath) || SFgetDir(dir))
722 {
723 SFunreadableDir(dir);
724 break;
725 }
726 }
727 *end = save;
728 if (!save)
729 SFunselect();
730 }
731 else
732 {
733 if (SFfindFile(&(SFdirs[SFdirEnd-1]), begin))
734 return;
735 }
736 }
737 else
738 SFunselect();
739 }
740
741 if ((end == SFcurrentPath + 1) && (!SFtwiddle))
742 SFunselect();
743
744 for (i = SFdirEnd; i < Alloc; i++)
745 if (SFdirs[i].dir)
746 SFfree(i);
747
748 if (SFdoNotTouchDirPtr)
749 {
750 if (wasTwiddle)
751 {
752 wasTwiddle = 0;
753 SFdirPtr = SFdirEnd - 2;
754 if (SFdirPtr < 0)
755 SFdirPtr = 0;
756 }
757 else
758 SFdirPtr = SFdirPtrSave;
759 SFdoNotTouchDirPtr = 0;
760 }
761
762 if ((SFdirPtr != SFdirPtrSave) || (SFdirEnd != SFdirEndSave))
763 {
764#ifdef FEAT_GUI_NEXTAW
765 XawScrollbarSetThumb( selFileHScroll,
766 (float) (((double) SFdirPtr) / SFdirEnd),
767 (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
768 SFdirEnd));
769#else
770 vim_XawScrollbarSetThumb( selFileHScroll,
771 (float) (((double) SFdirPtr) / SFdirEnd),
772 (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
773 SFdirEnd),
774 (double)SFdirEnd);
775#endif
776 }
777
778 if (SFdirPtr != SFdirPtrSave)
779 SFdrawLists(SF_DO_SCROLL);
780 else
781 for (i = 0; i < 3; i++)
782 {
783 if (SFdirPtr + i < SFdirEnd)
784 {
785 if (SFdirs[SFdirPtr + i].changed)
786 {
787 SFdirs[SFdirPtr + i].changed = 0;
788 SFdrawList(i, SF_DO_SCROLL);
789 }
790 }
791 else
792 SFclearList(i, SF_DO_SCROLL);
793 }
794}
795
796#ifdef XtNinternational
797 static int
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100798WcsLen(wchar_t *p)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000799{
800 int i = 0;
801 while (*p++ != 0)
802 i++;
803 return i;
804}
805#endif
806
807 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100808SFsetText(char *path)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000809{
810 XawTextBlock text;
811
812 text.firstPos = 0;
813 text.length = strlen(path);
814 text.ptr = path;
815 text.format = FMT8BIT;
816
817#ifdef XtNinternational
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +0000818 if ((unsigned long)_XawTextFormat((TextWidget)selFileField) == XawFmtWide)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000819 {
820 XawTextReplace(selFileField, (XawTextPosition)0,
821 (XawTextPosition)WcsLen((wchar_t *)&SFtextBuffer[0]), &text);
822 XawTextSetInsertionPoint(selFileField,
823 (XawTextPosition)WcsLen((wchar_t *)&SFtextBuffer[0]));
824 }
825 else
826 {
827 XawTextReplace(selFileField, (XawTextPosition)0,
828 (XawTextPosition)strlen(SFtextBuffer), &text);
829 XawTextSetInsertionPoint(selFileField,
830 (XawTextPosition)strlen(SFtextBuffer));
831 }
832#else
833 XawTextReplace(selFileField, (XawTextPosition)0,
834 (XawTextPosition)strlen(SFtextBuffer), &text);
835 XawTextSetInsertionPoint(selFileField,
836 (XawTextPosition)strlen(SFtextBuffer));
837#endif
838}
839
Bram Moolenaar071d4272004-06-13 20:20:40 +0000840 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100841SFbuttonPressList(
842 Widget w UNUSED,
843 int n UNUSED,
844 XButtonPressedEvent *event UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000845{
846 SFbuttonPressed = 1;
847}
848
Bram Moolenaar071d4272004-06-13 20:20:40 +0000849 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100850SFbuttonReleaseList(
851 Widget w,
852 int n,
853 XButtonReleasedEvent *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000854{
855 SFDir *dir;
856
857 SFbuttonPressed = 0;
858
859 if (SFcurrentInvert[n] != -1)
860 {
861 if (n < 2)
862 SFdoNotTouchDirPtr = 1;
863 SFdoNotTouchVorigin = 1;
864 dir = &(SFdirs[SFdirPtr + n]);
865 SFreplaceText(dir,
866 dir->entries[dir->vOrigin + SFcurrentInvert[n]].shown);
867 SFmotionList(w, n, (XMotionEvent *) event);
868 }
869}
870
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100871static int SFcheckDir(int n, SFDir *dir);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000872
873 static int
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100874SFcheckDir(int n, SFDir *dir)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000875{
Bram Moolenaar8767f522016-07-01 17:17:39 +0200876 stat_T statBuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000877 int i;
878
879 if ((!mch_stat(".", &statBuf)) && (statBuf.st_mtime != dir->mtime))
880 {
881 /*
882 * If the pointer is currently in the window that we are about
883 * to update, we must warp it to prevent the user from
884 * accidentally selecting the wrong file.
885 */
886 if (SFcurrentInvert[n] != -1)
887 {
888 XWarpPointer(
889 SFdisplay,
890 None,
891 XtWindow(selFileLists[n]),
892 0,
893 0,
894 0,
895 0,
896 0,
897 0);
898 }
899
900 for (i = dir->nEntries - 1; i >= 0; i--)
901 {
902 if (dir->entries[i].shown != dir->entries[i].real)
903 XtFree(dir->entries[i].shown);
904 XtFree(dir->entries[i].real);
905 }
906 XtFree((char *) dir->entries);
907 if (SFgetDir(dir))
908 SFunreadableDir(dir);
909 if (dir->vOrigin > dir->nEntries - SFlistSize)
910 dir->vOrigin = dir->nEntries - SFlistSize;
911 if (dir->vOrigin < 0)
912 dir->vOrigin = 0;
913 if (dir->hOrigin > dir->nChars - SFcharsPerEntry)
914 dir->hOrigin = dir->nChars - SFcharsPerEntry;
915 if (dir->hOrigin < 0)
916 dir->hOrigin = 0;
917 dir->beginSelection = -1;
918 dir->endSelection = -1;
919 SFdoNotTouchVorigin = 1;
920 if ((dir + 1)->dir)
921 (void) SFfindFile(dir, (dir + 1)->dir);
922 else
923 (void) SFfindFile(dir, dir->path);
924
925 if (!SFworkProcAdded)
926 {
927 (void) XtAppAddWorkProc(SFapp, (XtWorkProc)SFworkProc, NULL);
928 SFworkProcAdded = 1;
929 }
930 return 1;
931 }
932 return 0;
933}
934
Bram Moolenaard25c16e2016-01-29 22:13:30 +0100935static int SFcheckFiles(SFDir *dir);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000936
937 static int
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100938SFcheckFiles(SFDir *dir)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000939{
940 int from, to;
941 int result;
942 char oldc, newc;
943 int i;
944 char *str;
945 int last;
Bram Moolenaar8767f522016-07-01 17:17:39 +0200946 stat_T statBuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000947
948 result = 0;
949
950 from = dir->vOrigin;
951 to = dir->vOrigin + SFlistSize;
952 if (to > dir->nEntries)
953 to = dir->nEntries;
954
955 for (i = from; i < to; i++)
956 {
957 str = dir->entries[i].real;
958 last = strlen(str) - 1;
959 oldc = str[last];
960 str[last] = 0;
961 if (mch_stat(str, &statBuf))
962 newc = ' ';
963 else
964 newc = SFstatChar(&statBuf);
965 str[last] = newc;
966 if (newc != oldc)
967 result = 1;
968 }
969
970 return result;
971}
972
Bram Moolenaar071d4272004-06-13 20:20:40 +0000973 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +0100974SFdirModTimer(XtPointer cl UNUSED, XtIntervalId *id UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000975{
976 static int n = -1;
977 static int f = 0;
978 char save;
979 SFDir *dir;
980
981 if ((!SFtwiddle) && (SFdirPtr < SFdirEnd))
982 {
983 n++;
984 if ((n > 2) || (SFdirPtr + n >= SFdirEnd))
985 {
986 n = 0;
987 f++;
988 if ((f > 2) || (SFdirPtr + f >= SFdirEnd))
989 f = 0;
990 }
991 dir = &(SFdirs[SFdirPtr + n]);
992 save = *(dir->path);
993 *(dir->path) = 0;
994 if (SFchdir(SFcurrentPath))
995 {
996 *(dir->path) = save;
997
998 /*
999 * force a re-read
1000 */
1001 *(dir->dir) = 0;
1002
1003 SFupdatePath();
1004 }
1005 else
1006 {
1007 *(dir->path) = save;
1008 if (SFcheckDir(n, dir) || ((f == n) && SFcheckFiles(dir)))
1009 SFdrawList(n, SF_DO_SCROLL);
1010 }
1011 }
1012
1013 SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
1014 SFdirModTimer, (XtPointer) NULL);
1015}
1016
1017/* Return a single character describing what kind of file STATBUF is. */
1018
1019 static char
Bram Moolenaar8767f522016-07-01 17:17:39 +02001020SFstatChar(stat_T *statBuf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001021{
1022 if (S_ISDIR (statBuf->st_mode))
1023 return '/';
1024 if (S_ISREG (statBuf->st_mode))
1025 return S_ISXXX (statBuf->st_mode) ? '*' : ' ';
1026#ifdef S_ISSOCK
1027 if (S_ISSOCK (statBuf->st_mode))
1028 return '=';
1029#endif /* S_ISSOCK */
1030 return ' ';
1031}
1032
1033/***************** Draw.c */
1034
1035#ifdef FEAT_GUI_NEXTAW
1036# include <X11/neXtaw/Cardinals.h>
1037#else
1038# include <X11/Xaw/Cardinals.h>
1039#endif
1040
1041#ifdef FEAT_XFONTSET
1042# define SF_DEFAULT_FONT "-misc-fixed-medium-r-normal--14-*"
1043#else
1044# define SF_DEFAULT_FONT "9x15"
1045#endif
1046
1047#ifdef ABS
1048# undef ABS
1049#endif
1050#define ABS(x) (((x) < 0) ? (-(x)) : (x))
1051
1052typedef struct
1053{
1054 char *fontname;
1055} TextData;
1056
1057static GC SFlineGC, SFscrollGC, SFinvertGC, SFtextGC;
1058
1059static XtResource textResources[] =
1060{
1061#ifdef FEAT_XFONTSET
1062 {XtNfontSet, XtCFontSet, XtRString, sizeof (char *),
1063 XtOffsetOf(TextData, fontname), XtRString, SF_DEFAULT_FONT},
1064#else
1065 {XtNfont, XtCFont, XtRString, sizeof (char *),
1066 XtOffsetOf(TextData, fontname), XtRString, SF_DEFAULT_FONT},
1067#endif
1068};
1069
1070#ifdef FEAT_XFONTSET
1071static XFontSet SFfont;
1072#else
1073static XFontStruct *SFfont;
1074#endif
1075
1076static int SFcurrentListY;
1077
1078static XtIntervalId SFscrollTimerId;
1079
Bram Moolenaard25c16e2016-01-29 22:13:30 +01001080static void SFinitFont(void);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001081
1082 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001083SFinitFont(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001084{
1085 TextData *data;
1086#ifdef FEAT_XFONTSET
1087 XFontSetExtents *extents;
1088 char **missing, *def_str;
1089 int num_missing;
1090#endif
1091
1092 data = XtNew(TextData);
1093
1094 XtGetApplicationResources(selFileForm, (XtPointer) data, textResources,
1095 XtNumber(textResources), (Arg *) NULL, ZERO);
1096
1097#ifdef FEAT_XFONTSET
1098 SFfont = XCreateFontSet(SFdisplay, data->fontname,
1099 &missing, &num_missing, &def_str);
1100#else
1101 SFfont = XLoadQueryFont(SFdisplay, data->fontname);
1102#endif
1103 if (!SFfont)
1104 {
1105#ifdef FEAT_XFONTSET
1106 SFfont = XCreateFontSet(SFdisplay, SF_DEFAULT_FONT,
1107 &missing, &num_missing, &def_str);
1108#else
1109 SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT);
1110#endif
1111 if (!SFfont)
1112 {
1113 EMSG2(_("E616: vim_SelFile: can't get font %s"), SF_DEFAULT_FONT);
1114 SFstatus = SEL_FILE_CANCEL;
1115 return;
1116 }
1117 }
1118
1119#ifdef FEAT_XFONTSET
1120 extents = XExtentsOfFontSet(SFfont);
1121 SFcharWidth = extents->max_logical_extent.width;
1122 SFcharAscent = -extents->max_logical_extent.y;
1123 SFcharHeight = extents->max_logical_extent.height;
1124#else
1125 SFcharWidth = (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2;
1126 SFcharAscent = SFfont->max_bounds.ascent;
1127 SFcharHeight = SFcharAscent + SFfont->max_bounds.descent;
1128#endif
1129}
1130
Bram Moolenaard25c16e2016-01-29 22:13:30 +01001131static void SFcreateGC(void);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001132
1133 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001134SFcreateGC(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001135{
1136 XGCValues gcValues;
1137 XRectangle rectangles[1];
1138
1139 gcValues.foreground = SFfore;
1140
1141 SFlineGC = XtGetGC(
1142 selFileLists[0],
1143 (XtGCMask)GCForeground,
1144 &gcValues);
1145
1146 SFscrollGC = XtGetGC(
1147 selFileLists[0],
1148 (XtGCMask)0,
1149 &gcValues);
1150
1151 gcValues.function = GXxor;
1152 gcValues.foreground = SFfore ^ SFback;
1153 gcValues.background = SFfore ^ SFback;
1154
1155 SFinvertGC = XtGetGC(
1156 selFileLists[0],
1157 (XtGCMask)GCFunction | GCForeground | GCBackground,
1158 &gcValues);
1159
1160 gcValues.foreground = SFfore;
1161 gcValues.background = SFback;
1162#ifndef FEAT_XFONTSET
1163 gcValues.font = SFfont->fid;
1164#endif
1165
1166 SFtextGC = XCreateGC(
1167 SFdisplay,
1168 XtWindow(selFileLists[0]),
1169#ifdef FEAT_XFONTSET
1170 (unsigned long)GCForeground | GCBackground,
1171#else
1172 (unsigned long)GCForeground | GCBackground | GCFont,
1173#endif
1174 &gcValues);
1175
1176 rectangles[0].x = SFlineToTextH + SFbesideText;
1177 rectangles[0].y = 0;
1178 rectangles[0].width = SFcharsPerEntry * SFcharWidth;
1179 rectangles[0].height = SFupperY + 1;
1180
1181 XSetClipRectangles(
1182 SFdisplay,
1183 SFtextGC,
1184 0,
1185 0,
1186 rectangles,
1187 1,
1188 Unsorted);
1189}
1190
1191 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001192SFclearList(int n, int doScroll)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001193{
1194 SFDir *dir;
1195
1196 SFcurrentInvert[n] = -1;
1197
1198 XClearWindow(SFdisplay, XtWindow(selFileLists[n]));
1199
1200 XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs, 2);
1201
1202 if (doScroll)
1203 {
1204 dir = &(SFdirs[SFdirPtr + n]);
1205
1206 if ((SFdirPtr + n < SFdirEnd) && dir->nEntries && dir->nChars)
1207 {
1208#ifdef FEAT_GUI_NEXTAW
1209 XawScrollbarSetThumb(
1210 selFileVScrolls[n],
1211 (float) (((double) dir->vOrigin) /
1212 dir->nEntries),
1213 (float) (((double) ((dir->nEntries < SFlistSize)
1214 ? dir->nEntries : SFlistSize)) /
1215 dir->nEntries));
1216#else
1217 vim_XawScrollbarSetThumb(
1218 selFileVScrolls[n],
1219 (float) (((double) dir->vOrigin) /
1220 dir->nEntries),
1221 (float) (((double) ((dir->nEntries < SFlistSize)
1222 ? dir->nEntries : SFlistSize)) /
1223 dir->nEntries),
1224 (double)dir->nEntries);
1225#endif
1226
1227#ifdef FEAT_GUI_NEXTAW
1228 XawScrollbarSetThumb(
1229 selFileHScrolls[n],
1230 (float) (((double) dir->hOrigin) / dir->nChars),
1231 (float) (((double) ((dir->nChars <
1232 SFcharsPerEntry) ? dir->nChars :
1233 SFcharsPerEntry)) / dir->nChars));
1234#else
1235 vim_XawScrollbarSetThumb(
1236 selFileHScrolls[n],
1237 (float) (((double) dir->hOrigin) / dir->nChars),
1238 (float) (((double) ((dir->nChars <
1239 SFcharsPerEntry) ? dir->nChars :
1240 SFcharsPerEntry)) / dir->nChars),
1241 (double)dir->nChars);
1242#endif
1243 }
1244 else
1245 {
1246#ifdef FEAT_GUI_NEXTAW
1247 XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
1248 (float) 1.0);
1249#else
1250 vim_XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
1251 (float) 1.0, 1.0);
1252#endif
1253#ifdef FEAT_GUI_NEXTAW
1254 XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
1255 (float) 1.0);
1256#else
1257 vim_XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
1258 (float) 1.0, 1.0);
1259#endif
1260 }
1261 }
1262}
1263
Bram Moolenaard25c16e2016-01-29 22:13:30 +01001264static void SFdeleteEntry(SFDir *dir, SFEntry *entry);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001265
1266 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001267SFdeleteEntry(SFDir *dir, SFEntry *entry)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001268{
1269 SFEntry *e;
1270 SFEntry *end;
1271 int n;
1272 int idx;
1273
1274 idx = entry - dir->entries;
1275
1276 if (idx < dir->beginSelection)
1277 dir->beginSelection--;
1278 if (idx <= dir->endSelection)
1279 dir->endSelection--;
1280 if (dir->beginSelection > dir->endSelection)
1281 dir->beginSelection = dir->endSelection = -1;
1282
1283 if (idx < dir->vOrigin)
1284 dir->vOrigin--;
1285
1286 XtFree(entry->real);
1287
1288 end = &(dir->entries[dir->nEntries - 1]);
1289
1290 for (e = entry; e < end; e++)
1291 *e = *(e + 1);
1292
1293 if (!(--dir->nEntries))
1294 return;
1295
1296 n = dir - &(SFdirs[SFdirPtr]);
1297 if ((n < 0) || (n > 2))
1298 return;
1299
1300#ifdef FEAT_GUI_NEXTAW
1301 XawScrollbarSetThumb(
1302 selFileVScrolls[n],
1303 (float) (((double) dir->vOrigin) / dir->nEntries),
1304 (float) (((double) ((dir->nEntries < SFlistSize) ?
1305 dir->nEntries : SFlistSize)) / dir->nEntries));
1306#else
1307 vim_XawScrollbarSetThumb(
1308 selFileVScrolls[n],
1309 (float) (((double) dir->vOrigin) / dir->nEntries),
1310 (float) (((double) ((dir->nEntries < SFlistSize) ?
1311 dir->nEntries : SFlistSize)) / dir->nEntries),
1312 (double)dir->nEntries);
1313#endif
1314}
1315
Bram Moolenaar8767f522016-07-01 17:17:39 +02001316static void SFwriteStatChar(char *name, int last, stat_T *statBuf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001317
1318 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001319SFwriteStatChar(
1320 char *name,
1321 int last,
Bram Moolenaar8767f522016-07-01 17:17:39 +02001322 stat_T *statBuf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001323{
1324 name[last] = SFstatChar(statBuf);
1325}
1326
Bram Moolenaard25c16e2016-01-29 22:13:30 +01001327static int SFstatAndCheck(SFDir *dir, SFEntry *entry);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001328
1329 static int
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001330SFstatAndCheck(SFDir *dir, SFEntry *entry)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001331{
Bram Moolenaar8767f522016-07-01 17:17:39 +02001332 stat_T statBuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001333 char save;
1334 int last;
1335
1336 /*
1337 * must be restored before returning
1338 */
1339 save = *(dir->path);
1340 *(dir->path) = 0;
1341
1342 if (!SFchdir(SFcurrentPath))
1343 {
1344 last = strlen(entry->real) - 1;
1345 entry->real[last] = 0;
1346 entry->statDone = 1;
1347 if ((!mch_stat(entry->real, &statBuf))
1348#ifdef S_IFLNK
1349 || (!mch_lstat(entry->real, &statBuf))
1350#endif
1351 )
1352 {
1353 if (SFfunc)
1354 {
1355 char *shown;
1356
1357 shown = NULL;
1358 if (SFfunc(entry->real, &shown, &statBuf))
1359 {
1360 if (shown)
1361 {
1362 int len;
1363
1364 len = strlen(shown);
1365 entry->shown = XtMalloc((unsigned) (len + 2));
1366 (void) strcpy(entry->shown, shown);
1367 SFwriteStatChar(entry->shown, len, &statBuf);
1368 entry->shown[len + 1] = 0;
1369 }
1370 }
1371 else
1372 {
1373 SFdeleteEntry(dir, entry);
1374
1375 *(dir->path) = save;
1376 return 1;
1377 }
1378 }
1379 SFwriteStatChar(entry->real, last, &statBuf);
1380 }
1381 else
1382 entry->real[last] = ' ';
1383 }
1384
1385 *(dir->path) = save;
1386 return 0;
1387}
1388
1389
1390 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001391SFdrawStrings(
1392 Window w,
1393 SFDir *dir,
1394 int from,
1395 int to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001396{
1397 int i;
1398 SFEntry *entry;
1399 int x;
1400
1401 x = SFtextX - dir->hOrigin * SFcharWidth;
1402
1403 if (dir->vOrigin + to >= dir->nEntries)
1404 to = dir->nEntries - dir->vOrigin - 1;
1405 for (i = from; i <= to; i++)
1406 {
1407 entry = &(dir->entries[dir->vOrigin + i]);
1408 if (!(entry->statDone))
1409 {
1410 if (SFstatAndCheck(dir, entry))
1411 {
1412 if (dir->vOrigin + to >= dir->nEntries)
1413 to = dir->nEntries - dir->vOrigin - 1;
1414 i--;
1415 continue;
1416 }
1417 }
1418#ifdef FEAT_XFONTSET
1419 XmbDrawImageString(
1420 SFdisplay,
1421 w,
1422 SFfont,
1423 SFtextGC,
1424 x,
1425 SFtextYoffset + i * SFentryHeight,
1426 entry->shown,
1427 strlen(entry->shown));
1428#else
1429 XDrawImageString(
1430 SFdisplay,
1431 w,
1432 SFtextGC,
1433 x,
1434 SFtextYoffset + i * SFentryHeight,
1435 entry->shown,
1436 strlen(entry->shown));
1437#endif
1438 if (dir->vOrigin + i == dir->beginSelection)
1439 {
1440 XDrawLine(
1441 SFdisplay,
1442 w,
1443 SFlineGC,
1444 SFlineToTextH + 1,
1445 SFlowerY + i * SFentryHeight,
1446 SFlineToTextH + SFentryWidth - 2,
1447 SFlowerY + i * SFentryHeight);
1448 }
1449 if ((dir->vOrigin + i >= dir->beginSelection) &&
1450 (dir->vOrigin + i <= dir->endSelection))
1451 {
1452 SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 =
1453 SFlowerY + i * SFentryHeight;
1454 SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 =
1455 SFlowerY + (i + 1) * SFentryHeight - 1;
1456 XDrawSegments(
1457 SFdisplay,
1458 w,
1459 SFlineGC,
1460 SFcompletionSegs,
1461 2);
1462 }
1463 if (dir->vOrigin + i == dir->endSelection)
1464 {
1465 XDrawLine(
1466 SFdisplay,
1467 w,
1468 SFlineGC,
1469 SFlineToTextH + 1,
1470 SFlowerY + (i + 1) * SFentryHeight - 1,
1471 SFlineToTextH + SFentryWidth - 2,
1472 SFlowerY + (i + 1) * SFentryHeight - 1);
1473 }
1474 }
1475}
1476
1477 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001478SFdrawList(int n, int doScroll)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001479{
1480 SFDir *dir;
1481 Window w;
1482
1483 SFclearList(n, doScroll);
1484
1485 if (SFdirPtr + n < SFdirEnd)
1486 {
1487 dir = &(SFdirs[SFdirPtr + n]);
1488 w = XtWindow(selFileLists[n]);
1489#ifdef FEAT_XFONTSET
1490 XmbDrawImageString(
1491 SFdisplay,
1492 w,
1493 SFfont,
1494 SFtextGC,
1495 SFtextX - dir->hOrigin * SFcharWidth,
1496 SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
1497 dir->dir,
1498 strlen(dir->dir));
1499#else
1500 XDrawImageString(
1501 SFdisplay,
1502 w,
1503 SFtextGC,
1504 SFtextX - dir->hOrigin * SFcharWidth,
1505 SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
1506 dir->dir,
1507 strlen(dir->dir));
1508#endif
1509 SFdrawStrings(w, dir, 0, SFlistSize - 1);
1510 }
1511}
1512
1513 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001514SFdrawLists(int doScroll)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001515{
1516 int i;
1517
1518 for (i = 0; i < 3; i++)
1519 SFdrawList(i, doScroll);
1520}
1521
1522 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001523SFinvertEntry(int n)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001524{
1525 XFillRectangle(
1526 SFdisplay,
1527 XtWindow(selFileLists[n]),
1528 SFinvertGC,
1529 SFlineToTextH,
1530 SFcurrentInvert[n] * SFentryHeight + SFlowerY,
1531 SFentryWidth,
1532 SFentryHeight);
1533}
1534
Bram Moolenaard25c16e2016-01-29 22:13:30 +01001535static unsigned long SFscrollTimerInterval(void);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001536
1537 static unsigned long
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001538SFscrollTimerInterval(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001539{
1540 static int maxVal = 200;
1541 static int varyDist = 50;
1542 static int minDist = 50;
1543 int t;
1544 int dist;
1545
1546 if (SFcurrentListY < SFlowerY)
1547 dist = SFlowerY - SFcurrentListY;
1548 else if (SFcurrentListY > SFupperY)
1549 dist = SFcurrentListY - SFupperY;
1550 else
1551 return (unsigned long) 1;
1552
1553 t = maxVal - ((maxVal / varyDist) * (dist - minDist));
1554
1555 if (t < 1)
1556 t = 1;
1557
1558 if (t > maxVal)
1559 t = maxVal;
1560
1561 return (unsigned long)t;
1562}
1563
Bram Moolenaard25c16e2016-01-29 22:13:30 +01001564static void SFscrollTimer(XtPointer p, XtIntervalId *id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001565
Bram Moolenaar071d4272004-06-13 20:20:40 +00001566 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001567SFscrollTimer(XtPointer p, XtIntervalId *id UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001568{
1569 SFDir *dir;
1570 int save;
1571 int n;
1572
1573 n = (long)p;
1574
1575 dir = &(SFdirs[SFdirPtr + n]);
1576 save = dir->vOrigin;
1577
1578 if (SFcurrentListY < SFlowerY)
1579 {
1580 if (dir->vOrigin > 0)
1581 SFvSliderMovedCallback(selFileVScrolls[n], n, dir->vOrigin - 1);
1582 }
1583 else if (SFcurrentListY > SFupperY)
1584 {
1585 if (dir->vOrigin < dir->nEntries - SFlistSize)
1586 SFvSliderMovedCallback(selFileVScrolls[n], n, dir->vOrigin + 1);
1587 }
1588
1589 if (dir->vOrigin != save)
1590 {
1591 if (dir->nEntries)
1592 {
1593#ifdef FEAT_GUI_NEXTAW
1594 XawScrollbarSetThumb(
1595 selFileVScrolls[n],
1596 (float) (((double) dir->vOrigin) / dir->nEntries),
1597 (float) (((double) ((dir->nEntries < SFlistSize) ?
1598 dir->nEntries : SFlistSize)) / dir->nEntries));
1599#else
1600 vim_XawScrollbarSetThumb(
1601 selFileVScrolls[n],
1602 (float) (((double) dir->vOrigin) / dir->nEntries),
1603 (float) (((double) ((dir->nEntries < SFlistSize) ?
1604 dir->nEntries : SFlistSize)) / dir->nEntries),
1605 (double)dir->nEntries);
1606#endif
1607 }
1608 }
1609
1610 if (SFbuttonPressed)
1611 SFscrollTimerId = XtAppAddTimeOut(SFapp,
Bram Moolenaar9d6650f2010-06-06 23:04:47 +02001612 SFscrollTimerInterval(), SFscrollTimer,
1613 (XtPointer)(long_u)n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001614}
1615
1616 static int
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001617SFnewInvertEntry(int n, XMotionEvent *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001618{
1619 int x, y;
1620 int nw;
1621 static int SFscrollTimerAdded = 0;
1622
1623 x = event->x;
1624 y = event->y;
1625
1626 if (SFdirPtr + n >= SFdirEnd)
1627 return -1;
1628
1629 if ((x >= 0) && (x <= SFupperX) && (y >= SFlowerY) && (y <= SFupperY))
1630 {
1631 SFDir *dir = &(SFdirs[SFdirPtr + n]);
1632
1633 if (SFscrollTimerAdded)
1634 {
1635 SFscrollTimerAdded = 0;
1636 XtRemoveTimeOut(SFscrollTimerId);
1637 }
1638
1639 nw = (y - SFlowerY) / SFentryHeight;
1640 if (dir->vOrigin + nw >= dir->nEntries)
1641 return -1;
1642 return nw;
1643 }
1644 else
1645 {
1646 if (SFbuttonPressed)
1647 {
1648 SFcurrentListY = y;
1649 if (!SFscrollTimerAdded)
1650 {
1651 SFscrollTimerAdded = 1;
1652 SFscrollTimerId = XtAppAddTimeOut(SFapp,
1653 SFscrollTimerInterval(), SFscrollTimer,
Bram Moolenaar9d6650f2010-06-06 23:04:47 +02001654 (XtPointer)(long_u)n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001655 }
1656 }
1657 return -1;
1658 }
1659}
1660
Bram Moolenaar071d4272004-06-13 20:20:40 +00001661 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001662SFenterList(Widget w UNUSED, int n, XEnterWindowEvent *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001663{
1664 int nw;
1665
1666 /* sanity */
1667 if (SFcurrentInvert[n] != -1)
1668 {
1669 SFinvertEntry(n);
1670 SFcurrentInvert[n] = -1;
1671 }
1672
1673 nw = SFnewInvertEntry(n, (XMotionEvent *) event);
1674 if (nw != -1)
1675 {
1676 SFcurrentInvert[n] = nw;
1677 SFinvertEntry(n);
1678 }
1679}
1680
Bram Moolenaar071d4272004-06-13 20:20:40 +00001681 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001682SFleaveList(Widget w UNUSED, int n, XEvent *event UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001683{
1684 if (SFcurrentInvert[n] != -1)
1685 {
1686 SFinvertEntry(n);
1687 SFcurrentInvert[n] = -1;
1688 }
1689}
1690
Bram Moolenaar071d4272004-06-13 20:20:40 +00001691 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001692SFmotionList(Widget w UNUSED, int n, XMotionEvent *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001693{
1694 int nw;
1695
1696 nw = SFnewInvertEntry(n, event);
1697
1698 if (nw != SFcurrentInvert[n])
1699 {
1700 if (SFcurrentInvert[n] != -1)
1701 SFinvertEntry(n);
1702 SFcurrentInvert[n] = nw;
1703 if (nw != -1)
1704 SFinvertEntry(n);
1705 }
1706}
1707
Bram Moolenaar071d4272004-06-13 20:20:40 +00001708 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001709SFvFloatSliderMovedCallback(Widget w, XtPointer n, XtPointer fnew)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001710{
1711 int nw;
1712
1713 nw = (*(float *)fnew) * SFdirs[SFdirPtr + (int)(long)n].nEntries;
1714 SFvSliderMovedCallback(w, (int)(long)n, nw);
1715}
1716
Bram Moolenaar071d4272004-06-13 20:20:40 +00001717 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001718SFvSliderMovedCallback(Widget w UNUSED, int n, int nw)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001719{
1720 int old;
1721 Window win;
1722 SFDir *dir;
1723
1724 dir = &(SFdirs[SFdirPtr + n]);
1725
1726 old = dir->vOrigin;
1727 dir->vOrigin = nw;
1728
1729 if (old == nw)
1730 return;
1731
1732 win = XtWindow(selFileLists[n]);
1733
1734 if (ABS(nw - old) < SFlistSize)
1735 {
1736 if (nw > old)
1737 {
1738 XCopyArea(
1739 SFdisplay,
1740 win,
1741 win,
1742 SFscrollGC,
1743 SFlineToTextH,
1744 SFlowerY + (nw - old) * SFentryHeight,
1745 SFentryWidth + SFlineToTextH,
1746 (SFlistSize - (nw - old)) * SFentryHeight,
1747 SFlineToTextH,
1748 SFlowerY);
1749 XClearArea(
1750 SFdisplay,
1751 win,
1752 SFlineToTextH,
1753 SFlowerY + (SFlistSize - (nw - old)) *
1754 SFentryHeight,
1755 SFentryWidth + SFlineToTextH,
1756 (nw - old) * SFentryHeight,
1757 False);
1758 SFdrawStrings(win, dir, SFlistSize - (nw - old),
1759 SFlistSize - 1);
1760 }
1761 else
1762 {
1763 XCopyArea(
1764 SFdisplay,
1765 win,
1766 win,
1767 SFscrollGC,
1768 SFlineToTextH,
1769 SFlowerY,
1770 SFentryWidth + SFlineToTextH,
1771 (SFlistSize - (old - nw)) * SFentryHeight,
1772 SFlineToTextH,
1773 SFlowerY + (old - nw) * SFentryHeight);
1774 XClearArea(
1775 SFdisplay,
1776 win,
1777 SFlineToTextH,
1778 SFlowerY,
1779 SFentryWidth + SFlineToTextH,
1780 (old - nw) * SFentryHeight,
1781 False);
1782 SFdrawStrings(win, dir, 0, old - nw);
1783 }
1784 }
1785 else
1786 {
1787 XClearArea(
1788 SFdisplay,
1789 win,
1790 SFlineToTextH,
1791 SFlowerY,
1792 SFentryWidth + SFlineToTextH,
1793 SFlistSize * SFentryHeight,
1794 False);
1795 SFdrawStrings(win, dir, 0, SFlistSize - 1);
1796 }
1797}
1798
Bram Moolenaar071d4272004-06-13 20:20:40 +00001799 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001800SFvAreaSelectedCallback(Widget w, XtPointer n, XtPointer pnew)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001801{
1802 SFDir *dir;
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001803 int nw = (int)(long)pnew;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001804
1805 dir = &(SFdirs[SFdirPtr + (int)(long)n]);
1806
1807#ifdef FEAT_GUI_NEXTAW
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001808 if (nw < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001809 {
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001810 if (nw > -SFvScrollHeight)
1811 nw = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001812 else
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001813 nw = -SFlistSize;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001814 }
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001815 else if (nw > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001816 {
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001817 if (nw < SFvScrollHeight)
1818 nw = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001819 else
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001820 nw = SFlistSize;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001821 }
1822#endif
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001823 nw += dir->vOrigin;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001824
1825 if (nw > dir->nEntries - SFlistSize)
1826 nw = dir->nEntries - SFlistSize;
1827
1828 if (nw < 0)
1829 nw = 0;
1830
1831 if (dir->nEntries)
1832 {
1833 float f;
1834
1835 f = ((double) nw) / dir->nEntries;
1836
1837#ifdef FEAT_GUI_NEXTAW
1838 XawScrollbarSetThumb(
1839 w,
1840 f,
1841 (float) (((double) ((dir->nEntries < SFlistSize) ?
1842 dir->nEntries : SFlistSize)) / dir->nEntries));
1843#else
1844 vim_XawScrollbarSetThumb(
1845 w,
1846 f,
1847 (float) (((double) ((dir->nEntries < SFlistSize) ?
1848 dir->nEntries : SFlistSize)) / dir->nEntries),
1849 (double)dir->nEntries);
1850#endif
1851 }
1852
1853 SFvSliderMovedCallback(w, (int)(long)n, nw);
1854}
1855
Bram Moolenaar071d4272004-06-13 20:20:40 +00001856 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001857SFhSliderMovedCallback(Widget w UNUSED, XtPointer n, XtPointer nw)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001858{
1859 SFDir *dir;
1860 int save;
1861
1862 dir = &(SFdirs[SFdirPtr + (int)(long)n]);
1863 save = dir->hOrigin;
1864 dir->hOrigin = (*(float *)nw) * dir->nChars;
1865 if (dir->hOrigin == save)
1866 return;
1867
1868 SFdrawList((int)(long)n, SF_DO_NOT_SCROLL);
1869}
1870
Bram Moolenaar071d4272004-06-13 20:20:40 +00001871 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001872SFhAreaSelectedCallback(Widget w, XtPointer n, XtPointer pnew)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001873{
1874 SFDir *dir;
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001875 int nw = (int)(long)pnew;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001876
1877 dir = &(SFdirs[SFdirPtr + (int)(long)n]);
1878
1879#ifdef FEAT_GUI_NEXTAW
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001880 if (nw < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001881 {
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001882 if (nw > -SFhScrollWidth)
1883 nw = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001884 else
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001885 nw = -SFcharsPerEntry;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001886 }
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001887 else if (nw > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001888 {
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001889 if (nw < SFhScrollWidth)
1890 nw = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001891 else
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001892 nw = SFcharsPerEntry;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001893 }
1894#endif
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001895 nw += dir->hOrigin;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001896
1897 if (nw > dir->nChars - SFcharsPerEntry)
1898 nw = dir->nChars - SFcharsPerEntry;
1899
1900 if (nw < 0)
1901 nw = 0;
1902
1903 if (dir->nChars)
1904 {
1905 float f;
1906
1907 f = ((double) nw) / dir->nChars;
1908
1909#ifdef FEAT_GUI_NEXTAW
1910 XawScrollbarSetThumb(
1911 w,
1912 f,
1913 (float) (((double) ((dir->nChars < SFcharsPerEntry) ?
1914 dir->nChars : SFcharsPerEntry)) / dir->nChars));
1915#else
1916 vim_XawScrollbarSetThumb(
1917 w,
1918 f,
1919 (float) (((double) ((dir->nChars < SFcharsPerEntry) ?
1920 dir->nChars : SFcharsPerEntry)) / dir->nChars),
1921 (double)dir->nChars);
1922#endif
1923
1924 SFhSliderMovedCallback(w, n, (XtPointer)&f);
1925 }
1926}
1927
Bram Moolenaar071d4272004-06-13 20:20:40 +00001928 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001929SFpathSliderMovedCallback(
1930 Widget w UNUSED,
1931 XtPointer client_data UNUSED,
1932 XtPointer nw)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001933{
1934 SFDir *dir;
1935 int n;
1936 XawTextPosition pos;
1937 int SFdirPtrSave;
1938
1939 SFdirPtrSave = SFdirPtr;
1940 SFdirPtr = (*(float *)nw) * SFdirEnd;
1941 if (SFdirPtr == SFdirPtrSave)
1942 return;
1943
1944 SFdrawLists(SF_DO_SCROLL);
1945
1946 n = 2;
1947 while (SFdirPtr + n >= SFdirEnd)
1948 n--;
1949
1950 dir = &(SFdirs[SFdirPtr + n]);
1951
1952 pos = dir->path - SFcurrentPath;
1953
1954 if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir)))
1955 {
1956 pos -= strlen(SFstartDir);
1957 if (pos < 0)
1958 pos = 0;
1959 }
1960
1961 XawTextSetInsertionPoint(selFileField, pos);
1962}
1963
Bram Moolenaar071d4272004-06-13 20:20:40 +00001964 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01001965SFpathAreaSelectedCallback(
1966 Widget w,
1967 XtPointer client_data UNUSED,
1968 XtPointer pnew)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001969{
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001970 int nw = (int)(long)pnew;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001971 float f;
1972
1973#ifdef FEAT_GUI_NEXTAW
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001974 if (nw < 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001975 {
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001976 if (nw > -SFpathScrollWidth)
1977 nw = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001978 else
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001979 nw = -3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001980 }
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001981 else if (nw > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001982 {
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001983 if (nw < SFpathScrollWidth)
1984 nw = 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001985 else
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001986 nw = 3;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001987 }
1988#endif
Bram Moolenaar9fb0e132006-05-13 13:51:38 +00001989 nw += SFdirPtr;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001990
1991 if (nw > SFdirEnd - 3)
1992 nw = SFdirEnd - 3;
1993
1994 if (nw < 0)
1995 nw = 0;
1996
1997 f = ((double) nw) / SFdirEnd;
1998
1999#ifdef FEAT_GUI_NEXTAW
2000 XawScrollbarSetThumb(
2001 w,
2002 f,
2003 (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) / SFdirEnd));
2004#else
2005 vim_XawScrollbarSetThumb(
2006 w,
2007 f,
2008 (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) / SFdirEnd),
2009 (double)SFdirEnd);
2010#endif
2011
2012 SFpathSliderMovedCallback(w, (XtPointer) NULL, (XtPointer)&f);
2013}
2014
2015 static Boolean
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002016SFworkProc(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002017{
2018 SFDir *dir;
2019 SFEntry *entry;
2020
2021 for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--)
2022 {
2023 if (!(dir->nEntries))
2024 continue;
2025 for (entry = &(dir->entries[dir->nEntries - 1]);
2026 entry >= dir->entries;
2027 entry--)
2028 {
2029 if (!(entry->statDone))
2030 {
2031 (void)SFstatAndCheck(dir, entry);
2032 return False;
2033 }
2034 }
2035 }
2036
2037 SFworkProcAdded = 0;
2038
2039 return True;
2040}
2041
2042/***************** Dir.c */
2043
2044 static int
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002045SFcompareEntries(const void *p, const void *q)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002046{
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002047 return strcmp(((SFEntry *)p)->real, ((SFEntry *)q)->real);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002048}
2049
2050 static int
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002051SFgetDir(
2052 SFDir *dir)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002053{
2054 SFEntry *result = NULL;
2055 int Alloc = 0;
2056 int i;
2057 DIR *dirp;
2058 struct dirent *dp;
2059 char *str;
2060 int len;
2061 int maxChars;
Bram Moolenaar8767f522016-07-01 17:17:39 +02002062 stat_T statBuf;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002063
2064 maxChars = strlen(dir->dir) - 1;
2065
2066 dir->entries = NULL;
2067 dir->nEntries = 0;
2068 dir->nChars = 0;
2069
2070 result = NULL;
2071 i = 0;
2072
2073 dirp = opendir(".");
2074 if (!dirp)
2075 return 1;
2076
2077 (void)mch_stat(".", &statBuf);
2078 dir->mtime = statBuf.st_mtime;
2079
2080 while ((dp = readdir(dirp)))
2081 {
2082 /* Ignore "." and ".." */
2083 if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
2084 continue;
2085 if (i >= Alloc)
2086 {
2087 Alloc = 2 * (Alloc + 1);
2088 result = (SFEntry *) XtRealloc((char *) result,
2089 (unsigned) (Alloc * sizeof(SFEntry)));
2090 }
2091 result[i].statDone = 0;
2092 str = dp->d_name;
2093 len = strlen(str);
2094 result[i].real = XtMalloc((unsigned) (len + 2));
2095 (void) strcat(strcpy(result[i].real, str), " ");
2096 if (len > maxChars)
2097 maxChars = len;
2098 result[i].shown = result[i].real;
2099 i++;
2100 }
2101
2102 qsort((char *) result, (size_t) i, sizeof(SFEntry), SFcompareEntries);
2103
2104 dir->entries = result;
2105 dir->nEntries = i;
2106 dir->nChars = maxChars + 1;
2107
2108 closedir(dirp);
2109
2110 return 0;
2111}
2112
2113/***************** SFinternal.h */
2114
2115#include <sys/param.h>
2116#include <X11/cursorfont.h>
2117#include <X11/Composite.h>
2118#include <X11/Shell.h>
2119#ifdef FEAT_GUI_NEXTAW
2120# include <X11/neXtaw/Form.h>
2121# include <X11/neXtaw/Command.h>
2122# include <X11/neXtaw/Label.h>
2123#else
2124#include <X11/Xaw/Form.h>
2125#include <X11/Xaw/Command.h>
2126#include <X11/Xaw/Label.h>
2127#endif
2128
2129static char *oneLineTextEditTranslations = "\
2130 <Key>Return: redraw-display()\n\
2131 Ctrl<Key>M: redraw-display()\n\
2132";
2133
Bram Moolenaard25c16e2016-01-29 22:13:30 +01002134static void SFexposeList(Widget w, XtPointer n, XEvent *event, Boolean *cont);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002135
Bram Moolenaar071d4272004-06-13 20:20:40 +00002136 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002137SFexposeList(
2138 Widget w UNUSED,
2139 XtPointer n,
2140 XEvent *event,
2141 Boolean *cont UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002142{
2143 if ((event->type == NoExpose) || event->xexpose.count)
2144 return;
2145
2146 SFdrawList((int)(long)n, SF_DO_NOT_SCROLL);
2147}
2148
Bram Moolenaard25c16e2016-01-29 22:13:30 +01002149static void SFmodVerifyCallback(Widget w, XtPointer client_data, XEvent *event, Boolean *cont);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002150
Bram Moolenaar071d4272004-06-13 20:20:40 +00002151 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002152SFmodVerifyCallback(
2153 Widget w UNUSED,
2154 XtPointer client_data UNUSED,
2155 XEvent *event,
2156 Boolean *cont UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002157{
2158 char buf[2];
2159
2160 if ((XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) &&
2161 ((*buf) == '\r'))
2162 SFstatus = SEL_FILE_OK;
2163 else
2164 SFstatus = SEL_FILE_TEXT;
2165}
2166
Bram Moolenaard25c16e2016-01-29 22:13:30 +01002167static void SFokCallback(Widget w, XtPointer cl, XtPointer cd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002168
Bram Moolenaar071d4272004-06-13 20:20:40 +00002169 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002170SFokCallback(Widget w UNUSED, XtPointer cl UNUSED, XtPointer cd UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002171{
2172 SFstatus = SEL_FILE_OK;
2173}
2174
2175static XtCallbackRec SFokSelect[] =
2176{
2177 { SFokCallback, (XtPointer) NULL },
2178 { NULL, (XtPointer) NULL },
2179};
2180
Bram Moolenaard25c16e2016-01-29 22:13:30 +01002181static void SFcancelCallback(Widget w, XtPointer cl, XtPointer cd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002182
Bram Moolenaar071d4272004-06-13 20:20:40 +00002183 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002184SFcancelCallback(Widget w UNUSED, XtPointer cl UNUSED, XtPointer cd UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002185{
2186 SFstatus = SEL_FILE_CANCEL;
2187}
2188
2189static XtCallbackRec SFcancelSelect[] =
2190{
2191 { SFcancelCallback, (XtPointer) NULL },
2192 { NULL, (XtPointer) NULL },
2193};
2194
Bram Moolenaard25c16e2016-01-29 22:13:30 +01002195static void SFdismissAction(Widget w, XEvent *event, String *params, Cardinal *num_params);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002196
Bram Moolenaar071d4272004-06-13 20:20:40 +00002197 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002198SFdismissAction(
2199 Widget w UNUSED,
2200 XEvent *event,
2201 String *params UNUSED,
2202 Cardinal *num_params UNUSED)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002203{
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002204 if (event->type == ClientMessage
2205 && (Atom)event->xclient.data.l[0] != SFwmDeleteWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002206 return;
2207
2208 SFstatus = SEL_FILE_CANCEL;
2209}
2210
2211static char *wmDeleteWindowTranslation = "\
2212 <Message>WM_PROTOCOLS: SelFileDismiss()\n\
2213";
2214
2215static XtActionsRec actions[] =
2216{
2217 {"SelFileDismiss", SFdismissAction},
2218};
2219
2220 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002221SFsetColors(
2222 guicolor_T bg,
2223 guicolor_T fg,
2224 guicolor_T scroll_bg,
2225 guicolor_T scroll_fg)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002226{
2227 if (selFileForm)
2228 {
2229 XtVaSetValues(selFileForm, XtNbackground, bg,
2230 XtNforeground, fg,
2231 XtNborderColor, bg,
2232 NULL);
2233 }
2234 {
2235 int i;
2236
2237 for (i = 0; i < 3; ++i)
2238 {
2239 if (selFileLists[i])
2240 {
2241 XtVaSetValues(selFileLists[i], XtNbackground, bg,
2242 XtNforeground, fg,
2243 XtNborderColor, fg,
2244 NULL);
2245 }
2246 }
2247 }
2248 if (selFileOK)
2249 {
2250 XtVaSetValues(selFileOK, XtNbackground, bg,
2251 XtNforeground, fg,
2252 XtNborderColor, fg,
2253 NULL);
2254 }
2255 if (selFileCancel)
2256 {
2257 XtVaSetValues(selFileCancel, XtNbackground, bg,
2258 XtNforeground, fg,
2259 XtNborderColor, fg,
2260 NULL);
2261 }
2262 if (selFilePrompt)
2263 {
2264 XtVaSetValues(selFilePrompt, XtNbackground, bg,
2265 XtNforeground, fg,
2266 NULL);
2267 }
2268 if (gui.dpy)
2269 {
2270 XSetBackground(gui.dpy, SFtextGC, bg);
2271 XSetForeground(gui.dpy, SFtextGC, fg);
2272 XSetForeground(gui.dpy, SFlineGC, fg);
2273
2274 /* This is an xor GC, so combine the fg and background */
2275 XSetBackground(gui.dpy, SFinvertGC, fg ^ bg);
2276 XSetForeground(gui.dpy, SFinvertGC, fg ^ bg);
2277 }
2278 if (selFileHScroll)
2279 {
2280 XtVaSetValues(selFileHScroll, XtNbackground, scroll_bg,
2281 XtNforeground, scroll_fg,
2282 XtNborderColor, fg,
2283 NULL);
2284 }
2285 {
2286 int i;
2287
2288 for (i = 0; i < 3; i++)
2289 {
2290 XtVaSetValues(selFileVScrolls[i], XtNbackground, scroll_bg,
2291 XtNforeground, scroll_fg,
2292 XtNborderColor, fg,
2293 NULL);
2294 XtVaSetValues(selFileHScrolls[i], XtNbackground, scroll_bg,
2295 XtNforeground, scroll_fg,
2296 XtNborderColor, fg,
2297 NULL);
2298 }
2299 }
2300}
2301
2302 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002303SFcreateWidgets(
2304 Widget toplevel,
2305 char *prompt,
2306 char *ok,
2307 char *cancel)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002308{
2309 Cardinal n;
2310 int listWidth, listHeight;
2311 int listSpacing = 10;
2312 int scrollThickness = 15;
2313 int hScrollX, hScrollY;
2314 int vScrollX, vScrollY;
2315
2316 selFile = XtVaAppCreateShell("selFile", "SelFile",
2317 transientShellWidgetClass, SFdisplay,
2318 XtNtransientFor, toplevel,
2319 XtNtitle, prompt,
2320 NULL);
2321
2322 /* Add WM_DELETE_WINDOW protocol */
2323 XtAppAddActions(XtWidgetToApplicationContext(selFile),
2324 actions, XtNumber(actions));
2325 XtOverrideTranslations(selFile,
2326 XtParseTranslationTable(wmDeleteWindowTranslation));
2327
2328 selFileForm = XtVaCreateManagedWidget("selFileForm",
2329 formWidgetClass, selFile,
2330 XtNdefaultDistance, 30,
2331 XtNforeground, SFfore,
2332 XtNbackground, SFback,
2333 XtNborderColor, SFback,
2334 NULL);
2335
2336 selFilePrompt = XtVaCreateManagedWidget("selFilePrompt",
2337 labelWidgetClass, selFileForm,
2338 XtNlabel, prompt,
2339 XtNresizable, True,
2340 XtNtop, XtChainTop,
2341 XtNbottom, XtChainTop,
2342 XtNleft, XtChainLeft,
2343 XtNright, XtChainLeft,
2344 XtNborderWidth, 0,
2345 XtNforeground, SFfore,
2346 XtNbackground, SFback,
2347 NULL);
2348
2349 /*
2350 XtVaGetValues(selFilePrompt,
2351 XtNforeground, &SFfore,
2352 XtNbackground, &SFback,
2353 NULL);
2354 */
2355
2356 SFinitFont();
2357
2358 SFentryWidth = SFbesideText + SFcharsPerEntry * SFcharWidth +
2359 SFbesideText;
2360 SFentryHeight = SFaboveAndBelowText + SFcharHeight +
2361 SFaboveAndBelowText;
2362
2363 listWidth = SFlineToTextH + SFentryWidth + SFlineToTextH + 1 +
2364 scrollThickness;
2365 listHeight = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
2366 SFlineToTextV + SFlistSize * SFentryHeight +
2367 SFlineToTextV + 1 + scrollThickness;
2368
2369 SFpathScrollWidth = 3 * listWidth + 2 * listSpacing + 4;
2370
2371 hScrollX = -1;
2372 hScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
2373 SFlineToTextV + SFlistSize * SFentryHeight +
2374 SFlineToTextV;
2375 SFhScrollWidth = SFlineToTextH + SFentryWidth + SFlineToTextH;
2376
2377 vScrollX = SFlineToTextH + SFentryWidth + SFlineToTextH;
2378 vScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV;
2379 SFvScrollHeight = SFlineToTextV + SFlistSize * SFentryHeight +
2380 SFlineToTextV;
2381
2382 SFupperX = SFlineToTextH + SFentryWidth + SFlineToTextH - 1;
2383 SFlowerY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
2384 SFlineToTextV;
2385 SFupperY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
2386 SFlineToTextV + SFlistSize * SFentryHeight - 1;
2387
2388 SFtextX = SFlineToTextH + SFbesideText;
2389 SFtextYoffset = SFlowerY + SFaboveAndBelowText + SFcharAscent;
2390
2391 SFsegs[0].x1 = 0;
2392 SFsegs[0].y1 = vScrollY;
2393 SFsegs[0].x2 = vScrollX - 1;
2394 SFsegs[0].y2 = vScrollY;
2395 SFsegs[1].x1 = vScrollX;
2396 SFsegs[1].y1 = 0;
2397 SFsegs[1].x2 = vScrollX;
2398 SFsegs[1].y2 = vScrollY - 1;
2399
2400 SFcompletionSegs[0].x1 = SFcompletionSegs[0].x2 = SFlineToTextH;
2401 SFcompletionSegs[1].x1 = SFcompletionSegs[1].x2 =
2402 SFlineToTextH + SFentryWidth - 1;
2403
2404 selFileField = XtVaCreateManagedWidget("selFileField",
2405 asciiTextWidgetClass, selFileForm,
2406 XtNwidth, 3 * listWidth + 2 * listSpacing + 4,
2407 XtNborderColor, SFfore,
2408 XtNfromVert, selFilePrompt,
2409 XtNvertDistance, 10,
2410 XtNresizable, True,
2411 XtNtop, XtChainTop,
2412 XtNbottom, XtChainTop,
2413 XtNleft, XtChainLeft,
2414 XtNright, XtChainLeft,
2415 XtNstring, SFtextBuffer,
2416 XtNlength, MAXPATHL,
2417 XtNeditType, XawtextEdit,
2418 XtNwrap, XawtextWrapWord,
2419 XtNresize, XawtextResizeHeight,
2420 XtNuseStringInPlace, True,
2421 NULL);
2422
2423 XtOverrideTranslations(selFileField,
2424 XtParseTranslationTable(oneLineTextEditTranslations));
2425 XtSetKeyboardFocus(selFileForm, selFileField);
2426
2427 selFileHScroll = XtVaCreateManagedWidget("selFileHScroll",
2428#ifdef FEAT_GUI_NEXTAW
2429 scrollbarWidgetClass, selFileForm,
2430#else
2431 vim_scrollbarWidgetClass, selFileForm,
2432#endif
2433 XtNorientation, XtorientHorizontal,
2434 XtNwidth, SFpathScrollWidth,
2435 XtNheight, scrollThickness,
2436 XtNborderColor, SFfore,
2437 XtNfromVert, selFileField,
2438 XtNvertDistance, 30,
2439 XtNtop, XtChainTop,
2440 XtNbottom, XtChainTop,
2441 XtNleft, XtChainLeft,
2442 XtNright, XtChainLeft,
2443 XtNforeground, gui.scroll_fg_pixel,
2444 XtNbackground, gui.scroll_bg_pixel,
2445#ifndef FEAT_GUI_NEXTAW
2446 XtNlimitThumb, 1,
2447#endif
2448 NULL);
2449
2450 XtAddCallback(selFileHScroll, XtNjumpProc,
2451 (XtCallbackProc) SFpathSliderMovedCallback, (XtPointer)NULL);
2452 XtAddCallback(selFileHScroll, XtNscrollProc,
2453 (XtCallbackProc) SFpathAreaSelectedCallback, (XtPointer)NULL);
2454
2455 selFileLists[0] = XtVaCreateManagedWidget("selFileList1",
2456 compositeWidgetClass, selFileForm,
2457 XtNwidth, listWidth,
2458 XtNheight, listHeight,
2459 XtNforeground, SFfore,
2460 XtNbackground, SFback,
2461 XtNborderColor, SFfore,
2462 XtNfromVert, selFileHScroll,
2463 XtNvertDistance, 10,
2464 XtNtop, XtChainTop,
2465 XtNbottom, XtChainTop,
2466 XtNleft, XtChainLeft,
2467 XtNright, XtChainLeft,
2468 NULL);
2469
2470 selFileLists[1] = XtVaCreateManagedWidget("selFileList2",
2471 compositeWidgetClass, selFileForm,
2472 XtNwidth, listWidth,
2473 XtNheight, listHeight,
2474 XtNforeground, SFfore,
2475 XtNbackground, SFback,
2476 XtNborderColor, SFfore,
2477 XtNfromHoriz, selFileLists[0],
2478 XtNfromVert, selFileHScroll,
2479 XtNhorizDistance, listSpacing,
2480 XtNvertDistance, 10,
2481 XtNtop, XtChainTop,
2482 XtNbottom, XtChainTop,
2483 XtNleft, XtChainLeft,
2484 XtNright, XtChainLeft,
2485 NULL);
2486
2487 selFileLists[2] = XtVaCreateManagedWidget("selFileList3",
2488 compositeWidgetClass, selFileForm,
2489 XtNwidth, listWidth,
2490 XtNheight, listHeight,
2491 XtNforeground, SFfore,
2492 XtNbackground, SFback,
2493 XtNborderColor, SFfore,
2494 XtNfromHoriz, selFileLists[1],
2495 XtNfromVert, selFileHScroll,
2496 XtNhorizDistance, listSpacing,
2497 XtNvertDistance, 10,
2498 XtNtop, XtChainTop,
2499 XtNbottom, XtChainTop,
2500 XtNleft, XtChainLeft,
2501 XtNright, XtChainLeft,
2502 NULL);
2503
2504 for (n = 0; n < 3; n++)
2505 {
2506 selFileVScrolls[n] = XtVaCreateManagedWidget("selFileVScroll",
2507#ifdef FEAT_GUI_NEXTAW
2508 scrollbarWidgetClass, selFileLists[n],
2509#else
2510 vim_scrollbarWidgetClass, selFileLists[n],
2511#endif
2512 XtNx, vScrollX,
2513 XtNy, vScrollY,
2514 XtNwidth, scrollThickness,
2515 XtNheight, SFvScrollHeight,
2516 XtNborderColor, SFfore,
2517 XtNforeground, gui.scroll_fg_pixel,
2518 XtNbackground, gui.scroll_bg_pixel,
2519#ifndef FEAT_GUI_NEXTAW
2520 XtNlimitThumb, 1,
2521#endif
2522 NULL);
2523
2524 XtAddCallback(selFileVScrolls[n], XtNjumpProc,
Bram Moolenaar9d6650f2010-06-06 23:04:47 +02002525 (XtCallbackProc)SFvFloatSliderMovedCallback,
2526 (XtPointer)(long_u)n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002527 XtAddCallback(selFileVScrolls[n], XtNscrollProc,
Bram Moolenaar6470de82013-06-27 22:36:03 +02002528 (XtCallbackProc)SFvAreaSelectedCallback, (XtPointer)(long_u)n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002529
2530 selFileHScrolls[n] = XtVaCreateManagedWidget("selFileHScroll",
2531#ifdef FEAT_GUI_NEXTAW
2532 scrollbarWidgetClass, selFileLists[n],
2533#else
2534 vim_scrollbarWidgetClass, selFileLists[n],
2535#endif
2536 XtNorientation, XtorientHorizontal,
2537 XtNx, hScrollX,
2538 XtNy, hScrollY,
2539 XtNwidth, SFhScrollWidth,
2540 XtNheight, scrollThickness,
2541 XtNborderColor, SFfore,
2542 XtNforeground, gui.scroll_fg_pixel,
2543 XtNbackground, gui.scroll_bg_pixel,
2544#ifndef FEAT_GUI_NEXTAW
2545 XtNlimitThumb, 1,
2546#endif
2547 NULL);
2548
2549 XtAddCallback(selFileHScrolls[n], XtNjumpProc,
Bram Moolenaar9d6650f2010-06-06 23:04:47 +02002550 (XtCallbackProc)SFhSliderMovedCallback,
2551 (XtPointer)(long_u)n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002552 XtAddCallback(selFileHScrolls[n], XtNscrollProc,
Bram Moolenaar6470de82013-06-27 22:36:03 +02002553 (XtCallbackProc)SFhAreaSelectedCallback, (XtPointer)(long_u)n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002554 }
2555
2556 selFileOK = XtVaCreateManagedWidget("selFileOK",
2557 commandWidgetClass, selFileForm,
2558 XtNlabel, ok,
2559 XtNresizable, True,
2560 XtNcallback, SFokSelect,
2561 XtNforeground, SFfore,
2562 XtNbackground, SFback,
2563 XtNborderColor, SFfore,
2564 XtNfromHoriz, selFileLists[0],
2565 XtNfromVert, selFileLists[0],
2566 XtNvertDistance, 30,
2567 XtNtop, XtChainTop,
2568 XtNbottom, XtChainTop,
2569 XtNleft, XtChainLeft,
2570 XtNright, XtChainLeft,
2571 NULL);
2572
2573 selFileCancel = XtVaCreateManagedWidget("selFileCancel",
2574 commandWidgetClass, selFileForm,
2575 XtNlabel, cancel,
2576 XtNresizable, True,
2577 XtNcallback, SFcancelSelect,
2578 XtNforeground, SFfore,
2579 XtNbackground, SFback,
2580 XtNborderColor, SFfore,
2581 XtNfromHoriz, selFileOK,
2582 XtNfromVert, selFileLists[0],
2583 XtNhorizDistance, 30,
2584 XtNvertDistance, 30,
2585 XtNtop, XtChainTop,
2586 XtNbottom, XtChainTop,
2587 XtNleft, XtChainLeft,
2588 XtNright, XtChainLeft,
2589 NULL);
2590
2591 XtSetMappedWhenManaged(selFile, False);
2592 XtRealizeWidget(selFile);
2593
2594 /* Add WM_DELETE_WINDOW protocol */
2595 SFwmDeleteWindow = XInternAtom(SFdisplay, "WM_DELETE_WINDOW", False);
2596 XSetWMProtocols(SFdisplay, XtWindow(selFile), &SFwmDeleteWindow, 1);
2597
2598 SFcreateGC();
2599
2600 for (n = 0; n < 3; n++)
2601 {
2602 XtAddEventHandler(selFileLists[n], ExposureMask, True,
Bram Moolenaar9d6650f2010-06-06 23:04:47 +02002603 (XtEventHandler)SFexposeList, (XtPointer)(long_u)n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002604 XtAddEventHandler(selFileLists[n], EnterWindowMask, False,
Bram Moolenaar9d6650f2010-06-06 23:04:47 +02002605 (XtEventHandler)SFenterList, (XtPointer)(long_u)n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002606 XtAddEventHandler(selFileLists[n], LeaveWindowMask, False,
Bram Moolenaar9d6650f2010-06-06 23:04:47 +02002607 (XtEventHandler)SFleaveList, (XtPointer)(long_u)n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002608 XtAddEventHandler(selFileLists[n], PointerMotionMask, False,
Bram Moolenaar9d6650f2010-06-06 23:04:47 +02002609 (XtEventHandler)SFmotionList, (XtPointer)(long_u)n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002610 XtAddEventHandler(selFileLists[n], ButtonPressMask, False,
Bram Moolenaar9d6650f2010-06-06 23:04:47 +02002611 (XtEventHandler)SFbuttonPressList, (XtPointer)(long_u)n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002612 XtAddEventHandler(selFileLists[n], ButtonReleaseMask, False,
Bram Moolenaar9d6650f2010-06-06 23:04:47 +02002613 (XtEventHandler)SFbuttonReleaseList, (XtPointer)(long_u)n);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002614 }
2615
2616 XtAddEventHandler(selFileField, KeyPressMask, False,
2617 SFmodVerifyCallback, (XtPointer)NULL);
2618
2619 SFapp = XtWidgetToApplicationContext(selFile);
2620}
2621
2622 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002623SFtextChanged(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002624{
2625#if defined(FEAT_XFONTSET) && defined(XtNinternational)
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002626 if ((unsigned long)_XawTextFormat((TextWidget)selFileField) == XawFmtWide)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002627 {
2628 wchar_t *wcbuf=(wchar_t *)SFtextBuffer;
2629
2630 if ((wcbuf[0] == L'/') || (wcbuf[0] == L'~'))
2631 {
2632 (void) wcstombs(SFcurrentPath, wcbuf, MAXPATHL);
2633 SFtextPos = XawTextGetInsertionPoint(selFileField);
2634 }
2635 else
2636 {
2637 strcpy(SFcurrentPath, SFstartDir);
2638 (void) wcstombs(SFcurrentPath + strlen(SFcurrentPath), wcbuf, MAXPATHL);
2639
2640 SFtextPos = XawTextGetInsertionPoint(selFileField) + strlen(SFstartDir);
2641 }
2642 }
2643 else
2644#endif
2645 if ((SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~'))
2646 {
2647 (void) strcpy(SFcurrentPath, SFtextBuffer);
2648 SFtextPos = XawTextGetInsertionPoint(selFileField);
2649 }
2650 else
2651 {
2652 (void) strcat(strcpy(SFcurrentPath, SFstartDir), SFtextBuffer);
2653
2654 SFtextPos = XawTextGetInsertionPoint(selFileField) + strlen(SFstartDir);
2655 }
2656
2657 if (!SFworkProcAdded)
2658 {
2659 (void) XtAppAddWorkProc(SFapp, (XtWorkProc)SFworkProc, NULL);
2660 SFworkProcAdded = 1;
2661 }
2662
2663 SFupdatePath();
2664}
2665
2666 static char *
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002667SFgetText(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002668{
2669#if defined(FEAT_XFONTSET) && defined(XtNinternational)
2670 char *buf;
2671
Bram Moolenaar4bdbbf72009-05-21 21:27:43 +00002672 if ((unsigned long)_XawTextFormat((TextWidget)selFileField) == XawFmtWide)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002673 {
2674 wchar_t *wcbuf;
2675 int mbslength;
2676
2677 XtVaGetValues(selFileField,
2678 XtNstring, &wcbuf,
2679 NULL);
2680 mbslength = wcstombs(NULL, wcbuf, 0);
2681 /* Hack: some broken wcstombs() returns zero, just get a large buffer */
2682 if (mbslength == 0 && wcbuf != NULL && wcbuf[0] != 0)
2683 mbslength = MAXPATHL;
2684 buf=(char *)XtMalloc(mbslength + 1);
2685 wcstombs(buf, wcbuf, mbslength +1);
2686 return buf;
2687 }
2688#endif
2689 return (char *)vim_strsave((char_u *)SFtextBuffer);
2690}
2691
2692 static void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002693SFprepareToReturn(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002694{
2695 SFstatus = SEL_FILE_NULL;
2696 XtRemoveGrab(selFile);
2697 XtUnmapWidget(selFile);
2698 XtRemoveTimeOut(SFdirModTimerId);
2699 if (SFchdir(SFstartDir))
2700 {
2701 EMSG(_("E614: vim_SelFile: can't return to current directory"));
2702 SFstatus = SEL_FILE_CANCEL;
2703 }
2704}
2705
2706 char *
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002707vim_SelFile(
2708 Widget toplevel,
2709 char *prompt,
2710 char *init_path,
2711 int (*show_entry)(),
Bram Moolenaar02fdaea2016-01-30 18:13:55 +01002712 int x,
2713 int y,
2714 guicolor_T fg,
2715 guicolor_T bg,
2716 guicolor_T scroll_fg,
2717 guicolor_T scroll_bg) /* The "Scrollbar" group colors */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002718{
2719 static int firstTime = 1;
2720 XEvent event;
2721 char *name_return;
2722
2723 if (prompt == NULL)
2724 prompt = _("Pathname:");
2725 SFfore = fg;
2726 SFback = bg;
2727
2728 if (mch_dirname((char_u *)SFstartDir, MAXPATHL) == FAIL)
2729 {
2730 EMSG(_("E615: vim_SelFile: can't get current directory"));
2731 return NULL;
2732 }
2733
2734 if (firstTime)
2735 {
2736 firstTime = 0;
2737 SFdisplay = XtDisplay(toplevel);
2738 SFcreateWidgets(toplevel, prompt, _("OK"), _("Cancel"));
2739 }
2740 else
2741 {
2742 XtVaSetValues(selFilePrompt, XtNlabel, prompt, NULL);
2743 XtVaSetValues(selFile, XtNtitle, prompt, NULL);
2744 SFsetColors(bg, fg, scroll_bg, scroll_fg);
2745 }
2746
2747 XtVaSetValues(selFile, XtNx, x, XtNy, y, NULL);
2748 XtMapWidget(selFile);
2749
2750 (void)strcat(SFstartDir, "/");
2751 (void)strcpy(SFcurrentDir, SFstartDir);
2752
2753 if (init_path)
2754 {
2755 if (init_path[0] == '/')
2756 {
2757 (void)strcpy(SFcurrentPath, init_path);
2758 if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir)))
2759 SFsetText(SFcurrentPath);
2760 else
2761 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
2762 }
2763 else
2764 {
2765 (void)strcat(strcpy(SFcurrentPath, SFstartDir), init_path);
2766 SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
2767 }
2768 }
2769 else
2770 (void)strcpy(SFcurrentPath, SFstartDir);
2771
2772 SFfunc = show_entry;
2773
2774 SFtextChanged();
2775
2776 XtAddGrab(selFile, True, True);
2777
2778 SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
2779 SFdirModTimer, (XtPointer) NULL);
2780
Bram Moolenaara466c992005-07-09 21:03:22 +00002781 for (;;)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002782 {
2783 XtAppNextEvent(SFapp, &event);
2784 XtDispatchEvent(&event);
2785 switch (SFstatus)
2786 {
2787 case SEL_FILE_TEXT:
2788 SFstatus = SEL_FILE_NULL;
2789 SFtextChanged();
2790 break;
2791 case SEL_FILE_OK:
2792 name_return = SFgetText();
2793 SFprepareToReturn();
2794 return name_return;
2795 case SEL_FILE_CANCEL:
2796 SFprepareToReturn();
2797 return NULL;
2798 case SEL_FILE_NULL:
2799 break;
2800 }
2801 }
2802}
2803#endif /* FEAT_BROWSE */