This is archie.c in view mode; [Download] [Up]
/* vi:ts=4:sw=4 * * * VIM - Vi IMproved * * Code Contributions By: Bram Moolenaar mool@oce.nl * Tim Thompson twitch!tjt * Tony Andrews onecom!wldrdg!tony * G. R. (Fred) Walter watmath!watcgl!grwalter */ /* * archie.c -- RISC OS + UnixLib specific code. * * A lot of this file was written by Juergen Weigert. * * It was then hacked to pieces by Alun Jones to work on the Acorn * Archimedes! */ #include "vim.h" #include "globals.h" #include "param.h" #include "proto.h" #include <fcntl.h> #include <time.h> #include <unistd.h> #include <sys/types.h> #include <sys/os.h> #include <signal.h> #include <termio.h> static int Read __ARGS((char *, long)); static int WaitForChar __ARGS((int)); static int RealWaitForChar __ARGS((int)); static void fill_inbuf __ARGS((void)); static int do_resize = FALSE; /* I'm sure this should be defined in UnixLib, but it ain't! */ short ospeed; void mch_write(s, len) char *s; int len; { int i; for (i=0; i<len; i++) { os_vdu(s[i]); } } /* * GetChars(): low level input funcion. * Get a characters from the keyboard. * If time == 0 do not wait for characters. * If time == n wait a short time for characters. * If time == -1 wait forever for characters. */ int GetChars(buf, maxlen, time) char *buf; int maxlen; int time; { if (time >= 0) { if (WaitForChar(time) == 0) /* no character available */ return 0; } else /* time == -1 */ { /* * If there is no character available within 2 seconds (default) * write the autoscript file to disk */ if (WaitForChar((int)p_ut) == 0) updatescript(0); } WaitForChar(-1); return Read(buf, (long)maxlen); } void vim_delay() { clock_t now; now = clock(); while (clock() < now + CLOCKS_PER_SEC/2); } /* * No job control. Fake it by starting a new shell. */ void mch_suspend() { outstr("new shell started\n"); call_shell(NULL, 0, 1); } void mch_windinit() { Columns = 80; Rows = 24; flushbuf(); mch_get_winsize(); } /* * Check_win checks whether we have an interactive window. */ void check_win(argc, argv) int argc; char **argv; { if (!isatty(0) || !isatty(1)) { fprintf(stderr, "VIM: no controlling terminal\n"); exit(2); } } /* * fname_case(): Set the case of the filename, if it already exists. * This will cause the filename to remain exactly the same. */ void fname_case(name) char *name; { } void settitle(str) char *str; { } void resettitle() { } /* * Get name of current directory into buffer 'buf' of length 'len' bytes. * Return non-zero for success. */ int dirname(buf, len) char *buf; int len; { extern int errno; extern char *sys_errlist[]; if (getcwd(buf,len) == NULL) { strcpy(buf, sys_errlist[errno]); return 0; } return 1; } /* * get absolute filename into buffer 'buf' of length 'len' bytes */ int FullName(fname, buf, len) char *fname, *buf; int len; { int l; char olddir[MAXPATHL]; char *p; int c; int retval = 1; if (fname == NULL) /* always fail */ return 0; *buf = 0; if (*fname != '/') { /* * If the file name has a path, change to that directory for a moment, * and then do the getwd() (and get back to where we were). * This will get the correct path name with "../" things. */ if ((p = strrchr(fname, '/')) != NULL) { if (getcwd(olddir, MAXPATHL) == NULL) { p = NULL; /* can't get current dir: don't chdir */ retval = 0; } else { c = *p; *p = NUL; chdir("\\"); /* Try to maintain PSD */ if (chdir(fname)) retval = 0; else fname = p + 1; *p = c; } } if (getcwd(buf, len) == NULL) { retval = 0; *buf = NUL; } l = strlen(buf); if (l && buf[l - 1] != '/') strcat(buf, "/"); if (p) { chdir("\\"); /* Maintain PSD */ chdir(olddir); } } strcat(buf, fname); return retval; } /* * get file permissions for 'name' */ long getperm(name) char *name; { struct stat statb; if (stat(name, &statb)) return -1; return statb.st_mode; } /* * set file permission for 'name' to 'perm' */ int setperm(name, perm) char *name; int perm; { return chmod(name, perm); } /* * check if "name" is a directory */ int isdir(name) char *name; { struct stat statb; if (stat(name, &statb)) return -1; return (statb.st_mode & S_IFMT) == S_IFDIR; } void mch_windexit(r) int r; { settmode(0); stoptermcap(); flushbuf(); stopscript(); /* remove autoscript file */ exit(r); } void mch_settmode(raw) int raw; { static int old225, old226, old4; int retvals[3]; static struct termio told; struct termio tnew; if (raw) { /* Make arrow keys act as function keys. */ os_byte(4, 2, 0, retvals); old4 = retvals[1]; /* Now make function keys return NULL followed by a character. * Remember the old value for resetting. */ os_byte(225, 0xC0, 0, retvals); old225 = retvals[1]; os_byte(226, 0xD0, 0, retvals); old226 = retvals[1]; ioctl(0, TCGETA, &told); tnew = told; tnew.c_iflag &= ~(ICRNL | IXON); /* ICRNL enables typing ^V^M */ /* IXON enables typing ^S/^Q */ tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE); tnew.c_cc[VMIN] = 1; /* return after 1 char */ tnew.c_cc[VTIME] = 0; /* don't wait */ ioctl(0, TCSETA, &tnew); } else { os_byte(4, old4, 0, retvals); os_byte(225, old225, 0, retvals); os_byte(226, old226, 0, retvals); ioctl(0, TCSETA, &told); } } /* * Try to get the current window size: * 1. with an ioctl(), most accurate method * 2. from the environment variables LINES and COLUMNS * 3. from the termcap * 4. keep using the old values */ int mch_get_winsize() { int old_Rows = Rows; int old_Columns = Columns; char *p; Columns = 0; Rows = 0; /* * 1. try using an ioctl. It is the most accurate method. */ { struct winsize ws; if (ioctl(0, TIOCGWINSZ, &ws) == 0) { Columns = ws.ws_col; Rows = ws.ws_row; } } /* * 2. get size from environment */ if (Columns == 0 || Rows == 0) { if ((p = (char *)getenv("LINES"))) Rows = atoi(p); if ((p = (char *)getenv("COLUMNS"))) Columns = atoi(p); } /* * 3. try reading the termcap */ if (Columns == 0 || Rows == 0) { extern void getlinecol(); getlinecol(); /* get "co" and "li" entries from termcap */ } /* * 4. If everything fails, use the old values */ if (Columns <= 0 || Rows <= 0) { Columns = old_Columns; Rows = old_Rows; return 1; } debug2("mch_get_winsize: %dx%d\n", (int)Columns, (int)Rows); Rows_max = Rows; /* remember physical max height */ check_winsize(); script_winsize(); /* if size changed: screenalloc will allocate new screen buffers */ return (0); } void mch_set_winsize() { /* should try to set the window size to Rows and Columns */ } int call_shell(cmd, dummy, cooked) char *cmd; int dummy; int cooked; { int x; char newcmd[1024]; flushbuf(); if (cooked) settmode(0); /* set to cooked mode */ if (cmd == NULL) x = system(p_sh); else { sprintf(newcmd, "*%s", cmd); x = system(newcmd); } if (x == 127) { emsg("Cannot execute shell sh"); outchar('\n'); } else if (x) { smsg("%d returned", x); outchar('\n'); } if (cooked) settmode(1); /* set to raw mode */ return x; } /* * The input characters are buffered to be able to check for a CTRL-C. * This should be done with signals, but I don't know how to do that in * a portable way for a tty in RAW mode. */ #define INBUFLEN 50 static unsigned char inbuf[INBUFLEN]; /* internal typeahead buffer */ static int inbufcount = 0; /* number of chars in inbuf[] */ static int Read(buf, maxlen) char *buf; long maxlen; { if (inbufcount == 0) /* if the buffer is empty, fill it */ fill_inbuf(); if (maxlen > inbufcount) maxlen = inbufcount; memmove(buf, inbuf, maxlen); inbufcount -= maxlen; if (inbufcount) memmove(inbuf, inbuf + maxlen, inbufcount); return (int)maxlen; } void breakcheck() { /* * check for CTRL-C typed by reading all available characters */ if (RealWaitForChar(0)) /* if characters available */ fill_inbuf(); } static void fill_inbuf() { int len; if (inbufcount >= INBUFLEN) /* buffer full */ return; for (len=0; len < INBUFLEN-inbufcount; len++) { int key; key = os_inkey(0); if (key==-1) { break; } inbuf[inbufcount+len] = key; } while (len-- > 0) { /* * if a CTRL-C was typed, remove it from the buffer and set got_int */ if (inbuf[inbufcount] == 3) { /* remove everything typed before the CTRL-C */ memmove(inbuf, inbuf + inbufcount, len + 1); inbufcount = 0; got_int = TRUE; } ++inbufcount; } } /* * Wait "ticks" until a character is available from the keyboard or from inbuf[] * ticks = -1 will block forever */ static int WaitForChar(ticks) int ticks; { if (inbufcount) /* something in inbuf[] */ return 1; return RealWaitForChar(ticks); } /* * Wait "ticks" until a character is available from the keyboard * ticks = -1 will block forever */ static int RealWaitForChar(ticks) int ticks; { int key; if (ticks == -1) { key = os_get(); } else { key = os_inkey(ticks/10); } debug3("RWFC(%d) got %d (%c)\n", ticks, key, key); if (key != -1) { /* Unfortunately the key has now been taken from the * buffer, so we need to put it in outselves. It's a * shame, but the other way I can think of involves a * keyboard scan, and this would return for SHIFT, etc. */ if (inbufcount < INBUFLEN) { inbuf[inbufcount++] = key; } } return (key != -1); } /* * ExpandWildCard() - this code does wild-card pattern matching using the shell * * Mool: return 0 for success, 1 for error (you may loose some memory) and * put an error message in *file. * * num_pat is number of input patterns * pat is array of pointers to input patterns * num_file is pointer to number of matched file names * file is pointer to array of pointers to matched file names * On Unix we do not check for files only yet * list_notfound is ignored */ extern char *mktemp __ARGS((char *)); #ifndef SEEK_SET # define SEEK_SET 0 #endif #ifndef SEEK_END # define SEEK_END 2 #endif int ExpandWildCards(num_pat, pat, num_file, file, files_only, list_notfound) int num_pat; char **pat; int *num_file; char ***file; int files_only; int list_notfound; { char tmpname[TMPNAMELEN]; char *command; int i; int dir; size_t len; FILE *fd; char *buffer; char *p; *num_file = 0; /* default: no files found */ *file = (char **)""; /* * If there are no wildcards, just copy the names to allocated memory. * Saves a lot of time, because we don't have to run glob. */ if (!have_wildcard(num_pat, pat)) { *file = (char **)alloc(num_pat * sizeof(char *)); if (*file == NULL) { *file = (char **)""; return 1; } for (i = 0; i < num_pat; i++) (*file)[i] = strsave(pat[i]); *num_file = num_pat; return 0; } /* * get a name for the temp file */ strcpy(tmpname, TMPNAME2); if (*mktemp(tmpname) == NUL) { emsg(e_notmp); return 1; } len = TMPNAMELEN + 10; for (i = 0; i < num_pat; ++i) /* count the length of the patterns */ len += strlen(pat[i]) + 1; command = (char *)alloc(len); if (command == NULL) return 1; strcpy(command, "glob >"); /* built the shell command */ strcat(command, tmpname); for (i = 0; i < num_pat; ++i) { strcat(command, " "); strcat(command, pat[i]); } i = call_shell(command, 0, FALSE); /* execute it */ free(command); if (i) /* call_shell failed */ { remove(tmpname); sleep(1); /* give the user a chance to read error messages */ must_redraw = CLEAR; /* probably messed up screen */ return 1; } /* * read the names from the file into memory */ fd = fopen(tmpname, "r"); if (fd == NULL) { emsg(e_notopen); return 1; } fseek(fd, 0L, SEEK_END); len = ftell(fd); /* get size of temp file */ fseek(fd, 0L, SEEK_SET); buffer = (char *)alloc(len + 1); if (buffer == NULL) { remove(tmpname); fclose(fd); return 1; } i = fread(buffer, 1, len, fd); fclose(fd); remove(tmpname); if (i != len) { emsg(e_notread); free(buffer); return 1; } buffer[len] = NUL; /* make sure the buffers ends in NUL */ i = 0; for (p = buffer; p < buffer + len; ++p) if (*p == NUL) /* count entry */ ++i; if (len) ++i; /* count last entry */ *num_file = i; *file = (char **)alloc(sizeof(char *) * i); if (*file == NULL) { free(buffer); *file = (char **)""; return 1; } p = buffer; for (i = 0; i < *num_file; ++i) { (*file)[i] = p; while (*p && p < buffer + len) /* skip entry */ ++p; ++p; /* skip NUL */ } for (i = 0; i < *num_file; ++i) { dir = (isdir((*file)[i]) > 0); if (dir < 0) /* if file doesn't exist don't add '.' */ dir = 0; p = alloc((unsigned)(strlen((*file)[i]) + 1 + dir)); if (p) { strcpy(p, (*file)[i]); if (dir) strcat(p, "."); } (*file)[i] = p; } free(buffer); return 0; } void FreeWild(num, file) int num; char **file; { if (file == NULL || num == 0) return; while (num--) free(file[num]); free(file); } int has_wildcard(p) char *p; { return strpbrk(p, "*#") != NULL; } int have_wildcard(num, file) int num; char **file; { register int i; for (i = 0; i < num; i++) if (has_wildcard(file[i])) return 1; return 0; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.