Back to index

tetex-bin  3.0
lib_get_wstr.c
Go to the documentation of this file.
00001 /****************************************************************************
00002  * Copyright (c) 2002-2003,2004 Free Software Foundation, Inc.              *
00003  *                                                                          *
00004  * Permission is hereby granted, free of charge, to any person obtaining a  *
00005  * copy of this software and associated documentation files (the            *
00006  * "Software"), to deal in the Software without restriction, including      *
00007  * without limitation the rights to use, copy, modify, merge, publish,      *
00008  * distribute, distribute with modifications, sublicense, and/or sell       *
00009  * copies of the Software, and to permit persons to whom the Software is    *
00010  * furnished to do so, subject to the following conditions:                 *
00011  *                                                                          *
00012  * The above copyright notice and this permission notice shall be included  *
00013  * in all copies or substantial portions of the Software.                   *
00014  *                                                                          *
00015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
00016  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
00017  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
00018  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
00019  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
00020  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
00021  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
00022  *                                                                          *
00023  * Except as contained in this notice, the name(s) of the above copyright   *
00024  * holders shall not be used in advertising or otherwise to promote the     *
00025  * sale, use or other dealings in this Software without prior written       *
00026  * authorization.                                                           *
00027  ****************************************************************************/
00028 
00029 /****************************************************************************
00030  *  Author: Thomas E. Dickey                                                *
00031  ****************************************************************************/
00032 
00033 /*
00034 **     lib_get_wstr.c
00035 **
00036 **     The routine wgetn_wstr().
00037 **
00038 */
00039 
00040 #include <curses.priv.h>
00041 #include <term.h>
00042 
00043 MODULE_ID("$Id: lib_get_wstr.c,v 1.8 2004/10/16 21:55:36 tom Exp $")
00044 
00045 static int
00046 wadd_wint(WINDOW *win, wint_t *src)
00047 {
00048     cchar_t tmp;
00049     wchar_t wch[2];
00050 
00051     wch[0] = *src;
00052     wch[1] = 0;
00053     setcchar(&tmp, wch, A_NORMAL, 0, NULL);
00054     return wadd_wch(win, &tmp);
00055 }
00056 
00057 /*
00058  * This wipes out the last character, no matter whether it was a tab, control
00059  * or other character, and handles reverse wraparound.
00060  */
00061 static wint_t *
00062 WipeOut(WINDOW *win, int y, int x, wint_t *first, wint_t *last, bool echoed)
00063 {
00064     if (last > first) {
00065        *--last = '\0';
00066        if (echoed) {
00067            int y1 = win->_cury;
00068            int x1 = win->_curx;
00069            int n;
00070 
00071            wmove(win, y, x);
00072            for (n = 0; first[n] != 0; ++n) {
00073               wadd_wint(win, first + n);
00074            }
00075            getyx(win, y, x);
00076            while (win->_cury < y1
00077                  || (win->_cury == y1 && win->_curx < x1))
00078               waddch(win, (chtype) ' ');
00079 
00080            wmove(win, y, x);
00081        }
00082     }
00083     return last;
00084 }
00085 
00086 NCURSES_EXPORT(int)
00087 wgetn_wstr(WINDOW *win, wint_t *str, int maxlen)
00088 {
00089     TTY buf;
00090     bool oldnl, oldecho, oldraw, oldcbreak;
00091     wint_t erasec;
00092     wint_t killc;
00093     wint_t *oldstr = str;
00094     wint_t *tmpstr = str;
00095     wint_t ch;
00096     int y, x, code;
00097 
00098     T((T_CALLED("wgetn_wstr(%p,%p, %d)"), win, str, maxlen));
00099 
00100     if (!win)
00101        returnCode(ERR);
00102 
00103     _nc_get_tty_mode(&buf);
00104 
00105     oldnl = SP->_nl;
00106     oldecho = SP->_echo;
00107     oldraw = SP->_raw;
00108     oldcbreak = SP->_cbreak;
00109     nl();
00110     noecho();
00111     noraw();
00112     cbreak();
00113 
00114     erasec = erasechar();
00115     killc = killchar();
00116 
00117     getyx(win, y, x);
00118 
00119     if (is_wintouched(win) || (win->_flags & _HASMOVED))
00120        wrefresh(win);
00121 
00122     while ((code = wget_wch(win, &ch)) != ERR) {
00123        /*
00124         * Map special characters into key-codes.
00125         */
00126        if (ch == '\r')
00127            ch = '\n';
00128        if (ch == '\n') {
00129            code = KEY_CODE_YES;
00130            ch = KEY_ENTER;
00131        }
00132        if (ch < KEY_MIN) {
00133            if (ch == erasec) {
00134               ch = KEY_BACKSPACE;
00135               code = KEY_CODE_YES;
00136            }
00137            if (ch == killc) {
00138               ch = KEY_EOL;
00139               code = KEY_CODE_YES;
00140            }
00141        }
00142        if (code == KEY_CODE_YES) {
00143            /*
00144             * Some terminals (the Wyse-50 is the most common) generate a \n
00145             * from the down-arrow key.  With this logic, it's the user's
00146             * choice whether to set kcud=\n for wget_wch(); terminating
00147             * *getn_wstr() with \n should work either way.
00148             */
00149            if (ch == KEY_DOWN || ch == KEY_ENTER) {
00150               if (oldecho == TRUE
00151                   && win->_cury == win->_maxy
00152                   && win->_scroll)
00153                   wechochar(win, (chtype) '\n');
00154               break;
00155            }
00156            if (ch == KEY_LEFT || ch == KEY_BACKSPACE) {
00157               if (tmpstr > oldstr) {
00158                   tmpstr = WipeOut(win, y, x, oldstr, tmpstr, oldecho);
00159               }
00160            } else if (ch == KEY_EOL) {
00161               while (tmpstr > oldstr) {
00162                   tmpstr = WipeOut(win, y, x, oldstr, tmpstr, oldecho);
00163               }
00164            } else {
00165               beep();
00166            }
00167        } else if (maxlen >= 0 && tmpstr - oldstr >= maxlen) {
00168            beep();
00169        } else {
00170            *tmpstr++ = ch;
00171            *tmpstr = 0;
00172            if (oldecho == TRUE) {
00173               int oldy = win->_cury;
00174 
00175               if (wadd_wint(win, tmpstr - 1) == ERR) {
00176                   /*
00177                    * We can't really use the lower-right corner for input,
00178                    * since it'll mess up bookkeeping for erases.
00179                    */
00180                   win->_flags &= ~_WRAPPED;
00181                   waddch(win, (chtype) ' ');
00182                   tmpstr = WipeOut(win, y, x, oldstr, tmpstr, oldecho);
00183                   continue;
00184               } else if (win->_flags & _WRAPPED) {
00185                   /*
00186                    * If the last waddch forced a wrap & scroll, adjust our
00187                    * reference point for erasures.
00188                    */
00189                   if (win->_scroll
00190                      && oldy == win->_maxy
00191                      && win->_cury == win->_maxy) {
00192                      if (--y <= 0) {
00193                          y = 0;
00194                      }
00195                   }
00196                   win->_flags &= ~_WRAPPED;
00197               }
00198               wrefresh(win);
00199            }
00200        }
00201     }
00202 
00203     win->_curx = 0;
00204     win->_flags &= ~_WRAPPED;
00205     if (win->_cury < win->_maxy)
00206        win->_cury++;
00207     wrefresh(win);
00208 
00209     /* Restore with a single I/O call, to fix minor asymmetry between
00210      * raw/noraw, etc.
00211      */
00212     SP->_nl = oldnl;
00213     SP->_echo = oldecho;
00214     SP->_raw = oldraw;
00215     SP->_cbreak = oldcbreak;
00216 
00217     (void) _nc_set_tty_mode(&buf);
00218 
00219     *tmpstr = 0;
00220     if (code == ERR) {
00221        if (tmpstr == oldstr) {
00222            *tmpstr++ = WEOF;
00223            *tmpstr = 0;
00224        }
00225        returnCode(ERR);
00226     }
00227 
00228     T(("wgetn_wstr returns %s", _nc_viswibuf(oldstr)));
00229 
00230     returnCode(OK);
00231 }