common.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951
  1. /* $NetBSD: common.c,v 1.11 2002/03/18 16:00:51 christos Exp $ */
  2. /*-
  3. * Copyright (c) 1992, 1993
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * This code is derived from software contributed to Berkeley by
  7. * Christos Zoulas of Cornell University.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. All advertising materials mentioning features or use of this software
  18. * must display the following acknowledgement:
  19. * This product includes software developed by the University of
  20. * California, Berkeley and its contributors.
  21. * 4. Neither the name of the University nor the names of its contributors
  22. * may be used to endorse or promote products derived from this software
  23. * without specific prior written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35. * SUCH DAMAGE.
  36. */
  37. #include "config.h"
  38. #if !defined(lint) && !defined(SCCSID)
  39. #if 0
  40. static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93";
  41. #else
  42. __RCSID("$NetBSD: common.c,v 1.11 2002/03/18 16:00:51 christos Exp $");
  43. #endif
  44. #endif /* not lint && not SCCSID */
  45. /*
  46. * common.c: Common Editor functions
  47. */
  48. #include "el.h"
  49. /* ed_end_of_file():
  50. * Indicate end of file
  51. * [^D]
  52. */
  53. protected el_action_t
  54. /*ARGSUSED*/
  55. ed_end_of_file(EditLine *el, int c)
  56. {
  57. re_goto_bottom(el);
  58. *el->el_line.lastchar = '\0';
  59. return (CC_EOF);
  60. }
  61. /* ed_insert():
  62. * Add character to the line
  63. * Insert a character [bound to all insert keys]
  64. */
  65. protected el_action_t
  66. ed_insert(EditLine *el, int c)
  67. {
  68. int i;
  69. if (c == '\0')
  70. return (CC_ERROR);
  71. if (el->el_line.lastchar + el->el_state.argument >=
  72. el->el_line.limit) {
  73. /* end of buffer space, try to allocate more */
  74. if (!ch_enlargebufs(el, (size_t) el->el_state.argument))
  75. return CC_ERROR; /* error allocating more */
  76. }
  77. if (el->el_state.argument == 1) {
  78. if (el->el_state.inputmode != MODE_INSERT) {
  79. el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
  80. *el->el_line.cursor;
  81. el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] =
  82. '\0';
  83. c_delafter(el, 1);
  84. }
  85. c_insert(el, 1);
  86. *el->el_line.cursor++ = c;
  87. el->el_state.doingarg = 0; /* just in case */
  88. re_fastaddc(el); /* fast refresh for one char. */
  89. } else {
  90. if (el->el_state.inputmode != MODE_INSERT) {
  91. for (i = 0; i < el->el_state.argument; i++)
  92. el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
  93. el->el_line.cursor[i];
  94. el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] =
  95. '\0';
  96. c_delafter(el, el->el_state.argument);
  97. }
  98. c_insert(el, el->el_state.argument);
  99. while (el->el_state.argument--)
  100. *el->el_line.cursor++ = c;
  101. re_refresh(el);
  102. }
  103. if (el->el_state.inputmode == MODE_REPLACE_1)
  104. (void) vi_command_mode(el, 0);
  105. return (CC_NORM);
  106. }
  107. /* ed_delete_prev_word():
  108. * Delete from beginning of current word to cursor
  109. * [M-^?] [^W]
  110. */
  111. protected el_action_t
  112. /*ARGSUSED*/
  113. ed_delete_prev_word(EditLine *el, int c)
  114. {
  115. char *cp, *p, *kp;
  116. if (el->el_line.cursor == el->el_line.buffer)
  117. return (CC_ERROR);
  118. cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
  119. el->el_state.argument, ce__isword);
  120. for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
  121. *kp++ = *p;
  122. el->el_chared.c_kill.last = kp;
  123. c_delbefore(el, el->el_line.cursor - cp); /* delete before dot */
  124. el->el_line.cursor = cp;
  125. if (el->el_line.cursor < el->el_line.buffer)
  126. el->el_line.cursor = el->el_line.buffer; /* bounds check */
  127. return (CC_REFRESH);
  128. }
  129. /* ed_delete_next_char():
  130. * Delete character under cursor
  131. * [^D] [x]
  132. */
  133. protected el_action_t
  134. /*ARGSUSED*/
  135. ed_delete_next_char(EditLine *el, int c)
  136. {
  137. #ifdef notdef /* XXX */
  138. #define EL el->el_line
  139. (void) fprintf(el->el_errlfile,
  140. "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n",
  141. EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar,
  142. EL.lastchar, EL.limit, EL.limit);
  143. #endif
  144. if (el->el_line.cursor == el->el_line.lastchar) {
  145. /* if I'm at the end */
  146. if (el->el_map.type == MAP_VI) {
  147. if (el->el_line.cursor == el->el_line.buffer) {
  148. /* if I'm also at the beginning */
  149. #ifdef KSHVI
  150. return (CC_ERROR);
  151. #else
  152. term_overwrite(el, STReof, 4);
  153. /* then do a EOF */
  154. term__flush();
  155. return (CC_EOF);
  156. #endif
  157. } else {
  158. #ifdef KSHVI
  159. el->el_line.cursor--;
  160. #else
  161. return (CC_ERROR);
  162. #endif
  163. }
  164. } else {
  165. if (el->el_line.cursor != el->el_line.buffer)
  166. el->el_line.cursor--;
  167. else
  168. return (CC_ERROR);
  169. }
  170. }
  171. c_delafter(el, el->el_state.argument); /* delete after dot */
  172. if (el->el_line.cursor >= el->el_line.lastchar &&
  173. el->el_line.cursor > el->el_line.buffer)
  174. /* bounds check */
  175. el->el_line.cursor = el->el_line.lastchar - 1;
  176. return (CC_REFRESH);
  177. }
  178. /* ed_kill_line():
  179. * Cut to the end of line
  180. * [^K] [^K]
  181. */
  182. protected el_action_t
  183. /*ARGSUSED*/
  184. ed_kill_line(EditLine *el, int c)
  185. {
  186. char *kp, *cp;
  187. cp = el->el_line.cursor;
  188. kp = el->el_chared.c_kill.buf;
  189. while (cp < el->el_line.lastchar)
  190. *kp++ = *cp++; /* copy it */
  191. el->el_chared.c_kill.last = kp;
  192. /* zap! -- delete to end */
  193. el->el_line.lastchar = el->el_line.cursor;
  194. return (CC_REFRESH);
  195. }
  196. /* ed_move_to_end():
  197. * Move cursor to the end of line
  198. * [^E] [^E]
  199. */
  200. protected el_action_t
  201. /*ARGSUSED*/
  202. ed_move_to_end(EditLine *el, int c)
  203. {
  204. el->el_line.cursor = el->el_line.lastchar;
  205. if (el->el_map.type == MAP_VI) {
  206. #ifdef VI_MOVE
  207. el->el_line.cursor--;
  208. #endif
  209. if (el->el_chared.c_vcmd.action & DELETE) {
  210. cv_delfini(el);
  211. return (CC_REFRESH);
  212. }
  213. }
  214. return (CC_CURSOR);
  215. }
  216. /* ed_move_to_beg():
  217. * Move cursor to the beginning of line
  218. * [^A] [^A]
  219. */
  220. protected el_action_t
  221. /*ARGSUSED*/
  222. ed_move_to_beg(EditLine *el, int c)
  223. {
  224. el->el_line.cursor = el->el_line.buffer;
  225. if (el->el_map.type == MAP_VI) {
  226. /* We want FIRST non space character */
  227. while (isspace((unsigned char) *el->el_line.cursor))
  228. el->el_line.cursor++;
  229. if (el->el_chared.c_vcmd.action & DELETE) {
  230. cv_delfini(el);
  231. return (CC_REFRESH);
  232. }
  233. }
  234. return (CC_CURSOR);
  235. }
  236. /* ed_transpose_chars():
  237. * Exchange the character to the left of the cursor with the one under it
  238. * [^T] [^T]
  239. */
  240. protected el_action_t
  241. ed_transpose_chars(EditLine *el, int c)
  242. {
  243. if (el->el_line.cursor < el->el_line.lastchar) {
  244. if (el->el_line.lastchar <= &el->el_line.buffer[1])
  245. return (CC_ERROR);
  246. else
  247. el->el_line.cursor++;
  248. }
  249. if (el->el_line.cursor > &el->el_line.buffer[1]) {
  250. /* must have at least two chars entered */
  251. c = el->el_line.cursor[-2];
  252. el->el_line.cursor[-2] = el->el_line.cursor[-1];
  253. el->el_line.cursor[-1] = c;
  254. return (CC_REFRESH);
  255. } else
  256. return (CC_ERROR);
  257. }
  258. /* ed_next_char():
  259. * Move to the right one character
  260. * [^F] [^F]
  261. */
  262. protected el_action_t
  263. /*ARGSUSED*/
  264. ed_next_char(EditLine *el, int c)
  265. {
  266. if (el->el_line.cursor >= el->el_line.lastchar)
  267. return (CC_ERROR);
  268. el->el_line.cursor += el->el_state.argument;
  269. if (el->el_line.cursor > el->el_line.lastchar)
  270. el->el_line.cursor = el->el_line.lastchar;
  271. if (el->el_map.type == MAP_VI)
  272. if (el->el_chared.c_vcmd.action & DELETE) {
  273. cv_delfini(el);
  274. return (CC_REFRESH);
  275. }
  276. return (CC_CURSOR);
  277. }
  278. /* ed_prev_word():
  279. * Move to the beginning of the current word
  280. * [M-b] [b]
  281. */
  282. protected el_action_t
  283. /*ARGSUSED*/
  284. ed_prev_word(EditLine *el, int c)
  285. {
  286. if (el->el_line.cursor == el->el_line.buffer)
  287. return (CC_ERROR);
  288. el->el_line.cursor = c__prev_word(el->el_line.cursor,
  289. el->el_line.buffer,
  290. el->el_state.argument,
  291. ce__isword);
  292. if (el->el_map.type == MAP_VI)
  293. if (el->el_chared.c_vcmd.action & DELETE) {
  294. cv_delfini(el);
  295. return (CC_REFRESH);
  296. }
  297. return (CC_CURSOR);
  298. }
  299. /* ed_prev_char():
  300. * Move to the left one character
  301. * [^B] [^B]
  302. */
  303. protected el_action_t
  304. /*ARGSUSED*/
  305. ed_prev_char(EditLine *el, int c)
  306. {
  307. if (el->el_line.cursor > el->el_line.buffer) {
  308. el->el_line.cursor -= el->el_state.argument;
  309. if (el->el_line.cursor < el->el_line.buffer)
  310. el->el_line.cursor = el->el_line.buffer;
  311. if (el->el_map.type == MAP_VI)
  312. if (el->el_chared.c_vcmd.action & DELETE) {
  313. cv_delfini(el);
  314. return (CC_REFRESH);
  315. }
  316. return (CC_CURSOR);
  317. } else
  318. return (CC_ERROR);
  319. }
  320. /* ed_quoted_insert():
  321. * Add the next character typed verbatim
  322. * [^V] [^V]
  323. */
  324. protected el_action_t
  325. ed_quoted_insert(EditLine *el, int c)
  326. {
  327. int num;
  328. char tc;
  329. tty_quotemode(el);
  330. num = el_getc(el, &tc);
  331. c = (unsigned char) tc;
  332. tty_noquotemode(el);
  333. if (num == 1)
  334. return (ed_insert(el, c));
  335. else
  336. return (ed_end_of_file(el, 0));
  337. }
  338. /* ed_digit():
  339. * Adds to argument or enters a digit
  340. */
  341. protected el_action_t
  342. ed_digit(EditLine *el, int c)
  343. {
  344. if (!isdigit(c))
  345. return (CC_ERROR);
  346. if (el->el_state.doingarg) {
  347. /* if doing an arg, add this in... */
  348. if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
  349. el->el_state.argument = c - '0';
  350. else {
  351. if (el->el_state.argument > 1000000)
  352. return (CC_ERROR);
  353. el->el_state.argument =
  354. (el->el_state.argument * 10) + (c - '0');
  355. }
  356. return (CC_ARGHACK);
  357. } else {
  358. if (el->el_line.lastchar + 1 >= el->el_line.limit) {
  359. if (!ch_enlargebufs(el, 1))
  360. return (CC_ERROR);
  361. }
  362. if (el->el_state.inputmode != MODE_INSERT) {
  363. el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
  364. *el->el_line.cursor;
  365. el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] =
  366. '\0';
  367. c_delafter(el, 1);
  368. }
  369. c_insert(el, 1);
  370. *el->el_line.cursor++ = c;
  371. el->el_state.doingarg = 0;
  372. re_fastaddc(el);
  373. }
  374. return (CC_NORM);
  375. }
  376. /* ed_argument_digit():
  377. * Digit that starts argument
  378. * For ESC-n
  379. */
  380. protected el_action_t
  381. ed_argument_digit(EditLine *el, int c)
  382. {
  383. if (!isdigit(c))
  384. return (CC_ERROR);
  385. if (el->el_state.doingarg) {
  386. if (el->el_state.argument > 1000000)
  387. return (CC_ERROR);
  388. el->el_state.argument = (el->el_state.argument * 10) +
  389. (c - '0');
  390. } else { /* else starting an argument */
  391. el->el_state.argument = c - '0';
  392. el->el_state.doingarg = 1;
  393. }
  394. return (CC_ARGHACK);
  395. }
  396. /* ed_unassigned():
  397. * Indicates unbound character
  398. * Bound to keys that are not assigned
  399. */
  400. protected el_action_t
  401. /*ARGSUSED*/
  402. ed_unassigned(EditLine *el, int c)
  403. {
  404. term_beep(el);
  405. term__flush();
  406. return (CC_NORM);
  407. }
  408. /**
  409. ** TTY key handling.
  410. **/
  411. /* ed_tty_sigint():
  412. * Tty interrupt character
  413. * [^C]
  414. */
  415. protected el_action_t
  416. /*ARGSUSED*/
  417. ed_tty_sigint(EditLine *el, int c)
  418. {
  419. return (CC_NORM);
  420. }
  421. /* ed_tty_dsusp():
  422. * Tty delayed suspend character
  423. * [^Y]
  424. */
  425. protected el_action_t
  426. /*ARGSUSED*/
  427. ed_tty_dsusp(EditLine *el, int c)
  428. {
  429. return (CC_NORM);
  430. }
  431. /* ed_tty_flush_output():
  432. * Tty flush output characters
  433. * [^O]
  434. */
  435. protected el_action_t
  436. /*ARGSUSED*/
  437. ed_tty_flush_output(EditLine *el, int c)
  438. {
  439. return (CC_NORM);
  440. }
  441. /* ed_tty_sigquit():
  442. * Tty quit character
  443. * [^\]
  444. */
  445. protected el_action_t
  446. /*ARGSUSED*/
  447. ed_tty_sigquit(EditLine *el, int c)
  448. {
  449. return (CC_NORM);
  450. }
  451. /* ed_tty_sigtstp():
  452. * Tty suspend character
  453. * [^Z]
  454. */
  455. protected el_action_t
  456. /*ARGSUSED*/
  457. ed_tty_sigtstp(EditLine *el, int c)
  458. {
  459. return (CC_NORM);
  460. }
  461. /* ed_tty_stop_output():
  462. * Tty disallow output characters
  463. * [^S]
  464. */
  465. protected el_action_t
  466. /*ARGSUSED*/
  467. ed_tty_stop_output(EditLine *el, int c)
  468. {
  469. return (CC_NORM);
  470. }
  471. /* ed_tty_start_output():
  472. * Tty allow output characters
  473. * [^Q]
  474. */
  475. protected el_action_t
  476. /*ARGSUSED*/
  477. ed_tty_start_output(EditLine *el, int c)
  478. {
  479. return (CC_NORM);
  480. }
  481. /* ed_newline():
  482. * Execute command
  483. * [^J]
  484. */
  485. protected el_action_t
  486. /*ARGSUSED*/
  487. ed_newline(EditLine *el, int c)
  488. {
  489. re_goto_bottom(el);
  490. *el->el_line.lastchar++ = '\n';
  491. *el->el_line.lastchar = '\0';
  492. if (el->el_map.type == MAP_VI)
  493. el->el_chared.c_vcmd.ins = el->el_line.buffer;
  494. return (CC_NEWLINE);
  495. }
  496. /* ed_delete_prev_char():
  497. * Delete the character to the left of the cursor
  498. * [^?]
  499. */
  500. protected el_action_t
  501. /*ARGSUSED*/
  502. ed_delete_prev_char(EditLine *el, int c)
  503. {
  504. if (el->el_line.cursor <= el->el_line.buffer)
  505. return (CC_ERROR);
  506. c_delbefore(el, el->el_state.argument);
  507. el->el_line.cursor -= el->el_state.argument;
  508. if (el->el_line.cursor < el->el_line.buffer)
  509. el->el_line.cursor = el->el_line.buffer;
  510. return (CC_REFRESH);
  511. }
  512. /* ed_clear_screen():
  513. * Clear screen leaving current line at the top
  514. * [^L]
  515. */
  516. protected el_action_t
  517. /*ARGSUSED*/
  518. ed_clear_screen(EditLine *el, int c)
  519. {
  520. term_clear_screen(el); /* clear the whole real screen */
  521. re_clear_display(el); /* reset everything */
  522. return (CC_REFRESH);
  523. }
  524. /* ed_redisplay():
  525. * Redisplay everything
  526. * ^R
  527. */
  528. protected el_action_t
  529. /*ARGSUSED*/
  530. ed_redisplay(EditLine *el, int c)
  531. {
  532. return (CC_REDISPLAY);
  533. }
  534. /* ed_start_over():
  535. * Erase current line and start from scratch
  536. * [^G]
  537. */
  538. protected el_action_t
  539. /*ARGSUSED*/
  540. ed_start_over(EditLine *el, int c)
  541. {
  542. ch_reset(el);
  543. return (CC_REFRESH);
  544. }
  545. /* ed_sequence_lead_in():
  546. * First character in a bound sequence
  547. * Placeholder for external keys
  548. */
  549. protected el_action_t
  550. /*ARGSUSED*/
  551. ed_sequence_lead_in(EditLine *el, int c)
  552. {
  553. return (CC_NORM);
  554. }
  555. /* ed_prev_history():
  556. * Move to the previous history line
  557. * [^P] [k]
  558. */
  559. protected el_action_t
  560. /*ARGSUSED*/
  561. ed_prev_history(EditLine *el, int c)
  562. {
  563. char beep = 0;
  564. el->el_chared.c_undo.action = NOP;
  565. *el->el_line.lastchar = '\0'; /* just in case */
  566. if (el->el_history.eventno == 0) { /* save the current buffer
  567. * away */
  568. (void) strncpy(el->el_history.buf, el->el_line.buffer,
  569. EL_BUFSIZ - 1);
  570. el->el_history.last = el->el_history.buf +
  571. (el->el_line.lastchar - el->el_line.buffer);
  572. }
  573. el->el_history.eventno += el->el_state.argument;
  574. if (hist_get(el) == CC_ERROR) {
  575. beep = 1;
  576. /* el->el_history.eventno was fixed by first call */
  577. (void) hist_get(el);
  578. }
  579. re_refresh(el);
  580. if (beep)
  581. return (CC_ERROR);
  582. else
  583. return (CC_NORM); /* was CC_UP_HIST */
  584. }
  585. /* ed_next_history():
  586. * Move to the next history line
  587. * [^N] [j]
  588. */
  589. protected el_action_t
  590. /*ARGSUSED*/
  591. ed_next_history(EditLine *el, int c)
  592. {
  593. el->el_chared.c_undo.action = NOP;
  594. *el->el_line.lastchar = '\0'; /* just in case */
  595. el->el_history.eventno -= el->el_state.argument;
  596. if (el->el_history.eventno < 0) {
  597. el->el_history.eventno = 0;
  598. return (CC_ERROR);/* make it beep */
  599. }
  600. return (hist_get(el));
  601. }
  602. /* ed_search_prev_history():
  603. * Search previous in history for a line matching the current
  604. * next search history [M-P] [K]
  605. */
  606. protected el_action_t
  607. /*ARGSUSED*/
  608. ed_search_prev_history(EditLine *el, int c)
  609. {
  610. const char *hp;
  611. int h;
  612. bool_t found = 0;
  613. el->el_chared.c_vcmd.action = NOP;
  614. el->el_chared.c_undo.action = NOP;
  615. *el->el_line.lastchar = '\0'; /* just in case */
  616. if (el->el_history.eventno < 0) {
  617. #ifdef DEBUG_EDIT
  618. (void) fprintf(el->el_errfile,
  619. "e_prev_search_hist(): eventno < 0;\n");
  620. #endif
  621. el->el_history.eventno = 0;
  622. return (CC_ERROR);
  623. }
  624. if (el->el_history.eventno == 0) {
  625. (void) strncpy(el->el_history.buf, el->el_line.buffer,
  626. EL_BUFSIZ - 1);
  627. el->el_history.last = el->el_history.buf +
  628. (el->el_line.lastchar - el->el_line.buffer);
  629. }
  630. if (el->el_history.ref == NULL)
  631. return (CC_ERROR);
  632. hp = HIST_FIRST(el);
  633. if (hp == NULL)
  634. return (CC_ERROR);
  635. c_setpat(el); /* Set search pattern !! */
  636. for (h = 1; h <= el->el_history.eventno; h++)
  637. hp = HIST_NEXT(el);
  638. while (hp != NULL) {
  639. #ifdef SDEBUG
  640. (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
  641. #endif
  642. if ((strncmp(hp, el->el_line.buffer, (size_t)
  643. (el->el_line.lastchar - el->el_line.buffer)) ||
  644. hp[el->el_line.lastchar - el->el_line.buffer]) &&
  645. c_hmatch(el, hp)) {
  646. found++;
  647. break;
  648. }
  649. h++;
  650. hp = HIST_NEXT(el);
  651. }
  652. if (!found) {
  653. #ifdef SDEBUG
  654. (void) fprintf(el->el_errfile, "not found\n");
  655. #endif
  656. return (CC_ERROR);
  657. }
  658. el->el_history.eventno = h;
  659. return (hist_get(el));
  660. }
  661. /* ed_search_next_history():
  662. * Search next in history for a line matching the current
  663. * [M-N] [J]
  664. */
  665. protected el_action_t
  666. /*ARGSUSED*/
  667. ed_search_next_history(EditLine *el, int c)
  668. {
  669. const char *hp;
  670. int h;
  671. bool_t found = 0;
  672. el->el_chared.c_vcmd.action = NOP;
  673. el->el_chared.c_undo.action = NOP;
  674. *el->el_line.lastchar = '\0'; /* just in case */
  675. if (el->el_history.eventno == 0)
  676. return (CC_ERROR);
  677. if (el->el_history.ref == NULL)
  678. return (CC_ERROR);
  679. hp = HIST_FIRST(el);
  680. if (hp == NULL)
  681. return (CC_ERROR);
  682. c_setpat(el); /* Set search pattern !! */
  683. for (h = 1; h < el->el_history.eventno && hp; h++) {
  684. #ifdef SDEBUG
  685. (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
  686. #endif
  687. if ((strncmp(hp, el->el_line.buffer, (size_t)
  688. (el->el_line.lastchar - el->el_line.buffer)) ||
  689. hp[el->el_line.lastchar - el->el_line.buffer]) &&
  690. c_hmatch(el, hp))
  691. found = h;
  692. hp = HIST_NEXT(el);
  693. }
  694. if (!found) { /* is it the current history number? */
  695. if (!c_hmatch(el, el->el_history.buf)) {
  696. #ifdef SDEBUG
  697. (void) fprintf(el->el_errfile, "not found\n");
  698. #endif
  699. return (CC_ERROR);
  700. }
  701. }
  702. el->el_history.eventno = found;
  703. return (hist_get(el));
  704. }
  705. /* ed_prev_line():
  706. * Move up one line
  707. * Could be [k] [^p]
  708. */
  709. protected el_action_t
  710. /*ARGSUSED*/
  711. ed_prev_line(EditLine *el, int c)
  712. {
  713. char *ptr;
  714. int nchars = c_hpos(el);
  715. /*
  716. * Move to the line requested
  717. */
  718. if (*(ptr = el->el_line.cursor) == '\n')
  719. ptr--;
  720. for (; ptr >= el->el_line.buffer; ptr--)
  721. if (*ptr == '\n' && --el->el_state.argument <= 0)
  722. break;
  723. if (el->el_state.argument > 0)
  724. return (CC_ERROR);
  725. /*
  726. * Move to the beginning of the line
  727. */
  728. for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
  729. continue;
  730. /*
  731. * Move to the character requested
  732. */
  733. for (ptr++;
  734. nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
  735. ptr++)
  736. continue;
  737. el->el_line.cursor = ptr;
  738. return (CC_CURSOR);
  739. }
  740. /* ed_next_line():
  741. * Move down one line
  742. * Could be [j] [^n]
  743. */
  744. protected el_action_t
  745. /*ARGSUSED*/
  746. ed_next_line(EditLine *el, int c)
  747. {
  748. char *ptr;
  749. int nchars = c_hpos(el);
  750. /*
  751. * Move to the line requested
  752. */
  753. for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
  754. if (*ptr == '\n' && --el->el_state.argument <= 0)
  755. break;
  756. if (el->el_state.argument > 0)
  757. return (CC_ERROR);
  758. /*
  759. * Move to the character requested
  760. */
  761. for (ptr++;
  762. nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
  763. ptr++)
  764. continue;
  765. el->el_line.cursor = ptr;
  766. return (CC_CURSOR);
  767. }
  768. /* ed_command():
  769. * Editline extended command
  770. * [M-X] [:]
  771. */
  772. protected el_action_t
  773. /*ARGSUSED*/
  774. ed_command(EditLine *el, int c)
  775. {
  776. char tmpbuf[EL_BUFSIZ];
  777. int tmplen;
  778. el->el_line.buffer[0] = '\0';
  779. el->el_line.lastchar = el->el_line.buffer;
  780. el->el_line.cursor = el->el_line.buffer;
  781. c_insert(el, 3); /* prompt + ": " */
  782. *el->el_line.cursor++ = '\n';
  783. *el->el_line.cursor++ = ':';
  784. *el->el_line.cursor++ = ' ';
  785. re_refresh(el);
  786. tmplen = c_gets(el, tmpbuf);
  787. tmpbuf[tmplen] = '\0';
  788. el->el_line.buffer[0] = '\0';
  789. el->el_line.lastchar = el->el_line.buffer;
  790. el->el_line.cursor = el->el_line.buffer;
  791. if (parse_line(el, tmpbuf) == -1)
  792. return (CC_ERROR);
  793. else
  794. return (CC_REFRESH);
  795. }