home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
programs
/
text
/
vim
/
src
/
archie.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-27
|
13KB
|
763 lines
/* 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;
}