mirror of
https://github.com/vim/vim.git
synced 2025-07-04 23:07:33 -04:00
Problem: Compiler warnings when building with Athena GUI. Solution: Fix function signatures.
2754 lines
57 KiB
C
2754 lines
57 KiB
C
/* vi:set ts=8 sts=4 sw=4 noet: */
|
|
|
|
/*
|
|
* Copyright 1989 Software Research Associates, Inc., Tokyo, Japan
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software and its
|
|
* documentation for any purpose and without fee is hereby granted, provided
|
|
* that the above copyright notice appear in all copies and that both that
|
|
* copyright notice and this permission notice appear in supporting
|
|
* documentation, and that the name of Software Research Associates not be used
|
|
* in advertising or publicity pertaining to distribution of the software
|
|
* without specific, written prior permission. Software Research Associates
|
|
* makes no representations about the suitability of this software for any
|
|
* purpose. It is provided "as is" without express or implied warranty.
|
|
*
|
|
* SOFTWARE RESEARCH ASSOCIATES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
|
|
* IN NO EVENT SHALL SOFTWARE RESEARCH ASSOCIATES BE LIABLE FOR ANY SPECIAL,
|
|
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*
|
|
* Author: Erik M. van der Poel
|
|
* Software Research Associates, Inc., Tokyo, Japan
|
|
* erik@sra.co.jp
|
|
*/
|
|
/*
|
|
* Author's addresses:
|
|
* erik@sra.co.jp
|
|
* erik%sra.co.jp@uunet.uu.net
|
|
* erik%sra.co.jp@mcvax.uucp
|
|
* try junet instead of co.jp
|
|
* Erik M. van der Poel
|
|
* Software Research Associates, Inc.
|
|
* 1-1-1 Hirakawa-cho, Chiyoda-ku
|
|
* Tokyo 102 Japan. TEL +81-3-234-2692
|
|
*/
|
|
|
|
/*
|
|
* Heavely modified for Vim by Bram Moolenaar
|
|
*/
|
|
|
|
#include "vim.h"
|
|
|
|
// Only include this when using the file browser
|
|
|
|
#ifdef FEAT_BROWSE
|
|
|
|
// Weird complication: for "make lint" Text.h doesn't combine with Xm.h
|
|
#if defined(FEAT_GUI_MOTIF) && defined(FMT8BIT)
|
|
# undef FMT8BIT
|
|
#endif
|
|
|
|
#ifndef FEAT_GUI_NEXTAW
|
|
# include "gui_at_sb.h"
|
|
#endif
|
|
|
|
////////////////// SFinternal.h
|
|
|
|
#include <X11/Intrinsic.h>
|
|
#include <X11/StringDefs.h>
|
|
#include <X11/Xos.h>
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
# include <X11/neXtaw/Text.h>
|
|
# include <X11/neXtaw/AsciiText.h>
|
|
# include <X11/neXtaw/Scrollbar.h>
|
|
#else
|
|
# include <X11/Xaw/Text.h>
|
|
# include <X11/Xaw/AsciiText.h>
|
|
#endif
|
|
|
|
#define SEL_FILE_CANCEL -1
|
|
#define SEL_FILE_OK 0
|
|
#define SEL_FILE_NULL 1
|
|
#define SEL_FILE_TEXT 2
|
|
|
|
#define SF_DO_SCROLL 1
|
|
#define SF_DO_NOT_SCROLL 0
|
|
|
|
typedef struct
|
|
{
|
|
int statDone;
|
|
char *real;
|
|
char *shown;
|
|
} SFEntry;
|
|
|
|
typedef struct
|
|
{
|
|
char *dir;
|
|
char *path;
|
|
SFEntry *entries;
|
|
int nEntries;
|
|
int vOrigin;
|
|
int nChars;
|
|
int hOrigin;
|
|
int changed;
|
|
int beginSelection;
|
|
int endSelection;
|
|
time_t mtime;
|
|
} SFDir;
|
|
|
|
static char SFstartDir[MAXPATHL],
|
|
SFcurrentPath[MAXPATHL],
|
|
SFcurrentDir[MAXPATHL];
|
|
|
|
static Widget selFile,
|
|
selFileField,
|
|
selFileForm,
|
|
selFileHScroll,
|
|
selFileHScrolls[3],
|
|
selFileLists[3],
|
|
selFileOK,
|
|
selFileCancel,
|
|
selFilePrompt,
|
|
selFileVScrolls[3];
|
|
|
|
static Display *SFdisplay;
|
|
|
|
static int SFcharWidth, SFcharAscent, SFcharHeight;
|
|
|
|
static SFDir *SFdirs = NULL;
|
|
|
|
static int SFdirEnd;
|
|
static int SFdirPtr;
|
|
|
|
static Pixel SFfore, SFback;
|
|
|
|
static Atom SFwmDeleteWindow;
|
|
|
|
static XSegment SFsegs[2], SFcompletionSegs[2];
|
|
|
|
static XawTextPosition SFtextPos;
|
|
|
|
static int SFupperX, SFlowerY, SFupperY;
|
|
|
|
static int SFtextX, SFtextYoffset;
|
|
|
|
static int SFentryWidth, SFentryHeight;
|
|
|
|
static int SFlineToTextH = 3;
|
|
static int SFlineToTextV = 3;
|
|
|
|
static int SFbesideText = 3;
|
|
static int SFaboveAndBelowText = 2;
|
|
|
|
static int SFcharsPerEntry = 15;
|
|
|
|
static int SFlistSize = 10;
|
|
|
|
static int SFcurrentInvert[3] = { -1, -1, -1 };
|
|
|
|
static int SFworkProcAdded = 0;
|
|
|
|
static XtAppContext SFapp;
|
|
|
|
static int SFpathScrollWidth, SFvScrollHeight, SFhScrollWidth;
|
|
|
|
#ifdef FEAT_XFONTSET
|
|
static char SFtextBuffer[MAXPATHL*sizeof(wchar_t)];
|
|
#else
|
|
static char SFtextBuffer[MAXPATHL];
|
|
#endif
|
|
|
|
static int SFbuttonPressed = 0;
|
|
|
|
static XtIntervalId SFdirModTimerId;
|
|
|
|
static int (*SFfunc)();
|
|
|
|
static int SFstatus = SEL_FILE_NULL;
|
|
|
|
///////////////// forward declare static functions
|
|
|
|
static void SFsetText(char *path);
|
|
static void SFtextChanged(void);
|
|
static int SFgetDir(SFDir *dir);
|
|
static void SFdrawLists(int doScroll);
|
|
static void SFdrawList(int n, int doScroll);
|
|
static void SFclearList(int n, int doScroll);
|
|
static char SFstatChar(stat_T *statBuf);
|
|
static void SFmotionList(Widget w, XtPointer np, XMotionEvent *event, Boolean *cont);
|
|
static void SFvSliderMovedCallback(Widget w, int n, int nw);
|
|
static Boolean SFworkProc(void *);
|
|
static int SFcompareEntries(const void *p, const void *q);
|
|
|
|
////////////////// xstat.h
|
|
|
|
#ifndef S_IXUSR
|
|
# define S_IXUSR 0100
|
|
#endif
|
|
#ifndef S_IXGRP
|
|
# define S_IXGRP 0010
|
|
#endif
|
|
#ifndef S_IXOTH
|
|
# define S_IXOTH 0001
|
|
#endif
|
|
|
|
#define S_ISXXX(m) ((m) & (S_IXUSR | S_IXGRP | S_IXOTH))
|
|
|
|
////////////////// Path.c
|
|
|
|
#include <pwd.h>
|
|
|
|
typedef struct
|
|
{
|
|
char *name;
|
|
char *dir;
|
|
} SFLogin;
|
|
|
|
static int SFdoNotTouchDirPtr = 0;
|
|
|
|
static int SFdoNotTouchVorigin = 0;
|
|
|
|
static SFDir SFrootDir, SFhomeDir;
|
|
|
|
static SFLogin *SFlogins;
|
|
|
|
static int SFtwiddle = 0;
|
|
|
|
static int
|
|
SFchdir(char *path)
|
|
{
|
|
int result;
|
|
|
|
result = 0;
|
|
|
|
if (strcmp(path, SFcurrentDir))
|
|
{
|
|
result = mch_chdir(path);
|
|
if (!result)
|
|
(void) strcpy(SFcurrentDir, path);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static void
|
|
SFfree(int i)
|
|
{
|
|
SFDir *dir;
|
|
int j;
|
|
|
|
dir = &(SFdirs[i]);
|
|
|
|
for (j = dir->nEntries - 1; j >= 0; j--)
|
|
{
|
|
if (dir->entries[j].shown != dir->entries[j].real)
|
|
XtFree(dir->entries[j].shown);
|
|
XtFree(dir->entries[j].real);
|
|
}
|
|
|
|
XtFree((char *)dir->entries);
|
|
XtFree(dir->dir);
|
|
|
|
dir->dir = NULL;
|
|
}
|
|
|
|
static void
|
|
SFstrdup(char **s1, char *s2)
|
|
{
|
|
*s1 = strcpy(XtMalloc((unsigned)(strlen(s2) + 1)), s2);
|
|
}
|
|
|
|
static void
|
|
SFunreadableDir(SFDir *dir)
|
|
{
|
|
char *cannotOpen = _("<cannot open> ");
|
|
|
|
dir->entries = (SFEntry *) XtMalloc(sizeof(SFEntry));
|
|
dir->entries[0].statDone = 1;
|
|
SFstrdup(&dir->entries[0].real, cannotOpen);
|
|
dir->entries[0].shown = dir->entries[0].real;
|
|
dir->nEntries = 1;
|
|
dir->nChars = strlen(cannotOpen);
|
|
}
|
|
|
|
static void
|
|
SFreplaceText(SFDir *dir, char *str)
|
|
{
|
|
int len;
|
|
|
|
*(dir->path) = 0;
|
|
len = strlen(str);
|
|
if (str[len - 1] == '/')
|
|
(void) strcat(SFcurrentPath, str);
|
|
else
|
|
(void) strncat(SFcurrentPath, str, len - 1);
|
|
if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir)))
|
|
SFsetText(SFcurrentPath);
|
|
else
|
|
SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
|
|
|
|
SFtextChanged();
|
|
}
|
|
|
|
static void
|
|
SFexpand(char *str)
|
|
{
|
|
int len;
|
|
int cmp;
|
|
char *name, *growing;
|
|
SFDir *dir;
|
|
SFEntry *entry, *max;
|
|
|
|
len = strlen(str);
|
|
|
|
dir = &(SFdirs[SFdirEnd - 1]);
|
|
|
|
if (dir->beginSelection == -1)
|
|
{
|
|
SFstrdup(&str, str);
|
|
SFreplaceText(dir, str);
|
|
XtFree(str);
|
|
return;
|
|
}
|
|
else if (dir->beginSelection == dir->endSelection)
|
|
{
|
|
SFreplaceText(dir, dir->entries[dir->beginSelection].shown);
|
|
return;
|
|
}
|
|
|
|
max = &(dir->entries[dir->endSelection + 1]);
|
|
|
|
name = dir->entries[dir->beginSelection].shown;
|
|
SFstrdup(&growing, name);
|
|
|
|
cmp = 0;
|
|
while (!cmp)
|
|
{
|
|
entry = &(dir->entries[dir->beginSelection]);
|
|
while (entry < max)
|
|
{
|
|
if ((cmp = strncmp(growing, entry->shown, len)))
|
|
break;
|
|
entry++;
|
|
}
|
|
len++;
|
|
}
|
|
|
|
/*
|
|
* SFreplaceText() expects filename
|
|
*/
|
|
growing[len - 2] = ' ';
|
|
|
|
growing[len - 1] = 0;
|
|
SFreplaceText(dir, growing);
|
|
XtFree(growing);
|
|
}
|
|
|
|
static int
|
|
SFfindFile(SFDir *dir, char *str)
|
|
{
|
|
int i, last, max;
|
|
char *name, save;
|
|
SFEntry *entries;
|
|
int len;
|
|
int begin, end;
|
|
int result;
|
|
|
|
len = strlen(str);
|
|
|
|
if (str[len - 1] == ' ')
|
|
{
|
|
SFexpand(str);
|
|
return 1;
|
|
}
|
|
else if (str[len - 1] == '/')
|
|
len--;
|
|
|
|
max = dir->nEntries;
|
|
|
|
entries = dir->entries;
|
|
|
|
i = 0;
|
|
while (i < max)
|
|
{
|
|
name = entries[i].shown;
|
|
last = strlen(name) - 1;
|
|
save = name[last];
|
|
name[last] = 0;
|
|
|
|
result = strncmp(str, name, len);
|
|
|
|
name[last] = save;
|
|
if (result <= 0)
|
|
break;
|
|
i++;
|
|
}
|
|
begin = i;
|
|
while (i < max)
|
|
{
|
|
name = entries[i].shown;
|
|
last = strlen(name) - 1;
|
|
save = name[last];
|
|
name[last] = 0;
|
|
|
|
result = strncmp(str, name, len);
|
|
|
|
name[last] = save;
|
|
if (result)
|
|
break;
|
|
i++;
|
|
}
|
|
end = i;
|
|
|
|
if (begin != end)
|
|
{
|
|
if ((dir->beginSelection != begin) || (dir->endSelection != end - 1))
|
|
{
|
|
dir->changed = 1;
|
|
dir->beginSelection = begin;
|
|
if (str[strlen(str) - 1] == '/')
|
|
dir->endSelection = begin;
|
|
else
|
|
dir->endSelection = end - 1;
|
|
}
|
|
}
|
|
else if (dir->beginSelection != -1)
|
|
{
|
|
dir->changed = 1;
|
|
dir->beginSelection = -1;
|
|
dir->endSelection = -1;
|
|
}
|
|
|
|
if (SFdoNotTouchVorigin
|
|
|| ((begin > dir->vOrigin) && (end < dir->vOrigin + SFlistSize)))
|
|
{
|
|
SFdoNotTouchVorigin = 0;
|
|
return 0;
|
|
}
|
|
|
|
i = begin - 1;
|
|
if (i > max - SFlistSize)
|
|
i = max - SFlistSize;
|
|
if (i < 0)
|
|
i = 0;
|
|
|
|
if (dir->vOrigin != i)
|
|
{
|
|
dir->vOrigin = i;
|
|
dir->changed = 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
SFunselect(void)
|
|
{
|
|
SFDir *dir;
|
|
|
|
dir = &(SFdirs[SFdirEnd - 1]);
|
|
if (dir->beginSelection != -1)
|
|
dir->changed = 1;
|
|
dir->beginSelection = -1;
|
|
dir->endSelection = -1;
|
|
}
|
|
|
|
static int
|
|
SFcompareLogins(const void *p, const void *q)
|
|
{
|
|
return strcmp(((SFLogin *)p)->name, ((SFLogin *)q)->name);
|
|
}
|
|
|
|
static void
|
|
SFgetHomeDirs(void)
|
|
{
|
|
struct passwd *pw;
|
|
int Alloc;
|
|
int i;
|
|
SFEntry *entries = NULL;
|
|
int len;
|
|
int maxChars;
|
|
|
|
Alloc = 1;
|
|
i = 1;
|
|
entries = (SFEntry *)XtMalloc(sizeof(SFEntry));
|
|
SFlogins = (SFLogin *)XtMalloc(sizeof(SFLogin));
|
|
entries[0].real = XtMalloc(3);
|
|
(void) strcpy(entries[0].real, "~");
|
|
entries[0].shown = entries[0].real;
|
|
entries[0].statDone = 1;
|
|
SFlogins[0].name = "";
|
|
pw = getpwuid((int) getuid());
|
|
SFstrdup(&SFlogins[0].dir, pw ? pw->pw_dir : "/");
|
|
maxChars = 0;
|
|
|
|
(void) setpwent();
|
|
|
|
while ((pw = getpwent()) && (*(pw->pw_name)))
|
|
{
|
|
if (i >= Alloc)
|
|
{
|
|
Alloc *= 2;
|
|
entries = (SFEntry *) XtRealloc((char *)entries,
|
|
(unsigned)(Alloc * sizeof(SFEntry)));
|
|
SFlogins = (SFLogin *) XtRealloc((char *)SFlogins,
|
|
(unsigned)(Alloc * sizeof(SFLogin)));
|
|
}
|
|
len = strlen(pw->pw_name);
|
|
entries[i].real = XtMalloc((unsigned)(len + 3));
|
|
(void) strcat(strcpy(entries[i].real, "~"), pw->pw_name);
|
|
entries[i].shown = entries[i].real;
|
|
entries[i].statDone = 1;
|
|
if (len > maxChars)
|
|
maxChars = len;
|
|
SFstrdup(&SFlogins[i].name, pw->pw_name);
|
|
SFstrdup(&SFlogins[i].dir, pw->pw_dir);
|
|
i++;
|
|
}
|
|
|
|
SFhomeDir.dir = XtMalloc(1);
|
|
SFhomeDir.dir[0] = 0;
|
|
SFhomeDir.path = SFcurrentPath;
|
|
SFhomeDir.entries = entries;
|
|
SFhomeDir.nEntries = i;
|
|
SFhomeDir.vOrigin = 0; // :-)
|
|
SFhomeDir.nChars = maxChars + 2;
|
|
SFhomeDir.hOrigin = 0;
|
|
SFhomeDir.changed = 1;
|
|
SFhomeDir.beginSelection = -1;
|
|
SFhomeDir.endSelection = -1;
|
|
|
|
qsort((char *)entries, (size_t)i, sizeof(SFEntry), SFcompareEntries);
|
|
qsort((char *)SFlogins, (size_t)i, sizeof(SFLogin), SFcompareLogins);
|
|
|
|
for (i--; i >= 0; i--)
|
|
(void)strcat(entries[i].real, "/");
|
|
}
|
|
|
|
static int
|
|
SFfindHomeDir(char *begin, char *end)
|
|
{
|
|
char save;
|
|
char *theRest;
|
|
int i;
|
|
|
|
save = *end;
|
|
*end = 0;
|
|
|
|
for (i = SFhomeDir.nEntries - 1; i >= 0; i--)
|
|
{
|
|
if (!strcmp(SFhomeDir.entries[i].real, begin))
|
|
{
|
|
*end = save;
|
|
SFstrdup(&theRest, end);
|
|
(void) strcat(strcat(strcpy(SFcurrentPath,
|
|
SFlogins[i].dir), "/"), theRest);
|
|
XtFree(theRest);
|
|
SFsetText(SFcurrentPath);
|
|
SFtextChanged();
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
*end = save;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
SFupdatePath(void)
|
|
{
|
|
static int Alloc;
|
|
static int wasTwiddle = 0;
|
|
char *begin, *end;
|
|
int i, j;
|
|
int prevChange;
|
|
int SFdirPtrSave, SFdirEndSave;
|
|
SFDir *dir;
|
|
|
|
if (!SFdirs)
|
|
{
|
|
SFdirs = (SFDir *) XtMalloc((Alloc = 10) * sizeof(SFDir));
|
|
dir = &(SFdirs[0]);
|
|
SFstrdup(&dir->dir, "/");
|
|
(void) SFchdir("/");
|
|
(void) SFgetDir(dir);
|
|
for (j = 1; j < Alloc; j++)
|
|
SFdirs[j].dir = NULL;
|
|
dir->path = SFcurrentPath + 1;
|
|
dir->vOrigin = 0;
|
|
dir->hOrigin = 0;
|
|
dir->changed = 1;
|
|
dir->beginSelection = -1;
|
|
dir->endSelection = -1;
|
|
SFhomeDir.dir = NULL;
|
|
}
|
|
|
|
SFdirEndSave = SFdirEnd;
|
|
SFdirEnd = 1;
|
|
|
|
SFdirPtrSave = SFdirPtr;
|
|
SFdirPtr = 0;
|
|
|
|
begin = NULL;
|
|
|
|
if (SFcurrentPath[0] == '~')
|
|
{
|
|
if (!SFtwiddle)
|
|
{
|
|
SFtwiddle = 1;
|
|
dir = &(SFdirs[0]);
|
|
SFrootDir = *dir;
|
|
if (!SFhomeDir.dir)
|
|
SFgetHomeDirs();
|
|
*dir = SFhomeDir;
|
|
dir->changed = 1;
|
|
}
|
|
end = SFcurrentPath;
|
|
SFdoNotTouchDirPtr = 1;
|
|
wasTwiddle = 1;
|
|
}
|
|
else
|
|
{
|
|
if (SFtwiddle)
|
|
{
|
|
SFtwiddle = 0;
|
|
dir = &(SFdirs[0]);
|
|
*dir = SFrootDir;
|
|
dir->changed = 1;
|
|
}
|
|
end = SFcurrentPath + 1;
|
|
}
|
|
|
|
i = 0;
|
|
|
|
prevChange = 0;
|
|
|
|
while (*end)
|
|
{
|
|
while (*end++ == '/')
|
|
;
|
|
end--;
|
|
begin = end;
|
|
while ((*end) && (*end++ != '/'))
|
|
;
|
|
if ((end - SFcurrentPath <= SFtextPos) && (*(end - 1) == '/'))
|
|
{
|
|
SFdirPtr = i - 1;
|
|
if (SFdirPtr < 0)
|
|
SFdirPtr = 0;
|
|
}
|
|
if (*begin)
|
|
{
|
|
if (*(end - 1) == '/')
|
|
{
|
|
char save = *end;
|
|
|
|
if (SFtwiddle)
|
|
{
|
|
if (SFfindHomeDir(begin, end))
|
|
return;
|
|
}
|
|
*end = 0;
|
|
i++;
|
|
SFdirEnd++;
|
|
if (i >= Alloc)
|
|
{
|
|
SFdirs = (SFDir *) XtRealloc((char *) SFdirs,
|
|
(unsigned)((Alloc *= 2) * sizeof(SFDir)));
|
|
for (j = Alloc / 2; j < Alloc; j++)
|
|
SFdirs[j].dir = NULL;
|
|
}
|
|
dir = &(SFdirs[i]);
|
|
if ((!(dir->dir)) || prevChange || strcmp(dir->dir, begin))
|
|
{
|
|
if (dir->dir)
|
|
SFfree(i);
|
|
prevChange = 1;
|
|
SFstrdup(&dir->dir, begin);
|
|
dir->path = end;
|
|
dir->vOrigin = 0;
|
|
dir->hOrigin = 0;
|
|
dir->changed = 1;
|
|
dir->beginSelection = -1;
|
|
dir->endSelection = -1;
|
|
(void)SFfindFile(dir - 1, begin);
|
|
if (SFchdir(SFcurrentPath) || SFgetDir(dir))
|
|
{
|
|
SFunreadableDir(dir);
|
|
break;
|
|
}
|
|
}
|
|
*end = save;
|
|
if (!save)
|
|
SFunselect();
|
|
}
|
|
else
|
|
{
|
|
if (SFfindFile(&(SFdirs[SFdirEnd-1]), begin))
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
SFunselect();
|
|
}
|
|
|
|
if ((end == SFcurrentPath + 1) && (!SFtwiddle))
|
|
SFunselect();
|
|
|
|
for (i = SFdirEnd; i < Alloc; i++)
|
|
if (SFdirs[i].dir)
|
|
SFfree(i);
|
|
|
|
if (SFdoNotTouchDirPtr)
|
|
{
|
|
if (wasTwiddle)
|
|
{
|
|
wasTwiddle = 0;
|
|
SFdirPtr = SFdirEnd - 2;
|
|
if (SFdirPtr < 0)
|
|
SFdirPtr = 0;
|
|
}
|
|
else
|
|
SFdirPtr = SFdirPtrSave;
|
|
SFdoNotTouchDirPtr = 0;
|
|
}
|
|
|
|
if ((SFdirPtr != SFdirPtrSave) || (SFdirEnd != SFdirEndSave))
|
|
{
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
XawScrollbarSetThumb( selFileHScroll,
|
|
(float) (((double) SFdirPtr) / SFdirEnd),
|
|
(float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
|
|
SFdirEnd));
|
|
#else
|
|
vim_XawScrollbarSetThumb( selFileHScroll,
|
|
(float) (((double) SFdirPtr) / SFdirEnd),
|
|
(float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) /
|
|
SFdirEnd),
|
|
(double)SFdirEnd);
|
|
#endif
|
|
}
|
|
|
|
if (SFdirPtr != SFdirPtrSave)
|
|
SFdrawLists(SF_DO_SCROLL);
|
|
else
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
if (SFdirPtr + i < SFdirEnd)
|
|
{
|
|
if (SFdirs[SFdirPtr + i].changed)
|
|
{
|
|
SFdirs[SFdirPtr + i].changed = 0;
|
|
SFdrawList(i, SF_DO_SCROLL);
|
|
}
|
|
}
|
|
else
|
|
SFclearList(i, SF_DO_SCROLL);
|
|
}
|
|
}
|
|
|
|
#ifdef XtNinternational
|
|
static int
|
|
WcsLen(wchar_t *p)
|
|
{
|
|
int i = 0;
|
|
while (*p++ != 0)
|
|
i++;
|
|
return i;
|
|
}
|
|
#endif
|
|
|
|
static void
|
|
SFsetText(char *path)
|
|
{
|
|
XawTextBlock text;
|
|
|
|
text.firstPos = 0;
|
|
text.length = strlen(path);
|
|
text.ptr = path;
|
|
text.format = FMT8BIT;
|
|
|
|
#ifdef XtNinternational
|
|
if ((unsigned long)_XawTextFormat((TextWidget)selFileField) == XawFmtWide)
|
|
{
|
|
XawTextReplace(selFileField, (XawTextPosition)0,
|
|
(XawTextPosition)WcsLen((wchar_t *)&SFtextBuffer[0]), &text);
|
|
XawTextSetInsertionPoint(selFileField,
|
|
(XawTextPosition)WcsLen((wchar_t *)&SFtextBuffer[0]));
|
|
}
|
|
else
|
|
{
|
|
XawTextReplace(selFileField, (XawTextPosition)0,
|
|
(XawTextPosition)strlen(SFtextBuffer), &text);
|
|
XawTextSetInsertionPoint(selFileField,
|
|
(XawTextPosition)strlen(SFtextBuffer));
|
|
}
|
|
#else
|
|
XawTextReplace(selFileField, (XawTextPosition)0,
|
|
(XawTextPosition)strlen(SFtextBuffer), &text);
|
|
XawTextSetInsertionPoint(selFileField,
|
|
(XawTextPosition)strlen(SFtextBuffer));
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
SFbuttonPressList(
|
|
Widget w UNUSED,
|
|
XtPointer np UNUSED,
|
|
XEvent *event UNUSED,
|
|
Boolean *cont UNUSED)
|
|
{
|
|
SFbuttonPressed = 1;
|
|
}
|
|
|
|
static void
|
|
SFbuttonReleaseList(
|
|
Widget w UNUSED,
|
|
XtPointer np,
|
|
XEvent *event UNUSED,
|
|
Boolean *cont UNUSED)
|
|
{
|
|
long n = (long)np;
|
|
SFDir *dir;
|
|
|
|
SFbuttonPressed = 0;
|
|
|
|
if (SFcurrentInvert[n] != -1)
|
|
{
|
|
if (n < 2)
|
|
SFdoNotTouchDirPtr = 1;
|
|
SFdoNotTouchVorigin = 1;
|
|
dir = &(SFdirs[SFdirPtr + n]);
|
|
SFreplaceText(dir,
|
|
dir->entries[dir->vOrigin + SFcurrentInvert[n]].shown);
|
|
SFmotionList(w, (XtPointer)(long)n, (XMotionEvent *)event, 0);
|
|
}
|
|
}
|
|
|
|
static int
|
|
SFcheckDir(int n, SFDir *dir)
|
|
{
|
|
stat_T statBuf;
|
|
int i;
|
|
|
|
if ((!mch_stat(".", &statBuf)) && (statBuf.st_mtime != dir->mtime))
|
|
{
|
|
/*
|
|
* If the pointer is currently in the window that we are about
|
|
* to update, we must warp it to prevent the user from
|
|
* accidentally selecting the wrong file.
|
|
*/
|
|
if (SFcurrentInvert[n] != -1)
|
|
{
|
|
XWarpPointer(
|
|
SFdisplay,
|
|
None,
|
|
XtWindow(selFileLists[n]),
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0);
|
|
}
|
|
|
|
for (i = dir->nEntries - 1; i >= 0; i--)
|
|
{
|
|
if (dir->entries[i].shown != dir->entries[i].real)
|
|
XtFree(dir->entries[i].shown);
|
|
XtFree(dir->entries[i].real);
|
|
}
|
|
XtFree((char *) dir->entries);
|
|
if (SFgetDir(dir))
|
|
SFunreadableDir(dir);
|
|
if (dir->vOrigin > dir->nEntries - SFlistSize)
|
|
dir->vOrigin = dir->nEntries - SFlistSize;
|
|
if (dir->vOrigin < 0)
|
|
dir->vOrigin = 0;
|
|
if (dir->hOrigin > dir->nChars - SFcharsPerEntry)
|
|
dir->hOrigin = dir->nChars - SFcharsPerEntry;
|
|
if (dir->hOrigin < 0)
|
|
dir->hOrigin = 0;
|
|
dir->beginSelection = -1;
|
|
dir->endSelection = -1;
|
|
SFdoNotTouchVorigin = 1;
|
|
if ((dir + 1)->dir)
|
|
(void) SFfindFile(dir, (dir + 1)->dir);
|
|
else
|
|
(void) SFfindFile(dir, dir->path);
|
|
|
|
if (!SFworkProcAdded)
|
|
{
|
|
(void) XtAppAddWorkProc(SFapp, (XtWorkProc)SFworkProc, NULL);
|
|
SFworkProcAdded = 1;
|
|
}
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
SFcheckFiles(SFDir *dir)
|
|
{
|
|
int from, to;
|
|
int result;
|
|
char oldc, newc;
|
|
int i;
|
|
char *str;
|
|
int last;
|
|
stat_T statBuf;
|
|
|
|
result = 0;
|
|
|
|
from = dir->vOrigin;
|
|
to = dir->vOrigin + SFlistSize;
|
|
if (to > dir->nEntries)
|
|
to = dir->nEntries;
|
|
|
|
for (i = from; i < to; i++)
|
|
{
|
|
str = dir->entries[i].real;
|
|
last = strlen(str) - 1;
|
|
oldc = str[last];
|
|
str[last] = 0;
|
|
if (mch_stat(str, &statBuf))
|
|
newc = ' ';
|
|
else
|
|
newc = SFstatChar(&statBuf);
|
|
str[last] = newc;
|
|
if (newc != oldc)
|
|
result = 1;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static void
|
|
SFdirModTimer(XtPointer cl UNUSED, XtIntervalId *id UNUSED)
|
|
{
|
|
static int n = -1;
|
|
static int f = 0;
|
|
char save;
|
|
SFDir *dir;
|
|
|
|
if ((!SFtwiddle) && (SFdirPtr < SFdirEnd))
|
|
{
|
|
n++;
|
|
if ((n > 2) || (SFdirPtr + n >= SFdirEnd))
|
|
{
|
|
n = 0;
|
|
f++;
|
|
if ((f > 2) || (SFdirPtr + f >= SFdirEnd))
|
|
f = 0;
|
|
}
|
|
dir = &(SFdirs[SFdirPtr + n]);
|
|
save = *(dir->path);
|
|
*(dir->path) = 0;
|
|
if (SFchdir(SFcurrentPath))
|
|
{
|
|
*(dir->path) = save;
|
|
|
|
/*
|
|
* force a re-read
|
|
*/
|
|
*(dir->dir) = 0;
|
|
|
|
SFupdatePath();
|
|
}
|
|
else
|
|
{
|
|
*(dir->path) = save;
|
|
if (SFcheckDir(n, dir) || ((f == n) && SFcheckFiles(dir)))
|
|
SFdrawList(n, SF_DO_SCROLL);
|
|
}
|
|
}
|
|
|
|
SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
|
|
SFdirModTimer, (XtPointer) NULL);
|
|
}
|
|
|
|
// Return a single character describing what kind of file STATBUF is.
|
|
|
|
static char
|
|
SFstatChar(stat_T *statBuf)
|
|
{
|
|
if (S_ISDIR (statBuf->st_mode))
|
|
return '/';
|
|
if (S_ISREG (statBuf->st_mode))
|
|
return S_ISXXX (statBuf->st_mode) ? '*' : ' ';
|
|
#ifdef S_ISSOCK
|
|
if (S_ISSOCK (statBuf->st_mode))
|
|
return '=';
|
|
#endif // S_ISSOCK
|
|
return ' ';
|
|
}
|
|
|
|
////////////////// Draw.c
|
|
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
# include <X11/neXtaw/Cardinals.h>
|
|
#else
|
|
# include <X11/Xaw/Cardinals.h>
|
|
#endif
|
|
|
|
#ifdef FEAT_XFONTSET
|
|
# define SF_DEFAULT_FONT "-misc-fixed-medium-r-normal--14-*"
|
|
#else
|
|
# define SF_DEFAULT_FONT "9x15"
|
|
#endif
|
|
|
|
#ifdef ABS
|
|
# undef ABS
|
|
#endif
|
|
#define ABS(x) (((x) < 0) ? (-(x)) : (x))
|
|
|
|
typedef struct
|
|
{
|
|
char *fontname;
|
|
} TextData;
|
|
|
|
static GC SFlineGC, SFscrollGC, SFinvertGC, SFtextGC;
|
|
|
|
static XtResource textResources[] =
|
|
{
|
|
#ifdef FEAT_XFONTSET
|
|
{XtNfontSet, XtCFontSet, XtRString, sizeof (char *),
|
|
XtOffsetOf(TextData, fontname), XtRString, SF_DEFAULT_FONT},
|
|
#else
|
|
{XtNfont, XtCFont, XtRString, sizeof (char *),
|
|
XtOffsetOf(TextData, fontname), XtRString, SF_DEFAULT_FONT},
|
|
#endif
|
|
};
|
|
|
|
#ifdef FEAT_XFONTSET
|
|
static XFontSet SFfont;
|
|
#else
|
|
static XFontStruct *SFfont;
|
|
#endif
|
|
|
|
static int SFcurrentListY;
|
|
|
|
static XtIntervalId SFscrollTimerId;
|
|
|
|
static void
|
|
SFinitFont(void)
|
|
{
|
|
TextData *data;
|
|
#ifdef FEAT_XFONTSET
|
|
XFontSetExtents *extents;
|
|
char **missing, *def_str;
|
|
int num_missing;
|
|
#endif
|
|
|
|
data = XtNew(TextData);
|
|
|
|
XtGetApplicationResources(selFileForm, (XtPointer) data, textResources,
|
|
XtNumber(textResources), (Arg *) NULL, ZERO);
|
|
|
|
#ifdef FEAT_XFONTSET
|
|
SFfont = XCreateFontSet(SFdisplay, data->fontname,
|
|
&missing, &num_missing, &def_str);
|
|
#else
|
|
SFfont = XLoadQueryFont(SFdisplay, data->fontname);
|
|
#endif
|
|
if (!SFfont)
|
|
{
|
|
#ifdef FEAT_XFONTSET
|
|
SFfont = XCreateFontSet(SFdisplay, SF_DEFAULT_FONT,
|
|
&missing, &num_missing, &def_str);
|
|
#else
|
|
SFfont = XLoadQueryFont(SFdisplay, SF_DEFAULT_FONT);
|
|
#endif
|
|
if (!SFfont)
|
|
{
|
|
semsg(_("E616: vim_SelFile: can't get font %s"), SF_DEFAULT_FONT);
|
|
SFstatus = SEL_FILE_CANCEL;
|
|
return;
|
|
}
|
|
}
|
|
|
|
#ifdef FEAT_XFONTSET
|
|
extents = XExtentsOfFontSet(SFfont);
|
|
SFcharWidth = extents->max_logical_extent.width;
|
|
SFcharAscent = -extents->max_logical_extent.y;
|
|
SFcharHeight = extents->max_logical_extent.height;
|
|
#else
|
|
SFcharWidth = (SFfont->max_bounds.width + SFfont->min_bounds.width) / 2;
|
|
SFcharAscent = SFfont->max_bounds.ascent;
|
|
SFcharHeight = SFcharAscent + SFfont->max_bounds.descent;
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
SFcreateGC(void)
|
|
{
|
|
XGCValues gcValues;
|
|
XRectangle rectangles[1];
|
|
|
|
gcValues.foreground = SFfore;
|
|
|
|
SFlineGC = XtGetGC(
|
|
selFileLists[0],
|
|
(XtGCMask)GCForeground,
|
|
&gcValues);
|
|
|
|
SFscrollGC = XtGetGC(
|
|
selFileLists[0],
|
|
(XtGCMask)0,
|
|
&gcValues);
|
|
|
|
gcValues.function = GXxor;
|
|
gcValues.foreground = SFfore ^ SFback;
|
|
gcValues.background = SFfore ^ SFback;
|
|
|
|
SFinvertGC = XtGetGC(
|
|
selFileLists[0],
|
|
(XtGCMask)GCFunction | GCForeground | GCBackground,
|
|
&gcValues);
|
|
|
|
gcValues.foreground = SFfore;
|
|
gcValues.background = SFback;
|
|
#ifndef FEAT_XFONTSET
|
|
gcValues.font = SFfont->fid;
|
|
#endif
|
|
|
|
SFtextGC = XCreateGC(
|
|
SFdisplay,
|
|
XtWindow(selFileLists[0]),
|
|
#ifdef FEAT_XFONTSET
|
|
(unsigned long)GCForeground | GCBackground,
|
|
#else
|
|
(unsigned long)GCForeground | GCBackground | GCFont,
|
|
#endif
|
|
&gcValues);
|
|
|
|
rectangles[0].x = SFlineToTextH + SFbesideText;
|
|
rectangles[0].y = 0;
|
|
rectangles[0].width = SFcharsPerEntry * SFcharWidth;
|
|
rectangles[0].height = SFupperY + 1;
|
|
|
|
XSetClipRectangles(
|
|
SFdisplay,
|
|
SFtextGC,
|
|
0,
|
|
0,
|
|
rectangles,
|
|
1,
|
|
Unsorted);
|
|
}
|
|
|
|
static void
|
|
SFclearList(int n, int doScroll)
|
|
{
|
|
SFDir *dir;
|
|
|
|
SFcurrentInvert[n] = -1;
|
|
|
|
XClearWindow(SFdisplay, XtWindow(selFileLists[n]));
|
|
|
|
XDrawSegments(SFdisplay, XtWindow(selFileLists[n]), SFlineGC, SFsegs, 2);
|
|
|
|
if (doScroll)
|
|
{
|
|
dir = &(SFdirs[SFdirPtr + n]);
|
|
|
|
if ((SFdirPtr + n < SFdirEnd) && dir->nEntries && dir->nChars)
|
|
{
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
XawScrollbarSetThumb(
|
|
selFileVScrolls[n],
|
|
(float) (((double) dir->vOrigin) /
|
|
dir->nEntries),
|
|
(float) (((double) ((dir->nEntries < SFlistSize)
|
|
? dir->nEntries : SFlistSize)) /
|
|
dir->nEntries));
|
|
#else
|
|
vim_XawScrollbarSetThumb(
|
|
selFileVScrolls[n],
|
|
(float) (((double) dir->vOrigin) /
|
|
dir->nEntries),
|
|
(float) (((double) ((dir->nEntries < SFlistSize)
|
|
? dir->nEntries : SFlistSize)) /
|
|
dir->nEntries),
|
|
(double)dir->nEntries);
|
|
#endif
|
|
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
XawScrollbarSetThumb(
|
|
selFileHScrolls[n],
|
|
(float) (((double) dir->hOrigin) / dir->nChars),
|
|
(float) (((double) ((dir->nChars <
|
|
SFcharsPerEntry) ? dir->nChars :
|
|
SFcharsPerEntry)) / dir->nChars));
|
|
#else
|
|
vim_XawScrollbarSetThumb(
|
|
selFileHScrolls[n],
|
|
(float) (((double) dir->hOrigin) / dir->nChars),
|
|
(float) (((double) ((dir->nChars <
|
|
SFcharsPerEntry) ? dir->nChars :
|
|
SFcharsPerEntry)) / dir->nChars),
|
|
(double)dir->nChars);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
|
|
(float) 1.0);
|
|
#else
|
|
vim_XawScrollbarSetThumb(selFileVScrolls[n], (float) 0.0,
|
|
(float) 1.0, 1.0);
|
|
#endif
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
|
|
(float) 1.0);
|
|
#else
|
|
vim_XawScrollbarSetThumb(selFileHScrolls[n], (float) 0.0,
|
|
(float) 1.0, 1.0);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
SFdeleteEntry(SFDir *dir, SFEntry *entry)
|
|
{
|
|
SFEntry *e;
|
|
SFEntry *end;
|
|
int n;
|
|
int idx;
|
|
|
|
idx = entry - dir->entries;
|
|
|
|
if (idx < dir->beginSelection)
|
|
dir->beginSelection--;
|
|
if (idx <= dir->endSelection)
|
|
dir->endSelection--;
|
|
if (dir->beginSelection > dir->endSelection)
|
|
dir->beginSelection = dir->endSelection = -1;
|
|
|
|
if (idx < dir->vOrigin)
|
|
dir->vOrigin--;
|
|
|
|
XtFree(entry->real);
|
|
|
|
end = &(dir->entries[dir->nEntries - 1]);
|
|
|
|
for (e = entry; e < end; e++)
|
|
*e = *(e + 1);
|
|
|
|
if (!(--dir->nEntries))
|
|
return;
|
|
|
|
n = dir - &(SFdirs[SFdirPtr]);
|
|
if ((n < 0) || (n > 2))
|
|
return;
|
|
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
XawScrollbarSetThumb(
|
|
selFileVScrolls[n],
|
|
(float) (((double) dir->vOrigin) / dir->nEntries),
|
|
(float) (((double) ((dir->nEntries < SFlistSize) ?
|
|
dir->nEntries : SFlistSize)) / dir->nEntries));
|
|
#else
|
|
vim_XawScrollbarSetThumb(
|
|
selFileVScrolls[n],
|
|
(float) (((double) dir->vOrigin) / dir->nEntries),
|
|
(float) (((double) ((dir->nEntries < SFlistSize) ?
|
|
dir->nEntries : SFlistSize)) / dir->nEntries),
|
|
(double)dir->nEntries);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
SFwriteStatChar(
|
|
char *name,
|
|
int last,
|
|
stat_T *statBuf)
|
|
{
|
|
name[last] = SFstatChar(statBuf);
|
|
}
|
|
|
|
static int
|
|
SFstatAndCheck(SFDir *dir, SFEntry *entry)
|
|
{
|
|
stat_T statBuf;
|
|
char save;
|
|
int last;
|
|
|
|
/*
|
|
* must be restored before returning
|
|
*/
|
|
save = *(dir->path);
|
|
*(dir->path) = 0;
|
|
|
|
if (!SFchdir(SFcurrentPath))
|
|
{
|
|
last = strlen(entry->real) - 1;
|
|
entry->real[last] = 0;
|
|
entry->statDone = 1;
|
|
if ((!mch_stat(entry->real, &statBuf))
|
|
#ifdef S_IFLNK
|
|
|| (!mch_lstat(entry->real, &statBuf))
|
|
#endif
|
|
)
|
|
{
|
|
if (SFfunc)
|
|
{
|
|
char *shown;
|
|
|
|
shown = NULL;
|
|
if (SFfunc(entry->real, &shown, &statBuf))
|
|
{
|
|
if (shown)
|
|
{
|
|
int len;
|
|
|
|
len = strlen(shown);
|
|
entry->shown = XtMalloc((unsigned)(len + 2));
|
|
(void) strcpy(entry->shown, shown);
|
|
SFwriteStatChar(entry->shown, len, &statBuf);
|
|
entry->shown[len + 1] = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SFdeleteEntry(dir, entry);
|
|
|
|
*(dir->path) = save;
|
|
return 1;
|
|
}
|
|
}
|
|
SFwriteStatChar(entry->real, last, &statBuf);
|
|
}
|
|
else
|
|
entry->real[last] = ' ';
|
|
}
|
|
|
|
*(dir->path) = save;
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void
|
|
SFdrawStrings(
|
|
Window w,
|
|
SFDir *dir,
|
|
int from,
|
|
int to)
|
|
{
|
|
int i;
|
|
SFEntry *entry;
|
|
int x;
|
|
|
|
x = SFtextX - dir->hOrigin * SFcharWidth;
|
|
|
|
if (dir->vOrigin + to >= dir->nEntries)
|
|
to = dir->nEntries - dir->vOrigin - 1;
|
|
for (i = from; i <= to; i++)
|
|
{
|
|
entry = &(dir->entries[dir->vOrigin + i]);
|
|
if (!(entry->statDone))
|
|
{
|
|
if (SFstatAndCheck(dir, entry))
|
|
{
|
|
if (dir->vOrigin + to >= dir->nEntries)
|
|
to = dir->nEntries - dir->vOrigin - 1;
|
|
i--;
|
|
continue;
|
|
}
|
|
}
|
|
#ifdef FEAT_XFONTSET
|
|
XmbDrawImageString(
|
|
SFdisplay,
|
|
w,
|
|
SFfont,
|
|
SFtextGC,
|
|
x,
|
|
SFtextYoffset + i * SFentryHeight,
|
|
entry->shown,
|
|
strlen(entry->shown));
|
|
#else
|
|
XDrawImageString(
|
|
SFdisplay,
|
|
w,
|
|
SFtextGC,
|
|
x,
|
|
SFtextYoffset + i * SFentryHeight,
|
|
entry->shown,
|
|
strlen(entry->shown));
|
|
#endif
|
|
if (dir->vOrigin + i == dir->beginSelection)
|
|
{
|
|
XDrawLine(
|
|
SFdisplay,
|
|
w,
|
|
SFlineGC,
|
|
SFlineToTextH + 1,
|
|
SFlowerY + i * SFentryHeight,
|
|
SFlineToTextH + SFentryWidth - 2,
|
|
SFlowerY + i * SFentryHeight);
|
|
}
|
|
if ((dir->vOrigin + i >= dir->beginSelection) &&
|
|
(dir->vOrigin + i <= dir->endSelection))
|
|
{
|
|
SFcompletionSegs[0].y1 = SFcompletionSegs[1].y1 =
|
|
SFlowerY + i * SFentryHeight;
|
|
SFcompletionSegs[0].y2 = SFcompletionSegs[1].y2 =
|
|
SFlowerY + (i + 1) * SFentryHeight - 1;
|
|
XDrawSegments(
|
|
SFdisplay,
|
|
w,
|
|
SFlineGC,
|
|
SFcompletionSegs,
|
|
2);
|
|
}
|
|
if (dir->vOrigin + i == dir->endSelection)
|
|
{
|
|
XDrawLine(
|
|
SFdisplay,
|
|
w,
|
|
SFlineGC,
|
|
SFlineToTextH + 1,
|
|
SFlowerY + (i + 1) * SFentryHeight - 1,
|
|
SFlineToTextH + SFentryWidth - 2,
|
|
SFlowerY + (i + 1) * SFentryHeight - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
SFdrawList(int n, int doScroll)
|
|
{
|
|
SFDir *dir;
|
|
Window w;
|
|
|
|
SFclearList(n, doScroll);
|
|
|
|
if (SFdirPtr + n < SFdirEnd)
|
|
{
|
|
dir = &(SFdirs[SFdirPtr + n]);
|
|
w = XtWindow(selFileLists[n]);
|
|
#ifdef FEAT_XFONTSET
|
|
XmbDrawImageString(
|
|
SFdisplay,
|
|
w,
|
|
SFfont,
|
|
SFtextGC,
|
|
SFtextX - dir->hOrigin * SFcharWidth,
|
|
SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
|
|
dir->dir,
|
|
strlen(dir->dir));
|
|
#else
|
|
XDrawImageString(
|
|
SFdisplay,
|
|
w,
|
|
SFtextGC,
|
|
SFtextX - dir->hOrigin * SFcharWidth,
|
|
SFlineToTextV + SFaboveAndBelowText + SFcharAscent,
|
|
dir->dir,
|
|
strlen(dir->dir));
|
|
#endif
|
|
SFdrawStrings(w, dir, 0, SFlistSize - 1);
|
|
}
|
|
}
|
|
|
|
static void
|
|
SFdrawLists(int doScroll)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 3; i++)
|
|
SFdrawList(i, doScroll);
|
|
}
|
|
|
|
static void
|
|
SFinvertEntry(int n)
|
|
{
|
|
XFillRectangle(
|
|
SFdisplay,
|
|
XtWindow(selFileLists[n]),
|
|
SFinvertGC,
|
|
SFlineToTextH,
|
|
SFcurrentInvert[n] * SFentryHeight + SFlowerY,
|
|
SFentryWidth,
|
|
SFentryHeight);
|
|
}
|
|
|
|
static unsigned long
|
|
SFscrollTimerInterval(void)
|
|
{
|
|
static int maxVal = 200;
|
|
static int varyDist = 50;
|
|
static int minDist = 50;
|
|
int t;
|
|
int dist;
|
|
|
|
if (SFcurrentListY < SFlowerY)
|
|
dist = SFlowerY - SFcurrentListY;
|
|
else if (SFcurrentListY > SFupperY)
|
|
dist = SFcurrentListY - SFupperY;
|
|
else
|
|
return (unsigned long) 1;
|
|
|
|
t = maxVal - ((maxVal / varyDist) * (dist - minDist));
|
|
|
|
if (t < 1)
|
|
t = 1;
|
|
|
|
if (t > maxVal)
|
|
t = maxVal;
|
|
|
|
return (unsigned long)t;
|
|
}
|
|
|
|
static void
|
|
SFscrollTimer(XtPointer p, XtIntervalId *id UNUSED)
|
|
{
|
|
SFDir *dir;
|
|
int save;
|
|
int n;
|
|
|
|
n = (long)p;
|
|
|
|
dir = &(SFdirs[SFdirPtr + n]);
|
|
save = dir->vOrigin;
|
|
|
|
if (SFcurrentListY < SFlowerY)
|
|
{
|
|
if (dir->vOrigin > 0)
|
|
SFvSliderMovedCallback(selFileVScrolls[n], n, dir->vOrigin - 1);
|
|
}
|
|
else if (SFcurrentListY > SFupperY)
|
|
{
|
|
if (dir->vOrigin < dir->nEntries - SFlistSize)
|
|
SFvSliderMovedCallback(selFileVScrolls[n], n, dir->vOrigin + 1);
|
|
}
|
|
|
|
if (dir->vOrigin != save)
|
|
{
|
|
if (dir->nEntries)
|
|
{
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
XawScrollbarSetThumb(
|
|
selFileVScrolls[n],
|
|
(float) (((double) dir->vOrigin) / dir->nEntries),
|
|
(float) (((double) ((dir->nEntries < SFlistSize) ?
|
|
dir->nEntries : SFlistSize)) / dir->nEntries));
|
|
#else
|
|
vim_XawScrollbarSetThumb(
|
|
selFileVScrolls[n],
|
|
(float) (((double) dir->vOrigin) / dir->nEntries),
|
|
(float) (((double) ((dir->nEntries < SFlistSize) ?
|
|
dir->nEntries : SFlistSize)) / dir->nEntries),
|
|
(double)dir->nEntries);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
if (SFbuttonPressed)
|
|
SFscrollTimerId = XtAppAddTimeOut(SFapp,
|
|
SFscrollTimerInterval(), SFscrollTimer,
|
|
(XtPointer)(long_u)n);
|
|
}
|
|
|
|
static int
|
|
SFnewInvertEntry(int n, XMotionEvent *event)
|
|
{
|
|
int x, y;
|
|
int nw;
|
|
static int SFscrollTimerAdded = 0;
|
|
|
|
x = event->x;
|
|
y = event->y;
|
|
|
|
if (SFdirPtr + n >= SFdirEnd)
|
|
return -1;
|
|
|
|
if ((x >= 0) && (x <= SFupperX) && (y >= SFlowerY) && (y <= SFupperY))
|
|
{
|
|
SFDir *dir = &(SFdirs[SFdirPtr + n]);
|
|
|
|
if (SFscrollTimerAdded)
|
|
{
|
|
SFscrollTimerAdded = 0;
|
|
XtRemoveTimeOut(SFscrollTimerId);
|
|
}
|
|
|
|
nw = (y - SFlowerY) / SFentryHeight;
|
|
if (dir->vOrigin + nw >= dir->nEntries)
|
|
return -1;
|
|
return nw;
|
|
}
|
|
else
|
|
{
|
|
if (SFbuttonPressed)
|
|
{
|
|
SFcurrentListY = y;
|
|
if (!SFscrollTimerAdded)
|
|
{
|
|
SFscrollTimerAdded = 1;
|
|
SFscrollTimerId = XtAppAddTimeOut(SFapp,
|
|
SFscrollTimerInterval(), SFscrollTimer,
|
|
(XtPointer)(long_u)n);
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
static void
|
|
SFenterList(
|
|
Widget w UNUSED,
|
|
XtPointer np,
|
|
XEvent *event,
|
|
Boolean *cont UNUSED)
|
|
{
|
|
long n = (long)np;
|
|
int nw;
|
|
|
|
// sanity
|
|
if (SFcurrentInvert[n] != -1)
|
|
{
|
|
SFinvertEntry(n);
|
|
SFcurrentInvert[n] = -1;
|
|
}
|
|
|
|
nw = SFnewInvertEntry(n, (XMotionEvent *) event);
|
|
if (nw != -1)
|
|
{
|
|
SFcurrentInvert[n] = nw;
|
|
SFinvertEntry(n);
|
|
}
|
|
}
|
|
|
|
static void
|
|
SFleaveList(
|
|
Widget w UNUSED,
|
|
XtPointer np,
|
|
XEvent *event UNUSED,
|
|
Boolean *cont UNUSED)
|
|
{
|
|
long n = (long)np;
|
|
|
|
if (SFcurrentInvert[n] != -1)
|
|
{
|
|
SFinvertEntry(n);
|
|
SFcurrentInvert[n] = -1;
|
|
}
|
|
}
|
|
|
|
static void
|
|
SFmotionList(
|
|
Widget w UNUSED,
|
|
XtPointer np,
|
|
XMotionEvent *event UNUSED,
|
|
Boolean *cont UNUSED)
|
|
{
|
|
long n = (long)np;
|
|
int nw;
|
|
|
|
nw = SFnewInvertEntry(n, event);
|
|
|
|
if (nw != SFcurrentInvert[n])
|
|
{
|
|
if (SFcurrentInvert[n] != -1)
|
|
SFinvertEntry(n);
|
|
SFcurrentInvert[n] = nw;
|
|
if (nw != -1)
|
|
SFinvertEntry(n);
|
|
}
|
|
}
|
|
|
|
static void
|
|
SFvFloatSliderMovedCallback(Widget w, XtPointer n, XtPointer fnew)
|
|
{
|
|
int nw;
|
|
|
|
nw = (*(float *)fnew) * SFdirs[SFdirPtr + (int)(long)n].nEntries;
|
|
SFvSliderMovedCallback(w, (int)(long)n, nw);
|
|
}
|
|
|
|
static void
|
|
SFvSliderMovedCallback(Widget w UNUSED, int n, int nw)
|
|
{
|
|
int old;
|
|
Window win;
|
|
SFDir *dir;
|
|
|
|
dir = &(SFdirs[SFdirPtr + n]);
|
|
|
|
old = dir->vOrigin;
|
|
dir->vOrigin = nw;
|
|
|
|
if (old == nw)
|
|
return;
|
|
|
|
win = XtWindow(selFileLists[n]);
|
|
|
|
if (ABS(nw - old) < SFlistSize)
|
|
{
|
|
if (nw > old)
|
|
{
|
|
XCopyArea(
|
|
SFdisplay,
|
|
win,
|
|
win,
|
|
SFscrollGC,
|
|
SFlineToTextH,
|
|
SFlowerY + (nw - old) * SFentryHeight,
|
|
SFentryWidth + SFlineToTextH,
|
|
(SFlistSize - (nw - old)) * SFentryHeight,
|
|
SFlineToTextH,
|
|
SFlowerY);
|
|
XClearArea(
|
|
SFdisplay,
|
|
win,
|
|
SFlineToTextH,
|
|
SFlowerY + (SFlistSize - (nw - old)) *
|
|
SFentryHeight,
|
|
SFentryWidth + SFlineToTextH,
|
|
(nw - old) * SFentryHeight,
|
|
False);
|
|
SFdrawStrings(win, dir, SFlistSize - (nw - old),
|
|
SFlistSize - 1);
|
|
}
|
|
else
|
|
{
|
|
XCopyArea(
|
|
SFdisplay,
|
|
win,
|
|
win,
|
|
SFscrollGC,
|
|
SFlineToTextH,
|
|
SFlowerY,
|
|
SFentryWidth + SFlineToTextH,
|
|
(SFlistSize - (old - nw)) * SFentryHeight,
|
|
SFlineToTextH,
|
|
SFlowerY + (old - nw) * SFentryHeight);
|
|
XClearArea(
|
|
SFdisplay,
|
|
win,
|
|
SFlineToTextH,
|
|
SFlowerY,
|
|
SFentryWidth + SFlineToTextH,
|
|
(old - nw) * SFentryHeight,
|
|
False);
|
|
SFdrawStrings(win, dir, 0, old - nw);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XClearArea(
|
|
SFdisplay,
|
|
win,
|
|
SFlineToTextH,
|
|
SFlowerY,
|
|
SFentryWidth + SFlineToTextH,
|
|
SFlistSize * SFentryHeight,
|
|
False);
|
|
SFdrawStrings(win, dir, 0, SFlistSize - 1);
|
|
}
|
|
}
|
|
|
|
static void
|
|
SFvAreaSelectedCallback(Widget w, XtPointer n, XtPointer pnew)
|
|
{
|
|
SFDir *dir;
|
|
int nw = (int)(long)pnew;
|
|
|
|
dir = &(SFdirs[SFdirPtr + (int)(long)n]);
|
|
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
if (nw < 0)
|
|
{
|
|
if (nw > -SFvScrollHeight)
|
|
nw = -1;
|
|
else
|
|
nw = -SFlistSize;
|
|
}
|
|
else if (nw > 0)
|
|
{
|
|
if (nw < SFvScrollHeight)
|
|
nw = 1;
|
|
else
|
|
nw = SFlistSize;
|
|
}
|
|
#endif
|
|
nw += dir->vOrigin;
|
|
|
|
if (nw > dir->nEntries - SFlistSize)
|
|
nw = dir->nEntries - SFlistSize;
|
|
|
|
if (nw < 0)
|
|
nw = 0;
|
|
|
|
if (dir->nEntries)
|
|
{
|
|
float f;
|
|
|
|
f = ((double) nw) / dir->nEntries;
|
|
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
XawScrollbarSetThumb(
|
|
w,
|
|
f,
|
|
(float) (((double) ((dir->nEntries < SFlistSize) ?
|
|
dir->nEntries : SFlistSize)) / dir->nEntries));
|
|
#else
|
|
vim_XawScrollbarSetThumb(
|
|
w,
|
|
f,
|
|
(float) (((double) ((dir->nEntries < SFlistSize) ?
|
|
dir->nEntries : SFlistSize)) / dir->nEntries),
|
|
(double)dir->nEntries);
|
|
#endif
|
|
}
|
|
|
|
SFvSliderMovedCallback(w, (int)(long)n, nw);
|
|
}
|
|
|
|
static void
|
|
SFhSliderMovedCallback(Widget w UNUSED, XtPointer n, XtPointer nw)
|
|
{
|
|
SFDir *dir;
|
|
int save;
|
|
|
|
dir = &(SFdirs[SFdirPtr + (int)(long)n]);
|
|
save = dir->hOrigin;
|
|
dir->hOrigin = (*(float *)nw) * dir->nChars;
|
|
if (dir->hOrigin == save)
|
|
return;
|
|
|
|
SFdrawList((int)(long)n, SF_DO_NOT_SCROLL);
|
|
}
|
|
|
|
static void
|
|
SFhAreaSelectedCallback(Widget w, XtPointer n, XtPointer pnew)
|
|
{
|
|
SFDir *dir;
|
|
int nw = (int)(long)pnew;
|
|
|
|
dir = &(SFdirs[SFdirPtr + (int)(long)n]);
|
|
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
if (nw < 0)
|
|
{
|
|
if (nw > -SFhScrollWidth)
|
|
nw = -1;
|
|
else
|
|
nw = -SFcharsPerEntry;
|
|
}
|
|
else if (nw > 0)
|
|
{
|
|
if (nw < SFhScrollWidth)
|
|
nw = 1;
|
|
else
|
|
nw = SFcharsPerEntry;
|
|
}
|
|
#endif
|
|
nw += dir->hOrigin;
|
|
|
|
if (nw > dir->nChars - SFcharsPerEntry)
|
|
nw = dir->nChars - SFcharsPerEntry;
|
|
|
|
if (nw < 0)
|
|
nw = 0;
|
|
|
|
if (dir->nChars)
|
|
{
|
|
float f;
|
|
|
|
f = ((double) nw) / dir->nChars;
|
|
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
XawScrollbarSetThumb(
|
|
w,
|
|
f,
|
|
(float) (((double) ((dir->nChars < SFcharsPerEntry) ?
|
|
dir->nChars : SFcharsPerEntry)) / dir->nChars));
|
|
#else
|
|
vim_XawScrollbarSetThumb(
|
|
w,
|
|
f,
|
|
(float) (((double) ((dir->nChars < SFcharsPerEntry) ?
|
|
dir->nChars : SFcharsPerEntry)) / dir->nChars),
|
|
(double)dir->nChars);
|
|
#endif
|
|
|
|
SFhSliderMovedCallback(w, n, (XtPointer)&f);
|
|
}
|
|
}
|
|
|
|
static void
|
|
SFpathSliderMovedCallback(
|
|
Widget w UNUSED,
|
|
XtPointer client_data UNUSED,
|
|
XtPointer nw)
|
|
{
|
|
SFDir *dir;
|
|
int n;
|
|
XawTextPosition pos;
|
|
int SFdirPtrSave;
|
|
|
|
SFdirPtrSave = SFdirPtr;
|
|
SFdirPtr = (*(float *)nw) * SFdirEnd;
|
|
if (SFdirPtr == SFdirPtrSave)
|
|
return;
|
|
|
|
SFdrawLists(SF_DO_SCROLL);
|
|
|
|
n = 2;
|
|
while (SFdirPtr + n >= SFdirEnd)
|
|
n--;
|
|
|
|
dir = &(SFdirs[SFdirPtr + n]);
|
|
|
|
pos = dir->path - SFcurrentPath;
|
|
|
|
if (!strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir)))
|
|
{
|
|
pos -= strlen(SFstartDir);
|
|
if (pos < 0)
|
|
pos = 0;
|
|
}
|
|
|
|
XawTextSetInsertionPoint(selFileField, pos);
|
|
}
|
|
|
|
static void
|
|
SFpathAreaSelectedCallback(
|
|
Widget w,
|
|
XtPointer client_data UNUSED,
|
|
XtPointer pnew)
|
|
{
|
|
int nw = (int)(long)pnew;
|
|
float f;
|
|
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
if (nw < 0)
|
|
{
|
|
if (nw > -SFpathScrollWidth)
|
|
nw = -1;
|
|
else
|
|
nw = -3;
|
|
}
|
|
else if (nw > 0)
|
|
{
|
|
if (nw < SFpathScrollWidth)
|
|
nw = 1;
|
|
else
|
|
nw = 3;
|
|
}
|
|
#endif
|
|
nw += SFdirPtr;
|
|
|
|
if (nw > SFdirEnd - 3)
|
|
nw = SFdirEnd - 3;
|
|
|
|
if (nw < 0)
|
|
nw = 0;
|
|
|
|
f = ((double) nw) / SFdirEnd;
|
|
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
XawScrollbarSetThumb(
|
|
w,
|
|
f,
|
|
(float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) / SFdirEnd));
|
|
#else
|
|
vim_XawScrollbarSetThumb(
|
|
w,
|
|
f,
|
|
(float) (((double) ((SFdirEnd < 3) ? SFdirEnd : 3)) / SFdirEnd),
|
|
(double)SFdirEnd);
|
|
#endif
|
|
|
|
SFpathSliderMovedCallback(w, (XtPointer) NULL, (XtPointer)&f);
|
|
}
|
|
|
|
static Boolean
|
|
SFworkProc(void *arg UNUSED)
|
|
{
|
|
SFDir *dir;
|
|
SFEntry *entry;
|
|
|
|
for (dir = &(SFdirs[SFdirEnd - 1]); dir >= SFdirs; dir--)
|
|
{
|
|
if (!(dir->nEntries))
|
|
continue;
|
|
for (entry = &(dir->entries[dir->nEntries - 1]);
|
|
entry >= dir->entries;
|
|
entry--)
|
|
{
|
|
if (!(entry->statDone))
|
|
{
|
|
(void)SFstatAndCheck(dir, entry);
|
|
return False;
|
|
}
|
|
}
|
|
}
|
|
|
|
SFworkProcAdded = 0;
|
|
|
|
return True;
|
|
}
|
|
|
|
////////////////// Dir.c
|
|
|
|
static int
|
|
SFcompareEntries(const void *p, const void *q)
|
|
{
|
|
return strcmp(((SFEntry *)p)->real, ((SFEntry *)q)->real);
|
|
}
|
|
|
|
static int
|
|
SFgetDir(
|
|
SFDir *dir)
|
|
{
|
|
SFEntry *result = NULL;
|
|
int Alloc = 0;
|
|
int i;
|
|
DIR *dirp;
|
|
struct dirent *dp;
|
|
char *str;
|
|
int len;
|
|
int maxChars;
|
|
stat_T statBuf;
|
|
|
|
maxChars = strlen(dir->dir) - 1;
|
|
|
|
dir->entries = NULL;
|
|
dir->nEntries = 0;
|
|
dir->nChars = 0;
|
|
|
|
result = NULL;
|
|
i = 0;
|
|
|
|
dirp = opendir(".");
|
|
if (!dirp)
|
|
return 1;
|
|
|
|
(void)mch_stat(".", &statBuf);
|
|
dir->mtime = statBuf.st_mtime;
|
|
|
|
while ((dp = readdir(dirp)))
|
|
{
|
|
// Ignore "." and ".."
|
|
if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
|
|
continue;
|
|
if (i >= Alloc)
|
|
{
|
|
Alloc = 2 * (Alloc + 1);
|
|
result = (SFEntry *) XtRealloc((char *) result,
|
|
(unsigned) (Alloc * sizeof(SFEntry)));
|
|
}
|
|
result[i].statDone = 0;
|
|
str = dp->d_name;
|
|
len = strlen(str);
|
|
result[i].real = XtMalloc((unsigned)(len + 2));
|
|
(void) strcat(strcpy(result[i].real, str), " ");
|
|
if (len > maxChars)
|
|
maxChars = len;
|
|
result[i].shown = result[i].real;
|
|
i++;
|
|
}
|
|
|
|
qsort((char *) result, (size_t) i, sizeof(SFEntry), SFcompareEntries);
|
|
|
|
dir->entries = result;
|
|
dir->nEntries = i;
|
|
dir->nChars = maxChars + 1;
|
|
|
|
closedir(dirp);
|
|
|
|
return 0;
|
|
}
|
|
|
|
////////////////// SFinternal.h
|
|
|
|
#include <sys/param.h>
|
|
#include <X11/cursorfont.h>
|
|
#include <X11/Composite.h>
|
|
#include <X11/Shell.h>
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
# include <X11/neXtaw/Form.h>
|
|
# include <X11/neXtaw/Command.h>
|
|
# include <X11/neXtaw/Label.h>
|
|
#else
|
|
#include <X11/Xaw/Form.h>
|
|
#include <X11/Xaw/Command.h>
|
|
#include <X11/Xaw/Label.h>
|
|
#endif
|
|
|
|
static char *oneLineTextEditTranslations = "\
|
|
<Key>Return: redraw-display()\n\
|
|
Ctrl<Key>M: redraw-display()\n\
|
|
";
|
|
|
|
static void
|
|
SFexposeList(
|
|
Widget w UNUSED,
|
|
XtPointer n,
|
|
XEvent *event,
|
|
Boolean *cont UNUSED)
|
|
{
|
|
if ((event->type == NoExpose) || event->xexpose.count)
|
|
return;
|
|
|
|
SFdrawList((int)(long)n, SF_DO_NOT_SCROLL);
|
|
}
|
|
|
|
static void
|
|
SFmodVerifyCallback(
|
|
Widget w UNUSED,
|
|
XtPointer client_data UNUSED,
|
|
XEvent *event,
|
|
Boolean *cont UNUSED)
|
|
{
|
|
char buf[2];
|
|
|
|
if ((XLookupString(&(event->xkey), buf, 2, NULL, NULL) == 1) &&
|
|
((*buf) == '\r'))
|
|
SFstatus = SEL_FILE_OK;
|
|
else
|
|
SFstatus = SEL_FILE_TEXT;
|
|
}
|
|
|
|
static void
|
|
SFokCallback(Widget w UNUSED, XtPointer cl UNUSED, XtPointer cd UNUSED)
|
|
{
|
|
SFstatus = SEL_FILE_OK;
|
|
}
|
|
|
|
static XtCallbackRec SFokSelect[] =
|
|
{
|
|
{ SFokCallback, (XtPointer) NULL },
|
|
{ NULL, (XtPointer) NULL },
|
|
};
|
|
|
|
static void
|
|
SFcancelCallback(Widget w UNUSED, XtPointer cl UNUSED, XtPointer cd UNUSED)
|
|
{
|
|
SFstatus = SEL_FILE_CANCEL;
|
|
}
|
|
|
|
static XtCallbackRec SFcancelSelect[] =
|
|
{
|
|
{ SFcancelCallback, (XtPointer) NULL },
|
|
{ NULL, (XtPointer) NULL },
|
|
};
|
|
|
|
static void
|
|
SFdismissAction(
|
|
Widget w UNUSED,
|
|
XEvent *event,
|
|
String *params UNUSED,
|
|
Cardinal *num_params UNUSED)
|
|
{
|
|
if (event->type == ClientMessage
|
|
&& (Atom)event->xclient.data.l[0] != SFwmDeleteWindow)
|
|
return;
|
|
|
|
SFstatus = SEL_FILE_CANCEL;
|
|
}
|
|
|
|
static char *wmDeleteWindowTranslation = "\
|
|
<Message>WM_PROTOCOLS: SelFileDismiss()\n\
|
|
";
|
|
|
|
static XtActionsRec actions[] =
|
|
{
|
|
{"SelFileDismiss", SFdismissAction},
|
|
};
|
|
|
|
static void
|
|
SFsetColors(
|
|
guicolor_T bg,
|
|
guicolor_T fg,
|
|
guicolor_T scroll_bg,
|
|
guicolor_T scroll_fg)
|
|
{
|
|
if (selFileForm)
|
|
{
|
|
XtVaSetValues(selFileForm, XtNbackground, bg,
|
|
XtNforeground, fg,
|
|
XtNborderColor, bg,
|
|
NULL);
|
|
}
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 3; ++i)
|
|
{
|
|
if (selFileLists[i])
|
|
{
|
|
XtVaSetValues(selFileLists[i], XtNbackground, bg,
|
|
XtNforeground, fg,
|
|
XtNborderColor, fg,
|
|
NULL);
|
|
}
|
|
}
|
|
}
|
|
if (selFileOK)
|
|
{
|
|
XtVaSetValues(selFileOK, XtNbackground, bg,
|
|
XtNforeground, fg,
|
|
XtNborderColor, fg,
|
|
NULL);
|
|
}
|
|
if (selFileCancel)
|
|
{
|
|
XtVaSetValues(selFileCancel, XtNbackground, bg,
|
|
XtNforeground, fg,
|
|
XtNborderColor, fg,
|
|
NULL);
|
|
}
|
|
if (selFilePrompt)
|
|
{
|
|
XtVaSetValues(selFilePrompt, XtNbackground, bg,
|
|
XtNforeground, fg,
|
|
NULL);
|
|
}
|
|
if (gui.dpy)
|
|
{
|
|
XSetBackground(gui.dpy, SFtextGC, bg);
|
|
XSetForeground(gui.dpy, SFtextGC, fg);
|
|
XSetForeground(gui.dpy, SFlineGC, fg);
|
|
|
|
// This is an xor GC, so combine the fg and background
|
|
XSetBackground(gui.dpy, SFinvertGC, fg ^ bg);
|
|
XSetForeground(gui.dpy, SFinvertGC, fg ^ bg);
|
|
}
|
|
if (selFileHScroll)
|
|
{
|
|
XtVaSetValues(selFileHScroll, XtNbackground, scroll_bg,
|
|
XtNforeground, scroll_fg,
|
|
XtNborderColor, fg,
|
|
NULL);
|
|
}
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
XtVaSetValues(selFileVScrolls[i], XtNbackground, scroll_bg,
|
|
XtNforeground, scroll_fg,
|
|
XtNborderColor, fg,
|
|
NULL);
|
|
XtVaSetValues(selFileHScrolls[i], XtNbackground, scroll_bg,
|
|
XtNforeground, scroll_fg,
|
|
XtNborderColor, fg,
|
|
NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
SFcreateWidgets(
|
|
Widget toplevel,
|
|
char *prompt,
|
|
char *ok,
|
|
char *cancel)
|
|
{
|
|
Cardinal n;
|
|
int listWidth, listHeight;
|
|
int listSpacing = 10;
|
|
int scrollThickness = 15;
|
|
int hScrollX, hScrollY;
|
|
int vScrollX, vScrollY;
|
|
|
|
selFile = XtVaAppCreateShell("selFile", "SelFile",
|
|
transientShellWidgetClass, SFdisplay,
|
|
XtNtransientFor, toplevel,
|
|
XtNtitle, prompt,
|
|
NULL);
|
|
|
|
// Add WM_DELETE_WINDOW protocol
|
|
XtAppAddActions(XtWidgetToApplicationContext(selFile),
|
|
actions, XtNumber(actions));
|
|
XtOverrideTranslations(selFile,
|
|
XtParseTranslationTable(wmDeleteWindowTranslation));
|
|
|
|
selFileForm = XtVaCreateManagedWidget("selFileForm",
|
|
formWidgetClass, selFile,
|
|
XtNdefaultDistance, 30,
|
|
XtNforeground, SFfore,
|
|
XtNbackground, SFback,
|
|
XtNborderColor, SFback,
|
|
NULL);
|
|
|
|
selFilePrompt = XtVaCreateManagedWidget("selFilePrompt",
|
|
labelWidgetClass, selFileForm,
|
|
XtNlabel, prompt,
|
|
XtNresizable, True,
|
|
XtNtop, XtChainTop,
|
|
XtNbottom, XtChainTop,
|
|
XtNleft, XtChainLeft,
|
|
XtNright, XtChainLeft,
|
|
XtNborderWidth, 0,
|
|
XtNforeground, SFfore,
|
|
XtNbackground, SFback,
|
|
NULL);
|
|
|
|
/*
|
|
XtVaGetValues(selFilePrompt,
|
|
XtNforeground, &SFfore,
|
|
XtNbackground, &SFback,
|
|
NULL);
|
|
*/
|
|
|
|
SFinitFont();
|
|
|
|
SFentryWidth = SFbesideText + SFcharsPerEntry * SFcharWidth +
|
|
SFbesideText;
|
|
SFentryHeight = SFaboveAndBelowText + SFcharHeight +
|
|
SFaboveAndBelowText;
|
|
|
|
listWidth = SFlineToTextH + SFentryWidth + SFlineToTextH + 1 +
|
|
scrollThickness;
|
|
listHeight = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
|
|
SFlineToTextV + SFlistSize * SFentryHeight +
|
|
SFlineToTextV + 1 + scrollThickness;
|
|
|
|
SFpathScrollWidth = 3 * listWidth + 2 * listSpacing + 4;
|
|
|
|
hScrollX = -1;
|
|
hScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
|
|
SFlineToTextV + SFlistSize * SFentryHeight +
|
|
SFlineToTextV;
|
|
SFhScrollWidth = SFlineToTextH + SFentryWidth + SFlineToTextH;
|
|
|
|
vScrollX = SFlineToTextH + SFentryWidth + SFlineToTextH;
|
|
vScrollY = SFlineToTextV + SFentryHeight + SFlineToTextV;
|
|
SFvScrollHeight = SFlineToTextV + SFlistSize * SFentryHeight +
|
|
SFlineToTextV;
|
|
|
|
SFupperX = SFlineToTextH + SFentryWidth + SFlineToTextH - 1;
|
|
SFlowerY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
|
|
SFlineToTextV;
|
|
SFupperY = SFlineToTextV + SFentryHeight + SFlineToTextV + 1 +
|
|
SFlineToTextV + SFlistSize * SFentryHeight - 1;
|
|
|
|
SFtextX = SFlineToTextH + SFbesideText;
|
|
SFtextYoffset = SFlowerY + SFaboveAndBelowText + SFcharAscent;
|
|
|
|
SFsegs[0].x1 = 0;
|
|
SFsegs[0].y1 = vScrollY;
|
|
SFsegs[0].x2 = vScrollX - 1;
|
|
SFsegs[0].y2 = vScrollY;
|
|
SFsegs[1].x1 = vScrollX;
|
|
SFsegs[1].y1 = 0;
|
|
SFsegs[1].x2 = vScrollX;
|
|
SFsegs[1].y2 = vScrollY - 1;
|
|
|
|
SFcompletionSegs[0].x1 = SFcompletionSegs[0].x2 = SFlineToTextH;
|
|
SFcompletionSegs[1].x1 = SFcompletionSegs[1].x2 =
|
|
SFlineToTextH + SFentryWidth - 1;
|
|
|
|
selFileField = XtVaCreateManagedWidget("selFileField",
|
|
asciiTextWidgetClass, selFileForm,
|
|
XtNwidth, 3 * listWidth + 2 * listSpacing + 4,
|
|
XtNborderColor, SFfore,
|
|
XtNfromVert, selFilePrompt,
|
|
XtNvertDistance, 10,
|
|
XtNresizable, True,
|
|
XtNtop, XtChainTop,
|
|
XtNbottom, XtChainTop,
|
|
XtNleft, XtChainLeft,
|
|
XtNright, XtChainLeft,
|
|
XtNstring, SFtextBuffer,
|
|
XtNlength, MAXPATHL,
|
|
XtNeditType, XawtextEdit,
|
|
XtNwrap, XawtextWrapWord,
|
|
XtNresize, XawtextResizeHeight,
|
|
XtNuseStringInPlace, True,
|
|
NULL);
|
|
|
|
XtOverrideTranslations(selFileField,
|
|
XtParseTranslationTable(oneLineTextEditTranslations));
|
|
XtSetKeyboardFocus(selFileForm, selFileField);
|
|
|
|
selFileHScroll = XtVaCreateManagedWidget("selFileHScroll",
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
scrollbarWidgetClass, selFileForm,
|
|
#else
|
|
vim_scrollbarWidgetClass, selFileForm,
|
|
#endif
|
|
XtNorientation, XtorientHorizontal,
|
|
XtNwidth, SFpathScrollWidth,
|
|
XtNheight, scrollThickness,
|
|
XtNborderColor, SFfore,
|
|
XtNfromVert, selFileField,
|
|
XtNvertDistance, 30,
|
|
XtNtop, XtChainTop,
|
|
XtNbottom, XtChainTop,
|
|
XtNleft, XtChainLeft,
|
|
XtNright, XtChainLeft,
|
|
XtNforeground, gui.scroll_fg_pixel,
|
|
XtNbackground, gui.scroll_bg_pixel,
|
|
#ifndef FEAT_GUI_NEXTAW
|
|
XtNlimitThumb, 1,
|
|
#endif
|
|
NULL);
|
|
|
|
XtAddCallback(selFileHScroll, XtNjumpProc,
|
|
(XtCallbackProc) SFpathSliderMovedCallback, (XtPointer)NULL);
|
|
XtAddCallback(selFileHScroll, XtNscrollProc,
|
|
(XtCallbackProc) SFpathAreaSelectedCallback, (XtPointer)NULL);
|
|
|
|
selFileLists[0] = XtVaCreateManagedWidget("selFileList1",
|
|
compositeWidgetClass, selFileForm,
|
|
XtNwidth, listWidth,
|
|
XtNheight, listHeight,
|
|
XtNforeground, SFfore,
|
|
XtNbackground, SFback,
|
|
XtNborderColor, SFfore,
|
|
XtNfromVert, selFileHScroll,
|
|
XtNvertDistance, 10,
|
|
XtNtop, XtChainTop,
|
|
XtNbottom, XtChainTop,
|
|
XtNleft, XtChainLeft,
|
|
XtNright, XtChainLeft,
|
|
NULL);
|
|
|
|
selFileLists[1] = XtVaCreateManagedWidget("selFileList2",
|
|
compositeWidgetClass, selFileForm,
|
|
XtNwidth, listWidth,
|
|
XtNheight, listHeight,
|
|
XtNforeground, SFfore,
|
|
XtNbackground, SFback,
|
|
XtNborderColor, SFfore,
|
|
XtNfromHoriz, selFileLists[0],
|
|
XtNfromVert, selFileHScroll,
|
|
XtNhorizDistance, listSpacing,
|
|
XtNvertDistance, 10,
|
|
XtNtop, XtChainTop,
|
|
XtNbottom, XtChainTop,
|
|
XtNleft, XtChainLeft,
|
|
XtNright, XtChainLeft,
|
|
NULL);
|
|
|
|
selFileLists[2] = XtVaCreateManagedWidget("selFileList3",
|
|
compositeWidgetClass, selFileForm,
|
|
XtNwidth, listWidth,
|
|
XtNheight, listHeight,
|
|
XtNforeground, SFfore,
|
|
XtNbackground, SFback,
|
|
XtNborderColor, SFfore,
|
|
XtNfromHoriz, selFileLists[1],
|
|
XtNfromVert, selFileHScroll,
|
|
XtNhorizDistance, listSpacing,
|
|
XtNvertDistance, 10,
|
|
XtNtop, XtChainTop,
|
|
XtNbottom, XtChainTop,
|
|
XtNleft, XtChainLeft,
|
|
XtNright, XtChainLeft,
|
|
NULL);
|
|
|
|
for (n = 0; n < 3; n++)
|
|
{
|
|
selFileVScrolls[n] = XtVaCreateManagedWidget("selFileVScroll",
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
scrollbarWidgetClass, selFileLists[n],
|
|
#else
|
|
vim_scrollbarWidgetClass, selFileLists[n],
|
|
#endif
|
|
XtNx, vScrollX,
|
|
XtNy, vScrollY,
|
|
XtNwidth, scrollThickness,
|
|
XtNheight, SFvScrollHeight,
|
|
XtNborderColor, SFfore,
|
|
XtNforeground, gui.scroll_fg_pixel,
|
|
XtNbackground, gui.scroll_bg_pixel,
|
|
#ifndef FEAT_GUI_NEXTAW
|
|
XtNlimitThumb, 1,
|
|
#endif
|
|
NULL);
|
|
|
|
XtAddCallback(selFileVScrolls[n], XtNjumpProc,
|
|
(XtCallbackProc)SFvFloatSliderMovedCallback,
|
|
(XtPointer)(long_u)n);
|
|
XtAddCallback(selFileVScrolls[n], XtNscrollProc,
|
|
(XtCallbackProc)SFvAreaSelectedCallback, (XtPointer)(long_u)n);
|
|
|
|
selFileHScrolls[n] = XtVaCreateManagedWidget("selFileHScroll",
|
|
#ifdef FEAT_GUI_NEXTAW
|
|
scrollbarWidgetClass, selFileLists[n],
|
|
#else
|
|
vim_scrollbarWidgetClass, selFileLists[n],
|
|
#endif
|
|
XtNorientation, XtorientHorizontal,
|
|
XtNx, hScrollX,
|
|
XtNy, hScrollY,
|
|
XtNwidth, SFhScrollWidth,
|
|
XtNheight, scrollThickness,
|
|
XtNborderColor, SFfore,
|
|
XtNforeground, gui.scroll_fg_pixel,
|
|
XtNbackground, gui.scroll_bg_pixel,
|
|
#ifndef FEAT_GUI_NEXTAW
|
|
XtNlimitThumb, 1,
|
|
#endif
|
|
NULL);
|
|
|
|
XtAddCallback(selFileHScrolls[n], XtNjumpProc,
|
|
(XtCallbackProc)SFhSliderMovedCallback,
|
|
(XtPointer)(long_u)n);
|
|
XtAddCallback(selFileHScrolls[n], XtNscrollProc,
|
|
(XtCallbackProc)SFhAreaSelectedCallback, (XtPointer)(long_u)n);
|
|
}
|
|
|
|
selFileOK = XtVaCreateManagedWidget("selFileOK",
|
|
commandWidgetClass, selFileForm,
|
|
XtNlabel, ok,
|
|
XtNresizable, True,
|
|
XtNcallback, SFokSelect,
|
|
XtNforeground, SFfore,
|
|
XtNbackground, SFback,
|
|
XtNborderColor, SFfore,
|
|
XtNfromHoriz, selFileLists[0],
|
|
XtNfromVert, selFileLists[0],
|
|
XtNvertDistance, 30,
|
|
XtNtop, XtChainTop,
|
|
XtNbottom, XtChainTop,
|
|
XtNleft, XtChainLeft,
|
|
XtNright, XtChainLeft,
|
|
NULL);
|
|
|
|
selFileCancel = XtVaCreateManagedWidget("selFileCancel",
|
|
commandWidgetClass, selFileForm,
|
|
XtNlabel, cancel,
|
|
XtNresizable, True,
|
|
XtNcallback, SFcancelSelect,
|
|
XtNforeground, SFfore,
|
|
XtNbackground, SFback,
|
|
XtNborderColor, SFfore,
|
|
XtNfromHoriz, selFileOK,
|
|
XtNfromVert, selFileLists[0],
|
|
XtNhorizDistance, 30,
|
|
XtNvertDistance, 30,
|
|
XtNtop, XtChainTop,
|
|
XtNbottom, XtChainTop,
|
|
XtNleft, XtChainLeft,
|
|
XtNright, XtChainLeft,
|
|
NULL);
|
|
|
|
XtSetMappedWhenManaged(selFile, False);
|
|
XtRealizeWidget(selFile);
|
|
|
|
// Add WM_DELETE_WINDOW protocol
|
|
SFwmDeleteWindow = XInternAtom(SFdisplay, "WM_DELETE_WINDOW", False);
|
|
XSetWMProtocols(SFdisplay, XtWindow(selFile), &SFwmDeleteWindow, 1);
|
|
|
|
SFcreateGC();
|
|
|
|
for (n = 0; n < 3; n++)
|
|
{
|
|
XtAddEventHandler(selFileLists[n], ExposureMask, True,
|
|
(XtEventHandler)SFexposeList, (XtPointer)(long_u)n);
|
|
XtAddEventHandler(selFileLists[n], EnterWindowMask, False,
|
|
(XtEventHandler)SFenterList, (XtPointer)(long_u)n);
|
|
XtAddEventHandler(selFileLists[n], LeaveWindowMask, False,
|
|
(XtEventHandler)SFleaveList, (XtPointer)(long_u)n);
|
|
XtAddEventHandler(selFileLists[n], PointerMotionMask, False,
|
|
(XtEventHandler)SFmotionList, (XtPointer)(long_u)n);
|
|
XtAddEventHandler(selFileLists[n], ButtonPressMask, False,
|
|
(XtEventHandler)SFbuttonPressList, (XtPointer)(long_u)n);
|
|
XtAddEventHandler(selFileLists[n], ButtonReleaseMask, False,
|
|
(XtEventHandler)SFbuttonReleaseList, (XtPointer)(long_u)n);
|
|
}
|
|
|
|
XtAddEventHandler(selFileField, KeyPressMask, False,
|
|
SFmodVerifyCallback, (XtPointer)NULL);
|
|
|
|
SFapp = XtWidgetToApplicationContext(selFile);
|
|
}
|
|
|
|
static void
|
|
SFtextChanged(void)
|
|
{
|
|
#if defined(FEAT_XFONTSET) && defined(XtNinternational)
|
|
if ((unsigned long)_XawTextFormat((TextWidget)selFileField) == XawFmtWide)
|
|
{
|
|
wchar_t *wcbuf=(wchar_t *)SFtextBuffer;
|
|
|
|
if ((wcbuf[0] == L'/') || (wcbuf[0] == L'~'))
|
|
{
|
|
(void) wcstombs(SFcurrentPath, wcbuf, MAXPATHL);
|
|
SFtextPos = XawTextGetInsertionPoint(selFileField);
|
|
}
|
|
else
|
|
{
|
|
strcpy(SFcurrentPath, SFstartDir);
|
|
(void) wcstombs(SFcurrentPath + strlen(SFcurrentPath), wcbuf, MAXPATHL);
|
|
|
|
SFtextPos = XawTextGetInsertionPoint(selFileField) + strlen(SFstartDir);
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
if ((SFtextBuffer[0] == '/') || (SFtextBuffer[0] == '~'))
|
|
{
|
|
(void) strcpy(SFcurrentPath, SFtextBuffer);
|
|
SFtextPos = XawTextGetInsertionPoint(selFileField);
|
|
}
|
|
else
|
|
{
|
|
(void) strcat(strcpy(SFcurrentPath, SFstartDir), SFtextBuffer);
|
|
|
|
SFtextPos = XawTextGetInsertionPoint(selFileField) + strlen(SFstartDir);
|
|
}
|
|
|
|
if (!SFworkProcAdded)
|
|
{
|
|
(void) XtAppAddWorkProc(SFapp, (XtWorkProc)SFworkProc, NULL);
|
|
SFworkProcAdded = 1;
|
|
}
|
|
|
|
SFupdatePath();
|
|
}
|
|
|
|
static char *
|
|
SFgetText(void)
|
|
{
|
|
#if defined(FEAT_XFONTSET) && defined(XtNinternational)
|
|
char *buf;
|
|
|
|
if ((unsigned long)_XawTextFormat((TextWidget)selFileField) == XawFmtWide)
|
|
{
|
|
wchar_t *wcbuf;
|
|
int mbslength;
|
|
|
|
XtVaGetValues(selFileField,
|
|
XtNstring, &wcbuf,
|
|
NULL);
|
|
mbslength = wcstombs(NULL, wcbuf, 0);
|
|
// Hack: some broken wcstombs() returns zero, just get a large buffer
|
|
if (mbslength == 0 && wcbuf != NULL && wcbuf[0] != 0)
|
|
mbslength = MAXPATHL;
|
|
buf=(char *)XtMalloc(mbslength + 1);
|
|
wcstombs(buf, wcbuf, mbslength +1);
|
|
return buf;
|
|
}
|
|
#endif
|
|
return (char *)vim_strsave((char_u *)SFtextBuffer);
|
|
}
|
|
|
|
static void
|
|
SFprepareToReturn(void)
|
|
{
|
|
SFstatus = SEL_FILE_NULL;
|
|
XtRemoveGrab(selFile);
|
|
XtUnmapWidget(selFile);
|
|
XtRemoveTimeOut(SFdirModTimerId);
|
|
if (SFchdir(SFstartDir))
|
|
{
|
|
emsg(_("E614: vim_SelFile: can't return to current directory"));
|
|
SFstatus = SEL_FILE_CANCEL;
|
|
}
|
|
}
|
|
|
|
char *
|
|
vim_SelFile(
|
|
Widget toplevel,
|
|
char *prompt,
|
|
char *init_path,
|
|
int (*show_entry)(),
|
|
int x,
|
|
int y,
|
|
guicolor_T fg,
|
|
guicolor_T bg,
|
|
guicolor_T scroll_fg,
|
|
guicolor_T scroll_bg) // The "Scrollbar" group colors
|
|
{
|
|
static int firstTime = 1;
|
|
XEvent event;
|
|
char *name_return;
|
|
|
|
if (prompt == NULL)
|
|
prompt = _("Pathname:");
|
|
SFfore = fg;
|
|
SFback = bg;
|
|
|
|
if (mch_dirname((char_u *)SFstartDir, MAXPATHL) == FAIL)
|
|
{
|
|
emsg(_("E615: vim_SelFile: can't get current directory"));
|
|
return NULL;
|
|
}
|
|
|
|
if (firstTime)
|
|
{
|
|
firstTime = 0;
|
|
SFdisplay = XtDisplay(toplevel);
|
|
SFcreateWidgets(toplevel, prompt, _("OK"), _("Cancel"));
|
|
}
|
|
else
|
|
{
|
|
XtVaSetValues(selFilePrompt, XtNlabel, prompt, NULL);
|
|
XtVaSetValues(selFile, XtNtitle, prompt, NULL);
|
|
SFsetColors(bg, fg, scroll_bg, scroll_fg);
|
|
}
|
|
|
|
XtVaSetValues(selFile, XtNx, x, XtNy, y, NULL);
|
|
XtMapWidget(selFile);
|
|
|
|
(void)strcat(SFstartDir, "/");
|
|
(void)strcpy(SFcurrentDir, SFstartDir);
|
|
|
|
if (init_path)
|
|
{
|
|
if (init_path[0] == '/')
|
|
{
|
|
(void)strcpy(SFcurrentPath, init_path);
|
|
if (strncmp(SFcurrentPath, SFstartDir, strlen(SFstartDir)))
|
|
SFsetText(SFcurrentPath);
|
|
else
|
|
SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
|
|
}
|
|
else
|
|
{
|
|
(void)strcat(strcpy(SFcurrentPath, SFstartDir), init_path);
|
|
SFsetText(&(SFcurrentPath[strlen(SFstartDir)]));
|
|
}
|
|
}
|
|
else
|
|
(void)strcpy(SFcurrentPath, SFstartDir);
|
|
|
|
SFfunc = show_entry;
|
|
|
|
SFtextChanged();
|
|
|
|
XtAddGrab(selFile, True, True);
|
|
|
|
SFdirModTimerId = XtAppAddTimeOut(SFapp, (unsigned long) 1000,
|
|
SFdirModTimer, (XtPointer) NULL);
|
|
|
|
for (;;)
|
|
{
|
|
XtAppNextEvent(SFapp, &event);
|
|
XtDispatchEvent(&event);
|
|
switch (SFstatus)
|
|
{
|
|
case SEL_FILE_TEXT:
|
|
SFstatus = SEL_FILE_NULL;
|
|
SFtextChanged();
|
|
break;
|
|
case SEL_FILE_OK:
|
|
name_return = SFgetText();
|
|
SFprepareToReturn();
|
|
return name_return;
|
|
case SEL_FILE_CANCEL:
|
|
SFprepareToReturn();
|
|
return NULL;
|
|
case SEL_FILE_NULL:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif // FEAT_BROWSE
|