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