home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume44
/
vim
/
part17
< prev
next >
Wrap
Internet Message Format
|
1994-08-18
|
71KB
From: mool@oce.nl (Bram Moolenaar)
Newsgroups: comp.sources.misc
Subject: v44i036: vim - Vi IMproved editor, v3.0, Part17/26
Date: 18 Aug 1994 14:03:00 -0500
Organization: Sterling Software
Sender: kent@sparky.sterling.com
Approved: kent@sparky.sterling.com
Message-ID: <330b94$e60@sparky.sterling.com>
X-Md4-Signature: 53fa669384f024ab9c97b93695b199ea
Submitted-by: mool@oce.nl (Bram Moolenaar)
Posting-number: Volume 44, Issue 36
Archive-name: vim/part17
Environment: UNIX, AMIGA, MS-DOS, Windows NT
Supersedes: vim: Volume 41, Issue 50-75
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# Contents: vim/macros/center.UU vim/src/amiga.c vim/src/edit.c
# Wrapped by kent@sparky on Mon Aug 15 21:44:09 1994
PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 17 (of 26)."'
if test -f 'vim/macros/center.UU' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'vim/macros/center.UU'\"
else
echo shar: Extracting \"'vim/macros/center.UU'\" \(270 characters\)
sed "s/^X//" >'vim/macros/center.UU' <<'END_OF_FILE'
Xbegin 644 vim/macros/center
XM(E1H:7,@;6%C<F\@8V5N=&5R<R!A(&QI;F4@:6X@86X@.# @8VAA<F%C=&5R
XM('-P86-E+@HB0V%R969U;#H@;&EN97,@;&]N9V5R('1H86X@.# @8VAA<F%C
XM=&5R<R!W:6QL(&)E('1R=6YC871E9 IM87 @.V-E(#IS+UY;( E=*B\O#21M
XB83@Q82 ;.#$6?$1@86QL9# Z<R\@("\@+V<-)' -:R1X"EY;
X
Xend
END_OF_FILE
if test 270 -ne `wc -c <'vim/macros/center.UU'`; then
echo shar: \"'vim/macros/center.UU'\" unpacked with wrong size!
else
echo shar: Uudecoding \"'vim/macros/center'\" \(169 characters\)
cat vim/macros/center.UU | uudecode
if test 169 -ne `wc -c <'vim/macros/center'`; then
echo shar: \"'vim/macros/center'\" uudecoded with wrong size!
else
rm vim/macros/center.UU
fi
fi
# end of 'vim/macros/center.UU'
fi
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'\" \(32474 characters\)
sed "s/^X//" >'vim/src/amiga.c' <<'END_OF_FILE'
X/* vi:ts=4:sw=4
X *
X * VIM - Vi IMproved by Bram Moolenaar
X *
X * Read the file "credits.txt" for a list of people who contributed.
X * Read the file "uganda.txt" for copying and usage conditions.
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#include <exec/memory.h>
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_u *buf, long len));
Xstatic struct FileInfoBlock *get_fib __ARGS((char_u *));
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_u *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_u *p;
X int len;
X{
X Write(raw_out, (char *)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 * Return number of characters read.
X */
X int
XGetChars(buf, maxlen, time)
X char_u *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, (char *)buf, (long)maxlen);
X if (len > 0)
X return len;
X }
X}
X
X/*
X * return non-zero if a character is available
X */
X int
Xmch_char_avail()
X{
X return (WaitForChar(raw_in, 100L) != 0);
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 long
Xmch_avail_mem(special)
X int special;
X{
X return (long)AvailMem(special ? (long)MEMF_CHIP : (long)MEMF_ANY);
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 (void)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 (void)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_u buf1[20];
X char_u buf2[BUF2SIZE];
X static char_u *(constrings[3]) = {(char_u *)"con:0/0/662/210/",
X (char_u *)"con:0/0/640/200/",
X (char_u *)"con:0/0/320/200/"};
X static char_u winerr[] = "VIM: Can't open window!\n";
X struct WBArg *argp;
X int ac;
X char *av;
X char_u *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 = (char_u *)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, (char *)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((char *)buf1, "t:nc%ld", (char *)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", (char *)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 (void)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((char *)buf2, argp->wa_Name);
X#endif
X av = (char *)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((char *)buf2, "newcli <nil: >nil: %s from %s", (char *)device, (char *)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, (char *)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_u *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((char *)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_u *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 * set the title of our window
X * icon name is not set
X */
X void
Xmch_settitle(title, icon)
X char_u *title;
X char_u *icon;
X{
X if (wb_window != NULL && title != NULL)
X SetWindowTitles(wb_window, (UBYTE *)title, (UBYTE *)-1L);
X}
X
X/*
X * Restore the window/icon title.
X * which is one of:
X * 1 Just restore title
X * 2 Just restore icon (which we don't have)
X * 3 Restore title and icon (which we don't have)
X */
X void
Xmch_restore_title(which)
X int which;
X{
X mch_settitle((which & 1) ? oldwindowtitle : NULL, NULL);
X}
X
X/*
X * Get name of current directory into buffer 'buf' of length 'len' bytes.
X * Return OK for success, FAIL for failure.
X */
X int
Xvim_dirname(buf, len)
X char_u *buf;
X int len;
X{
X return FullName((char_u *)"", buf, len);
X}
X
X/*
X * get absolute filename into buffer 'buf' of length 'len' bytes
X *
X * return FAIL for failure, OK otherwise
X */
X int
XFullName(fname, buf, len)
X char_u *fname, *buf;
X int len;
X{
X BPTR l;
X int retval = FAIL;
X int i;
X
X *buf = NUL;
X if (fname == NULL) /* always fail */
X return FAIL;
X
X if ((l = Lock((UBYTE *)fname, (long)ACCESS_READ)) != (BPTR)0)/* lock the file */
X {
X retval = lock2name(l, buf, (long)len);
X UnLock(l);
X }
X else if (!isFullName(fname)) /* not a full path yet */
X {
X /*
X * if cannot lock the file, try to lock the current directory and then
X * concatenate the file name
X */
X if ((l = Lock((UBYTE *)"", (long)ACCESS_READ)) != (BPTR)NULL) /* lock current dir */
X {
X retval = lock2name(l, buf, (long)len);
X UnLock(l);
X if (retval == OK)
X {
X i = STRLEN(buf);
X if (i < len - 1 && (i == 0 || buf[i - 1] != ':'))
X buf[i++] = '/';
X STRNCPY(buf + i, fname, (size_t)(len - i)); /* concatenate the fname */
X }
X }
X }
X if (retval == FAIL || *buf == 0 || *buf == ':')
X STRCPY(buf, fname); /* something failed; use the filename */
X return retval;
X}
X
X/*
X * return TRUE is fname is an absolute path name
X */
X int
XisFullName(fname)
X char_u *fname;
X{
X return (STRCHR(fname, ':') != NULL);
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 * return FAIL for failure, OK otherwise
X */
X static int
Xlock2name(lock, buf, len)
X BPTR lock;
X char_u *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) ? OK : FAIL);
X#ifndef NO_ARP
X else /* use arp function */
X return ((int)PathName(lock, (char *)buf, (long)(len/32)) ? OK : FAIL);
X#endif
X}
X
X/*
X * get file permissions for 'name'
X */
X long
Xgetperm(name)
X char_u *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 *
X * return FAIL for failure, OK otherwise
X */
X int
Xsetperm(name, perm)
X char_u *name;
X long perm;
X{
X perm &= ~FIBF_ARCHIVE; /* reset archived bit */
X return (SetProtection((UBYTE *)name, (long)perm) ? OK : FAIL);
X}
X
X/*
X * return FALSE if "name" is not a directory
X * return TRUE if "name" is a directory.
X * return -1 for error.
X */
X int
Xisdir(name)
X char_u *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) ? TRUE : FALSE);
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 mch_restore_title(3); /* restore window title */
X
X ml_close_all(); /* remove all memfiles */
X
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 * set screen mode, always fails.
X */
X int
Xmch_screenmode(arg)
X char_u *arg;
X{
X EMSG("Screen mode setting not supported");
X return FAIL;
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 FAIL for failure, OK otherwise
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 FAIL;
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 FAIL;
X }
X if (oldwindowtitle == NULL)
X oldwindowtitle = (char_u *)wb_window->Title;
X if (id->id_InUse == (BPTR)NULL)
X {
X fprintf(stderr, "mch_get_winsize: not a console??\n");
X return FAIL;
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 FAIL;
X }
X check_winsize();
X
X return OK;
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_u *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 FAIL for failure, OK otherwise
X */
X int
Xcall_shell(cmd, filter, cooked)
X char_u *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_u *shellcmd = NULL;
X char_u *shellarg;
X#endif
X int retval = OK;
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 FAIL;
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((char *)cmd, SYS_UserShell, TRUE, TAG_DONE);
X# ifndef NO_ARP
X else
X x = Execute((char *)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 outstr((char_u *)"Cannot execute ");
X if (cmd == NULL)
X {
X outstr((char_u *)"shell ");
X outstr(p_sh);
X }
X else
X outstr(cmd);
X outchar('\n');
X retval = FAIL;
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#ifdef WEBB_COMPLETE
X if (!expand_interactively)
X#endif
X {
X outchar('\n');
X outnum(x);
X outstr((char_u *)" returned\n");
X }
X retval = FAIL;
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((char *)shellcmd, (char *)shellcmd, (char *)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((char *)shellcmd, (char *)shellcmd, (char *)shellarg, (char *)cmd, NULL);
X else
X x = fexecl((char *)shellcmd, (char *)shellcmd, (char *)shellarg, "-c", (char *)cmd, NULL);
X# ifdef NO_ARP
X if (x < 0)
X# else
X if ((dos2 && x < 0) || (!dos2 && x))
X# endif
X {
X outstr((char_u *)"Cannot execute ");
X if (use_execute)
X {
X if (cmd == NULL)
X outstr(p_sh);
X else
X outstr(cmd);
X }
X else
X {
X outstr((char_u *)"shell ");
X outstr(shellcmd);
X }
X outchar('\n');
X retval = FAIL;
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#ifdef WEBB_COMPLETE
X if (!expand_interactively)
X#endif
X {
X outchar('\n');
X outnum((long)x);
X outstrn((char_u *)" returned\n");
X }
X retval = FAIL;
X }
X }
X free(shellcmd);
X#endif /* !LATTICE */
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 OK for success, FAIL 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_u *, 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_u name[1]; /* really longer */
X} *namelist = NULL;
X
X/*
X * insert one file into the list of file names
X * return FAIL for failure
X * return OK for success
X */
X static int
Xinsfile(name, isdir)
X char_u *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 FAIL;
X STRCPY(&(new->name[0]), name);
X if (isdir)
X STRCAT(&(new->name[0]), "/");
X new->next = namelist;
X namelist = new;
X return OK;
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
X int
XExpandWildCards(num_pat, pat, num_file, file, files_only, list_notfound)
X int num_pat;
X char_u **pat;
X int *num_file;
X char_u ***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_u *errmsg = NULL;
X char_u *starbuf, *sp, *dp;
X int foundone;
X
X *num_file = 0;
X *file = (char_u **)"";
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((char *)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((char_u *)Anchor->ap_Buf, Anchor->ap_Info.fib_DirEntryType >= 0) == FAIL)
X {
XOUT_OF_MEMORY:
X errmsg = (char_u *)"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 = (char_u *)"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) == FAIL)
X goto OUT_OF_MEMORY;
X }
X else if (Result != ERROR_OBJECT_NOT_FOUND && Result != ERROR_NO_MORE_ENTRIES)
X {
X errmsg = (char_u *)"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 FreeAnchorChain(Anchor);
X#endif
X domatchend = FALSE;
X }
X
X p = namelist;
X if (p)
X {
X *file = (char_u **) malloc(sizeof(char_u *) * (*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_u *) 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_u *), 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 FreeAnchorChain(Anchor);
X#endif
X }
X if (Anchor)
X free(Anchor);
X freefiles();
X if (errmsg)
X {
X emsg(errmsg);
X *num_file = 0;
X return FAIL;
X }
X return OK;
X}
X
X void
XFreeWild(num, file)
X int num;
X char_u **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_u *p;
X{
X for ( ; *p; ++p)
X if (strchr("*?[(~#", *p) != NULL)
X return TRUE;
X return FALSE;
X}
X
X/*
X * With 2.0 support for reading local environment variables
X * Careful: uses IObuff!
X */
X
X char_u *
Xvimgetenv(var)
X char_u *var;
X{
X int len;
X
X#ifndef NO_ARP
X if (!dos2)
X return (char_u *)getenv((char *)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 32474 -ne `wc -c <'vim/src/amiga.c'`; then
echo shar: \"'vim/src/amiga.c'\" unpacked with wrong size!
fi
# end of 'vim/src/amiga.c'
fi
if test -f 'vim/src/edit.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'vim/src/edit.c'\"
else
echo shar: Extracting \"'vim/src/edit.c'\" \(31932 characters\)
sed "s/^X//" >'vim/src/edit.c' <<'END_OF_FILE'
X/* vi:ts=4:sw=4
X *
X * VIM - Vi IMproved by Bram Moolenaar
X *
X * Read the file "credits.txt" for a list of people who contributed.
X * Read the file "uganda.txt" for copying and usage conditions.
X */
X
X/*
X * edit.c: functions for insert mode
X */
X
X#include "vim.h"
X#include "globals.h"
X#include "proto.h"
X#include "param.h"
X#include "ops.h" /* for operator */
X
Xextern char_u *get_inserted();
Xstatic void start_arrow __ARGS((void));
Xstatic void stop_arrow __ARGS((void));
Xstatic void stop_insert __ARGS((void));
Xstatic int echeck_abbr __ARGS((int));
X
Xint arrow_used; /* Normally FALSE, set to TRUE after hitting
X * cursor key in insert mode. Used by vgetorpeek()
X * to decide when to call u_sync() */
Xint restart_edit = 0; /* call edit when next command finished */
Xstatic char_u *last_insert = NULL;
X /* the text of the previous insert */
Xstatic int last_insert_skip;
X /* number of chars in front of the previous insert */
Xstatic int new_insert_skip;
X /* number of chars in front of the current insert */
X
X void
Xedit(count)
X long count;
X{
X int c;
X int cc;
X char_u *ptr;
X char_u *saved_line = NULL; /* saved line for replace mode */
X linenr_t saved_lnum = 0; /* lnum of saved line */
X int saved_char = NUL; /* char replaced by NL */
X linenr_t lnum;
X int temp = 0;
X int mode;
X int nextc = 0;
X int lastc = 0;
X colnr_t mincol;
X static linenr_t o_lnum = 0;
X static int o_eol = FALSE;
X#ifdef WEBB_KEYWORD_COMPL
X FPOS complete_pos;
X FPOS first_match;
X char_u *complete_pat = NULL;
X char_u *completion_str = NULL;
X char_u *last_completion_str = NULL;
X char_u *tmp_ptr;
X int previous_c = 0;
X int complete_col = 0; /* init for gcc */
X int complete_direction;
X int complete_any_word = 0; /* true -> ^N/^P hit with no prefix
X * init for gcc */
X int done;
X int found_error = FALSE;
X char_u backup_char = 0; /* init for gcc */
X
X c = NUL;
X#endif /* WEBB_KEYWORD_COMPL */
X
X if (restart_edit)
X {
X arrow_used = TRUE;
X restart_edit = 0;
X /*
X * If the cursor was after the end-of-line before the CTRL-O
X * and it is now at the end-of-line, put it after the end-of-line
X * (this is not correct in very rare cases).
X */
X if (o_eol && curwin->w_cursor.lnum == o_lnum &&
X *((ptr = ml_get(curwin->w_cursor.lnum)) + curwin->w_cursor.col) != NUL &&
X *(ptr + curwin->w_cursor.col + 1) == NUL)
X ++curwin->w_cursor.col;
X }
X else
X {
X arrow_used = FALSE;
X o_eol = FALSE;
X }
X
X#ifdef DIGRAPHS
X dodigraph(-1); /* clear digraphs */
X#endif
X
X/*
X * Get the current length of the redo buffer, those characters have to be
X * skipped if we want to get to the inserted characters.
X */
X
X ptr = get_inserted();
X new_insert_skip = STRLEN(ptr);
X free(ptr);
X
X old_indent = 0;
X
X for (;;)
X {
X if (arrow_used) /* don't repeat insert when arrow key used */
X count = 0;
X
X if (!arrow_used)
X curwin->w_set_curswant = TRUE; /* set curwin->w_curswant for next K_DARROW or K_UARROW */
X cursupdate(); /* Figure out where the cursor is based on curwin->w_cursor. */
X showruler(0);
X setcursor();
X#ifdef WEBB_KEYWORD_COMPL
X previous_c = c;
X#endif /* WEBB_KEYWORD_COMPL */
X if (nextc) /* character remaining from CTRL-V */
X {
X c = nextc;
X nextc = 0;
X }
X else
X {
X c = vgetc();
X if (c == Ctrl('C'))
X got_int = FALSE;
X }
X#ifdef WEBB_KEYWORD_COMPL
X if (previous_c == Ctrl('N') || previous_c == Ctrl('P'))
X {
X /* Show error message from attempted keyword completion (probably
X * 'Pattern not found') until another key is hit, then go back to
X * showing what mode we are in.
X */
X showmode();
X if (c != Ctrl('N') && c != Ctrl('P'))
X {
X /* Get here when we have finished typing a sequence of ^N and
X * ^P. Free up memory that was used, and make sure we can redo
X * the insert.
X */
X if (completion_str != NULL)
X AppendToRedobuff(completion_str);
X free(complete_pat);
X free(completion_str);
X free(last_completion_str);
X complete_pat = completion_str = last_completion_str = NULL;
X }
X }
X#endif /* WEBB_KEYWORD_COMPL */
X if (c != Ctrl('D')) /* remember to detect ^^D and 0^D */
X lastc = c;
X
X/*
X * In replace mode a backspace puts the original text back.
X * We save the current line to be able to do that.
X * If characters are appended to the line, they will be deleted.
X * If we start a new line (with CR) the saved line will be empty, thus
X * the characters will be deleted.
X * If we backspace over the new line, that line will be saved.
X */
X if (State == REPLACE && saved_lnum != curwin->w_cursor.lnum)
X {
X free(saved_line);
X saved_line = strsave(ml_get(curwin->w_cursor.lnum));
X saved_lnum = curwin->w_cursor.lnum;
X }
X
X#ifdef DIGRAPHS
X c = dodigraph(c);
X#endif /* DIGRAPHS */
X
X if (c == Ctrl('V'))
X {
X screen_start();
X screen_outchar('^', curwin->w_row, curwin->w_col);
X AppendToRedobuff((char_u *)"\026"); /* CTRL-V */
X cursupdate();
X setcursor();
X
X c = get_literal(&nextc);
X
X insertchar(c);
X continue;
X }
X switch (c) /* handle character in insert mode */
X {
X case Ctrl('O'): /* execute one command */
X if (echeck_abbr(Ctrl('O') + 0x100))
X break;
X count = 0;
X if (State == INSERT)
X restart_edit = 'I';
X else
X restart_edit = 'R';
X o_lnum = curwin->w_cursor.lnum;
X o_eol = (gchar_cursor() == NUL);
X goto doESCkey;
X
X case ESC: /* an escape ends input mode */
X if (echeck_abbr(ESC + 0x100))
X break;
X /*FALLTHROUGH*/
X
X case Ctrl('C'):
XdoESCkey:
X if (!arrow_used)
X {
X AppendToRedobuff(ESC_STR);
X
X if (--count > 0) /* repeat what was typed */
X {
X (void)start_redo_ins();
X continue;
X }
X stop_insert();
X }
X if (!restart_edit)
X curwin->w_set_curswant = TRUE;
X
X /*
X * The cursor should end up on the last inserted character.
X */
X if (curwin->w_cursor.col != 0 && (!restart_edit || gchar_cursor() == NUL) && !p_ri)
X dec_cursor();
X if (extraspace) /* did reverse replace in column 0 */
X {
X (void)delchar(FALSE);
X updateline();
X extraspace = FALSE;
X }
X State = NORMAL;
X /* inchar() may have deleted the "INSERT" message */
X if (Recording)
X showmode();
X else if (p_smd)
X MSG("");
X free(saved_line);
X old_indent = 0;
X return;
X
X /*
X * Insert the previously inserted text.
X * Last_insert actually is a copy of the redo buffer, so we
X * first have to remove the command.
X * For ^@ the trailing ESC will end the insert.
X */
X case K_ZERO:
X case Ctrl('A'):
X stuff_inserted(NUL, 1L, (c == Ctrl('A')));
X break;
X
X /*
X * insert the contents of a register
X */
X case Ctrl('R'):
X if (insertbuf(vgetc()) == FAIL)
X beep();
X break;
X
X case Ctrl('B'): /* toggle reverse insert mode */
X p_ri = !p_ri;
X showmode();
X break;
X
X /*
X * If the cursor is on an indent, ^T/^D insert/delete one
X * shiftwidth. Otherwise ^T/^D behave like a TAB/backspace.
X * This isn't completely compatible with
X * vi, but the difference isn't very noticeable and now you can
X * mix ^D/backspace and ^T/TAB without thinking about which one
X * must be used.
X */
X case Ctrl('T'): /* make indent one shiftwidth greater */
X case Ctrl('D'): /* make indent one shiftwidth smaller */
X stop_arrow();
X AppendCharToRedobuff(c);
X if ((lastc == '0' || lastc == '^') && curwin->w_cursor.col)
X {
X --curwin->w_cursor.col;
X (void)delchar(FALSE); /* delete the '^' or '0' */
X if (lastc == '^')
X old_indent = get_indent(); /* remember current indent */
X
X /* determine offset from first non-blank */
X temp = curwin->w_cursor.col;
X beginline(TRUE);
X temp -= curwin->w_cursor.col;
X set_indent(0, TRUE); /* remove all indent */
X }
X else
X {
Xins_indent:
X /* determine offset from first non-blank */
X temp = curwin->w_cursor.col;
X beginline(TRUE);
X temp -= curwin->w_cursor.col;
X
X shift_line(c == Ctrl('D'), TRUE, 1);
X
X /* try to put cursor on same character */
X temp += curwin->w_cursor.col;
X }
X if (temp <= 0)
X curwin->w_cursor.col = 0;
X else
X curwin->w_cursor.col = temp;
X did_ai = FALSE;
X did_si = FALSE;
X can_si = FALSE;
X goto redraw;
X
X case BS:
X case DEL:
Xnextbs:
X mode = 0;
Xdodel:
X /* can't delete anything in an empty file */
X /* can't backup past first character in buffer */
X /* can't backup past starting point unless 'backspace' > 1 */
X /* can backup to a previous line if 'backspace' == 0 */
X if (bufempty() || (!p_ri &&
X ((curwin->w_cursor.lnum == 1 && curwin->w_cursor.col <= 0) ||
X (p_bs < 2 && (arrow_used ||
X (curwin->w_cursor.lnum == Insstart.lnum &&
X curwin->w_cursor.col <= Insstart.col) ||
X (curwin->w_cursor.col <= 0 && p_bs == 0))))))
X {
X beep();
X goto redraw;
X }
X
X stop_arrow();
X if (p_ri)
X inc_cursor();
X if (curwin->w_cursor.col <= 0) /* delete newline! */
X {
X lnum = Insstart.lnum;
X if (curwin->w_cursor.lnum == Insstart.lnum || p_ri)
X {
X if (!u_save((linenr_t)(curwin->w_cursor.lnum - 2), (linenr_t)(curwin->w_cursor.lnum + 1)))
X goto redraw;
X --Insstart.lnum;
X Insstart.col = 0;
X /* this is in xvim, why?
X if (curbuf->b_p_ai)
X for (ptr = ml_get(Insstart.lnum);
X iswhite(*ptr++); Insstart.col++)
X ; */
X }
X /* in replace mode, in the line we started replacing, we
X only move the cursor */
X if (State != REPLACE || curwin->w_cursor.lnum > lnum)
X {
X temp = gchar_cursor(); /* remember current char */
X --curwin->w_cursor.lnum;
X (void)dojoin(FALSE, TRUE);
X if (temp == NUL && gchar_cursor() != NUL)
X ++curwin->w_cursor.col;
X if (saved_char) /* restore what NL replaced */
X {
X State = NORMAL; /* no replace for this char */
X inschar(saved_char); /* but no showmatch */
X State = REPLACE;
X saved_char = NUL;
X if (!p_ri)
X dec_cursor();
X }
X else if (p_ri) /* in reverse mode */
X saved_lnum = 0; /* save this line again */
X }
X else
X dec_cursor();
X did_ai = FALSE;
X }
X else
X {
X if (p_ri && State != REPLACE)
X dec_cursor();
X mincol = 0;
X if (mode == 3 && !p_ri && curbuf->b_p_ai) /* keep indent */
X {
X temp = curwin->w_cursor.col;
X beginline(TRUE);
X if (curwin->w_cursor.col < temp)
X mincol = curwin->w_cursor.col;
X curwin->w_cursor.col = temp;
X }
X
X /* delete upto starting point, start of line or previous word */
X do
X {
X if (!p_ri)
X dec_cursor();
X
X /* start of word? */
X if (mode == 1 && !isspace(gchar_cursor()))
X {
X mode = 2;
X temp = isidchar(gchar_cursor());
X }
X /* end of word? */
X else if (mode == 2 && (isspace(cc = gchar_cursor()) || isidchar(cc) != temp))
X {
X if (!p_ri)
X inc_cursor();
X else if (State == REPLACE)
X dec_cursor();
X break;
X }
X if (State == REPLACE)
X {
X if (saved_line)
X {
X if (extraspace)
X {
X if ((int)STRLEN(ml_get(curwin->w_cursor.lnum)) - 1 > (int)STRLEN(saved_line))
X (void)delchar(FALSE);
X else
X {
X dec_cursor();
X (void)delchar(FALSE);
X extraspace = FALSE;
X pchar_cursor(*saved_line);
X }
X }
X else if (curwin->w_cursor.col < STRLEN(saved_line))
X pchar_cursor(saved_line[curwin->w_cursor.col]);
X else if (!p_ri)
X (void)delchar(FALSE);
X }
X }
X else /* State != REPLACE */
X {
X (void)delchar(FALSE);
X if (p_ri && gchar_cursor() == NUL)
X break;
X }
X if (mode == 0) /* just a single backspace */
X break;
X if (p_ri && State == REPLACE && inc_cursor())
X break;
X } while (p_ri || (curwin->w_cursor.col > mincol && (curwin->w_cursor.lnum != Insstart.lnum ||
X curwin->w_cursor.col != Insstart.col)));
X if (extraspace)
X dec_cursor();
X }
X did_si = FALSE;
X can_si = FALSE;
X if (curwin->w_cursor.col <= 1)
X did_ai = FALSE;
X /*
X * It's a little strange to put backspaces into the redo
X * buffer, but it makes auto-indent a lot easier to deal
X * with.
X */
X AppendCharToRedobuff(c);
X if (vpeekc() == BS)
X {
X c = vgetc();
X goto nextbs; /* speedup multiple backspaces */
X }
Xredraw:
X cursupdate();
X updateline();
X break;
X
X case Ctrl('W'): /* delete word before cursor */
X mode = 1;
X goto dodel;
X
X case Ctrl('U'): /* delete inserted text in current line */
X mode = 3;
X goto dodel;
X
X case K_LARROW:
X if (oneleft() == OK)
X {
X start_arrow();
X }
X /* if 'whichwrap' set for cursor in insert mode may go
X * to previous line */
X else if ((p_ww & 16) && curwin->w_cursor.lnum > 1)
X {
X start_arrow();
X --(curwin->w_cursor.lnum);
X coladvance(MAXCOL);
X curwin->w_curswant = MAXCOL; /* so we stay at the end */
X }
X else
X beep();
X break;
X
X case K_SLARROW:
X if (curwin->w_cursor.lnum > 1 || curwin->w_cursor.col > 0)
X {
X bck_word(1L, 0);
X start_arrow();
X }
X else
X beep();
X break;
X
X case K_RARROW:
X if (gchar_cursor() != NUL)
X {
X curwin->w_set_curswant = TRUE;
X start_arrow();
X ++curwin->w_cursor.col;
X }
X /* if 'whichwrap' set for cursor in insert mode may go
X * to next line */
X else if ((p_ww & 16) && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
X {
X curwin->w_set_curswant = TRUE;
X start_arrow();
X ++curwin->w_cursor.lnum;
X curwin->w_cursor.col = 0;
X }
X else
X beep();
X break;
X
X case K_SRARROW:
X if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count || gchar_cursor() != NUL)
X {
X fwd_word(1L, 0, 0);
X start_arrow();
X }
X else
X beep();
X break;
X
X case K_UARROW:
X if (oneup(1L))
X start_arrow();
X else
X beep();
X break;
X
X case K_SUARROW:
X if (onepage(BACKWARD, 1L))
X start_arrow();
X else
X beep();
X break;
X
X case K_DARROW:
X if (onedown(1L))
X start_arrow();
X else
X beep();
X break;
X
X case K_SDARROW:
X if (onepage(FORWARD, 1L))
X start_arrow();
X else
X beep();
X break;
X
X case TAB:
X if (echeck_abbr(TAB + 0x100))
X break;
X if ((!curbuf->b_p_et && !(p_sta && inindent())) || (p_ri && State == REPLACE))
X goto normalchar;
X
X AppendToRedobuff((char_u *)"\t");
X
X if (!curbuf->b_p_et) /* insert smart tab */
X goto ins_indent;
X
X /* p_te set: expand a tab into spaces */
X stop_arrow();
X did_ai = FALSE;
X did_si = FALSE;
X can_si = FALSE;
X if (p_sta && inindent())
X temp = (int)curbuf->b_p_sw;
X else
X temp = (int)curbuf->b_p_ts;
X temp -= curwin->w_cursor.col % temp;
X inschar(' '); /* delete one char in replace mode */
X while (--temp)
X insstr((char_u *)" "); /* insstr does not delete chars */
X goto redraw;
X
X case CR:
X case NL:
X if (echeck_abbr(c + 0x100))
X break;
X stop_arrow();
X if (State == REPLACE)
X {
X saved_char = gchar_cursor();
X (void)delchar(FALSE);
X }
X /*
X * When 'autoindent' set delete white space after the cursor.
X * Vi does this, although it probably does it implicitly due
X * to the way it does auto-indent -- webb.
X */
X if (curbuf->b_p_ai || curbuf->b_p_si)
X while ((c = gchar_cursor()) == ' ' || c == TAB)
X (void)delchar(FALSE);
X
X AppendToRedobuff(NL_STR);
X if (!Opencmd(FORWARD, TRUE, State == INSERT))
X goto doESCkey; /* out of memory */
X if (p_ri)
X {
X dec_cursor();
X if (State == REPLACE && curwin->w_cursor.col > 0)
X dec_cursor();
X }
X break;
X
X#ifdef DIGRAPHS
X case Ctrl('K'):
X screen_start();
X screen_outchar('?', curwin->w_row, curwin->w_col);
X setcursor();
X c = vgetc();
X if (c != ESC)
X {
X if (charsize(c) == 1)
X {
X screen_start();
X screen_outchar(c, curwin->w_row, curwin->w_col);
X }
X setcursor();
X cc = vgetc();
X if (cc != ESC)
X {
X AppendToRedobuff((char_u *)"\026"); /* CTRL-V */
X c = getdigraph(c, cc, TRUE);
X goto normalchar;
X }
X }
X updateline();
X goto doESCkey;
X#endif /* DIGRAPHS */
X
X#ifdef WEBB_KEYWORD_COMPL
X case Ctrl('P'): /* Do previous pattern completion */
X case Ctrl('N'): /* Do next pattern completion */
X if (c == Ctrl('P'))
X complete_direction = BACKWARD;
X else
X complete_direction = FORWARD;
X if (previous_c != Ctrl('N') && previous_c != Ctrl('P'))
X {
X /* First time we hit ^N or ^P (in a row, I mean) */
X complete_pos = curwin->w_cursor;
X ptr = ml_get(complete_pos.lnum);
X complete_col = complete_pos.col;
X temp = complete_col - 1;
X if (temp < 0 || !isidchar(ptr[temp]))
X {
X complete_pat = strsave((char_u *)"\\<[a-zA-Z_]");
X complete_any_word = TRUE;
X }
X else
X {
X while (temp >= 0 && isidchar(ptr[temp]))
X temp--;
X temp++;
X complete_pat = alloc(curwin->w_cursor.col - temp + 3);
X if (complete_pat != NULL)
X sprintf((char *)complete_pat, "\\<%.*s",
X (int)(curwin->w_cursor.col - temp), ptr + temp);
X complete_any_word = FALSE;
X }
X last_completion_str = strsave((char_u *)" ");
X }
X else
X {
X /* This is not the first ^N or ^P we have hit in a row */
X while (curwin->w_cursor.col != complete_col)
X {
X curwin->w_cursor.col--;
X delchar(FALSE);
X }
X if (completion_str != NULL)
X {
X free(last_completion_str);
X last_completion_str = strsave(completion_str);
X }
X }
X if (complete_pat == NULL || last_completion_str == NULL)
X {
X found_error = TRUE;
X break;
X }
X if (!complete_any_word)
X {
X ptr = ml_get(curwin->w_cursor.lnum);
X backup_char = ptr[complete_col - 1];
X ptr[complete_col - 1] = ' ';
X }
X done = FALSE;
X found_error = FALSE;
X first_match.lnum = 0;
X keep_old_search_pattern = TRUE;
X while (!done)
X {
X if (complete_direction == BACKWARD)
X {
X ptr = ml_get(complete_pos.lnum);
X while (isidchar(ptr[complete_pos.col]))
X complete_pos.col--;
X complete_pos.col++;
X }
X if (!searchit(&complete_pos, complete_direction,
X complete_pat, 1L, TRUE, TRUE))
X {
X found_error = TRUE;
X break;
X }
X if (complete_any_word)
X ptr = ml_get_pos(&complete_pos);
X else
X ptr = ml_get_pos(&complete_pos) + 1;
X tmp_ptr = ptr;
X temp = 1;
X while (*tmp_ptr != NUL && isidchar(*tmp_ptr++))
X temp++;
X free (completion_str);
X tmp_ptr = completion_str = alloc(temp);
X if (completion_str == NULL)
X {
X found_error = TRUE;
X break;
X }
X while (*ptr != NUL && isidchar(*ptr))
X *(tmp_ptr++) = *(ptr++);
X *tmp_ptr = NUL;
X if (completion_str[0] != NUL &&
X STRCMP(completion_str, last_completion_str) != 0)
X done = TRUE;
X else if (first_match.lnum == 0)
X {
X first_match.lnum = complete_pos.lnum;
X first_match.col = complete_pos.col;
X }
X else if (complete_pos.lnum == first_match.lnum
X && complete_pos.col == first_match.col)
X {
X if (completion_str[0] == NUL)
X EMSG("Exact match only");
X else
X EMSG("No other matches");
X done = TRUE;
X }
X }
X if (!found_error)
X insstr(completion_str);
X if (!complete_any_word)
X {
X ptr = ml_get(curwin->w_cursor.lnum);
X ptr[complete_col - 1] = backup_char;
X }
X keep_old_search_pattern = FALSE;
X updateline();
X break;
X#endif /* WEBB_KEYWORD_COMPL */
X
X case Ctrl('Y'): /* copy from previous line */
X lnum = curwin->w_cursor.lnum - 1;
X goto copychar;
X
X case Ctrl('E'): /* copy from next line */
X lnum = curwin->w_cursor.lnum + 1;
Xcopychar:
X if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
X {
X beep();
X break;
X }
X
X /* try to advance to the cursor column */
X temp = 0;
X ptr = ml_get(lnum);
X while (temp < curwin->w_virtcol && *ptr)
X temp += chartabsize(*ptr++, (long)temp);
X
X if (temp > curwin->w_virtcol)
X --ptr;
X if ((c = *ptr) == NUL)
X {
X beep();
X break;
X }
X
X /*FALLTHROUGH*/
X default:
Xnormalchar:
X /*
X * do some very smart indenting when entering '{' or '}' or '#'
X */
X if (curwin->w_cursor.col > 0 && ((can_si && c == '}') || (did_si && c == '{')))
X {
X FPOS *pos, old_pos;
X int i;
X
X /* for '}' set indent equal to matching '{' */
X if (c == '}' && (pos = showmatch('{')) != NULL)
X {
X old_pos = curwin->w_cursor;
X curwin->w_cursor = *pos;
X i = get_indent();
X curwin->w_cursor = old_pos;
X set_indent(i, TRUE);
X }
X else
X shift_line(TRUE, TRUE, 1);
X }
X /* set indent of '#' always to 0 */
X if (curwin->w_cursor.col > 0 && can_si && c == '#')
X {
X /* remember current indent for next line */
X old_indent = get_indent();
X set_indent(0, TRUE);
X }
X
X if (isidchar(c) || !echeck_abbr(c))
X insertchar(c);
X break;
X }
X }
X}
X
X/*
X * Next character is interpreted literally.
X * A one, two or three digit decimal number is interpreted as its byte value.
X * If one or two digits are entered, *nextc is set to the next character.
X */
X int
Xget_literal(nextc)
X int *nextc;
X{
X int cc;
X int nc;
X int oldstate;
X int i;
X
X oldstate = State;
X State = NOMAPPING; /* next characters not mapped */
X
X if (got_int)
X {
X *nextc = NUL;
X return Ctrl('C');
X }
X cc = 0;
X for (i = 0; i < 3; ++i)
X {
X nc = vgetc();
X if (!isdigit(nc))
X break;
X cc = cc * 10 + nc - '0';
X nc = 0;
X }
X if (i == 0) /* no number entered */
X {
X cc = nc;
X nc = 0;
X if (cc == K_ZERO) /* NUL is stored as NL */
X cc = '\n';
X }
X else if (cc == 0) /* NUL is stored as NL */
X cc = '\n';
X
X State = oldstate;
X *nextc = nc;
X got_int = FALSE; /* CTRL-C typed after CTRL-V is not an interrupt */
X return cc;
X}
X
X/*
X * Special characters in this context are those that need processing other
X * than the simple insertion that can be performed here. This includes ESC
X * which terminates the insert, and CR/NL which need special processing to
X * open up a new line. This routine tries to optimize insertions performed by
X * the "redo", "undo" or "put" commands, so it needs to know when it should
X * stop and defer processing to the "normal" mechanism.
X */
X#define ISSPECIAL(c) ((c) < ' ' || (c) >= DEL)
X
X void
Xinsertchar(c)
X unsigned c;
X{
X int haveto_redraw = FALSE;
X int textwidth;
X
X stop_arrow();
X
X /*
X * find out textwidth to be used:
X * if 'textwidth' option is set, use it
X * else if 'wrapmargin' option is set, use Columns - 'wrapmargin'
X * if invalid value, us 0.
X */
X textwidth = curbuf->b_p_tw;
X if (textwidth == 0 && curbuf->b_p_wm)
X textwidth = Columns - curbuf->b_p_wm;
X if (textwidth < 0)
X textwidth = 0;
X
X /*
X * If the cursor is past 'textwidth' and we are inserting a non-space,
X * try to break the line in two or more pieces. If c == NUL then we have
X * been called to do formatting only. If textwidth == 0 it does nothing.
X * Don't do this if an existing character is being replaced.
X */
X if (c == NUL || !(isspace(c) || (State == REPLACE && *ml_get_cursor() != NUL)))
X {
X while (textwidth && curwin->w_virtcol >= textwidth)
X {
X int startcol; /* Cursor column at entry */
X int wantcol; /* column at textwidth border */
X int foundcol; /* column for start of word */
X
X if ((startcol = curwin->w_cursor.col) == 0)
X break;
X coladvance(textwidth); /* find column of textwidth border */
X wantcol = curwin->w_cursor.col;
X
X curwin->w_cursor.col = startcol - 1;
X foundcol = 0;
X while (curwin->w_cursor.col > 0) /* find position to break at */
X {
X if (isspace(gchar_cursor()))
X {
X while (curwin->w_cursor.col > 0 && isspace(gchar_cursor()))
X --curwin->w_cursor.col;
X if (curwin->w_cursor.col == 0) /* only spaces in front of text */
X break;
X foundcol = curwin->w_cursor.col + 1;
X if (curwin->w_cursor.col < wantcol)
X break;
X }
X --curwin->w_cursor.col;
X }
X
X if (foundcol == 0) /* no spaces, cannot break line */
X {
X curwin->w_cursor.col = startcol;
X break;
X }
X curwin->w_cursor.col = foundcol; /* put cursor after pos. to break line */
X startcol -= foundcol;
X Opencmd(FORWARD, FALSE, FALSE);
X while (isspace(gchar_cursor()) && startcol) /* delete blanks */
X {
X (void)delchar(FALSE);
X --startcol; /* adjust cursor pos. */
X }
X curwin->w_cursor.col += startcol;
X curs_columns(FALSE); /* update curwin->w_virtcol */
X haveto_redraw = TRUE;
X }
X if (c == NUL) /* formatting only */
X return;
X if (haveto_redraw)
X {
X /*
X * If the cursor ended up just below the screen we scroll up here
X * to avoid a redraw of the whole screen in the most common cases.
X */
X if (curwin->w_cursor.lnum == curwin->w_botline && !curwin->w_empty_rows)
X win_del_lines(curwin, 0, 1, TRUE, TRUE);
X updateScreen(CURSUPD);
X }
X }
X
X did_ai = FALSE;
X did_si = FALSE;
X can_si = FALSE;
X
X /*
X * If there's any pending input, grab up to MAX_COLUMNS at once.
X * This speeds up normal text input considerably.
X */
X if (vpeekc() != NUL && State != REPLACE && !p_ri)
X {
X char_u p[MAX_COLUMNS + 1];
X int i;
X
X p[0] = c;
X i = 1;
X while ((c = vpeekc()) != NUL && !ISSPECIAL(c) && i < MAX_COLUMNS &&
X (textwidth == 0 || (curwin->w_virtcol += charsize(p[i - 1])) < textwidth) &&
X !(!no_abbr && !isidchar(c) && isidchar(p[i - 1])))
X p[i++] = vgetc();
X#ifdef DIGRAPHS
X dodigraph(-1); /* clear digraphs */
X dodigraph(p[i-1]); /* may be the start of a digraph */
X#endif
X p[i] = '\0';
X insstr(p);
X AppendToRedobuff(p);
X }
X else
X {
X inschar(c);
X AppendCharToRedobuff(c);
X }
X
X /*
X * TODO: If the cursor has shifted past the end of the screen, should
X * adjust the screen display. Avoids extra redraw.
X */
X
X updateline();
X}
X
X/*
X * start_arrow() is called when an arrow key is used in insert mode.
X * It resembles hitting the <ESC> key.
X */
X static void
Xstart_arrow()
X{
X if (!arrow_used) /* something has been inserted */
X {
X AppendToRedobuff(ESC_STR);
X arrow_used = TRUE; /* this means we stopped the current insert */
X stop_insert();
X }
X}
X
X/*
X * stop_arrow() is called before a change is made in insert mode.
X * If an arrow key has been used, start a new insertion.
X */
X static void
Xstop_arrow()
X{
X if (arrow_used)
X {
X u_save_cursor(); /* errors are ignored! */
X Insstart = curwin->w_cursor; /* new insertion starts here */
X ResetRedobuff();
X AppendToRedobuff((char_u *)"1i"); /* pretend we start an insertion */
X arrow_used = FALSE;
X }
X}
X
X/*
X * do a few things to stop inserting
X */
X static void
Xstop_insert()
X{
X stop_redo_ins();
X
X /*
X * save the inserted text for later redo with ^@
X */
X free(last_insert);
X last_insert = get_inserted();
X last_insert_skip = new_insert_skip;
X
X /*
X * If we just did an auto-indent, truncate the line, and put
X * the cursor back.
X */
X if (did_ai && !arrow_used)
X {
X ml_replace(curwin->w_cursor.lnum, (char_u *)"", TRUE);
X curwin->w_cursor.col = 0;
X if (curwin->w_p_list) /* the deletion is only seen in list mode */
X updateline();
X }
X did_ai = FALSE;
X did_si = FALSE;
X can_si = FALSE;
X}
X
X/*
X * move cursor to start of line
X * if flag == TRUE move to first non-white
X */
X void
Xbeginline(flag)
X int flag;
X{
X curwin->w_cursor.col = 0;
X if (flag)
X {
X register char_u *ptr;
X
X for (ptr = ml_get(curwin->w_cursor.lnum); iswhite(*ptr); ++ptr)
X ++curwin->w_cursor.col;
X }
X curwin->w_set_curswant = TRUE;
X}
X
X/*
X * oneright oneleft onedown oneup
X *
X * Move one char {right,left,down,up}.
X * Return OK when sucessful, FAIL when we hit a line of file boundary.
X */
X
X int
Xoneright()
X{
X char_u *ptr;
X
X ptr = ml_get_cursor();
X if (*ptr++ == NUL || *ptr == NUL)
X return FAIL;
X curwin->w_set_curswant = TRUE;
X ++curwin->w_cursor.col;
X return OK;
X}
X
X int
Xoneleft()
X{
X if (curwin->w_cursor.col == 0)
X return FAIL;
X curwin->w_set_curswant = TRUE;
X --curwin->w_cursor.col;
X return OK;
X}
X
X int
Xoneup(n)
X long n;
X{
X if (n != 0 && curwin->w_cursor.lnum == 1)
X return FAIL;
X if (n >= curwin->w_cursor.lnum)
X curwin->w_cursor.lnum = 1;
X else
X curwin->w_cursor.lnum -= n;
X
X if (operator == NOP)
X cursupdate(); /* make sure curwin->w_topline is valid */
X
X /* try to advance to the column we want to be at */
X coladvance(curwin->w_curswant);
X return OK;
X}
X
X int
Xonedown(n)
X long n;
X{
X if (n != 0 && curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
X return FAIL;
X curwin->w_cursor.lnum += n;
X if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
X curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
X
X if (operator == NOP)
X cursupdate(); /* make sure curwin->w_topline is valid */
X
X /* try to advance to the column we want to be at */
X coladvance(curwin->w_curswant);
X return OK;
X}
X
X/*
X * move screen 'count' pages up or down and update screen
X *
X * return FAIL for failure, OK otherwise
X */
X int
Xonepage(dir, count)
X int dir;
X long count;
X{
X linenr_t lp;
X long n;
X
X if (curbuf->b_ml.ml_line_count == 1) /* nothing to do */
X return FAIL;
X for ( ; count > 0; --count)
X {
X if (dir == FORWARD ? (curwin->w_topline >= curbuf->b_ml.ml_line_count - 1) : (curwin->w_topline == 1))
X {
X beep();
X return FAIL;
X }
X if (dir == FORWARD)
X {
X if (curwin->w_botline > curbuf->b_ml.ml_line_count) /* at end of file */
X curwin->w_topline = curbuf->b_ml.ml_line_count;
X else if (plines(curwin->w_botline) >= curwin->w_height - 2 || /* next line is big */
X curwin->w_botline - curwin->w_topline <= 3) /* just three lines on screen */
X curwin->w_topline = curwin->w_botline;
X else
X curwin->w_topline = curwin->w_botline - 2;
X curwin->w_cursor.lnum = curwin->w_topline;
X if (count != 1)
X comp_Botline(curwin);
X }
X else /* dir == BACKWARDS */
X {
X lp = curwin->w_topline;
X /*
X * If the first two lines on the screen are not too big, we keep
X * them on the screen.
X */
X if ((n = plines(lp)) > curwin->w_height / 2)
X --lp;
X else if (lp < curbuf->b_ml.ml_line_count && n + plines(lp + 1) < curwin->w_height / 2)
X ++lp;
X curwin->w_cursor.lnum = lp;
X n = 0;
X while (n <= curwin->w_height && lp >= 1)
X {
X n += plines(lp);
X --lp;
X }
X if (n <= curwin->w_height) /* at begin of file */
X curwin->w_topline = 1;
X else if (lp >= curwin->w_topline - 2) /* happens with very long lines */
X {
X --curwin->w_topline;
X comp_Botline(curwin);
X curwin->w_cursor.lnum = curwin->w_botline - 1;
X }
X else
X curwin->w_topline = lp + 2;
X }
X }
X beginline(TRUE);
X updateScreen(VALID);
X return OK;
X}
X
X void
Xstuff_inserted(c, count, no_esc)
X int c;
X long count;
X int no_esc;
X{
X char_u *esc_ptr = NULL;
X char_u *ptr;
X
X if (last_insert == NULL)
X {
X EMSG("No inserted text yet");
X return;
X }
X if (c)
X stuffcharReadbuff(c);
X if (no_esc && (esc_ptr = (char_u *)STRRCHR(last_insert, 27)) != NULL)
X *esc_ptr = NUL; /* remove the ESC */
X
X /* skip the command */
X ptr = last_insert + last_insert_skip;
X
X do
X stuffReadbuff(ptr);
X while (--count > 0);
X
X if (no_esc && esc_ptr)
X *esc_ptr = 27; /* put the ESC back */
X}
X
X char_u *
Xget_last_insert()
X{
X if (last_insert == NULL)
X return NULL;
X return last_insert + last_insert_skip;
X}
X
X/*
X * Check the word in front of the cursor for an abbreviation.
X * Called when the non-id character "c" has been entered.
X * When an abbreviation is recognized it is removed from the text and
X * the replacement string is inserted in typestr, followed by "c".
X */
X static int
Xecheck_abbr(c)
X int c;
X{
X if (p_paste || no_abbr) /* no abbreviations or in paste mode */
X return FALSE;
X
X return check_abbr(c, ml_get(curwin->w_cursor.lnum), curwin->w_cursor.col,
X curwin->w_cursor.lnum == Insstart.lnum ? Insstart.col : 0);
X}
END_OF_FILE
if test 31932 -ne `wc -c <'vim/src/edit.c'`; then
echo shar: \"'vim/src/edit.c'\" unpacked with wrong size!
fi
# end of 'vim/src/edit.c'
fi
echo shar: End of archive 17 \(of 26\).
cp /dev/null ark17isdone
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 26 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 26 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...