PageRenderTime 38ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/libedit/chared.c

https://github.com/okuoku/freebsd-head
C | 776 lines | 499 code | 125 blank | 152 comment | 120 complexity | 0e4fe11914dfa8be518094d024bec041 MD5 | raw file
  1. /*-
  2. * Copyright (c) 1992, 1993
  3. * The Regents of the University of California. All rights reserved.
  4. *
  5. * This code is derived from software contributed to Berkeley by
  6. * Christos Zoulas of Cornell University.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. Neither the name of the University nor the names of its contributors
  17. * may be used to endorse or promote products derived from this software
  18. * without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  21. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  24. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * $NetBSD: chared.c,v 1.25 2005/08/08 01:41:30 christos Exp $
  33. */
  34. #if !defined(lint) && !defined(SCCSID)
  35. static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93";
  36. #endif /* not lint && not SCCSID */
  37. #include <sys/cdefs.h>
  38. __FBSDID("$FreeBSD$");
  39. /*
  40. * chared.c: Character editor utilities
  41. */
  42. #include "sys.h"
  43. #include <stdlib.h>
  44. #include "el.h"
  45. private void ch__clearmacro(EditLine *);
  46. /* value to leave unused in line buffer */
  47. #define EL_LEAVE 2
  48. /* cv_undo():
  49. * Handle state for the vi undo command
  50. */
  51. protected void
  52. cv_undo(EditLine *el)
  53. {
  54. c_undo_t *vu = &el->el_chared.c_undo;
  55. c_redo_t *r = &el->el_chared.c_redo;
  56. unsigned int size;
  57. /* Save entire line for undo */
  58. size = el->el_line.lastchar - el->el_line.buffer;
  59. vu->len = size;
  60. vu->cursor = el->el_line.cursor - el->el_line.buffer;
  61. memcpy(vu->buf, el->el_line.buffer, size);
  62. /* save command info for redo */
  63. r->count = el->el_state.doingarg ? el->el_state.argument : 0;
  64. r->action = el->el_chared.c_vcmd.action;
  65. r->pos = r->buf;
  66. r->cmd = el->el_state.thiscmd;
  67. r->ch = el->el_state.thisch;
  68. }
  69. /* cv_yank():
  70. * Save yank/delete data for paste
  71. */
  72. protected void
  73. cv_yank(EditLine *el, const char *ptr, int size)
  74. {
  75. c_kill_t *k = &el->el_chared.c_kill;
  76. memcpy(k->buf, ptr, size +0u);
  77. k->last = k->buf + size;
  78. }
  79. /* c_insert():
  80. * Insert num characters
  81. */
  82. protected void
  83. c_insert(EditLine *el, int num)
  84. {
  85. char *cp;
  86. if (el->el_line.lastchar + num >= el->el_line.limit) {
  87. if (!ch_enlargebufs(el, num +0u))
  88. return; /* can't go past end of buffer */
  89. }
  90. if (el->el_line.cursor < el->el_line.lastchar) {
  91. /* if I must move chars */
  92. for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--)
  93. cp[num] = *cp;
  94. }
  95. el->el_line.lastchar += num;
  96. }
  97. /* c_delafter():
  98. * Delete num characters after the cursor
  99. */
  100. protected void
  101. c_delafter(EditLine *el, int num)
  102. {
  103. if (el->el_line.cursor + num > el->el_line.lastchar)
  104. num = el->el_line.lastchar - el->el_line.cursor;
  105. if (el->el_map.current != el->el_map.emacs) {
  106. cv_undo(el);
  107. cv_yank(el, el->el_line.cursor, num);
  108. }
  109. if (num > 0) {
  110. char *cp;
  111. for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
  112. *cp = cp[num];
  113. el->el_line.lastchar -= num;
  114. }
  115. }
  116. /* c_delafter1():
  117. * Delete the character after the cursor, do not yank
  118. */
  119. protected void
  120. c_delafter1(EditLine *el)
  121. {
  122. char *cp;
  123. for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
  124. *cp = cp[1];
  125. el->el_line.lastchar--;
  126. }
  127. /* c_delbefore():
  128. * Delete num characters before the cursor
  129. */
  130. protected void
  131. c_delbefore(EditLine *el, int num)
  132. {
  133. if (el->el_line.cursor - num < el->el_line.buffer)
  134. num = el->el_line.cursor - el->el_line.buffer;
  135. if (el->el_map.current != el->el_map.emacs) {
  136. cv_undo(el);
  137. cv_yank(el, el->el_line.cursor - num, num);
  138. }
  139. if (num > 0) {
  140. char *cp;
  141. for (cp = el->el_line.cursor - num;
  142. cp <= el->el_line.lastchar;
  143. cp++)
  144. *cp = cp[num];
  145. el->el_line.lastchar -= num;
  146. }
  147. }
  148. /* c_delbefore1():
  149. * Delete the character before the cursor, do not yank
  150. */
  151. protected void
  152. c_delbefore1(EditLine *el)
  153. {
  154. char *cp;
  155. for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++)
  156. *cp = cp[1];
  157. el->el_line.lastchar--;
  158. }
  159. /* ce__isword():
  160. * Return if p is part of a word according to emacs
  161. */
  162. protected int
  163. ce__isword(int p)
  164. {
  165. return (isalnum(p) || strchr("*?_-.[]~=", p) != NULL);
  166. }
  167. /* cv__isword():
  168. * Return if p is part of a word according to vi
  169. */
  170. protected int
  171. cv__isword(int p)
  172. {
  173. if (isalnum(p) || p == '_')
  174. return 1;
  175. if (isgraph(p))
  176. return 2;
  177. return 0;
  178. }
  179. /* cv__isWord():
  180. * Return if p is part of a big word according to vi
  181. */
  182. protected int
  183. cv__isWord(int p)
  184. {
  185. return (!isspace(p));
  186. }
  187. /* c__prev_word():
  188. * Find the previous word
  189. */
  190. protected char *
  191. c__prev_word(char *p, char *low, int n, int (*wtest)(int))
  192. {
  193. p--;
  194. while (n--) {
  195. while ((p >= low) && !(*wtest)((unsigned char) *p))
  196. p--;
  197. while ((p >= low) && (*wtest)((unsigned char) *p))
  198. p--;
  199. }
  200. /* cp now points to one character before the word */
  201. p++;
  202. if (p < low)
  203. p = low;
  204. /* cp now points where we want it */
  205. return (p);
  206. }
  207. /* c__next_word():
  208. * Find the next word
  209. */
  210. protected char *
  211. c__next_word(char *p, char *high, int n, int (*wtest)(int))
  212. {
  213. while (n--) {
  214. while ((p < high) && !(*wtest)((unsigned char) *p))
  215. p++;
  216. while ((p < high) && (*wtest)((unsigned char) *p))
  217. p++;
  218. }
  219. if (p > high)
  220. p = high;
  221. /* p now points where we want it */
  222. return (p);
  223. }
  224. /* cv_next_word():
  225. * Find the next word vi style
  226. */
  227. protected char *
  228. cv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int))
  229. {
  230. int test;
  231. while (n--) {
  232. test = (*wtest)((unsigned char) *p);
  233. while ((p < high) && (*wtest)((unsigned char) *p) == test)
  234. p++;
  235. /*
  236. * vi historically deletes with cw only the word preserving the
  237. * trailing whitespace! This is not what 'w' does..
  238. */
  239. if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT))
  240. while ((p < high) && isspace((unsigned char) *p))
  241. p++;
  242. }
  243. /* p now points where we want it */
  244. if (p > high)
  245. return (high);
  246. else
  247. return (p);
  248. }
  249. /* cv_prev_word():
  250. * Find the previous word vi style
  251. */
  252. protected char *
  253. cv_prev_word(char *p, char *low, int n, int (*wtest)(int))
  254. {
  255. int test;
  256. p--;
  257. while (n--) {
  258. while ((p > low) && isspace((unsigned char) *p))
  259. p--;
  260. test = (*wtest)((unsigned char) *p);
  261. while ((p >= low) && (*wtest)((unsigned char) *p) == test)
  262. p--;
  263. }
  264. p++;
  265. /* p now points where we want it */
  266. if (p < low)
  267. return (low);
  268. else
  269. return (p);
  270. }
  271. #ifdef notdef
  272. /* c__number():
  273. * Ignore character p points to, return number appearing after that.
  274. * A '$' by itself means a big number; "$-" is for negative; '^' means 1.
  275. * Return p pointing to last char used.
  276. */
  277. protected char *
  278. c__number(
  279. char *p, /* character position */
  280. int *num, /* Return value */
  281. int dval) /* dval is the number to subtract from like $-3 */
  282. {
  283. int i;
  284. int sign = 1;
  285. if (*++p == '^') {
  286. *num = 1;
  287. return (p);
  288. }
  289. if (*p == '$') {
  290. if (*++p != '-') {
  291. *num = 0x7fffffff; /* Handle $ */
  292. return (--p);
  293. }
  294. sign = -1; /* Handle $- */
  295. ++p;
  296. }
  297. for (i = 0; isdigit((unsigned char) *p); i = 10 * i + *p++ - '0')
  298. continue;
  299. *num = (sign < 0 ? dval - i : i);
  300. return (--p);
  301. }
  302. #endif
  303. /* cv_delfini():
  304. * Finish vi delete action
  305. */
  306. protected void
  307. cv_delfini(EditLine *el)
  308. {
  309. int size;
  310. int action = el->el_chared.c_vcmd.action;
  311. if (action & INSERT)
  312. el->el_map.current = el->el_map.key;
  313. if (el->el_chared.c_vcmd.pos == 0)
  314. /* sanity */
  315. return;
  316. size = el->el_line.cursor - el->el_chared.c_vcmd.pos;
  317. if (size == 0)
  318. size = 1;
  319. el->el_line.cursor = el->el_chared.c_vcmd.pos;
  320. if (action & YANK) {
  321. if (size > 0)
  322. cv_yank(el, el->el_line.cursor, size);
  323. else
  324. cv_yank(el, el->el_line.cursor + size, -size);
  325. } else {
  326. if (size > 0) {
  327. c_delafter(el, size);
  328. re_refresh_cursor(el);
  329. } else {
  330. c_delbefore(el, -size);
  331. el->el_line.cursor += size;
  332. }
  333. }
  334. el->el_chared.c_vcmd.action = NOP;
  335. }
  336. #ifdef notdef
  337. /* ce__endword():
  338. * Go to the end of this word according to emacs
  339. */
  340. protected char *
  341. ce__endword(char *p, char *high, int n)
  342. {
  343. p++;
  344. while (n--) {
  345. while ((p < high) && isspace((unsigned char) *p))
  346. p++;
  347. while ((p < high) && !isspace((unsigned char) *p))
  348. p++;
  349. }
  350. p--;
  351. return (p);
  352. }
  353. #endif
  354. /* cv__endword():
  355. * Go to the end of this word according to vi
  356. */
  357. protected char *
  358. cv__endword(char *p, char *high, int n, int (*wtest)(int))
  359. {
  360. int test;
  361. p++;
  362. while (n--) {
  363. while ((p < high) && isspace((unsigned char) *p))
  364. p++;
  365. test = (*wtest)((unsigned char) *p);
  366. while ((p < high) && (*wtest)((unsigned char) *p) == test)
  367. p++;
  368. }
  369. p--;
  370. return (p);
  371. }
  372. /* ch_init():
  373. * Initialize the character editor
  374. */
  375. protected int
  376. ch_init(EditLine *el)
  377. {
  378. c_macro_t *ma = &el->el_chared.c_macro;
  379. el->el_line.buffer = (char *) el_malloc(EL_BUFSIZ);
  380. if (el->el_line.buffer == NULL)
  381. return (-1);
  382. (void) memset(el->el_line.buffer, 0, EL_BUFSIZ);
  383. el->el_line.cursor = el->el_line.buffer;
  384. el->el_line.lastchar = el->el_line.buffer;
  385. el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE];
  386. el->el_chared.c_undo.buf = (char *) el_malloc(EL_BUFSIZ);
  387. if (el->el_chared.c_undo.buf == NULL)
  388. return (-1);
  389. (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ);
  390. el->el_chared.c_undo.len = -1;
  391. el->el_chared.c_undo.cursor = 0;
  392. el->el_chared.c_redo.buf = (char *) el_malloc(EL_BUFSIZ);
  393. if (el->el_chared.c_redo.buf == NULL)
  394. return (-1);
  395. el->el_chared.c_redo.pos = el->el_chared.c_redo.buf;
  396. el->el_chared.c_redo.lim = el->el_chared.c_redo.buf + EL_BUFSIZ;
  397. el->el_chared.c_redo.cmd = ED_UNASSIGNED;
  398. el->el_chared.c_vcmd.action = NOP;
  399. el->el_chared.c_vcmd.pos = el->el_line.buffer;
  400. el->el_chared.c_kill.buf = (char *) el_malloc(EL_BUFSIZ);
  401. if (el->el_chared.c_kill.buf == NULL)
  402. return (-1);
  403. (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ);
  404. el->el_chared.c_kill.mark = el->el_line.buffer;
  405. el->el_chared.c_kill.last = el->el_chared.c_kill.buf;
  406. el->el_map.current = el->el_map.key;
  407. el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */
  408. el->el_state.doingarg = 0;
  409. el->el_state.metanext = 0;
  410. el->el_state.argument = 1;
  411. el->el_state.lastcmd = ED_UNASSIGNED;
  412. ma->level = -1;
  413. ma->offset = 0;
  414. ma->macro = (char **) el_malloc(EL_MAXMACRO * sizeof(char *));
  415. if (ma->macro == NULL)
  416. return (-1);
  417. return (0);
  418. }
  419. /* ch_reset():
  420. * Reset the character editor
  421. */
  422. protected void
  423. ch_reset(EditLine *el, int mclear)
  424. {
  425. el->el_line.cursor = el->el_line.buffer;
  426. el->el_line.lastchar = el->el_line.buffer;
  427. el->el_chared.c_undo.len = -1;
  428. el->el_chared.c_undo.cursor = 0;
  429. el->el_chared.c_vcmd.action = NOP;
  430. el->el_chared.c_vcmd.pos = el->el_line.buffer;
  431. el->el_chared.c_kill.mark = el->el_line.buffer;
  432. el->el_map.current = el->el_map.key;
  433. el->el_state.inputmode = MODE_INSERT; /* XXX: save a default */
  434. el->el_state.doingarg = 0;
  435. el->el_state.metanext = 0;
  436. el->el_state.argument = 1;
  437. el->el_state.lastcmd = ED_UNASSIGNED;
  438. el->el_history.eventno = 0;
  439. if (mclear)
  440. ch__clearmacro(el);
  441. }
  442. private void
  443. ch__clearmacro(el)
  444. EditLine *el;
  445. {
  446. c_macro_t *ma = &el->el_chared.c_macro;
  447. while (ma->level >= 0)
  448. el_free((ptr_t)ma->macro[ma->level--]);
  449. }
  450. /* ch_enlargebufs():
  451. * Enlarge line buffer to be able to hold twice as much characters.
  452. * Returns 1 if successful, 0 if not.
  453. */
  454. protected int
  455. ch_enlargebufs(el, addlen)
  456. EditLine *el;
  457. size_t addlen;
  458. {
  459. size_t sz, newsz;
  460. char *newbuffer, *oldbuf, *oldkbuf;
  461. sz = el->el_line.limit - el->el_line.buffer + EL_LEAVE;
  462. newsz = sz * 2;
  463. /*
  464. * If newly required length is longer than current buffer, we need
  465. * to make the buffer big enough to hold both old and new stuff.
  466. */
  467. if (addlen > sz) {
  468. while(newsz - sz < addlen)
  469. newsz *= 2;
  470. }
  471. /*
  472. * Reallocate line buffer.
  473. */
  474. newbuffer = el_realloc(el->el_line.buffer, newsz);
  475. if (!newbuffer)
  476. return 0;
  477. /* zero the newly added memory, leave old data in */
  478. (void) memset(&newbuffer[sz], 0, newsz - sz);
  479. oldbuf = el->el_line.buffer;
  480. el->el_line.buffer = newbuffer;
  481. el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf);
  482. el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf);
  483. /* don't set new size until all buffers are enlarged */
  484. el->el_line.limit = &newbuffer[sz - EL_LEAVE];
  485. /*
  486. * Reallocate kill buffer.
  487. */
  488. newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz);
  489. if (!newbuffer)
  490. return 0;
  491. /* zero the newly added memory, leave old data in */
  492. (void) memset(&newbuffer[sz], 0, newsz - sz);
  493. oldkbuf = el->el_chared.c_kill.buf;
  494. el->el_chared.c_kill.buf = newbuffer;
  495. el->el_chared.c_kill.last = newbuffer +
  496. (el->el_chared.c_kill.last - oldkbuf);
  497. el->el_chared.c_kill.mark = el->el_line.buffer +
  498. (el->el_chared.c_kill.mark - oldbuf);
  499. /*
  500. * Reallocate undo buffer.
  501. */
  502. newbuffer = el_realloc(el->el_chared.c_undo.buf, newsz);
  503. if (!newbuffer)
  504. return 0;
  505. /* zero the newly added memory, leave old data in */
  506. (void) memset(&newbuffer[sz], 0, newsz - sz);
  507. el->el_chared.c_undo.buf = newbuffer;
  508. newbuffer = el_realloc(el->el_chared.c_redo.buf, newsz);
  509. if (!newbuffer)
  510. return 0;
  511. el->el_chared.c_redo.pos = newbuffer +
  512. (el->el_chared.c_redo.pos - el->el_chared.c_redo.buf);
  513. el->el_chared.c_redo.lim = newbuffer +
  514. (el->el_chared.c_redo.lim - el->el_chared.c_redo.buf);
  515. el->el_chared.c_redo.buf = newbuffer;
  516. if (!hist_enlargebuf(el, sz, newsz))
  517. return 0;
  518. /* Safe to set enlarged buffer size */
  519. el->el_line.limit = &el->el_line.buffer[newsz - EL_LEAVE];
  520. return 1;
  521. }
  522. /* ch_end():
  523. * Free the data structures used by the editor
  524. */
  525. protected void
  526. ch_end(EditLine *el)
  527. {
  528. el_free((ptr_t) el->el_line.buffer);
  529. el->el_line.buffer = NULL;
  530. el->el_line.limit = NULL;
  531. el_free((ptr_t) el->el_chared.c_undo.buf);
  532. el->el_chared.c_undo.buf = NULL;
  533. el_free((ptr_t) el->el_chared.c_redo.buf);
  534. el->el_chared.c_redo.buf = NULL;
  535. el->el_chared.c_redo.pos = NULL;
  536. el->el_chared.c_redo.lim = NULL;
  537. el->el_chared.c_redo.cmd = ED_UNASSIGNED;
  538. el_free((ptr_t) el->el_chared.c_kill.buf);
  539. el->el_chared.c_kill.buf = NULL;
  540. ch_reset(el, 1);
  541. el_free((ptr_t) el->el_chared.c_macro.macro);
  542. el->el_chared.c_macro.macro = NULL;
  543. }
  544. /* el_insertstr():
  545. * Insert string at cursorI
  546. */
  547. public int
  548. el_insertstr(EditLine *el, const char *s)
  549. {
  550. size_t len;
  551. if ((len = strlen(s)) == 0)
  552. return (-1);
  553. if (el->el_line.lastchar + len >= el->el_line.limit) {
  554. if (!ch_enlargebufs(el, len))
  555. return (-1);
  556. }
  557. c_insert(el, (int)len);
  558. while (*s)
  559. *el->el_line.cursor++ = *s++;
  560. return (0);
  561. }
  562. /* el_deletestr():
  563. * Delete num characters before the cursor
  564. */
  565. public void
  566. el_deletestr(EditLine *el, int n)
  567. {
  568. if (n <= 0)
  569. return;
  570. if (el->el_line.cursor < &el->el_line.buffer[n])
  571. return;
  572. c_delbefore(el, n); /* delete before dot */
  573. el->el_line.cursor -= n;
  574. if (el->el_line.cursor < el->el_line.buffer)
  575. el->el_line.cursor = el->el_line.buffer;
  576. }
  577. /* c_gets():
  578. * Get a string
  579. */
  580. protected int
  581. c_gets(EditLine *el, char *buf, const char *prompt)
  582. {
  583. char ch;
  584. int len;
  585. char *cp = el->el_line.buffer;
  586. if (prompt) {
  587. len = strlen(prompt);
  588. memcpy(cp, prompt, len + 0u);
  589. cp += len;
  590. }
  591. len = 0;
  592. for (;;) {
  593. el->el_line.cursor = cp;
  594. *cp = ' ';
  595. el->el_line.lastchar = cp + 1;
  596. re_refresh(el);
  597. if (el_getc(el, &ch) != 1) {
  598. ed_end_of_file(el, 0);
  599. len = -1;
  600. break;
  601. }
  602. switch (ch) {
  603. case '\010': /* Delete and backspace */
  604. case '\177':
  605. if (len <= 0) {
  606. len = -1;
  607. break;
  608. }
  609. cp--;
  610. continue;
  611. case '\033': /* ESC */
  612. case '\r': /* Newline */
  613. case '\n':
  614. buf[len] = ch;
  615. break;
  616. default:
  617. if (len >= EL_BUFSIZ - 16)
  618. term_beep(el);
  619. else {
  620. buf[len++] = ch;
  621. *cp++ = ch;
  622. }
  623. continue;
  624. }
  625. break;
  626. }
  627. el->el_line.buffer[0] = '\0';
  628. el->el_line.lastchar = el->el_line.buffer;
  629. el->el_line.cursor = el->el_line.buffer;
  630. return len;
  631. }
  632. /* c_hpos():
  633. * Return the current horizontal position of the cursor
  634. */
  635. protected int
  636. c_hpos(EditLine *el)
  637. {
  638. char *ptr;
  639. /*
  640. * Find how many characters till the beginning of this line.
  641. */
  642. if (el->el_line.cursor == el->el_line.buffer)
  643. return (0);
  644. else {
  645. for (ptr = el->el_line.cursor - 1;
  646. ptr >= el->el_line.buffer && *ptr != '\n';
  647. ptr--)
  648. continue;
  649. return (el->el_line.cursor - ptr - 1);
  650. }
  651. }