home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume41
/
vim
/
part14
< prev
next >
Wrap
Text File
|
1993-12-20
|
66KB
|
2,853 lines
Newsgroups: comp.sources.misc
From: mool@oce.nl (Bram Moolenaar)
Subject: v41i064: vim - Vi IMitation editor, v2.0, Part14/25
Message-ID: <1993Dec21.035146.28532@sparky.sterling.com>
X-Md4-Signature: e893f42c485c2e2e6fe52ea6624a2a22
Keywords: utility, editor, vi, vim
Sender: kent@sparky.sterling.com (Kent Landfield)
Organization: Sterling Software
Date: Tue, 21 Dec 1993 03:51:46 GMT
Approved: kent@sparky.sterling.com
Submitted-by: mool@oce.nl (Bram Moolenaar)
Posting-number: Volume 41, Issue 64
Archive-name: vim/part14
Environment: UNIX, AMIGA, MS-DOS
Supersedes: vim: Volume 37, Issue 1-24
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 14 (of 25)."
# Contents: vim/src/amiga.c vim/src/buffers.c
# Wrapped by mool@oce-rd2 on Wed Dec 15 09:50:06 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'vim/src/amiga.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'vim/src/amiga.c'\"
else
echo shar: Extracting \"'vim/src/amiga.c'\" \(30444 characters\)
sed "s/^X//" >'vim/src/amiga.c' <<'END_OF_FILE'
X/* vi:ts=4:sw=4
X *
X * VIM - Vi IMproved
X *
X * Code Contributions By: Bram Moolenaar mool@oce.nl
X * Tim Thompson twitch!tjt
X * Tony Andrews onecom!wldrdg!tony
X * G. R. (Fred) Walter watmath!watcgl!grwalter
X */
X
X/*
X * amiga.c
X *
X * Amiga system-dependent routines.
X */
X
X#include "vim.h"
X#include "globals.h"
X#include "proto.h"
X#include "param.h"
X
X#include <fcntl.h>
X
X#undef TRUE /* will be redefined by exec/types.h */
X#undef FALSE
X
X#ifndef LATTICE
X# include <exec/types.h>
X# include <exec/exec.h>
X# include <libraries/dos.h>
X# include <libraries/dosextens.h>
X# include <intuition/intuition.h>
X#else
X# include <proto/dos.h>
X# include <libraries/dosextens.h>
X# include <proto/intuition.h>
X# include <proto/exec.h>
X#endif
X
X#ifndef NO_ARP
X#include <libraries/arpbase.h> /* for arp.library */
X#endif
X#include <dos/dostags.h> /* for 2.0 functions */
X#include <dos/dosasl.h>
X
X#if defined(LATTICE) && !defined(SASC) && !defined(NO_ARP)
X# include <libraries/arp_pragmas.h>
X#endif
X
X/*
X * At this point TRUE and FALSE are defined as 1L and 0L, but we want 1 and 0.
X */
X#undef TRUE
X#define TRUE (1)
X#undef FALSE
X#define FALSE (0)
X
X#ifndef AZTEC_C
Xstatic long dos_packet __ARGS((struct MsgPort *, long, long));
X#endif
Xstatic int lock2name __ARGS((BPTR lock, char *buf, long len));
Xstatic struct FileInfoBlock *get_fib __ARGS((char *));
Xstatic int sortcmp __ARGS((char **a, char **b));
X
Xstatic BPTR raw_in = (BPTR)NULL;
Xstatic BPTR raw_out = (BPTR)NULL;
Xstatic int close_win = FALSE; /* set if Vim opened the window */
X
Xstruct IntuitionBase *IntuitionBase = NULL;
X#ifndef NO_ARP
Xstruct ArpBase *ArpBase = NULL;
X#endif
X
Xstatic struct Window *wb_window;
Xstatic char *oldwindowtitle = NULL;
X
X#ifndef NO_ARP
Xint dos2 = FALSE; /* Amiga DOS 2.0x or higher */
X#endif
Xint size_set = FALSE; /* set to TRUE if window size was set */
X
X void
Xwin_resize_on()
X{
X outstrn("\033[12{");
X}
X
X void
Xwin_resize_off()
X{
X outstrn("\033[12}");
X}
X
X void
Xmch_write(p, len)
X char *p;
X int len;
X{
X Write(raw_out, p, (long)len);
X}
X
X/*
X * GetChars(): low level input funcion.
X * Get a characters from the keyboard.
X * If time == 0 do not wait for characters.
X * If time == n wait a short time for characters.
X * If time == -1 wait forever for characters.
X */
X int
XGetChars(buf, maxlen, time)
X char *buf;
X int maxlen;
X int time; /* milli seconds */
X{
X int len;
X long utime;
X
X if (time >= 0)
X {
X if (time == 0)
X utime = 100L; /* time = 0 causes problems in DOS 1.2 */
X else
X utime = time * 1000L; /* convert from milli to micro secs */
X if (WaitForChar(raw_in, utime) == 0) /* no character available */
X return 0;
X }
X else /* time == -1 */
X {
X /*
X * If there is no character available within 2 seconds (default)
X * write the autoscript file to disk
X */
X if (WaitForChar(raw_in, p_ut * 1000L) == 0)
X updatescript(0);
X }
X
X for (;;) /* repeat until we got a character */
X {
X len = Read(raw_in, buf, (long)maxlen);
X if (len > 0)
X return len;
X }
X}
X
X void
Xsleep(n)
X int n;
X{
X#ifndef LATTICE /* SAS declares void Delay(UNLONG) */
X void Delay __ARGS((long));
X#endif
X
X if (n > 0)
X Delay((long)(50L * n));
X}
X
X void
Xvim_delay()
X{
X Delay(25L);
X}
X
X/*
X * We have no job control, fake it by starting a new shell.
X */
Xvoid
Xmch_suspend()
X{
X outstr("new shell started\n");
X call_shell(NULL, 0, TRUE);
X}
X
X#define DOS_LIBRARY ((UBYTE *) "dos.library")
X
X void
Xmch_windinit()
X{
X static char intlibname[] = "intuition.library";
X
X#ifdef AZTEC_C
X Enable_Abort = 0; /* disallow vim to be aborted */
X#endif
X Columns = 80;
X Rows = 24;
X
X /*
X * Set input and output channels, unless we have opened our own window
X */
X if (raw_in == (BPTR)NULL)
X {
X raw_in = Input();
X raw_out = Output();
X }
X
X flushbuf();
X
X wb_window = NULL;
X if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary((UBYTE *)intlibname, 0L)) == NULL)
X {
X fprintf(stderr, "cannot open %s!?\n", intlibname);
X mch_windexit(3);
X }
X mch_get_winsize();
X}
X
X#include <workbench/startup.h>
X
X/*
X * Check_win checks whether we have an interactive window.
X * If not, a new window is opened with the newcli command.
X * If we would open a window ourselves, the :sh and :! commands would not
X * work properly (Why? probably because we are then running in a background CLI).
X * This also is the best way to assure proper working in a next Workbench release.
X *
X * For the -e option (quickfix mode) and -x we open our own window and disable :sh.
X * Otherwise the compiler would never know when editing is finished.
X */
X#define BUF2SIZE 320 /* lenght of buffer for argument with complete path */
X
X void
Xcheck_win(argc, argv)
X int argc;
X char **argv;
X{
X int i;
X BPTR nilfh, fh;
X char buf1[20];
X char buf2[BUF2SIZE];
X static char *(constrings[3]) = {"con:0/0/662/210/",
X "con:0/0/640/200/",
X "con:0/0/320/200/"};
X static char winerr[] = "VIM: Can't open window!\n";
X struct WBArg *argp;
X int ac;
X char *av;
X char *device = NULL;
X int exitval = 4;
X struct Library *DosBase;
X int usewin = FALSE;
X
X/*
X * check if we are running under DOS 2.0x or higher
X */
X if (DosBase = OpenLibrary(DOS_LIBRARY, 37L))
X {
X CloseLibrary(DosBase);
X#ifndef NO_ARP
X dos2 = TRUE;
X#endif
X }
X else /* without arp functions we NEED 2.0 */
X {
X#ifdef NO_ARP
X fprintf(stderr, "Need Amigados version 2.04 or later\n");
X exit(3);
X#else
X /* need arp functions for dos 1.x */
X if (!(ArpBase = (struct ArpBase *) OpenLibrary((UBYTE *)ArpName, ArpVersion)))
X {
X fprintf(stderr, "Need %s version %ld\n", ArpName, ArpVersion);
X exit(3);
X }
X#endif
X }
X
X/*
X * scan argv[] for the '-e', '-x' and '-d' arguments
X */
X for (i = 1; i < argc; ++i)
X if (argv[i][0] == '-')
X {
X switch (argv[i][1])
X {
X case 'e':
X case 'x':
X usewin = TRUE;
X break;
X
X case 'd':
X if (i < argc - 1)
X device = argv[i + 1];
X break;
X }
X }
X
X/*
X * If we were not started from workbench, do not have a '-d' argument and
X * we have been started with an interactive window, use that window.
X */
X if (argc != 0 && device == NULL &&
X IsInteractive(Input()) && IsInteractive(Output()))
X return;
X
X/*
X * If we are in quickfix mode, we open our own window. We can't use the
X * newcli trick below, because the compiler would not know when we are finished.
X * We do the same with the '-x' option, for mail, rn, etc.
X */
X if (usewin)
X {
X /*
X * Try to open a window. First try the specified device.
X * Then try a 24 line 80 column window.
X * If that fails, try two smaller ones.
X */
X for (i = -1; i < 3; ++i)
X {
X if (i >= 0)
X device = constrings[i];
X if (device && (raw_in = Open((UBYTE *)device, (long)MODE_NEWFILE)) != (BPTR)NULL)
X break;
X }
X if (raw_in == (BPTR)NULL) /* all three failed */
X {
X fprintf(stderr, winerr);
X goto exit;
X }
X raw_out = raw_in;
X close_win = TRUE;
X return;
X }
X
X if ((nilfh = Open((UBYTE *)"NIL:", (long)MODE_NEWFILE)) == (BPTR)NULL)
X {
X fprintf(stderr, "Cannot open NIL:\n");
X goto exit;
X }
X
X /*
X * make a unique name for the temp file (which we will not delete!)
X */
X sprintf(buf1, "t:nc%ld", buf1); /* nobody else is using our stack */
X if ((fh = Open((UBYTE *)buf1, (long)MODE_NEWFILE)) == (BPTR)NULL)
X {
X fprintf(stderr, "Cannot create %s\n", buf1);
X goto exit;
X }
X /*
X * Write the command into the file, put quotes around the arguments that
X * have a space in them.
X */
X if (argc == 0) /* run from workbench */
X ac = ((struct WBStartup *)argv)->sm_NumArgs;
X else
X ac = argc;
X for (i = 0; i < ac; ++i)
X {
X if (argc == 0)
X {
X *buf2 = NUL;
X argp = &(((struct WBStartup *)argv)->sm_ArgList[i]);
X if (argp->wa_Lock)
X lock2name(argp->wa_Lock, buf2, (long)(BUF2SIZE - 1));
X#ifndef NO_ARP
X if (dos2) /* use 2.0 function */
X#endif
X AddPart((UBYTE *)buf2, (UBYTE *)argp->wa_Name, (long)(BUF2SIZE - 1));
X#ifndef NO_ARP
X else /* use arp function */
X TackOn(buf2, argp->wa_Name);
X#endif
X av = buf2;
X }
X else
X av = argv[i];
X
X if (av[0] == '-' && av[1] == 'd') /* skip '-d' option */
X {
X ++i;
X continue;
X }
X if (strchr(av, ' '))
X Write(fh, "\"", 1L);
X Write(fh, av, (long)strlen(av));
X if (strchr(av, ' '))
X Write(fh, "\"", 1L);
X Write(fh, " ", 1L);
X }
X Write(fh, "\nendcli\n", 8L);
X Close(fh);
X
X/*
X * Try to open a new cli in a window. If '-d' argument was given try to open
X * the specified device. Then try a 24 line 80 column window.
X * If that fails, try two smaller ones.
X */
X for (i = -1; i < 3; ++i)
X {
X if (i >= 0)
X device = constrings[i];
X else if (device == NULL)
X continue;
X sprintf(buf2, "newcli <nil: >nil: %s from %s", device, buf1);
X#ifndef NO_ARP
X if (dos2)
X {
X#endif
X if (!SystemTags((UBYTE *)buf2, SYS_UserShell, TRUE, TAG_DONE))
X break;
X#ifndef NO_ARP
X }
X else
X {
X if (Execute((UBYTE *)buf2, nilfh, nilfh))
X break;
X }
X#endif
X }
X if (i == 3) /* all three failed */
X {
X DeleteFile((UBYTE *)buf1);
X fprintf(stderr, winerr);
X goto exit;
X }
X exitval = 0; /* The Execute succeeded: exit this program */
X
Xexit:
X#ifndef NO_ARP
X if (ArpBase)
X CloseLibrary((struct Library *) ArpBase);
X#endif
X exit(exitval);
X}
X
X/*
X * fname_case(): Set the case of the filename, if it already exists.
X * This will cause the filename to remain exactly the same.
X */
X void
Xfname_case(name)
X char *name;
X{
X register struct FileInfoBlock *fib;
X register size_t len;
X
X fib = get_fib(name);
X if (fib != NULL)
X {
X len = strlen(name);
X if (len == strlen(fib->fib_FileName)) /* safety check */
X memmove(name, fib->fib_FileName, len);
X free(fib);
X }
X}
X
X/*
X * Get the FileInfoBlock for file "fname"
X * The returned structure has to be free()d.
X * Returns NULL on error.
X */
X static struct FileInfoBlock *
Xget_fib(fname)
X char *fname;
X{
X register BPTR flock;
X register struct FileInfoBlock *fib;
X
X if (fname == NULL) /* safety check */
X return NULL;
X fib = (struct FileInfoBlock *)malloc(sizeof(struct FileInfoBlock));
X if (fib != NULL)
X {
X flock = Lock((UBYTE *)fname, (long)ACCESS_READ);
X if (flock == (BPTR)NULL || !Examine(flock, fib))
X {
X free(fib); /* in case of an error the memory is freed here */
X fib = NULL;
X }
X if (flock)
X UnLock(flock);
X }
X return fib;
X}
X
X/*
X * settitle(): set titlebar of our window
X */
Xstatic char *lasttitle = NULL;
X
X void
Xsettitle(str)
X char *str;
X{
X
X if (wb_window != NULL)
X {
X free(lasttitle);
X lasttitle = alloc((unsigned)(strlen(str) + 7));
X if (lasttitle != NULL)
X {
X sprintf(lasttitle, "VIM - %s", str);
X SetWindowTitles(wb_window, (UBYTE *)lasttitle, (UBYTE *)-1L);
X }
X }
X}
X
X void
Xresettitle()
X{
X if (wb_window != NULL && lasttitle != NULL)
X SetWindowTitles(wb_window, (UBYTE *)lasttitle, (UBYTE *)-1L);
X}
X
X/*
X * Get name of current directory into buffer 'buf' of length 'len' bytes.
X * Return non-zero for success.
X */
Xdirname(buf, len)
X char *buf;
X int len;
X{
X return FullName("", buf, len);
X}
X
X/*
X * get absolute filename into buffer 'buf' of length 'len' bytes
X */
XFullName(fname, buf, len)
X char *fname, *buf;
X int len;
X{
X BPTR l;
X int retval = 0;
X
X if (fname == NULL) /* always fail */
X return 0;
X
X if ((l = Lock((UBYTE *)fname, (long)ACCESS_READ)))/* lock the file */
X {
X retval = lock2name(l, buf, (long)len);
X UnLock(l);
X }
X if (retval == 0 || *buf == 0 || *buf == ':')
X strcpy(buf, fname); /* something failed; use the filename */
X return retval;
X}
X
X/*
X * Get the full filename from a lock. Use 2.0 function if possible, because
X * the arp function has more restrictions on the path length.
X */
X static int
Xlock2name(lock, buf, len)
X BPTR lock;
X char *buf;
X long len;
X{
X#ifndef NO_ARP
X if (dos2) /* use 2.0 function */
X#endif
X return (int)NameFromLock(lock, (UBYTE *)buf, len);
X#ifndef NO_ARP
X else /* use arp function */
X return (int)PathName(lock, buf, (long)(len/32));
X#endif
X}
X
X/*
X * get file permissions for 'name'
X */
X long
Xgetperm(name)
X char *name;
X{
X struct FileInfoBlock *fib;
X long retval = -1;
X
X fib = get_fib(name);
X if (fib != NULL)
X {
X retval = fib->fib_Protection;
X free(fib);
X }
X return retval;
X}
X
X/*
X * set file permission for 'name' to 'perm'
X */
Xsetperm(name, perm)
X char *name;
X long perm;
X{
X perm &= ~FIBF_ARCHIVE; /* reset archived bit */
X return (int)SetProtection((UBYTE *)name, (long)perm);
X}
X
X/*
X * check if "name" is a directory
X */
Xisdir(name)
X char *name;
X{
X struct FileInfoBlock *fib;
X int retval = -1;
X
X fib = get_fib(name);
X if (fib != NULL)
X {
X retval = (fib->fib_DirEntryType >= 0);
X free(fib);
X }
X return retval;
X}
X
X/*
X * Careful: mch_windexit() may be called before mch_windinit()!
X */
X void
Xmch_windexit(r)
X int r;
X{
X if (raw_in) /* put terminal in 'normal' mode */
X {
X settmode(0);
X stoptermcap();
X }
X if (raw_out)
X {
X if (term_console)
X {
X win_resize_off(); /* window resize events de-activated */
X if (size_set)
X outstr("\233t\233u"); /* reset window size (CSI t CSI u) */
X }
X flushbuf();
X }
X
X if (wb_window != NULL) /* disable window title */
X SetWindowTitles(wb_window, (UBYTE *)oldwindowtitle, (UBYTE *)-1L);
X stopscript(); /* remove autoscript file */
X#ifndef NO_ARP
X if (ArpBase)
X CloseLibrary((struct Library *) ArpBase);
X#endif
X if (close_win)
X Close(raw_in);
X if (r)
X printf("Vim exiting with %d\n", r); /* somehow this makes :cq work!? */
X exit(r);
X}
X
X/*
X * This is a routine for setting a given stream to raw or cooked mode on the
X * Amiga . This is useful when you are using Lattice C to produce programs
X * that want to read single characters with the "getch()" or "fgetc" call.
X *
X * Written : 18-Jun-87 By Chuck McManis.
X */
X
X#define MP(xx) ((struct MsgPort *)((struct FileHandle *) (BADDR(xx)))->fh_Type)
X
X/*
X * Function mch_settmode() - Convert the specified file pointer to 'raw' or 'cooked'
X * mode. This only works on TTY's.
X *
X * Raw: keeps DOS from translating keys for you, also (BIG WIN) it means
X * getch() will return immediately rather than wait for a return. You
X * lose editing features though.
X *
X * Cooked: This function returns the designate file pointer to it's normal,
X * wait for a <CR> mode. This is exactly like raw() except that
X * it sends a 0 to the console to make it back into a CON: from a RAW:
X */
X void
Xmch_settmode(raw)
X int raw;
X{
X if (dos_packet(MP(raw_in), (long)ACTION_SCREEN_MODE, raw ? -1L : 0L) == 0)
X fprintf(stderr, "cannot change console mode ?!\n");
X}
X
X/*
X * Code for this routine came from the following :
X *
X * ConPackets.c - C. Scheppner, A. Finkel, P. Lindsay CBM
X * DOS packet example
X * Requires 1.2
X *
X * Found on Fish Disk 56.
X *
X * Heavely modified by mool.
X */
X
X#include <devices/conunit.h>
X
X/*
X * try to get the real window size
X * return non-zero for failure
X */
X int
Xmch_get_winsize()
X{
X struct ConUnit *conUnit;
X char id_a[sizeof(struct InfoData) + 3];
X struct InfoData *id;
X
X if (!term_console) /* not an amiga window */
X return 1;
X
X /* insure longword alignment */
X id = (struct InfoData *)(((long)id_a + 3L) & ~3L);
X
X /*
X * Should make console aware of real window size, not the one we set.
X * Unfortunately, under DOS 2.0x this redraws the window and it
X * is rarely needed, so we skip it now, unless we changed the size.
X */
X if (size_set)
X outstr("\233t\233u"); /* CSI t CSI u */
X flushbuf();
X
X if (dos_packet(MP(raw_out), (long)ACTION_DISK_INFO, ((ULONG) id) >> 2) == 0 ||
X (wb_window = (struct Window *)id->id_VolumeNode) == NULL)
X {
X /* it's not an amiga window, maybe aux device */
X /* terminal type should be set */
X term_console = FALSE;
X return 1;
X }
X if (oldwindowtitle == NULL)
X oldwindowtitle = (char *)wb_window->Title;
X if (id->id_InUse == (BPTR)NULL)
X {
X fprintf(stderr, "mch_get_winsize: not a console??\n");
X return (2);
X }
X conUnit = (struct ConUnit *) ((struct IOStdReq *) id->id_InUse)->io_Unit;
X
X /* get window size */
X Rows = conUnit->cu_YMax + 1;
X Columns = conUnit->cu_XMax + 1;
X if (Rows < 0 || Rows > 200) /* cannot be an amiga window */
X {
X Columns = 80;
X Rows = 24;
X term_console = FALSE;
X return 1;
X }
X Rows_max = Rows; /* remember physical max height */
X
X check_winsize();
X script_winsize();
X
X return 0;
X}
X
X/*
X * try to set the real window size
X */
X void
Xmch_set_winsize()
X{
X if (term_console)
X {
X size_set = TRUE;
X outchar(CSI);
X outnum((long)Rows);
X outchar('t');
X outchar(CSI);
X outnum((long)Columns);
X outchar('u');
X flushbuf();
X }
X}
X
X#ifdef SETKEYMAP
X/*
X * load and activate a new keymap for our CLI - DOES NOT WORK -
X * The problem is that after the setting of the keymap the input blocks
X * But the new keymap works allright in another window.
X * Tried but no improvement:
X * - remembering the length, data and command fields in request->io_xxx
X * - settmode(0) first, settmode(1) afterwards
X * - putting the keymap directly in conunit structure
X */
X
X#include <devices/keymap.h>
X
X void
Xset_keymap(name)
X char *name;
X{
X char id_a[sizeof(struct InfoData) + 3];
X struct InfoData *id;
X static struct KeyMap *old;
X static BPTR segment = (BPTR)NULL;
X struct IOStdReq *request;
X int c;
X
X if (!term_console)
X return;
X
X /* insure longword alignment */
X id = (struct InfoData *)(((long)id_a + 3L) & ~3L);
X
X if (dos_packet(MP(raw_out), (long)ACTION_DISK_INFO, ((ULONG) id) >> 2) == 0)
X {
X emsg("dos_packet failed");
X return;
X }
X if (id->id_InUse == (BPTR)NULL)
X {
X emsg("not a console??");
X return;
X }
X request = (struct IOStdReq *) id->id_InUse;
X
X if (segment != (BPTR)NULL) /* restore old keymap */
X {
X request->io_Command = CD_SETKEYMAP;
X request->io_Length = sizeof(struct KeyMap);
X request->io_Data = (APTR)old;
X DoIO((struct IORequest *)request);
X if (request->io_Error)
X emsg("Cannot reset keymap");
X else /* no error, free the allocated memory */
X {
X UnLoadSeg(segment);
X FreeMem(old, sizeof(struct KeyMap));
X segment = (BPTR)NULL;
X }
X }
X if (name != NULL)
X {
X segment = LoadSeg(name);
X if (segment == (BPTR)NULL)
X {
X emsg("Cannot open keymap file");
X return;
X }
X old = (struct KeyMap *)AllocMem(sizeof(struct KeyMap), MEMF_PUBLIC);
X if (old == NULL)
X {
X emsg(e_outofmem);
X UnLoadSeg(segment);
X segment = (BPTR)NULL;
X }
X else
X {
X request->io_Command = CD_ASKKEYMAP;
X request->io_Length = sizeof(struct KeyMap);
X request->io_Data = (APTR)old;
X DoIO((struct IORequest *)request);
X if (request->io_Error)
X {
X emsg("Cannot get old keymap");
X UnLoadSeg(segment);
X segment = (BPTR)NULL;
X FreeMem(old, sizeof(struct KeyMap));
X }
X else
X {
X request->io_Command = CD_SETKEYMAP;
X request->io_Length = sizeof(struct KeyMap);
X request->io_Data = (APTR)((segment << 2) + 18);
X DoIO((struct IORequest *)request);
X if (request->io_Error)
X emsg("Cannot set keymap");
X
X /* test for blocking */
X request->io_Command = CMD_READ;
X request->io_Length = 1;
X request->io_Data = (APTR)&c;
X DoIO((struct IORequest *)request); /* BLOCK HERE! */
X if (request->io_Error)
X emsg("Cannot set keymap");
X }
X }
X }
X}
X#endif
X
X#ifndef AZTEC_C
X/*
X * Sendpacket.c
X *
X * An invaluable addition to your Amiga.lib file. This code sends a packet to
X * the given message port. This makes working around DOS lots easier.
X *
X * Note, I didn't write this, those wonderful folks at CBM did. I do suggest
X * however that you may wish to add it to Amiga.Lib, to do so, compile it and
X * say 'oml lib:amiga.lib -r sendpacket.o'
X */
X
X/* #include <proto/exec.h> */
X/* #include <proto/dos.h> */
X#include <exec/memory.h>
X
X/*
X * Function - dos_packet written by Phil Lindsay, Carolyn Scheppner, and Andy
X * Finkel. This function will send a packet of the given type to the Message
X * Port supplied.
X */
X
X static long
Xdos_packet(pid, action, arg)
X struct MsgPort *pid; /* process indentifier ... (handlers message port) */
X long action, /* packet type ... (what you want handler to do) */
X arg; /* single argument */
X{
X# ifndef NO_ARP
X struct MsgPort *replyport;
X struct StandardPacket *packet;
X long res1;
X
X if (dos2)
X# endif
X return DoPkt(pid, action, arg, 0L, 0L, 0L, 0L); /* use 2.0 function */
X# ifndef NO_ARP
X
X replyport = (struct MsgPort *) CreatePort(NULL, 0); /* use arp function */
X if (!replyport)
X return (0);
X
X /* Allocate space for a packet, make it public and clear it */
X packet = (struct StandardPacket *)
X AllocMem((long) sizeof(struct StandardPacket), MEMF_PUBLIC | MEMF_CLEAR);
X if (!packet) {
X DeletePort(replyport);
X return (0);
X }
X packet->sp_Msg.mn_Node.ln_Name = (char *) &(packet->sp_Pkt);
X packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
X packet->sp_Pkt.dp_Port = replyport;
X packet->sp_Pkt.dp_Type = action;
X packet->sp_Pkt.dp_Arg1 = arg;
X
X PutMsg(pid, (struct Message *)packet); /* send packet */
X
X WaitPort(replyport);
X GetMsg(replyport);
X
X res1 = packet->sp_Pkt.dp_Res1;
X
X FreeMem(packet, (long) sizeof(struct StandardPacket));
X DeletePort(replyport);
X
X return (res1);
X# endif
X}
X#endif
X
X/*
X * call shell, return non-zero for failure
X */
X int
Xcall_shell(cmd, filter, cooked)
X char *cmd;
X int filter; /* if != 0: called by dofilter() */
X int cooked;
X{
X BPTR mydir;
X int x;
X#ifndef LATTICE
X int use_execute;
X char *shellcmd = NULL;
X char *shellarg;
X#endif
X int retval = 0;
X
X if (close_win)
X {
X /* if Vim opened a window: Executing a shell may cause crashes */
X emsg("Cannot execute shell with -e or -x option");
X return 1;
X }
X
X if (term_console)
X win_resize_off(); /* window resize events de-activated */
X flushbuf();
X
X if (cooked)
X settmode(0); /* set to cooked mode */
X mydir = Lock((UBYTE *)"", (long)ACCESS_READ); /* remember current directory */
X
X#ifdef LATTICE /* not tested very much */
X if (cmd == NULL)
X {
X# ifndef NO_ARP
X if (dos2)
X# endif
X x = SystemTags(p_sh, SYS_UserShell, TRUE, TAG_DONE);
X# ifndef NO_ARP
X else
X x = Execute(p_sh, raw_in, raw_out);
X# endif
X }
X else
X {
X# ifndef NO_ARP
X if (dos2)
X# endif
X x = SystemTags(cmd, SYS_UserShell, TRUE, TAG_DONE);
X# ifndef NO_ARP
X else
X x = Execute(cmd, 0L, raw_out);
X# endif
X }
X# ifdef NO_ARP
X if (x < 0)
X# else
X if ((dos2 && x < 0) || (!dos2 && !x))
X# endif
X {
X if (cmd == NULL)
X emsg2("Cannot execute shell %s", p_sh);
X else
X emsg2("Cannot execute %s", cmd);
X outchar('\n');
X retval = 1;
X }
X# ifdef NO_ARP
X else if (x)
X# else
X else if (!dos2 || x)
X# endif
X {
X if (x = IoErr())
X {
X smsg("%d returned", x);
X outchar('\n');
X retval = 1;
X }
X }
X#else /* LATTICE */
X if (p_st >= 4 || (p_st >= 2 && !filter))
X use_execute = 1;
X else
X use_execute = 0;
X if (!use_execute)
X {
X /*
X * separate shell name from argument
X */
X shellcmd = strsave(p_sh);
X if (shellcmd == NULL) /* out of memory, use Execute */
X use_execute = 1;
X else
X {
X shellarg = shellcmd;
X skiptospace(&shellarg); /* find start of arguments */
X if (*shellarg != NUL)
X {
X *shellarg++ = NUL;
X skipspace(&shellarg);
X }
X }
X }
X if (cmd == NULL)
X {
X if (use_execute)
X {
X#ifndef NO_ARP
X if (dos2)
X#endif
X x = SystemTags((UBYTE *)p_sh, SYS_UserShell, TRUE, TAG_DONE);
X#ifndef NO_ARP
X else
X x = !Execute((UBYTE *)p_sh, raw_in, raw_out);
X#endif
X }
X else
X x = fexecl(shellcmd, shellcmd, shellarg, NULL);
X }
X else if (use_execute)
X {
X#ifndef NO_ARP
X if (dos2)
X#endif
X x = SystemTags((UBYTE *)cmd, SYS_UserShell, TRUE, TAG_DONE);
X#ifndef NO_ARP
X else
X x = !Execute((UBYTE *)cmd, 0L, raw_out);
X#endif
X }
X else if (p_st & 1)
X x = fexecl(shellcmd, shellcmd, shellarg, cmd, NULL);
X else
X x = fexecl(shellcmd, shellcmd, shellarg, "-c", cmd, NULL);
X#ifdef NO_ARP
X if (x < 0)
X#else
X if ((dos2 && x < 0) || (!dos2 && x))
X#endif
X {
X if (use_execute)
X emsg2("Cannot execute %s", cmd == NULL ? p_sh : cmd);
X else
X emsg2("Cannot execute shell %s", shellcmd);
X outchar('\n');
X retval = 1;
X }
X else
X {
X if (use_execute)
X {
X#ifdef NO_ARP
X if (x)
X#else
X if (!dos2 || x)
X#endif
X x = IoErr();
X }
X else
X x = wait();
X if (x)
X {
X smsg("%d returned", x);
X outchar('\n');
X retval = 1;
X }
X }
X free(shellcmd);
X#endif
X
X if (mydir = CurrentDir(mydir)) /* make sure we stay in the same directory */
X UnLock(mydir);
X if (cooked)
X settmode(1); /* set to raw mode */
X resettitle();
X if (term_console)
X win_resize_on(); /* window resize events activated */
X return retval;
X}
X
X/*
X * check for an "interrupt signal"
X * We only react to a CTRL-C, but also clear the other break signals to avoid trouble
X * with lattice-c programs.
X */
X void
Xbreakcheck()
X{
X if (SetSignal(0L, (long)(SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F)) & SIGBREAKF_CTRL_C)
X got_int = TRUE;
X}
X
X/* this routine causes manx to use this Chk_Abort() rather than it's own */
X/* otherwise it resets our ^C when doing any I/O (even when Enable_Abort */
X/* is zero). Since we want to check for our own ^C's */
X
X#ifdef _DCC
X#define Chk_Abort chkabort
X#endif
X
X long
XChk_Abort()
X{
X return(0L);
X}
X
X/*
X * ExpandWildCard() - this code does wild-card pattern matching using the arp
X * routines. This is based on WildDemo2.c (found in arp1.1
X * distribution). That code's copyright follows :
X *-------------------------------------------------------------------------
X * WildDemo2.c - Search filesystem for patterns, and separate into directories
X * and files, sorting each separately using DA lists.
X *
X * -+=SDB=+-
X *
X * Copyright (c) 1987, Scott Ballantyne
X * Use and abuse as you please.
X *
X * num_pat is number of input patterns
X * pat is array of pointers to input patterns
X * num_file is pointer to number of matched file names
X * file is pointer to array of pointers to matched file names
X * if file_only is TRUE we match only files, no dirs
X * if list_notfound is TRUE we include not-found entries (probably locked)
X * return 0 for success, 1 for error (you may loose some memory)
X *-------------------------------------------------------------------------
X */
X
X/* #include <arpfunctions.h> */
Xextern void *malloc __ARGS((size_t)), *calloc __ARGS((size_t, size_t));
Xstatic int insfile __ARGS((char *, int));
Xstatic void freefiles __ARGS((void));
X
X#define ANCHOR_BUF_SIZE (512)
X#define ANCHOR_SIZE (sizeof(struct AnchorPath) + ANCHOR_BUF_SIZE)
X
X/*
X * we use this structure to built a list of file names
X */
Xstruct onefile
X{
X struct onefile *next;
X char name[1]; /* really longer */
X} *namelist = NULL;
X
X/*
X * insert one file into the list of file names
X * return -1 for failure
X * return 0 for success
X */
X static int
Xinsfile(name, isdir)
X char *name;
X int isdir;
X{
X struct onefile *new;
X
X new = (struct onefile *)alloc((unsigned)(sizeof(struct onefile) + strlen(name) + isdir));
X if (new == NULL)
X return -1;
X strcpy(&(new->name[0]), name);
X if (isdir)
X strcat(&(new->name[0]), "/");
X new->next = namelist;
X namelist = new;
X return 0;
X}
X
X/*
X * free a whole list of file names
X */
X static void
Xfreefiles()
X{
X struct onefile *p;
X
X while (namelist)
X {
X p = namelist->next;
X free(namelist);
X namelist = p;
X }
X}
X
X static int
Xsortcmp(a, b)
X char **a, **b;
X{
X return strcmp(*a, *b);
X}
X
XExpandWildCards(num_pat, pat, num_file, file, files_only, list_notfound)
X int num_pat;
X char **pat;
X int *num_file;
X char ***file;
X int files_only;
X int list_notfound;
X{
X int i;
X struct AnchorPath *Anchor;
X int domatchend = FALSE;
X LONG Result;
X struct onefile *p;
X char *errmsg = NULL;
X char *starbuf, *sp, *dp;
X int foundone;
X
X *num_file = 0;
X *file = (char **)"";
X
X /* Get our AnchorBase */
X Anchor = (struct AnchorPath *) calloc((size_t)1, (size_t)ANCHOR_SIZE);
X if (!Anchor)
X goto OUT_OF_MEMORY;
X Anchor->ap_StrLen = ANCHOR_BUF_SIZE; /* ap_Length not supported anymore */
X#ifdef APF_DODOT
X Anchor->ap_Flags = APF_DODOT | APF_DOWILD; /* allow '.' for current dir */
X#else
X Anchor->ap_Flags = APF_DoDot | APF_DoWild; /* allow '.' for current dir */
X#endif
X
X for (i = 0; i < num_pat; i++)
X {
X#ifndef NO_ARP
X if (dos2)
X {
X#endif
X /* hack to replace '*' by '#?' */
X starbuf = alloc((unsigned)(2 * strlen(pat[i]) + 1)); /* maximum required */
X if (starbuf == NULL)
X goto OUT_OF_MEMORY;
X for (sp = pat[i], dp = starbuf; *sp; ++sp)
X {
X if (*sp == '*')
X {
X *dp++ = '#';
X *dp++ = '?';
X }
X else
X *dp++ = *sp;
X }
X *dp = NUL;
X Result = MatchFirst((UBYTE *)starbuf, Anchor);
X free(starbuf);
X#ifndef NO_ARP
X }
X else
X Result = FindFirst(pat[i], Anchor);
X#endif
X domatchend = TRUE;
X foundone = FALSE;
X while (Result == 0)
X {
X if (!files_only || Anchor->ap_Info.fib_DirEntryType < 0)
X {
X (*num_file)++;
X if (insfile(Anchor->ap_Buf, Anchor->ap_Info.fib_DirEntryType >= 0))
X {
XOUT_OF_MEMORY:
X errmsg = "Out of memory";
X goto Return;
X }
X foundone = TRUE;
X }
X#ifndef NO_ARP
X if (dos2)
X#endif
X Result = MatchNext(Anchor);
X#ifndef NO_ARP
X else
X Result = FindNext(Anchor);
X#endif
X }
X if (Result == ERROR_BUFFER_OVERFLOW)
X {
X errmsg = "ANCHOR_BUF_SIZE too small.";
X goto Return;
X }
X if (!foundone)
X {
X if (list_notfound) /* put object with error in list */
X {
X (*num_file)++;
X if (insfile(pat[i], FALSE))
X goto OUT_OF_MEMORY;
X }
X else if (Result != ERROR_OBJECT_NOT_FOUND && Result != ERROR_NO_MORE_ENTRIES)
X {
X errmsg = "I/O ERROR";
X goto Return;
X }
X }
X#ifndef NO_ARP
X if (dos2)
X#endif
X MatchEnd(Anchor);
X#ifndef NO_ARP
X else
X {
X FreeAnchorChain(Anchor);
X Anchor = NULL; /* is this right or wrong? */
X }
X#endif
X domatchend = FALSE;
X }
X
X p = namelist;
X if (p)
X {
X *file = (char **) malloc(sizeof(char *) * (*num_file));
X if (*file == NULL)
X goto OUT_OF_MEMORY;
X for (i = *num_file - 1; p; p = p->next, --i)
X {
X (*file)[i] = (char *) malloc(strlen(p->name) + 1);
X if ((*file)[i] == NULL)
X goto OUT_OF_MEMORY;
X strcpy((*file)[i], p->name);
X }
X qsort((void *)*file, (size_t)*num_file, sizeof(char *), sortcmp);
X }
XReturn:
X if (domatchend)
X {
X#ifndef NO_ARP
X if (dos2)
X#endif
X MatchEnd(Anchor);
X#ifndef NO_ARP
X else
X {
X FreeAnchorChain(Anchor);
X Anchor = NULL; /* is this right or wrong? */
X }
X#endif
X }
X if (Anchor)
X free(Anchor);
X freefiles();
X if (errmsg)
X {
X emsg(errmsg);
X *num_file = 0;
X return 1;
X }
X return 0;
X}
X
X void
XFreeWild(num, file)
X int num;
X char **file;
X{
X if (file == NULL || num == 0)
X return;
X while (num--)
X free(file[num]);
X free(file);
X}
X
X int
Xhas_wildcard(p)
X char *p;
X{
X for ( ; *p; ++p)
X if (strchr("*?[(~#", *p) != NULL)
X return 1;
X return 0;
X}
X
X/*
X * With 2.0 support for reading local environment variables
X */
X
X char *
Xvimgetenv(var)
X char *var;
X{
X int len;
X
X#ifndef NO_ARP
X if (!dos2)
X return getenv(var);
X#endif
X
X len = GetVar((UBYTE *)var, (UBYTE *)IObuff, (long)(IOSIZE - 1), (long)0);
X
X if (len == -1)
X return NULL;
X else
X return IObuff;
X}
END_OF_FILE
if test 30444 -ne `wc -c <'vim/src/amiga.c'`; then
echo shar: \"'vim/src/amiga.c'\" unpacked with wrong size!
fi
chmod +x 'vim/src/amiga.c'
# end of 'vim/src/amiga.c'
fi
if test -f 'vim/src/buffers.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'vim/src/buffers.c'\"
else
echo shar: Extracting \"'vim/src/buffers.c'\" \(29561 characters\)
sed "s/^X//" >'vim/src/buffers.c' <<'END_OF_FILE'
X/* vi:ts=4:sw=4
X *
X * VIM - Vi IMproved
X *
X * Code Contributions By: Bram Moolenaar mool@oce.nl
X * Tim Thompson twitch!tjt
X * Tony Andrews onecom!wldrdg!tony
X * G. R. (Fred) Walter watmath!watcgl!grwalter
X */
X
X/*
X * buffers.c
X *
X * manipulations with redo buffer and stuff buffer
X */
X
X#include "vim.h"
X#include "globals.h"
X#include "proto.h"
X#include "param.h"
X
X/*
X * structure used to store one block of the stuff/redo/macro buffers
X */
Xstruct bufblock
X{
X struct bufblock *b_next; /* pointer to next bufblock */
X u_char b_str[1]; /* contents (actually longer) */
X};
X
X#define MINIMAL_SIZE 20 /* minimal size for b_str */
X
X/*
X * header used for the stuff buffer and the redo buffer
X */
Xstruct buffheader
X{
X struct bufblock bh_first; /* first (dummy) block of list */
X struct bufblock *bh_curr; /* bufblock for appending */
X int bh_index; /* index for reading */
X int bh_space; /* space in bh_curr for appending */
X};
X
Xstatic struct buffheader stuffbuff = {{NULL, {NUL}}, NULL, 0, 0};
Xstatic struct buffheader redobuff = {{NULL, {NUL}}, NULL, 0, 0};
Xstatic struct buffheader recordbuff = {{NULL, {NUL}}, NULL, 0, 0};
X
X /*
X * when block_redo is TRUE redo buffer will not be changed
X * used by edit() to repeat insertions and 'V' command for redoing
X */
Xstatic int block_redo = FALSE;
X
X/*
X * structure used for mapping
X */
Xstruct mapblock
X{
X struct mapblock *m_next; /* next mapblock */
X char *m_keys; /* mapped from */
X int m_keylen; /* strlen(m_keys) */
X char *m_str; /* mapped to */
X int m_mode; /* valid mode */
X int m_noremap; /* if non-zero no re-mapping for m_str */
X};
X
Xstatic struct mapblock maplist = {NULL, NULL, 0, NULL, 0, 0};
X /* first dummy entry in maplist */
X
X/*
X * variables used by vgetorpeek() and flush_buffers()
X *
X * typestr contains all characters that are not consumed yet.
X * The part in front may contain the result of mappings and @a commands.
X * The lenght of this part is typemaplen.
X * After it are characters that come from the terminal.
X * Some parts of typestr may not be mapped. These parts are remembered in
X * the noremaplist.
X */
X#define MAXMAPLEN 50 /* maximum length of key sequence to be mapped */
X /* must be able to hold an Amiga resize report */
Xstatic char *typestr = NULL; /* NUL-terminated buffer for typeahead characters */
Xstatic char typebuf[MAXMAPLEN + 3]; /* initial typestr */
X
Xstatic int typemaplen = 0; /* number of mapped characters in typestr */
X
X/*
X * parts int typestr that should not be mapped are remembered with a list
X * of noremap structs. Noremaplist is the first.
X */
Xstruct noremap
X{
X int nr_off; /* offset to not remappable chars */
X int nr_len; /* number of not remappable chars */
X struct noremap *nr_next; /* next entry in the list */
X};
X
Xstatic struct noremap noremaplist = {0, 0, NULL};
X
Xstatic void free_buff __ARGS((struct buffheader *));
Xstatic u_char *get_bufcont __ARGS((struct buffheader *, int));
Xstatic void add_buff __ARGS((struct buffheader *, char *));
Xstatic void add_num_buff __ARGS((struct buffheader *, long));
Xstatic void add_char_buff __ARGS((struct buffheader *, int));
Xstatic u_char read_stuff __ARGS((int));
Xstatic int start_stuff __ARGS((void));
Xstatic int read_redo __ARGS((int));
Xstatic void gotchars __ARGS((char *, int));
Xstatic void init_typestr __ARGS((void));
Xstatic u_char vgetorpeek __ARGS((int));
Xstatic void showmap __ARGS((struct mapblock *));
X
X/*
X * free and clear a buffer
X */
X static void
Xfree_buff(buf)
X struct buffheader *buf;
X{
X register struct bufblock *p, *np;
X
X for (p = buf->bh_first.b_next; p != NULL; p = np)
X {
X np = p->b_next;
X free((char *)p);
X }
X buf->bh_first.b_next = NULL;
X}
X
X/*
X * return the contents of a buffer as a single string
X */
X static u_char *
Xget_bufcont(buffer, dozero)
X struct buffheader *buffer;
X int dozero; /* count == zero is not an error */
X{
X u_long count = 0;
X u_char *p = NULL;
X struct bufblock *bp;
X
X/* compute the total length of the string */
X for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next)
X count += strlen((char *)bp->b_str);
X
X if ((count || dozero) && (p = (u_char *)lalloc(count + 1, TRUE)) != NULL)
X {
X *p = NUL;
X for (bp = buffer->bh_first.b_next; bp != NULL; bp = bp->b_next)
X strcat((char *)p, (char *)bp->b_str);
X }
X return (p);
X}
X
X/*
X * return the contents of the record buffer as a single string
X * and clear the record buffer
X */
X u_char *
Xget_recorded()
X{
X u_char *p;
X
X p = get_bufcont(&recordbuff, TRUE);
X free_buff(&recordbuff);
X return (p);
X}
X
X/*
X * return the contents of the redo buffer as a single string
X */
X u_char *
Xget_inserted()
X{
X return(get_bufcont(&redobuff, FALSE));
X}
X
X/*
X * add string "s" after the current block of buffer "buf"
X */
X static void
Xadd_buff(buf, s)
X register struct buffheader *buf;
X char *s;
X{
X struct bufblock *p;
X u_long n;
X u_long len;
X
X if ((n = strlen(s)) == 0) /* don't add empty strings */
X return;
X
X if (buf->bh_first.b_next == NULL) /* first add to list */
X {
X buf->bh_space = 0;
X buf->bh_curr = &(buf->bh_first);
X }
X else if (buf->bh_curr == NULL) /* buffer has already been read */
X {
X emsg("Add to read buffer");
X return;
X }
X else if (buf->bh_index != 0)
X strcpy((char *)buf->bh_first.b_next->b_str, (char *)buf->bh_first.b_next->b_str + buf->bh_index);
X buf->bh_index = 0;
X
X if (buf->bh_space >= n)
X {
X strcat((char *)buf->bh_curr->b_str, s);
X buf->bh_space -= n;
X }
X else
X {
X if (n < MINIMAL_SIZE)
X len = MINIMAL_SIZE;
X else
X len = n;
X p = (struct bufblock *)lalloc((u_long)(sizeof(struct bufblock) + len), TRUE);
X if (p == NULL)
X return; /* no space, just forget it */
X buf->bh_space = len - n;
X strcpy((char *)p->b_str, s);
X
X p->b_next = buf->bh_curr->b_next;
X buf->bh_curr->b_next = p;
X buf->bh_curr = p;
X }
X return;
X}
X
X static void
Xadd_num_buff(buf, n)
X struct buffheader *buf;
X long n;
X{
X char number[32];
X
X sprintf(number, "%ld", n);
X add_buff(buf, number);
X}
X
X static void
Xadd_char_buff(buf, c)
X struct buffheader *buf;
X int c;
X{
X char temp[2];
X
X temp[0] = c;
X temp[1] = NUL;
X add_buff(buf, temp);
X}
X
X/*
X * get one character from the stuff buffer
X * If advance == TRUE go to the next char.
X */
X static u_char
Xread_stuff(advance)
X int advance;
X{
X register u_char c;
X register struct bufblock *curr;
X
X
X if (stuffbuff.bh_first.b_next == NULL) /* buffer is empty */
X return NUL;
X
X curr = stuffbuff.bh_first.b_next;
X c = curr->b_str[stuffbuff.bh_index];
X
X if (advance)
X {
X if (curr->b_str[++stuffbuff.bh_index] == NUL)
X {
X stuffbuff.bh_first.b_next = curr->b_next;
X free((char *)curr);
X stuffbuff.bh_index = 0;
X }
X }
X return c;
X}
X
X/*
X * prepare stuff buffer for reading (if it contains something)
X */
X static int
Xstart_stuff()
X{
X if (stuffbuff.bh_first.b_next == NULL)
X return FALSE;
X stuffbuff.bh_curr = &(stuffbuff.bh_first);
X stuffbuff.bh_space = 0;
X return TRUE;
X}
X
X/*
X * check if the stuff buffer is empty
X */
X int
Xstuff_empty()
X{
X return (stuffbuff.bh_first.b_next == NULL);
X}
X
X/*
X * Remove the contents of the stuff buffer and the mapped characters in the
X * typeahead buffer (used in case of an error). If 'typeahead' is true,
X * flush all typeahead characters (used when interrupted by a CTRL-C).
X */
X void
Xflush_buffers(typeahead)
X int typeahead;
X{
X struct noremap *p;
X
X init_typestr();
X
X start_stuff();
X while (read_stuff(TRUE) != NUL)
X ;
X
X if (typeahead) /* remove all typeahead */
X {
X /*
X * We have to get all characters, because we may delete the first
X * part of an escape sequence.
X * In an xterm we get one char at a time and we have to get them all.
X */
X while (inchar(typestr, MAXMAPLEN, 10))
X ;
X *typestr = NUL;
X }
X else /* remove mapped characters only */
X strcpy(typestr, typestr + typemaplen);
X typemaplen = 0;
X noremaplist.nr_len = 0;
X noremaplist.nr_off = 0;
X while (noremaplist.nr_next)
X {
X p = noremaplist.nr_next->nr_next;
X free(noremaplist.nr_next);
X noremaplist.nr_next = p;
X }
X}
X
X void
XResetRedobuff()
X{
X if (!block_redo)
X free_buff(&redobuff);
X}
X
X void
XAppendToRedobuff(s)
X char *s;
X{
X if (!block_redo)
X add_buff(&redobuff, s);
X}
X
X void
XAppendCharToRedobuff(c)
X int c;
X{
X if (!block_redo)
X add_char_buff(&redobuff, c);
X}
X
X void
XAppendNumberToRedobuff(n)
X long n;
X{
X if (!block_redo)
X add_num_buff(&redobuff, n);
X}
X
X void
XstuffReadbuff(s)
X char *s;
X{
X add_buff(&stuffbuff, s);
X}
X
X void
XstuffcharReadbuff(c)
X int c;
X{
X add_char_buff(&stuffbuff, c);
X}
X
X void
XstuffnumReadbuff(n)
X long n;
X{
X add_num_buff(&stuffbuff, n);
X}
X
X/*
X * Read a character from the redo buffer.
X * The redo buffer is left as it is.
X */
X static int
Xread_redo(init)
X int init;
X{
X static struct bufblock *bp;
X static u_char *p;
X int c;
X
X if (init)
X {
X if ((bp = redobuff.bh_first.b_next) == NULL)
X return TRUE;
X p = bp->b_str;
X return FALSE;
X }
X if ((c = *p) != NUL)
X {
X if (*++p == NUL && bp->b_next != NULL)
X {
X bp = bp->b_next;
X p = bp->b_str;
X }
X }
X return c;
X}
X
X/*
X * copy the rest of the redo buffer into the stuff buffer (could be done faster)
X */
X void
Xcopy_redo()
X{
X register int c;
X
X while ((c = read_redo(FALSE)) != NUL)
X stuffcharReadbuff(c);
X}
X
Xextern int redo_Visual_busy; /* this is in normal.c */
X
X/*
X * Stuff the redo buffer into the stuffbuff.
X * Insert the redo count into the command.
X */
X int
Xstart_redo(count)
X long count;
X{
X register int c;
X
X if (read_redo(TRUE)) /* init the pointers; return if nothing to redo */
X return FALSE;
X
X c = read_redo(FALSE);
X
X/* copy the buffer name, if present */
X if (c == '"')
X {
X add_buff(&stuffbuff, "\"");
X c = read_redo(FALSE);
X
X/* if a numbered buffer is used, increment the number */
X if (c >= '1' && c < '9')
X ++c;
X add_char_buff(&stuffbuff, c);
X c = read_redo(FALSE);
X }
X
X if (c == 'v') /* redo Visual */
X {
X Visual = Curpos;
X redo_Visual_busy = TRUE;
X c = read_redo(FALSE);
X }
X
X/* try to enter the count (in place of a previous count) */
X if (count)
X {
X while (isdigit(c)) /* skip "old" count */
X c = read_redo(FALSE);
X add_num_buff(&stuffbuff, count);
X }
X
X/* copy from the redo buffer into the stuff buffer */
X add_char_buff(&stuffbuff, c);
X copy_redo();
X return TRUE;
X}
X
X/*
X * Repeat the last insert (R, o, O, a, A, i or I command) by stuffing
X * the redo buffer into the stuffbuff.
X */
X int
Xstart_redo_ins()
X{
X register u_char c;
X
X if (read_redo(TRUE))
X return FALSE;
X start_stuff();
X
X/* skip the count and the command character */
X while ((c = read_redo(FALSE)) != NUL)
X {
X c = TO_UPPER(c);
X if (strchr("AIRO", c) != NULL)
X {
X if (c == 'O')
X stuffReadbuff(NL_STR);
X break;
X }
X }
X
X/* copy the typed text from the redo buffer into the stuff buffer */
X copy_redo();
X block_redo = TRUE;
X return TRUE;
X}
X
X void
Xset_redo_ins()
X{
X block_redo = TRUE;
X}
X
X void
Xstop_redo_ins()
X{
X block_redo = FALSE;
X}
X
X/*
X * insert a string in front of the typeahead buffer (for '@' command and vgetorpeek)
X */
X int
Xins_typestr(str, noremap)
X char *str;
X int noremap;
X{
X register char *s;
X register int newlen;
X register int addlen;
X
X init_typestr();
X
X /*
X * In typestr there must always be room for MAXMAPLEN + 3 characters
X */
X addlen = strlen(str);
X newlen = strlen(typestr) + addlen + MAXMAPLEN + 3;
X if (newlen < 0) /* string is getting too long */
X {
X emsg(e_toocompl); /* also calls flush_buffers */
X setcursor();
X return -1;
X }
X s = alloc(newlen);
X if (s == NULL) /* out of memory */
X return -1;
X
X strcpy(s, str);
X strcat(s, typestr);
X if (typestr != typebuf)
X free(typestr);
X typestr = s;
X typemaplen += addlen; /* the inserted string is not typed */
X if (noremap)
X {
X if (noremaplist.nr_off == 0)
X noremaplist.nr_len += addlen;
X else
X {
X struct noremap *p;
X
X p = (struct noremap *)alloc((int)sizeof(struct noremap));
X if (p != NULL)
X {
X p->nr_next = noremaplist.nr_next;
X p->nr_off = noremaplist.nr_off;
X p->nr_len = noremaplist.nr_len;
X noremaplist.nr_next = p;
X noremaplist.nr_len = addlen;
X noremaplist.nr_off = 0;
X }
X }
X }
X else if (noremaplist.nr_len)
X noremaplist.nr_off += addlen;
X return 0;
X}
X
X/*
X * remove "len" characters from the front of typestr
X */
X void
Xdel_typestr(len)
X int len;
X{
X struct noremap *p;
X
X strcpy(typestr, typestr + len); /* remove chars from the buffer */
X if ((typemaplen -= len) <= 0) /* adjust typemaplen */
X typemaplen = 0;
X while (len) /* adjust noremaplist */
X {
X if (noremaplist.nr_off >= len)
X {
X noremaplist.nr_off -= len;
X break;
X }
X len -= noremaplist.nr_off;
X noremaplist.nr_off = 0;
X if (noremaplist.nr_len > len)
X {
X noremaplist.nr_len -= len;
X break;
X }
X len -= noremaplist.nr_len;
X p = noremaplist.nr_next;
X if (p == NULL)
X {
X noremaplist.nr_len = 0;
X break;
X }
X noremaplist.nr_next = p->nr_next;
X noremaplist.nr_len = p->nr_len;
X noremaplist.nr_off = p->nr_off;
X free(p);
X }
X}
X
Xextern int arrow_used; /* this is in edit.c */
X
X/*
X * Write typed characters to script file.
X * If recording is on put the character in the recordbuffer.
X */
X static void
Xgotchars(s, len)
X char *s;
X int len;
X{
X while (len--)
X {
X updatescript(*s & 255);
X
X if (Recording)
X add_char_buff(&recordbuff, (*s & 255));
X ++s;
X }
X
X /* do not sync in insert mode, unless cursor key has been used */
X if (!(State & (INSERT + CMDLINE)) || arrow_used)
X u_sync();
X}
X
X/*
X * Initialize typestr to point to typebuf.
X * Alloc() cannot be used here: In out-of-memory situations it would
X * be impossible to type anything.
X */
X static void
Xinit_typestr()
X{
X if (typestr == NULL)
X {
X typestr = typebuf;
X typebuf[0] = NUL;
X }
X}
X
X#define NEEDMORET 9999 /* value for incomplete mapping or key-code */
X
X/*
X * get a character: 1. from the stuffbuffer
X * 2. from the typeahead buffer
X * 3. from the user
X *
X * KeyTyped is set to TRUE in the case the user typed the key.
X * If advance is TRUE, we really get the character. Otherwise we just look
X * whether there is a character available.
X */
X static u_char
Xvgetorpeek(advance)
X int advance;
X{
X register int c;
X int n = 0; /* init for GCC */
X int len;
X#ifdef AMIGA
X char *s;
X#endif
X register struct mapblock *mp;
X int timedout = FALSE; /* waited for more than 1 second
X for mapping to complete */
X int mapdepth = 0; /* check for recursive mapping */
X int mode_deleted = FALSE; /* set when mode has been deleted */
X
X init_typestr();
X start_stuff();
X if (typemaplen == 0)
X Exec_reg = FALSE;
X do
X {
X c = read_stuff(advance);
X if (c != NUL && !got_int)
X KeyTyped = FALSE;
X else
X {
X /*
X * Loop until we either find a matching mapped key, or we
X * are sure that it is not a mapped key.
X * If a mapped key sequence is found we go back to the start to
X * try re-mapping.
X */
X
X for (;;)
X {
X len = strlen(typestr);
X breakcheck(); /* check for CTRL-C */
X if (got_int)
X {
X c = inchar(typestr, MAXMAPLEN, 0); /* flush all input */
X /*
X * If inchar returns TRUE (script file was active) or we are
X * inside a mapping, get out of insert mode.
X * Otherwise we behave like having gotten a CTRL-C.
X * As a result typing CTRL-C in insert mode will
X * really insert a CTRL-C.
X */
X if ((c || typemaplen) && (State & (INSERT + CMDLINE)))
X c = ESC;
X else
X c = Ctrl('C');
X flush_buffers(TRUE); /* flush all typeahead */
X break;
X }
X else if (len > 0) /* see if we have a mapped key sequence */
X {
X /*
X * walk through the maplist until we find an
X * entry that matches (if not timed out).
X */
X mp = NULL;
X if (!timedout && (typemaplen == 0 || (p_remap &&
X (noremaplist.nr_len == 0 || noremaplist.nr_off != 0)))
X && !((State & (INSERT + CMDLINE)) && p_paste))
X {
X for (mp = maplist.m_next; mp; mp = mp->m_next)
X {
X if ((mp->m_mode & ABBREV) || !(mp->m_mode & State))
X continue;
X n = mp->m_keylen;
X if (noremaplist.nr_off != 0 && n > noremaplist.nr_off)
X continue;
X if (!strncmp(mp->m_keys, typestr, (size_t)(n > len ? len : n)))
X break;
X }
X }
X if (mp == NULL) /* no match found */
X {
X /*
X * check if we have a terminal code, when
X * mapping is allowed,
X * keys have not been mapped,
X * and not an ESC sequence, not in insert mode or
X * p_ek is on,
X * and when not timed out,
X */
X if (State != NOMAPPING &&
X typemaplen == 0 &&
X (typestr[0] != ESC || p_ek || !(State & INSERT)) &&
X !timedout)
X n = check_termcode(typestr);
X else
X n = 0;
X if (n == 0) /* no matching terminal code */
X {
X#ifdef AMIGA /* check for window bounds report */
X if (typemaplen == 0 && (typestr[0] & 0xff) == CSI)
X {
X for (s = typestr + 1; isdigit(*s) || *s == ';' || *s == ' '; ++s)
X ;
X if (*s == 'r' || *s == '|') /* found one */
X {
X strcpy(typestr, s + 1);
X set_winsize(0, 0, FALSE); /* get size and redraw screen */
X continue;
X }
X if (*s == NUL) /* need more characters */
X n = -1;
X }
X if (n != -1) /* got a single character */
X#endif
X {
X c = typestr[0] & 255;
X if (typemaplen)
X KeyTyped = FALSE;
X else
X {
X KeyTyped = TRUE;
X if (advance) /* write char to script file(s) */
X gotchars(typestr, 1);
X }
X if (advance) /* remove chars from typestr */
X del_typestr(1);
X break; /* got character, break for loop */
X }
X }
X if (n > 0) /* full matching terminal code */
X continue; /* try mapping again */
X
X /* partial match: get some more characters */
X n = NEEDMORET;
X }
X if (n <= len) /* complete match */
X {
X if (n > typemaplen) /* write chars to script file(s) */
X gotchars(typestr + typemaplen, n - typemaplen);
X
X del_typestr(n); /* remove the mapped keys */
X
X /*
X * Put the replacement string in front of mapstr.
X * The depth check catches ":map x y" and ":map y x".
X */
X if (++mapdepth == 1000)
X {
X emsg("recursive mapping");
X if (State == CMDLINE)
X redrawcmdline();
X else
X setcursor();
X flush_buffers(FALSE);
X mapdepth = 0; /* for next one */
X c = -1;
X break;
X }
X if (ins_typestr(mp->m_str, mp->m_noremap) < 0)
X {
X c = -1;
X break;
X }
X continue;
X }
X }
X /*
X * special case: if we get an <ESC> in insert mode and there are
X * no more characters at once, we pretend to go out of insert mode.
X * This prevents the one second delay after typing an <ESC>.
X * If we get something after all, we may have to redisplay the
X * mode. That the cursor is in the wrong place does not matter.
X */
X c = 0;
X if (advance && len == 1 && typestr[0] == ESC && typemaplen == 0 && (State & INSERT) && (p_timeout || (n == NEEDMORET && p_ttimeout)) && (c = inchar(typestr + len, 2, 0)) == 0)
X {
X if (p_smd)
X {
X delmode();
X mode_deleted = TRUE;
X }
X if (Curscol) /* move cursor one left if possible */
X --Curscol;
X else if (p_wrap && Curpos.col != 0 && Cursrow)
X {
X --Cursrow;
X Curscol = Columns - 1;
X }
X setcursor();
X flushbuf();
X }
X len += c;
X
X if (len >= typemaplen + MAXMAPLEN) /* buffer full, don't map */
X {
X timedout = TRUE;
X continue;
X }
X c = inchar(typestr + len, typemaplen + MAXMAPLEN - len, !advance ? 0 : ((len == 0 || !(p_timeout || (p_ttimeout && n == NEEDMORET))) ? -1 : (int)p_tm));
X if (c <= NUL) /* no character available */
X {
X if (!advance)
X break;
X if (len) /* timed out */
X {
X timedout = TRUE;
X continue;
X }
X }
X else
X {
X if (mode_deleted) /* character entered after ESC */
X {
X showmode();
X mode_deleted = FALSE;
X }
X }
X } /* for (;;) */
X } /* if (!character from stuffbuf) */
X
X /* if advance is FALSE don't loop on NULs */
X } while (c < 0 || (advance && c == NUL));
X
X /* delete "INSERT" message if we return an ESC */
X if (c == ESC && p_smd && !mode_deleted && (State & INSERT))
X delmode();
X
X return (u_char) c;
X}
X
X u_char
Xvgetc()
X{
X return (vgetorpeek(TRUE));
X}
X
X u_char
Xvpeekc()
X{
X return (vgetorpeek(FALSE));
X}
X
X/*
X * map[!] : show all key mappings
X * map[!] {lhs} : show key mapping for {lhs}
X * map[!] {lhs} {rhs} : set key mapping for {lhs} to {rhs}
X * noremap[!] {lhs} {rhs} : same, but no remapping for {rhs}
X * unmap[!] {lhs} : remove key mapping for {lhs}
X * abbr : show all abbreviations
X * abbr {lhs} : show abbreviations for {lhs}
X * abbr {lhs} {rhs} : set abbreviation for {lhs} to {rhs}
X * noreabbr {lhs} {rhs} : same, but no remapping for {rhs}
X * unabbr {lhs} : remove abbreviation for {lhs}
X *
X * maptype == 1 for unmap command, 2 for noremap command.
X *
X * keys is pointer to any arguments.
X *
X * for :map mode is NORMAL
X * for :map! mode is INSERT + CMDLINE
X * for :cmap mode is CMDLINE
X * for :imap mode is INSERT
X * for :abbr mode is INSERT + CMDLINE + ABBREV
X * for :iabbr mode is INSERT + ABBREV
X * for :cabbr mode is CMDLINE + ABBREV
X *
X * Return 0 for success
X * 1 for invalid arguments
X * 2 for no match
X * 3 for ambiguety
X * 4 for out of mem
X */
X int
Xdomap(maptype, keys, mode)
X int maptype;
X char *keys;
X int mode;
X{
X struct mapblock *mp, *mprev;
X char *arg;
X char *p;
X int n = 0; /* init for GCC */
X int len = 0; /* init for GCC */
X char *newstr;
X int hasarg;
X int haskey;
X int did_it = FALSE;
X int abbrev = 0;
X int round;
X
X if (mode & ABBREV) /* not a mapping but an abbreviation */
X {
X abbrev = ABBREV;
X mode &= ~ABBREV;
X }
X/*
X * find end of keys and remove CTRL-Vs in it
X */
X p = keys;
X while (*p && *p != ' ' && *p != '\t')
X {
X if (*p == Ctrl('V') && p[1] != NUL)
X strcpy(p, p + 1); /* remove CTRL-V */
X ++p;
X }
X if (*p != NUL)
X *p++ = NUL;
X skipspace(&p);
X arg = p;
X hasarg = (*arg != NUL);
X haskey = (*keys != NUL);
X
X /* check for :unmap with not one argument */
X if (maptype == 1 && (!haskey || hasarg))
X return 1;
X
X/*
X * remove CTRL-Vs from argument
X */
X while (*p)
X {
X if (*p == Ctrl('V') && p[1] != NUL)
X strcpy(p, p + 1); /* remove CTRL-V */
X ++p;
X }
X
X/*
X * check arguments and translate function keys
X */
X if (haskey)
X {
X if (*keys == '#' && isdigit(*(keys + 1))) /* function key */
X {
X if (*++keys == '0')
X *(u_char *)keys = K_F10;
X else
X *keys += K_F1 - '1';
X }
X len = strlen(keys);
X if (len > MAXMAPLEN) /* maximum lenght of MAXMAPLEN chars */
X return 2;
X }
X
X if (haskey && hasarg && abbrev) /* will add an abbreviation */
X no_abbr = FALSE;
X
X#ifdef AMIGA
X if (!haskey || (maptype != 1 && !hasarg))
X settmode(0); /* set cooked mode so output can be halted */
X#endif
X/*
X * Find an entry in the maplist that matches.
X * For :unmap we may loop two times: once to try to unmap an entry with a
X * matching 'from' part, a second time, if the first fails, to unmap an
X * entry with a matching 'to' part. This was done to allow ":ab foo bar" to be
X * unmapped by typing ":unab foo", where "foo" will be replaced by "bar" because
X * of the abbreviation.
X */
X for (round = 0; (round == 0 || maptype == 1) && round <= 1 && !did_it; ++round)
X {
X for (mp = maplist.m_next, mprev = &maplist; mp; mprev = mp, mp = mp->m_next)
X {
X /* skip entries with wrong mode */
X if (!(mp->m_mode & mode) || (mp->m_mode & ABBREV) != abbrev)
X continue;
X if (!haskey) /* show all entries */
X {
X showmap(mp);
X did_it = TRUE;
X }
X else /* do we have a match? */
X {
X if (round) /* second round: try 'to' string for unmap */
X {
X n = strlen(mp->m_str);
X p = mp->m_str;
X }
X else
X {
X n = mp->m_keylen;
X p = mp->m_keys;
X }
X if (!strncmp(p, keys, (size_t)(n < len ? n : len)))
X {
X if (maptype == 1) /* delete entry */
X {
X if (n != len) /* not a full match */
X continue;
X /*
X * We reset the indicated mode bits. If nothing is left the
X * entry is deleted below.
X */
X mp->m_mode &= (~mode | ABBREV);
X did_it = TRUE; /* remember that we did something */
X }
X else if (!hasarg) /* show matching entry */
X {
X showmap(mp);
X did_it = TRUE;
X }
X else if (n != len) /* new entry is ambigious */
X {
X return 3;
X }
X else
X {
X mp->m_mode &= (~mode | ABBREV); /* remove mode bits */
X if (!(mp->m_mode & ~ABBREV) && !did_it) /* reuse existing entry */
X {
X newstr = strsave(arg);
X if (newstr == NULL)
X return 4; /* no mem */
X free(mp->m_str);
X mp->m_str = newstr;
X mp->m_noremap = maptype;
X mp->m_mode = mode + abbrev;
X did_it = TRUE;
X }
X }
X if (!(mp->m_mode & ~ABBREV)) /* entry can be deleted */
X {
X free(mp->m_keys);
X free(mp->m_str);
X mprev->m_next = mp->m_next;
X free(mp);
X mp = mprev; /* continue with next entry */
X }
X }
X }
X }
X }
X
X if (maptype == 1) /* delete entry */
X {
X if (did_it)
X return 0; /* removed OK */
X else
X return 2; /* no match */
X }
X
X if (!haskey || !hasarg) /* print entries */
X {
X#ifdef AMIGA
X settmode(1);
X#endif
X if (did_it)
X wait_return(TRUE);
X else if (abbrev)
X msg("No abbreviation found");
X else
X msg("No mapping found");
X return 0; /* listing finished */
X }
X
X if (did_it) /* have added the new entry already */
X return 0;
X/*
X * get here when we have to add a new entry
X */
X /* allocate a new entry for the maplist */
X mp = (struct mapblock *)alloc((unsigned)sizeof(struct mapblock));
X if (mp == NULL)
X return 4; /* no mem */
X mp->m_keys = strsave(keys);
X mp->m_str = strsave(arg);
X if (mp->m_keys == NULL || mp->m_str == NULL)
X {
X free(mp->m_keys);
X free(mp->m_str);
X free(mp);
X return 4; /* no mem */
X }
X mp->m_keylen = strlen(mp->m_keys);
X mp->m_noremap = maptype;
X mp->m_mode = mode + abbrev;
X
X /* add the new entry in front of the maplist */
X mp->m_next = maplist.m_next;
X maplist.m_next = mp;
X
X return 0; /* added OK */
X}
X
X static void
Xshowmap(mp)
X struct mapblock *mp;
X{
X int len;
X
X if ((mp->m_mode & (INSERT + CMDLINE)) == INSERT + CMDLINE)
X outstr("! ");
X else if (mp->m_mode & INSERT)
X outstr("i ");
X else if (mp->m_mode & CMDLINE)
X outstr("c ");
X len = outtrans(mp->m_keys, -1); /* get length of what we have written */
X do
X {
X outchar(' '); /* padd with blanks */
X ++len;
X } while (len < 12);
X if (mp->m_noremap)
X outchar('*');
X else
X outchar(' ');
X outtrans(mp->m_str, -1);
X outchar('\n');
X flushbuf();
X}
X
X/*
X * Check for an abbreviation.
X * Cursor is at ptr[col]. When inserting, mincol is where insert started.
X * "c" is the character typed before check_abbr was called.
X */
X int
Xcheck_abbr(c, ptr, col, mincol)
X int c;
X char *ptr;
X int col;
X int mincol;
X{
X int len;
X int j;
X char tb[3];
X struct mapblock *mp;
X
X for (len = col; len > 0 && isidchar(ptr[len - 1]); --len)
X ;
X if (len < mincol)
X len = mincol;
X if (len < col) /* there is a word in front of the cursor */
X {
X ptr += len;
X len = col - len;
X for (mp = maplist.m_next; mp; mp = mp->m_next)
X {
X /* find entries with right mode and keys */
X if ((mp->m_mode & ABBREV) == ABBREV &&
X (mp->m_mode & State) &&
X mp->m_keylen == len &&
X !strncmp(mp->m_keys, ptr, (size_t)len))
X break;
X }
X if (mp) /* found a match */
X {
X j = 0;
X if (c < 0x100 && (c < ' ' || c > '~'))
X tb[j++] = Ctrl('V'); /* special char needs CTRL-V */
X tb[j++] = c;
X tb[j] = NUL;
X ins_typestr(tb, TRUE); /* insert the last typed char */
X ins_typestr(mp->m_str, mp->m_noremap); /* insert the to string */
X while (len--)
X ins_typestr("\b", TRUE); /* delete the from string */
X return TRUE;
X }
X }
X return FALSE;
X}
X
X/*
X * Write map commands for the current mappings to an .exrc file.
X * Return 1 on error.
X */
X int
Xmakemap(fd)
X FILE *fd;
X{
X struct mapblock *mp;
X char c1;
X char *p;
X
X for (mp = maplist.m_next; mp; mp = mp->m_next)
X {
X c1 = NUL;
X p = "map";
X switch (mp->m_mode)
X {
X case NORMAL:
X break;
X case CMDLINE + INSERT:
X p = "map!";
X break;
X case CMDLINE:
X c1 = 'c';
X break;
X case INSERT:
X c1 = 'i';
X break;
X case INSERT + CMDLINE + ABBREV:
X p = "abbr";
X break;
X case CMDLINE + ABBREV:
X c1 = 'c';
X p = "abbr";
X break;
X case INSERT + ABBREV:
X c1 = 'i';
X p = "abbr";
X break;
X default:
X emsg("makemap: Illegal mode");
X return 1;
X }
X if (c1 && putc(c1, fd) < 0)
X return 1;
X if (mp->m_noremap && fprintf(fd, "nore") < 0)
X return 1;
X if (fprintf(fd, p) < 0)
X return 1;
X
X if ( putc(' ', fd) < 0 || putescstr(fd, mp->m_keys, FALSE) < 0 ||
X putc(' ', fd) < 0 || putescstr(fd, mp->m_str, FALSE) < 0 ||
X#ifdef MSDOS
X putc('\r', fd) < 0 ||
X#endif
X putc('\n', fd) < 0)
X return 1;
X }
X return 0;
X}
X
X int
Xputescstr(fd, str, set)
X FILE *fd;
X char *str;
X int set; /* TRUE for makeset, FALSE for makemap */
X{
X for ( ; *str; ++str)
X {
X /*
X * some characters have to be escaped with CTRL-V to
X * prevent them from misinterpreted in DoOneCmd().
X * A space has to be escaped with a backslash to
X * prevent it to be misinterpreted in doset().
X */
X if (*str < ' ' || *str > '~' || (*str == ' ' && !set))
X {
X if (putc(Ctrl('V'), fd) < 0)
X return -1;
X }
X else if ((set && *str == ' ') || *str == '|')
X {
X if (putc('\\', fd) < 0)
X return -1;
X }
X if (putc(*str, fd) < 0)
X return -1;
X }
X return 0;
X}
END_OF_FILE
if test 29561 -ne `wc -c <'vim/src/buffers.c'`; then
echo shar: \"'vim/src/buffers.c'\" unpacked with wrong size!
fi
chmod +x 'vim/src/buffers.c'
# end of 'vim/src/buffers.c'
fi
echo shar: End of archive 14 \(of 25\).
cp /dev/null ark14isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 25 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
===============================================================================
Bram Moolenaar | DISCLAIMER: This note does not
Oce Nederland B.V., Research & Development | necessarily represent the position
p.o. box 101, 5900 MA Venlo | of Oce-Nederland B.V. Therefore
The Netherlands phone +31 77 594077 | no liability or responsibility for
UUCP: mool@oce.nl fax +31 77 595473 | whatever will be accepted.
exit 0 # Just in case...