getline.c
来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· C语言 代码 · 共 2,474 行 · 第 1/4 页
C
2,474 行
matchpfx = (char *) malloc(mlen + 1);
memcpy(matchpfx, cp, mlen);
matchpfx[mlen] = '\0';
#define GL_COMPLETE_VECTOR_BLOCK_SIZE 64
nused = 0;
ntoalloc = GL_COMPLETE_VECTOR_BLOCK_SIZE;
newgl_matchlist = (char **) malloc((size_t) (sizeof(char *) * (ntoalloc + 1)));
if (newgl_matchlist == NULL) {
free(matchpfx);
gl_beep();
return 0;
}
gl_matchlist = newgl_matchlist;
nalloced = ntoalloc;
for (i=nused; i<=nalloced; i++)
gl_matchlist[i] = NULL;
gl_completion_exact_match_extra_char = ' ';
for (nprocused = 0;; nprocused++) {
if (nused == nalloced) {
ntoalloc += GL_COMPLETE_VECTOR_BLOCK_SIZE;
newgl_matchlist = (char **) realloc((char *) gl_matchlist, (size_t) (sizeof(char *) * (ntoalloc + 1)));
if (newgl_matchlist == NULL) {
/* not enough memory to expand list -- abort */
for (i=0; i<nused; i++)
free(gl_matchlist[i]);
free(gl_matchlist);
gl_matchlist = NULL;
gl_beep();
free(matchpfx);
return 0;
}
gl_matchlist = newgl_matchlist;
nalloced = ntoalloc;
for (i=nused; i<=nalloced; i++)
gl_matchlist[i] = NULL;
}
cp = gl_completion_proc(matchpfx, nprocused);
if (cp == NULL)
break;
if ((cp[0] == '.') && ((cp[1] == '\0') || ((cp[1] == '.') && (cp[2] == '\0'))))
continue; /* Skip . and .. */
gl_matchlist[nused++] = cp;
}
if (gl_ellipses_during_completion != 0) {
gl_fixup(gl_prompt, gl_pos, gl_pos);
gl_puts(" ");
}
/* We now have an array strings, whose last element is NULL. */
strtoadd = NULL;
strtoadd1 = NULL;
amt = 0;
addquotes = (gl_filename_quoting_desired > 0) || ((gl_filename_quoting_desired < 0) && (gl_completion_proc == gl_local_filename_completion_proc));
if (nused == 1) {
/* Exactly one match. */
strtoadd = gl_matchlist[0];
} else if (tabtab != 0) {
/* TAB-TAB: print all matches */
gl_display_matches(nused);
} else if ((nused > 1) && (mlen > 0)) {
/* Find the greatest amount that matches. */
for (glen = strlen(matchpfx); ; glen++) {
allmatch = 1;
for (i=1; i<nused; i++) {
if (gl_matchlist[0][glen] != gl_matchlist[i][glen]) {
allmatch = 0;
break;
}
}
if (allmatch == 0)
break;
}
strtoadd1 = (char *) malloc(glen + 1);
if (strtoadd1 != NULL) {
memcpy(strtoadd1, gl_matchlist[0], glen);
strtoadd1[glen] = '\0';
strtoadd = strtoadd1;
}
}
if (strtoadd != NULL) {
if ((qmode == 0) && (addquotes != 0)) {
if (strpbrk(strtoadd, gl_filename_quote_characters) != NULL) {
qmode = (strchr(strtoadd, '"') == NULL) ? '"' : '\'';
memmove(curposp + 1, curposp, lenaftercursor + 1 /* NUL */);
curposp++;
*startp++ = (char) qmode;
}
}
startoff = (size_t) (startp - buf);
amt = strlen(strtoadd);
if ((amt + startoff + lenaftercursor) >= bufsize)
amt = bufsize - (amt + startoff + lenaftercursor);
memmove(curposp + amt - mlen, curposp, lenaftercursor + 1 /* NUL */);
curposp += amt - mlen;
memcpy(startp, strtoadd, amt);
if (nused == 1) {
/* Exact match. */
if (qmode != 0) {
/* Finish the quoting. */
memmove(curposp + 1, curposp, lenaftercursor + 1 /* NUL */);
curposp++;
buf[amt + startoff] = (char) qmode;
amt++;
}
memmove(curposp + 1, curposp, lenaftercursor + 1 /* NUL */);
curposp++;
buf[amt + startoff] = (char) gl_completion_exact_match_extra_char;
amt++;
} else if ((!wasateol) && (!isspace(*curposp))) {
/* Not a full match, but insert a
* space for better readability.
*/
memmove(curposp + 1, curposp, lenaftercursor + 1 /* NUL */);
curposp++;
buf[amt + startoff] = ' ';
}
*loc = (int) (startoff + amt);
if (strtoadd1 != NULL)
free(strtoadd1);
}
/* Don't need this any more. */
for (i=0; i<nused; i++)
free(gl_matchlist[i]);
free(gl_matchlist);
gl_matchlist = NULL;
free(matchpfx);
return 0;
} /* gl_do_tab_completion */
void
gl_tab_completion(gl_tab_completion_proc proc)
{
if (proc == NULL)
proc = gl_local_filename_completion_proc; /* default proc */
gl_completion_proc = proc;
} /* gl_tab_completion */
#ifndef _StrFindLocalPathDelim
static char *
_StrRFindLocalPathDelim(const char *src) /* TODO: optimize */
{
const char *last;
int c;
last = NULL;
for (;;) {
c = *src++;
if (c == '\0')
break;
if (IsLocalPathDelim(c))
last = src - 1;
}
return ((char *) last);
} /* StrRFindLocalPathDelim */
#endif /* Windows */
void
gl_set_home_dir(const char *homedir)
{
size_t len;
#ifdef __windows__
const char *homedrive, *homepath;
char wdir[64];
#else
struct passwd *pw;
char *cp;
#endif
if (gl_home_dir != NULL) {
free(gl_home_dir);
gl_home_dir = NULL;
}
if (homedir == NULL) {
#ifdef __windows__
homedrive = getenv("HOMEDRIVE");
homepath = getenv("HOMEPATH");
if ((homedrive != NULL) && (homepath != NULL)) {
len = strlen(homedrive) + strlen(homepath) + 1;
gl_home_dir = (char *) malloc(len);
if (gl_home_dir != NULL) {
strcpy(gl_home_dir, homedrive);
strcat(gl_home_dir, homepath);
return;
}
}
wdir[0] = '\0';
if (GetWindowsDirectory(wdir, sizeof(wdir) - 1) < 1)
(void) strncpy(wdir, ".", sizeof(wdir));
else if (wdir[1] == ':') {
wdir[2] = '\\';
wdir[3] = '\0';
}
homedir = wdir;
#else
cp = (char *) getlogin();
if (cp == NULL) {
cp = (char *) getenv("LOGNAME");
if (cp == NULL)
cp = (char *) getenv("USER");
}
pw = NULL;
if (cp != NULL)
pw = getpwnam(cp);
if (pw == NULL)
pw = getpwuid(getuid());
if (pw == NULL)
return; /* hell with it */
homedir = pw->pw_dir;
#endif
}
len = strlen(homedir) + /* NUL */ 1;
gl_home_dir = (char *) malloc(len);
if (gl_home_dir != NULL) {
memcpy(gl_home_dir, homedir, len);
}
} /* gl_set_home_dir */
char *gl_getpass(const char *const prompt, char *const pass, int dsize)
{
#ifdef __unix__
char *cp;
int c;
memset(pass, 0, (size_t) sizeof(dsize));
dsize--;
gl_init();
/* Display the prompt first. */
if ((prompt != NULL) && (prompt[0] != '\0'))
gl_puts(prompt);
cp = pass;
while ((c = gl_getc()) != (-1)) {
if ((c == '\r') || (c == '\n'))
break;
if ((c == '\010') || (c == '\177')) {
/* ^H and DEL */
if (cp > pass) {
*--cp = '\0';
gl_putc('\010');
gl_putc(' ');
gl_putc('\010');
}
} else if (cp < (pass + dsize)) {
gl_putc('*');
*cp++ = c;
}
}
*cp = '\0';
gl_putc('\n');
gl_cleanup();
return (pass);
#else
#ifdef __windows__
char *cp;
int c;
FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
ZeroMemory(pass, (DWORD) sizeof(dsize));
dsize--;
if ((prompt != NULL) && (prompt[0] != '\0'))
_cputs(prompt);
for (cp = pass;;) {
c = (int) _getch();
if ((c == '\r') || (c == '\n'))
break;
if ((c == '\010') || (c == '\177')) {
/* ^H and DEL */
if (cp > pass) {
*--cp = '\0';
_putch('\010');
_putch(' ');
_putch('\010');
}
} else if (cp < (pass + dsize)) {
_putch('*');
*cp++ = c;
}
}
_putch('\r');
_putch('\n');
Sleep(40);
FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
*cp = '\0';
return (pass);
#endif /* __windows__ */
#endif /* ! __unix__ */
} /* gl_getpass */
#ifdef __unix__
char *
gl_local_filename_completion_proc(const char *start, int idx)
{
static DIR *dir = NULL;
static int filepfxoffset;
static size_t filepfxlen;
const char *filepfx;
struct dirent *dent;
char *cp;
const char *dirtoopen, *name;
char *dirtoopen1;
size_t len, len2;
struct stat st;
if (idx == 0) {
if (dir != NULL) {
/* shouldn't get here! */
closedir(dir);
dir = NULL;
}
}
if (dir == NULL) {
dirtoopen1 = NULL;
cp = _StrRFindLocalPathDelim(start);
if (cp == start) {
dirtoopen = LOCAL_PATH_DELIM_STR; /* root dir */
filepfxoffset = 1;
} else if (cp == NULL) {
dirtoopen = ".";
filepfxoffset = 0;
} else {
len = strlen(start) + 1;
dirtoopen1 = (char *) malloc(len);
if (dirtoopen1 == NULL)
return NULL;
memcpy(dirtoopen1, start, len);
len = (cp - start);
dirtoopen1[len] = '\0';
dirtoopen = dirtoopen1;
filepfxoffset = (int) ((cp + 1) - start);
}
if (strcmp(dirtoopen, "~") == 0) {
if (gl_home_dir == NULL)
gl_set_home_dir(NULL);
if (gl_home_dir == NULL)
return (NULL);
dirtoopen = gl_home_dir;
}
dir = opendir(dirtoopen);
if (dirtoopen1 != NULL)
free(dirtoopen1);
filepfx = start + filepfxoffset;
filepfxlen = strlen(filepfx);
}
if (dir != NULL) {
/* assumes "start" is same for each iteration. */
filepfx = start + filepfxoffset;
for (;;) {
dent = readdir(dir);
if (dent == NULL) {
/* no more items */
closedir(dir);
dir = NULL;
if (idx == 1) {
/* There was exactly one match.
* In this special case, we
* want to append a / instead
* of a space.
*/
cp = gl_matchlist[0];
if ((cp[0] == '~') && ((cp[1] == '\0') || (IsLocalPathDelim(cp[1])))) {
len = strlen(cp + 1) + /* NUL */ 1;
len2 = strlen(gl_home_dir);
if (IsLocalPathDelim(gl_home_dir[len2 - 1]))
len2--;
cp = (char *) realloc(gl_matchlist[0], len + len2);
if (cp == NULL) {
cp = gl_matchlist[0];
} else {
memmove(cp + len2, cp + 1, len);
memcpy(cp, gl_home_dir, len2);
gl_matchlist[0] = cp;
}
}
if ((lstat(cp, &st) == 0) && (S_ISDIR(st.st_mode)))
gl_completion_exact_match_extra_char = LOCAL_PATH_DELIM;
}
return NULL;
}
name = dent->d_name;
if ((name[0] == '.') && ((name[1] == '\0') || ((name[1] == '.') && (name[2] == '\0'))))
continue; /* Skip . and .. */
if ((filepfxlen == 0) || (strncmp(name, filepfx, filepfxlen) == 0)) {
/* match */
len = strlen(name);
cp = (char *) malloc(filepfxoffset + len + 1 /* spare */ + 1 /* NUL */);
*cp = '\0';
if (filepfxoffset > 0)
memcpy(cp, start, (size_t) filepfxoffset);
memcpy(cp + filepfxoffset, name, len + 1);
return (cp);
}
}
}
return NULL;
} /* gl_local_filename_completion_proc */
#endif /* __unix__ */
#ifdef __windows__
char *
gl_local_filename_completion_proc(const char *start, int idx)
{
static HANDLE searchHandle = NULL;
static int filepfxoffset;
static size_t filepfxlen;
WIN32_FIND_DATA ffd;
DWORD dwErr;
char *cp, *c2, ch;
const char *filepfx;
const char *dirtoopen, *name;
char *dirtoopen1, *dirtoopen2;
size_t len, len2;
if (idx == 0) {
if (searchHandle != NULL) {
/* shouldn't get here! */
FindClose(searchHandle);
searchHandle = NULL;
}
}
if (searchHandle == NULL) {
dirtoopen1 = NULL;
dirtoopen2 = NULL;
cp = _StrRFindLocalPathDelim(start);
if (cp == start) {
dirtoopen = LOCAL_PATH_DELIM_STR; /* root dir */
filepfxoffset = 1;
} else if (cp == NULL) {
dirtoopen = ".";
filepfxoffset = 0;
} else {
len = strlen(start) + 1;
dirtoopen1 = (char *) malloc(len);
if (dirtoopen1 == NULL)
return NULL;
memcpy(dirtoopen1, start, len);
len = (cp - start);
dirtoopen1[len] = '\0';
dirtoopen = dirtoopen1;
filepfxoffset = (int) ((cp + 1) - start);
}
if (strcmp(dirtoopen, "~") == 0) {
if (gl_home_dir == NULL)
gl_set_home_dir(NULL);
if (gl_home_dir == NULL)
return (NULL);
dirtoopen = gl_home_dir;
}
len = strlen(dirtoopen);
dirtoopen2 = (char *) malloc(len + 8);
if (dirtoopen2 == NULL) {
if (dirtoopen1 != NULL)
free(dirtoopen1);
return NULL;
}
memcpy(dirtoopen2, dirtoopen, len + 1);
if (dirtoopen2[len - 1] == LOCAL_PATH_DELIM)
memcpy(dirtoopen2 + len, "*.*", (size_t) 4);
else
memcpy(dirtoopen2 + len, "\\*.*", (size_t) 5);
/* "Open" the directory. */
memset(&ffd, 0, sizeof(ffd));
searchHandle = FindFirstFile(dirtoopen2, &ffd);
free(dirtoopen2);
if (dirtoopen1 != NULL)
free(dirtoopen1);
if (searchHandle == INVALID_HANDLE_VALUE) {
return NULL;
}
filepfx = start + filepfxoffset;
filepfxlen = strlen(filepfx);
} else {
/* assumes "start" is same for each iteration. */
filepfx = start + filepfxoffset;
goto next;
}
for (;;) {
name = ffd.cFileName;
if ((name[0] == '.') && ((name[1] == '\0') || ((name[1] == '.') && (name[2] == '\0'))))
goto next; /* Skip . and .. */
if ((filepfxlen == 0) || (strnicmp(name, filepfx, filepfxlen) == 0)) {
/* match */
len = strlen(name);
cp = (char *) malloc(filepfxoffset + len + 4 /* spare */ + 1 /* NUL */);
*cp = '\0';
if (filepfxoffset > 0)
memcpy(cp, start, filepfxoffset);
memcpy(cp + filepfxoffset, name, len + 1);
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
/* Embed file type with name. */
c2 = cp + filepfxoffset + len + 1;
*c2++ = '\0';
*c2++ = 'd';
*c2 = '\0';
} else {
c2 = cp + filepfxoffset + len + 1;
*c2++ = '\0';
*c2++ = '-';
*c2 = '\0';
}
return (cp);
}
next:
if (!FindNextFile(searchHandle, &ffd)) {
dwErr = GetLastError();
if (dwErr != ERROR_NO_MORE_FILES) {
FindClose(searchHandle);
searchHandle = NULL;
return NULL;
}
/* no more items */
FindClose(searchHandle);
searchHandle = NULL;
if (idx == 1) {
/* There was exactly one match.
* In this special case, we
* want to append a \ instead
* of a space.
*/
cp = gl_matchlist[0];
ch = (char) cp[strlen(cp) + 2];
if (ch == (char) 'd')
gl_completion_exact_match_extra_char = LOCAL_PATH_DELIM;
if ((cp[0] == '~') && ((cp[1] == '\0') || (IsLocalPathDelim(cp[1])))) {
len = strlen(cp + 1) + /* NUL */ 1;
len2 = strlen(gl_home_dir);
if (IsLocalPathDelim(gl_home_dir[len2 - 1]))
len2--;
cp = (char *) realloc(gl_matchlist[0], len + len2 + 4);
if (cp == NULL) {
cp = gl_matchlist[0];
} else {
memmove(cp + len2, cp + 1, len);
memcpy(cp, gl_home_dir, len2);
c2 = cp + len + len2;
*c2++ = '\0';
*c2++ = ch;
*c2 = '\0';
gl_matchlist[0] = cp;
}
}
}
break;
}
}
return (NULL);
} /* gl_local_filename_completion_proc */
#endif /* __windows__ */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?