LCOV - code coverage report
Current view: directory - js/src/editline - editline.c (source / functions) Found Hit Coverage
Test: app.info Lines: 584 0 0.0 %
Date: 2012-06-02 Functions: 67 0 0.0 %

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

Generated by: LCOV version 1.7