js/src/editline/editline.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/editline/editline.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1341 @@
     1.4 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +/*
    1.10 + * Copyright 1992,1993 Simmule Turner and Rich Salz.  All rights reserved.
    1.11 + *
    1.12 + * This software is not subject to any license of the American Telephone
    1.13 + * and Telegraph Company or of the Regents of the University of California.
    1.14 + *
    1.15 + * Permission is granted to anyone to use this software for any purpose on
    1.16 + * any computer system, and to alter it and redistribute it freely, subject
    1.17 + * to the following restrictions:
    1.18 + * 1. The authors are not responsible for the consequences of use of this
    1.19 + *    software, no matter how awful, even if they arise from flaws in it.
    1.20 + * 2. The origin of this software must not be misrepresented, either by
    1.21 + *    explicit claim or by omission.  Since few users ever read sources,
    1.22 + *    credits must appear in the documentation.
    1.23 + * 3. Altered versions must be plainly marked as such, and must not be
    1.24 + *    misrepresented as being the original software.  Since few users
    1.25 + *    ever read sources, credits must appear in the documentation.
    1.26 + * 4. This notice may not be removed or altered.
    1.27 + */
    1.28 +
    1.29 +
    1.30 +/*
    1.31 +**  Main editing routines for editline library.
    1.32 +*/
    1.33 +#include "editline.h"
    1.34 +#include <signal.h>
    1.35 +#include <ctype.h>
    1.36 +#include <unistd.h>
    1.37 +
    1.38 +/*
    1.39 +**  Manifest constants.
    1.40 +*/
    1.41 +#define SCREEN_WIDTH	80
    1.42 +#define SCREEN_ROWS	24
    1.43 +#define NO_ARG		(-1)
    1.44 +#define DEL		127
    1.45 +#define CTL(x)		((x) & 0x1F)
    1.46 +#define ISCTL(x)	((x) && (x) < ' ')
    1.47 +#define UNCTL(x)	((x) + 64)
    1.48 +#define META(x)		((x) | 0x80)
    1.49 +#define ISMETA(x)	((x) & 0x80)
    1.50 +#define UNMETA(x)	((x) & 0x7F)
    1.51 +#if	!defined(HIST_SIZE)
    1.52 +#define HIST_SIZE	20
    1.53 +#endif	/* !defined(HIST_SIZE) */
    1.54 +
    1.55 +/*
    1.56 +**  Command status codes.
    1.57 +*/
    1.58 +typedef enum _STATUS {
    1.59 +    CSdone, CSeof, CSmove, CSdispatch, CSstay, CSsignal
    1.60 +} STATUS;
    1.61 +
    1.62 +/*
    1.63 +**  The type of case-changing to perform.
    1.64 +*/
    1.65 +typedef enum _CASE {
    1.66 +    TOupper, TOlower
    1.67 +} CASE;
    1.68 +
    1.69 +/*
    1.70 +**  Key to command mapping.
    1.71 +*/
    1.72 +typedef struct _KEYMAP {
    1.73 +    CHAR	Key;
    1.74 +    STATUS	(*Function)();
    1.75 +} KEYMAP;
    1.76 +
    1.77 +/*
    1.78 +**  Command history structure.
    1.79 +*/
    1.80 +typedef struct _HISTORY {
    1.81 +    int		Size;
    1.82 +    int		Pos;
    1.83 +    CHAR	*Lines[HIST_SIZE];
    1.84 +} HISTORY;
    1.85 +
    1.86 +/*
    1.87 +**  Globals.
    1.88 +*/
    1.89 +unsigned	rl_eof;
    1.90 +unsigned	rl_erase;
    1.91 +unsigned	rl_intr;
    1.92 +unsigned	rl_kill;
    1.93 +unsigned	rl_quit;
    1.94 +
    1.95 +STATIC CHAR		NIL[] = "";
    1.96 +STATIC CONST CHAR	*Input = NIL;
    1.97 +STATIC CHAR		*Line;
    1.98 +STATIC CONST char	*Prompt;
    1.99 +STATIC CHAR		*Yanked;
   1.100 +STATIC char		*Screen;
   1.101 +STATIC CONST char	NEWLINE[]= CRLF;
   1.102 +STATIC HISTORY		H;
   1.103 +STATIC int		Repeat;
   1.104 +STATIC int		End;
   1.105 +STATIC int		Mark;
   1.106 +STATIC int		OldPoint;
   1.107 +STATIC int		Point;
   1.108 +STATIC int		PushBack;
   1.109 +STATIC int		Pushed;
   1.110 +STATIC int		Signal;
   1.111 +FORWARD CONST KEYMAP	Map[32];
   1.112 +FORWARD CONST KEYMAP	MetaMap[16];
   1.113 +STATIC SIZE_T		Length;
   1.114 +STATIC SIZE_T		ScreenCount;
   1.115 +STATIC SIZE_T		ScreenSize;
   1.116 +STATIC char		*backspace;
   1.117 +STATIC int		TTYwidth;
   1.118 +STATIC int		TTYrows;
   1.119 +
   1.120 +/* Display print 8-bit chars as `M-x' or as the actual 8-bit char? */
   1.121 +int		rl_meta_chars = 0;
   1.122 +
   1.123 +/*
   1.124 +**  Declarations.
   1.125 +*/
   1.126 +STATIC CHAR	*editinput();
   1.127 +#if	defined(USE_TERMCAP)
   1.128 +#include <stdlib.h>
   1.129 +#include <curses.h>
   1.130 +#include <term.h>
   1.131 +#endif	/* defined(USE_TERMCAP) */
   1.132 +
   1.133 +/*
   1.134 +**  TTY input/output functions.
   1.135 +*/
   1.136 +
   1.137 +STATIC void
   1.138 +TTYflush()
   1.139 +{
   1.140 +    if (ScreenCount) {
   1.141 +        /* Dummy assignment avoids GCC warning on
   1.142 +         * "attribute warn_unused_result" */
   1.143 +	ssize_t dummy = write(1, Screen, ScreenCount);
   1.144 +        (void)dummy;
   1.145 +	ScreenCount = 0;
   1.146 +    }
   1.147 +}
   1.148 +
   1.149 +STATIC void
   1.150 +TTYput(c)
   1.151 +    CHAR	c;
   1.152 +{
   1.153 +    Screen[ScreenCount] = c;
   1.154 +    if (++ScreenCount >= ScreenSize - 1) {
   1.155 +	ScreenSize += SCREEN_INC;
   1.156 +	RENEW(Screen, char, ScreenSize);
   1.157 +    }
   1.158 +}
   1.159 +
   1.160 +STATIC void
   1.161 +TTYputs(p)
   1.162 +    CONST CHAR	*p;
   1.163 +{
   1.164 +    while (*p)
   1.165 +	TTYput(*p++);
   1.166 +}
   1.167 +
   1.168 +STATIC void
   1.169 +TTYshow(c)
   1.170 +    CHAR	c;
   1.171 +{
   1.172 +    if (c == DEL) {
   1.173 +	TTYput('^');
   1.174 +	TTYput('?');
   1.175 +    }
   1.176 +    else if (ISCTL(c)) {
   1.177 +	TTYput('^');
   1.178 +	TTYput(UNCTL(c));
   1.179 +    }
   1.180 +    else if (rl_meta_chars && ISMETA(c)) {
   1.181 +	TTYput('M');
   1.182 +	TTYput('-');
   1.183 +	TTYput(UNMETA(c));
   1.184 +    }
   1.185 +    else
   1.186 +	TTYput(c);
   1.187 +}
   1.188 +
   1.189 +STATIC void
   1.190 +TTYstring(p)
   1.191 +    CHAR	*p;
   1.192 +{
   1.193 +    while (*p)
   1.194 +	TTYshow(*p++);
   1.195 +}
   1.196 +
   1.197 +STATIC unsigned int
   1.198 +TTYget()
   1.199 +{
   1.200 +    CHAR	c;
   1.201 +
   1.202 +    TTYflush();
   1.203 +    if (Pushed) {
   1.204 +	Pushed = 0;
   1.205 +	return PushBack;
   1.206 +    }
   1.207 +    if (*Input)
   1.208 +	return *Input++;
   1.209 +    return read(0, &c, (SIZE_T)1) == 1 ? c : EOF;
   1.210 +}
   1.211 +
   1.212 +#define TTYback()	(backspace ? TTYputs((CHAR *)backspace) : TTYput('\b'))
   1.213 +
   1.214 +STATIC void
   1.215 +TTYbackn(n)
   1.216 +    int		n;
   1.217 +{
   1.218 +    while (--n >= 0)
   1.219 +	TTYback();
   1.220 +}
   1.221 +
   1.222 +STATIC void
   1.223 +TTYinfo()
   1.224 +{
   1.225 +    static int		init;
   1.226 +#if	defined(USE_TERMCAP)
   1.227 +    char		*term;
   1.228 +    char		buff[2048];
   1.229 +    char		*bp, *p;
   1.230 +#endif	/* defined(USE_TERMCAP) */
   1.231 +#if	defined(TIOCGWINSZ)
   1.232 +    struct winsize	W;
   1.233 +#endif	/* defined(TIOCGWINSZ) */
   1.234 +
   1.235 +    if (init) {
   1.236 +#if	defined(TIOCGWINSZ)
   1.237 +	/* Perhaps we got resized. */
   1.238 +	if (ioctl(0, TIOCGWINSZ, &W) >= 0
   1.239 +	 && W.ws_col > 0 && W.ws_row > 0) {
   1.240 +	    TTYwidth = (int)W.ws_col;
   1.241 +	    TTYrows = (int)W.ws_row;
   1.242 +	}
   1.243 +#endif	/* defined(TIOCGWINSZ) */
   1.244 +	return;
   1.245 +    }
   1.246 +    init++;
   1.247 +
   1.248 +    TTYwidth = TTYrows = 0;
   1.249 +#if	defined(USE_TERMCAP)
   1.250 +    bp = &buff[0];
   1.251 +    if ((term = getenv("TERM")) == NULL)
   1.252 +	term = "dumb";
   1.253 +    if (tgetent(buff, term) < 0) {
   1.254 +       TTYwidth = SCREEN_WIDTH;
   1.255 +       TTYrows = SCREEN_ROWS;
   1.256 +       return;
   1.257 +    }
   1.258 +    p = tgetstr("le", &bp);
   1.259 +    backspace = p ? strdup(p) : NULL;
   1.260 +    TTYwidth = tgetnum("co");
   1.261 +    TTYrows = tgetnum("li");
   1.262 +#endif	/* defined(USE_TERMCAP) */
   1.263 +
   1.264 +#if	defined(TIOCGWINSZ)
   1.265 +    if (ioctl(0, TIOCGWINSZ, &W) >= 0) {
   1.266 +	TTYwidth = (int)W.ws_col;
   1.267 +	TTYrows = (int)W.ws_row;
   1.268 +    }
   1.269 +#endif	/* defined(TIOCGWINSZ) */
   1.270 +
   1.271 +    if (TTYwidth <= 0 || TTYrows <= 0) {
   1.272 +	TTYwidth = SCREEN_WIDTH;
   1.273 +	TTYrows = SCREEN_ROWS;
   1.274 +    }
   1.275 +}
   1.276 +
   1.277 +
   1.278 +STATIC void
   1.279 +reposition()
   1.280 +{
   1.281 +    int		i;
   1.282 +    CHAR	*p;
   1.283 +
   1.284 +    TTYput('\r');
   1.285 +    TTYputs((CONST CHAR *)Prompt);
   1.286 +    for (i = Point, p = Line; --i >= 0; p++)
   1.287 +	TTYshow(*p);
   1.288 +}
   1.289 +
   1.290 +STATIC void
   1.291 +left(Change)
   1.292 +    STATUS	Change;
   1.293 +{
   1.294 +    TTYback();
   1.295 +    if (Point) {
   1.296 +	if (ISCTL(Line[Point - 1]))
   1.297 +	    TTYback();
   1.298 +        else if (rl_meta_chars && ISMETA(Line[Point - 1])) {
   1.299 +	    TTYback();
   1.300 +	    TTYback();
   1.301 +	}
   1.302 +    }
   1.303 +    if (Change == CSmove)
   1.304 +	Point--;
   1.305 +}
   1.306 +
   1.307 +STATIC void
   1.308 +right(Change)
   1.309 +    STATUS	Change;
   1.310 +{
   1.311 +    TTYshow(Line[Point]);
   1.312 +    if (Change == CSmove)
   1.313 +	Point++;
   1.314 +}
   1.315 +
   1.316 +STATIC STATUS
   1.317 +ring_bell()
   1.318 +{
   1.319 +    TTYput('\07');
   1.320 +    TTYflush();
   1.321 +    return CSstay;
   1.322 +}
   1.323 +
   1.324 +STATIC STATUS
   1.325 +do_macro(c)
   1.326 +    unsigned int	c;
   1.327 +{
   1.328 +    CHAR		name[4];
   1.329 +
   1.330 +    name[0] = '_';
   1.331 +    name[1] = c;
   1.332 +    name[2] = '_';
   1.333 +    name[3] = '\0';
   1.334 +
   1.335 +    if ((Input = (CHAR *)getenv((char *)name)) == NULL) {
   1.336 +	Input = NIL;
   1.337 +	return ring_bell();
   1.338 +    }
   1.339 +    return CSstay;
   1.340 +}
   1.341 +
   1.342 +STATIC STATUS
   1.343 +do_forward(move)
   1.344 +    STATUS	move;
   1.345 +{
   1.346 +    int		i;
   1.347 +    CHAR	*p;
   1.348 +
   1.349 +    i = 0;
   1.350 +    do {
   1.351 +	p = &Line[Point];
   1.352 +	for ( ; Point < End && (*p == ' ' || !isalnum(*p)); Point++, p++)
   1.353 +	    if (move == CSmove)
   1.354 +		right(CSstay);
   1.355 +
   1.356 +	for (; Point < End && isalnum(*p); Point++, p++)
   1.357 +	    if (move == CSmove)
   1.358 +		right(CSstay);
   1.359 +
   1.360 +	if (Point == End)
   1.361 +	    break;
   1.362 +    } while (++i < Repeat);
   1.363 +
   1.364 +    return CSstay;
   1.365 +}
   1.366 +
   1.367 +STATIC STATUS
   1.368 +do_case(type)
   1.369 +    CASE	type;
   1.370 +{
   1.371 +    int		i;
   1.372 +    int		end;
   1.373 +    int		count;
   1.374 +    CHAR	*p;
   1.375 +
   1.376 +    (void)do_forward(CSstay);
   1.377 +    if (OldPoint != Point) {
   1.378 +	if ((count = Point - OldPoint) < 0)
   1.379 +	    count = -count;
   1.380 +	Point = OldPoint;
   1.381 +	if ((end = Point + count) > End)
   1.382 +	    end = End;
   1.383 +	for (i = Point, p = &Line[i]; i < end; i++, p++) {
   1.384 +	    if (type == TOupper) {
   1.385 +		if (islower(*p))
   1.386 +		    *p = toupper(*p);
   1.387 +	    }
   1.388 +	    else if (isupper(*p))
   1.389 +		*p = tolower(*p);
   1.390 +	    right(CSmove);
   1.391 +	}
   1.392 +    }
   1.393 +    return CSstay;
   1.394 +}
   1.395 +
   1.396 +STATIC STATUS
   1.397 +case_down_word()
   1.398 +{
   1.399 +    return do_case(TOlower);
   1.400 +}
   1.401 +
   1.402 +STATIC STATUS
   1.403 +case_up_word()
   1.404 +{
   1.405 +    return do_case(TOupper);
   1.406 +}
   1.407 +
   1.408 +STATIC void
   1.409 +ceol()
   1.410 +{
   1.411 +    int		extras;
   1.412 +    int		i;
   1.413 +    CHAR	*p;
   1.414 +
   1.415 +    for (extras = 0, i = Point, p = &Line[i]; i <= End; i++, p++) {
   1.416 +	TTYput(' ');
   1.417 +	if (ISCTL(*p)) {
   1.418 +	    TTYput(' ');
   1.419 +	    extras++;
   1.420 +	}
   1.421 +	else if (rl_meta_chars && ISMETA(*p)) {
   1.422 +	    TTYput(' ');
   1.423 +	    TTYput(' ');
   1.424 +	    extras += 2;
   1.425 +	}
   1.426 +    }
   1.427 +
   1.428 +    for (i += extras; i > Point; i--)
   1.429 +	TTYback();
   1.430 +}
   1.431 +
   1.432 +STATIC void
   1.433 +clear_line()
   1.434 +{
   1.435 +    Point = -strlen(Prompt);
   1.436 +    TTYput('\r');
   1.437 +    ceol();
   1.438 +    Point = 0;
   1.439 +    End = 0;
   1.440 +    Line[0] = '\0';
   1.441 +}
   1.442 +
   1.443 +STATIC STATUS
   1.444 +insert_string(p)
   1.445 +    CHAR	*p;
   1.446 +{
   1.447 +    SIZE_T	len;
   1.448 +    int		i;
   1.449 +    CHAR	*new;
   1.450 +    CHAR	*q;
   1.451 +
   1.452 +    len = strlen((char *)p);
   1.453 +    if (End + len >= Length) {
   1.454 +	if ((new = NEW(CHAR, Length + len + MEM_INC)) == NULL)
   1.455 +	    return CSstay;
   1.456 +	if (Length) {
   1.457 +	    COPYFROMTO(new, Line, Length);
   1.458 +	    DISPOSE(Line);
   1.459 +	}
   1.460 +	Line = new;
   1.461 +	Length += len + MEM_INC;
   1.462 +    }
   1.463 +
   1.464 +    for (q = &Line[Point], i = End - Point; --i >= 0; )
   1.465 +	q[len + i] = q[i];
   1.466 +    COPYFROMTO(&Line[Point], p, len);
   1.467 +    End += len;
   1.468 +    Line[End] = '\0';
   1.469 +    TTYstring(&Line[Point]);
   1.470 +    Point += len;
   1.471 +
   1.472 +    return Point == End ? CSstay : CSmove;
   1.473 +}
   1.474 +
   1.475 +STATIC STATUS
   1.476 +redisplay()
   1.477 +{
   1.478 +    TTYputs((CONST CHAR *)NEWLINE);
   1.479 +    TTYputs((CONST CHAR *)Prompt);
   1.480 +    TTYstring(Line);
   1.481 +    return CSmove;
   1.482 +}
   1.483 +
   1.484 +STATIC STATUS
   1.485 +toggle_meta_mode()
   1.486 +{
   1.487 +    rl_meta_chars = ! rl_meta_chars;
   1.488 +    return redisplay();
   1.489 +}
   1.490 +
   1.491 +
   1.492 +STATIC CHAR *
   1.493 +next_hist()
   1.494 +{
   1.495 +    return H.Pos >= H.Size - 1 ? NULL : H.Lines[++H.Pos];
   1.496 +}
   1.497 +
   1.498 +STATIC CHAR *
   1.499 +prev_hist()
   1.500 +{
   1.501 +    return H.Pos == 0 ? NULL : H.Lines[--H.Pos];
   1.502 +}
   1.503 +
   1.504 +STATIC STATUS
   1.505 +do_insert_hist(p)
   1.506 +    CHAR	*p;
   1.507 +{
   1.508 +    if (p == NULL)
   1.509 +	return ring_bell();
   1.510 +    Point = 0;
   1.511 +    reposition();
   1.512 +    ceol();
   1.513 +    End = 0;
   1.514 +    return insert_string(p);
   1.515 +}
   1.516 +
   1.517 +STATIC STATUS
   1.518 +do_hist(move)
   1.519 +    CHAR	*(*move)();
   1.520 +{
   1.521 +    CHAR	*p;
   1.522 +    int		i;
   1.523 +
   1.524 +    i = 0;
   1.525 +    do {
   1.526 +	if ((p = (*move)()) == NULL)
   1.527 +	    return ring_bell();
   1.528 +    } while (++i < Repeat);
   1.529 +    return do_insert_hist(p);
   1.530 +}
   1.531 +
   1.532 +STATIC STATUS
   1.533 +h_next()
   1.534 +{
   1.535 +    return do_hist(next_hist);
   1.536 +}
   1.537 +
   1.538 +STATIC STATUS
   1.539 +h_prev()
   1.540 +{
   1.541 +    return do_hist(prev_hist);
   1.542 +}
   1.543 +
   1.544 +STATIC STATUS
   1.545 +h_first()
   1.546 +{
   1.547 +    return do_insert_hist(H.Lines[H.Pos = 0]);
   1.548 +}
   1.549 +
   1.550 +STATIC STATUS
   1.551 +h_last()
   1.552 +{
   1.553 +    return do_insert_hist(H.Lines[H.Pos = H.Size - 1]);
   1.554 +}
   1.555 +
   1.556 +/*
   1.557 +**  Return zero if pat appears as a substring in text.
   1.558 +*/
   1.559 +STATIC int
   1.560 +substrcmp(text, pat, len)
   1.561 +    char	*text;
   1.562 +    char	*pat;
   1.563 +    int		len;
   1.564 +{
   1.565 +    char	c;
   1.566 +
   1.567 +    if ((c = *pat) == '\0')
   1.568 +        return *text == '\0';
   1.569 +    for ( ; *text; text++)
   1.570 +        if (*text == c && strncmp(text, pat, len) == 0)
   1.571 +            return 0;
   1.572 +    return 1;
   1.573 +}
   1.574 +
   1.575 +STATIC CHAR *
   1.576 +search_hist(search, move)
   1.577 +    CHAR	*search;
   1.578 +    CHAR	*(*move)();
   1.579 +{
   1.580 +    static CHAR	*old_search;
   1.581 +    int		len;
   1.582 +    int		pos;
   1.583 +    int		(*match)();
   1.584 +    char	*pat;
   1.585 +
   1.586 +    /* Save or get remembered search pattern. */
   1.587 +    if (search && *search) {
   1.588 +	if (old_search)
   1.589 +	    DISPOSE(old_search);
   1.590 +	old_search = (CHAR *)strdup((char *)search);
   1.591 +    }
   1.592 +    else {
   1.593 +	if (old_search == NULL || *old_search == '\0')
   1.594 +            return NULL;
   1.595 +	search = old_search;
   1.596 +    }
   1.597 +
   1.598 +    /* Set up pattern-finder. */
   1.599 +    if (*search == '^') {
   1.600 +	match = strncmp;
   1.601 +	pat = (char *)(search + 1);
   1.602 +    }
   1.603 +    else {
   1.604 +	match = substrcmp;
   1.605 +	pat = (char *)search;
   1.606 +    }
   1.607 +    len = strlen(pat);
   1.608 +
   1.609 +    for (pos = H.Pos; (*move)() != NULL; )
   1.610 +	if ((*match)((char *)H.Lines[H.Pos], pat, len) == 0)
   1.611 +            return H.Lines[H.Pos];
   1.612 +    H.Pos = pos;
   1.613 +    return NULL;
   1.614 +}
   1.615 +
   1.616 +STATIC STATUS
   1.617 +h_search()
   1.618 +{
   1.619 +    static int	Searching;
   1.620 +    CONST char	*old_prompt;
   1.621 +    CHAR	*(*move)();
   1.622 +    CHAR	*p;
   1.623 +
   1.624 +    if (Searching)
   1.625 +	return ring_bell();
   1.626 +    Searching = 1;
   1.627 +
   1.628 +    clear_line();
   1.629 +    old_prompt = Prompt;
   1.630 +    Prompt = "Search: ";
   1.631 +    TTYputs((CONST CHAR *)Prompt);
   1.632 +    move = Repeat == NO_ARG ? prev_hist : next_hist;
   1.633 +    p = editinput();
   1.634 +    Prompt = old_prompt;
   1.635 +    Searching = 0;
   1.636 +    TTYputs((CONST CHAR *)Prompt);
   1.637 +    if (p == NULL && Signal > 0) {
   1.638 +	Signal = 0;
   1.639 +	clear_line();
   1.640 +	return redisplay();
   1.641 +    }
   1.642 +    p = search_hist(p, move);
   1.643 +    clear_line();
   1.644 +    if (p == NULL) {
   1.645 +	(void)ring_bell();
   1.646 +	return redisplay();
   1.647 +    }
   1.648 +    return do_insert_hist(p);
   1.649 +}
   1.650 +
   1.651 +STATIC STATUS
   1.652 +fd_char()
   1.653 +{
   1.654 +    int		i;
   1.655 +
   1.656 +    i = 0;
   1.657 +    do {
   1.658 +	if (Point >= End)
   1.659 +	    break;
   1.660 +	right(CSmove);
   1.661 +    } while (++i < Repeat);
   1.662 +    return CSstay;
   1.663 +}
   1.664 +
   1.665 +STATIC void
   1.666 +save_yank(begin, i)
   1.667 +    int		begin;
   1.668 +    int		i;
   1.669 +{
   1.670 +    if (Yanked) {
   1.671 +	DISPOSE(Yanked);
   1.672 +	Yanked = NULL;
   1.673 +    }
   1.674 +
   1.675 +    if (i < 1)
   1.676 +	return;
   1.677 +
   1.678 +    if ((Yanked = NEW(CHAR, (SIZE_T)i + 1)) != NULL) {
   1.679 +	COPYFROMTO(Yanked, &Line[begin], i);
   1.680 +	Yanked[i] = '\0';
   1.681 +    }
   1.682 +}
   1.683 +
   1.684 +STATIC STATUS
   1.685 +delete_string(count)
   1.686 +    int		count;
   1.687 +{
   1.688 +    int		i;
   1.689 +    CHAR	*p;
   1.690 +
   1.691 +    if (count <= 0 || End == Point)
   1.692 +	return ring_bell();
   1.693 +
   1.694 +    if (count == 1 && Point == End - 1) {
   1.695 +	/* Optimize common case of delete at end of line. */
   1.696 +	End--;
   1.697 +	p = &Line[Point];
   1.698 +	i = 1;
   1.699 +	TTYput(' ');
   1.700 +	if (ISCTL(*p)) {
   1.701 +	    i = 2;
   1.702 +	    TTYput(' ');
   1.703 +	}
   1.704 +	else if (rl_meta_chars && ISMETA(*p)) {
   1.705 +	    i = 3;
   1.706 +	    TTYput(' ');
   1.707 +	    TTYput(' ');
   1.708 +	}
   1.709 +	TTYbackn(i);
   1.710 +	*p = '\0';
   1.711 +	return CSmove;
   1.712 +    }
   1.713 +    if (Point + count > End && (count = End - Point) <= 0)
   1.714 +	return CSstay;
   1.715 +
   1.716 +    if (count > 1)
   1.717 +	save_yank(Point, count);
   1.718 +
   1.719 +    for (p = &Line[Point], i = End - (Point + count) + 1; --i >= 0; p++)
   1.720 +	p[0] = p[count];
   1.721 +    ceol();
   1.722 +    End -= count;
   1.723 +    TTYstring(&Line[Point]);
   1.724 +    return CSmove;
   1.725 +}
   1.726 +
   1.727 +STATIC STATUS
   1.728 +bk_char()
   1.729 +{
   1.730 +    int		i;
   1.731 +
   1.732 +    i = 0;
   1.733 +    do {
   1.734 +	if (Point == 0)
   1.735 +	    break;
   1.736 +	left(CSmove);
   1.737 +    } while (++i < Repeat);
   1.738 +
   1.739 +    return CSstay;
   1.740 +}
   1.741 +
   1.742 +STATIC STATUS
   1.743 +bk_del_char()
   1.744 +{
   1.745 +    int		i;
   1.746 +
   1.747 +    i = 0;
   1.748 +    do {
   1.749 +	if (Point == 0)
   1.750 +	    break;
   1.751 +	left(CSmove);
   1.752 +    } while (++i < Repeat);
   1.753 +
   1.754 +    return delete_string(i);
   1.755 +}
   1.756 +
   1.757 +STATIC STATUS
   1.758 +kill_line()
   1.759 +{
   1.760 +    int		i;
   1.761 +
   1.762 +    if (Repeat != NO_ARG) {
   1.763 +	if (Repeat < Point) {
   1.764 +	    i = Point;
   1.765 +	    Point = Repeat;
   1.766 +	    reposition();
   1.767 +	    (void)delete_string(i - Point);
   1.768 +	}
   1.769 +	else if (Repeat > Point) {
   1.770 +	    right(CSmove);
   1.771 +	    (void)delete_string(Repeat - Point - 1);
   1.772 +	}
   1.773 +	return CSmove;
   1.774 +    }
   1.775 +
   1.776 +    save_yank(Point, End - Point);
   1.777 +    Line[Point] = '\0';
   1.778 +    ceol();
   1.779 +    End = Point;
   1.780 +    return CSstay;
   1.781 +}
   1.782 +
   1.783 +STATIC STATUS
   1.784 +insert_char(c)
   1.785 +    int		c;
   1.786 +{
   1.787 +    STATUS	s;
   1.788 +    CHAR	buff[2];
   1.789 +    CHAR	*p;
   1.790 +    CHAR	*q;
   1.791 +    int		i;
   1.792 +
   1.793 +    if (Repeat == NO_ARG || Repeat < 2) {
   1.794 +	buff[0] = c;
   1.795 +	buff[1] = '\0';
   1.796 +	return insert_string(buff);
   1.797 +    }
   1.798 +
   1.799 +    if ((p = NEW(CHAR, Repeat + 1)) == NULL)
   1.800 +	return CSstay;
   1.801 +    for (i = Repeat, q = p; --i >= 0; )
   1.802 +	*q++ = c;
   1.803 +    *q = '\0';
   1.804 +    Repeat = 0;
   1.805 +    s = insert_string(p);
   1.806 +    DISPOSE(p);
   1.807 +    return s;
   1.808 +}
   1.809 +
   1.810 +STATIC STATUS
   1.811 +meta()
   1.812 +{
   1.813 +    unsigned int	c;
   1.814 +    CONST KEYMAP	*kp;
   1.815 +
   1.816 +    if ((int)(c = TTYget()) == EOF)
   1.817 +	return CSeof;
   1.818 +#if	defined(ANSI_ARROWS)
   1.819 +    /* Also include VT-100 arrows. */
   1.820 +    if (c == '[' || c == 'O')
   1.821 +	switch (c = TTYget()) {
   1.822 +	default:	return ring_bell();
   1.823 +	case EOF:	return CSeof;
   1.824 +	case 'A':	return h_prev();
   1.825 +	case 'B':	return h_next();
   1.826 +	case 'C':	return fd_char();
   1.827 +	case 'D':	return bk_char();
   1.828 +	}
   1.829 +#endif	/* defined(ANSI_ARROWS) */
   1.830 +
   1.831 +    if (isdigit(c)) {
   1.832 +	for (Repeat = c - '0'; (int)(c = TTYget()) != EOF && isdigit(c); )
   1.833 +	    Repeat = Repeat * 10 + c - '0';
   1.834 +	Pushed = 1;
   1.835 +	PushBack = c;
   1.836 +	return CSstay;
   1.837 +    }
   1.838 +
   1.839 +    if (isupper(c))
   1.840 +	return do_macro(c);
   1.841 +    for (OldPoint = Point, kp = MetaMap; kp->Function; kp++)
   1.842 +	if (kp->Key == c)
   1.843 +	    return (*kp->Function)();
   1.844 +
   1.845 +    return ring_bell();
   1.846 +}
   1.847 +
   1.848 +STATIC STATUS
   1.849 +emacs(c)
   1.850 +    unsigned int	c;
   1.851 +{
   1.852 +    STATUS		s;
   1.853 +    const KEYMAP	*kp;
   1.854 +
   1.855 +    if (rl_meta_chars && ISMETA(c)) {
   1.856 +	Pushed = 1;
   1.857 +	PushBack = UNMETA(c);
   1.858 +	return meta();
   1.859 +    }
   1.860 +    for (kp = Map; kp->Function; kp++)
   1.861 +	if (kp->Key == c)
   1.862 +	    break;
   1.863 +    s = kp->Function ? (*kp->Function)() : insert_char((int)c);
   1.864 +    if (!Pushed)
   1.865 +	/* No pushback means no repeat count; hacky, but true. */
   1.866 +	Repeat = NO_ARG;
   1.867 +    return s;
   1.868 +}
   1.869 +
   1.870 +STATIC STATUS
   1.871 +TTYspecial(c)
   1.872 +    unsigned int	c;
   1.873 +{
   1.874 +    if (ISMETA(c))
   1.875 +	return CSdispatch;
   1.876 +
   1.877 +    if (c == rl_erase || (int)c == DEL)
   1.878 +	return bk_del_char();
   1.879 +    if (c == rl_kill) {
   1.880 +	if (Point != 0) {
   1.881 +	    Point = 0;
   1.882 +	    reposition();
   1.883 +	}
   1.884 +	Repeat = NO_ARG;
   1.885 +	return kill_line();
   1.886 +    }
   1.887 +    if (c == rl_eof && Point == 0 && End == 0)
   1.888 +	return CSeof;
   1.889 +    if (c == rl_intr) {
   1.890 +	Signal = SIGINT;
   1.891 +	return CSsignal;
   1.892 +    }
   1.893 +    if (c == rl_quit) {
   1.894 +	Signal = SIGQUIT;
   1.895 +	return CSeof;
   1.896 +    }
   1.897 +
   1.898 +    return CSdispatch;
   1.899 +}
   1.900 +
   1.901 +STATIC CHAR *
   1.902 +editinput()
   1.903 +{
   1.904 +    unsigned int	c;
   1.905 +
   1.906 +    Repeat = NO_ARG;
   1.907 +    OldPoint = Point = Mark = End = 0;
   1.908 +    Line[0] = '\0';
   1.909 +
   1.910 +    Signal = -1;
   1.911 +    while ((int)(c = TTYget()) != EOF)
   1.912 +	switch (TTYspecial(c)) {
   1.913 +	case CSdone:
   1.914 +	    return Line;
   1.915 +	case CSeof:
   1.916 +	    return NULL;
   1.917 +	case CSsignal:
   1.918 +	    return (CHAR *)"";
   1.919 +	case CSmove:
   1.920 +	    reposition();
   1.921 +	    break;
   1.922 +	case CSdispatch:
   1.923 +	    switch (emacs(c)) {
   1.924 +	    case CSdone:
   1.925 +		return Line;
   1.926 +	    case CSeof:
   1.927 +		return NULL;
   1.928 +	    case CSsignal:
   1.929 +		return (CHAR *)"";
   1.930 +	    case CSmove:
   1.931 +		reposition();
   1.932 +		break;
   1.933 +	    case CSdispatch:
   1.934 +	    case CSstay:
   1.935 +		break;
   1.936 +	    }
   1.937 +	    break;
   1.938 +	case CSstay:
   1.939 +	    break;
   1.940 +	}
   1.941 +    if (strlen((char *)Line))
   1.942 +        return Line;
   1.943 +    free(Line);
   1.944 +    return NULL;
   1.945 +}
   1.946 +
   1.947 +STATIC void
   1.948 +hist_add(p)
   1.949 +    CHAR	*p;
   1.950 +{
   1.951 +    int		i;
   1.952 +
   1.953 +    if ((p = (CHAR *)strdup((char *)p)) == NULL)
   1.954 +	return;
   1.955 +    if (H.Size < HIST_SIZE)
   1.956 +	H.Lines[H.Size++] = p;
   1.957 +    else {
   1.958 +	DISPOSE(H.Lines[0]);
   1.959 +	for (i = 0; i < HIST_SIZE - 1; i++)
   1.960 +	    H.Lines[i] = H.Lines[i + 1];
   1.961 +	H.Lines[i] = p;
   1.962 +    }
   1.963 +    H.Pos = H.Size - 1;
   1.964 +}
   1.965 +
   1.966 +/*
   1.967 +**  For compatibility with FSF readline.
   1.968 +*/
   1.969 +/* ARGSUSED0 */
   1.970 +void
   1.971 +rl_reset_terminal(p)
   1.972 +    char	*p;
   1.973 +{
   1.974 +    (void)p;
   1.975 +}
   1.976 +
   1.977 +void
   1.978 +rl_initialize()
   1.979 +{
   1.980 +}
   1.981 +
   1.982 +char *
   1.983 +readline(prompt)
   1.984 +    CONST char	*prompt;
   1.985 +{
   1.986 +    CHAR	*line;
   1.987 +    int		s;
   1.988 +
   1.989 +    if (Line == NULL) {
   1.990 +	Length = MEM_INC;
   1.991 +	if ((Line = NEW(CHAR, Length)) == NULL)
   1.992 +	    return NULL;
   1.993 +    }
   1.994 +
   1.995 +    TTYinfo();
   1.996 +    rl_ttyset(0);
   1.997 +    hist_add(NIL);
   1.998 +    ScreenSize = SCREEN_INC;
   1.999 +    Screen = NEW(char, ScreenSize);
  1.1000 +    Prompt = prompt ? prompt : (char *)NIL;
  1.1001 +    TTYputs((CONST CHAR *)Prompt);
  1.1002 +    if ((line = editinput()) != NULL) {
  1.1003 +	line = (CHAR *)strdup((char *)line);
  1.1004 +	TTYputs((CONST CHAR *)NEWLINE);
  1.1005 +	TTYflush();
  1.1006 +    }
  1.1007 +    rl_ttyset(1);
  1.1008 +    DISPOSE(Screen);
  1.1009 +    DISPOSE(H.Lines[--H.Size]);
  1.1010 +    if (Signal > 0) {
  1.1011 +	s = Signal;
  1.1012 +	Signal = 0;
  1.1013 +	(void)kill(getpid(), s);
  1.1014 +    }
  1.1015 +    return (char *)line;
  1.1016 +}
  1.1017 +
  1.1018 +void
  1.1019 +add_history(p)
  1.1020 +    char	*p;
  1.1021 +{
  1.1022 +    if (p == NULL || *p == '\0')
  1.1023 +	return;
  1.1024 +
  1.1025 +#if	defined(UNIQUE_HISTORY)
  1.1026 +    if (H.Size && strcmp(p, (char *)H.Lines[H.Size - 1]) == 0)
  1.1027 +        return;
  1.1028 +#endif	/* defined(UNIQUE_HISTORY) */
  1.1029 +    hist_add((CHAR *)p);
  1.1030 +}
  1.1031 +
  1.1032 +
  1.1033 +STATIC STATUS
  1.1034 +beg_line()
  1.1035 +{
  1.1036 +    if (Point) {
  1.1037 +	Point = 0;
  1.1038 +	return CSmove;
  1.1039 +    }
  1.1040 +    return CSstay;
  1.1041 +}
  1.1042 +
  1.1043 +STATIC STATUS
  1.1044 +del_char()
  1.1045 +{
  1.1046 +    return delete_string(Repeat == NO_ARG ? 1 : Repeat);
  1.1047 +}
  1.1048 +
  1.1049 +STATIC STATUS
  1.1050 +end_line()
  1.1051 +{
  1.1052 +    if (Point != End) {
  1.1053 +	Point = End;
  1.1054 +	return CSmove;
  1.1055 +    }
  1.1056 +    return CSstay;
  1.1057 +}
  1.1058 +
  1.1059 +STATIC STATUS
  1.1060 +accept_line()
  1.1061 +{
  1.1062 +    Line[End] = '\0';
  1.1063 +    return CSdone;
  1.1064 +}
  1.1065 +
  1.1066 +STATIC STATUS
  1.1067 +transpose()
  1.1068 +{
  1.1069 +    CHAR	c;
  1.1070 +
  1.1071 +    if (Point) {
  1.1072 +	if (Point == End)
  1.1073 +	    left(CSmove);
  1.1074 +	c = Line[Point - 1];
  1.1075 +	left(CSstay);
  1.1076 +	Line[Point - 1] = Line[Point];
  1.1077 +	TTYshow(Line[Point - 1]);
  1.1078 +	Line[Point++] = c;
  1.1079 +	TTYshow(c);
  1.1080 +    }
  1.1081 +    return CSstay;
  1.1082 +}
  1.1083 +
  1.1084 +STATIC STATUS
  1.1085 +quote()
  1.1086 +{
  1.1087 +    unsigned int	c;
  1.1088 +
  1.1089 +    return (int)(c = TTYget()) == EOF ? CSeof : insert_char((int)c);
  1.1090 +}
  1.1091 +
  1.1092 +STATIC STATUS
  1.1093 +wipe()
  1.1094 +{
  1.1095 +    int		i;
  1.1096 +
  1.1097 +    if (Mark > End)
  1.1098 +	return ring_bell();
  1.1099 +
  1.1100 +    if (Point > Mark) {
  1.1101 +	i = Point;
  1.1102 +	Point = Mark;
  1.1103 +	Mark = i;
  1.1104 +	reposition();
  1.1105 +    }
  1.1106 +
  1.1107 +    return delete_string(Mark - Point);
  1.1108 +}
  1.1109 +
  1.1110 +STATIC STATUS
  1.1111 +mk_set()
  1.1112 +{
  1.1113 +    Mark = Point;
  1.1114 +    return CSstay;
  1.1115 +}
  1.1116 +
  1.1117 +STATIC STATUS
  1.1118 +exchange()
  1.1119 +{
  1.1120 +    unsigned int	c;
  1.1121 +
  1.1122 +    if ((c = TTYget()) != CTL('X'))
  1.1123 +	return (int)c == EOF ? CSeof : ring_bell();
  1.1124 +
  1.1125 +    if ((int)(c = Mark) <= End) {
  1.1126 +	Mark = Point;
  1.1127 +	Point = c;
  1.1128 +	return CSmove;
  1.1129 +    }
  1.1130 +    return CSstay;
  1.1131 +}
  1.1132 +
  1.1133 +STATIC STATUS
  1.1134 +yank()
  1.1135 +{
  1.1136 +    if (Yanked && *Yanked)
  1.1137 +	return insert_string(Yanked);
  1.1138 +    return CSstay;
  1.1139 +}
  1.1140 +
  1.1141 +STATIC STATUS
  1.1142 +copy_region()
  1.1143 +{
  1.1144 +    if (Mark > End)
  1.1145 +	return ring_bell();
  1.1146 +
  1.1147 +    if (Point > Mark)
  1.1148 +	save_yank(Mark, Point - Mark);
  1.1149 +    else
  1.1150 +	save_yank(Point, Mark - Point);
  1.1151 +
  1.1152 +    return CSstay;
  1.1153 +}
  1.1154 +
  1.1155 +STATIC STATUS
  1.1156 +move_to_char()
  1.1157 +{
  1.1158 +    unsigned int	c;
  1.1159 +    int			i;
  1.1160 +    CHAR		*p;
  1.1161 +
  1.1162 +    if ((int)(c = TTYget()) == EOF)
  1.1163 +	return CSeof;
  1.1164 +    for (i = Point + 1, p = &Line[i]; i < End; i++, p++)
  1.1165 +	if (*p == c) {
  1.1166 +	    Point = i;
  1.1167 +	    return CSmove;
  1.1168 +	}
  1.1169 +    return CSstay;
  1.1170 +}
  1.1171 +
  1.1172 +STATIC STATUS
  1.1173 +fd_word()
  1.1174 +{
  1.1175 +    return do_forward(CSmove);
  1.1176 +}
  1.1177 +
  1.1178 +STATIC STATUS
  1.1179 +fd_kill_word()
  1.1180 +{
  1.1181 +    int		i;
  1.1182 +
  1.1183 +    (void)do_forward(CSstay);
  1.1184 +    if (OldPoint != Point) {
  1.1185 +	i = Point - OldPoint;
  1.1186 +	Point = OldPoint;
  1.1187 +	return delete_string(i);
  1.1188 +    }
  1.1189 +    return CSstay;
  1.1190 +}
  1.1191 +
  1.1192 +STATIC STATUS
  1.1193 +bk_word()
  1.1194 +{
  1.1195 +    int		i;
  1.1196 +    CHAR	*p;
  1.1197 +
  1.1198 +    i = 0;
  1.1199 +    do {
  1.1200 +	for (p = &Line[Point]; p > Line && !isalnum(p[-1]); p--)
  1.1201 +	    left(CSmove);
  1.1202 +
  1.1203 +	for (; p > Line && p[-1] != ' ' && isalnum(p[-1]); p--)
  1.1204 +	    left(CSmove);
  1.1205 +
  1.1206 +	if (Point == 0)
  1.1207 +	    break;
  1.1208 +    } while (++i < Repeat);
  1.1209 +
  1.1210 +    return CSstay;
  1.1211 +}
  1.1212 +
  1.1213 +STATIC STATUS
  1.1214 +bk_kill_word()
  1.1215 +{
  1.1216 +    (void)bk_word();
  1.1217 +    if (OldPoint != Point)
  1.1218 +	return delete_string(OldPoint - Point);
  1.1219 +    return CSstay;
  1.1220 +}
  1.1221 +
  1.1222 +STATIC int
  1.1223 +argify(line, avp)
  1.1224 +    CHAR	*line;
  1.1225 +    CHAR	***avp;
  1.1226 +{
  1.1227 +    CHAR	*c;
  1.1228 +    CHAR	**p;
  1.1229 +    CHAR	**new;
  1.1230 +    int		ac;
  1.1231 +    int		i;
  1.1232 +
  1.1233 +    i = MEM_INC;
  1.1234 +    if ((*avp = p = NEW(CHAR*, i))== NULL)
  1.1235 +	 return 0;
  1.1236 +
  1.1237 +    for (c = line; isspace(*c); c++)
  1.1238 +	continue;
  1.1239 +    if (*c == '\n' || *c == '\0')
  1.1240 +	return 0;
  1.1241 +
  1.1242 +    for (ac = 0, p[ac++] = c; *c && *c != '\n'; ) {
  1.1243 +	if (isspace(*c)) {
  1.1244 +	    *c++ = '\0';
  1.1245 +	    if (*c && *c != '\n') {
  1.1246 +		if (ac + 1 == i) {
  1.1247 +		    new = NEW(CHAR*, i + MEM_INC);
  1.1248 +		    if (new == NULL) {
  1.1249 +			p[ac] = NULL;
  1.1250 +			return ac;
  1.1251 +		    }
  1.1252 +		    COPYFROMTO(new, p, i * sizeof (char **));
  1.1253 +		    i += MEM_INC;
  1.1254 +		    DISPOSE(p);
  1.1255 +		    *avp = p = new;
  1.1256 +		}
  1.1257 +		p[ac++] = c;
  1.1258 +	    }
  1.1259 +	}
  1.1260 +	else
  1.1261 +	    c++;
  1.1262 +    }
  1.1263 +    *c = '\0';
  1.1264 +    p[ac] = NULL;
  1.1265 +    return ac;
  1.1266 +}
  1.1267 +
  1.1268 +STATIC STATUS
  1.1269 +last_argument()
  1.1270 +{
  1.1271 +    CHAR	**av;
  1.1272 +    CHAR	*p;
  1.1273 +    STATUS	s;
  1.1274 +    int		ac;
  1.1275 +
  1.1276 +    if (H.Size == 1 || (p = H.Lines[H.Size - 2]) == NULL)
  1.1277 +	return ring_bell();
  1.1278 +
  1.1279 +    if ((p = (CHAR *)strdup((char *)p)) == NULL)
  1.1280 +	return CSstay;
  1.1281 +    ac = argify(p, &av);
  1.1282 +
  1.1283 +    if (Repeat != NO_ARG)
  1.1284 +	s = Repeat < ac ? insert_string(av[Repeat]) : ring_bell();
  1.1285 +    else
  1.1286 +	s = ac ? insert_string(av[ac - 1]) : CSstay;
  1.1287 +
  1.1288 +    if (ac)
  1.1289 +	DISPOSE(av);
  1.1290 +    DISPOSE(p);
  1.1291 +    return s;
  1.1292 +}
  1.1293 +
  1.1294 +STATIC CONST KEYMAP Map[32] = {
  1.1295 +    {	CTL('@'),	ring_bell	},
  1.1296 +    {	CTL('A'),	beg_line	},
  1.1297 +    {	CTL('B'),	bk_char		},
  1.1298 +    {	CTL('D'),	del_char	},
  1.1299 +    {	CTL('E'),	end_line	},
  1.1300 +    {	CTL('F'),	fd_char		},
  1.1301 +    {	CTL('G'),	ring_bell	},
  1.1302 +    {	CTL('H'),	bk_del_char	},
  1.1303 +    {	CTL('J'),	accept_line	},
  1.1304 +    {	CTL('K'),	kill_line	},
  1.1305 +    {	CTL('L'),	redisplay	},
  1.1306 +    {	CTL('M'),	accept_line	},
  1.1307 +    {	CTL('N'),	h_next		},
  1.1308 +    {	CTL('O'),	ring_bell	},
  1.1309 +    {	CTL('P'),	h_prev		},
  1.1310 +    {	CTL('Q'),	ring_bell	},
  1.1311 +    {	CTL('R'),	h_search	},
  1.1312 +    {	CTL('S'),	ring_bell	},
  1.1313 +    {	CTL('T'),	transpose	},
  1.1314 +    {	CTL('U'),	ring_bell	},
  1.1315 +    {	CTL('V'),	quote		},
  1.1316 +    {	CTL('W'),	wipe		},
  1.1317 +    {	CTL('X'),	exchange	},
  1.1318 +    {	CTL('Y'),	yank		},
  1.1319 +    {	CTL('Z'),	ring_bell	},
  1.1320 +    {	CTL('['),	meta		},
  1.1321 +    {	CTL(']'),	move_to_char	},
  1.1322 +    {	CTL('^'),	ring_bell	},
  1.1323 +    {	CTL('_'),	ring_bell	},
  1.1324 +    {	0,		NULL		}
  1.1325 +};
  1.1326 +
  1.1327 +STATIC CONST KEYMAP MetaMap[16]= {
  1.1328 +    {	CTL('H'),	bk_kill_word	},
  1.1329 +    {	DEL,		bk_kill_word	},
  1.1330 +    {	' ',		mk_set		},
  1.1331 +    {	'.',		last_argument	},
  1.1332 +    {	'<',		h_first		},
  1.1333 +    {	'>',		h_last		},
  1.1334 +    {	'b',		bk_word		},
  1.1335 +    {	'd',		fd_kill_word	},
  1.1336 +    {	'f',		fd_word		},
  1.1337 +    {	'l',		case_down_word	},
  1.1338 +    {	'm',		toggle_meta_mode },
  1.1339 +    {	'u',		case_up_word	},
  1.1340 +    {	'y',		yank		},
  1.1341 +    {	'w',		copy_region	},
  1.1342 +    {	0,		NULL		}
  1.1343 +};
  1.1344 +

mercurial