emacs.cxx

Go to the documentation of this file.
00001 // @(#)root/editline:$Id: emacs.cxx 36303 2010-10-11 15:16:49Z 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: emacs.c,v 1.9 2001/01/10 07:45:41 jdolecek 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  * emacs.c: Emacs functions
00049  */
00050 #include "sys.h"
00051 #include "el.h"
00052 
00053 /* em_delete_or_list():
00054  *      Delete character under cursor or list completions if at end of line
00055  *      [^D]
00056  */
00057 el_protected ElAction_t
00058 /*ARGSUSED*/
00059 em_delete_or_list(EditLine_t* el, int /*c*/) {
00060    if (el->fLine.fCursor == el->fLine.fLastChar) {
00061       /* if I'm at the end */
00062       if (el->fLine.fCursor == el->fLine.fBuffer) {
00063          /* and the beginning */
00064          term_overwrite(el, STReof, 0, 4);                      /* then do a EOF */
00065          term__flush();
00066          return CC_EOF;
00067       } else {
00068          /*
00069           * Here we could list completions, but it is an
00070           * error right now
00071           */
00072          term_beep(el);
00073          return CC_ERROR;
00074       }
00075    } else {
00076       c_delafter(el, el->fState.fArgument);            /* delete after dot */
00077 
00078       if (el->fLine.fCursor > el->fLine.fLastChar) {
00079          el->fLine.fCursor = el->fLine.fLastChar;
00080       }
00081       /* bounds check */
00082       return CC_REFRESH;
00083    }
00084 } // em_delete_or_list
00085 
00086 
00087 /* em_delete_next_word():
00088  *      Cut from cursor to end of current word
00089  *      [M-d]
00090  */
00091 el_protected ElAction_t
00092 /*ARGSUSED*/
00093 em_delete_next_word(EditLine_t* el, int /*c*/) {
00094    char* cp, * p, * kp;
00095 
00096    if (el->fLine.fCursor == el->fLine.fLastChar) {
00097       return CC_ERROR;
00098    }
00099 
00100    cp = c__next_word(el->fLine.fCursor, el->fLine.fLastChar,
00101                      el->fState.fArgument, ce__isword);
00102 
00103    for (p = el->fLine.fCursor, kp = el->fCharEd.fKill.fBuf; p < cp; p++) {
00104       /* save the text */
00105       *kp++ = *p;
00106    }
00107    el->fCharEd.fKill.fLast = kp;
00108 
00109    c_delafter(el, cp - el->fLine.fCursor);             /* delete after dot */
00110 
00111    if (el->fLine.fCursor > el->fLine.fLastChar) {
00112       el->fLine.fCursor = el->fLine.fLastChar;
00113    }
00114    /* bounds check */
00115    return CC_REFRESH;
00116 } // em_delete_next_word
00117 
00118 
00119 /* em_yank():
00120  *      Paste cut buffer at cursor position
00121  *      [^Y]
00122  */
00123 el_protected ElAction_t
00124 /*ARGSUSED*/
00125 em_yank(EditLine_t* el, int /*c*/) {
00126    char* kp, * cp;
00127 
00128    if (el->fCharEd.fKill.fLast == el->fCharEd.fKill.fBuf) {
00129       if (!ch_enlargebufs(el, 1)) {
00130          return CC_ERROR;
00131       }
00132    }
00133 
00134    if (el->fLine.fLastChar +
00135        (el->fCharEd.fKill.fLast - el->fCharEd.fKill.fBuf) >=
00136        el->fLine.fLimit) {
00137       return CC_ERROR;
00138    }
00139 
00140    el->fCharEd.fKill.fMark = el->fLine.fCursor;
00141    cp = el->fLine.fCursor;
00142 
00143    /* open the space, */
00144    c_insert(el, el->fCharEd.fKill.fLast - el->fCharEd.fKill.fBuf);
00145 
00146    /* copy the chars */
00147    for (kp = el->fCharEd.fKill.fBuf; kp < el->fCharEd.fKill.fLast; kp++) {
00148       *cp++ = *kp;
00149    }
00150 
00151    /* if an arg, cursor at beginning else cursor at end */
00152    if (el->fState.fArgument == 1) {
00153       el->fLine.fCursor = cp;
00154    }
00155 
00156    return CC_REFRESH;
00157 } // em_yank
00158 
00159 
00160 /* em_kill_line():
00161  *      Cut the entire line and save in cut buffer
00162  *      [^U]
00163  */
00164 el_protected ElAction_t
00165 /*ARGSUSED*/
00166 em_kill_line(EditLine_t* el, int /*c*/) {
00167    char* kp, * cp;
00168 
00169    cp = el->fLine.fBuffer;
00170    kp = el->fCharEd.fKill.fBuf;
00171 
00172    while (cp < el->fLine.fLastChar)
00173       *kp++ = *cp++;            /* copy it */
00174    el->fCharEd.fKill.fLast = kp;
00175    /* zap! -- delete all of it */
00176    el->fLine.fLastChar = el->fLine.fBuffer;
00177    el->fLine.fCursor = el->fLine.fBuffer;
00178    return CC_REFRESH;
00179 }
00180 
00181 
00182 /* em_kill_region():
00183  *      Cut area between mark and cursor and save in cut buffer
00184  *      [^W]
00185  */
00186 el_protected ElAction_t
00187 /*ARGSUSED*/
00188 em_kill_region(EditLine_t* el, int /*c*/) {
00189    char* kp, * cp;
00190 
00191    if (!el->fCharEd.fKill.fMark) {
00192       return CC_ERROR;
00193    }
00194 
00195    if (el->fCharEd.fKill.fMark > el->fLine.fCursor) {
00196       cp = el->fLine.fCursor;
00197       kp = el->fCharEd.fKill.fBuf;
00198 
00199       while (cp < el->fCharEd.fKill.fMark)
00200          *kp++ = *cp++;                 /* copy it */
00201       el->fCharEd.fKill.fLast = kp;
00202       c_delafter(el, cp - el->fLine.fCursor);
00203    } else {                     /* mark is before cursor */
00204       cp = el->fCharEd.fKill.fMark;
00205       kp = el->fCharEd.fKill.fBuf;
00206 
00207       while (cp < el->fLine.fCursor)
00208          *kp++ = *cp++;                 /* copy it */
00209       el->fCharEd.fKill.fLast = kp;
00210       c_delbefore(el, cp - el->fCharEd.fKill.fMark);
00211       el->fLine.fCursor = el->fCharEd.fKill.fMark;
00212    }
00213    return CC_REFRESH;
00214 } // em_kill_region
00215 
00216 
00217 /* em_copy_region():
00218  *      Copy area between mark and cursor to cut buffer
00219  *      [M-W]
00220  */
00221 el_protected ElAction_t
00222 /*ARGSUSED*/
00223 em_copy_region(EditLine_t* el, int /*c*/) {
00224    char* kp, * cp;
00225 
00226    if (!el->fCharEd.fKill.fMark) {
00227       return CC_ERROR;
00228    }
00229 
00230    if (el->fCharEd.fKill.fMark > el->fLine.fCursor) {
00231       cp = el->fLine.fCursor;
00232       kp = el->fCharEd.fKill.fBuf;
00233 
00234       while (cp < el->fCharEd.fKill.fMark)
00235          *kp++ = *cp++;                 /* copy it */
00236       el->fCharEd.fKill.fLast = kp;
00237    } else {
00238       cp = el->fCharEd.fKill.fMark;
00239       kp = el->fCharEd.fKill.fBuf;
00240 
00241       while (cp < el->fLine.fCursor)
00242          *kp++ = *cp++;                 /* copy it */
00243       el->fCharEd.fKill.fLast = kp;
00244    }
00245    return CC_NORM;
00246 } // em_copy_region
00247 
00248 
00249 /* em_gosmacs_traspose():
00250  *      Exchange the two characters before the cursor
00251  *      Gosling emacs transpose chars [^T]
00252  */
00253 el_protected ElAction_t
00254 em_gosmacs_traspose(EditLine_t* el, int c) {
00255    if (el->fLine.fCursor > &el->fLine.fBuffer[1]) {
00256       /* must have at least two chars entered */
00257       c = el->fLine.fCursor[-2];
00258       el->fLine.fCursor[-2] = el->fLine.fCursor[-1];
00259       el->fLine.fCursor[-1] = c;
00260       return CC_REFRESH;
00261    } else {
00262       return CC_ERROR;
00263    }
00264 }
00265 
00266 
00267 /* em_next_word():
00268  *      Move next to end of current word
00269  *      [M-f]
00270  */
00271 el_protected ElAction_t
00272 /*ARGSUSED*/
00273 em_next_word(EditLine_t* el, int /*c*/) {
00274    if (el->fLine.fCursor == el->fLine.fLastChar) {
00275       return CC_ERROR;
00276    }
00277 
00278    el->fLine.fCursor = c__next_word(el->fLine.fCursor,
00279                                      el->fLine.fLastChar,
00280                                      el->fState.fArgument,
00281                                      ce__isword);
00282 
00283    if (el->fMap.fType == MAP_VI) {
00284       if (el->fCharEd.fVCmd.fAction & DELETE) {
00285          cv_delfini(el);
00286          return CC_REFRESH;
00287       }
00288    }
00289    return CC_CURSOR;
00290 } // em_next_word
00291 
00292 
00293 /* em_upper_case():
00294  *      Uppercase the characters from cursor to end of current word
00295  *      [M-u]
00296  */
00297 el_protected ElAction_t
00298 /*ARGSUSED*/
00299 em_upper_case(EditLine_t* el, int /*c*/) {
00300    char* cp, * ep;
00301 
00302    ep = c__next_word(el->fLine.fCursor, el->fLine.fLastChar,
00303                      el->fState.fArgument, ce__isword);
00304 
00305    for (cp = el->fLine.fCursor; cp < ep; cp++) {
00306       if (islower((unsigned char) *cp)) {
00307          *cp = toupper(*cp);
00308       }
00309    }
00310 
00311    el->fLine.fCursor = ep;
00312 
00313    if (el->fLine.fCursor > el->fLine.fLastChar) {
00314       el->fLine.fCursor = el->fLine.fLastChar;
00315    }
00316    return CC_REFRESH;
00317 } // em_upper_case
00318 
00319 
00320 /* em_capitol_case():
00321  *      Capitalize the characters from cursor to end of current word
00322  *      [M-c]
00323  */
00324 el_protected ElAction_t
00325 /*ARGSUSED*/
00326 em_capitol_case(EditLine_t* el, int /*c*/) {
00327    char* cp, * ep;
00328 
00329    ep = c__next_word(el->fLine.fCursor, el->fLine.fLastChar,
00330                      el->fState.fArgument, ce__isword);
00331 
00332    for (cp = el->fLine.fCursor; cp < ep; cp++) {
00333       if (isalpha((unsigned char) *cp)) {
00334          if (islower((unsigned char) *cp)) {
00335             *cp = toupper(*cp);
00336          }
00337          cp++;
00338          break;
00339       }
00340    }
00341 
00342    for ( ; cp < ep; cp++) {
00343       if (isupper((unsigned char) *cp)) {
00344          *cp = tolower(*cp);
00345       }
00346    }
00347 
00348    el->fLine.fCursor = ep;
00349 
00350    if (el->fLine.fCursor > el->fLine.fLastChar) {
00351       el->fLine.fCursor = el->fLine.fLastChar;
00352    }
00353    return CC_REFRESH;
00354 } // em_capitol_case
00355 
00356 
00357 /* em_lower_case():
00358  *      Lowercase the characters from cursor to end of current word
00359  *      [M-l]
00360  */
00361 el_protected ElAction_t
00362 /*ARGSUSED*/
00363 em_lower_case(EditLine_t* el, int /*c*/) {
00364    char* cp, * ep;
00365 
00366    ep = c__next_word(el->fLine.fCursor, el->fLine.fLastChar,
00367                      el->fState.fArgument, ce__isword);
00368 
00369    for (cp = el->fLine.fCursor; cp < ep; cp++) {
00370       if (isupper((unsigned char) *cp)) {
00371          *cp = tolower(*cp);
00372       }
00373    }
00374 
00375    el->fLine.fCursor = ep;
00376 
00377    if (el->fLine.fCursor > el->fLine.fLastChar) {
00378       el->fLine.fCursor = el->fLine.fLastChar;
00379    }
00380    return CC_REFRESH;
00381 } // em_lower_case
00382 
00383 
00384 /* em_set_mark():
00385  *      Set the mark at cursor
00386  *      [^@]
00387  */
00388 el_protected ElAction_t
00389 /*ARGSUSED*/
00390 em_set_mark(EditLine_t* el, int /*c*/) {
00391    el->fCharEd.fKill.fMark = el->fLine.fCursor;
00392    return CC_NORM;
00393 }
00394 
00395 
00396 /* em_exchange_mark():
00397  *      Exchange the cursor and mark
00398  *      [^X^X]
00399  */
00400 el_protected ElAction_t
00401 /*ARGSUSED*/
00402 em_exchange_mark(EditLine_t* el, int /*c*/) {
00403    char* cp;
00404 
00405    cp = el->fLine.fCursor;
00406    el->fLine.fCursor = el->fCharEd.fKill.fMark;
00407    el->fCharEd.fKill.fMark = cp;
00408    return CC_CURSOR;
00409 }
00410 
00411 
00412 /* em_universal_argument():
00413  *      Universal argument (argument times 4)
00414  *      [^U]
00415  */
00416 el_protected ElAction_t
00417 /*ARGSUSED*/
00418 em_universal_argument(EditLine_t* el, int /*c*/) { /* multiply current argument by 4 */
00419    if (el->fState.fArgument > 1000000) {
00420       return CC_ERROR;
00421    }
00422    el->fState.fDoingArg = 1;
00423    el->fState.fArgument *= 4;
00424    return CC_ARGHACK;
00425 }
00426 
00427 
00428 /* em_meta_next():
00429  *      Add 8th bit to next character typed
00430  *      [<ESC>]
00431  */
00432 el_protected ElAction_t
00433 /*ARGSUSED*/
00434 em_meta_next(EditLine_t* el, int /*c*/) {
00435    el->fState.fMetaNext = 1;
00436    return CC_ARGHACK;
00437 }
00438 
00439 
00440 /* em_toggle_overwrite():
00441  *      Switch from insert to overwrite mode or vice versa
00442  */
00443 el_protected ElAction_t
00444 /*ARGSUSED*/
00445 em_toggle_overwrite(EditLine_t* el, int /*c*/) {
00446    el->fState.fInputMode = (el->fState.fInputMode == MODE_INSERT) ?
00447                             MODE_REPLACE : MODE_INSERT;
00448    return CC_NORM;
00449 }
00450 
00451 
00452 /* em_copy_prev_word():
00453  *      Copy current word to cursor
00454  */
00455 el_protected ElAction_t
00456 /*ARGSUSED*/
00457 em_copy_prev_word(EditLine_t* el, int /*c*/) {
00458    char* cp, * oldc, * dp;
00459 
00460    if (el->fLine.fCursor == el->fLine.fBuffer) {
00461       return CC_ERROR;
00462    }
00463 
00464    oldc = el->fLine.fCursor;
00465    /* does a bounds check */
00466    cp = c__prev_word(el->fLine.fCursor, el->fLine.fBuffer,
00467                      el->fState.fArgument, ce__isword);
00468 
00469    c_insert(el, oldc - cp);
00470 
00471    for (dp = oldc; cp < oldc && dp < el->fLine.fLastChar; cp++) {
00472       *dp++ = *cp;
00473    }
00474 
00475    el->fLine.fCursor = dp;     /* put cursor at end */
00476 
00477    return CC_REFRESH;
00478 } // em_copy_prev_word
00479 
00480 
00481 /* em_inc_search_next():
00482  *      Emacs incremental next search
00483  */
00484 el_protected ElAction_t
00485 /*ARGSUSED*/
00486 em_inc_search_next(EditLine_t* el, int /*c*/) {
00487    el->fSearch.fPatLen = 0;
00488    return ce_inc_search(el, ED_SEARCH_NEXT_HISTORY);
00489 }
00490 
00491 
00492 /* em_inc_search_prev():
00493  *      Emacs incremental reverse search
00494  */
00495 el_protected ElAction_t
00496 /*ARGSUSED*/
00497 em_inc_search_prev(EditLine_t* el, int /*c*/) {
00498    el->fSearch.fPatLen = 0;
00499    return ce_inc_search(el, ED_SEARCH_PREV_HISTORY);
00500 }
00501 
00502 
00503 /* vi_undo():
00504  *      Vi undo last change
00505  *      [u]
00506  */
00507 el_protected ElAction_t
00508 /*ARGSUSED*/
00509 em_undo(EditLine_t* el, int /*c*/) {
00510    char* cp, * kp;
00511    char temp;
00512    int i, size;
00513    CUndo_t* un = &el->fCharEd.fUndo;
00514 
00515 #ifdef DEBUG_UNDO
00516       (void) fprintf(el->fErrFile, "Undo: %x \"%s\" +%d -%d\n",
00517                      un->fAction, un->fBuf, un->fISize, un->fDSize);
00518 #endif
00519 
00520    switch (un->fAction) {
00521    case DELETE:
00522 
00523       if (un->fDSize == 0) {
00524          return CC_NORM;
00525       }
00526 
00527       (void) memcpy(un->fBuf, un->fPtr, un->fDSize);
00528 
00529       for (cp = un->fPtr; cp <= el->fLine.fLastChar; cp++) {
00530          *cp = cp[un->fDSize];
00531       }
00532 
00533       el->fLine.fLastChar -= un->fDSize;
00534       el->fLine.fCursor = un->fPtr;
00535 
00536       un->fAction = INSERT;
00537       un->fISize = un->fDSize;
00538       un->fDSize = 0;
00539       break;
00540 
00541    case DELETE | INSERT:
00542       size = un->fISize - un->fDSize;
00543 
00544       if (size > 0) {
00545          i = un->fDSize;
00546       } else {
00547          i = un->fISize;
00548       }
00549       cp = un->fPtr;
00550       kp = un->fBuf;
00551 
00552       while (i-- > 0) {
00553          temp = *kp;
00554          *kp++ = *cp;
00555          *cp++ = temp;
00556       }
00557 
00558       if (size > 0) {
00559          el->fLine.fCursor = cp;
00560          c_insert(el, size);
00561 
00562          while (size-- > 0 && cp < el->fLine.fLastChar) {
00563             temp = *kp;
00564             *kp++ = *cp;
00565             *cp++ = temp;
00566          }
00567       } else if (size < 0) {
00568          size = -size;
00569 
00570          for ( ; cp <= el->fLine.fLastChar; cp++) {
00571             *kp++ = *cp;
00572             *cp = cp[size];
00573          }
00574          el->fLine.fLastChar -= size;
00575       }
00576       el->fLine.fCursor = un->fPtr;
00577       i = un->fDSize;
00578       un->fDSize = un->fISize;
00579       un->fISize = i;
00580       break;
00581 
00582    case INSERT:
00583 
00584       if (un->fISize == 0) {
00585          return CC_NORM;
00586       }
00587 
00588       el->fLine.fCursor = un->fPtr;
00589       c_insert(el, (int) un->fISize);
00590       (void) memcpy(un->fPtr, un->fBuf, un->fISize);
00591       un->fAction = DELETE;
00592       un->fDSize = un->fISize;
00593       un->fISize = 0;
00594       break;
00595 
00596    case CHANGE:
00597 
00598       if (un->fISize == 0) {
00599          return CC_NORM;
00600       }
00601 
00602       el->fLine.fCursor = un->fPtr;
00603       size = (int) (el->fLine.fCursor - el->fLine.fLastChar);
00604 
00605       if ((unsigned int) size < un->fISize) {
00606          size = un->fISize;
00607       }
00608       cp = un->fPtr;
00609       kp = un->fBuf;
00610 
00611       for (i = 0; i < size; i++) {
00612          temp = *kp;
00613          *kp++ = *cp;
00614          *cp++ = temp;
00615       }
00616       un->fDSize = 0;
00617       break;
00618 
00619    default:
00620       return CC_ERROR;
00621    } // switch
00622 
00623    return CC_REFRESH;
00624 } // em_undo

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