"Fossies" - the Fresh Open Source Software Archive

Member "tnftp-20200705/libedit/chared.c" (4 Jul 2020, 16918 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 "chared.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 20151004_vs_20200705.

    1 /*  $NetBSD: chared.c,v 1.9 2020/07/04 13:43:21 lukem Exp $ */
    2 /*  from    NetBSD: chared.c,v 1.59 2019/07/23 10:18:52 christos 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[] = "@(#)chared.c    8.1 (Berkeley) 6/4/93";
   42 #else
   43 __RCSID(" NetBSD: chared.c,v 1.59 2019/07/23 10:18:52 christos Exp  ");
   44 #endif
   45 #endif /* not lint && not SCCSID */
   46 #endif /* tnftp */
   47 
   48 /*
   49  * chared.c: Character editor utilities
   50  */
   51 #if 0 /* tnftp */
   52 #include <ctype.h>
   53 #include <stdlib.h>
   54 #include <string.h>
   55 #endif /* tnftp */
   56 
   57 #include "el.h"
   58 #include "common.h"
   59 #include "fcns.h"
   60 
   61 /* value to leave unused in line buffer */
   62 #define EL_LEAVE    2
   63 
   64 /* cv_undo():
   65  *  Handle state for the vi undo command
   66  */
   67 libedit_private void
   68 cv_undo(EditLine *el)
   69 {
   70     c_undo_t *vu = &el->el_chared.c_undo;
   71     c_redo_t *r = &el->el_chared.c_redo;
   72     size_t size;
   73 
   74     /* Save entire line for undo */
   75     size = (size_t)(el->el_line.lastchar - el->el_line.buffer);
   76     vu->len = (ssize_t)size;
   77     vu->cursor = (int)(el->el_line.cursor - el->el_line.buffer);
   78     (void)memcpy(vu->buf, el->el_line.buffer, size * sizeof(*vu->buf));
   79 
   80     /* save command info for redo */
   81     r->count = el->el_state.doingarg ? el->el_state.argument : 0;
   82     r->action = el->el_chared.c_vcmd.action;
   83     r->pos = r->buf;
   84     r->cmd = el->el_state.thiscmd;
   85     r->ch = el->el_state.thisch;
   86 }
   87 
   88 /* cv_yank():
   89  *  Save yank/delete data for paste
   90  */
   91 libedit_private void
   92 cv_yank(EditLine *el, const wchar_t *ptr, int size)
   93 {
   94     c_kill_t *k = &el->el_chared.c_kill;
   95 
   96     (void)memcpy(k->buf, ptr, (size_t)size * sizeof(*k->buf));
   97     k->last = k->buf + size;
   98 }
   99 
  100 
  101 /* c_insert():
  102  *  Insert num characters
  103  */
  104 libedit_private void
  105 c_insert(EditLine *el, int num)
  106 {
  107     wchar_t *cp;
  108 
  109     if (el->el_line.lastchar + num >= el->el_line.limit) {
  110         if (!ch_enlargebufs(el, (size_t)num))
  111             return;     /* can't go past end of buffer */
  112     }
  113 
  114     if (el->el_line.cursor < el->el_line.lastchar) {
  115         /* if I must move chars */
  116         for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--)
  117             cp[num] = *cp;
  118     }
  119     el->el_line.lastchar += num;
  120 }
  121 
  122 
  123 /* c_delafter():
  124  *  Delete num characters after the cursor
  125  */
  126 libedit_private void
  127 c_delafter(EditLine *el, int num)
  128 {
  129 
  130     if (el->el_line.cursor + num > el->el_line.lastchar)
  131         num = (int)(el->el_line.lastchar - el->el_line.cursor);
  132 
  133     if (el->el_map.current != el->el_map.emacs) {
  134         cv_undo(el);
  135         cv_yank(el, el->el_line.cursor, num);
  136     }
  137 
  138     if (num > 0) {
  139         wchar_t *cp;
  140 
  141         for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
  142             *cp = cp[num];
  143 
  144         el->el_line.lastchar -= num;
  145     }
  146 }
  147 
  148 
  149 /* c_delafter1():
  150  *  Delete the character after the cursor, do not yank
  151  */
  152 libedit_private void
  153 c_delafter1(EditLine *el)
  154 {
  155     wchar_t *cp;
  156 
  157     for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
  158         *cp = cp[1];
  159 
  160     el->el_line.lastchar--;
  161 }
  162 
  163 
  164 /* c_delbefore():
  165  *  Delete num characters before the cursor
  166  */
  167 libedit_private void
  168 c_delbefore(EditLine *el, int num)
  169 {
  170 
  171     if (el->el_line.cursor - num < el->el_line.buffer)
  172         num = (int)(el->el_line.cursor - el->el_line.buffer);
  173 
  174     if (el->el_map.current != el->el_map.emacs) {
  175         cv_undo(el);
  176         cv_yank(el, el->el_line.cursor - num, num);
  177     }
  178 
  179     if (num > 0) {
  180         wchar_t *cp;
  181 
  182         for (cp = el->el_line.cursor - num;
  183             &cp[num] <= el->el_line.lastchar;
  184             cp++)
  185             *cp = cp[num];
  186 
  187         el->el_line.lastchar -= num;
  188     }
  189 }
  190 
  191 
  192 /* c_delbefore1():
  193  *  Delete the character before the cursor, do not yank
  194  */
  195 libedit_private void
  196 c_delbefore1(EditLine *el)
  197 {
  198     wchar_t *cp;
  199 
  200     for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++)
  201         *cp = cp[1];
  202 
  203     el->el_line.lastchar--;
  204 }
  205 
  206 
  207 /* ce__isword():
  208  *  Return if p is part of a word according to emacs
  209  */
  210 libedit_private int
  211 ce__isword(wint_t p)
  212 {
  213     return iswalnum(p) || wcschr(L"*?_-.[]~=", p) != NULL;
  214 }
  215 
  216 
  217 /* cv__isword():
  218  *  Return if p is part of a word according to vi
  219  */
  220 libedit_private int
  221 cv__isword(wint_t p)
  222 {
  223     if (iswalnum(p) || p == L'_')
  224         return 1;
  225     if (iswgraph(p))
  226         return 2;
  227     return 0;
  228 }
  229 
  230 
  231 /* cv__isWord():
  232  *  Return if p is part of a big word according to vi
  233  */
  234 libedit_private int
  235 cv__isWord(wint_t p)
  236 {
  237     return !iswspace(p);
  238 }
  239 
  240 
  241 /* c__prev_word():
  242  *  Find the previous word
  243  */
  244 libedit_private wchar_t *
  245 c__prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t))
  246 {
  247     p--;
  248 
  249     while (n--) {
  250         while ((p >= low) && !(*wtest)(*p))
  251             p--;
  252         while ((p >= low) && (*wtest)(*p))
  253             p--;
  254     }
  255 
  256     /* cp now points to one character before the word */
  257     p++;
  258     if (p < low)
  259         p = low;
  260     /* cp now points where we want it */
  261     return p;
  262 }
  263 
  264 
  265 /* c__next_word():
  266  *  Find the next word
  267  */
  268 libedit_private wchar_t *
  269 c__next_word(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t))
  270 {
  271     while (n--) {
  272         while ((p < high) && !(*wtest)(*p))
  273             p++;
  274         while ((p < high) && (*wtest)(*p))
  275             p++;
  276     }
  277     if (p > high)
  278         p = high;
  279     /* p now points where we want it */
  280     return p;
  281 }
  282 
  283 /* cv_next_word():
  284  *  Find the next word vi style
  285  */
  286 libedit_private wchar_t *
  287 cv_next_word(EditLine *el, wchar_t *p, wchar_t *high, int n,
  288     int (*wtest)(wint_t))
  289 {
  290     int test;
  291 
  292     while (n--) {
  293         test = (*wtest)(*p);
  294         while ((p < high) && (*wtest)(*p) == test)
  295             p++;
  296         /*
  297          * vi historically deletes with cw only the word preserving the
  298          * trailing whitespace! This is not what 'w' does..
  299          */
  300         if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT))
  301             while ((p < high) && iswspace(*p))
  302                 p++;
  303     }
  304 
  305     /* p now points where we want it */
  306     if (p > high)
  307         return high;
  308     else
  309         return p;
  310 }
  311 
  312 
  313 /* cv_prev_word():
  314  *  Find the previous word vi style
  315  */
  316 libedit_private wchar_t *
  317 cv_prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t))
  318 {
  319     int test;
  320 
  321     p--;
  322     while (n--) {
  323         while ((p > low) && iswspace(*p))
  324             p--;
  325         test = (*wtest)(*p);
  326         while ((p >= low) && (*wtest)(*p) == test)
  327             p--;
  328     }
  329     p++;
  330 
  331     /* p now points where we want it */
  332     if (p < low)
  333         return low;
  334     else
  335         return p;
  336 }
  337 
  338 
  339 /* cv_delfini():
  340  *  Finish vi delete action
  341  */
  342 libedit_private void
  343 cv_delfini(EditLine *el)
  344 {
  345     int size;
  346     int action = el->el_chared.c_vcmd.action;
  347 
  348     if (action & INSERT)
  349         el->el_map.current = el->el_map.key;
  350 
  351     if (el->el_chared.c_vcmd.pos == 0)
  352         /* sanity */
  353         return;
  354 
  355     size = (int)(el->el_line.cursor - el->el_chared.c_vcmd.pos);
  356     if (size == 0)
  357         size = 1;
  358     el->el_line.cursor = el->el_chared.c_vcmd.pos;
  359     if (action & YANK) {
  360         if (size > 0)
  361             cv_yank(el, el->el_line.cursor, size);
  362         else
  363             cv_yank(el, el->el_line.cursor + size, -size);
  364     } else {
  365         if (size > 0) {
  366             c_delafter(el, size);
  367             re_refresh_cursor(el);
  368         } else  {
  369             c_delbefore(el, -size);
  370             el->el_line.cursor += size;
  371         }
  372     }
  373     el->el_chared.c_vcmd.action = NOP;
  374 }
  375 
  376 
  377 /* cv__endword():
  378  *  Go to the end of this word according to vi
  379  */
  380 libedit_private wchar_t *
  381 cv__endword(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t))
  382 {
  383     int test;
  384 
  385     p++;
  386 
  387     while (n--) {
  388         while ((p < high) && iswspace(*p))
  389             p++;
  390 
  391         test = (*wtest)(*p);
  392         while ((p < high) && (*wtest)(*p) == test)
  393             p++;
  394     }
  395     p--;
  396     return p;
  397 }
  398 
  399 /* ch_init():
  400  *  Initialize the character editor
  401  */
  402 libedit_private int
  403 ch_init(EditLine *el)
  404 {
  405     el->el_line.buffer      = el_calloc(EL_BUFSIZ,
  406         sizeof(*el->el_line.buffer));
  407     if (el->el_line.buffer == NULL)
  408         return -1;
  409 
  410     el->el_line.cursor      = el->el_line.buffer;
  411     el->el_line.lastchar        = el->el_line.buffer;
  412     el->el_line.limit       = &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE];
  413 
  414     el->el_chared.c_undo.buf    = el_calloc(EL_BUFSIZ,
  415         sizeof(*el->el_chared.c_undo.buf));
  416     if (el->el_chared.c_undo.buf == NULL)
  417         return -1;
  418     el->el_chared.c_undo.len    = -1;
  419     el->el_chared.c_undo.cursor = 0;
  420     el->el_chared.c_redo.buf    = el_calloc(EL_BUFSIZ,
  421         sizeof(*el->el_chared.c_redo.buf));
  422     if (el->el_chared.c_redo.buf == NULL)
  423         return -1;
  424     el->el_chared.c_redo.pos    = el->el_chared.c_redo.buf;
  425     el->el_chared.c_redo.lim    = el->el_chared.c_redo.buf + EL_BUFSIZ;
  426     el->el_chared.c_redo.cmd    = ED_UNASSIGNED;
  427 
  428     el->el_chared.c_vcmd.action = NOP;
  429     el->el_chared.c_vcmd.pos    = el->el_line.buffer;
  430 
  431     el->el_chared.c_kill.buf    = el_calloc(EL_BUFSIZ,
  432         sizeof(*el->el_chared.c_kill.buf));
  433     if (el->el_chared.c_kill.buf == NULL)
  434         return -1;
  435     el->el_chared.c_kill.mark   = el->el_line.buffer;
  436     el->el_chared.c_kill.last   = el->el_chared.c_kill.buf;
  437     el->el_chared.c_resizefun   = NULL;
  438     el->el_chared.c_resizearg   = NULL;
  439     el->el_chared.c_aliasfun    = NULL;
  440     el->el_chared.c_aliasarg    = NULL;
  441 
  442     el->el_map.current      = el->el_map.key;
  443 
  444     el->el_state.inputmode      = MODE_INSERT; /* XXX: save a default */
  445     el->el_state.doingarg       = 0;
  446     el->el_state.metanext       = 0;
  447     el->el_state.argument       = 1;
  448     el->el_state.lastcmd        = ED_UNASSIGNED;
  449 
  450     return 0;
  451 }
  452 
  453 /* ch_reset():
  454  *  Reset the character editor
  455  */
  456 libedit_private void
  457 ch_reset(EditLine *el)
  458 {
  459     el->el_line.cursor      = el->el_line.buffer;
  460     el->el_line.lastchar        = el->el_line.buffer;
  461 
  462     el->el_chared.c_undo.len    = -1;
  463     el->el_chared.c_undo.cursor = 0;
  464 
  465     el->el_chared.c_vcmd.action = NOP;
  466     el->el_chared.c_vcmd.pos    = el->el_line.buffer;
  467 
  468     el->el_chared.c_kill.mark   = el->el_line.buffer;
  469 
  470     el->el_map.current      = el->el_map.key;
  471 
  472     el->el_state.inputmode      = MODE_INSERT; /* XXX: save a default */
  473     el->el_state.doingarg       = 0;
  474     el->el_state.metanext       = 0;
  475     el->el_state.argument       = 1;
  476     el->el_state.lastcmd        = ED_UNASSIGNED;
  477 
  478     el->el_history.eventno      = 0;
  479 }
  480 
  481 /* ch_enlargebufs():
  482  *  Enlarge line buffer to be able to hold twice as much characters.
  483  *  Returns 1 if successful, 0 if not.
  484  */
  485 libedit_private int
  486 ch_enlargebufs(EditLine *el, size_t addlen)
  487 {
  488     size_t sz, newsz;
  489     wchar_t *newbuffer, *oldbuf, *oldkbuf;
  490 
  491     sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE);
  492     newsz = sz * 2;
  493     /*
  494      * If newly required length is longer than current buffer, we need
  495      * to make the buffer big enough to hold both old and new stuff.
  496      */
  497     if (addlen > sz) {
  498         while(newsz - sz < addlen)
  499             newsz *= 2;
  500     }
  501 
  502     /*
  503      * Reallocate line buffer.
  504      */
  505     newbuffer = el_realloc(el->el_line.buffer, newsz * sizeof(*newbuffer));
  506     if (!newbuffer)
  507         return 0;
  508 
  509     /* zero the newly added memory, leave old data in */
  510     (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
  511 
  512     oldbuf = el->el_line.buffer;
  513 
  514     el->el_line.buffer = newbuffer;
  515     el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf);
  516     el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf);
  517     /* don't set new size until all buffers are enlarged */
  518     el->el_line.limit  = &newbuffer[sz - EL_LEAVE];
  519 
  520     /*
  521      * Reallocate kill buffer.
  522      */
  523     newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz *
  524         sizeof(*newbuffer));
  525     if (!newbuffer)
  526         return 0;
  527 
  528     /* zero the newly added memory, leave old data in */
  529     (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
  530 
  531     oldkbuf = el->el_chared.c_kill.buf;
  532 
  533     el->el_chared.c_kill.buf = newbuffer;
  534     el->el_chared.c_kill.last = newbuffer +
  535                     (el->el_chared.c_kill.last - oldkbuf);
  536     el->el_chared.c_kill.mark = el->el_line.buffer +
  537                     (el->el_chared.c_kill.mark - oldbuf);
  538 
  539     /*
  540      * Reallocate undo buffer.
  541      */
  542     newbuffer = el_realloc(el->el_chared.c_undo.buf,
  543         newsz * sizeof(*newbuffer));
  544     if (!newbuffer)
  545         return 0;
  546 
  547     /* zero the newly added memory, leave old data in */
  548     (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
  549     el->el_chared.c_undo.buf = newbuffer;
  550 
  551     newbuffer = el_realloc(el->el_chared.c_redo.buf,
  552         newsz * sizeof(*newbuffer));
  553     if (!newbuffer)
  554         return 0;
  555     el->el_chared.c_redo.pos = newbuffer +
  556             (el->el_chared.c_redo.pos - el->el_chared.c_redo.buf);
  557     el->el_chared.c_redo.lim = newbuffer +
  558             (el->el_chared.c_redo.lim - el->el_chared.c_redo.buf);
  559     el->el_chared.c_redo.buf = newbuffer;
  560 
  561     if (!hist_enlargebuf(el, sz, newsz))
  562         return 0;
  563 
  564     /* Safe to set enlarged buffer size */
  565     el->el_line.limit  = &el->el_line.buffer[newsz - EL_LEAVE];
  566     if (el->el_chared.c_resizefun)
  567         (*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg);
  568     return 1;
  569 }
  570 
  571 /* ch_end():
  572  *  Free the data structures used by the editor
  573  */
  574 libedit_private void
  575 ch_end(EditLine *el)
  576 {
  577     el_free(el->el_line.buffer);
  578     el->el_line.buffer = NULL;
  579     el->el_line.limit = NULL;
  580     el_free(el->el_chared.c_undo.buf);
  581     el->el_chared.c_undo.buf = NULL;
  582     el_free(el->el_chared.c_redo.buf);
  583     el->el_chared.c_redo.buf = NULL;
  584     el->el_chared.c_redo.pos = NULL;
  585     el->el_chared.c_redo.lim = NULL;
  586     el->el_chared.c_redo.cmd = ED_UNASSIGNED;
  587     el_free(el->el_chared.c_kill.buf);
  588     el->el_chared.c_kill.buf = NULL;
  589     ch_reset(el);
  590 }
  591 
  592 
  593 /* el_insertstr():
  594  *  Insert string at cursor
  595  */
  596 int
  597 el_winsertstr(EditLine *el, const wchar_t *s)
  598 {
  599     size_t len;
  600 
  601     if (s == NULL || (len = wcslen(s)) == 0)
  602         return -1;
  603     if (el->el_line.lastchar + len >= el->el_line.limit) {
  604         if (!ch_enlargebufs(el, len))
  605             return -1;
  606     }
  607 
  608     c_insert(el, (int)len);
  609     while (*s)
  610         *el->el_line.cursor++ = *s++;
  611     return 0;
  612 }
  613 
  614 
  615 /* el_deletestr():
  616  *  Delete num characters before the cursor
  617  */
  618 void
  619 el_deletestr(EditLine *el, int n)
  620 {
  621     if (n <= 0)
  622         return;
  623 
  624     if (el->el_line.cursor < &el->el_line.buffer[n])
  625         return;
  626 
  627     c_delbefore(el, n);     /* delete before dot */
  628     el->el_line.cursor -= n;
  629     if (el->el_line.cursor < el->el_line.buffer)
  630         el->el_line.cursor = el->el_line.buffer;
  631 }
  632 
  633 /* el_cursor():
  634  *  Move the cursor to the left or the right of the current position
  635  */
  636 int
  637 el_cursor(EditLine *el, int n)
  638 {
  639     if (n == 0)
  640         goto out;
  641 
  642     el->el_line.cursor += n;
  643 
  644     if (el->el_line.cursor < el->el_line.buffer)
  645         el->el_line.cursor = el->el_line.buffer;
  646     if (el->el_line.cursor > el->el_line.lastchar)
  647         el->el_line.cursor = el->el_line.lastchar;
  648 out:
  649     return (int)(el->el_line.cursor - el->el_line.buffer);
  650 }
  651 
  652 /* c_gets():
  653  *  Get a string
  654  */
  655 libedit_private int
  656 c_gets(EditLine *el, wchar_t *buf, const wchar_t *prompt)
  657 {
  658     ssize_t len;
  659     wchar_t *cp = el->el_line.buffer, ch;
  660 
  661     if (prompt) {
  662         len = (ssize_t)wcslen(prompt);
  663         (void)memcpy(cp, prompt, (size_t)len * sizeof(*cp));
  664         cp += len;
  665     }
  666     len = 0;
  667 
  668     for (;;) {
  669         el->el_line.cursor = cp;
  670         *cp = ' ';
  671         el->el_line.lastchar = cp + 1;
  672         re_refresh(el);
  673 
  674         if (el_wgetc(el, &ch) != 1) {
  675             ed_end_of_file(el, 0);
  676             len = -1;
  677             break;
  678         }
  679 
  680         switch (ch) {
  681 
  682         case L'\b': /* Delete and backspace */
  683         case 0177:
  684             if (len == 0) {
  685                 len = -1;
  686                 break;
  687             }
  688             len--;
  689             cp--;
  690             continue;
  691 
  692         case 0033:  /* ESC */
  693         case L'\r': /* Newline */
  694         case L'\n':
  695             buf[len] = ch;
  696             break;
  697 
  698         default:
  699             if (len >= (ssize_t)(EL_BUFSIZ - 16))
  700                 terminal_beep(el);
  701             else {
  702                 buf[len++] = ch;
  703                 *cp++ = ch;
  704             }
  705             continue;
  706         }
  707         break;
  708     }
  709 
  710     el->el_line.buffer[0] = '\0';
  711     el->el_line.lastchar = el->el_line.buffer;
  712     el->el_line.cursor = el->el_line.buffer;
  713     return (int)len;
  714 }
  715 
  716 
  717 /* c_hpos():
  718  *  Return the current horizontal position of the cursor
  719  */
  720 libedit_private int
  721 c_hpos(EditLine *el)
  722 {
  723     wchar_t *ptr;
  724 
  725     /*
  726      * Find how many characters till the beginning of this line.
  727      */
  728     if (el->el_line.cursor == el->el_line.buffer)
  729         return 0;
  730     else {
  731         for (ptr = el->el_line.cursor - 1;
  732              ptr >= el->el_line.buffer && *ptr != '\n';
  733              ptr--)
  734             continue;
  735         return (int)(el->el_line.cursor - ptr - 1);
  736     }
  737 }
  738 
  739 libedit_private int
  740 ch_resizefun(EditLine *el, el_zfunc_t f, void *a)
  741 {
  742     el->el_chared.c_resizefun = f;
  743     el->el_chared.c_resizearg = a;
  744     return 0;
  745 }
  746 
  747 libedit_private int
  748 ch_aliasfun(EditLine *el, el_afunc_t f, void *a)
  749 {
  750     el->el_chared.c_aliasfun = f;
  751     el->el_chared.c_aliasarg = a;
  752     return 0;
  753 }