The world's most popular open source database
00001 /* $NetBSD: chared.c,v 1.22 2004/08/13 12:10:38 mycroft Exp $ */ 00002 00003 /*- 00004 * Copyright (c) 1992, 1993 00005 * The Regents of the University of California. All rights reserved. 00006 * 00007 * This code is derived from software contributed to Berkeley by 00008 * Christos Zoulas of Cornell University. 00009 * 00010 * Redistribution and use in source and binary forms, with or without 00011 * modification, are permitted provided that the following conditions 00012 * are met: 00013 * 1. Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * 2. Redistributions in binary form must reproduce the above copyright 00016 * notice, this list of conditions and the following disclaimer in the 00017 * documentation and/or other materials provided with the distribution. 00018 * 3. Neither the name of the University nor the names of its contributors 00019 * may be used to endorse or promote products derived from this software 00020 * without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 00023 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00024 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00025 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 00026 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00027 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00028 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00029 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00031 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00032 * SUCH DAMAGE. 00033 */ 00034 00035 #include <config.h> 00036 00037 /* 00038 * chared.c: Character editor utilities 00039 */ 00040 #include <stdlib.h> 00041 #include "el.h" 00042 00043 /* value to leave unused in line buffer */ 00044 #define EL_LEAVE 2 00045 00046 /* cv_undo(): 00047 * Handle state for the vi undo command 00048 */ 00049 protected void 00050 cv_undo(EditLine *el) 00051 { 00052 c_undo_t *vu = &el->el_chared.c_undo; 00053 c_redo_t *r = &el->el_chared.c_redo; 00054 int size; 00055 00056 /* Save entire line for undo */ 00057 size = el->el_line.lastchar - el->el_line.buffer; 00058 vu->len = size; 00059 vu->cursor = el->el_line.cursor - el->el_line.buffer; 00060 memcpy(vu->buf, el->el_line.buffer, (size_t)size); 00061 00062 /* save command info for redo */ 00063 r->count = el->el_state.doingarg ? el->el_state.argument : 0; 00064 r->action = el->el_chared.c_vcmd.action; 00065 r->pos = r->buf; 00066 r->cmd = el->el_state.thiscmd; 00067 r->ch = el->el_state.thisch; 00068 } 00069 00070 /* cv_yank(): 00071 * Save yank/delete data for paste 00072 */ 00073 protected void 00074 cv_yank(EditLine *el, const char *ptr, int size) 00075 { 00076 c_kill_t *k = &el->el_chared.c_kill; 00077 00078 memcpy(k->buf, ptr, size +0u); 00079 k->last = k->buf + size; 00080 } 00081 00082 00083 /* c_insert(): 00084 * Insert num characters 00085 */ 00086 protected void 00087 c_insert(EditLine *el, int num) 00088 { 00089 char *cp; 00090 00091 if (el->el_line.lastchar + num >= el->el_line.limit) { 00092 if (!ch_enlargebufs(el, num +0u)) 00093 return; /* can't go past end of buffer */ 00094 } 00095 00096 if (el->el_line.cursor < el->el_line.lastchar) { 00097 /* if I must move chars */ 00098 for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--) 00099 cp[num] = *cp; 00100 } 00101 el->el_line.lastchar += num; 00102 } 00103 00104 00105 /* c_delafter(): 00106 * Delete num characters after the cursor 00107 */ 00108 protected void 00109 c_delafter(EditLine *el, int num) 00110 { 00111 00112 if (el->el_line.cursor + num > el->el_line.lastchar) 00113 num = el->el_line.lastchar - el->el_line.cursor; 00114 00115 if (el->el_map.current != el->el_map.emacs) { 00116 cv_undo(el); 00117 cv_yank(el, el->el_line.cursor, num); 00118 } 00119 00120 if (num > 0) { 00121 char *cp; 00122 00123 for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) 00124 *cp = cp[num]; 00125 00126 el->el_line.lastchar -= num; 00127 } 00128 } 00129 00130 00131 /* c_delafter1(): 00132 * Delete the character after the cursor, do not yank 00133 */ 00134 protected void 00135 c_delafter1(EditLine *el) 00136 { 00137 char *cp; 00138 00139 for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) 00140 *cp = cp[1]; 00141 00142 el->el_line.lastchar--; 00143 } 00144 00145 00146 /* c_delbefore(): 00147 * Delete num characters before the cursor 00148 */ 00149 protected void 00150 c_delbefore(EditLine *el, int num) 00151 { 00152 00153 if (el->el_line.cursor - num < el->el_line.buffer) 00154 num = el->el_line.cursor - el->el_line.buffer; 00155 00156 if (el->el_map.current != el->el_map.emacs) { 00157 cv_undo(el); 00158 cv_yank(el, el->el_line.cursor - num, num); 00159 } 00160 00161 if (num > 0) { 00162 char *cp; 00163 00164 for (cp = el->el_line.cursor - num; 00165 cp <= el->el_line.lastchar; 00166 cp++) 00167 *cp = cp[num]; 00168 00169 el->el_line.lastchar -= num; 00170 } 00171 } 00172 00173 00174 /* c_delbefore1(): 00175 * Delete the character before the cursor, do not yank 00176 */ 00177 protected void 00178 c_delbefore1(EditLine *el) 00179 { 00180 char *cp; 00181 00182 for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++) 00183 *cp = cp[1]; 00184 00185 el->el_line.lastchar--; 00186 } 00187 00188 00189 /* ce__isword(): 00190 * Return if p is part of a word according to emacs 00191 */ 00192 protected int 00193 ce__isword(int p) 00194 { 00195 return (isalnum(p) || strchr("*?_-.[]~=", p) != NULL); 00196 } 00197 00198 00199 /* cv__isword(): 00200 * Return if p is part of a word according to vi 00201 */ 00202 protected int 00203 cv__isword(int p) 00204 { 00205 if (isalnum(p) || p == '_') 00206 return 1; 00207 if (isgraph(p)) 00208 return 2; 00209 return 0; 00210 } 00211 00212 00213 /* cv__isWord(): 00214 * Return if p is part of a big word according to vi 00215 */ 00216 protected int 00217 cv__isWord(int p) 00218 { 00219 return (!isspace(p)); 00220 } 00221 00222 00223 /* c__prev_word(): 00224 * Find the previous word 00225 */ 00226 protected char * 00227 c__prev_word(char *p, char *low, int n, int (*wtest)(int)) 00228 { 00229 p--; 00230 00231 while (n--) { 00232 while ((p >= low) && !(*wtest)((unsigned char) *p)) 00233 p--; 00234 while ((p >= low) && (*wtest)((unsigned char) *p)) 00235 p--; 00236 } 00237 00238 /* cp now points to one character before the word */ 00239 p++; 00240 if (p < low) 00241 p = low; 00242 /* cp now points where we want it */ 00243 return (p); 00244 } 00245 00246 00247 /* c__next_word(): 00248 * Find the next word 00249 */ 00250 protected char * 00251 c__next_word(char *p, char *high, int n, int (*wtest)(int)) 00252 { 00253 while (n--) { 00254 while ((p < high) && !(*wtest)((unsigned char) *p)) 00255 p++; 00256 while ((p < high) && (*wtest)((unsigned char) *p)) 00257 p++; 00258 } 00259 if (p > high) 00260 p = high; 00261 /* p now points where we want it */ 00262 return (p); 00263 } 00264 00265 /* cv_next_word(): 00266 * Find the next word vi style 00267 */ 00268 protected char * 00269 cv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int)) 00270 { 00271 int test; 00272 00273 while (n--) { 00274 test = (*wtest)((unsigned char) *p); 00275 while ((p < high) && (*wtest)((unsigned char) *p) == test) 00276 p++; 00277 /* 00278 * vi historically deletes with cw only the word preserving the 00279 * trailing whitespace! This is not what 'w' does.. 00280 */ 00281 if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT)) 00282 while ((p < high) && isspace((unsigned char) *p)) 00283 p++; 00284 } 00285 00286 /* p now points where we want it */ 00287 if (p > high) 00288 return (high); 00289 else 00290 return (p); 00291 } 00292 00293 00294 /* cv_prev_word(): 00295 * Find the previous word vi style 00296 */ 00297 protected char * 00298 cv_prev_word(char *p, char *low, int n, int (*wtest)(int)) 00299 { 00300 int test; 00301 00302 p--; 00303 while (n--) { 00304 while ((p > low) && isspace((unsigned char) *p)) 00305 p--; 00306 test = (*wtest)((unsigned char) *p); 00307 while ((p >= low) && (*wtest)((unsigned char) *p) == test) 00308 p--; 00309 } 00310 p++; 00311 00312 /* p now points where we want it */ 00313 if (p < low) 00314 return (low); 00315 else 00316 return (p); 00317 } 00318 00319 00320 #ifdef notdef 00321 /* c__number(): 00322 * Ignore character p points to, return number appearing after that. 00323 * A '$' by itself means a big number; "$-" is for negative; '^' means 1. 00324 * Return p pointing to last char used. 00325 */ 00326 protected char * 00327 c__number( 00328 char *p, /* character position */ 00329 int *num, /* Return value */ 00330 int dval) /* dval is the number to subtract from like $-3 */ 00331 { 00332 int i; 00333 int sign = 1; 00334 00335 if (*++p == '^') { 00336 *num = 1; 00337 return (p); 00338 } 00339 if (*p == '$') { 00340 if (*++p != '-') { 00341 *num = 0x7fffffff; /* Handle $ */ 00342 return (--p); 00343 } 00344 sign = -1; /* Handle $- */ 00345 ++p; 00346 } 00347 for (i = 0; isdigit((unsigned char) *p); i = 10 * i + *p++ - '0') 00348 continue; 00349 *num = (sign < 0 ? dval - i : i); 00350 return (--p); 00351 } 00352 #endif 00353 00354 /* cv_delfini(): 00355 * Finish vi delete action 00356 */ 00357 protected void 00358 cv_delfini(EditLine *el) 00359 { 00360 int size; 00361 int action = el->el_chared.c_vcmd.action; 00362 00363 if (action & INSERT) 00364 el->el_map.current = el->el_map.key; 00365 00366 if (el->el_chared.c_vcmd.pos == 0) 00367 /* sanity */ 00368 return; 00369 00370 size = el->el_line.cursor - el->el_chared.c_vcmd.pos; 00371 if (size == 0) 00372 size = 1; 00373 el->el_line.cursor = el->el_chared.c_vcmd.pos; 00374 if (action & YANK) { 00375 if (size > 0) 00376 cv_yank(el, el->el_line.cursor, size); 00377 else 00378 cv_yank(el, el->el_line.cursor + size, -size); 00379 } else { 00380 if (size > 0) { 00381 c_delafter(el, size); 00382 re_refresh_cursor(el); 00383 } else { 00384 c_delbefore(el, -size); 00385 el->el_line.cursor += size; 00386 } 00387 } 00388 el->el_chared.c_vcmd.action = NOP; 00389 } 00390 00391 00392 #ifdef notdef 00393 /* ce__endword(): 00394 * Go to the end of this word according to emacs 00395 */ 00396 protected char * 00397 ce__endword(char *p, char *high, int n) 00398 { 00399 p++; 00400 00401 while (n--) { 00402 while ((p < high) && isspace((unsigned char) *p)) 00403 p++; 00404 while ((p < high) && !isspace((unsigned char) *p)) 00405 p++; 00406 } 00407 00408 p--; 00409 return (p); 00410 } 00411 #endif 00412 00413 00414 /* cv__endword(): 00415 * Go to the end of this word according to vi 00416 */ 00417 protected char * 00418 cv__endword(char *p, char *high, int n, int (*wtest)(int)) 00419 { 00420 int test; 00421 00422 p++; 00423 00424 while (n--) { 00425 while ((p < high) && isspace((unsigned char) *p)) 00426 p++; 00427 00428 test = (*wtest)((unsigned char) *p); 00429 while ((p < high) && (*wtest)((unsigned char) *p) == test) 00430 p++; 00431 } 00432 p--; 00433 return (p); 00434 } 00435 00436 /* ch_init(): 00437 * Initialize the character editor 00438 */ 00439 protected int 00440 ch_init(EditLine *el) 00441 { 00442 el->el_line.buffer = (char *) el_malloc(EL_BUFSIZ); 00443 if (el->el_line.buffer == NULL) 00444 return (-1); 00445 00446 (void) memset(el->el_line.buffer, 0, EL_BUFSIZ); 00447 el->el_line.cursor = el->el_line.buffer; 00448 el->el_line.lastchar = el->el_line.buffer; 00449 el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE]; 00450 00451 el->el_chared.c_undo.buf = (char *) el_malloc(EL_BUFSIZ); 00452 if (el->el_chared.c_undo.buf == NULL) 00453 return (-1); 00454 (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ); 00455 el->el_chared.c_undo.len = -1; 00456 el->el_chared.c_undo.cursor = 0; 00457 el->el_chared.c_redo.buf = (char *) el_malloc(EL_BUFSIZ); 00458 if (el->el_chared.c_redo.buf == NULL) 00459 return (-1); 00460 el->el_chared.c_redo.pos = el->el_chared.c_redo.buf; 00461 el->el_chared.c_redo.lim = el->el_chared.c_redo.buf + EL_BUFSIZ; 00462 el->el_chared.c_redo.cmd = ED_UNASSIGNED; 00463 00464 el->el_chared.c_vcmd.action = NOP; 00465 el->el_chared.c_vcmd.pos = el->el_line.buffer; 00466 00467 el->el_chared.c_kill.buf = (char *) el_malloc(EL_BUFSIZ); 00468 if (el->el_chared.c_kill.buf == NULL) 00469 return (-1); 00470 (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ); 00471 el->el_chared.c_kill.mark = el->el_line.buffer; 00472 el->el_chared.c_kill.last = el->el_chared.c_kill.buf; 00473 00474 el->el_map.current = el->el_map.key; 00475 00476 el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ 00477 el->el_state.doingarg = 0; 00478 el->el_state.metanext = 0; 00479 el->el_state.argument = 1; 00480 el->el_state.lastcmd = ED_UNASSIGNED; 00481 00482 el->el_chared.c_macro.level = -1; 00483 el->el_chared.c_macro.offset = 0; 00484 el->el_chared.c_macro.macro = (char **) el_malloc(EL_MAXMACRO * 00485 sizeof(char *)); 00486 if (el->el_chared.c_macro.macro == NULL) 00487 return (-1); 00488 return (0); 00489 } 00490 00491 /* ch_reset(): 00492 * Reset the character editor 00493 */ 00494 protected void 00495 ch_reset(EditLine *el) 00496 { 00497 el->el_line.cursor = el->el_line.buffer; 00498 el->el_line.lastchar = el->el_line.buffer; 00499 00500 el->el_chared.c_undo.len = -1; 00501 el->el_chared.c_undo.cursor = 0; 00502 00503 el->el_chared.c_vcmd.action = NOP; 00504 el->el_chared.c_vcmd.pos = el->el_line.buffer; 00505 00506 el->el_chared.c_kill.mark = el->el_line.buffer; 00507 00508 el->el_map.current = el->el_map.key; 00509 00510 el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */ 00511 el->el_state.doingarg = 0; 00512 el->el_state.metanext = 0; 00513 el->el_state.argument = 1; 00514 el->el_state.lastcmd = ED_UNASSIGNED; 00515 00516 el->el_chared.c_macro.level = -1; 00517 00518 el->el_history.eventno = 0; 00519 } 00520 00521 /* ch_enlargebufs(): 00522 * Enlarge line buffer to be able to hold twice as much characters. 00523 * Returns 1 if successful, 0 if not. 00524 */ 00525 protected int 00526 ch_enlargebufs(el, addlen) 00527 EditLine *el; 00528 size_t addlen; 00529 { 00530 size_t sz, newsz; 00531 char *newbuffer, *oldbuf, *oldkbuf; 00532 00533 sz = el->el_line.limit - el->el_line.buffer + EL_LEAVE; 00534 newsz = sz * 2; 00535 /* 00536 * If newly required length is longer than current buffer, we need 00537 * to make the buffer big enough to hold both old and new stuff. 00538 */ 00539 if (addlen > sz) { 00540 while(newsz - sz < addlen) 00541 newsz *= 2; 00542 } 00543 00544 /* 00545 * Reallocate line buffer. 00546 */ 00547 newbuffer = el_realloc(el->el_line.buffer, newsz); 00548 if (!newbuffer) 00549 return 0; 00550 00551 /* zero the newly added memory, leave old data in */ 00552 (void) memset(&newbuffer[sz], 0, newsz - sz); 00553 00554 oldbuf = el->el_line.buffer; 00555 00556 el->el_line.buffer = newbuffer; 00557 el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf); 00558 el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf); 00559 /* don't set new size until all buffers are enlarged */ 00560 el->el_line.limit = &newbuffer[sz - EL_LEAVE]; 00561 00562 /* 00563 * Reallocate kill buffer. 00564 */ 00565 newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz); 00566 if (!newbuffer) 00567 return 0; 00568 00569 /* zero the newly added memory, leave old data in */ 00570 (void) memset(&newbuffer[sz], 0, newsz - sz); 00571 00572 oldkbuf = el->el_chared.c_kill.buf; 00573 00574 el->el_chared.c_kill.buf = newbuffer; 00575 el->el_chared.c_kill.last = newbuffer + 00576 (el->el_chared.c_kill.last - oldkbuf); 00577 el->el_chared.c_kill.mark = el->el_line.buffer + 00578 (el->el_chared.c_kill.mark - oldbuf); 00579 00580 /* 00581 * Reallocate undo buffer. 00582 */ 00583 newbuffer = el_realloc(el->el_chared.c_undo.buf, newsz); 00584 if (!newbuffer) 00585 return 0; 00586 00587 /* zero the newly added memory, leave old data in */ 00588 (void) memset(&newbuffer[sz], 0, newsz - sz); 00589 el->el_chared.c_undo.buf = newbuffer; 00590 00591 newbuffer = el_realloc(el->el_chared.c_redo.buf, newsz); 00592 if (!newbuffer) 00593 return 0; 00594 el->el_chared.c_redo.pos = newbuffer + 00595 (el->el_chared.c_redo.pos - el->el_chared.c_redo.buf); 00596 el->el_chared.c_redo.lim = newbuffer + 00597 (el->el_chared.c_redo.lim - el->el_chared.c_redo.buf); 00598 el->el_chared.c_redo.buf = newbuffer; 00599 00600 if (!hist_enlargebuf(el, sz, newsz)) 00601 return 0; 00602 00603 /* Safe to set enlarged buffer size */ 00604 el->el_line.limit = &el->el_line.buffer[newsz - EL_LEAVE]; 00605 return 1; 00606 } 00607 00608 /* ch_end(): 00609 * Free the data structures used by the editor 00610 */ 00611 protected void 00612 ch_end(EditLine *el) 00613 { 00614 el_free((ptr_t) el->el_line.buffer); 00615 el->el_line.buffer = NULL; 00616 el->el_line.limit = NULL; 00617 el_free((ptr_t) el->el_chared.c_undo.buf); 00618 el->el_chared.c_undo.buf = NULL; 00619 el_free((ptr_t) el->el_chared.c_redo.buf); 00620 el->el_chared.c_redo.buf = NULL; 00621 el->el_chared.c_redo.pos = NULL; 00622 el->el_chared.c_redo.lim = NULL; 00623 el->el_chared.c_redo.cmd = ED_UNASSIGNED; 00624 el_free((ptr_t) el->el_chared.c_kill.buf); 00625 el->el_chared.c_kill.buf = NULL; 00626 el_free((ptr_t) el->el_chared.c_macro.macro); 00627 el->el_chared.c_macro.macro = NULL; 00628 ch_reset(el); 00629 } 00630 00631 00632 /* el_insertstr(): 00633 * Insert string at cursorI 00634 */ 00635 public int 00636 el_insertstr(EditLine *el, const char *s) 00637 { 00638 size_t len; 00639 00640 if ((len = strlen(s)) == 0) 00641 return (-1); 00642 if (el->el_line.lastchar + len >= el->el_line.limit) { 00643 if (!ch_enlargebufs(el, len)) 00644 return (-1); 00645 } 00646 00647 c_insert(el, (int)len); 00648 while (*s) 00649 *el->el_line.cursor++ = *s++; 00650 return (0); 00651 } 00652 00653 00654 /* el_deletestr(): 00655 * Delete num characters before the cursor 00656 */ 00657 public void 00658 el_deletestr(EditLine *el, int n) 00659 { 00660 if (n <= 0) 00661 return; 00662 00663 if (el->el_line.cursor < &el->el_line.buffer[n]) 00664 return; 00665 00666 c_delbefore(el, n); /* delete before dot */ 00667 el->el_line.cursor -= n; 00668 if (el->el_line.cursor < el->el_line.buffer) 00669 el->el_line.cursor = el->el_line.buffer; 00670 } 00671 00672 /* c_gets(): 00673 * Get a string 00674 */ 00675 protected int 00676 c_gets(EditLine *el, char *buf, const char *prompt) 00677 { 00678 char ch; 00679 int len; 00680 char *cp = el->el_line.buffer; 00681 00682 if (prompt) { 00683 len = strlen(prompt); 00684 memcpy(cp, prompt, len + 0u); 00685 cp += len; 00686 } 00687 len = 0; 00688 00689 for (;;) { 00690 el->el_line.cursor = cp; 00691 *cp = ' '; 00692 el->el_line.lastchar = cp + 1; 00693 re_refresh(el); 00694 00695 if (el_getc(el, &ch) != 1) { 00696 ed_end_of_file(el, 0); 00697 len = -1; 00698 break; 00699 } 00700 00701 switch (ch) { 00702 00703 case 0010: /* Delete and backspace */ 00704 case 0177: 00705 if (len <= 0) { 00706 len = -1; 00707 break; 00708 } 00709 cp--; 00710 continue; 00711 00712 case 0033: /* ESC */ 00713 case '\r': /* Newline */ 00714 case '\n': 00715 buf[len] = ch; 00716 break; 00717 00718 default: 00719 if (len >= EL_BUFSIZ - 16) 00720 term_beep(el); 00721 else { 00722 buf[len++] = ch; 00723 *cp++ = ch; 00724 } 00725 continue; 00726 } 00727 break; 00728 } 00729 00730 el->el_line.buffer[0] = '\0'; 00731 el->el_line.lastchar = el->el_line.buffer; 00732 el->el_line.cursor = el->el_line.buffer; 00733 return len; 00734 } 00735 00736 00737 /* c_hpos(): 00738 * Return the current horizontal position of the cursor 00739 */ 00740 protected int 00741 c_hpos(EditLine *el) 00742 { 00743 char *ptr; 00744 00745 /* 00746 * Find how many characters till the beginning of this line. 00747 */ 00748 if (el->el_line.cursor == el->el_line.buffer) 00749 return (0); 00750 else { 00751 for (ptr = el->el_line.cursor - 1; 00752 ptr >= el->el_line.buffer && *ptr != '\n'; 00753 ptr--) 00754 continue; 00755 return (el->el_line.cursor - ptr - 1); 00756 } 00757 }
1.4.7

