search.cxx

Go to the documentation of this file.
00001 // @(#)root/editline:$Id: search.cxx 36313 2010-10-12 12:40:20Z 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: search.c,v 1.11 2001/01/23 15:55:31 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 /*
00049  * search.c: History_t and character search functions
00050  */
00051 #include "sys.h"
00052 #include <stdlib.h>
00053 #if HAVE_SYS_TYPES_H
00054 # include <sys/types.h>
00055 #endif
00056 #if defined(REGEX)
00057 # include <regex.h>
00058 #elif defined(REGEXP)
00059 # include <regexp.h>
00060 #endif
00061 #include "el.h"
00062 #include "enhance.h"
00063 
00064 #define ANCHOR_SEARCHES 1
00065 // ^^^ don't undef ANCHOR_SEARCHES or set it to 0! It breaks ^R searches! (stephan)
00066 
00067 /*
00068  * Adjust cursor in vi mode to include the character under it
00069  */
00070 #define EL_CURSOR(el) \
00071    ((el)->fLine.fCursor + (((el)->fMap.fType == MAP_VI) && \
00072                             ((el)->fMap.fCurrent == (el)->fMap.fAlt)))
00073 
00074 /* search_init():
00075  *      Initialize the search stuff
00076  */
00077 el_protected int
00078 search_init(EditLine_t* el) {
00079    el->fSearch.fPatBuf = (char*) el_malloc(EL_BUFSIZ);
00080 
00081    if (el->fSearch.fPatBuf == NULL) {
00082       return -1;
00083    }
00084    el->fSearch.fPatLen = 0;
00085    el->fSearch.fPatDir = -1;
00086    el->fSearch.fChaCha = '\0';
00087    el->fSearch.fChaDir = -1;
00088    return 0;
00089 }
00090 
00091 
00092 /* search_end():
00093  *      Initialize the search stuff
00094  */
00095 el_protected void
00096 search_end(EditLine_t* el) {
00097    el_free((ptr_t) el->fSearch.fPatBuf);
00098    el->fSearch.fPatBuf = NULL;
00099 }
00100 
00101 
00102 #ifdef REGEXP
00103 
00104 /* regerror():
00105  *      Handle regular expression errors
00106  */
00107 el_public void
00108 /*ARGSUSED*/
00109 regerror(const char* msg) {
00110 }
00111 
00112 
00113 #endif
00114 
00115 
00116 /* el_match():
00117  *      Return if string matches pattern
00118  */
00119 el_protected int
00120 el_match(const char* str, const char* pat) {
00121 #if defined(REGEX)
00122    regex_t re;
00123    int rv;
00124 #elif defined(REGEXP)
00125    regexp* rp;
00126    int rv;
00127 #else
00128    extern char* re_comp(const char*);
00129    extern int re_exec(const char*);
00130 #endif
00131 
00132    if (strstr(str, pat) != NULL) {
00133       return 1;
00134    }
00135 
00136 #if defined(REGEX)
00137 
00138    if (regcomp(&re, pat, 0) == 0) {
00139       rv = regexec(&re, str, 0, NULL, 0) == 0;
00140       regfree(&re);
00141    } else {
00142       rv = 0;
00143    }
00144    return rv;
00145 #elif defined(REGEXP)
00146 
00147    if ((re = regcomp(pat)) != NULL) {
00148       rv = regexec(re, str);
00149       free((ptr_t) re);
00150    } else {
00151       rv = 0;
00152    }
00153    return rv;
00154 #else
00155 
00156    if (re_comp(pat) != NULL) {
00157       return 0;
00158    } else {
00159       return re_exec(str) == 1;
00160    }
00161 #endif
00162 } // el_match
00163 
00164 
00165 /* c_hmatch():
00166  *       return True if the pattern matches the prefix
00167  */
00168 el_protected int
00169 c_hmatch(EditLine_t* el, const char* str) {
00170 #ifdef SDEBUG
00171       (void) fprintf(el->fErrFile, "match `%s' with `%s'\n",
00172                      el->fSearch.fPatBuf, str);
00173 #endif /* SDEBUG */
00174 
00175    return el_match(str, el->fSearch.fPatBuf);
00176 }
00177 
00178 
00179 /* c_setpat():
00180  *      Set the history seatch pattern
00181  */
00182 el_protected void
00183 c_setpat(EditLine_t* el) {
00184    if (el->fState.fLastCmd != ED_SEARCH_PREV_HISTORY &&
00185        el->fState.fLastCmd != ED_SEARCH_NEXT_HISTORY) {
00186       el->fSearch.fPatLen = EL_CURSOR(el) - el->fLine.fBuffer;
00187 
00188       if (el->fSearch.fPatLen >= EL_BUFSIZ) {
00189          el->fSearch.fPatLen = EL_BUFSIZ - 1;
00190       }
00191 
00192       if (el->fSearch.fPatLen != 0) {
00193          (void) strncpy(el->fSearch.fPatBuf, el->fLine.fBuffer,
00194                         el->fSearch.fPatLen);
00195          el->fSearch.fPatBuf[el->fSearch.fPatLen] = '\0';
00196       } else {
00197          el->fSearch.fPatLen = strlen(el->fSearch.fPatBuf);
00198       }
00199    }
00200 #ifdef SDEBUG
00201       (void) fprintf(el->fErrFile, "\neventno = %d\n",
00202                      el->fHistory.fEventNo);
00203    (void) fprintf(el->fErrFile, "patlen = %d\n", el->fSearch.fPatLen);
00204    (void) fprintf(el->fErrFile, "patbuf = \"%s\"\n",
00205                   el->fSearch.fPatBuf);
00206    (void) fprintf(el->fErrFile, "cursor %d lastchar %d\n",
00207                   EL_CURSOR(el) - el->fLine.fBuffer,
00208                   el->fLine.fLastChar - el->fLine.fBuffer);
00209 #endif
00210 } // c_setpat
00211 
00212 
00213 /* ce_inc_search():
00214  *      Emacs incremental search
00215  */
00216 el_protected ElAction_t
00217 ce_inc_search(EditLine_t* el, int dir) {
00218    static const char strfwd[] = { 'f', 'w', 'd', '\0' },
00219                      strbck[] = { 'b', 'c', 'k', '\0' };
00220    static char pchar = ':';     /* ':' = normal, '?' = failed */
00221    static char endcmd[2] = { '\0', '\0' };
00222    char ch, * ocursor = el->fLine.fCursor, oldpchar = pchar;
00223    const char* cp;
00224 
00225    ElAction_t ret = CC_NORM;
00226 
00227    int ohisteventno = el->fHistory.fEventNo;
00228    int oldpatlen = el->fSearch.fPatLen;
00229    int newdir = dir;
00230    int done, redo;
00231 
00232    if (el->fLine.fLastChar + sizeof(strfwd) / sizeof(char) + 2 +
00233        el->fSearch.fPatLen >= el->fLine.fLimit) {
00234       return CC_ERROR;
00235    }
00236 
00237    for ( ; ;) {
00238       if (el->fSearch.fPatLen == 0) {                  /* first round */
00239          pchar = ':';
00240 #if ANCHOR_SEARCHES
00241          el->fSearch.fPatBuf[el->fSearch.fPatLen++] = '.';
00242          el->fSearch.fPatBuf[el->fSearch.fPatLen++] = '*';
00243 #endif
00244       }
00245       done = redo = 0;
00246       el->fLine.fBufColor[el->fLine.fLastChar - el->fLine.fBuffer] = -1;
00247       *el->fLine.fLastChar++ = '\n';
00248 
00249       for (cp = (newdir == ED_SEARCH_PREV_HISTORY) ? strbck : strfwd;
00250            *cp; *el->fLine.fLastChar++ = *cp++) {
00251          el->fLine.fBufColor[el->fLine.fLastChar - el->fLine.fBuffer] = -1;
00252       }
00253       el->fLine.fBufColor[el->fLine.fLastChar - el->fLine.fBuffer] = -1;
00254       *el->fLine.fLastChar++ = pchar;
00255 #if ANCHOR_SEARCHES
00256       cp = &el->fSearch.fPatBuf[2];
00257 #else
00258       cp = &el->fSearch.fPatBuf[1];
00259 #endif
00260 
00261       for ( ;
00262             cp < &el->fSearch.fPatBuf[el->fSearch.fPatLen];
00263             *el->fLine.fLastChar++ = *cp++) {
00264          el->fLine.fBufColor[el->fLine.fLastChar - el->fLine.fBuffer] = -1;
00265          continue;
00266       }
00267       el->fLine.fBufColor[el->fLine.fLastChar - el->fLine.fBuffer] = -1;
00268       *el->fLine.fLastChar = '\0';
00269 
00270       // Would love to highlight, but el_dispcolor isn't set up yet...
00271       //highlightKeywords(el);
00272       re_refresh(el);
00273 
00274       if (el_getc(el, &ch) != 1) {
00275          return ed_end_of_file(el, 0);
00276       }
00277 
00278       // Coverity is complaining that the value of ch comes from the user
00279       // and nowhere do we check its value. But that's fine: it's 0<=ch<255,
00280       // and fCurrent has 256 entries.
00281       // coverity[tainted_data]
00282       switch (el->fMap.fCurrent[(unsigned char) ch]) {
00283       case ED_INSERT:
00284       case ED_DIGIT:
00285 
00286          if (el->fSearch.fPatLen > EL_BUFSIZ - 3) {
00287             term_beep(el);
00288          } else {
00289             el->fSearch.fPatBuf[el->fSearch.fPatLen++] =
00290                ch;
00291             el->fLine.fBufColor[el->fLine.fLastChar - el->fLine.fBuffer] = -1;
00292             *el->fLine.fLastChar++ = ch;
00293             el->fLine.fBufColor[el->fLine.fLastChar - el->fLine.fBuffer] = -1;
00294             *el->fLine.fLastChar = '\0';
00295             re_refresh(el);
00296          }
00297          break;
00298 
00299       case EM_INC_SEARCH_NEXT:
00300          newdir = ED_SEARCH_NEXT_HISTORY;
00301          redo++;
00302          break;
00303 
00304       case EM_INC_SEARCH_PREV:
00305          newdir = ED_SEARCH_PREV_HISTORY;
00306          redo++;
00307          break;
00308 
00309       case ED_DELETE_PREV_CHAR:
00310 
00311          if (el->fSearch.fPatLen > 1) {
00312             done++;
00313          } else {
00314             term_beep(el);
00315          }
00316          break;
00317 
00318       default:
00319 
00320          switch (ch) {
00321          case 0007:                     /* ^G: Abort */
00322             ret = CC_ERROR;
00323             done++;
00324             break;
00325 
00326          case 0027:                     /* ^W: Append word */
00327 
00328             /* No can do if globbing characters in pattern */
00329             for (cp = &el->fSearch.fPatBuf[1]; ; cp++) {
00330                if (cp >= &el->fSearch.fPatBuf[el->fSearch.fPatLen]) {
00331                   el->fLine.fCursor +=
00332                      el->fSearch.fPatLen - 1;
00333                   cp = c__next_word(el->fLine.fCursor,
00334                                     el->fLine.fLastChar, 1,
00335                                     ce__isword);
00336 
00337                   while (el->fLine.fCursor < cp &&
00338                          *el->fLine.fCursor != '\n') {
00339                      if (el->fSearch.fPatLen >
00340                          EL_BUFSIZ - 3) {
00341                         term_beep(el);
00342                         break;
00343                      }
00344                      el->fSearch.fPatBuf[el->fSearch.fPatLen++] =
00345                         *el->fLine.fCursor;
00346                      el->fLine.fBufColor[el->fLine.fLastChar - el->fLine.fBuffer] =
00347                         el->fLine.fBufColor[el->fLine.fCursor - el->fLine.fBuffer];
00348                      *el->fLine.fLastChar++ =
00349                         *el->fLine.fCursor++;
00350                   }
00351                   el->fLine.fCursor = ocursor;
00352                   el->fLine.fBufColor[el->fLine.fLastChar - el->fLine.fBuffer] = -1;
00353                   *el->fLine.fLastChar = '\0';
00354                   re_refresh(el);
00355                   break;
00356                } else if (isglob(*cp)) {
00357                   term_beep(el);
00358                   break;
00359                }
00360             }
00361             break;
00362 
00363          default:                       /* Terminate and execute cmd */
00364             endcmd[0] = ch;
00365             el_push(el, endcmd);
00366             ret = CC_REFRESH;
00367             done++;
00368             break;
00369          } // switch
00370          break;
00371       } // switch
00372 
00373       while (el->fLine.fLastChar > el->fLine.fBuffer &&
00374              *el->fLine.fLastChar != '\n') {
00375          el->fLine.fBufColor[el->fLine.fLastChar - el->fLine.fBuffer] = -1;
00376          *el->fLine.fLastChar-- = '\0';
00377       }
00378       el->fLine.fBufColor[el->fLine.fLastChar - el->fLine.fBuffer] = -1;
00379       *el->fLine.fLastChar = '\0';
00380 
00381       if (!done) {
00382          /* Can't search if unmatched '[' */
00383          ch = ']';
00384          for (cp = &el->fSearch.fPatBuf[el->fSearch.fPatLen - 1];
00385               cp > el->fSearch.fPatBuf; cp--) {
00386             if (*cp == '[' || *cp == ']') {
00387                ch = *cp;
00388                break;
00389             }
00390          }
00391 
00392          if (el->fSearch.fPatLen > 1 && ch != '[') {
00393             if (redo && newdir == dir) {
00394                if (pchar == '?') {                          /* wrap around */
00395                   el->fHistory.fEventNo =
00396                      newdir == ED_SEARCH_PREV_HISTORY ? 0 : 0x7fffffff;
00397 
00398                   if (hist_get(el) == CC_ERROR) {
00399                      /* el->fHistory.event
00400                       * no was fixed by
00401                       * first call */
00402                      (void) hist_get(el);
00403                   }
00404                   el->fLine.fCursor = newdir ==
00405                                        ED_SEARCH_PREV_HISTORY ?
00406                                        el->fLine.fLastChar :
00407                                        el->fLine.fBuffer;
00408                } else {
00409                   el->fLine.fCursor +=
00410                      newdir ==
00411                      ED_SEARCH_PREV_HISTORY ?
00412                      -1 : 1;
00413                }
00414             }
00415 #if ANCHOR_SEARCHES
00416             el->fSearch.fPatBuf[el->fSearch.fPatLen++] =
00417                '.';
00418             el->fSearch.fPatBuf[el->fSearch.fPatLen++] =
00419                '*';
00420 #endif
00421             el->fSearch.fPatBuf[el->fSearch.fPatLen] =
00422                '\0';
00423 
00424             if (el->fLine.fCursor < el->fLine.fBuffer ||
00425                 el->fLine.fCursor > el->fLine.fLastChar ||
00426                 (ret = ce_search_line(el, &el->fSearch.fPatBuf[1], newdir)) == CC_ERROR) {
00427                /* avoid c_setpat */
00428                el->fState.fLastCmd =
00429                   (ElAction_t) newdir;
00430                ret = newdir == ED_SEARCH_PREV_HISTORY ?
00431                      ed_search_prev_history(el, 0) :
00432                      ed_search_next_history(el, 0);
00433 
00434                if (ret != CC_ERROR) {
00435                   el->fLine.fCursor = newdir ==
00436                                        ED_SEARCH_PREV_HISTORY ?
00437                                        el->fLine.fLastChar :
00438                                        el->fLine.fBuffer;
00439                   (void) ce_search_line(el,
00440                                         &el->fSearch.fPatBuf[1],
00441                                         newdir);
00442                }
00443             }
00444 #if ANCHOR_SEARCHES
00445             el->fSearch.fPatLen -= 2;
00446             el->fSearch.fPatBuf[el->fSearch.fPatLen] = 0;
00447 #else
00448             el->fSearch.fPatBuf[--el->fSearch.fPatLen] = 0;
00449 #endif
00450 
00451             if (ret == CC_ERROR) {
00452                term_beep(el);
00453 
00454                if (el->fHistory.fEventNo !=
00455                    ohisteventno) {
00456                   el->fHistory.fEventNo =
00457                      ohisteventno;
00458 
00459                   if (hist_get(el) == CC_ERROR) {
00460                      return CC_ERROR;
00461                   }
00462                }
00463                el->fLine.fCursor = ocursor;
00464                pchar = '?';
00465             } else {
00466                pchar = ':';
00467             }
00468          }
00469          ret = ce_inc_search(el, newdir);
00470 
00471          if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') {
00472             /*
00473              * break abort of failed search at last
00474              * non-failed
00475              */
00476             ret = CC_NORM;
00477          }
00478 
00479       }
00480 
00481       if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) {
00482          /* restore on normal return or error exit */
00483          pchar = oldpchar;
00484          el->fSearch.fPatLen = oldpatlen;
00485 
00486          if (el->fHistory.fEventNo != ohisteventno) {
00487             el->fHistory.fEventNo = ohisteventno;
00488 
00489             if (hist_get(el) == CC_ERROR) {
00490                return CC_ERROR;
00491             }
00492          }
00493          el->fLine.fCursor = ocursor;
00494 
00495          if (ret == CC_ERROR) {
00496             re_refresh(el);
00497          }
00498       }
00499 
00500       if (done || ret != CC_NORM) {
00501          return ret;
00502       }
00503    }
00504 } // ce_inc_search
00505 
00506 
00507 /* cv_search():
00508  *      Vi search.
00509  */
00510 el_protected ElAction_t
00511 cv_search(EditLine_t* el, int dir) {
00512    char ch;
00513    char tmpbuf[EL_BUFSIZ];
00514    int tmplen;
00515 
00516    tmplen = 0;
00517 #if ANCHOR_SEARCHES
00518    tmpbuf[tmplen++] = '.';
00519    tmpbuf[tmplen++] = '*';
00520 #endif
00521 
00522    el->fLine.fBuffer[0] = '\0';
00523    el->fLine.fLastChar = el->fLine.fBuffer;
00524    el->fLine.fCursor = el->fLine.fBuffer;
00525    el->fSearch.fPatDir = dir;
00526 
00527    c_insert(el, 2);             /* prompt + '\n' */
00528    *el->fLine.fCursor++ = '\n';
00529    *el->fLine.fCursor++ = dir == ED_SEARCH_PREV_HISTORY ? '/' : '?';
00530    re_refresh(el);
00531 
00532 #if ANCHOR_SEARCHES
00533 # define LEN 2
00534 #else
00535 # define LEN 0
00536 #endif
00537 
00538    tmplen = c_gets(el, &tmpbuf[LEN]) + LEN;
00539    ch = tmpbuf[tmplen];
00540    tmpbuf[tmplen] = '\0';
00541 
00542    if (tmplen == LEN) {
00543       /*
00544        * Use the old pattern, but wild-card it.
00545        */
00546       if (el->fSearch.fPatLen == 0) {
00547          el->fLine.fBuffer[0] = '\0';
00548          el->fLine.fLastChar = el->fLine.fBuffer;
00549          el->fLine.fCursor = el->fLine.fBuffer;
00550          re_refresh(el);
00551          return CC_ERROR;
00552       }
00553 #if ANCHOR_SEARCHES
00554 
00555       if (el->fSearch.fPatBuf[0] != '.' &&
00556           el->fSearch.fPatBuf[0] != '*') {
00557          (void) strncpy(tmpbuf, el->fSearch.fPatBuf,
00558                         sizeof(tmpbuf) - 1);
00559          el->fSearch.fPatBuf[0] = '.';
00560          el->fSearch.fPatBuf[1] = '*';
00561          (void) strncpy(&el->fSearch.fPatBuf[2], tmpbuf,
00562                         EL_BUFSIZ - 3);
00563          el->fSearch.fPatLen++;
00564          el->fSearch.fPatBuf[el->fSearch.fPatLen++] = '.';
00565          el->fSearch.fPatBuf[el->fSearch.fPatLen++] = '*';
00566          el->fSearch.fPatBuf[el->fSearch.fPatLen] = '\0';
00567       }
00568 #endif
00569    } else {
00570 #if ANCHOR_SEARCHES
00571       tmpbuf[tmplen++] = '.';
00572       tmpbuf[tmplen++] = '*';
00573 #endif
00574       tmpbuf[tmplen] = '\0';
00575       (void) strncpy(el->fSearch.fPatBuf, tmpbuf, EL_BUFSIZ - 1);
00576       el->fSearch.fPatLen = tmplen;
00577    }
00578    el->fState.fLastCmd = (ElAction_t) dir;            /* avoid c_setpat */
00579    el->fLine.fCursor = el->fLine.fLastChar = el->fLine.fBuffer;
00580 
00581    if ((dir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) :
00582         ed_search_next_history(el, 0)) == CC_ERROR) {
00583       re_refresh(el);
00584       return CC_ERROR;
00585    } else {
00586       if (ch == 0033) {
00587          re_refresh(el);
00588          *el->fLine.fLastChar++ = '\n';
00589          *el->fLine.fLastChar = '\0';
00590          re_goto_bottom(el);
00591          return CC_NEWLINE;
00592       } else {
00593          return CC_REFRESH;
00594       }
00595    }
00596 } // cv_search
00597 
00598 
00599 /* ce_search_line():
00600  *      Look for a pattern inside a line
00601  */
00602 el_protected ElAction_t
00603 ce_search_line(EditLine_t* el, char* pattern, int dir) {
00604    char* cp;
00605 
00606    if (dir == ED_SEARCH_PREV_HISTORY) {
00607       for (cp = el->fLine.fCursor; cp >= el->fLine.fBuffer; cp--) {
00608          if (el_match(cp, pattern)) {
00609             el->fLine.fCursor = cp;
00610             return CC_NORM;
00611          }
00612       }
00613       return CC_ERROR;
00614    } else {
00615       for (cp = el->fLine.fCursor; *cp != '\0' &&
00616            cp < el->fLine.fLimit; cp++) {
00617          if (el_match(cp, pattern)) {
00618             el->fLine.fCursor = cp;
00619             return CC_NORM;
00620          }
00621       }
00622       return CC_ERROR;
00623    }
00624 } // ce_search_line
00625 
00626 
00627 /* cv_repeat_srch():
00628  *      Vi repeat search
00629  */
00630 el_protected ElAction_t
00631 cv_repeat_srch(EditLine_t* el, int c) {
00632 #ifdef SDEBUG
00633       (void) fprintf(el->fErrFile, "dir %d patlen %d patbuf %s\n",
00634                      c, el->fSearch.fPatLen, el->fSearch.fPatBuf);
00635 #endif
00636 
00637    el->fState.fLastCmd = (ElAction_t) c;      /* Hack to stop c_setpat */
00638    el->fLine.fLastChar = el->fLine.fBuffer;
00639 
00640    switch (c) {
00641    case ED_SEARCH_NEXT_HISTORY:
00642       return ed_search_next_history(el, 0);
00643    case ED_SEARCH_PREV_HISTORY:
00644       return ed_search_prev_history(el, 0);
00645    default:
00646       return CC_ERROR;
00647    }
00648 } // cv_repeat_srch
00649 
00650 
00651 /* cv_csearch_back():
00652  *      Vi character search reverse
00653  */
00654 el_protected ElAction_t
00655 cv_csearch_back(EditLine_t* el, int ch, int count, int tflag) {
00656    char* cp;
00657 
00658    cp = el->fLine.fCursor;
00659 
00660    while (count--) {
00661       if (*cp == ch) {
00662          cp--;
00663       }
00664 
00665       while (cp > el->fLine.fBuffer && *cp != ch)
00666          cp--;
00667    }
00668 
00669    if (cp < el->fLine.fBuffer || (cp == el->fLine.fBuffer && *cp != ch)) {
00670       return CC_ERROR;
00671    }
00672 
00673    if (*cp == ch && tflag) {
00674       cp++;
00675    }
00676 
00677    el->fLine.fCursor = cp;
00678 
00679    if (el->fCharEd.fVCmd.fAction & DELETE) {
00680       el->fLine.fCursor++;
00681       cv_delfini(el);
00682       return CC_REFRESH;
00683    }
00684    re_refresh_cursor(el);
00685    return CC_NORM;
00686 } // cv_csearch_back
00687 
00688 
00689 /* cv_csearch_fwd():
00690  *      Vi character search forward
00691  */
00692 el_protected ElAction_t
00693 cv_csearch_fwd(EditLine_t* el, int ch, int count, int tflag) {
00694    char* cp;
00695 
00696    cp = el->fLine.fCursor;
00697 
00698    while (count--) {
00699       if (*cp == ch) {
00700          cp++;
00701       }
00702 
00703       while (cp < el->fLine.fLastChar && *cp != ch)
00704          cp++;
00705    }
00706 
00707    if (cp >= el->fLine.fLastChar) {
00708       return CC_ERROR;
00709    }
00710 
00711    if (*cp == ch && tflag) {
00712       cp--;
00713    }
00714 
00715    el->fLine.fCursor = cp;
00716 
00717    if (el->fCharEd.fVCmd.fAction & DELETE) {
00718       el->fLine.fCursor++;
00719       cv_delfini(el);
00720       return CC_REFRESH;
00721    }
00722    re_refresh_cursor(el);
00723    return CC_NORM;
00724 } // cv_csearch_fwd

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