js/src/editline/editline.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /*
michael@0 7 * Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
michael@0 8 *
michael@0 9 * This software is not subject to any license of the American Telephone
michael@0 10 * and Telegraph Company or of the Regents of the University of California.
michael@0 11 *
michael@0 12 * Permission is granted to anyone to use this software for any purpose on
michael@0 13 * any computer system, and to alter it and redistribute it freely, subject
michael@0 14 * to the following restrictions:
michael@0 15 * 1. The authors are not responsible for the consequences of use of this
michael@0 16 * software, no matter how awful, even if they arise from flaws in it.
michael@0 17 * 2. The origin of this software must not be misrepresented, either by
michael@0 18 * explicit claim or by omission. Since few users ever read sources,
michael@0 19 * credits must appear in the documentation.
michael@0 20 * 3. Altered versions must be plainly marked as such, and must not be
michael@0 21 * misrepresented as being the original software. Since few users
michael@0 22 * ever read sources, credits must appear in the documentation.
michael@0 23 * 4. This notice may not be removed or altered.
michael@0 24 */
michael@0 25
michael@0 26
michael@0 27 /*
michael@0 28 ** Main editing routines for editline library.
michael@0 29 */
michael@0 30 #include "editline.h"
michael@0 31 #include <signal.h>
michael@0 32 #include <ctype.h>
michael@0 33 #include <unistd.h>
michael@0 34
michael@0 35 /*
michael@0 36 ** Manifest constants.
michael@0 37 */
michael@0 38 #define SCREEN_WIDTH 80
michael@0 39 #define SCREEN_ROWS 24
michael@0 40 #define NO_ARG (-1)
michael@0 41 #define DEL 127
michael@0 42 #define CTL(x) ((x) & 0x1F)
michael@0 43 #define ISCTL(x) ((x) && (x) < ' ')
michael@0 44 #define UNCTL(x) ((x) + 64)
michael@0 45 #define META(x) ((x) | 0x80)
michael@0 46 #define ISMETA(x) ((x) & 0x80)
michael@0 47 #define UNMETA(x) ((x) & 0x7F)
michael@0 48 #if !defined(HIST_SIZE)
michael@0 49 #define HIST_SIZE 20
michael@0 50 #endif /* !defined(HIST_SIZE) */
michael@0 51
michael@0 52 /*
michael@0 53 ** Command status codes.
michael@0 54 */
michael@0 55 typedef enum _STATUS {
michael@0 56 CSdone, CSeof, CSmove, CSdispatch, CSstay, CSsignal
michael@0 57 } STATUS;
michael@0 58
michael@0 59 /*
michael@0 60 ** The type of case-changing to perform.
michael@0 61 */
michael@0 62 typedef enum _CASE {
michael@0 63 TOupper, TOlower
michael@0 64 } CASE;
michael@0 65
michael@0 66 /*
michael@0 67 ** Key to command mapping.
michael@0 68 */
michael@0 69 typedef struct _KEYMAP {
michael@0 70 CHAR Key;
michael@0 71 STATUS (*Function)();
michael@0 72 } KEYMAP;
michael@0 73
michael@0 74 /*
michael@0 75 ** Command history structure.
michael@0 76 */
michael@0 77 typedef struct _HISTORY {
michael@0 78 int Size;
michael@0 79 int Pos;
michael@0 80 CHAR *Lines[HIST_SIZE];
michael@0 81 } HISTORY;
michael@0 82
michael@0 83 /*
michael@0 84 ** Globals.
michael@0 85 */
michael@0 86 unsigned rl_eof;
michael@0 87 unsigned rl_erase;
michael@0 88 unsigned rl_intr;
michael@0 89 unsigned rl_kill;
michael@0 90 unsigned rl_quit;
michael@0 91
michael@0 92 STATIC CHAR NIL[] = "";
michael@0 93 STATIC CONST CHAR *Input = NIL;
michael@0 94 STATIC CHAR *Line;
michael@0 95 STATIC CONST char *Prompt;
michael@0 96 STATIC CHAR *Yanked;
michael@0 97 STATIC char *Screen;
michael@0 98 STATIC CONST char NEWLINE[]= CRLF;
michael@0 99 STATIC HISTORY H;
michael@0 100 STATIC int Repeat;
michael@0 101 STATIC int End;
michael@0 102 STATIC int Mark;
michael@0 103 STATIC int OldPoint;
michael@0 104 STATIC int Point;
michael@0 105 STATIC int PushBack;
michael@0 106 STATIC int Pushed;
michael@0 107 STATIC int Signal;
michael@0 108 FORWARD CONST KEYMAP Map[32];
michael@0 109 FORWARD CONST KEYMAP MetaMap[16];
michael@0 110 STATIC SIZE_T Length;
michael@0 111 STATIC SIZE_T ScreenCount;
michael@0 112 STATIC SIZE_T ScreenSize;
michael@0 113 STATIC char *backspace;
michael@0 114 STATIC int TTYwidth;
michael@0 115 STATIC int TTYrows;
michael@0 116
michael@0 117 /* Display print 8-bit chars as `M-x' or as the actual 8-bit char? */
michael@0 118 int rl_meta_chars = 0;
michael@0 119
michael@0 120 /*
michael@0 121 ** Declarations.
michael@0 122 */
michael@0 123 STATIC CHAR *editinput();
michael@0 124 #if defined(USE_TERMCAP)
michael@0 125 #include <stdlib.h>
michael@0 126 #include <curses.h>
michael@0 127 #include <term.h>
michael@0 128 #endif /* defined(USE_TERMCAP) */
michael@0 129
michael@0 130 /*
michael@0 131 ** TTY input/output functions.
michael@0 132 */
michael@0 133
michael@0 134 STATIC void
michael@0 135 TTYflush()
michael@0 136 {
michael@0 137 if (ScreenCount) {
michael@0 138 /* Dummy assignment avoids GCC warning on
michael@0 139 * "attribute warn_unused_result" */
michael@0 140 ssize_t dummy = write(1, Screen, ScreenCount);
michael@0 141 (void)dummy;
michael@0 142 ScreenCount = 0;
michael@0 143 }
michael@0 144 }
michael@0 145
michael@0 146 STATIC void
michael@0 147 TTYput(c)
michael@0 148 CHAR c;
michael@0 149 {
michael@0 150 Screen[ScreenCount] = c;
michael@0 151 if (++ScreenCount >= ScreenSize - 1) {
michael@0 152 ScreenSize += SCREEN_INC;
michael@0 153 RENEW(Screen, char, ScreenSize);
michael@0 154 }
michael@0 155 }
michael@0 156
michael@0 157 STATIC void
michael@0 158 TTYputs(p)
michael@0 159 CONST CHAR *p;
michael@0 160 {
michael@0 161 while (*p)
michael@0 162 TTYput(*p++);
michael@0 163 }
michael@0 164
michael@0 165 STATIC void
michael@0 166 TTYshow(c)
michael@0 167 CHAR c;
michael@0 168 {
michael@0 169 if (c == DEL) {
michael@0 170 TTYput('^');
michael@0 171 TTYput('?');
michael@0 172 }
michael@0 173 else if (ISCTL(c)) {
michael@0 174 TTYput('^');
michael@0 175 TTYput(UNCTL(c));
michael@0 176 }
michael@0 177 else if (rl_meta_chars && ISMETA(c)) {
michael@0 178 TTYput('M');
michael@0 179 TTYput('-');
michael@0 180 TTYput(UNMETA(c));
michael@0 181 }
michael@0 182 else
michael@0 183 TTYput(c);
michael@0 184 }
michael@0 185
michael@0 186 STATIC void
michael@0 187 TTYstring(p)
michael@0 188 CHAR *p;
michael@0 189 {
michael@0 190 while (*p)
michael@0 191 TTYshow(*p++);
michael@0 192 }
michael@0 193
michael@0 194 STATIC unsigned int
michael@0 195 TTYget()
michael@0 196 {
michael@0 197 CHAR c;
michael@0 198
michael@0 199 TTYflush();
michael@0 200 if (Pushed) {
michael@0 201 Pushed = 0;
michael@0 202 return PushBack;
michael@0 203 }
michael@0 204 if (*Input)
michael@0 205 return *Input++;
michael@0 206 return read(0, &c, (SIZE_T)1) == 1 ? c : EOF;
michael@0 207 }
michael@0 208
michael@0 209 #define TTYback() (backspace ? TTYputs((CHAR *)backspace) : TTYput('\b'))
michael@0 210
michael@0 211 STATIC void
michael@0 212 TTYbackn(n)
michael@0 213 int n;
michael@0 214 {
michael@0 215 while (--n >= 0)
michael@0 216 TTYback();
michael@0 217 }
michael@0 218
michael@0 219 STATIC void
michael@0 220 TTYinfo()
michael@0 221 {
michael@0 222 static int init;
michael@0 223 #if defined(USE_TERMCAP)
michael@0 224 char *term;
michael@0 225 char buff[2048];
michael@0 226 char *bp, *p;
michael@0 227 #endif /* defined(USE_TERMCAP) */
michael@0 228 #if defined(TIOCGWINSZ)
michael@0 229 struct winsize W;
michael@0 230 #endif /* defined(TIOCGWINSZ) */
michael@0 231
michael@0 232 if (init) {
michael@0 233 #if defined(TIOCGWINSZ)
michael@0 234 /* Perhaps we got resized. */
michael@0 235 if (ioctl(0, TIOCGWINSZ, &W) >= 0
michael@0 236 && W.ws_col > 0 && W.ws_row > 0) {
michael@0 237 TTYwidth = (int)W.ws_col;
michael@0 238 TTYrows = (int)W.ws_row;
michael@0 239 }
michael@0 240 #endif /* defined(TIOCGWINSZ) */
michael@0 241 return;
michael@0 242 }
michael@0 243 init++;
michael@0 244
michael@0 245 TTYwidth = TTYrows = 0;
michael@0 246 #if defined(USE_TERMCAP)
michael@0 247 bp = &buff[0];
michael@0 248 if ((term = getenv("TERM")) == NULL)
michael@0 249 term = "dumb";
michael@0 250 if (tgetent(buff, term) < 0) {
michael@0 251 TTYwidth = SCREEN_WIDTH;
michael@0 252 TTYrows = SCREEN_ROWS;
michael@0 253 return;
michael@0 254 }
michael@0 255 p = tgetstr("le", &bp);
michael@0 256 backspace = p ? strdup(p) : NULL;
michael@0 257 TTYwidth = tgetnum("co");
michael@0 258 TTYrows = tgetnum("li");
michael@0 259 #endif /* defined(USE_TERMCAP) */
michael@0 260
michael@0 261 #if defined(TIOCGWINSZ)
michael@0 262 if (ioctl(0, TIOCGWINSZ, &W) >= 0) {
michael@0 263 TTYwidth = (int)W.ws_col;
michael@0 264 TTYrows = (int)W.ws_row;
michael@0 265 }
michael@0 266 #endif /* defined(TIOCGWINSZ) */
michael@0 267
michael@0 268 if (TTYwidth <= 0 || TTYrows <= 0) {
michael@0 269 TTYwidth = SCREEN_WIDTH;
michael@0 270 TTYrows = SCREEN_ROWS;
michael@0 271 }
michael@0 272 }
michael@0 273
michael@0 274
michael@0 275 STATIC void
michael@0 276 reposition()
michael@0 277 {
michael@0 278 int i;
michael@0 279 CHAR *p;
michael@0 280
michael@0 281 TTYput('\r');
michael@0 282 TTYputs((CONST CHAR *)Prompt);
michael@0 283 for (i = Point, p = Line; --i >= 0; p++)
michael@0 284 TTYshow(*p);
michael@0 285 }
michael@0 286
michael@0 287 STATIC void
michael@0 288 left(Change)
michael@0 289 STATUS Change;
michael@0 290 {
michael@0 291 TTYback();
michael@0 292 if (Point) {
michael@0 293 if (ISCTL(Line[Point - 1]))
michael@0 294 TTYback();
michael@0 295 else if (rl_meta_chars && ISMETA(Line[Point - 1])) {
michael@0 296 TTYback();
michael@0 297 TTYback();
michael@0 298 }
michael@0 299 }
michael@0 300 if (Change == CSmove)
michael@0 301 Point--;
michael@0 302 }
michael@0 303
michael@0 304 STATIC void
michael@0 305 right(Change)
michael@0 306 STATUS Change;
michael@0 307 {
michael@0 308 TTYshow(Line[Point]);
michael@0 309 if (Change == CSmove)
michael@0 310 Point++;
michael@0 311 }
michael@0 312
michael@0 313 STATIC STATUS
michael@0 314 ring_bell()
michael@0 315 {
michael@0 316 TTYput('\07');
michael@0 317 TTYflush();
michael@0 318 return CSstay;
michael@0 319 }
michael@0 320
michael@0 321 STATIC STATUS
michael@0 322 do_macro(c)
michael@0 323 unsigned int c;
michael@0 324 {
michael@0 325 CHAR name[4];
michael@0 326
michael@0 327 name[0] = '_';
michael@0 328 name[1] = c;
michael@0 329 name[2] = '_';
michael@0 330 name[3] = '\0';
michael@0 331
michael@0 332 if ((Input = (CHAR *)getenv((char *)name)) == NULL) {
michael@0 333 Input = NIL;
michael@0 334 return ring_bell();
michael@0 335 }
michael@0 336 return CSstay;
michael@0 337 }
michael@0 338
michael@0 339 STATIC STATUS
michael@0 340 do_forward(move)
michael@0 341 STATUS move;
michael@0 342 {
michael@0 343 int i;
michael@0 344 CHAR *p;
michael@0 345
michael@0 346 i = 0;
michael@0 347 do {
michael@0 348 p = &Line[Point];
michael@0 349 for ( ; Point < End && (*p == ' ' || !isalnum(*p)); Point++, p++)
michael@0 350 if (move == CSmove)
michael@0 351 right(CSstay);
michael@0 352
michael@0 353 for (; Point < End && isalnum(*p); Point++, p++)
michael@0 354 if (move == CSmove)
michael@0 355 right(CSstay);
michael@0 356
michael@0 357 if (Point == End)
michael@0 358 break;
michael@0 359 } while (++i < Repeat);
michael@0 360
michael@0 361 return CSstay;
michael@0 362 }
michael@0 363
michael@0 364 STATIC STATUS
michael@0 365 do_case(type)
michael@0 366 CASE type;
michael@0 367 {
michael@0 368 int i;
michael@0 369 int end;
michael@0 370 int count;
michael@0 371 CHAR *p;
michael@0 372
michael@0 373 (void)do_forward(CSstay);
michael@0 374 if (OldPoint != Point) {
michael@0 375 if ((count = Point - OldPoint) < 0)
michael@0 376 count = -count;
michael@0 377 Point = OldPoint;
michael@0 378 if ((end = Point + count) > End)
michael@0 379 end = End;
michael@0 380 for (i = Point, p = &Line[i]; i < end; i++, p++) {
michael@0 381 if (type == TOupper) {
michael@0 382 if (islower(*p))
michael@0 383 *p = toupper(*p);
michael@0 384 }
michael@0 385 else if (isupper(*p))
michael@0 386 *p = tolower(*p);
michael@0 387 right(CSmove);
michael@0 388 }
michael@0 389 }
michael@0 390 return CSstay;
michael@0 391 }
michael@0 392
michael@0 393 STATIC STATUS
michael@0 394 case_down_word()
michael@0 395 {
michael@0 396 return do_case(TOlower);
michael@0 397 }
michael@0 398
michael@0 399 STATIC STATUS
michael@0 400 case_up_word()
michael@0 401 {
michael@0 402 return do_case(TOupper);
michael@0 403 }
michael@0 404
michael@0 405 STATIC void
michael@0 406 ceol()
michael@0 407 {
michael@0 408 int extras;
michael@0 409 int i;
michael@0 410 CHAR *p;
michael@0 411
michael@0 412 for (extras = 0, i = Point, p = &Line[i]; i <= End; i++, p++) {
michael@0 413 TTYput(' ');
michael@0 414 if (ISCTL(*p)) {
michael@0 415 TTYput(' ');
michael@0 416 extras++;
michael@0 417 }
michael@0 418 else if (rl_meta_chars && ISMETA(*p)) {
michael@0 419 TTYput(' ');
michael@0 420 TTYput(' ');
michael@0 421 extras += 2;
michael@0 422 }
michael@0 423 }
michael@0 424
michael@0 425 for (i += extras; i > Point; i--)
michael@0 426 TTYback();
michael@0 427 }
michael@0 428
michael@0 429 STATIC void
michael@0 430 clear_line()
michael@0 431 {
michael@0 432 Point = -strlen(Prompt);
michael@0 433 TTYput('\r');
michael@0 434 ceol();
michael@0 435 Point = 0;
michael@0 436 End = 0;
michael@0 437 Line[0] = '\0';
michael@0 438 }
michael@0 439
michael@0 440 STATIC STATUS
michael@0 441 insert_string(p)
michael@0 442 CHAR *p;
michael@0 443 {
michael@0 444 SIZE_T len;
michael@0 445 int i;
michael@0 446 CHAR *new;
michael@0 447 CHAR *q;
michael@0 448
michael@0 449 len = strlen((char *)p);
michael@0 450 if (End + len >= Length) {
michael@0 451 if ((new = NEW(CHAR, Length + len + MEM_INC)) == NULL)
michael@0 452 return CSstay;
michael@0 453 if (Length) {
michael@0 454 COPYFROMTO(new, Line, Length);
michael@0 455 DISPOSE(Line);
michael@0 456 }
michael@0 457 Line = new;
michael@0 458 Length += len + MEM_INC;
michael@0 459 }
michael@0 460
michael@0 461 for (q = &Line[Point], i = End - Point; --i >= 0; )
michael@0 462 q[len + i] = q[i];
michael@0 463 COPYFROMTO(&Line[Point], p, len);
michael@0 464 End += len;
michael@0 465 Line[End] = '\0';
michael@0 466 TTYstring(&Line[Point]);
michael@0 467 Point += len;
michael@0 468
michael@0 469 return Point == End ? CSstay : CSmove;
michael@0 470 }
michael@0 471
michael@0 472 STATIC STATUS
michael@0 473 redisplay()
michael@0 474 {
michael@0 475 TTYputs((CONST CHAR *)NEWLINE);
michael@0 476 TTYputs((CONST CHAR *)Prompt);
michael@0 477 TTYstring(Line);
michael@0 478 return CSmove;
michael@0 479 }
michael@0 480
michael@0 481 STATIC STATUS
michael@0 482 toggle_meta_mode()
michael@0 483 {
michael@0 484 rl_meta_chars = ! rl_meta_chars;
michael@0 485 return redisplay();
michael@0 486 }
michael@0 487
michael@0 488
michael@0 489 STATIC CHAR *
michael@0 490 next_hist()
michael@0 491 {
michael@0 492 return H.Pos >= H.Size - 1 ? NULL : H.Lines[++H.Pos];
michael@0 493 }
michael@0 494
michael@0 495 STATIC CHAR *
michael@0 496 prev_hist()
michael@0 497 {
michael@0 498 return H.Pos == 0 ? NULL : H.Lines[--H.Pos];
michael@0 499 }
michael@0 500
michael@0 501 STATIC STATUS
michael@0 502 do_insert_hist(p)
michael@0 503 CHAR *p;
michael@0 504 {
michael@0 505 if (p == NULL)
michael@0 506 return ring_bell();
michael@0 507 Point = 0;
michael@0 508 reposition();
michael@0 509 ceol();
michael@0 510 End = 0;
michael@0 511 return insert_string(p);
michael@0 512 }
michael@0 513
michael@0 514 STATIC STATUS
michael@0 515 do_hist(move)
michael@0 516 CHAR *(*move)();
michael@0 517 {
michael@0 518 CHAR *p;
michael@0 519 int i;
michael@0 520
michael@0 521 i = 0;
michael@0 522 do {
michael@0 523 if ((p = (*move)()) == NULL)
michael@0 524 return ring_bell();
michael@0 525 } while (++i < Repeat);
michael@0 526 return do_insert_hist(p);
michael@0 527 }
michael@0 528
michael@0 529 STATIC STATUS
michael@0 530 h_next()
michael@0 531 {
michael@0 532 return do_hist(next_hist);
michael@0 533 }
michael@0 534
michael@0 535 STATIC STATUS
michael@0 536 h_prev()
michael@0 537 {
michael@0 538 return do_hist(prev_hist);
michael@0 539 }
michael@0 540
michael@0 541 STATIC STATUS
michael@0 542 h_first()
michael@0 543 {
michael@0 544 return do_insert_hist(H.Lines[H.Pos = 0]);
michael@0 545 }
michael@0 546
michael@0 547 STATIC STATUS
michael@0 548 h_last()
michael@0 549 {
michael@0 550 return do_insert_hist(H.Lines[H.Pos = H.Size - 1]);
michael@0 551 }
michael@0 552
michael@0 553 /*
michael@0 554 ** Return zero if pat appears as a substring in text.
michael@0 555 */
michael@0 556 STATIC int
michael@0 557 substrcmp(text, pat, len)
michael@0 558 char *text;
michael@0 559 char *pat;
michael@0 560 int len;
michael@0 561 {
michael@0 562 char c;
michael@0 563
michael@0 564 if ((c = *pat) == '\0')
michael@0 565 return *text == '\0';
michael@0 566 for ( ; *text; text++)
michael@0 567 if (*text == c && strncmp(text, pat, len) == 0)
michael@0 568 return 0;
michael@0 569 return 1;
michael@0 570 }
michael@0 571
michael@0 572 STATIC CHAR *
michael@0 573 search_hist(search, move)
michael@0 574 CHAR *search;
michael@0 575 CHAR *(*move)();
michael@0 576 {
michael@0 577 static CHAR *old_search;
michael@0 578 int len;
michael@0 579 int pos;
michael@0 580 int (*match)();
michael@0 581 char *pat;
michael@0 582
michael@0 583 /* Save or get remembered search pattern. */
michael@0 584 if (search && *search) {
michael@0 585 if (old_search)
michael@0 586 DISPOSE(old_search);
michael@0 587 old_search = (CHAR *)strdup((char *)search);
michael@0 588 }
michael@0 589 else {
michael@0 590 if (old_search == NULL || *old_search == '\0')
michael@0 591 return NULL;
michael@0 592 search = old_search;
michael@0 593 }
michael@0 594
michael@0 595 /* Set up pattern-finder. */
michael@0 596 if (*search == '^') {
michael@0 597 match = strncmp;
michael@0 598 pat = (char *)(search + 1);
michael@0 599 }
michael@0 600 else {
michael@0 601 match = substrcmp;
michael@0 602 pat = (char *)search;
michael@0 603 }
michael@0 604 len = strlen(pat);
michael@0 605
michael@0 606 for (pos = H.Pos; (*move)() != NULL; )
michael@0 607 if ((*match)((char *)H.Lines[H.Pos], pat, len) == 0)
michael@0 608 return H.Lines[H.Pos];
michael@0 609 H.Pos = pos;
michael@0 610 return NULL;
michael@0 611 }
michael@0 612
michael@0 613 STATIC STATUS
michael@0 614 h_search()
michael@0 615 {
michael@0 616 static int Searching;
michael@0 617 CONST char *old_prompt;
michael@0 618 CHAR *(*move)();
michael@0 619 CHAR *p;
michael@0 620
michael@0 621 if (Searching)
michael@0 622 return ring_bell();
michael@0 623 Searching = 1;
michael@0 624
michael@0 625 clear_line();
michael@0 626 old_prompt = Prompt;
michael@0 627 Prompt = "Search: ";
michael@0 628 TTYputs((CONST CHAR *)Prompt);
michael@0 629 move = Repeat == NO_ARG ? prev_hist : next_hist;
michael@0 630 p = editinput();
michael@0 631 Prompt = old_prompt;
michael@0 632 Searching = 0;
michael@0 633 TTYputs((CONST CHAR *)Prompt);
michael@0 634 if (p == NULL && Signal > 0) {
michael@0 635 Signal = 0;
michael@0 636 clear_line();
michael@0 637 return redisplay();
michael@0 638 }
michael@0 639 p = search_hist(p, move);
michael@0 640 clear_line();
michael@0 641 if (p == NULL) {
michael@0 642 (void)ring_bell();
michael@0 643 return redisplay();
michael@0 644 }
michael@0 645 return do_insert_hist(p);
michael@0 646 }
michael@0 647
michael@0 648 STATIC STATUS
michael@0 649 fd_char()
michael@0 650 {
michael@0 651 int i;
michael@0 652
michael@0 653 i = 0;
michael@0 654 do {
michael@0 655 if (Point >= End)
michael@0 656 break;
michael@0 657 right(CSmove);
michael@0 658 } while (++i < Repeat);
michael@0 659 return CSstay;
michael@0 660 }
michael@0 661
michael@0 662 STATIC void
michael@0 663 save_yank(begin, i)
michael@0 664 int begin;
michael@0 665 int i;
michael@0 666 {
michael@0 667 if (Yanked) {
michael@0 668 DISPOSE(Yanked);
michael@0 669 Yanked = NULL;
michael@0 670 }
michael@0 671
michael@0 672 if (i < 1)
michael@0 673 return;
michael@0 674
michael@0 675 if ((Yanked = NEW(CHAR, (SIZE_T)i + 1)) != NULL) {
michael@0 676 COPYFROMTO(Yanked, &Line[begin], i);
michael@0 677 Yanked[i] = '\0';
michael@0 678 }
michael@0 679 }
michael@0 680
michael@0 681 STATIC STATUS
michael@0 682 delete_string(count)
michael@0 683 int count;
michael@0 684 {
michael@0 685 int i;
michael@0 686 CHAR *p;
michael@0 687
michael@0 688 if (count <= 0 || End == Point)
michael@0 689 return ring_bell();
michael@0 690
michael@0 691 if (count == 1 && Point == End - 1) {
michael@0 692 /* Optimize common case of delete at end of line. */
michael@0 693 End--;
michael@0 694 p = &Line[Point];
michael@0 695 i = 1;
michael@0 696 TTYput(' ');
michael@0 697 if (ISCTL(*p)) {
michael@0 698 i = 2;
michael@0 699 TTYput(' ');
michael@0 700 }
michael@0 701 else if (rl_meta_chars && ISMETA(*p)) {
michael@0 702 i = 3;
michael@0 703 TTYput(' ');
michael@0 704 TTYput(' ');
michael@0 705 }
michael@0 706 TTYbackn(i);
michael@0 707 *p = '\0';
michael@0 708 return CSmove;
michael@0 709 }
michael@0 710 if (Point + count > End && (count = End - Point) <= 0)
michael@0 711 return CSstay;
michael@0 712
michael@0 713 if (count > 1)
michael@0 714 save_yank(Point, count);
michael@0 715
michael@0 716 for (p = &Line[Point], i = End - (Point + count) + 1; --i >= 0; p++)
michael@0 717 p[0] = p[count];
michael@0 718 ceol();
michael@0 719 End -= count;
michael@0 720 TTYstring(&Line[Point]);
michael@0 721 return CSmove;
michael@0 722 }
michael@0 723
michael@0 724 STATIC STATUS
michael@0 725 bk_char()
michael@0 726 {
michael@0 727 int i;
michael@0 728
michael@0 729 i = 0;
michael@0 730 do {
michael@0 731 if (Point == 0)
michael@0 732 break;
michael@0 733 left(CSmove);
michael@0 734 } while (++i < Repeat);
michael@0 735
michael@0 736 return CSstay;
michael@0 737 }
michael@0 738
michael@0 739 STATIC STATUS
michael@0 740 bk_del_char()
michael@0 741 {
michael@0 742 int i;
michael@0 743
michael@0 744 i = 0;
michael@0 745 do {
michael@0 746 if (Point == 0)
michael@0 747 break;
michael@0 748 left(CSmove);
michael@0 749 } while (++i < Repeat);
michael@0 750
michael@0 751 return delete_string(i);
michael@0 752 }
michael@0 753
michael@0 754 STATIC STATUS
michael@0 755 kill_line()
michael@0 756 {
michael@0 757 int i;
michael@0 758
michael@0 759 if (Repeat != NO_ARG) {
michael@0 760 if (Repeat < Point) {
michael@0 761 i = Point;
michael@0 762 Point = Repeat;
michael@0 763 reposition();
michael@0 764 (void)delete_string(i - Point);
michael@0 765 }
michael@0 766 else if (Repeat > Point) {
michael@0 767 right(CSmove);
michael@0 768 (void)delete_string(Repeat - Point - 1);
michael@0 769 }
michael@0 770 return CSmove;
michael@0 771 }
michael@0 772
michael@0 773 save_yank(Point, End - Point);
michael@0 774 Line[Point] = '\0';
michael@0 775 ceol();
michael@0 776 End = Point;
michael@0 777 return CSstay;
michael@0 778 }
michael@0 779
michael@0 780 STATIC STATUS
michael@0 781 insert_char(c)
michael@0 782 int c;
michael@0 783 {
michael@0 784 STATUS s;
michael@0 785 CHAR buff[2];
michael@0 786 CHAR *p;
michael@0 787 CHAR *q;
michael@0 788 int i;
michael@0 789
michael@0 790 if (Repeat == NO_ARG || Repeat < 2) {
michael@0 791 buff[0] = c;
michael@0 792 buff[1] = '\0';
michael@0 793 return insert_string(buff);
michael@0 794 }
michael@0 795
michael@0 796 if ((p = NEW(CHAR, Repeat + 1)) == NULL)
michael@0 797 return CSstay;
michael@0 798 for (i = Repeat, q = p; --i >= 0; )
michael@0 799 *q++ = c;
michael@0 800 *q = '\0';
michael@0 801 Repeat = 0;
michael@0 802 s = insert_string(p);
michael@0 803 DISPOSE(p);
michael@0 804 return s;
michael@0 805 }
michael@0 806
michael@0 807 STATIC STATUS
michael@0 808 meta()
michael@0 809 {
michael@0 810 unsigned int c;
michael@0 811 CONST KEYMAP *kp;
michael@0 812
michael@0 813 if ((int)(c = TTYget()) == EOF)
michael@0 814 return CSeof;
michael@0 815 #if defined(ANSI_ARROWS)
michael@0 816 /* Also include VT-100 arrows. */
michael@0 817 if (c == '[' || c == 'O')
michael@0 818 switch (c = TTYget()) {
michael@0 819 default: return ring_bell();
michael@0 820 case EOF: return CSeof;
michael@0 821 case 'A': return h_prev();
michael@0 822 case 'B': return h_next();
michael@0 823 case 'C': return fd_char();
michael@0 824 case 'D': return bk_char();
michael@0 825 }
michael@0 826 #endif /* defined(ANSI_ARROWS) */
michael@0 827
michael@0 828 if (isdigit(c)) {
michael@0 829 for (Repeat = c - '0'; (int)(c = TTYget()) != EOF && isdigit(c); )
michael@0 830 Repeat = Repeat * 10 + c - '0';
michael@0 831 Pushed = 1;
michael@0 832 PushBack = c;
michael@0 833 return CSstay;
michael@0 834 }
michael@0 835
michael@0 836 if (isupper(c))
michael@0 837 return do_macro(c);
michael@0 838 for (OldPoint = Point, kp = MetaMap; kp->Function; kp++)
michael@0 839 if (kp->Key == c)
michael@0 840 return (*kp->Function)();
michael@0 841
michael@0 842 return ring_bell();
michael@0 843 }
michael@0 844
michael@0 845 STATIC STATUS
michael@0 846 emacs(c)
michael@0 847 unsigned int c;
michael@0 848 {
michael@0 849 STATUS s;
michael@0 850 const KEYMAP *kp;
michael@0 851
michael@0 852 if (rl_meta_chars && ISMETA(c)) {
michael@0 853 Pushed = 1;
michael@0 854 PushBack = UNMETA(c);
michael@0 855 return meta();
michael@0 856 }
michael@0 857 for (kp = Map; kp->Function; kp++)
michael@0 858 if (kp->Key == c)
michael@0 859 break;
michael@0 860 s = kp->Function ? (*kp->Function)() : insert_char((int)c);
michael@0 861 if (!Pushed)
michael@0 862 /* No pushback means no repeat count; hacky, but true. */
michael@0 863 Repeat = NO_ARG;
michael@0 864 return s;
michael@0 865 }
michael@0 866
michael@0 867 STATIC STATUS
michael@0 868 TTYspecial(c)
michael@0 869 unsigned int c;
michael@0 870 {
michael@0 871 if (ISMETA(c))
michael@0 872 return CSdispatch;
michael@0 873
michael@0 874 if (c == rl_erase || (int)c == DEL)
michael@0 875 return bk_del_char();
michael@0 876 if (c == rl_kill) {
michael@0 877 if (Point != 0) {
michael@0 878 Point = 0;
michael@0 879 reposition();
michael@0 880 }
michael@0 881 Repeat = NO_ARG;
michael@0 882 return kill_line();
michael@0 883 }
michael@0 884 if (c == rl_eof && Point == 0 && End == 0)
michael@0 885 return CSeof;
michael@0 886 if (c == rl_intr) {
michael@0 887 Signal = SIGINT;
michael@0 888 return CSsignal;
michael@0 889 }
michael@0 890 if (c == rl_quit) {
michael@0 891 Signal = SIGQUIT;
michael@0 892 return CSeof;
michael@0 893 }
michael@0 894
michael@0 895 return CSdispatch;
michael@0 896 }
michael@0 897
michael@0 898 STATIC CHAR *
michael@0 899 editinput()
michael@0 900 {
michael@0 901 unsigned int c;
michael@0 902
michael@0 903 Repeat = NO_ARG;
michael@0 904 OldPoint = Point = Mark = End = 0;
michael@0 905 Line[0] = '\0';
michael@0 906
michael@0 907 Signal = -1;
michael@0 908 while ((int)(c = TTYget()) != EOF)
michael@0 909 switch (TTYspecial(c)) {
michael@0 910 case CSdone:
michael@0 911 return Line;
michael@0 912 case CSeof:
michael@0 913 return NULL;
michael@0 914 case CSsignal:
michael@0 915 return (CHAR *)"";
michael@0 916 case CSmove:
michael@0 917 reposition();
michael@0 918 break;
michael@0 919 case CSdispatch:
michael@0 920 switch (emacs(c)) {
michael@0 921 case CSdone:
michael@0 922 return Line;
michael@0 923 case CSeof:
michael@0 924 return NULL;
michael@0 925 case CSsignal:
michael@0 926 return (CHAR *)"";
michael@0 927 case CSmove:
michael@0 928 reposition();
michael@0 929 break;
michael@0 930 case CSdispatch:
michael@0 931 case CSstay:
michael@0 932 break;
michael@0 933 }
michael@0 934 break;
michael@0 935 case CSstay:
michael@0 936 break;
michael@0 937 }
michael@0 938 if (strlen((char *)Line))
michael@0 939 return Line;
michael@0 940 free(Line);
michael@0 941 return NULL;
michael@0 942 }
michael@0 943
michael@0 944 STATIC void
michael@0 945 hist_add(p)
michael@0 946 CHAR *p;
michael@0 947 {
michael@0 948 int i;
michael@0 949
michael@0 950 if ((p = (CHAR *)strdup((char *)p)) == NULL)
michael@0 951 return;
michael@0 952 if (H.Size < HIST_SIZE)
michael@0 953 H.Lines[H.Size++] = p;
michael@0 954 else {
michael@0 955 DISPOSE(H.Lines[0]);
michael@0 956 for (i = 0; i < HIST_SIZE - 1; i++)
michael@0 957 H.Lines[i] = H.Lines[i + 1];
michael@0 958 H.Lines[i] = p;
michael@0 959 }
michael@0 960 H.Pos = H.Size - 1;
michael@0 961 }
michael@0 962
michael@0 963 /*
michael@0 964 ** For compatibility with FSF readline.
michael@0 965 */
michael@0 966 /* ARGSUSED0 */
michael@0 967 void
michael@0 968 rl_reset_terminal(p)
michael@0 969 char *p;
michael@0 970 {
michael@0 971 (void)p;
michael@0 972 }
michael@0 973
michael@0 974 void
michael@0 975 rl_initialize()
michael@0 976 {
michael@0 977 }
michael@0 978
michael@0 979 char *
michael@0 980 readline(prompt)
michael@0 981 CONST char *prompt;
michael@0 982 {
michael@0 983 CHAR *line;
michael@0 984 int s;
michael@0 985
michael@0 986 if (Line == NULL) {
michael@0 987 Length = MEM_INC;
michael@0 988 if ((Line = NEW(CHAR, Length)) == NULL)
michael@0 989 return NULL;
michael@0 990 }
michael@0 991
michael@0 992 TTYinfo();
michael@0 993 rl_ttyset(0);
michael@0 994 hist_add(NIL);
michael@0 995 ScreenSize = SCREEN_INC;
michael@0 996 Screen = NEW(char, ScreenSize);
michael@0 997 Prompt = prompt ? prompt : (char *)NIL;
michael@0 998 TTYputs((CONST CHAR *)Prompt);
michael@0 999 if ((line = editinput()) != NULL) {
michael@0 1000 line = (CHAR *)strdup((char *)line);
michael@0 1001 TTYputs((CONST CHAR *)NEWLINE);
michael@0 1002 TTYflush();
michael@0 1003 }
michael@0 1004 rl_ttyset(1);
michael@0 1005 DISPOSE(Screen);
michael@0 1006 DISPOSE(H.Lines[--H.Size]);
michael@0 1007 if (Signal > 0) {
michael@0 1008 s = Signal;
michael@0 1009 Signal = 0;
michael@0 1010 (void)kill(getpid(), s);
michael@0 1011 }
michael@0 1012 return (char *)line;
michael@0 1013 }
michael@0 1014
michael@0 1015 void
michael@0 1016 add_history(p)
michael@0 1017 char *p;
michael@0 1018 {
michael@0 1019 if (p == NULL || *p == '\0')
michael@0 1020 return;
michael@0 1021
michael@0 1022 #if defined(UNIQUE_HISTORY)
michael@0 1023 if (H.Size && strcmp(p, (char *)H.Lines[H.Size - 1]) == 0)
michael@0 1024 return;
michael@0 1025 #endif /* defined(UNIQUE_HISTORY) */
michael@0 1026 hist_add((CHAR *)p);
michael@0 1027 }
michael@0 1028
michael@0 1029
michael@0 1030 STATIC STATUS
michael@0 1031 beg_line()
michael@0 1032 {
michael@0 1033 if (Point) {
michael@0 1034 Point = 0;
michael@0 1035 return CSmove;
michael@0 1036 }
michael@0 1037 return CSstay;
michael@0 1038 }
michael@0 1039
michael@0 1040 STATIC STATUS
michael@0 1041 del_char()
michael@0 1042 {
michael@0 1043 return delete_string(Repeat == NO_ARG ? 1 : Repeat);
michael@0 1044 }
michael@0 1045
michael@0 1046 STATIC STATUS
michael@0 1047 end_line()
michael@0 1048 {
michael@0 1049 if (Point != End) {
michael@0 1050 Point = End;
michael@0 1051 return CSmove;
michael@0 1052 }
michael@0 1053 return CSstay;
michael@0 1054 }
michael@0 1055
michael@0 1056 STATIC STATUS
michael@0 1057 accept_line()
michael@0 1058 {
michael@0 1059 Line[End] = '\0';
michael@0 1060 return CSdone;
michael@0 1061 }
michael@0 1062
michael@0 1063 STATIC STATUS
michael@0 1064 transpose()
michael@0 1065 {
michael@0 1066 CHAR c;
michael@0 1067
michael@0 1068 if (Point) {
michael@0 1069 if (Point == End)
michael@0 1070 left(CSmove);
michael@0 1071 c = Line[Point - 1];
michael@0 1072 left(CSstay);
michael@0 1073 Line[Point - 1] = Line[Point];
michael@0 1074 TTYshow(Line[Point - 1]);
michael@0 1075 Line[Point++] = c;
michael@0 1076 TTYshow(c);
michael@0 1077 }
michael@0 1078 return CSstay;
michael@0 1079 }
michael@0 1080
michael@0 1081 STATIC STATUS
michael@0 1082 quote()
michael@0 1083 {
michael@0 1084 unsigned int c;
michael@0 1085
michael@0 1086 return (int)(c = TTYget()) == EOF ? CSeof : insert_char((int)c);
michael@0 1087 }
michael@0 1088
michael@0 1089 STATIC STATUS
michael@0 1090 wipe()
michael@0 1091 {
michael@0 1092 int i;
michael@0 1093
michael@0 1094 if (Mark > End)
michael@0 1095 return ring_bell();
michael@0 1096
michael@0 1097 if (Point > Mark) {
michael@0 1098 i = Point;
michael@0 1099 Point = Mark;
michael@0 1100 Mark = i;
michael@0 1101 reposition();
michael@0 1102 }
michael@0 1103
michael@0 1104 return delete_string(Mark - Point);
michael@0 1105 }
michael@0 1106
michael@0 1107 STATIC STATUS
michael@0 1108 mk_set()
michael@0 1109 {
michael@0 1110 Mark = Point;
michael@0 1111 return CSstay;
michael@0 1112 }
michael@0 1113
michael@0 1114 STATIC STATUS
michael@0 1115 exchange()
michael@0 1116 {
michael@0 1117 unsigned int c;
michael@0 1118
michael@0 1119 if ((c = TTYget()) != CTL('X'))
michael@0 1120 return (int)c == EOF ? CSeof : ring_bell();
michael@0 1121
michael@0 1122 if ((int)(c = Mark) <= End) {
michael@0 1123 Mark = Point;
michael@0 1124 Point = c;
michael@0 1125 return CSmove;
michael@0 1126 }
michael@0 1127 return CSstay;
michael@0 1128 }
michael@0 1129
michael@0 1130 STATIC STATUS
michael@0 1131 yank()
michael@0 1132 {
michael@0 1133 if (Yanked && *Yanked)
michael@0 1134 return insert_string(Yanked);
michael@0 1135 return CSstay;
michael@0 1136 }
michael@0 1137
michael@0 1138 STATIC STATUS
michael@0 1139 copy_region()
michael@0 1140 {
michael@0 1141 if (Mark > End)
michael@0 1142 return ring_bell();
michael@0 1143
michael@0 1144 if (Point > Mark)
michael@0 1145 save_yank(Mark, Point - Mark);
michael@0 1146 else
michael@0 1147 save_yank(Point, Mark - Point);
michael@0 1148
michael@0 1149 return CSstay;
michael@0 1150 }
michael@0 1151
michael@0 1152 STATIC STATUS
michael@0 1153 move_to_char()
michael@0 1154 {
michael@0 1155 unsigned int c;
michael@0 1156 int i;
michael@0 1157 CHAR *p;
michael@0 1158
michael@0 1159 if ((int)(c = TTYget()) == EOF)
michael@0 1160 return CSeof;
michael@0 1161 for (i = Point + 1, p = &Line[i]; i < End; i++, p++)
michael@0 1162 if (*p == c) {
michael@0 1163 Point = i;
michael@0 1164 return CSmove;
michael@0 1165 }
michael@0 1166 return CSstay;
michael@0 1167 }
michael@0 1168
michael@0 1169 STATIC STATUS
michael@0 1170 fd_word()
michael@0 1171 {
michael@0 1172 return do_forward(CSmove);
michael@0 1173 }
michael@0 1174
michael@0 1175 STATIC STATUS
michael@0 1176 fd_kill_word()
michael@0 1177 {
michael@0 1178 int i;
michael@0 1179
michael@0 1180 (void)do_forward(CSstay);
michael@0 1181 if (OldPoint != Point) {
michael@0 1182 i = Point - OldPoint;
michael@0 1183 Point = OldPoint;
michael@0 1184 return delete_string(i);
michael@0 1185 }
michael@0 1186 return CSstay;
michael@0 1187 }
michael@0 1188
michael@0 1189 STATIC STATUS
michael@0 1190 bk_word()
michael@0 1191 {
michael@0 1192 int i;
michael@0 1193 CHAR *p;
michael@0 1194
michael@0 1195 i = 0;
michael@0 1196 do {
michael@0 1197 for (p = &Line[Point]; p > Line && !isalnum(p[-1]); p--)
michael@0 1198 left(CSmove);
michael@0 1199
michael@0 1200 for (; p > Line && p[-1] != ' ' && isalnum(p[-1]); p--)
michael@0 1201 left(CSmove);
michael@0 1202
michael@0 1203 if (Point == 0)
michael@0 1204 break;
michael@0 1205 } while (++i < Repeat);
michael@0 1206
michael@0 1207 return CSstay;
michael@0 1208 }
michael@0 1209
michael@0 1210 STATIC STATUS
michael@0 1211 bk_kill_word()
michael@0 1212 {
michael@0 1213 (void)bk_word();
michael@0 1214 if (OldPoint != Point)
michael@0 1215 return delete_string(OldPoint - Point);
michael@0 1216 return CSstay;
michael@0 1217 }
michael@0 1218
michael@0 1219 STATIC int
michael@0 1220 argify(line, avp)
michael@0 1221 CHAR *line;
michael@0 1222 CHAR ***avp;
michael@0 1223 {
michael@0 1224 CHAR *c;
michael@0 1225 CHAR **p;
michael@0 1226 CHAR **new;
michael@0 1227 int ac;
michael@0 1228 int i;
michael@0 1229
michael@0 1230 i = MEM_INC;
michael@0 1231 if ((*avp = p = NEW(CHAR*, i))== NULL)
michael@0 1232 return 0;
michael@0 1233
michael@0 1234 for (c = line; isspace(*c); c++)
michael@0 1235 continue;
michael@0 1236 if (*c == '\n' || *c == '\0')
michael@0 1237 return 0;
michael@0 1238
michael@0 1239 for (ac = 0, p[ac++] = c; *c && *c != '\n'; ) {
michael@0 1240 if (isspace(*c)) {
michael@0 1241 *c++ = '\0';
michael@0 1242 if (*c && *c != '\n') {
michael@0 1243 if (ac + 1 == i) {
michael@0 1244 new = NEW(CHAR*, i + MEM_INC);
michael@0 1245 if (new == NULL) {
michael@0 1246 p[ac] = NULL;
michael@0 1247 return ac;
michael@0 1248 }
michael@0 1249 COPYFROMTO(new, p, i * sizeof (char **));
michael@0 1250 i += MEM_INC;
michael@0 1251 DISPOSE(p);
michael@0 1252 *avp = p = new;
michael@0 1253 }
michael@0 1254 p[ac++] = c;
michael@0 1255 }
michael@0 1256 }
michael@0 1257 else
michael@0 1258 c++;
michael@0 1259 }
michael@0 1260 *c = '\0';
michael@0 1261 p[ac] = NULL;
michael@0 1262 return ac;
michael@0 1263 }
michael@0 1264
michael@0 1265 STATIC STATUS
michael@0 1266 last_argument()
michael@0 1267 {
michael@0 1268 CHAR **av;
michael@0 1269 CHAR *p;
michael@0 1270 STATUS s;
michael@0 1271 int ac;
michael@0 1272
michael@0 1273 if (H.Size == 1 || (p = H.Lines[H.Size - 2]) == NULL)
michael@0 1274 return ring_bell();
michael@0 1275
michael@0 1276 if ((p = (CHAR *)strdup((char *)p)) == NULL)
michael@0 1277 return CSstay;
michael@0 1278 ac = argify(p, &av);
michael@0 1279
michael@0 1280 if (Repeat != NO_ARG)
michael@0 1281 s = Repeat < ac ? insert_string(av[Repeat]) : ring_bell();
michael@0 1282 else
michael@0 1283 s = ac ? insert_string(av[ac - 1]) : CSstay;
michael@0 1284
michael@0 1285 if (ac)
michael@0 1286 DISPOSE(av);
michael@0 1287 DISPOSE(p);
michael@0 1288 return s;
michael@0 1289 }
michael@0 1290
michael@0 1291 STATIC CONST KEYMAP Map[32] = {
michael@0 1292 { CTL('@'), ring_bell },
michael@0 1293 { CTL('A'), beg_line },
michael@0 1294 { CTL('B'), bk_char },
michael@0 1295 { CTL('D'), del_char },
michael@0 1296 { CTL('E'), end_line },
michael@0 1297 { CTL('F'), fd_char },
michael@0 1298 { CTL('G'), ring_bell },
michael@0 1299 { CTL('H'), bk_del_char },
michael@0 1300 { CTL('J'), accept_line },
michael@0 1301 { CTL('K'), kill_line },
michael@0 1302 { CTL('L'), redisplay },
michael@0 1303 { CTL('M'), accept_line },
michael@0 1304 { CTL('N'), h_next },
michael@0 1305 { CTL('O'), ring_bell },
michael@0 1306 { CTL('P'), h_prev },
michael@0 1307 { CTL('Q'), ring_bell },
michael@0 1308 { CTL('R'), h_search },
michael@0 1309 { CTL('S'), ring_bell },
michael@0 1310 { CTL('T'), transpose },
michael@0 1311 { CTL('U'), ring_bell },
michael@0 1312 { CTL('V'), quote },
michael@0 1313 { CTL('W'), wipe },
michael@0 1314 { CTL('X'), exchange },
michael@0 1315 { CTL('Y'), yank },
michael@0 1316 { CTL('Z'), ring_bell },
michael@0 1317 { CTL('['), meta },
michael@0 1318 { CTL(']'), move_to_char },
michael@0 1319 { CTL('^'), ring_bell },
michael@0 1320 { CTL('_'), ring_bell },
michael@0 1321 { 0, NULL }
michael@0 1322 };
michael@0 1323
michael@0 1324 STATIC CONST KEYMAP MetaMap[16]= {
michael@0 1325 { CTL('H'), bk_kill_word },
michael@0 1326 { DEL, bk_kill_word },
michael@0 1327 { ' ', mk_set },
michael@0 1328 { '.', last_argument },
michael@0 1329 { '<', h_first },
michael@0 1330 { '>', h_last },
michael@0 1331 { 'b', bk_word },
michael@0 1332 { 'd', fd_kill_word },
michael@0 1333 { 'f', fd_word },
michael@0 1334 { 'l', case_down_word },
michael@0 1335 { 'm', toggle_meta_mode },
michael@0 1336 { 'u', case_up_word },
michael@0 1337 { 'y', yank },
michael@0 1338 { 'w', copy_region },
michael@0 1339 { 0, NULL }
michael@0 1340 };
michael@0 1341

mercurial