"Fossies" - the Fresh Open Source Software Archive

Member "tnftp-20200705/libedit/common.c" (4 Jul 2020, 18940 Bytes) of package /linux/privat/tnftp-20200705.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "common.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 20151004_vs_20200705.

    1 /*  $NetBSD: common.c,v 1.8 2020/07/04 13:43:21 lukem Exp $ */
    2 /*  from    NetBSD: common.c,v 1.49 2020/03/30 06:54:37 ryo Exp */
    3 
    4 /*-
    5  * Copyright (c) 1992, 1993
    6  *  The Regents of the University of California.  All rights reserved.
    7  *
    8  * This code is derived from software contributed to Berkeley by
    9  * Christos Zoulas of Cornell University.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. Neither the name of the University nor the names of its contributors
   20  *    may be used to endorse or promote products derived from this software
   21  *    without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  */
   35 
   36 #include "config.h"
   37 
   38 #if 0 /* tnftp */
   39 #if !defined(lint) && !defined(SCCSID)
   40 #if 0
   41 static char sccsid[] = "@(#)common.c    8.1 (Berkeley) 6/4/93";
   42 #else
   43 __RCSID(" NetBSD: common.c,v 1.49 2020/03/30 06:54:37 ryo Exp  ");
   44 #endif
   45 #endif /* not lint && not SCCSID */
   46 #endif /* tnftp */
   47 
   48 /*
   49  * common.c: Common Editor functions
   50  */
   51 #include <ctype.h>
   52 #include <string.h>
   53 
   54 #include "el.h"
   55 #include "common.h"
   56 #include "fcns.h"
   57 #include "parse.h"
   58 #include "vi.h"
   59 
   60 /* ed_end_of_file():
   61  *  Indicate end of file
   62  *  [^D]
   63  */
   64 libedit_private el_action_t
   65 /*ARGSUSED*/
   66 ed_end_of_file(EditLine *el, wint_t c __attribute__((__unused__)))
   67 {
   68 
   69     re_goto_bottom(el);
   70     *el->el_line.lastchar = '\0';
   71     return CC_EOF;
   72 }
   73 
   74 
   75 /* ed_insert():
   76  *  Add character to the line
   77  *  Insert a character [bound to all insert keys]
   78  */
   79 libedit_private el_action_t
   80 ed_insert(EditLine *el, wint_t c)
   81 {
   82     int count = el->el_state.argument;
   83 
   84     if (c == '\0')
   85         return CC_ERROR;
   86 
   87     if (el->el_line.lastchar + el->el_state.argument >=
   88         el->el_line.limit) {
   89         /* end of buffer space, try to allocate more */
   90         if (!ch_enlargebufs(el, (size_t) count))
   91             return CC_ERROR;    /* error allocating more */
   92     }
   93 
   94     if (count == 1) {
   95         if (el->el_state.inputmode == MODE_INSERT
   96             || el->el_line.cursor >= el->el_line.lastchar)
   97             c_insert(el, 1);
   98 
   99         *el->el_line.cursor++ = c;
  100         re_fastaddc(el);        /* fast refresh for one char. */
  101     } else {
  102         if (el->el_state.inputmode != MODE_REPLACE_1)
  103             c_insert(el, el->el_state.argument);
  104 
  105         while (count-- && el->el_line.cursor < el->el_line.lastchar)
  106             *el->el_line.cursor++ = c;
  107         re_refresh(el);
  108     }
  109 
  110     if (el->el_state.inputmode == MODE_REPLACE_1)
  111         return vi_command_mode(el, 0);
  112 
  113     return CC_NORM;
  114 }
  115 
  116 
  117 /* ed_delete_prev_word():
  118  *  Delete from beginning of current word to cursor
  119  *  [M-^?] [^W]
  120  */
  121 libedit_private el_action_t
  122 /*ARGSUSED*/
  123 ed_delete_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
  124 {
  125     wchar_t *cp, *p, *kp;
  126 
  127     if (el->el_line.cursor == el->el_line.buffer)
  128         return CC_ERROR;
  129 
  130     cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
  131         el->el_state.argument, ce__isword);
  132 
  133     for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
  134         *kp++ = *p;
  135     el->el_chared.c_kill.last = kp;
  136 
  137     c_delbefore(el, (int)(el->el_line.cursor - cp));/* delete before dot */
  138     el->el_line.cursor = cp;
  139     if (el->el_line.cursor < el->el_line.buffer)
  140         el->el_line.cursor = el->el_line.buffer; /* bounds check */
  141     return CC_REFRESH;
  142 }
  143 
  144 
  145 /* ed_delete_next_char():
  146  *  Delete character under cursor
  147  *  [^D] [x]
  148  */
  149 libedit_private el_action_t
  150 /*ARGSUSED*/
  151 ed_delete_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
  152 {
  153 #ifdef DEBUG_EDIT
  154 #define EL  el->el_line
  155     (void) fprintf(el->el_errfile,
  156         "\nD(b: %p(%ls)  c: %p(%ls) last: %p(%ls) limit: %p(%ls)\n",
  157         EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar,
  158         EL.lastchar, EL.limit, EL.limit);
  159 #endif
  160     if (el->el_line.cursor == el->el_line.lastchar) {
  161             /* if I'm at the end */
  162         if (el->el_map.type == MAP_VI) {
  163             if (el->el_line.cursor == el->el_line.buffer) {
  164                 /* if I'm also at the beginning */
  165 #ifdef KSHVI
  166                 return CC_ERROR;
  167 #else
  168                 /* then do an EOF */
  169                 terminal_writec(el, c);
  170                 return CC_EOF;
  171 #endif
  172             } else {
  173 #ifdef KSHVI
  174                 el->el_line.cursor--;
  175 #else
  176                 return CC_ERROR;
  177 #endif
  178             }
  179         } else
  180                 return CC_ERROR;
  181     }
  182     c_delafter(el, el->el_state.argument);  /* delete after dot */
  183     if (el->el_map.type == MAP_VI &&
  184         el->el_line.cursor >= el->el_line.lastchar &&
  185         el->el_line.cursor > el->el_line.buffer)
  186             /* bounds check */
  187         el->el_line.cursor = el->el_line.lastchar - 1;
  188     return CC_REFRESH;
  189 }
  190 
  191 
  192 /* ed_kill_line():
  193  *  Cut to the end of line
  194  *  [^K] [^K]
  195  */
  196 libedit_private el_action_t
  197 /*ARGSUSED*/
  198 ed_kill_line(EditLine *el, wint_t c __attribute__((__unused__)))
  199 {
  200     wchar_t *kp, *cp;
  201 
  202     cp = el->el_line.cursor;
  203     kp = el->el_chared.c_kill.buf;
  204     while (cp < el->el_line.lastchar)
  205         *kp++ = *cp++;  /* copy it */
  206     el->el_chared.c_kill.last = kp;
  207             /* zap! -- delete to end */
  208     el->el_line.lastchar = el->el_line.cursor;
  209     return CC_REFRESH;
  210 }
  211 
  212 
  213 /* ed_move_to_end():
  214  *  Move cursor to the end of line
  215  *  [^E] [^E]
  216  */
  217 libedit_private el_action_t
  218 /*ARGSUSED*/
  219 ed_move_to_end(EditLine *el, wint_t c __attribute__((__unused__)))
  220 {
  221 
  222     el->el_line.cursor = el->el_line.lastchar;
  223     if (el->el_map.type == MAP_VI) {
  224         if (el->el_chared.c_vcmd.action != NOP) {
  225             cv_delfini(el);
  226             return CC_REFRESH;
  227         }
  228 #ifdef VI_MOVE
  229         el->el_line.cursor--;
  230 #endif
  231     }
  232     return CC_CURSOR;
  233 }
  234 
  235 
  236 /* ed_move_to_beg():
  237  *  Move cursor to the beginning of line
  238  *  [^A] [^A]
  239  */
  240 libedit_private el_action_t
  241 /*ARGSUSED*/
  242 ed_move_to_beg(EditLine *el, wint_t c __attribute__((__unused__)))
  243 {
  244 
  245     el->el_line.cursor = el->el_line.buffer;
  246 
  247     if (el->el_map.type == MAP_VI) {
  248             /* We want FIRST non space character */
  249         while (iswspace(*el->el_line.cursor))
  250             el->el_line.cursor++;
  251         if (el->el_chared.c_vcmd.action != NOP) {
  252             cv_delfini(el);
  253             return CC_REFRESH;
  254         }
  255     }
  256     return CC_CURSOR;
  257 }
  258 
  259 
  260 /* ed_transpose_chars():
  261  *  Exchange the character to the left of the cursor with the one under it
  262  *  [^T] [^T]
  263  */
  264 libedit_private el_action_t
  265 ed_transpose_chars(EditLine *el, wint_t c)
  266 {
  267 
  268     if (el->el_line.cursor < el->el_line.lastchar) {
  269         if (el->el_line.lastchar <= &el->el_line.buffer[1])
  270             return CC_ERROR;
  271         else
  272             el->el_line.cursor++;
  273     }
  274     if (el->el_line.cursor > &el->el_line.buffer[1]) {
  275         /* must have at least two chars entered */
  276         c = el->el_line.cursor[-2];
  277         el->el_line.cursor[-2] = el->el_line.cursor[-1];
  278         el->el_line.cursor[-1] = c;
  279         return CC_REFRESH;
  280     } else
  281         return CC_ERROR;
  282 }
  283 
  284 
  285 /* ed_next_char():
  286  *  Move to the right one character
  287  *  [^F] [^F]
  288  */
  289 libedit_private el_action_t
  290 /*ARGSUSED*/
  291 ed_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
  292 {
  293     wchar_t *lim = el->el_line.lastchar;
  294 
  295     if (el->el_line.cursor >= lim ||
  296         (el->el_line.cursor == lim - 1 &&
  297         el->el_map.type == MAP_VI &&
  298         el->el_chared.c_vcmd.action == NOP))
  299         return CC_ERROR;
  300 
  301     el->el_line.cursor += el->el_state.argument;
  302     if (el->el_line.cursor > lim)
  303         el->el_line.cursor = lim;
  304 
  305     if (el->el_map.type == MAP_VI)
  306         if (el->el_chared.c_vcmd.action != NOP) {
  307             cv_delfini(el);
  308             return CC_REFRESH;
  309         }
  310     return CC_CURSOR;
  311 }
  312 
  313 
  314 /* ed_prev_word():
  315  *  Move to the beginning of the current word
  316  *  [M-b] [b]
  317  */
  318 libedit_private el_action_t
  319 /*ARGSUSED*/
  320 ed_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
  321 {
  322 
  323     if (el->el_line.cursor == el->el_line.buffer)
  324         return CC_ERROR;
  325 
  326     el->el_line.cursor = c__prev_word(el->el_line.cursor,
  327         el->el_line.buffer,
  328         el->el_state.argument,
  329         ce__isword);
  330 
  331     if (el->el_map.type == MAP_VI)
  332         if (el->el_chared.c_vcmd.action != NOP) {
  333             cv_delfini(el);
  334             return CC_REFRESH;
  335         }
  336     return CC_CURSOR;
  337 }
  338 
  339 
  340 /* ed_prev_char():
  341  *  Move to the left one character
  342  *  [^B] [^B]
  343  */
  344 libedit_private el_action_t
  345 /*ARGSUSED*/
  346 ed_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
  347 {
  348 
  349     if (el->el_line.cursor > el->el_line.buffer) {
  350         el->el_line.cursor -= el->el_state.argument;
  351         if (el->el_line.cursor < el->el_line.buffer)
  352             el->el_line.cursor = el->el_line.buffer;
  353 
  354         if (el->el_map.type == MAP_VI)
  355             if (el->el_chared.c_vcmd.action != NOP) {
  356                 cv_delfini(el);
  357                 return CC_REFRESH;
  358             }
  359         return CC_CURSOR;
  360     } else
  361         return CC_ERROR;
  362 }
  363 
  364 
  365 /* ed_quoted_insert():
  366  *  Add the next character typed verbatim
  367  *  [^V] [^V]
  368  */
  369 libedit_private el_action_t
  370 /*ARGSUSED*/
  371 ed_quoted_insert(EditLine *el, wint_t c __attribute__((__unused__)))
  372 {
  373     int num;
  374     wchar_t ch;
  375 
  376     tty_quotemode(el);
  377     num = el_wgetc(el, &ch);
  378     tty_noquotemode(el);
  379     if (num == 1)
  380         return ed_insert(el, ch);
  381     else
  382         return ed_end_of_file(el, 0);
  383 }
  384 
  385 
  386 /* ed_digit():
  387  *  Adds to argument or enters a digit
  388  */
  389 libedit_private el_action_t
  390 ed_digit(EditLine *el, wint_t c)
  391 {
  392 
  393     if (!iswdigit(c))
  394         return CC_ERROR;
  395 
  396     if (el->el_state.doingarg) {
  397             /* if doing an arg, add this in... */
  398         if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
  399             el->el_state.argument = c - '0';
  400         else {
  401             if (el->el_state.argument > 1000000)
  402                 return CC_ERROR;
  403             el->el_state.argument =
  404                 (el->el_state.argument * 10) + (c - '0');
  405         }
  406         return CC_ARGHACK;
  407     }
  408 
  409     return ed_insert(el, c);
  410 }
  411 
  412 
  413 /* ed_argument_digit():
  414  *  Digit that starts argument
  415  *  For ESC-n
  416  */
  417 libedit_private el_action_t
  418 ed_argument_digit(EditLine *el, wint_t c)
  419 {
  420 
  421     if (!iswdigit(c))
  422         return CC_ERROR;
  423 
  424     if (el->el_state.doingarg) {
  425         if (el->el_state.argument > 1000000)
  426             return CC_ERROR;
  427         el->el_state.argument = (el->el_state.argument * 10) +
  428             (c - '0');
  429     } else {        /* else starting an argument */
  430         el->el_state.argument = c - '0';
  431         el->el_state.doingarg = 1;
  432     }
  433     return CC_ARGHACK;
  434 }
  435 
  436 
  437 /* ed_unassigned():
  438  *  Indicates unbound character
  439  *  Bound to keys that are not assigned
  440  */
  441 libedit_private el_action_t
  442 /*ARGSUSED*/
  443 ed_unassigned(EditLine *el __attribute__((__unused__)),
  444     wint_t c __attribute__((__unused__)))
  445 {
  446 
  447     return CC_ERROR;
  448 }
  449 
  450 
  451 /* ed_ignore():
  452  *  Input characters that have no effect
  453  *  [^C ^O ^Q ^S ^Z ^\ ^]] [^C ^O ^Q ^S ^\]
  454  */
  455 libedit_private el_action_t
  456 /*ARGSUSED*/
  457 ed_ignore(EditLine *el __attribute__((__unused__)),
  458           wint_t c __attribute__((__unused__)))
  459 {
  460 
  461     return CC_NORM;
  462 }
  463 
  464 
  465 /* ed_newline():
  466  *  Execute command
  467  *  [^J]
  468  */
  469 libedit_private el_action_t
  470 /*ARGSUSED*/
  471 ed_newline(EditLine *el, wint_t c __attribute__((__unused__)))
  472 {
  473 
  474     re_goto_bottom(el);
  475     *el->el_line.lastchar++ = '\n';
  476     *el->el_line.lastchar = '\0';
  477     return CC_NEWLINE;
  478 }
  479 
  480 
  481 /* ed_delete_prev_char():
  482  *  Delete the character to the left of the cursor
  483  *  [^?]
  484  */
  485 libedit_private el_action_t
  486 /*ARGSUSED*/
  487 ed_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
  488 {
  489 
  490     if (el->el_line.cursor <= el->el_line.buffer)
  491         return CC_ERROR;
  492 
  493     c_delbefore(el, el->el_state.argument);
  494     el->el_line.cursor -= el->el_state.argument;
  495     if (el->el_line.cursor < el->el_line.buffer)
  496         el->el_line.cursor = el->el_line.buffer;
  497     return CC_REFRESH;
  498 }
  499 
  500 
  501 /* ed_clear_screen():
  502  *  Clear screen leaving current line at the top
  503  *  [^L]
  504  */
  505 libedit_private el_action_t
  506 /*ARGSUSED*/
  507 ed_clear_screen(EditLine *el, wint_t c __attribute__((__unused__)))
  508 {
  509 
  510     terminal_clear_screen(el);  /* clear the whole real screen */
  511     re_clear_display(el);   /* reset everything */
  512     return CC_REFRESH;
  513 }
  514 
  515 
  516 /* ed_redisplay():
  517  *  Redisplay everything
  518  *  ^R
  519  */
  520 libedit_private el_action_t
  521 /*ARGSUSED*/
  522 ed_redisplay(EditLine *el __attribute__((__unused__)),
  523          wint_t c __attribute__((__unused__)))
  524 {
  525 
  526     return CC_REDISPLAY;
  527 }
  528 
  529 
  530 /* ed_start_over():
  531  *  Erase current line and start from scratch
  532  *  [^G]
  533  */
  534 libedit_private el_action_t
  535 /*ARGSUSED*/
  536 ed_start_over(EditLine *el, wint_t c __attribute__((__unused__)))
  537 {
  538 
  539     ch_reset(el);
  540     return CC_REFRESH;
  541 }
  542 
  543 
  544 /* ed_sequence_lead_in():
  545  *  First character in a bound sequence
  546  *  Placeholder for external keys
  547  */
  548 libedit_private el_action_t
  549 /*ARGSUSED*/
  550 ed_sequence_lead_in(EditLine *el __attribute__((__unused__)),
  551             wint_t c __attribute__((__unused__)))
  552 {
  553 
  554     return CC_NORM;
  555 }
  556 
  557 
  558 /* ed_prev_history():
  559  *  Move to the previous history line
  560  *  [^P] [k]
  561  */
  562 libedit_private el_action_t
  563 /*ARGSUSED*/
  564 ed_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
  565 {
  566     char beep = 0;
  567     int sv_event = el->el_history.eventno;
  568 
  569     el->el_chared.c_undo.len = -1;
  570     *el->el_line.lastchar = '\0';       /* just in case */
  571 
  572     if (el->el_history.eventno == 0) {  /* save the current buffer
  573                          * away */
  574         (void) wcsncpy(el->el_history.buf, el->el_line.buffer,
  575             EL_BUFSIZ);
  576         el->el_history.last = el->el_history.buf +
  577             (el->el_line.lastchar - el->el_line.buffer);
  578     }
  579     el->el_history.eventno += el->el_state.argument;
  580 
  581     if (hist_get(el) == CC_ERROR) {
  582         if (el->el_map.type == MAP_VI) {
  583             el->el_history.eventno = sv_event;
  584         }
  585         beep = 1;
  586         /* el->el_history.eventno was fixed by first call */
  587         (void) hist_get(el);
  588     }
  589     if (beep)
  590         return CC_REFRESH_BEEP;
  591     return CC_REFRESH;
  592 }
  593 
  594 
  595 /* ed_next_history():
  596  *  Move to the next history line
  597  *  [^N] [j]
  598  */
  599 libedit_private el_action_t
  600 /*ARGSUSED*/
  601 ed_next_history(EditLine *el, wint_t c __attribute__((__unused__)))
  602 {
  603     el_action_t beep = CC_REFRESH, rval;
  604 
  605     el->el_chared.c_undo.len = -1;
  606     *el->el_line.lastchar = '\0';   /* just in case */
  607 
  608     el->el_history.eventno -= el->el_state.argument;
  609 
  610     if (el->el_history.eventno < 0) {
  611         el->el_history.eventno = 0;
  612         beep = CC_REFRESH_BEEP;
  613     }
  614     rval = hist_get(el);
  615     if (rval == CC_REFRESH)
  616         return beep;
  617     return rval;
  618 
  619 }
  620 
  621 
  622 /* ed_search_prev_history():
  623  *  Search previous in history for a line matching the current
  624  *  next search history [M-P] [K]
  625  */
  626 libedit_private el_action_t
  627 /*ARGSUSED*/
  628 ed_search_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
  629 {
  630     const wchar_t *hp;
  631     int h;
  632     int found = 0;
  633 
  634     el->el_chared.c_vcmd.action = NOP;
  635     el->el_chared.c_undo.len = -1;
  636     *el->el_line.lastchar = '\0';   /* just in case */
  637     if (el->el_history.eventno < 0) {
  638 #ifdef DEBUG_EDIT
  639         (void) fprintf(el->el_errfile,
  640             "e_prev_search_hist(): eventno < 0;\n");
  641 #endif
  642         el->el_history.eventno = 0;
  643         return CC_ERROR;
  644     }
  645     if (el->el_history.eventno == 0) {
  646         (void) wcsncpy(el->el_history.buf, el->el_line.buffer,
  647             EL_BUFSIZ);
  648         el->el_history.last = el->el_history.buf +
  649             (el->el_line.lastchar - el->el_line.buffer);
  650     }
  651     if (el->el_history.ref == NULL)
  652         return CC_ERROR;
  653 
  654     hp = HIST_FIRST(el);
  655     if (hp == NULL)
  656         return CC_ERROR;
  657 
  658     c_setpat(el);       /* Set search pattern !! */
  659 
  660     for (h = 1; h <= el->el_history.eventno; h++)
  661         hp = HIST_NEXT(el);
  662 
  663     while (hp != NULL) {
  664 #ifdef SDEBUG
  665         (void) fprintf(el->el_errfile, "Comparing with \"%ls\"\n", hp);
  666 #endif
  667         if ((wcsncmp(hp, el->el_line.buffer, (size_t)
  668                 (el->el_line.lastchar - el->el_line.buffer)) ||
  669             hp[el->el_line.lastchar - el->el_line.buffer]) &&
  670             c_hmatch(el, hp)) {
  671             found = 1;
  672             break;
  673         }
  674         h++;
  675         hp = HIST_NEXT(el);
  676     }
  677 
  678     if (!found) {
  679 #ifdef SDEBUG
  680         (void) fprintf(el->el_errfile, "not found\n");
  681 #endif
  682         return CC_ERROR;
  683     }
  684     el->el_history.eventno = h;
  685 
  686     return hist_get(el);
  687 }
  688 
  689 
  690 /* ed_search_next_history():
  691  *  Search next in history for a line matching the current
  692  *  [M-N] [J]
  693  */
  694 libedit_private el_action_t
  695 /*ARGSUSED*/
  696 ed_search_next_history(EditLine *el, wint_t c __attribute__((__unused__)))
  697 {
  698     const wchar_t *hp;
  699     int h;
  700     int found = 0;
  701 
  702     el->el_chared.c_vcmd.action = NOP;
  703     el->el_chared.c_undo.len = -1;
  704     *el->el_line.lastchar = '\0';   /* just in case */
  705 
  706     if (el->el_history.eventno == 0)
  707         return CC_ERROR;
  708 
  709     if (el->el_history.ref == NULL)
  710         return CC_ERROR;
  711 
  712     hp = HIST_FIRST(el);
  713     if (hp == NULL)
  714         return CC_ERROR;
  715 
  716     c_setpat(el);       /* Set search pattern !! */
  717 
  718     for (h = 1; h < el->el_history.eventno && hp; h++) {
  719 #ifdef SDEBUG
  720         (void) fprintf(el->el_errfile, "Comparing with \"%ls\"\n", hp);
  721 #endif
  722         if ((wcsncmp(hp, el->el_line.buffer, (size_t)
  723                 (el->el_line.lastchar - el->el_line.buffer)) ||
  724             hp[el->el_line.lastchar - el->el_line.buffer]) &&
  725             c_hmatch(el, hp))
  726             found = h;
  727         hp = HIST_NEXT(el);
  728     }
  729 
  730     if (!found) {       /* is it the current history number? */
  731         if (!c_hmatch(el, el->el_history.buf)) {
  732 #ifdef SDEBUG
  733             (void) fprintf(el->el_errfile, "not found\n");
  734 #endif
  735             return CC_ERROR;
  736         }
  737     }
  738     el->el_history.eventno = found;
  739 
  740     return hist_get(el);
  741 }
  742 
  743 
  744 /* ed_prev_line():
  745  *  Move up one line
  746  *  Could be [k] [^p]
  747  */
  748 libedit_private el_action_t
  749 /*ARGSUSED*/
  750 ed_prev_line(EditLine *el, wint_t c __attribute__((__unused__)))
  751 {
  752     wchar_t *ptr;
  753     int nchars = c_hpos(el);
  754 
  755     /*
  756          * Move to the line requested
  757          */
  758     if (*(ptr = el->el_line.cursor) == '\n')
  759         ptr--;
  760 
  761     for (; ptr >= el->el_line.buffer; ptr--)
  762         if (*ptr == '\n' && --el->el_state.argument <= 0)
  763             break;
  764 
  765     if (el->el_state.argument > 0)
  766         return CC_ERROR;
  767 
  768     /*
  769          * Move to the beginning of the line
  770          */
  771     for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
  772         continue;
  773 
  774     /*
  775          * Move to the character requested
  776          */
  777     for (ptr++;
  778         nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
  779         ptr++)
  780         continue;
  781 
  782     el->el_line.cursor = ptr;
  783     return CC_CURSOR;
  784 }
  785 
  786 
  787 /* ed_next_line():
  788  *  Move down one line
  789  *  Could be [j] [^n]
  790  */
  791 libedit_private el_action_t
  792 /*ARGSUSED*/
  793 ed_next_line(EditLine *el, wint_t c __attribute__((__unused__)))
  794 {
  795     wchar_t *ptr;
  796     int nchars = c_hpos(el);
  797 
  798     /*
  799          * Move to the line requested
  800          */
  801     for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
  802         if (*ptr == '\n' && --el->el_state.argument <= 0)
  803             break;
  804 
  805     if (el->el_state.argument > 0)
  806         return CC_ERROR;
  807 
  808     /*
  809          * Move to the character requested
  810          */
  811     for (ptr++;
  812         nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
  813         ptr++)
  814         continue;
  815 
  816     el->el_line.cursor = ptr;
  817     return CC_CURSOR;
  818 }
  819 
  820 
  821 /* ed_command():
  822  *  Editline extended command
  823  *  [M-X] [:]
  824  */
  825 libedit_private el_action_t
  826 /*ARGSUSED*/
  827 ed_command(EditLine *el, wint_t c __attribute__((__unused__)))
  828 {
  829     wchar_t tmpbuf[EL_BUFSIZ];
  830     int tmplen;
  831 
  832     tmplen = c_gets(el, tmpbuf, L"\n: ");
  833     terminal__putc(el, '\n');
  834 
  835     if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1)
  836         terminal_beep(el);
  837 
  838     el->el_map.current = el->el_map.key;
  839     re_clear_display(el);
  840     return CC_REFRESH;
  841 }