Mercurial > vim
comparison src/gui_at_fs.c @ 7:3fc0f57ecb91 v7.0001
updated for version 7.0001
author | vimboss |
---|---|
date | Sun, 13 Jun 2004 20:20:40 +0000 |
parents | |
children | aa550d9d2403 |
comparison
equal
deleted
inserted
replaced
6:c2daee826b8f | 7:3fc0f57ecb91 |
---|---|
1 /* 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 | |
81 typedef struct | |
82 { | |
83 int statDone; | |
84 char *real; | |
85 char *shown; | |
86 } SFEntry; | |
87 | |
88 typedef 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 | |
103 static char SFstartDir[MAXPATHL], | |
104 SFcurrentPath[MAXPATHL], | |
105 SFcurrentDir[MAXPATHL]; | |
106 | |
107 static Widget selFile, | |
108 selFileField, | |
109 selFileForm, | |
110 selFileHScroll, | |
111 selFileHScrolls[3], | |
112 selFileLists[3], | |
113 selFileOK, | |
114 selFileCancel, | |
115 selFilePrompt, | |
116 selFileVScrolls[3]; | |
117 | |
118 static Display *SFdisplay; | |
119 | |
120 static int SFcharWidth, SFcharAscent, SFcharHeight; | |
121 | |
122 static SFDir *SFdirs = NULL; | |
123 | |
124 static int SFdirEnd; | |
125 static int SFdirPtr; | |
126 | |
127 static Pixel SFfore, SFback; | |
128 | |
129 static Atom SFwmDeleteWindow; | |
130 | |
131 static XSegment SFsegs[2], SFcompletionSegs[2]; | |
132 | |
133 static XawTextPosition SFtextPos; | |
134 | |
135 static int SFupperX, SFlowerY, SFupperY; | |
136 | |
137 static int SFtextX, SFtextYoffset; | |
138 | |
139 static int SFentryWidth, SFentryHeight; | |
140 | |
141 static int SFlineToTextH = 3; | |
142 static int SFlineToTextV = 3; | |
143 | |
144 static int SFbesideText = 3; | |
145 static int SFaboveAndBelowText = 2; | |
146 | |
147 static int SFcharsPerEntry = 15; | |
148 | |
149 static int SFlistSize = 10; | |
150 | |
151 static int SFcurrentInvert[3] = { -1, -1, -1 }; | |
152 | |
153 static int SFworkProcAdded = 0; | |
154 | |
155 static XtAppContext SFapp; | |
156 | |
157 static int SFpathScrollWidth, SFvScrollHeight, SFhScrollWidth; | |
158 | |
159 #ifdef FEAT_XFONTSET | |
160 static char SFtextBuffer[MAXPATHL*sizeof(wchar_t)]; | |
161 #else | |
162 static char SFtextBuffer[MAXPATHL]; | |
163 #endif | |
164 | |
165 static int SFbuttonPressed = 0; | |
166 | |
167 static XtIntervalId SFdirModTimerId; | |
168 | |
169 static int (*SFfunc)(); | |
170 | |
171 static int SFstatus = SEL_FILE_NULL; | |
172 | |
173 /***************** static functions */ | |
174 | |
175 static void SFsetText __ARGS((char *path)); | |
176 static void SFtextChanged __ARGS((void)); | |
177 static char *SFgetText __ARGS((void)); | |
178 static void SFupdatePath __ARGS((void)); | |
179 static int SFgetDir __ARGS((SFDir *dir)); | |
180 static void SFdrawLists __ARGS((int doScroll)); | |
181 static void SFdrawList __ARGS((int n, int doScroll)); | |
182 static void SFclearList __ARGS((int n, int doScroll)); | |
183 static void SFbuttonPressList __ARGS((Widget w, int n, XButtonPressedEvent *event)); | |
184 static void SFbuttonReleaseList __ARGS((Widget w, int n, XButtonReleasedEvent *event)); | |
185 static void SFdirModTimer __ARGS((XtPointer cl, XtIntervalId *id)); | |
186 static char SFstatChar __ARGS((struct stat *statBuf)); | |
187 static void SFdrawStrings __ARGS((Window w, SFDir *dir, int from, int to)); | |
188 static int SFnewInvertEntry __ARGS((int n, XMotionEvent *event)); | |
189 static void SFinvertEntry __ARGS((int n)); | |
190 static void SFenterList __ARGS((Widget w, int n, XEnterWindowEvent *event)); | |
191 static void SFleaveList __ARGS((Widget w, int n, XEvent *event)); | |
192 static void SFmotionList __ARGS((Widget w, int n, XMotionEvent *event)); | |
193 static void SFvFloatSliderMovedCallback __ARGS((Widget w, XtPointer n, XtPointer fnew)); | |
194 static void SFvSliderMovedCallback __ARGS((Widget w, int n, int nw)); | |
195 static void SFvAreaSelectedCallback __ARGS((Widget w, XtPointer n, XtPointer pnew)); | |
196 static void SFhSliderMovedCallback __ARGS((Widget w, XtPointer n, XtPointer nw)); | |
197 static void SFhAreaSelectedCallback __ARGS((Widget w, XtPointer n, XtPointer pnew)); | |
198 static void SFpathSliderMovedCallback __ARGS((Widget w, XtPointer client_data, XtPointer nw)); | |
199 static void SFpathAreaSelectedCallback __ARGS((Widget w, XtPointer client_data, XtPointer pnew)); | |
200 static Boolean SFworkProc __ARGS((void)); | |
201 static int SFcompareEntries __ARGS((const void *p, const void *q)); | |
202 static void SFprepareToReturn __ARGS((void)); | |
203 static void SFcreateWidgets __ARGS((Widget toplevel, char *prompt, char *ok, char *cancel)); | |
204 static void SFsetColors __ARGS((guicolor_T bg, guicolor_T fg, guicolor_T scroll_bg, guicolor_T scrollfg)); | |
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 | |
224 typedef struct | |
225 { | |
226 char *name; | |
227 char *dir; | |
228 } SFLogin; | |
229 | |
230 static int SFdoNotTouchDirPtr = 0; | |
231 | |
232 static int SFdoNotTouchVorigin = 0; | |
233 | |
234 static SFDir SFrootDir, SFhomeDir; | |
235 | |
236 static SFLogin *SFlogins; | |
237 | |
238 static int SFtwiddle = 0; | |
239 | |
240 static int SFchdir __ARGS((char *path)); | |
241 | |
242 static int | |
243 SFchdir(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 | |
260 static void SFfree __ARGS((int i)); | |
261 | |
262 static void | |
263 SFfree(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 | |
284 static void SFstrdup __ARGS((char **s1, char *s2)); | |
285 | |
286 static void | |
287 SFstrdup(s1, s2) | |
288 char **s1; | |
289 char *s2; | |
290 { | |
291 *s1 = strcpy(XtMalloc((unsigned)(strlen(s2) + 1)), s2); | |
292 } | |
293 | |
294 static void SFunreadableDir __ARGS((SFDir *dir)); | |
295 | |
296 static void | |
297 SFunreadableDir(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 | |
310 static void SFreplaceText __ARGS((SFDir *dir, char *str)); | |
311 | |
312 static void | |
313 SFreplaceText(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 | |
333 static void SFexpand __ARGS((char *str)); | |
334 | |
335 static void | |
336 SFexpand(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 | |
390 static int SFfindFile __ARGS((SFDir *dir, char *str)); | |
391 | |
392 static int | |
393 SFfindFile(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 | |
491 static void SFunselect __ARGS((void)); | |
492 | |
493 static void | |
494 SFunselect() | |
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 | |
505 static int SFcompareLogins __ARGS((const void *p, const void *q)); | |
506 | |
507 static int | |
508 SFcompareLogins(p, q) | |
509 const void *p, *q; | |
510 { | |
511 return strcmp(((SFLogin *)p)->name, ((SFLogin *)q)->name); | |
512 } | |
513 | |
514 static void SFgetHomeDirs __ARGS((void)); | |
515 | |
516 static void | |
517 SFgetHomeDirs() | |
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 | |
582 static int SFfindHomeDir __ARGS((char *begin, char *end)); | |
583 | |
584 static int | |
585 SFfindHomeDir(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 | |
616 SFupdatePath() | |
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 | |
810 WcsLen(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 | |
821 SFsetText(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 | |
832 if (_XawTextFormat((TextWidget)selFileField) == XawFmtWide) | |
833 { | |
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 | |
854 /* ARGSUSED */ | |
855 static void | |
856 SFbuttonPressList(w, n, event) | |
857 Widget w; | |
858 int n; | |
859 XButtonPressedEvent *event; | |
860 { | |
861 SFbuttonPressed = 1; | |
862 } | |
863 | |
864 /* ARGSUSED */ | |
865 static void | |
866 SFbuttonReleaseList(w, n, event) | |
867 Widget w; | |
868 int n; | |
869 XButtonReleasedEvent *event; | |
870 { | |
871 SFDir *dir; | |
872 | |
873 SFbuttonPressed = 0; | |
874 | |
875 if (SFcurrentInvert[n] != -1) | |
876 { | |
877 if (n < 2) | |
878 SFdoNotTouchDirPtr = 1; | |
879 SFdoNotTouchVorigin = 1; | |
880 dir = &(SFdirs[SFdirPtr + n]); | |
881 SFreplaceText(dir, | |
882 dir->entries[dir->vOrigin + SFcurrentInvert[n]].shown); | |
883 SFmotionList(w, n, (XMotionEvent *) event); | |
884 } | |
885 } | |
886 | |
887 static int SFcheckDir __ARGS((int n, SFDir *dir)); | |
888 | |
889 static int | |
890 SFcheckDir(n, dir) | |
891 int n; | |
892 SFDir *dir; | |
893 { | |
894 struct stat statBuf; | |
895 int i; | |
896 | |
897 if ((!mch_stat(".", &statBuf)) && (statBuf.st_mtime != dir->mtime)) | |
898 { | |
899 /* | |
900 * If the pointer is currently in the window that we are about | |
901 * to update, we must warp it to prevent the user from | |
902 * accidentally selecting the wrong file. | |
903 */ | |
904 if (SFcurrentInvert[n] != -1) | |
905 { | |
906 XWarpPointer( | |
907 SFdisplay, | |
908 None, | |
909 XtWindow(selFileLists[n]), | |
910 0, | |
911 0, | |
912 0, | |
913 0, | |
914 0, | |
915 0); | |
916 } | |
917 | |
918 for (i = dir->nEntries - 1; i >= 0; i--) | |
919 { | |
920 if (dir->entries[i].shown != dir->entries[i].real) | |
921 XtFree(dir->entries[i].shown); | |
922 XtFree(dir->entries[i].real); | |
923 } | |
924 XtFree((char *) dir->entries); | |
925 if (SFgetDir(dir)) | |
926 SFunreadableDir(dir); | |
927 if (dir->vOrigin > dir->nEntries - SFlistSize) | |
928 dir->vOrigin = dir->nEntries - SFlistSize; | |
929 if (dir->vOrigin < 0) | |
930 dir->vOrigin = 0; | |
931 if (dir->hOrigin > dir->nChars - SFcharsPerEntry) | |
932 dir->hOrigin = dir->nChars - SFcharsPerEntry; | |
933 if (dir->hOrigin < 0) | |
934 dir->hOrigin = 0; | |
935 dir->beginSelection = -1; | |
936 dir->endSelection = -1; | |
937 SFdoNotTouchVorigin = 1; | |
938 if ((dir + 1)->dir) | |
939 (void) SFfindFile(dir, (dir + 1)->dir); | |
940 else | |
941 (void) SFfindFile(dir, dir->path); | |
942 | |
943 if (!SFworkProcAdded) | |
944 { | |
945 (void) XtAppAddWorkProc(SFapp, (XtWorkProc)SFworkProc, NULL); | |
946 SFworkProcAdded = 1; | |
947 } | |
948 return 1; | |
949 } | |
950 return 0; | |
951 } | |
952 | |
953 static int SFcheckFiles __ARGS((SFDir *dir)); | |
954 | |
955 static int | |
956 SFcheckFiles(dir) | |
957 SFDir *dir; | |
958 { | |
959 int from, to; | |
960 int result; | |
961 char oldc, newc; | |
962 int i; | |
963 char *str; | |
964 int last; | |
965 struct stat statBuf; | |
966 | |
967 result = 0; | |
968 | |
969 from = dir->vOrigin; | |
970 to = dir->vOrigin + SFlistSize; | |
971 if (to > dir->nEntries) | |
972 to = dir->nEntries; | |
973 | |
974 for (i = from; i < to; i++) | |
975 { | |
976 str = dir->entries[i].real; | |
977 last = strlen(str) - 1; | |
978 oldc = str[last]; | |
979 str[last] = 0; | |
980 if (mch_stat(str, &statBuf)) | |
981 newc = ' '; | |
982 else | |
983 newc = SFstatChar(&statBuf); | |
984 str[last] = newc; | |
985 if (newc != oldc) | |
986 result = 1; | |
987 } | |
988 | |
989 return result; | |
990 } | |
991 | |
992 /* ARGSUSED */ | |
993 static void | |
994 SFdirModTimer(cl, id) | |
995 XtPointer cl; | |
996 XtIntervalId *id; | |
997 { | |
998 static int n = -1; | |
999 static int f = 0; | |
1000 char save; | |
1001 SFDir *dir; | |
1002 | |
1003 if ((!SFtwiddle) && (SFdirPtr < SFdirEnd)) | |
1004 { | |
1005 n++; | |
1006 if ((n > 2) || (SFdirPtr + n >= SFdirEnd)) | |
1007 { | |
1008 n = 0; | |
1009 f++; | |
1010 if ((f > 2) || (SFdirPtr + f >= SFdirEnd)) | |
1011 f = 0; | |
1012 } | |
1013 dir = &(SFdirs[SFdirPtr + n]); | |
1014 save = *(dir->path); | |
1015 *(dir->path) = 0; | |
1016 if (SFchdir(SFcurrentPath)) | |
1017 { | |
1018 *(dir->path) = save; | |
1019 | |
1020 /* | |
1021 * force a re-read | |
1022 */ | |
1023 *(dir->dir) = 0; | |
1024 | |
1025 SFupdatePath(); | |
1026 } | |
1027 else | |
1028 { | |
1029 *(dir->path) = save; | |
1030 if (SFcheckDir(n, dir) || ((f == n) && SFcheckFiles(dir))) | |
1031 SFdrawList(n, SF_DO_SCROLL); | |
1032 } | |
1033 } | |
1034 | |
1035 SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000, | |
1036 SFdirModTimer, (XtPointer) NULL); | |
1037 } | |
1038 | |
1039 /* Return a single character describing what kind of file STATBUF is. */ | |
1040 | |
1041 static char | |
1042 SFstatChar(statBuf) | |
1043 struct stat *statBuf; | |
1044 { | |
1045 if (S_ISDIR (statBuf->st_mode)) | |
1046 return '/'; | |
1047 if (S_ISREG (statBuf->st_mode)) | |
1048 return S_ISXXX (statBuf->st_mode) ? '*' : ' '; | |
1049 #ifdef S_ISSOCK | |
1050 if (S_ISSOCK (statBuf->st_mode)) | |
1051 return '='; | |
1052 #endif /* S_ISSOCK */ | |
1053 return ' '; | |
1054 } | |
1055 | |
1056 /***************** Draw.c */ | |
1057 | |
1058 #ifdef FEAT_GUI_NEXTAW | |
1059 # include <X11/neXtaw/Cardinals.h> | |
1060 #else | |
1061 # include <X11/Xaw/Cardinals.h> | |
1062 #endif | |
1063 | |
1064 #ifdef FEAT_XFONTSET | |
1065 # define SF_DEFAULT_FONT "-misc-fixed-medium-r-normal--14-*" | |
1066 #else | |
1067 # define SF_DEFAULT_FONT "9x15" | |
1068 #endif | |
1069 | |
1070 #ifdef ABS | |
1071 # undef ABS | |
1072 #endif | |
1073 #define ABS(x) (((x) < 0) ? (-(x)) : (x)) | |
1074 | |
1075 typedef struct | |
1076 { | |
1077 char *fontname; | |
1078 } TextData; | |
1079 | |
1080 static GC SFlineGC, SFscrollGC, SFinvertGC, SFtextGC; | |
1081 | |
1082 static XtResource textResources[] = | |
1083 { | |
1084 #ifdef FEAT_XFONTSET | |
1085 {XtNfontSet, XtCFontSet, XtRString, sizeof (char *), | |
1086 XtOffsetOf(TextData, fontname), XtRString, SF_DEFAULT_FONT}, | |
1087 #else | |
1088 {XtNfont, XtCFont, XtRString, sizeof (char *), | |
1089 XtOffsetOf(TextData, fontname), XtRString, SF_DEFAULT_FONT}, | |
1090 #endif | |
1091 }; | |
1092 | |
1093 #ifdef FEAT_XFONTSET | |
1094 static XFontSet SFfont; | |
1095 #else | |
1096 static XFontStruct *SFfont; | |
1097 #endif | |
1098 | |
1099 static int SFcurrentListY; | |
1100 | |
1101 static XtIntervalId SFscrollTimerId; | |
1102 | |
1103 static void SFinitFont __ARGS((void)); | |
1104 | |
1105 static void | |
1106 SFinitFont() | |
1107 { | |
1108 TextData *data; | |
1109 #ifdef FEAT_XFONTSET | |
1110 XFontSetExtents *extents; | |
1111 char **missing, *def_str; | |
1112 int num_missing; | |
1113 #endif | |
1114 | |
1115 data = XtNew(TextData); | |
1116 | |
1117 XtGetApplicationResources(selFileForm, (XtPointer) data, textResources, | |
1118 XtNumber(textResources), (Arg *) NULL, ZERO); | |
1119 | |
1120 #ifdef FEAT_XFONTSET | |
1121 SFfont = XCreateFontSet(SFdisplay, data->fontname, | |
1122 &missing, &num_missing, &def_str); | |
1123 #else | |
1124 SFfont = XLoadQueryFont(SFdisplay, data->fontname); | |
1125 #endif | |
1126 if (!SFfont) | |
1127 { | |
1128 #ifdef FEAT_XFONTSET | |
1129 SFfont = XCreateFontSet(SFdisplay, SF_DEFAULT_FONT, | |
1130 &missing, &num_missing, &def_str); | |
1131 #else | |
1132 SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT); | |
1133 #endif | |
1134 if (!SFfont) | |
1135 { | |
1136 EMSG2(_("E616: vim_SelFile: can't get font %s"), SF_DEFAULT_FONT); | |
1137 SFstatus = SEL_FILE_CANCEL; | |
1138 return; | |
1139 } | |
1140 } | |
1141 | |
1142 #ifdef FEAT_XFONTSET | |
1143 extents = XExtentsOfFontSet(SFfont); | |
1144 SFcharWidth = extents->max_logical_extent.width; | |
1145 SFcharAscent = -extents->max_logical_extent.y; | |
1146 SFcharHeight = extents->max_logical_extent.height; | |
1147 #else | |
1148 SFcharWidth = (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2; | |
1149 SFcharAscent = SFfont->max_bounds.ascent; | |
1150 SFcharHeight = SFcharAscent + SFfont->max_bounds.descent; | |
1151 #endif | |
1152 } | |
1153 | |
1154 static void SFcreateGC __ARGS((void)); | |
1155 | |
1156 static void | |
1157 SFcreateGC() | |
1158 { | |
1159 XGCValues gcValues; | |
1160 XRectangle rectangles[1]; | |
1161 | |
1162 gcValues.foreground = SFfore; | |
1163 | |
1164 SFlineGC = XtGetGC( | |
1165 selFileLists[0], | |
1166 (XtGCMask)GCForeground, | |
1167 &gcValues); | |
1168 | |
1169 SFscrollGC = XtGetGC( | |
1170 selFileLists[0], | |
1171 (XtGCMask)0, | |
1172 &gcValues); | |
1173 | |
1174 gcValues.function = GXxor; | |
1175 gcValues.foreground = SFfore ^ SFback; | |
1176 gcValues.background = SFfore ^ SFback; | |
1177 | |
1178 SFinvertGC = XtGetGC( | |
1179 selFileLists[0], | |
1180 (XtGCMask)GCFunction | GCForeground | GCBackground, | |
1181 &gcValues); | |
1182 | |
1183 gcValues.foreground = SFfore; | |
1184 gcValues.background = SFback; | |
1185 #ifndef FEAT_XFONTSET | |
1186 gcValues.font = SFfont->fid; | |
1187 #endif | |
1188 | |
1189 SFtextGC = XCreateGC( | |
1190 SFdisplay, | |
1191 XtWindow(selFileLists[0]), | |
1192 #ifdef FEAT_XFONTSET | |
1193 (unsigned long)GCForeground | GCBackground, | |
1194 #else | |
1195 (unsigned long)GCForeground | GCBackground | GCFont, | |
1196 #endif | |
1197 &gcValues); | |
1198 | |
1199 rectangles[0].x = SFlineToTextH + SFbesideText; | |
1200 rectangles[0].y = 0; | |
1201 rectangles[0].width = SFcharsPerEntry * SFcharWidth; | |
1202 rectangles[0].height = SFupperY + 1; | |
1203 | |
1204 XSetClipRectangles( | |
1205 SFdisplay, | |
1206 SFtextGC, | |
1207 0, | |
1208 0, | |
1209 rectangles, | |
1210 1, | |
1211 Unsorted); | |
1212 } | |
1213 | |
1214 static void | |
1215 SFclearList(n, doScroll) | |
1216 int n; | |
1217 int doScroll; | |
1218 { | |
1219 SFDir *dir; | |
1220 | |
1221 SFcurrentInvert[n] = -1; | |
1222 | |
1223 XClearWindow(SFdisplay, XtWindow(selFileLists[n])); | |
1224 | |
1225 XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs, 2); | |
1226 | |
1227 if (doScroll) | |
1228 { | |
1229 dir = &(SFdirs[SFdirPtr + n]); | |
1230 | |
1231 if ((SFdirPtr + n < SFdirEnd) && dir->nEntries && dir->nChars) | |
1232 { | |
1233 #ifdef FEAT_GUI_NEXTAW | |
1234 XawScrollbarSetThumb( | |
1235 selFileVScrolls[n], | |
1236 (float) (((double) dir->vOrigin) / | |
1237 dir->nEntries), | |
1238 (float) (((double) ((dir->nEntries < SFlistSize) | |
1239 ? dir->nEntries : SFlistSize)) / | |
1240 dir->nEntries)); | |
1241 #else | |
1242 vim_XawScrollbarSetThumb( | |
1243 selFileVScrolls[n], | |
1244 (float) (((double) dir->vOrigin) / | |
1245 dir->nEntries), | |
1246 (float) (((double) ((dir->nEntries < SFlistSize) | |
1247 ? dir->nEntries : SFlistSize)) / | |
1248 dir->nEntries), | |
1249 (double)dir->nEntries); | |
1250 #endif | |
1251 | |
1252 #ifdef FEAT_GUI_NEXTAW | |
1253 XawScrollbarSetThumb( | |
1254 selFileHScrolls[n], | |
1255 (float) (((double) dir->hOrigin) / dir->nChars), | |
1256 (float) (((double) ((dir->nChars < | |
1257 SFcharsPerEntry) ? dir->nChars : | |
1258 SFcharsPerEntry)) / dir->nChars)); | |
1259 #else | |
1260 vim_XawScrollbarSetThumb( | |
1261 selFileHScrolls[n], | |
1262 (float) (((double) dir->hOrigin) / dir->nChars), | |
1263 (float) (((double) ((dir->nChars < | |
1264 SFcharsPerEntry) ? dir->nChars : | |
1265 SFcharsPerEntry)) / dir->nChars), | |
1266 (double)dir->nChars); | |
1267 #endif | |
1268 } | |
1269 else | |
1270 { | |
1271 #ifdef FEAT_GUI_NEXTAW | |
1272 XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0, | |
1273 (float) 1.0); | |
1274 #else | |
1275 vim_XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0, | |
1276 (float) 1.0, 1.0); | |
1277 #endif | |
1278 #ifdef FEAT_GUI_NEXTAW | |
1279 XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0, | |
1280 (float) 1.0); | |
1281 #else | |
1282 vim_XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0, | |
1283 (float) 1.0, 1.0); | |
1284 #endif | |
1285 } | |
1286 } | |
1287 } | |
1288 | |
1289 static void SFdeleteEntry __ARGS((SFDir *dir, SFEntry *entry)); | |
1290 | |
1291 static void | |
1292 SFdeleteEntry(dir, entry) | |
1293 SFDir *dir; | |
1294 SFEntry *entry; | |
1295 { | |
1296 SFEntry *e; | |
1297 SFEntry *end; | |
1298 int n; | |
1299 int idx; | |
1300 | |
1301 idx = entry - dir->entries; | |
1302 | |
1303 if (idx < dir->beginSelection) | |
1304 dir->beginSelection--; | |
1305 if (idx <= dir->endSelection) | |
1306 dir->endSelection--; | |
1307 if (dir->beginSelection > dir->endSelection) | |
1308 dir->beginSelection = dir->endSelection = -1; | |
1309 | |
1310 if (idx < dir->vOrigin) | |
1311 dir->vOrigin--; | |
1312 | |
1313 XtFree(entry->real); | |
1314 | |
1315 end = &(dir->entries[dir->nEntries - 1]); | |
1316 | |
1317 for (e = entry; e < end; e++) | |
1318 *e = *(e + 1); | |
1319 | |
1320 if (!(--dir->nEntries)) | |
1321 return; | |
1322 | |
1323 n = dir - &(SFdirs[SFdirPtr]); | |
1324 if ((n < 0) || (n > 2)) | |
1325 return; | |
1326 | |
1327 #ifdef FEAT_GUI_NEXTAW | |
1328 XawScrollbarSetThumb( | |
1329 selFileVScrolls[n], | |
1330 (float) (((double) dir->vOrigin) / dir->nEntries), | |
1331 (float) (((double) ((dir->nEntries < SFlistSize) ? | |
1332 dir->nEntries : SFlistSize)) / dir->nEntries)); | |
1333 #else | |
1334 vim_XawScrollbarSetThumb( | |
1335 selFileVScrolls[n], | |
1336 (float) (((double) dir->vOrigin) / dir->nEntries), | |
1337 (float) (((double) ((dir->nEntries < SFlistSize) ? | |
1338 dir->nEntries : SFlistSize)) / dir->nEntries), | |
1339 (double)dir->nEntries); | |
1340 #endif | |
1341 } | |
1342 | |
1343 static void SFwriteStatChar __ARGS((char *name, int last, struct stat *statBuf)); | |
1344 | |
1345 static void | |
1346 SFwriteStatChar(name, last, statBuf) | |
1347 char *name; | |
1348 int last; | |
1349 struct stat *statBuf; | |
1350 { | |
1351 name[last] = SFstatChar(statBuf); | |
1352 } | |
1353 | |
1354 static int SFstatAndCheck __ARGS((SFDir *dir, SFEntry *entry)); | |
1355 | |
1356 static int | |
1357 SFstatAndCheck(dir, entry) | |
1358 SFDir *dir; | |
1359 SFEntry *entry; | |
1360 { | |
1361 struct stat statBuf; | |
1362 char save; | |
1363 int last; | |
1364 | |
1365 /* | |
1366 * must be restored before returning | |
1367 */ | |
1368 save = *(dir->path); | |
1369 *(dir->path) = 0; | |
1370 | |
1371 if (!SFchdir(SFcurrentPath)) | |
1372 { | |
1373 last = strlen(entry->real) - 1; | |
1374 entry->real[last] = 0; | |
1375 entry->statDone = 1; | |
1376 if ((!mch_stat(entry->real, &statBuf)) | |
1377 #ifdef S_IFLNK | |
1378 || (!mch_lstat(entry->real, &statBuf)) | |
1379 #endif | |
1380 ) | |
1381 { | |
1382 if (SFfunc) | |
1383 { | |
1384 char *shown; | |
1385 | |
1386 shown = NULL; | |
1387 if (SFfunc(entry->real, &shown, &statBuf)) | |
1388 { | |
1389 if (shown) | |
1390 { | |
1391 int len; | |
1392 | |
1393 len = strlen(shown); | |
1394 entry->shown = XtMalloc((unsigned) (len + 2)); | |
1395 (void) strcpy(entry->shown, shown); | |
1396 SFwriteStatChar(entry->shown, len, &statBuf); | |
1397 entry->shown[len + 1] = 0; | |
1398 } | |
1399 } | |
1400 else | |
1401 { | |
1402 SFdeleteEntry(dir, entry); | |
1403 | |
1404 *(dir->path) = save; | |
1405 return 1; | |
1406 } | |
1407 } | |
1408 SFwriteStatChar(entry->real, last, &statBuf); | |
1409 } | |
1410 else | |
1411 entry->real[last] = ' '; | |
1412 } | |
1413 | |
1414 *(dir->path) = save; | |
1415 return 0; | |
1416 } | |
1417 | |
1418 | |
1419 static void | |
1420 SFdrawStrings(w, dir, from, to) | |
1421 Window w; | |
1422 SFDir *dir; | |
1423 int from; | |
1424 int to; | |
1425 { | |
1426 int i; | |
1427 SFEntry *entry; | |
1428 int x; | |
1429 | |
1430 x = SFtextX - dir->hOrigin * SFcharWidth; | |
1431 | |
1432 if (dir->vOrigin + to >= dir->nEntries) | |
1433 to = dir->nEntries - dir->vOrigin - 1; | |
1434 for (i = from; i <= to; i++) | |
1435 { | |
1436 entry = &(dir->entries[dir->vOrigin + i]); | |
1437 if (!(entry->statDone)) | |
1438 { | |
1439 if (SFstatAndCheck(dir, entry)) | |
1440 { | |
1441 if (dir->vOrigin + to >= dir->nEntries) | |
1442 to = dir->nEntries - dir->vOrigin - 1; | |
1443 i--; | |
1444 continue; | |
1445 } | |
1446 } | |
1447 #ifdef FEAT_XFONTSET | |
1448 XmbDrawImageString( | |
1449 SFdisplay, | |
1450 w, | |
1451 SFfont, | |
1452 SFtextGC, | |
1453 x, | |
1454 SFtextYoffset + i * SFentryHeight, | |
1455 entry->shown, | |
1456 strlen(entry->shown)); | |
1457 #else | |
1458 XDrawImageString( | |
1459 SFdisplay, | |
1460 w, | |
1461 SFtextGC, | |
1462 x, | |
1463 SFtextYoffset + i * SFentryHeight, | |
1464 entry->shown, | |
1465 strlen(entry->shown)); | |
1466 #endif | |
1467 if (dir->vOrigin + i == dir->beginSelection) | |
1468 { | |
1469 XDrawLine( | |
1470 SFdisplay, | |
1471 w, | |
1472 SFlineGC, | |
1473 SFlineToTextH + 1, | |
1474 SFlowerY + i * SFentryHeight, | |
1475 SFlineToTextH + SFentryWidth - 2, | |
1476 SFlowerY + i * SFentryHeight); | |
1477 } | |
1478 if ((dir->vOrigin + i >= dir->beginSelection) && | |
1479 (dir->vOrigin + i <= dir->endSelection)) | |
1480 { | |
1481 SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 = | |
1482 SFlowerY + i * SFentryHeight; | |
1483 SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 = | |
1484 SFlowerY + (i + 1) * SFentryHeight - 1; | |
1485 XDrawSegments( | |
1486 SFdisplay, | |
1487 w, | |
1488 SFlineGC, | |
1489 SFcompletionSegs, | |
1490 2); | |
1491 } | |
1492 if (dir->vOrigin + i == dir->endSelection) | |
1493 { | |
1494 XDrawLine( | |
1495 SFdisplay, | |
1496 w, | |
1497 SFlineGC, | |
1498 SFlineToTextH + 1, | |
1499 SFlowerY + (i + 1) * SFentryHeight - 1, | |
1500 SFlineToTextH + SFentryWidth - 2, | |
1501 SFlowerY + (i + 1) * SFentryHeight - 1); | |
1502 } | |
1503 } | |
1504 } | |
1505 | |
1506 static void | |
1507 SFdrawList(n, doScroll) | |
1508 int n; | |
1509 int doScroll; | |
1510 { | |
1511 SFDir *dir; | |
1512 Window w; | |
1513 | |
1514 SFclearList(n, doScroll); | |
1515 | |
1516 if (SFdirPtr + n < SFdirEnd) | |
1517 { | |
1518 dir = &(SFdirs[SFdirPtr + n]); | |
1519 w = XtWindow(selFileLists[n]); | |
1520 #ifdef FEAT_XFONTSET | |
1521 XmbDrawImageString( | |
1522 SFdisplay, | |
1523 w, | |
1524 SFfont, | |
1525 SFtextGC, | |
1526 SFtextX - dir->hOrigin * SFcharWidth, | |
1527 SFlineToTextV + SFaboveAndBelowText + SFcharAscent, | |
1528 dir->dir, | |
1529 strlen(dir->dir)); | |
1530 #else | |
1531 XDrawImageString( | |
1532 SFdisplay, | |
1533 w, | |
1534 SFtextGC, | |
1535 SFtextX - dir->hOrigin * SFcharWidth, | |
1536 SFlineToTextV + SFaboveAndBelowText + SFcharAscent, | |
1537 dir->dir, | |
1538 strlen(dir->dir)); | |
1539 #endif | |
1540 SFdrawStrings(w, dir, 0, SFlistSize - 1); | |
1541 } | |
1542 } | |
1543 | |
1544 static void | |
1545 SFdrawLists(doScroll) | |
1546 int doScroll; | |
1547 { | |
1548 int i; | |
1549 | |
1550 for (i = 0; i < 3; i++) | |
1551 SFdrawList(i, doScroll); | |
1552 } | |
1553 | |
1554 static void | |
1555 SFinvertEntry(n) | |
1556 int n; | |
1557 { | |
1558 XFillRectangle( | |
1559 SFdisplay, | |
1560 XtWindow(selFileLists[n]), | |
1561 SFinvertGC, | |
1562 SFlineToTextH, | |
1563 SFcurrentInvert[n] * SFentryHeight + SFlowerY, | |
1564 SFentryWidth, | |
1565 SFentryHeight); | |
1566 } | |
1567 | |
1568 static unsigned long SFscrollTimerInterval __ARGS((void)); | |
1569 | |
1570 static unsigned long | |
1571 SFscrollTimerInterval() | |
1572 { | |
1573 static int maxVal = 200; | |
1574 static int varyDist = 50; | |
1575 static int minDist = 50; | |
1576 int t; | |
1577 int dist; | |
1578 | |
1579 if (SFcurrentListY < SFlowerY) | |
1580 dist = SFlowerY - SFcurrentListY; | |
1581 else if (SFcurrentListY > SFupperY) | |
1582 dist = SFcurrentListY - SFupperY; | |
1583 else | |
1584 return (unsigned long) 1; | |
1585 | |
1586 t = maxVal - ((maxVal / varyDist) * (dist - minDist)); | |
1587 | |
1588 if (t < 1) | |
1589 t = 1; | |
1590 | |
1591 if (t > maxVal) | |
1592 t = maxVal; | |
1593 | |
1594 return (unsigned long)t; | |
1595 } | |
1596 | |
1597 static void SFscrollTimer __ARGS((XtPointer p, XtIntervalId *id)); | |
1598 | |
1599 /* ARGSUSED */ | |
1600 static void | |
1601 SFscrollTimer(p, id) | |
1602 XtPointer p; | |
1603 XtIntervalId *id; | |
1604 { | |
1605 SFDir *dir; | |
1606 int save; | |
1607 int n; | |
1608 | |
1609 n = (long)p; | |
1610 | |
1611 dir = &(SFdirs[SFdirPtr + n]); | |
1612 save = dir->vOrigin; | |
1613 | |
1614 if (SFcurrentListY < SFlowerY) | |
1615 { | |
1616 if (dir->vOrigin > 0) | |
1617 SFvSliderMovedCallback(selFileVScrolls[n], n, dir->vOrigin - 1); | |
1618 } | |
1619 else if (SFcurrentListY > SFupperY) | |
1620 { | |
1621 if (dir->vOrigin < dir->nEntries - SFlistSize) | |
1622 SFvSliderMovedCallback(selFileVScrolls[n], n, dir->vOrigin + 1); | |
1623 } | |
1624 | |
1625 if (dir->vOrigin != save) | |
1626 { | |
1627 if (dir->nEntries) | |
1628 { | |
1629 #ifdef FEAT_GUI_NEXTAW | |
1630 XawScrollbarSetThumb( | |
1631 selFileVScrolls[n], | |
1632 (float) (((double) dir->vOrigin) / dir->nEntries), | |
1633 (float) (((double) ((dir->nEntries < SFlistSize) ? | |
1634 dir->nEntries : SFlistSize)) / dir->nEntries)); | |
1635 #else | |
1636 vim_XawScrollbarSetThumb( | |
1637 selFileVScrolls[n], | |
1638 (float) (((double) dir->vOrigin) / dir->nEntries), | |
1639 (float) (((double) ((dir->nEntries < SFlistSize) ? | |
1640 dir->nEntries : SFlistSize)) / dir->nEntries), | |
1641 (double)dir->nEntries); | |
1642 #endif | |
1643 } | |
1644 } | |
1645 | |
1646 if (SFbuttonPressed) | |
1647 SFscrollTimerId = XtAppAddTimeOut(SFapp, | |
1648 SFscrollTimerInterval(), SFscrollTimer, (XtPointer) n); | |
1649 } | |
1650 | |
1651 static int | |
1652 SFnewInvertEntry(n, event) | |
1653 int n; | |
1654 XMotionEvent *event; | |
1655 { | |
1656 int x, y; | |
1657 int nw; | |
1658 static int SFscrollTimerAdded = 0; | |
1659 | |
1660 x = event->x; | |
1661 y = event->y; | |
1662 | |
1663 if (SFdirPtr + n >= SFdirEnd) | |
1664 return -1; | |
1665 | |
1666 if ((x >= 0) && (x <= SFupperX) && (y >= SFlowerY) && (y <= SFupperY)) | |
1667 { | |
1668 SFDir *dir = &(SFdirs[SFdirPtr + n]); | |
1669 | |
1670 if (SFscrollTimerAdded) | |
1671 { | |
1672 SFscrollTimerAdded = 0; | |
1673 XtRemoveTimeOut(SFscrollTimerId); | |
1674 } | |
1675 | |
1676 nw = (y - SFlowerY) / SFentryHeight; | |
1677 if (dir->vOrigin + nw >= dir->nEntries) | |
1678 return -1; | |
1679 return nw; | |
1680 } | |
1681 else | |
1682 { | |
1683 if (SFbuttonPressed) | |
1684 { | |
1685 SFcurrentListY = y; | |
1686 if (!SFscrollTimerAdded) | |
1687 { | |
1688 SFscrollTimerAdded = 1; | |
1689 SFscrollTimerId = XtAppAddTimeOut(SFapp, | |
1690 SFscrollTimerInterval(), SFscrollTimer, | |
1691 (XtPointer) n); | |
1692 } | |
1693 } | |
1694 return -1; | |
1695 } | |
1696 } | |
1697 | |
1698 /* ARGSUSED */ | |
1699 static void | |
1700 SFenterList(w, n, event) | |
1701 Widget w; | |
1702 int n; | |
1703 XEnterWindowEvent *event; | |
1704 { | |
1705 int nw; | |
1706 | |
1707 /* sanity */ | |
1708 if (SFcurrentInvert[n] != -1) | |
1709 { | |
1710 SFinvertEntry(n); | |
1711 SFcurrentInvert[n] = -1; | |
1712 } | |
1713 | |
1714 nw = SFnewInvertEntry(n, (XMotionEvent *) event); | |
1715 if (nw != -1) | |
1716 { | |
1717 SFcurrentInvert[n] = nw; | |
1718 SFinvertEntry(n); | |
1719 } | |
1720 } | |
1721 | |
1722 /* ARGSUSED */ | |
1723 static void | |
1724 SFleaveList(w, n, event) | |
1725 Widget w; | |
1726 int n; | |
1727 XEvent *event; | |
1728 { | |
1729 if (SFcurrentInvert[n] != -1) | |
1730 { | |
1731 SFinvertEntry(n); | |
1732 SFcurrentInvert[n] = -1; | |
1733 } | |
1734 } | |
1735 | |
1736 /* ARGSUSED */ | |
1737 static void | |
1738 SFmotionList(w, n, event) | |
1739 Widget w; | |
1740 int n; | |
1741 XMotionEvent *event; | |
1742 { | |
1743 int nw; | |
1744 | |
1745 nw = SFnewInvertEntry(n, event); | |
1746 | |
1747 if (nw != SFcurrentInvert[n]) | |
1748 { | |
1749 if (SFcurrentInvert[n] != -1) | |
1750 SFinvertEntry(n); | |
1751 SFcurrentInvert[n] = nw; | |
1752 if (nw != -1) | |
1753 SFinvertEntry(n); | |
1754 } | |
1755 } | |
1756 | |
1757 /* ARGSUSED */ | |
1758 static void | |
1759 SFvFloatSliderMovedCallback(w, n, fnew) | |
1760 Widget w; | |
1761 XtPointer n; | |
1762 XtPointer fnew; | |
1763 { | |
1764 int nw; | |
1765 | |
1766 nw = (*(float *)fnew) * SFdirs[SFdirPtr + (int)(long)n].nEntries; | |
1767 SFvSliderMovedCallback(w, (int)(long)n, nw); | |
1768 } | |
1769 | |
1770 /* ARGSUSED */ | |
1771 static void | |
1772 SFvSliderMovedCallback(w, n, nw) | |
1773 Widget w; | |
1774 int n; | |
1775 int nw; | |
1776 { | |
1777 int old; | |
1778 Window win; | |
1779 SFDir *dir; | |
1780 | |
1781 dir = &(SFdirs[SFdirPtr + n]); | |
1782 | |
1783 old = dir->vOrigin; | |
1784 dir->vOrigin = nw; | |
1785 | |
1786 if (old == nw) | |
1787 return; | |
1788 | |
1789 win = XtWindow(selFileLists[n]); | |
1790 | |
1791 if (ABS(nw - old) < SFlistSize) | |
1792 { | |
1793 if (nw > old) | |
1794 { | |
1795 XCopyArea( | |
1796 SFdisplay, | |
1797 win, | |
1798 win, | |
1799 SFscrollGC, | |
1800 SFlineToTextH, | |
1801 SFlowerY + (nw - old) * SFentryHeight, | |
1802 SFentryWidth + SFlineToTextH, | |
1803 (SFlistSize - (nw - old)) * SFentryHeight, | |
1804 SFlineToTextH, | |
1805 SFlowerY); | |
1806 XClearArea( | |
1807 SFdisplay, | |
1808 win, | |
1809 SFlineToTextH, | |
1810 SFlowerY + (SFlistSize - (nw - old)) * | |
1811 SFentryHeight, | |
1812 SFentryWidth + SFlineToTextH, | |
1813 (nw - old) * SFentryHeight, | |
1814 False); | |
1815 SFdrawStrings(win, dir, SFlistSize - (nw - old), | |
1816 SFlistSize - 1); | |
1817 } | |
1818 else | |
1819 { | |
1820 XCopyArea( | |
1821 SFdisplay, | |
1822 win, | |
1823 win, | |
1824 SFscrollGC, | |
1825 SFlineToTextH, | |
1826 SFlowerY, | |
1827 SFentryWidth + SFlineToTextH, | |
1828 (SFlistSize - (old - nw)) * SFentryHeight, | |
1829 SFlineToTextH, | |
1830 SFlowerY + (old - nw) * SFentryHeight); | |
1831 XClearArea( | |
1832 SFdisplay, | |
1833 win, | |
1834 SFlineToTextH, | |
1835 SFlowerY, | |
1836 SFentryWidth + SFlineToTextH, | |
1837 (old - nw) * SFentryHeight, | |
1838 False); | |
1839 SFdrawStrings(win, dir, 0, old - nw); | |
1840 } | |
1841 } | |
1842 else | |
1843 { | |
1844 XClearArea( | |
1845 SFdisplay, | |
1846 win, | |
1847 SFlineToTextH, | |
1848 SFlowerY, | |
1849 SFentryWidth + SFlineToTextH, | |
1850 SFlistSize * SFentryHeight, | |
1851 False); | |
1852 SFdrawStrings(win, dir, 0, SFlistSize - 1); | |
1853 } | |
1854 } | |
1855 | |
1856 /* ARGSUSED */ | |
1857 static void | |
1858 SFvAreaSelectedCallback(w, n, pnew) | |
1859 Widget w; | |
1860 XtPointer n; | |
1861 XtPointer pnew; | |
1862 { | |
1863 SFDir *dir; | |
1864 int nw; | |
1865 | |
1866 dir = &(SFdirs[SFdirPtr + (int)(long)n]); | |
1867 | |
1868 #ifdef FEAT_GUI_NEXTAW | |
1869 if ((int)(long)pnew < 0) | |
1870 { | |
1871 if ((int)(long)pnew > -SFvScrollHeight) | |
1872 (int)(long)pnew = -1; | |
1873 else | |
1874 (int)(long)pnew = -SFlistSize; | |
1875 } | |
1876 else if ((int)(long)pnew > 0) | |
1877 { | |
1878 if ((int)(long)pnew < SFvScrollHeight) | |
1879 (int)(long)pnew = 1; | |
1880 else | |
1881 (int)(long)pnew = SFlistSize; | |
1882 } | |
1883 #endif | |
1884 nw = dir->vOrigin + (int)(long)pnew; | |
1885 | |
1886 if (nw > dir->nEntries - SFlistSize) | |
1887 nw = dir->nEntries - SFlistSize; | |
1888 | |
1889 if (nw < 0) | |
1890 nw = 0; | |
1891 | |
1892 if (dir->nEntries) | |
1893 { | |
1894 float f; | |
1895 | |
1896 f = ((double) nw) / dir->nEntries; | |
1897 | |
1898 #ifdef FEAT_GUI_NEXTAW | |
1899 XawScrollbarSetThumb( | |
1900 w, | |
1901 f, | |
1902 (float) (((double) ((dir->nEntries < SFlistSize) ? | |
1903 dir->nEntries : SFlistSize)) / dir->nEntries)); | |
1904 #else | |
1905 vim_XawScrollbarSetThumb( | |
1906 w, | |
1907 f, | |
1908 (float) (((double) ((dir->nEntries < SFlistSize) ? | |
1909 dir->nEntries : SFlistSize)) / dir->nEntries), | |
1910 (double)dir->nEntries); | |
1911 #endif | |
1912 } | |
1913 | |
1914 SFvSliderMovedCallback(w, (int)(long)n, nw); | |
1915 } | |
1916 | |
1917 /* ARGSUSED */ | |
1918 static void | |
1919 SFhSliderMovedCallback(w, n, nw) | |
1920 Widget w; | |
1921 XtPointer n; | |
1922 XtPointer nw; | |
1923 { | |
1924 SFDir *dir; | |
1925 int save; | |
1926 | |
1927 dir = &(SFdirs[SFdirPtr + (int)(long)n]); | |
1928 save = dir->hOrigin; | |
1929 dir->hOrigin = (*(float *)nw) * dir->nChars; | |
1930 if (dir->hOrigin == save) | |
1931 return; | |
1932 | |
1933 SFdrawList((int)(long)n, SF_DO_NOT_SCROLL); | |
1934 } | |
1935 | |
1936 /* ARGSUSED */ | |
1937 static void | |
1938 SFhAreaSelectedCallback(w, n, pnew) | |
1939 Widget w; | |
1940 XtPointer n; | |
1941 XtPointer pnew; | |
1942 { | |
1943 SFDir *dir; | |
1944 int nw; | |
1945 | |
1946 dir = &(SFdirs[SFdirPtr + (int)(long)n]); | |
1947 | |
1948 #ifdef FEAT_GUI_NEXTAW | |
1949 if ((int)(long)pnew < 0) | |
1950 { | |
1951 if ((int)(long)pnew > -SFhScrollWidth) | |
1952 (int)(long)pnew = -1; | |
1953 else | |
1954 (int)(long)pnew = -SFcharsPerEntry; | |
1955 } | |
1956 else if ((int)(long)pnew > 0) | |
1957 { | |
1958 if ((int)(long)pnew < SFhScrollWidth) | |
1959 (int)(long)pnew = 1; | |
1960 else | |
1961 (int)(long)pnew = SFcharsPerEntry; | |
1962 } | |
1963 #endif | |
1964 nw = dir->hOrigin + (int)(long)pnew; | |
1965 | |
1966 if (nw > dir->nChars - SFcharsPerEntry) | |
1967 nw = dir->nChars - SFcharsPerEntry; | |
1968 | |
1969 if (nw < 0) | |
1970 nw = 0; | |
1971 | |
1972 if (dir->nChars) | |
1973 { | |
1974 float f; | |
1975 | |
1976 f = ((double) nw) / dir->nChars; | |
1977 | |
1978 #ifdef FEAT_GUI_NEXTAW | |
1979 XawScrollbarSetThumb( | |
1980 w, | |
1981 f, | |
1982 (float) (((double) ((dir->nChars < SFcharsPerEntry) ? | |
1983 dir->nChars : SFcharsPerEntry)) / dir->nChars)); | |
1984 #else | |
1985 vim_XawScrollbarSetThumb( | |
1986 w, | |
1987 f, | |
1988 (float) (((double) ((dir->nChars < SFcharsPerEntry) ? | |
1989 dir->nChars : SFcharsPerEntry)) / dir->nChars), | |
1990 (double)dir->nChars); | |
1991 #endif | |
1992 | |
1993 SFhSliderMovedCallback(w, n, (XtPointer)&f); | |
1994 } | |
1995 } | |
1996 | |
1997 /* ARGSUSED */ | |
1998 static void | |
1999 SFpathSliderMovedCallback(w, client_data, nw) | |
2000 Widget w; | |
2001 XtPointer client_data; | |
2002 XtPointer nw; | |
2003 { | |
2004 SFDir *dir; | |
2005 int n; | |
2006 XawTextPosition pos; | |
2007 int SFdirPtrSave; | |
2008 | |
2009 SFdirPtrSave = SFdirPtr; | |
2010 SFdirPtr = (*(float *)nw) * SFdirEnd; | |
2011 if (SFdirPtr == SFdirPtrSave) | |
2012 return; | |
2013 | |
2014 SFdrawLists(SF_DO_SCROLL); | |
2015 | |
2016 n = 2; | |
2017 while (SFdirPtr + n >= SFdirEnd) | |
2018 n--; | |
2019 | |
2020 dir = &(SFdirs[SFdirPtr + n]); | |
2021 | |
2022 pos = dir->path - SFcurrentPath; | |
2023 | |
2024 if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) | |
2025 { | |
2026 pos -= strlen(SFstartDir); | |
2027 if (pos < 0) | |
2028 pos = 0; | |
2029 } | |
2030 | |
2031 XawTextSetInsertionPoint(selFileField, pos); | |
2032 } | |
2033 | |
2034 /* ARGSUSED */ | |
2035 static void | |
2036 SFpathAreaSelectedCallback(w, client_data, pnew) | |
2037 Widget w; | |
2038 XtPointer client_data; | |
2039 XtPointer pnew; | |
2040 { | |
2041 int nw; | |
2042 float f; | |
2043 | |
2044 #ifdef FEAT_GUI_NEXTAW | |
2045 if ((int)(long)pnew < 0) | |
2046 { | |
2047 if ((int)(long)pnew > -SFpathScrollWidth) | |
2048 (int)(long)pnew = -1; | |
2049 else | |
2050 (int)(long)pnew = -3; | |
2051 } | |
2052 else if ((int)(long)pnew > 0) | |
2053 { | |
2054 if ((int)(long)pnew < SFpathScrollWidth) | |
2055 (int)(long)pnew = 1; | |
2056 else | |
2057 (int)(long)pnew = 3; | |
2058 } | |
2059 #endif | |
2060 nw = SFdirPtr + (int)(long)pnew; | |
2061 | |
2062 if (nw > SFdirEnd - 3) | |
2063 nw = SFdirEnd - 3; | |
2064 | |
2065 if (nw < 0) | |
2066 nw = 0; | |
2067 | |
2068 f = ((double) nw) / SFdirEnd; | |
2069 | |
2070 #ifdef FEAT_GUI_NEXTAW | |
2071 XawScrollbarSetThumb( | |
2072 w, | |
2073 f, | |
2074 (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) / SFdirEnd)); | |
2075 #else | |
2076 vim_XawScrollbarSetThumb( | |
2077 w, | |
2078 f, | |
2079 (float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) / SFdirEnd), | |
2080 (double)SFdirEnd); | |
2081 #endif | |
2082 | |
2083 SFpathSliderMovedCallback(w, (XtPointer) NULL, (XtPointer)&f); | |
2084 } | |
2085 | |
2086 static Boolean | |
2087 SFworkProc() | |
2088 { | |
2089 SFDir *dir; | |
2090 SFEntry *entry; | |
2091 | |
2092 for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--) | |
2093 { | |
2094 if (!(dir->nEntries)) | |
2095 continue; | |
2096 for (entry = &(dir->entries[dir->nEntries - 1]); | |
2097 entry >= dir->entries; | |
2098 entry--) | |
2099 { | |
2100 if (!(entry->statDone)) | |
2101 { | |
2102 (void)SFstatAndCheck(dir, entry); | |
2103 return False; | |
2104 } | |
2105 } | |
2106 } | |
2107 | |
2108 SFworkProcAdded = 0; | |
2109 | |
2110 return True; | |
2111 } | |
2112 | |
2113 /***************** Dir.c */ | |
2114 | |
2115 static int | |
2116 SFcompareEntries(p, q) | |
2117 const void *p; | |
2118 const void *q; | |
2119 { | |
2120 return strcmp(((SFEntry *)p)->real, ((SFEntry *)q)->real); | |
2121 } | |
2122 | |
2123 static int | |
2124 SFgetDir(dir) | |
2125 SFDir *dir; | |
2126 { | |
2127 SFEntry *result = NULL; | |
2128 int Alloc = 0; | |
2129 int i; | |
2130 DIR *dirp; | |
2131 struct dirent *dp; | |
2132 char *str; | |
2133 int len; | |
2134 int maxChars; | |
2135 struct stat statBuf; | |
2136 | |
2137 maxChars = strlen(dir->dir) - 1; | |
2138 | |
2139 dir->entries = NULL; | |
2140 dir->nEntries = 0; | |
2141 dir->nChars = 0; | |
2142 | |
2143 result = NULL; | |
2144 i = 0; | |
2145 | |
2146 dirp = opendir("."); | |
2147 if (!dirp) | |
2148 return 1; | |
2149 | |
2150 (void)mch_stat(".", &statBuf); | |
2151 dir->mtime = statBuf.st_mtime; | |
2152 | |
2153 while ((dp = readdir(dirp))) | |
2154 { | |
2155 /* Ignore "." and ".." */ | |
2156 if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) | |
2157 continue; | |
2158 if (i >= Alloc) | |
2159 { | |
2160 Alloc = 2 * (Alloc + 1); | |
2161 result = (SFEntry *) XtRealloc((char *) result, | |
2162 (unsigned) (Alloc * sizeof(SFEntry))); | |
2163 } | |
2164 result[i].statDone = 0; | |
2165 str = dp->d_name; | |
2166 len = strlen(str); | |
2167 result[i].real = XtMalloc((unsigned) (len + 2)); | |
2168 (void) strcat(strcpy(result[i].real, str), " "); | |
2169 if (len > maxChars) | |
2170 maxChars = len; | |
2171 result[i].shown = result[i].real; | |
2172 i++; | |
2173 } | |
2174 | |
2175 qsort((char *) result, (size_t) i, sizeof(SFEntry), SFcompareEntries); | |
2176 | |
2177 dir->entries = result; | |
2178 dir->nEntries = i; | |
2179 dir->nChars = maxChars + 1; | |
2180 | |
2181 closedir(dirp); | |
2182 | |
2183 return 0; | |
2184 } | |
2185 | |
2186 /***************** SFinternal.h */ | |
2187 | |
2188 #include <sys/param.h> | |
2189 #include <X11/cursorfont.h> | |
2190 #include <X11/Composite.h> | |
2191 #include <X11/Shell.h> | |
2192 #ifdef FEAT_GUI_NEXTAW | |
2193 # include <X11/neXtaw/Form.h> | |
2194 # include <X11/neXtaw/Command.h> | |
2195 # include <X11/neXtaw/Label.h> | |
2196 #else | |
2197 #include <X11/Xaw/Form.h> | |
2198 #include <X11/Xaw/Command.h> | |
2199 #include <X11/Xaw/Label.h> | |
2200 #endif | |
2201 | |
2202 static char *oneLineTextEditTranslations = "\ | |
2203 <Key>Return: redraw-display()\n\ | |
2204 Ctrl<Key>M: redraw-display()\n\ | |
2205 "; | |
2206 | |
2207 static void SFexposeList __ARGS((Widget w, XtPointer n, XEvent *event, Boolean *cont)); | |
2208 | |
2209 /* ARGSUSED */ | |
2210 static void | |
2211 SFexposeList(w, n, event, cont) | |
2212 Widget w; | |
2213 XtPointer n; | |
2214 XEvent *event; | |
2215 Boolean *cont; | |
2216 { | |
2217 if ((event->type == NoExpose) || event->xexpose.count) | |
2218 return; | |
2219 | |
2220 SFdrawList((int)(long)n, SF_DO_NOT_SCROLL); | |
2221 } | |
2222 | |
2223 static void SFmodVerifyCallback __ARGS((Widget w, XtPointer client_data, XEvent *event, Boolean *cont)); | |
2224 | |
2225 /* ARGSUSED */ | |
2226 static void | |
2227 SFmodVerifyCallback(w, client_data, event, cont) | |
2228 Widget w; | |
2229 XtPointer client_data; | |
2230 XEvent *event; | |
2231 Boolean *cont; | |
2232 { | |
2233 char buf[2]; | |
2234 | |
2235 if ((XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) && | |
2236 ((*buf) == '\r')) | |
2237 SFstatus = SEL_FILE_OK; | |
2238 else | |
2239 SFstatus = SEL_FILE_TEXT; | |
2240 } | |
2241 | |
2242 static void SFokCallback __ARGS((Widget w, XtPointer cl, XtPointer cd)); | |
2243 | |
2244 /* ARGSUSED */ | |
2245 static void | |
2246 SFokCallback(w, cl, cd) | |
2247 Widget w; | |
2248 XtPointer cl, cd; | |
2249 { | |
2250 SFstatus = SEL_FILE_OK; | |
2251 } | |
2252 | |
2253 static XtCallbackRec SFokSelect[] = | |
2254 { | |
2255 { SFokCallback, (XtPointer) NULL }, | |
2256 { NULL, (XtPointer) NULL }, | |
2257 }; | |
2258 | |
2259 static void SFcancelCallback __ARGS((Widget w, XtPointer cl, XtPointer cd)); | |
2260 | |
2261 /* ARGSUSED */ | |
2262 static void | |
2263 SFcancelCallback(w, cl, cd) | |
2264 Widget w; | |
2265 XtPointer cl, cd; | |
2266 { | |
2267 SFstatus = SEL_FILE_CANCEL; | |
2268 } | |
2269 | |
2270 static XtCallbackRec SFcancelSelect[] = | |
2271 { | |
2272 { SFcancelCallback, (XtPointer) NULL }, | |
2273 { NULL, (XtPointer) NULL }, | |
2274 }; | |
2275 | |
2276 static void SFdismissAction __ARGS((Widget w, XEvent *event, String *params, Cardinal *num_params)); | |
2277 | |
2278 /* ARGSUSED */ | |
2279 static void | |
2280 SFdismissAction(w, event, params, num_params) | |
2281 Widget w; | |
2282 XEvent *event; | |
2283 String *params; | |
2284 Cardinal *num_params; | |
2285 { | |
2286 if (event->type == ClientMessage && | |
2287 event->xclient.data.l[0] != SFwmDeleteWindow) | |
2288 return; | |
2289 | |
2290 SFstatus = SEL_FILE_CANCEL; | |
2291 } | |
2292 | |
2293 static char *wmDeleteWindowTranslation = "\ | |
2294 <Message>WM_PROTOCOLS: SelFileDismiss()\n\ | |
2295 "; | |
2296 | |
2297 static XtActionsRec actions[] = | |
2298 { | |
2299 {"SelFileDismiss", SFdismissAction}, | |
2300 }; | |
2301 | |
2302 static void | |
2303 SFsetColors(bg, fg, scroll_bg, scroll_fg) | |
2304 guicolor_T bg; | |
2305 guicolor_T fg; | |
2306 guicolor_T scroll_bg; | |
2307 guicolor_T scroll_fg; | |
2308 { | |
2309 if (selFileForm) | |
2310 { | |
2311 XtVaSetValues(selFileForm, XtNbackground, bg, | |
2312 XtNforeground, fg, | |
2313 XtNborderColor, bg, | |
2314 NULL); | |
2315 } | |
2316 { | |
2317 int i; | |
2318 | |
2319 for (i = 0; i < 3; ++i) | |
2320 { | |
2321 if (selFileLists[i]) | |
2322 { | |
2323 XtVaSetValues(selFileLists[i], XtNbackground, bg, | |
2324 XtNforeground, fg, | |
2325 XtNborderColor, fg, | |
2326 NULL); | |
2327 } | |
2328 } | |
2329 } | |
2330 if (selFileOK) | |
2331 { | |
2332 XtVaSetValues(selFileOK, XtNbackground, bg, | |
2333 XtNforeground, fg, | |
2334 XtNborderColor, fg, | |
2335 NULL); | |
2336 } | |
2337 if (selFileCancel) | |
2338 { | |
2339 XtVaSetValues(selFileCancel, XtNbackground, bg, | |
2340 XtNforeground, fg, | |
2341 XtNborderColor, fg, | |
2342 NULL); | |
2343 } | |
2344 if (selFilePrompt) | |
2345 { | |
2346 XtVaSetValues(selFilePrompt, XtNbackground, bg, | |
2347 XtNforeground, fg, | |
2348 NULL); | |
2349 } | |
2350 if (gui.dpy) | |
2351 { | |
2352 XSetBackground(gui.dpy, SFtextGC, bg); | |
2353 XSetForeground(gui.dpy, SFtextGC, fg); | |
2354 XSetForeground(gui.dpy, SFlineGC, fg); | |
2355 | |
2356 /* This is an xor GC, so combine the fg and background */ | |
2357 XSetBackground(gui.dpy, SFinvertGC, fg ^ bg); | |
2358 XSetForeground(gui.dpy, SFinvertGC, fg ^ bg); | |
2359 } | |
2360 if (selFileHScroll) | |
2361 { | |
2362 XtVaSetValues(selFileHScroll, XtNbackground, scroll_bg, | |
2363 XtNforeground, scroll_fg, | |
2364 XtNborderColor, fg, | |
2365 NULL); | |
2366 } | |
2367 { | |
2368 int i; | |
2369 | |
2370 for (i = 0; i < 3; i++) | |
2371 { | |
2372 XtVaSetValues(selFileVScrolls[i], XtNbackground, scroll_bg, | |
2373 XtNforeground, scroll_fg, | |
2374 XtNborderColor, fg, | |
2375 NULL); | |
2376 XtVaSetValues(selFileHScrolls[i], XtNbackground, scroll_bg, | |
2377 XtNforeground, scroll_fg, | |
2378 XtNborderColor, fg, | |
2379 NULL); | |
2380 } | |
2381 } | |
2382 } | |
2383 | |
2384 static void | |
2385 SFcreateWidgets(toplevel, prompt, ok, cancel) | |
2386 Widget toplevel; | |
2387 char *prompt; | |
2388 char *ok; | |
2389 char *cancel; | |
2390 { | |
2391 Cardinal n; | |
2392 int listWidth, listHeight; | |
2393 int listSpacing = 10; | |
2394 int scrollThickness = 15; | |
2395 int hScrollX, hScrollY; | |
2396 int vScrollX, vScrollY; | |
2397 | |
2398 selFile = XtVaAppCreateShell("selFile", "SelFile", | |
2399 transientShellWidgetClass, SFdisplay, | |
2400 XtNtransientFor, toplevel, | |
2401 XtNtitle, prompt, | |
2402 NULL); | |
2403 | |
2404 /* Add WM_DELETE_WINDOW protocol */ | |
2405 XtAppAddActions(XtWidgetToApplicationContext(selFile), | |
2406 actions, XtNumber(actions)); | |
2407 XtOverrideTranslations(selFile, | |
2408 XtParseTranslationTable(wmDeleteWindowTranslation)); | |
2409 | |
2410 selFileForm = XtVaCreateManagedWidget("selFileForm", | |
2411 formWidgetClass, selFile, | |
2412 XtNdefaultDistance, 30, | |
2413 XtNforeground, SFfore, | |
2414 XtNbackground, SFback, | |
2415 XtNborderColor, SFback, | |
2416 NULL); | |
2417 | |
2418 selFilePrompt = XtVaCreateManagedWidget("selFilePrompt", | |
2419 labelWidgetClass, selFileForm, | |
2420 XtNlabel, prompt, | |
2421 XtNresizable, True, | |
2422 XtNtop, XtChainTop, | |
2423 XtNbottom, XtChainTop, | |
2424 XtNleft, XtChainLeft, | |
2425 XtNright, XtChainLeft, | |
2426 XtNborderWidth, 0, | |
2427 XtNforeground, SFfore, | |
2428 XtNbackground, SFback, | |
2429 NULL); | |
2430 | |
2431 /* | |
2432 XtVaGetValues(selFilePrompt, | |
2433 XtNforeground, &SFfore, | |
2434 XtNbackground, &SFback, | |
2435 NULL); | |
2436 */ | |
2437 | |
2438 SFinitFont(); | |
2439 | |
2440 SFentryWidth = SFbesideText + SFcharsPerEntry * SFcharWidth + | |
2441 SFbesideText; | |
2442 SFentryHeight = SFaboveAndBelowText + SFcharHeight + | |
2443 SFaboveAndBelowText; | |
2444 | |
2445 listWidth = SFlineToTextH + SFentryWidth + SFlineToTextH + 1 + | |
2446 scrollThickness; | |
2447 listHeight = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 + | |
2448 SFlineToTextV + SFlistSize * SFentryHeight + | |
2449 SFlineToTextV + 1 + scrollThickness; | |
2450 | |
2451 SFpathScrollWidth = 3 * listWidth + 2 * listSpacing + 4; | |
2452 | |
2453 hScrollX = -1; | |
2454 hScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 + | |
2455 SFlineToTextV + SFlistSize * SFentryHeight + | |
2456 SFlineToTextV; | |
2457 SFhScrollWidth = SFlineToTextH + SFentryWidth + SFlineToTextH; | |
2458 | |
2459 vScrollX = SFlineToTextH + SFentryWidth + SFlineToTextH; | |
2460 vScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV; | |
2461 SFvScrollHeight = SFlineToTextV + SFlistSize * SFentryHeight + | |
2462 SFlineToTextV; | |
2463 | |
2464 SFupperX = SFlineToTextH + SFentryWidth + SFlineToTextH - 1; | |
2465 SFlowerY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 + | |
2466 SFlineToTextV; | |
2467 SFupperY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 + | |
2468 SFlineToTextV + SFlistSize * SFentryHeight - 1; | |
2469 | |
2470 SFtextX = SFlineToTextH + SFbesideText; | |
2471 SFtextYoffset = SFlowerY + SFaboveAndBelowText + SFcharAscent; | |
2472 | |
2473 SFsegs[0].x1 = 0; | |
2474 SFsegs[0].y1 = vScrollY; | |
2475 SFsegs[0].x2 = vScrollX - 1; | |
2476 SFsegs[0].y2 = vScrollY; | |
2477 SFsegs[1].x1 = vScrollX; | |
2478 SFsegs[1].y1 = 0; | |
2479 SFsegs[1].x2 = vScrollX; | |
2480 SFsegs[1].y2 = vScrollY - 1; | |
2481 | |
2482 SFcompletionSegs[0].x1 = SFcompletionSegs[0].x2 = SFlineToTextH; | |
2483 SFcompletionSegs[1].x1 = SFcompletionSegs[1].x2 = | |
2484 SFlineToTextH + SFentryWidth - 1; | |
2485 | |
2486 selFileField = XtVaCreateManagedWidget("selFileField", | |
2487 asciiTextWidgetClass, selFileForm, | |
2488 XtNwidth, 3 * listWidth + 2 * listSpacing + 4, | |
2489 XtNborderColor, SFfore, | |
2490 XtNfromVert, selFilePrompt, | |
2491 XtNvertDistance, 10, | |
2492 XtNresizable, True, | |
2493 XtNtop, XtChainTop, | |
2494 XtNbottom, XtChainTop, | |
2495 XtNleft, XtChainLeft, | |
2496 XtNright, XtChainLeft, | |
2497 XtNstring, SFtextBuffer, | |
2498 XtNlength, MAXPATHL, | |
2499 XtNeditType, XawtextEdit, | |
2500 XtNwrap, XawtextWrapWord, | |
2501 XtNresize, XawtextResizeHeight, | |
2502 XtNuseStringInPlace, True, | |
2503 NULL); | |
2504 | |
2505 XtOverrideTranslations(selFileField, | |
2506 XtParseTranslationTable(oneLineTextEditTranslations)); | |
2507 XtSetKeyboardFocus(selFileForm, selFileField); | |
2508 | |
2509 selFileHScroll = XtVaCreateManagedWidget("selFileHScroll", | |
2510 #ifdef FEAT_GUI_NEXTAW | |
2511 scrollbarWidgetClass, selFileForm, | |
2512 #else | |
2513 vim_scrollbarWidgetClass, selFileForm, | |
2514 #endif | |
2515 XtNorientation, XtorientHorizontal, | |
2516 XtNwidth, SFpathScrollWidth, | |
2517 XtNheight, scrollThickness, | |
2518 XtNborderColor, SFfore, | |
2519 XtNfromVert, selFileField, | |
2520 XtNvertDistance, 30, | |
2521 XtNtop, XtChainTop, | |
2522 XtNbottom, XtChainTop, | |
2523 XtNleft, XtChainLeft, | |
2524 XtNright, XtChainLeft, | |
2525 XtNforeground, gui.scroll_fg_pixel, | |
2526 XtNbackground, gui.scroll_bg_pixel, | |
2527 #ifndef FEAT_GUI_NEXTAW | |
2528 XtNlimitThumb, 1, | |
2529 #endif | |
2530 NULL); | |
2531 | |
2532 XtAddCallback(selFileHScroll, XtNjumpProc, | |
2533 (XtCallbackProc) SFpathSliderMovedCallback, (XtPointer)NULL); | |
2534 XtAddCallback(selFileHScroll, XtNscrollProc, | |
2535 (XtCallbackProc) SFpathAreaSelectedCallback, (XtPointer)NULL); | |
2536 | |
2537 selFileLists[0] = XtVaCreateManagedWidget("selFileList1", | |
2538 compositeWidgetClass, selFileForm, | |
2539 XtNwidth, listWidth, | |
2540 XtNheight, listHeight, | |
2541 XtNforeground, SFfore, | |
2542 XtNbackground, SFback, | |
2543 XtNborderColor, SFfore, | |
2544 XtNfromVert, selFileHScroll, | |
2545 XtNvertDistance, 10, | |
2546 XtNtop, XtChainTop, | |
2547 XtNbottom, XtChainTop, | |
2548 XtNleft, XtChainLeft, | |
2549 XtNright, XtChainLeft, | |
2550 NULL); | |
2551 | |
2552 selFileLists[1] = XtVaCreateManagedWidget("selFileList2", | |
2553 compositeWidgetClass, selFileForm, | |
2554 XtNwidth, listWidth, | |
2555 XtNheight, listHeight, | |
2556 XtNforeground, SFfore, | |
2557 XtNbackground, SFback, | |
2558 XtNborderColor, SFfore, | |
2559 XtNfromHoriz, selFileLists[0], | |
2560 XtNfromVert, selFileHScroll, | |
2561 XtNhorizDistance, listSpacing, | |
2562 XtNvertDistance, 10, | |
2563 XtNtop, XtChainTop, | |
2564 XtNbottom, XtChainTop, | |
2565 XtNleft, XtChainLeft, | |
2566 XtNright, XtChainLeft, | |
2567 NULL); | |
2568 | |
2569 selFileLists[2] = XtVaCreateManagedWidget("selFileList3", | |
2570 compositeWidgetClass, selFileForm, | |
2571 XtNwidth, listWidth, | |
2572 XtNheight, listHeight, | |
2573 XtNforeground, SFfore, | |
2574 XtNbackground, SFback, | |
2575 XtNborderColor, SFfore, | |
2576 XtNfromHoriz, selFileLists[1], | |
2577 XtNfromVert, selFileHScroll, | |
2578 XtNhorizDistance, listSpacing, | |
2579 XtNvertDistance, 10, | |
2580 XtNtop, XtChainTop, | |
2581 XtNbottom, XtChainTop, | |
2582 XtNleft, XtChainLeft, | |
2583 XtNright, XtChainLeft, | |
2584 NULL); | |
2585 | |
2586 for (n = 0; n < 3; n++) | |
2587 { | |
2588 selFileVScrolls[n] = XtVaCreateManagedWidget("selFileVScroll", | |
2589 #ifdef FEAT_GUI_NEXTAW | |
2590 scrollbarWidgetClass, selFileLists[n], | |
2591 #else | |
2592 vim_scrollbarWidgetClass, selFileLists[n], | |
2593 #endif | |
2594 XtNx, vScrollX, | |
2595 XtNy, vScrollY, | |
2596 XtNwidth, scrollThickness, | |
2597 XtNheight, SFvScrollHeight, | |
2598 XtNborderColor, SFfore, | |
2599 XtNforeground, gui.scroll_fg_pixel, | |
2600 XtNbackground, gui.scroll_bg_pixel, | |
2601 #ifndef FEAT_GUI_NEXTAW | |
2602 XtNlimitThumb, 1, | |
2603 #endif | |
2604 NULL); | |
2605 | |
2606 XtAddCallback(selFileVScrolls[n], XtNjumpProc, | |
2607 (XtCallbackProc)SFvFloatSliderMovedCallback, (XtPointer)n); | |
2608 XtAddCallback(selFileVScrolls[n], XtNscrollProc, | |
2609 (XtCallbackProc)SFvAreaSelectedCallback, (XtPointer)n); | |
2610 | |
2611 selFileHScrolls[n] = XtVaCreateManagedWidget("selFileHScroll", | |
2612 #ifdef FEAT_GUI_NEXTAW | |
2613 scrollbarWidgetClass, selFileLists[n], | |
2614 #else | |
2615 vim_scrollbarWidgetClass, selFileLists[n], | |
2616 #endif | |
2617 XtNorientation, XtorientHorizontal, | |
2618 XtNx, hScrollX, | |
2619 XtNy, hScrollY, | |
2620 XtNwidth, SFhScrollWidth, | |
2621 XtNheight, scrollThickness, | |
2622 XtNborderColor, SFfore, | |
2623 XtNforeground, gui.scroll_fg_pixel, | |
2624 XtNbackground, gui.scroll_bg_pixel, | |
2625 #ifndef FEAT_GUI_NEXTAW | |
2626 XtNlimitThumb, 1, | |
2627 #endif | |
2628 NULL); | |
2629 | |
2630 XtAddCallback(selFileHScrolls[n], XtNjumpProc, | |
2631 (XtCallbackProc)SFhSliderMovedCallback, (XtPointer)n); | |
2632 XtAddCallback(selFileHScrolls[n], XtNscrollProc, | |
2633 (XtCallbackProc)SFhAreaSelectedCallback, (XtPointer)n); | |
2634 } | |
2635 | |
2636 selFileOK = XtVaCreateManagedWidget("selFileOK", | |
2637 commandWidgetClass, selFileForm, | |
2638 XtNlabel, ok, | |
2639 XtNresizable, True, | |
2640 XtNcallback, SFokSelect, | |
2641 XtNforeground, SFfore, | |
2642 XtNbackground, SFback, | |
2643 XtNborderColor, SFfore, | |
2644 XtNfromHoriz, selFileLists[0], | |
2645 XtNfromVert, selFileLists[0], | |
2646 XtNvertDistance, 30, | |
2647 XtNtop, XtChainTop, | |
2648 XtNbottom, XtChainTop, | |
2649 XtNleft, XtChainLeft, | |
2650 XtNright, XtChainLeft, | |
2651 NULL); | |
2652 | |
2653 selFileCancel = XtVaCreateManagedWidget("selFileCancel", | |
2654 commandWidgetClass, selFileForm, | |
2655 XtNlabel, cancel, | |
2656 XtNresizable, True, | |
2657 XtNcallback, SFcancelSelect, | |
2658 XtNforeground, SFfore, | |
2659 XtNbackground, SFback, | |
2660 XtNborderColor, SFfore, | |
2661 XtNfromHoriz, selFileOK, | |
2662 XtNfromVert, selFileLists[0], | |
2663 XtNhorizDistance, 30, | |
2664 XtNvertDistance, 30, | |
2665 XtNtop, XtChainTop, | |
2666 XtNbottom, XtChainTop, | |
2667 XtNleft, XtChainLeft, | |
2668 XtNright, XtChainLeft, | |
2669 NULL); | |
2670 | |
2671 XtSetMappedWhenManaged(selFile, False); | |
2672 XtRealizeWidget(selFile); | |
2673 | |
2674 /* Add WM_DELETE_WINDOW protocol */ | |
2675 SFwmDeleteWindow = XInternAtom(SFdisplay, "WM_DELETE_WINDOW", False); | |
2676 XSetWMProtocols(SFdisplay, XtWindow(selFile), &SFwmDeleteWindow, 1); | |
2677 | |
2678 SFcreateGC(); | |
2679 | |
2680 for (n = 0; n < 3; n++) | |
2681 { | |
2682 XtAddEventHandler(selFileLists[n], ExposureMask, True, | |
2683 (XtEventHandler)SFexposeList, (XtPointer)n); | |
2684 XtAddEventHandler(selFileLists[n], EnterWindowMask, False, | |
2685 (XtEventHandler)SFenterList, (XtPointer)n); | |
2686 XtAddEventHandler(selFileLists[n], LeaveWindowMask, False, | |
2687 (XtEventHandler)SFleaveList, (XtPointer)n); | |
2688 XtAddEventHandler(selFileLists[n], PointerMotionMask, False, | |
2689 (XtEventHandler)SFmotionList, (XtPointer)n); | |
2690 XtAddEventHandler(selFileLists[n], ButtonPressMask, False, | |
2691 (XtEventHandler)SFbuttonPressList, (XtPointer)n); | |
2692 XtAddEventHandler(selFileLists[n], ButtonReleaseMask, False, | |
2693 (XtEventHandler)SFbuttonReleaseList, (XtPointer)n); | |
2694 } | |
2695 | |
2696 XtAddEventHandler(selFileField, KeyPressMask, False, | |
2697 SFmodVerifyCallback, (XtPointer)NULL); | |
2698 | |
2699 SFapp = XtWidgetToApplicationContext(selFile); | |
2700 } | |
2701 | |
2702 static void | |
2703 SFtextChanged() | |
2704 { | |
2705 #if defined(FEAT_XFONTSET) && defined(XtNinternational) | |
2706 if (_XawTextFormat((TextWidget)selFileField) == XawFmtWide) | |
2707 { | |
2708 wchar_t *wcbuf=(wchar_t *)SFtextBuffer; | |
2709 | |
2710 if ((wcbuf[0] == L'/') || (wcbuf[0] == L'~')) | |
2711 { | |
2712 (void) wcstombs(SFcurrentPath, wcbuf, MAXPATHL); | |
2713 SFtextPos = XawTextGetInsertionPoint(selFileField); | |
2714 } | |
2715 else | |
2716 { | |
2717 strcpy(SFcurrentPath, SFstartDir); | |
2718 (void) wcstombs(SFcurrentPath + strlen(SFcurrentPath), wcbuf, MAXPATHL); | |
2719 | |
2720 SFtextPos = XawTextGetInsertionPoint(selFileField) + strlen(SFstartDir); | |
2721 } | |
2722 } | |
2723 else | |
2724 #endif | |
2725 if ((SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~')) | |
2726 { | |
2727 (void) strcpy(SFcurrentPath, SFtextBuffer); | |
2728 SFtextPos = XawTextGetInsertionPoint(selFileField); | |
2729 } | |
2730 else | |
2731 { | |
2732 (void) strcat(strcpy(SFcurrentPath, SFstartDir), SFtextBuffer); | |
2733 | |
2734 SFtextPos = XawTextGetInsertionPoint(selFileField) + strlen(SFstartDir); | |
2735 } | |
2736 | |
2737 if (!SFworkProcAdded) | |
2738 { | |
2739 (void) XtAppAddWorkProc(SFapp, (XtWorkProc)SFworkProc, NULL); | |
2740 SFworkProcAdded = 1; | |
2741 } | |
2742 | |
2743 SFupdatePath(); | |
2744 } | |
2745 | |
2746 static char * | |
2747 SFgetText() | |
2748 { | |
2749 #if defined(FEAT_XFONTSET) && defined(XtNinternational) | |
2750 char *buf; | |
2751 | |
2752 if (_XawTextFormat((TextWidget)selFileField) == XawFmtWide) | |
2753 { | |
2754 wchar_t *wcbuf; | |
2755 int mbslength; | |
2756 | |
2757 XtVaGetValues(selFileField, | |
2758 XtNstring, &wcbuf, | |
2759 NULL); | |
2760 mbslength = wcstombs(NULL, wcbuf, 0); | |
2761 /* Hack: some broken wcstombs() returns zero, just get a large buffer */ | |
2762 if (mbslength == 0 && wcbuf != NULL && wcbuf[0] != 0) | |
2763 mbslength = MAXPATHL; | |
2764 buf=(char *)XtMalloc(mbslength + 1); | |
2765 wcstombs(buf, wcbuf, mbslength +1); | |
2766 return buf; | |
2767 } | |
2768 #endif | |
2769 return (char *)vim_strsave((char_u *)SFtextBuffer); | |
2770 } | |
2771 | |
2772 static void | |
2773 SFprepareToReturn() | |
2774 { | |
2775 SFstatus = SEL_FILE_NULL; | |
2776 XtRemoveGrab(selFile); | |
2777 XtUnmapWidget(selFile); | |
2778 XtRemoveTimeOut(SFdirModTimerId); | |
2779 if (SFchdir(SFstartDir)) | |
2780 { | |
2781 EMSG(_("E614: vim_SelFile: can't return to current directory")); | |
2782 SFstatus = SEL_FILE_CANCEL; | |
2783 } | |
2784 } | |
2785 | |
2786 char * | |
2787 vim_SelFile(toplevel, prompt, init_path, show_entry, x, y, fg, bg, scroll_fg, scroll_bg) | |
2788 Widget toplevel; | |
2789 char *prompt; | |
2790 char *init_path; | |
2791 int (*show_entry)(); | |
2792 int x, y; | |
2793 guicolor_T fg, bg; | |
2794 guicolor_T scroll_fg, scroll_bg; /* The "Scrollbar" group colors */ | |
2795 { | |
2796 static int firstTime = 1; | |
2797 XEvent event; | |
2798 char *name_return; | |
2799 | |
2800 if (prompt == NULL) | |
2801 prompt = _("Pathname:"); | |
2802 SFfore = fg; | |
2803 SFback = bg; | |
2804 | |
2805 if (mch_dirname((char_u *)SFstartDir, MAXPATHL) == FAIL) | |
2806 { | |
2807 EMSG(_("E615: vim_SelFile: can't get current directory")); | |
2808 return NULL; | |
2809 } | |
2810 | |
2811 if (firstTime) | |
2812 { | |
2813 firstTime = 0; | |
2814 SFdisplay = XtDisplay(toplevel); | |
2815 SFcreateWidgets(toplevel, prompt, _("OK"), _("Cancel")); | |
2816 } | |
2817 else | |
2818 { | |
2819 XtVaSetValues(selFilePrompt, XtNlabel, prompt, NULL); | |
2820 XtVaSetValues(selFile, XtNtitle, prompt, NULL); | |
2821 SFsetColors(bg, fg, scroll_bg, scroll_fg); | |
2822 } | |
2823 | |
2824 XtVaSetValues(selFile, XtNx, x, XtNy, y, NULL); | |
2825 XtMapWidget(selFile); | |
2826 | |
2827 (void)strcat(SFstartDir, "/"); | |
2828 (void)strcpy(SFcurrentDir, SFstartDir); | |
2829 | |
2830 if (init_path) | |
2831 { | |
2832 if (init_path[0] == '/') | |
2833 { | |
2834 (void)strcpy(SFcurrentPath, init_path); | |
2835 if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir))) | |
2836 SFsetText(SFcurrentPath); | |
2837 else | |
2838 SFsetText(&(SFcurrentPath[strlen(SFstartDir)])); | |
2839 } | |
2840 else | |
2841 { | |
2842 (void)strcat(strcpy(SFcurrentPath, SFstartDir), init_path); | |
2843 SFsetText(&(SFcurrentPath[strlen(SFstartDir)])); | |
2844 } | |
2845 } | |
2846 else | |
2847 (void)strcpy(SFcurrentPath, SFstartDir); | |
2848 | |
2849 SFfunc = show_entry; | |
2850 | |
2851 SFtextChanged(); | |
2852 | |
2853 XtAddGrab(selFile, True, True); | |
2854 | |
2855 SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000, | |
2856 SFdirModTimer, (XtPointer) NULL); | |
2857 | |
2858 while (1) | |
2859 { | |
2860 XtAppNextEvent(SFapp, &event); | |
2861 XtDispatchEvent(&event); | |
2862 switch (SFstatus) | |
2863 { | |
2864 case SEL_FILE_TEXT: | |
2865 SFstatus = SEL_FILE_NULL; | |
2866 SFtextChanged(); | |
2867 break; | |
2868 case SEL_FILE_OK: | |
2869 name_return = SFgetText(); | |
2870 SFprepareToReturn(); | |
2871 return name_return; | |
2872 case SEL_FILE_CANCEL: | |
2873 SFprepareToReturn(); | |
2874 return NULL; | |
2875 case SEL_FILE_NULL: | |
2876 break; | |
2877 } | |
2878 } | |
2879 } | |
2880 #endif /* FEAT_BROWSE */ |