emacs.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. /* $NetBSD: emacs.c,v 1.10 2002/03/18 16:00:52 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[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93";
  41. #else
  42. __RCSID("$NetBSD: emacs.c,v 1.10 2002/03/18 16:00:52 christos Exp $");
  43. #endif
  44. #endif /* not lint && not SCCSID */
  45. /*
  46. * emacs.c: Emacs functions
  47. */
  48. #include "el.h"
  49. /* em_delete_or_list():
  50. * Delete character under cursor or list completions if at end of line
  51. * [^D]
  52. */
  53. protected el_action_t
  54. /*ARGSUSED*/
  55. em_delete_or_list(EditLine *el, int c)
  56. {
  57. if (el->el_line.cursor == el->el_line.lastchar) {
  58. /* if I'm at the end */
  59. if (el->el_line.cursor == el->el_line.buffer) {
  60. /* and the beginning */
  61. term_overwrite(el, STReof, 4); /* then do a EOF */
  62. term__flush();
  63. return (CC_EOF);
  64. } else {
  65. /*
  66. * Here we could list completions, but it is an
  67. * error right now
  68. */
  69. term_beep(el);
  70. return (CC_ERROR);
  71. }
  72. } else {
  73. c_delafter(el, el->el_state.argument); /* delete after dot */
  74. if (el->el_line.cursor > el->el_line.lastchar)
  75. el->el_line.cursor = el->el_line.lastchar;
  76. /* bounds check */
  77. return (CC_REFRESH);
  78. }
  79. }
  80. /* em_delete_next_word():
  81. * Cut from cursor to end of current word
  82. * [M-d]
  83. */
  84. protected el_action_t
  85. /*ARGSUSED*/
  86. em_delete_next_word(EditLine *el, int c)
  87. {
  88. char *cp, *p, *kp;
  89. if (el->el_line.cursor == el->el_line.lastchar)
  90. return (CC_ERROR);
  91. cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
  92. el->el_state.argument, ce__isword);
  93. for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
  94. /* save the text */
  95. *kp++ = *p;
  96. el->el_chared.c_kill.last = kp;
  97. c_delafter(el, cp - el->el_line.cursor); /* delete after dot */
  98. if (el->el_line.cursor > el->el_line.lastchar)
  99. el->el_line.cursor = el->el_line.lastchar;
  100. /* bounds check */
  101. return (CC_REFRESH);
  102. }
  103. /* em_yank():
  104. * Paste cut buffer at cursor position
  105. * [^Y]
  106. */
  107. protected el_action_t
  108. /*ARGSUSED*/
  109. em_yank(EditLine *el, int c)
  110. {
  111. char *kp, *cp;
  112. if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf) {
  113. if (!ch_enlargebufs(el, 1))
  114. return (CC_ERROR);
  115. }
  116. if (el->el_line.lastchar +
  117. (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >=
  118. el->el_line.limit)
  119. return (CC_ERROR);
  120. el->el_chared.c_kill.mark = el->el_line.cursor;
  121. cp = el->el_line.cursor;
  122. /* open the space, */
  123. c_insert(el, el->el_chared.c_kill.last - el->el_chared.c_kill.buf);
  124. /* copy the chars */
  125. for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
  126. *cp++ = *kp;
  127. /* if an arg, cursor at beginning else cursor at end */
  128. if (el->el_state.argument == 1)
  129. el->el_line.cursor = cp;
  130. return (CC_REFRESH);
  131. }
  132. /* em_kill_line():
  133. * Cut the entire line and save in cut buffer
  134. * [^U]
  135. */
  136. protected el_action_t
  137. /*ARGSUSED*/
  138. em_kill_line(EditLine *el, int c)
  139. {
  140. char *kp, *cp;
  141. cp = el->el_line.buffer;
  142. kp = el->el_chared.c_kill.buf;
  143. while (cp < el->el_line.lastchar)
  144. *kp++ = *cp++; /* copy it */
  145. el->el_chared.c_kill.last = kp;
  146. /* zap! -- delete all of it */
  147. el->el_line.lastchar = el->el_line.buffer;
  148. el->el_line.cursor = el->el_line.buffer;
  149. return (CC_REFRESH);
  150. }
  151. /* em_kill_region():
  152. * Cut area between mark and cursor and save in cut buffer
  153. * [^W]
  154. */
  155. protected el_action_t
  156. /*ARGSUSED*/
  157. em_kill_region(EditLine *el, int c)
  158. {
  159. char *kp, *cp;
  160. if (!el->el_chared.c_kill.mark)
  161. return (CC_ERROR);
  162. if (el->el_chared.c_kill.mark > el->el_line.cursor) {
  163. cp = el->el_line.cursor;
  164. kp = el->el_chared.c_kill.buf;
  165. while (cp < el->el_chared.c_kill.mark)
  166. *kp++ = *cp++; /* copy it */
  167. el->el_chared.c_kill.last = kp;
  168. c_delafter(el, cp - el->el_line.cursor);
  169. } else { /* mark is before cursor */
  170. cp = el->el_chared.c_kill.mark;
  171. kp = el->el_chared.c_kill.buf;
  172. while (cp < el->el_line.cursor)
  173. *kp++ = *cp++; /* copy it */
  174. el->el_chared.c_kill.last = kp;
  175. c_delbefore(el, cp - el->el_chared.c_kill.mark);
  176. el->el_line.cursor = el->el_chared.c_kill.mark;
  177. }
  178. return (CC_REFRESH);
  179. }
  180. /* em_copy_region():
  181. * Copy area between mark and cursor to cut buffer
  182. * [M-W]
  183. */
  184. protected el_action_t
  185. /*ARGSUSED*/
  186. em_copy_region(EditLine *el, int c)
  187. {
  188. char *kp, *cp;
  189. if (el->el_chared.c_kill.mark)
  190. return (CC_ERROR);
  191. if (el->el_chared.c_kill.mark > el->el_line.cursor) {
  192. cp = el->el_line.cursor;
  193. kp = el->el_chared.c_kill.buf;
  194. while (cp < el->el_chared.c_kill.mark)
  195. *kp++ = *cp++; /* copy it */
  196. el->el_chared.c_kill.last = kp;
  197. } else {
  198. cp = el->el_chared.c_kill.mark;
  199. kp = el->el_chared.c_kill.buf;
  200. while (cp < el->el_line.cursor)
  201. *kp++ = *cp++; /* copy it */
  202. el->el_chared.c_kill.last = kp;
  203. }
  204. return (CC_NORM);
  205. }
  206. /* em_gosmacs_traspose():
  207. * Exchange the two characters before the cursor
  208. * Gosling emacs transpose chars [^T]
  209. */
  210. protected el_action_t
  211. em_gosmacs_traspose(EditLine *el, int c)
  212. {
  213. if (el->el_line.cursor > &el->el_line.buffer[1]) {
  214. /* must have at least two chars entered */
  215. c = el->el_line.cursor[-2];
  216. el->el_line.cursor[-2] = el->el_line.cursor[-1];
  217. el->el_line.cursor[-1] = c;
  218. return (CC_REFRESH);
  219. } else
  220. return (CC_ERROR);
  221. }
  222. /* em_next_word():
  223. * Move next to end of current word
  224. * [M-f]
  225. */
  226. protected el_action_t
  227. /*ARGSUSED*/
  228. em_next_word(EditLine *el, int c)
  229. {
  230. if (el->el_line.cursor == el->el_line.lastchar)
  231. return (CC_ERROR);
  232. el->el_line.cursor = c__next_word(el->el_line.cursor,
  233. el->el_line.lastchar,
  234. el->el_state.argument,
  235. ce__isword);
  236. if (el->el_map.type == MAP_VI)
  237. if (el->el_chared.c_vcmd.action & DELETE) {
  238. cv_delfini(el);
  239. return (CC_REFRESH);
  240. }
  241. return (CC_CURSOR);
  242. }
  243. /* em_upper_case():
  244. * Uppercase the characters from cursor to end of current word
  245. * [M-u]
  246. */
  247. protected el_action_t
  248. /*ARGSUSED*/
  249. em_upper_case(EditLine *el, int c)
  250. {
  251. char *cp, *ep;
  252. ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
  253. el->el_state.argument, ce__isword);
  254. for (cp = el->el_line.cursor; cp < ep; cp++)
  255. if (islower((unsigned char) *cp))
  256. *cp = toupper(*cp);
  257. el->el_line.cursor = ep;
  258. if (el->el_line.cursor > el->el_line.lastchar)
  259. el->el_line.cursor = el->el_line.lastchar;
  260. return (CC_REFRESH);
  261. }
  262. /* em_capitol_case():
  263. * Capitalize the characters from cursor to end of current word
  264. * [M-c]
  265. */
  266. protected el_action_t
  267. /*ARGSUSED*/
  268. em_capitol_case(EditLine *el, int c)
  269. {
  270. char *cp, *ep;
  271. ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
  272. el->el_state.argument, ce__isword);
  273. for (cp = el->el_line.cursor; cp < ep; cp++) {
  274. if (isalpha((unsigned char) *cp)) {
  275. if (islower((unsigned char) *cp))
  276. *cp = toupper(*cp);
  277. cp++;
  278. break;
  279. }
  280. }
  281. for (; cp < ep; cp++)
  282. if (isupper((unsigned char) *cp))
  283. *cp = tolower(*cp);
  284. el->el_line.cursor = ep;
  285. if (el->el_line.cursor > el->el_line.lastchar)
  286. el->el_line.cursor = el->el_line.lastchar;
  287. return (CC_REFRESH);
  288. }
  289. /* em_lower_case():
  290. * Lowercase the characters from cursor to end of current word
  291. * [M-l]
  292. */
  293. protected el_action_t
  294. /*ARGSUSED*/
  295. em_lower_case(EditLine *el, int c)
  296. {
  297. char *cp, *ep;
  298. ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
  299. el->el_state.argument, ce__isword);
  300. for (cp = el->el_line.cursor; cp < ep; cp++)
  301. if (isupper((unsigned char) *cp))
  302. *cp = tolower(*cp);
  303. el->el_line.cursor = ep;
  304. if (el->el_line.cursor > el->el_line.lastchar)
  305. el->el_line.cursor = el->el_line.lastchar;
  306. return (CC_REFRESH);
  307. }
  308. /* em_set_mark():
  309. * Set the mark at cursor
  310. * [^@]
  311. */
  312. protected el_action_t
  313. /*ARGSUSED*/
  314. em_set_mark(EditLine *el, int c)
  315. {
  316. el->el_chared.c_kill.mark = el->el_line.cursor;
  317. return (CC_NORM);
  318. }
  319. /* em_exchange_mark():
  320. * Exchange the cursor and mark
  321. * [^X^X]
  322. */
  323. protected el_action_t
  324. /*ARGSUSED*/
  325. em_exchange_mark(EditLine *el, int c)
  326. {
  327. char *cp;
  328. cp = el->el_line.cursor;
  329. el->el_line.cursor = el->el_chared.c_kill.mark;
  330. el->el_chared.c_kill.mark = cp;
  331. return (CC_CURSOR);
  332. }
  333. /* em_universal_argument():
  334. * Universal argument (argument times 4)
  335. * [^U]
  336. */
  337. protected el_action_t
  338. /*ARGSUSED*/
  339. em_universal_argument(EditLine *el, int c)
  340. { /* multiply current argument by 4 */
  341. if (el->el_state.argument > 1000000)
  342. return (CC_ERROR);
  343. el->el_state.doingarg = 1;
  344. el->el_state.argument *= 4;
  345. return (CC_ARGHACK);
  346. }
  347. /* em_meta_next():
  348. * Add 8th bit to next character typed
  349. * [<ESC>]
  350. */
  351. protected el_action_t
  352. /*ARGSUSED*/
  353. em_meta_next(EditLine *el, int c)
  354. {
  355. el->el_state.metanext = 1;
  356. return (CC_ARGHACK);
  357. }
  358. /* em_toggle_overwrite():
  359. * Switch from insert to overwrite mode or vice versa
  360. */
  361. protected el_action_t
  362. /*ARGSUSED*/
  363. em_toggle_overwrite(EditLine *el, int c)
  364. {
  365. el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ?
  366. MODE_REPLACE : MODE_INSERT;
  367. return (CC_NORM);
  368. }
  369. /* em_copy_prev_word():
  370. * Copy current word to cursor
  371. */
  372. protected el_action_t
  373. /*ARGSUSED*/
  374. em_copy_prev_word(EditLine *el, int c)
  375. {
  376. char *cp, *oldc, *dp;
  377. if (el->el_line.cursor == el->el_line.buffer)
  378. return (CC_ERROR);
  379. oldc = el->el_line.cursor;
  380. /* does a bounds check */
  381. cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
  382. el->el_state.argument, ce__isword);
  383. c_insert(el, oldc - cp);
  384. for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
  385. *dp++ = *cp;
  386. el->el_line.cursor = dp;/* put cursor at end */
  387. return (CC_REFRESH);
  388. }
  389. /* em_inc_search_next():
  390. * Emacs incremental next search
  391. */
  392. protected el_action_t
  393. /*ARGSUSED*/
  394. em_inc_search_next(EditLine *el, int c)
  395. {
  396. el->el_search.patlen = 0;
  397. return (ce_inc_search(el, ED_SEARCH_NEXT_HISTORY));
  398. }
  399. /* em_inc_search_prev():
  400. * Emacs incremental reverse search
  401. */
  402. protected el_action_t
  403. /*ARGSUSED*/
  404. em_inc_search_prev(EditLine *el, int c)
  405. {
  406. el->el_search.patlen = 0;
  407. return (ce_inc_search(el, ED_SEARCH_PREV_HISTORY));
  408. }