el.cxx

Go to the documentation of this file.
00001 // @(#)root/editline:$Id: el.cxx 36302 2010-10-11 15:07:25Z axel $
00002 // Author: Mary-Louise Gill, 2009
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 /*      $NetBSD: el.c,v 1.21 2001/01/05 22:45:30 christos Exp $ */
00013 
00014 /*-
00015  * Copyright (c) 1992, 1993
00016  *      The Regents of the University of California.  All rights reserved.
00017  *
00018  * This code is derived from software contributed to Berkeley by
00019  * Christos Zoulas of Cornell University.
00020  *
00021  * Redistribution and use in source and binary forms, with or without
00022  * modification, are permitted provided that the following conditions
00023  * are met:
00024  * 1. Redistributions of source code must retain the above copyright
00025  *    notice, this list of conditions and the following disclaimer.
00026  * 2. Redistributions in binary form must reproduce the above copyright
00027  *    notice, this list of conditions and the following disclaimer in the
00028  *    documentation and/or other materials provided with the distribution.
00029  * 3. Neither the name of the University nor the names of its contributors
00030  *    may be used to endorse or promote products derived from this software
00031  *    without specific prior written permission.
00032  *
00033  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00034  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00035  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00036  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00037  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00038  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00039  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00040  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00041  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00042  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00043  * SUCH DAMAGE.
00044  */
00045 
00046 #include "compat.h"
00047 
00048 #include <fstream>
00049 #include <string>
00050 
00051 /*
00052  * el.c: EditLine_t interface functions
00053  */
00054 #include "sys.h"
00055 
00056 #include <sys/types.h>
00057 #include <sys/param.h>
00058 #include <string.h>
00059 #include <stdlib.h>
00060 #include <stdarg.h>
00061 #include "el.h"
00062 
00063 /* el_init():
00064  *      Initialize SEditLine_t and set default parameters.
00065  */
00066 el_public EditLine_t*
00067 el_init(const char* prog, FILE* fin, FILE* fout, FILE* ferr) {
00068    EditLine_t* el = (EditLine_t*) el_malloc(sizeof(EditLine_t));
00069 #ifdef DEBUG
00070    char* tty;
00071 #endif
00072 
00073    if (el == NULL) {
00074       return NULL;
00075    }
00076 
00077    memset(el, 0, sizeof(EditLine_t));
00078 
00079    el->fIn = fin;
00080    el->fInFD = fileno(fin);
00081    if (isatty(el->fInFD))
00082       el->fIn = 0;
00083 
00084    el->fOutFile = fout;
00085    el->fErrFile = ferr;
00086    el->fProg = strdup(prog);
00087 
00088    /*
00089     * Initialize all the modules. Order is important!!!
00090     */
00091    el->fFlags = 0;
00092 
00093    (void) term_init(el);
00094    (void) key_init(el);
00095    (void) map_init(el);
00096 
00097    if (tty_init(el) == -1) {
00098       el->fFlags |= NO_TTY;
00099    }
00100    (void) ch_init(el);
00101    (void) search_init(el);
00102    (void) hist_init(el);
00103    (void) prompt_init(el);
00104    (void) sig_init(el);
00105 
00106    return el;
00107 } // el_init
00108 
00109 
00110 /* el_end():
00111  *      Clean up.
00112  */
00113 el_public void
00114 el_end(EditLine_t* el) {
00115    if (el == NULL) {
00116       return;
00117    }
00118 
00119    el_reset(el);
00120 
00121    term_end(el);
00122    key_end(el);
00123    map_end(el);
00124    tty_end(el);
00125    ch_end(el);
00126    search_end(el);
00127    hist_end(el);
00128    prompt_end(el);
00129    sig_end(el);
00130 
00131    el_free((ptr_t) el->fProg);
00132    el_free((ptr_t) el);
00133 } // el_end
00134 
00135 
00136 /* el_reset():
00137  *      Reset the tty and the parser
00138  */
00139 el_public void
00140 el_reset(EditLine_t* el) {
00141    tty_cookedmode(el);
00142    ch_reset(el);                /* XXX: Do we want that? */
00143 }
00144 
00145 
00146 /* el_set():
00147  *      set the SEditLine_t parameters
00148  */
00149 el_public int
00150 el_set(EditLine_t* el, int op, ...) {
00151    va_list va;
00152    int rv;
00153    va_start(va, op);
00154 
00155    if (el == NULL) {
00156       va_end(va);
00157       return -1;
00158    }
00159 
00160    switch (op) {
00161    case EL_PROMPT:
00162    case EL_RPROMPT:
00163       rv = prompt_set(el, va_arg(va, ElPFunc_t), op);
00164       break;
00165 
00166    case EL_TERMINAL:
00167       rv = term_set(el, va_arg(va, char*));
00168       break;
00169 
00170    case EL_EDITOR:
00171       rv = map_set_editor(el, va_arg(va, char*));
00172       break;
00173 
00174    case EL_SIGNAL:
00175 
00176       if (va_arg(va, int)) {
00177          el->fFlags |= HANDLE_SIGNALS;
00178       } else {
00179          el->fFlags &= ~HANDLE_SIGNALS;
00180       }
00181       rv = 0;
00182       break;
00183 
00184    case EL_BIND:
00185    case EL_TELLTC:
00186    case EL_SETTC:
00187    case EL_ECHOTC:
00188    case EL_SETTY:
00189    {
00190       const char* argv[20];
00191       const char** cargv = 0;
00192       int i;
00193 
00194       for (i = 1; i < 20; i++) {
00195          if ((argv[i] = va_arg(va, const char*)) == NULL) {
00196             break;
00197          }
00198       }
00199       argv[0] = argv[1];
00200       cargv = argv;
00201 
00202       switch (op) {
00203       case EL_BIND:
00204          argv[0] = "bind";
00205          rv = map_bind(el, i, cargv);
00206          break;
00207 
00208       case EL_TELLTC:
00209          argv[0] = "telltc";
00210          rv = term_telltc(el, i, cargv);
00211          break;
00212 
00213       case EL_SETTC:
00214          argv[0] = "settc";
00215          rv = term_settc(el, i, cargv);
00216          break;
00217 
00218       case EL_ECHOTC:
00219          argv[0] = "echotc";
00220          rv = term_echotc(el, i, cargv);
00221          break;
00222 
00223       case EL_SETTY:
00224          argv[0] = "setty";
00225          rv = tty_stty(el, i, cargv);
00226          break;
00227 
00228       default:
00229          rv = -1;
00230          EL_ABORT((el->fErrFile, "Bad op %d\n", op));
00231          break;
00232       } // switch
00233       break;
00234    }
00235 
00236    case EL_ADDFN:
00237    {
00238       char* name = va_arg(va, char*);
00239       char* help = va_arg(va, char*);
00240       ElFunc_t func = va_arg(va, ElFunc_t);
00241 
00242       rv = map_addfunc(el, name, help, func);
00243       break;
00244    }
00245 
00246    case EL_HIST:
00247    {
00248       HistFun_t func = va_arg(va, HistFun_t);
00249       ptr_t ptr = va_arg(va, char*);
00250 
00251       rv = hist_set(el, func, ptr);
00252       break;
00253    }
00254 
00255    case EL_EDITMODE:
00256 
00257       if (va_arg(va, int)) {
00258          el->fFlags &= ~EDIT_DISABLED;
00259       } else {
00260          el->fFlags |= EDIT_DISABLED;
00261       }
00262       rv = 0;
00263       break;
00264 
00265    default:
00266       rv = -1;
00267    } // switch
00268 
00269    va_end(va);
00270    return rv;
00271 } // el_set
00272 
00273 
00274 /* el_get():
00275  *      retrieve the SEditLine_t parameters
00276  */
00277 el_public int
00278 el_get(EditLine_t* el, int op, void* ret) {
00279    int rv;
00280 
00281    if (el == NULL || ret == NULL) {
00282       return -1;
00283    }
00284 
00285    switch (op) {
00286    case EL_PROMPT:
00287    case EL_RPROMPT:
00288       {
00289          ElPFunc_t func;
00290          rv = prompt_get(el, &func, op);
00291          ret = (void*) func;
00292          break;
00293       }
00294 
00295    case EL_EDITOR:
00296       {
00297          const char* str;
00298          rv = map_get_editor(el, &str);
00299          ret = (void*)str;
00300          break;
00301       }
00302 
00303    case EL_SIGNAL:
00304       *((int*) ret) = (el->fFlags & HANDLE_SIGNALS);
00305       rv = 0;
00306       break;
00307 
00308    case EL_EDITMODE:
00309       *((int*) ret) = (!(el->fFlags & EDIT_DISABLED));
00310       rv = 0;
00311       break;
00312 
00313 #if 0                           /* XXX */
00314    case EL_TERMINAL:
00315       rv = term_get(el, (const char*) &ret);
00316       break;
00317 
00318    case EL_BIND:
00319    case EL_TELLTC:
00320    case EL_SETTC:
00321    case EL_ECHOTC:
00322    case EL_SETTY:
00323    {
00324       char* argv[20];
00325       int i;
00326 
00327       for (i = 1; i < 20; i++) {
00328          if ((argv[i] = va_arg(va, char*)) == NULL) {
00329             break;
00330          }
00331       }
00332 
00333       switch (op) {
00334       case EL_BIND:
00335          argv[0] = "bind";
00336          rv = map_bind(el, i, argv);
00337          break;
00338 
00339       case EL_TELLTC:
00340          argv[0] = "telltc";
00341          rv = term_telltc(el, i, argv);
00342          break;
00343 
00344       case EL_SETTC:
00345          argv[0] = "settc";
00346          rv = term_settc(el, i, argv);
00347          break;
00348 
00349       case EL_ECHOTC:
00350          argv[0] = "echotc";
00351          rv = term_echotc(el, i, argv);
00352          break;
00353 
00354       case EL_SETTY:
00355          argv[0] = "setty";
00356          rv = tty_stty(el, i, argv);
00357          break;
00358 
00359       default:
00360          rv = -1;
00361          EL_ABORT((el->errfile, "Bad op %d\n", op));
00362          break;
00363       } // switch
00364       break;
00365    }
00366 
00367    case EL_ADDFN:
00368    {
00369       char* name = va_arg(va, char*);
00370       char* help = va_arg(va, char*);
00371       ElFunc_t func = va_arg(va, ElFunc_t);
00372 
00373       rv = map_addfunc(el, name, help, func);
00374       break;
00375    }
00376 
00377    case EL_HIST:
00378    {
00379       HistFun_t func = va_arg(va, HistFun_t);
00380       ptr_t ptr = va_arg(va, char*);
00381       rv = hist_set(el, func, ptr);
00382    }
00383    break;
00384 #endif /* XXX */
00385 
00386    default:
00387       rv = -1;
00388    } // switch
00389 
00390    return rv;
00391 } // el_get
00392 
00393 
00394 /* el_line():
00395  *      Return editing info
00396  */
00397 el_public const LineInfo_t*
00398 el_line(EditLine_t* el) {
00399    return (const LineInfo_t*) (void*) &el->fLine;
00400 }
00401 
00402 
00403 static const char elpath[] = "/.editrc";
00404 
00405 /* el_source():
00406  *      Source a file
00407  */
00408 el_public int
00409 el_source(EditLine_t* el, const char* fname) {
00410    char* ptr, path[MAXPATHLEN];
00411 
00412    if (fname == NULL) {
00413       if ((ptr = getenv("HOME")) == NULL) {
00414          return -1;
00415       }
00416 
00417       if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path)) {
00418          return -1;
00419       }
00420 
00421       if (strlcat(path, elpath, sizeof(path)) >= sizeof(path)) {
00422          return -1;
00423       }
00424       fname = path;
00425    }
00426 
00427    std::ifstream in(fname);
00428    std::string line;
00429    while (in) {
00430       std::getline(in, line);
00431       if (parse_line(el, line.c_str()) == -1) {
00432          return -1;
00433       }
00434    }
00435 
00436    return 0;
00437 } // el_source
00438 
00439 
00440 /* el_resize():
00441  *      Called from program when terminal is resized
00442  */
00443 el_public void
00444 el_resize(EditLine_t* el) {
00445    int lins, cols;
00446    sigset_t oset, nset;
00447 
00448    (void) sigemptyset(&nset);
00449    (void) sigaddset(&nset, SIGWINCH);
00450    (void) sigprocmask(SIG_BLOCK, &nset, &oset);
00451 
00452    int curHPos = el->fCursor.fH;
00453    int curVPos = el->fCursor.fV;
00454 
00455    // We want to clear the old lines later. But how many did we have?
00456    int displen = el->fPrompt.fPos.fH;
00457    displen += el->fLine.fLastChar - el->fLine.fBuffer;
00458    // fTerm still has the old number of columns
00459    int nlines = displen / el->fTerm.fSize.fH;
00460 
00461    /* get the correct window size */
00462    if (term_get_size(el, &lins, &cols)) {
00463       term_change_size(el, lins, cols);
00464    }
00465 
00466    // Now clear the old lines.
00467    el->fRefresh.r_oldcv = nlines;
00468 
00469    // We need to set the cursor position after the resize, or refresh
00470    // will argue that nothing has changed (term_change_size set it to 0).
00471    // Set it to the last column if too large, otherwise keep it.
00472    el->fCursor.fH = curHPos >= cols ? cols - 1 : curHPos;
00473    // the vertical cursor pos does not change by resizing the window
00474    el->fCursor.fV = curVPos;
00475    re_clear_lines(el);
00476    re_refresh(el);
00477    term__flush();
00478 
00479    (void) sigprocmask(SIG_SETMASK, &oset, NULL);
00480 } // el_resize
00481 
00482 
00483 /* el_beep():
00484  *      Called from the program to beep
00485  */
00486 el_public void
00487 el_beep(EditLine_t* el) {
00488    term_beep(el);
00489 }
00490 
00491 
00492 /* el_editmode()
00493  *      Set the state of EDIT_DISABLED from the `edit' command.
00494  */
00495 el_protected int
00496 /*ARGSUSED*/
00497 el_editmode(EditLine_t* el, int argc, const char** argv) {
00498    const char* how;
00499 
00500    if (argv == NULL || argc != 2 || argv[1] == NULL) {
00501       (void) fprintf(el->fErrFile, "edit: Usage error. Pass 'on' or 'off' to enable or disable line-editing mode.\n");
00502       return -1;
00503    }
00504 
00505    how = argv[1];
00506 
00507    if (strcmp(how, "on") == 0) {
00508       el->fFlags &= ~EDIT_DISABLED;
00509    } else if (strcmp(how, "off") == 0) {
00510       el->fFlags |= EDIT_DISABLED;
00511    } else {
00512       (void) fprintf(el->fErrFile, "edit: Bad value `%s'.\n", how);
00513       return -1;
00514    }
00515    return 0;
00516 } // el_editmode

Generated on Tue Jul 5 14:11:38 2011 for ROOT_528-00b_version by  doxygen 1.5.1