PageRenderTime 262ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/js/lib/Socket.IO-node/support/expresso/deps/jscoverage/js/editline/editline.c

http://github.com/onedayitwillmake/RealtimeMultiplayerNodeJs
C | 1368 lines | 1112 code | 158 blank | 98 comment | 272 complexity | 9a92f794d6fc8318bee250795bfb0b05 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2. *
  3. * ***** BEGIN LICENSE BLOCK *****
  4. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  5. *
  6. * The contents of this file are subject to the Mozilla Public License Version
  7. * 1.1 (the "License"); you may not use this file except in compliance with
  8. * the License. You may obtain a copy of the License at
  9. * http://www.mozilla.org/MPL/
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. *
  16. * The Original Code is Mozilla Communicator client code, released
  17. * March 31, 1998.
  18. *
  19. * The Initial Developer of the Original Code is
  20. * Simmule Turner and Rich Salz.
  21. * Portions created by the Initial Developer are Copyright (C) 1998
  22. * the Initial Developer. All Rights Reserved.
  23. *
  24. * Contributor(s):
  25. *
  26. * Alternatively, the contents of this file may be used under the terms of
  27. * either the GNU General Public License Version 2 or later (the "GPL"), or
  28. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  29. * in which case the provisions of the GPL or the LGPL are applicable instead
  30. * of those above. If you wish to allow use of your version of this file only
  31. * under the terms of either the GPL or the LGPL, and not to allow others to
  32. * use your version of this file under the terms of the MPL, indicate your
  33. * decision by deleting the provisions above and replace them with the notice
  34. * and other provisions required by the GPL or the LGPL. If you do not delete
  35. * the provisions above, a recipient may use your version of this file under
  36. * the terms of any one of the MPL, the GPL or the LGPL.
  37. *
  38. * ***** END LICENSE BLOCK ***** */
  39. /*
  40. * Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
  41. *
  42. * This software is not subject to any license of the American Telephone
  43. * and Telegraph Company or of the Regents of the University of California.
  44. *
  45. * Permission is granted to anyone to use this software for any purpose on
  46. * any computer system, and to alter it and redistribute it freely, subject
  47. * to the following restrictions:
  48. * 1. The authors are not responsible for the consequences of use of this
  49. * software, no matter how awful, even if they arise from flaws in it.
  50. * 2. The origin of this software must not be misrepresented, either by
  51. * explicit claim or by omission. Since few users ever read sources,
  52. * credits must appear in the documentation.
  53. * 3. Altered versions must be plainly marked as such, and must not be
  54. * misrepresented as being the original software. Since few users
  55. * ever read sources, credits must appear in the documentation.
  56. * 4. This notice may not be removed or altered.
  57. */
  58. /*
  59. ** Main editing routines for editline library.
  60. */
  61. #include "editline.h"
  62. #include <signal.h>
  63. #include <ctype.h>
  64. #include <unistd.h>
  65. /*
  66. ** Manifest constants.
  67. */
  68. #define SCREEN_WIDTH 80
  69. #define SCREEN_ROWS 24
  70. #define NO_ARG (-1)
  71. #define DEL 127
  72. #define CTL(x) ((x) & 0x1F)
  73. #define ISCTL(x) ((x) && (x) < ' ')
  74. #define UNCTL(x) ((x) + 64)
  75. #define META(x) ((x) | 0x80)
  76. #define ISMETA(x) ((x) & 0x80)
  77. #define UNMETA(x) ((x) & 0x7F)
  78. #if !defined(HIST_SIZE)
  79. #define HIST_SIZE 20
  80. #endif /* !defined(HIST_SIZE) */
  81. /*
  82. ** Command status codes.
  83. */
  84. typedef enum _STATUS {
  85. CSdone, CSeof, CSmove, CSdispatch, CSstay, CSsignal
  86. } STATUS;
  87. /*
  88. ** The type of case-changing to perform.
  89. */
  90. typedef enum _CASE {
  91. TOupper, TOlower
  92. } CASE;
  93. /*
  94. ** Key to command mapping.
  95. */
  96. typedef struct _KEYMAP {
  97. CHAR Key;
  98. STATUS (*Function)();
  99. } KEYMAP;
  100. /*
  101. ** Command history structure.
  102. */
  103. typedef struct _HISTORY {
  104. int Size;
  105. int Pos;
  106. CHAR *Lines[HIST_SIZE];
  107. } HISTORY;
  108. /*
  109. ** Globals.
  110. */
  111. int rl_eof;
  112. int rl_erase;
  113. int rl_intr;
  114. int rl_kill;
  115. int rl_quit;
  116. STATIC CHAR NIL[] = "";
  117. STATIC CONST CHAR *Input = NIL;
  118. STATIC CHAR *Line;
  119. STATIC CONST char *Prompt;
  120. STATIC CHAR *Yanked;
  121. STATIC char *Screen;
  122. STATIC char NEWLINE[]= CRLF;
  123. STATIC HISTORY H;
  124. STATIC int Repeat;
  125. STATIC int End;
  126. STATIC int Mark;
  127. STATIC int OldPoint;
  128. STATIC int Point;
  129. STATIC int PushBack;
  130. STATIC int Pushed;
  131. STATIC int Signal;
  132. FORWARD KEYMAP Map[32];
  133. FORWARD KEYMAP MetaMap[16];
  134. STATIC SIZE_T Length;
  135. STATIC SIZE_T ScreenCount;
  136. STATIC SIZE_T ScreenSize;
  137. STATIC char *backspace;
  138. STATIC int TTYwidth;
  139. STATIC int TTYrows;
  140. /* Display print 8-bit chars as `M-x' or as the actual 8-bit char? */
  141. int rl_meta_chars = 0;
  142. /*
  143. ** Declarations.
  144. */
  145. STATIC CHAR *editinput();
  146. #if defined(USE_TERMCAP)
  147. #include <stdlib.h>
  148. #include <curses.h>
  149. #include <term.h>
  150. #endif /* defined(USE_TERMCAP) */
  151. /*
  152. ** TTY input/output functions.
  153. */
  154. STATIC void
  155. TTYflush()
  156. {
  157. if (ScreenCount) {
  158. (void)write(1, Screen, ScreenCount);
  159. ScreenCount = 0;
  160. }
  161. }
  162. STATIC void
  163. TTYput(c)
  164. CHAR c;
  165. {
  166. Screen[ScreenCount] = c;
  167. if (++ScreenCount >= ScreenSize - 1) {
  168. ScreenSize += SCREEN_INC;
  169. RENEW(Screen, char, ScreenSize);
  170. }
  171. }
  172. STATIC void
  173. TTYputs(p)
  174. CHAR *p;
  175. {
  176. while (*p)
  177. TTYput(*p++);
  178. }
  179. STATIC void
  180. TTYshow(c)
  181. CHAR c;
  182. {
  183. if (c == DEL) {
  184. TTYput('^');
  185. TTYput('?');
  186. }
  187. else if (ISCTL(c)) {
  188. TTYput('^');
  189. TTYput(UNCTL(c));
  190. }
  191. else if (rl_meta_chars && ISMETA(c)) {
  192. TTYput('M');
  193. TTYput('-');
  194. TTYput(UNMETA(c));
  195. }
  196. else
  197. TTYput(c);
  198. }
  199. STATIC void
  200. TTYstring(p)
  201. CHAR *p;
  202. {
  203. while (*p)
  204. TTYshow(*p++);
  205. }
  206. STATIC unsigned int
  207. TTYget()
  208. {
  209. CHAR c;
  210. TTYflush();
  211. if (Pushed) {
  212. Pushed = 0;
  213. return PushBack;
  214. }
  215. if (*Input)
  216. return *Input++;
  217. return read(0, &c, (SIZE_T)1) == 1 ? c : EOF;
  218. }
  219. #define TTYback() (backspace ? TTYputs((CHAR *)backspace) : TTYput('\b'))
  220. STATIC void
  221. TTYbackn(n)
  222. int n;
  223. {
  224. while (--n >= 0)
  225. TTYback();
  226. }
  227. STATIC void
  228. TTYinfo()
  229. {
  230. static int init;
  231. #if defined(USE_TERMCAP)
  232. char *term;
  233. char buff[2048];
  234. char *bp, *p;
  235. #endif /* defined(USE_TERMCAP) */
  236. #if defined(TIOCGWINSZ)
  237. struct winsize W;
  238. #endif /* defined(TIOCGWINSZ) */
  239. if (init) {
  240. #if defined(TIOCGWINSZ)
  241. /* Perhaps we got resized. */
  242. if (ioctl(0, TIOCGWINSZ, &W) >= 0
  243. && W.ws_col > 0 && W.ws_row > 0) {
  244. TTYwidth = (int)W.ws_col;
  245. TTYrows = (int)W.ws_row;
  246. }
  247. #endif /* defined(TIOCGWINSZ) */
  248. return;
  249. }
  250. init++;
  251. TTYwidth = TTYrows = 0;
  252. #if defined(USE_TERMCAP)
  253. bp = &buff[0];
  254. if ((term = getenv("TERM")) == NULL)
  255. term = "dumb";
  256. if (tgetent(buff, term) < 0) {
  257. TTYwidth = SCREEN_WIDTH;
  258. TTYrows = SCREEN_ROWS;
  259. return;
  260. }
  261. p = tgetstr("le", &bp);
  262. backspace = p ? strdup(p) : NULL;
  263. TTYwidth = tgetnum("co");
  264. TTYrows = tgetnum("li");
  265. #endif /* defined(USE_TERMCAP) */
  266. #if defined(TIOCGWINSZ)
  267. if (ioctl(0, TIOCGWINSZ, &W) >= 0) {
  268. TTYwidth = (int)W.ws_col;
  269. TTYrows = (int)W.ws_row;
  270. }
  271. #endif /* defined(TIOCGWINSZ) */
  272. if (TTYwidth <= 0 || TTYrows <= 0) {
  273. TTYwidth = SCREEN_WIDTH;
  274. TTYrows = SCREEN_ROWS;
  275. }
  276. }
  277. STATIC void
  278. reposition()
  279. {
  280. int i;
  281. CHAR *p;
  282. TTYput('\r');
  283. TTYputs((CONST CHAR *)Prompt);
  284. for (i = Point, p = Line; --i >= 0; p++)
  285. TTYshow(*p);
  286. }
  287. STATIC void
  288. left(Change)
  289. STATUS Change;
  290. {
  291. TTYback();
  292. if (Point) {
  293. if (ISCTL(Line[Point - 1]))
  294. TTYback();
  295. else if (rl_meta_chars && ISMETA(Line[Point - 1])) {
  296. TTYback();
  297. TTYback();
  298. }
  299. }
  300. if (Change == CSmove)
  301. Point--;
  302. }
  303. STATIC void
  304. right(Change)
  305. STATUS Change;
  306. {
  307. TTYshow(Line[Point]);
  308. if (Change == CSmove)
  309. Point++;
  310. }
  311. STATIC STATUS
  312. ring_bell()
  313. {
  314. TTYput('\07');
  315. TTYflush();
  316. return CSstay;
  317. }
  318. STATIC STATUS
  319. do_macro(c)
  320. unsigned int c;
  321. {
  322. CHAR name[4];
  323. name[0] = '_';
  324. name[1] = c;
  325. name[2] = '_';
  326. name[3] = '\0';
  327. if ((Input = (CHAR *)getenv((char *)name)) == NULL) {
  328. Input = NIL;
  329. return ring_bell();
  330. }
  331. return CSstay;
  332. }
  333. STATIC STATUS
  334. do_forward(move)
  335. STATUS move;
  336. {
  337. int i;
  338. CHAR *p;
  339. i = 0;
  340. do {
  341. p = &Line[Point];
  342. for ( ; Point < End && (*p == ' ' || !isalnum(*p)); Point++, p++)
  343. if (move == CSmove)
  344. right(CSstay);
  345. for (; Point < End && isalnum(*p); Point++, p++)
  346. if (move == CSmove)
  347. right(CSstay);
  348. if (Point == End)
  349. break;
  350. } while (++i < Repeat);
  351. return CSstay;
  352. }
  353. STATIC STATUS
  354. do_case(type)
  355. CASE type;
  356. {
  357. int i;
  358. int end;
  359. int count;
  360. CHAR *p;
  361. (void)do_forward(CSstay);
  362. if (OldPoint != Point) {
  363. if ((count = Point - OldPoint) < 0)
  364. count = -count;
  365. Point = OldPoint;
  366. if ((end = Point + count) > End)
  367. end = End;
  368. for (i = Point, p = &Line[i]; i < end; i++, p++) {
  369. if (type == TOupper) {
  370. if (islower(*p))
  371. *p = toupper(*p);
  372. }
  373. else if (isupper(*p))
  374. *p = tolower(*p);
  375. right(CSmove);
  376. }
  377. }
  378. return CSstay;
  379. }
  380. STATIC STATUS
  381. case_down_word()
  382. {
  383. return do_case(TOlower);
  384. }
  385. STATIC STATUS
  386. case_up_word()
  387. {
  388. return do_case(TOupper);
  389. }
  390. STATIC void
  391. ceol()
  392. {
  393. int extras;
  394. int i;
  395. CHAR *p;
  396. for (extras = 0, i = Point, p = &Line[i]; i <= End; i++, p++) {
  397. TTYput(' ');
  398. if (ISCTL(*p)) {
  399. TTYput(' ');
  400. extras++;
  401. }
  402. else if (rl_meta_chars && ISMETA(*p)) {
  403. TTYput(' ');
  404. TTYput(' ');
  405. extras += 2;
  406. }
  407. }
  408. for (i += extras; i > Point; i--)
  409. TTYback();
  410. }
  411. STATIC void
  412. clear_line()
  413. {
  414. Point = -strlen(Prompt);
  415. TTYput('\r');
  416. ceol();
  417. Point = 0;
  418. End = 0;
  419. Line[0] = '\0';
  420. }
  421. STATIC STATUS
  422. insert_string(p)
  423. CHAR *p;
  424. {
  425. SIZE_T len;
  426. int i;
  427. CHAR *new;
  428. CHAR *q;
  429. len = strlen((char *)p);
  430. if (End + len >= Length) {
  431. if ((new = NEW(CHAR, Length + len + MEM_INC)) == NULL)
  432. return CSstay;
  433. if (Length) {
  434. COPYFROMTO(new, Line, Length);
  435. DISPOSE(Line);
  436. }
  437. Line = new;
  438. Length += len + MEM_INC;
  439. }
  440. for (q = &Line[Point], i = End - Point; --i >= 0; )
  441. q[len + i] = q[i];
  442. COPYFROMTO(&Line[Point], p, len);
  443. End += len;
  444. Line[End] = '\0';
  445. TTYstring(&Line[Point]);
  446. Point += len;
  447. return Point == End ? CSstay : CSmove;
  448. }
  449. STATIC STATUS
  450. redisplay()
  451. {
  452. TTYputs((CONST CHAR *)NEWLINE);
  453. TTYputs((CONST CHAR *)Prompt);
  454. TTYstring(Line);
  455. return CSmove;
  456. }
  457. STATIC STATUS
  458. toggle_meta_mode()
  459. {
  460. rl_meta_chars = ! rl_meta_chars;
  461. return redisplay();
  462. }
  463. STATIC CHAR *
  464. next_hist()
  465. {
  466. return H.Pos >= H.Size - 1 ? NULL : H.Lines[++H.Pos];
  467. }
  468. STATIC CHAR *
  469. prev_hist()
  470. {
  471. return H.Pos == 0 ? NULL : H.Lines[--H.Pos];
  472. }
  473. STATIC STATUS
  474. do_insert_hist(p)
  475. CHAR *p;
  476. {
  477. if (p == NULL)
  478. return ring_bell();
  479. Point = 0;
  480. reposition();
  481. ceol();
  482. End = 0;
  483. return insert_string(p);
  484. }
  485. STATIC STATUS
  486. do_hist(move)
  487. CHAR *(*move)();
  488. {
  489. CHAR *p;
  490. int i;
  491. i = 0;
  492. do {
  493. if ((p = (*move)()) == NULL)
  494. return ring_bell();
  495. } while (++i < Repeat);
  496. return do_insert_hist(p);
  497. }
  498. STATIC STATUS
  499. h_next()
  500. {
  501. return do_hist(next_hist);
  502. }
  503. STATIC STATUS
  504. h_prev()
  505. {
  506. return do_hist(prev_hist);
  507. }
  508. STATIC STATUS
  509. h_first()
  510. {
  511. return do_insert_hist(H.Lines[H.Pos = 0]);
  512. }
  513. STATIC STATUS
  514. h_last()
  515. {
  516. return do_insert_hist(H.Lines[H.Pos = H.Size - 1]);
  517. }
  518. /*
  519. ** Return zero if pat appears as a substring in text.
  520. */
  521. STATIC int
  522. substrcmp(text, pat, len)
  523. char *text;
  524. char *pat;
  525. int len;
  526. {
  527. char c;
  528. if ((c = *pat) == '\0')
  529. return *text == '\0';
  530. for ( ; *text; text++)
  531. if (*text == c && strncmp(text, pat, len) == 0)
  532. return 0;
  533. return 1;
  534. }
  535. STATIC CHAR *
  536. search_hist(search, move)
  537. CHAR *search;
  538. CHAR *(*move)();
  539. {
  540. static CHAR *old_search;
  541. int len;
  542. int pos;
  543. int (*match)();
  544. char *pat;
  545. /* Save or get remembered search pattern. */
  546. if (search && *search) {
  547. if (old_search)
  548. DISPOSE(old_search);
  549. old_search = (CHAR *)strdup((char *)search);
  550. }
  551. else {
  552. if (old_search == NULL || *old_search == '\0')
  553. return NULL;
  554. search = old_search;
  555. }
  556. /* Set up pattern-finder. */
  557. if (*search == '^') {
  558. match = strncmp;
  559. pat = (char *)(search + 1);
  560. }
  561. else {
  562. match = substrcmp;
  563. pat = (char *)search;
  564. }
  565. len = strlen(pat);
  566. for (pos = H.Pos; (*move)() != NULL; )
  567. if ((*match)((char *)H.Lines[H.Pos], pat, len) == 0)
  568. return H.Lines[H.Pos];
  569. H.Pos = pos;
  570. return NULL;
  571. }
  572. STATIC STATUS
  573. h_search()
  574. {
  575. static int Searching;
  576. CONST char *old_prompt;
  577. CHAR *(*move)();
  578. CHAR *p;
  579. if (Searching)
  580. return ring_bell();
  581. Searching = 1;
  582. clear_line();
  583. old_prompt = Prompt;
  584. Prompt = "Search: ";
  585. TTYputs((CONST CHAR *)Prompt);
  586. move = Repeat == NO_ARG ? prev_hist : next_hist;
  587. p = editinput();
  588. Prompt = old_prompt;
  589. Searching = 0;
  590. TTYputs((CONST CHAR *)Prompt);
  591. if (p == NULL && Signal > 0) {
  592. Signal = 0;
  593. clear_line();
  594. return redisplay();
  595. }
  596. p = search_hist(p, move);
  597. clear_line();
  598. if (p == NULL) {
  599. (void)ring_bell();
  600. return redisplay();
  601. }
  602. return do_insert_hist(p);
  603. }
  604. STATIC STATUS
  605. fd_char()
  606. {
  607. int i;
  608. i = 0;
  609. do {
  610. if (Point >= End)
  611. break;
  612. right(CSmove);
  613. } while (++i < Repeat);
  614. return CSstay;
  615. }
  616. STATIC void
  617. save_yank(begin, i)
  618. int begin;
  619. int i;
  620. {
  621. if (Yanked) {
  622. DISPOSE(Yanked);
  623. Yanked = NULL;
  624. }
  625. if (i < 1)
  626. return;
  627. if ((Yanked = NEW(CHAR, (SIZE_T)i + 1)) != NULL) {
  628. COPYFROMTO(Yanked, &Line[begin], i);
  629. Yanked[i] = '\0';
  630. }
  631. }
  632. STATIC STATUS
  633. delete_string(count)
  634. int count;
  635. {
  636. int i;
  637. CHAR *p;
  638. if (count <= 0 || End == Point)
  639. return ring_bell();
  640. if (count == 1 && Point == End - 1) {
  641. /* Optimize common case of delete at end of line. */
  642. End--;
  643. p = &Line[Point];
  644. i = 1;
  645. TTYput(' ');
  646. if (ISCTL(*p)) {
  647. i = 2;
  648. TTYput(' ');
  649. }
  650. else if (rl_meta_chars && ISMETA(*p)) {
  651. i = 3;
  652. TTYput(' ');
  653. TTYput(' ');
  654. }
  655. TTYbackn(i);
  656. *p = '\0';
  657. return CSmove;
  658. }
  659. if (Point + count > End && (count = End - Point) <= 0)
  660. return CSstay;
  661. if (count > 1)
  662. save_yank(Point, count);
  663. for (p = &Line[Point], i = End - (Point + count) + 1; --i >= 0; p++)
  664. p[0] = p[count];
  665. ceol();
  666. End -= count;
  667. TTYstring(&Line[Point]);
  668. return CSmove;
  669. }
  670. STATIC STATUS
  671. bk_char()
  672. {
  673. int i;
  674. i = 0;
  675. do {
  676. if (Point == 0)
  677. break;
  678. left(CSmove);
  679. } while (++i < Repeat);
  680. return CSstay;
  681. }
  682. STATIC STATUS
  683. bk_del_char()
  684. {
  685. int i;
  686. i = 0;
  687. do {
  688. if (Point == 0)
  689. break;
  690. left(CSmove);
  691. } while (++i < Repeat);
  692. return delete_string(i);
  693. }
  694. STATIC STATUS
  695. kill_line()
  696. {
  697. int i;
  698. if (Repeat != NO_ARG) {
  699. if (Repeat < Point) {
  700. i = Point;
  701. Point = Repeat;
  702. reposition();
  703. (void)delete_string(i - Point);
  704. }
  705. else if (Repeat > Point) {
  706. right(CSmove);
  707. (void)delete_string(Repeat - Point - 1);
  708. }
  709. return CSmove;
  710. }
  711. save_yank(Point, End - Point);
  712. Line[Point] = '\0';
  713. ceol();
  714. End = Point;
  715. return CSstay;
  716. }
  717. STATIC STATUS
  718. insert_char(c)
  719. int c;
  720. {
  721. STATUS s;
  722. CHAR buff[2];
  723. CHAR *p;
  724. CHAR *q;
  725. int i;
  726. if (Repeat == NO_ARG || Repeat < 2) {
  727. buff[0] = c;
  728. buff[1] = '\0';
  729. return insert_string(buff);
  730. }
  731. if ((p = NEW(CHAR, Repeat + 1)) == NULL)
  732. return CSstay;
  733. for (i = Repeat, q = p; --i >= 0; )
  734. *q++ = c;
  735. *q = '\0';
  736. Repeat = 0;
  737. s = insert_string(p);
  738. DISPOSE(p);
  739. return s;
  740. }
  741. STATIC STATUS
  742. meta()
  743. {
  744. unsigned int c;
  745. KEYMAP *kp;
  746. if ((c = TTYget()) == EOF)
  747. return CSeof;
  748. #if defined(ANSI_ARROWS)
  749. /* Also include VT-100 arrows. */
  750. if (c == '[' || c == 'O')
  751. switch (c = TTYget()) {
  752. default: return ring_bell();
  753. case EOF: return CSeof;
  754. case 'A': return h_prev();
  755. case 'B': return h_next();
  756. case 'C': return fd_char();
  757. case 'D': return bk_char();
  758. }
  759. #endif /* defined(ANSI_ARROWS) */
  760. if (isdigit(c)) {
  761. for (Repeat = c - '0'; (c = TTYget()) != EOF && isdigit(c); )
  762. Repeat = Repeat * 10 + c - '0';
  763. Pushed = 1;
  764. PushBack = c;
  765. return CSstay;
  766. }
  767. if (isupper(c))
  768. return do_macro(c);
  769. for (OldPoint = Point, kp = MetaMap; kp->Function; kp++)
  770. if (kp->Key == c)
  771. return (*kp->Function)();
  772. return ring_bell();
  773. }
  774. STATIC STATUS
  775. emacs(c)
  776. unsigned int c;
  777. {
  778. STATUS s;
  779. KEYMAP *kp;
  780. if (rl_meta_chars && ISMETA(c)) {
  781. Pushed = 1;
  782. PushBack = UNMETA(c);
  783. return meta();
  784. }
  785. for (kp = Map; kp->Function; kp++)
  786. if (kp->Key == c)
  787. break;
  788. s = kp->Function ? (*kp->Function)() : insert_char((int)c);
  789. if (!Pushed)
  790. /* No pushback means no repeat count; hacky, but true. */
  791. Repeat = NO_ARG;
  792. return s;
  793. }
  794. STATIC STATUS
  795. TTYspecial(c)
  796. unsigned int c;
  797. {
  798. if (ISMETA(c))
  799. return CSdispatch;
  800. if (c == rl_erase || c == DEL)
  801. return bk_del_char();
  802. if (c == rl_kill) {
  803. if (Point != 0) {
  804. Point = 0;
  805. reposition();
  806. }
  807. Repeat = NO_ARG;
  808. return kill_line();
  809. }
  810. if (c == rl_eof && Point == 0 && End == 0)
  811. return CSeof;
  812. if (c == rl_intr) {
  813. Signal = SIGINT;
  814. return CSsignal;
  815. }
  816. if (c == rl_quit) {
  817. Signal = SIGQUIT;
  818. return CSeof;
  819. }
  820. return CSdispatch;
  821. }
  822. STATIC CHAR *
  823. editinput()
  824. {
  825. unsigned int c;
  826. Repeat = NO_ARG;
  827. OldPoint = Point = Mark = End = 0;
  828. Line[0] = '\0';
  829. Signal = -1;
  830. while ((c = TTYget()) != EOF)
  831. switch (TTYspecial(c)) {
  832. case CSdone:
  833. return Line;
  834. case CSeof:
  835. return NULL;
  836. case CSsignal:
  837. return (CHAR *)"";
  838. case CSmove:
  839. reposition();
  840. break;
  841. case CSdispatch:
  842. switch (emacs(c)) {
  843. case CSdone:
  844. return Line;
  845. case CSeof:
  846. return NULL;
  847. case CSsignal:
  848. return (CHAR *)"";
  849. case CSmove:
  850. reposition();
  851. break;
  852. case CSdispatch:
  853. case CSstay:
  854. break;
  855. }
  856. break;
  857. case CSstay:
  858. break;
  859. }
  860. return NULL;
  861. }
  862. STATIC void
  863. hist_add(p)
  864. CHAR *p;
  865. {
  866. int i;
  867. if ((p = (CHAR *)strdup((char *)p)) == NULL)
  868. return;
  869. if (H.Size < HIST_SIZE)
  870. H.Lines[H.Size++] = p;
  871. else {
  872. DISPOSE(H.Lines[0]);
  873. for (i = 0; i < HIST_SIZE - 1; i++)
  874. H.Lines[i] = H.Lines[i + 1];
  875. H.Lines[i] = p;
  876. }
  877. H.Pos = H.Size - 1;
  878. }
  879. /*
  880. ** For compatibility with FSF readline.
  881. */
  882. /* ARGSUSED0 */
  883. void
  884. rl_reset_terminal(p)
  885. char *p;
  886. {
  887. }
  888. void
  889. rl_initialize()
  890. {
  891. }
  892. char *
  893. readline(prompt)
  894. CONST char *prompt;
  895. {
  896. CHAR *line;
  897. int s;
  898. if (Line == NULL) {
  899. Length = MEM_INC;
  900. if ((Line = NEW(CHAR, Length)) == NULL)
  901. return NULL;
  902. }
  903. TTYinfo();
  904. rl_ttyset(0);
  905. hist_add(NIL);
  906. ScreenSize = SCREEN_INC;
  907. Screen = NEW(char, ScreenSize);
  908. Prompt = prompt ? prompt : (char *)NIL;
  909. TTYputs((CONST CHAR *)Prompt);
  910. if ((line = editinput()) != NULL) {
  911. line = (CHAR *)strdup((char *)line);
  912. TTYputs((CHAR *)NEWLINE);
  913. TTYflush();
  914. }
  915. rl_ttyset(1);
  916. DISPOSE(Screen);
  917. DISPOSE(H.Lines[--H.Size]);
  918. if (Signal > 0) {
  919. s = Signal;
  920. Signal = 0;
  921. (void)kill(getpid(), s);
  922. }
  923. return (char *)line;
  924. }
  925. void
  926. add_history(p)
  927. char *p;
  928. {
  929. if (p == NULL || *p == '\0')
  930. return;
  931. #if defined(UNIQUE_HISTORY)
  932. if (H.Size && strcmp(p, H.Lines[H.Size - 1]) == 0)
  933. return;
  934. #endif /* defined(UNIQUE_HISTORY) */
  935. hist_add((CHAR *)p);
  936. }
  937. STATIC STATUS
  938. beg_line()
  939. {
  940. if (Point) {
  941. Point = 0;
  942. return CSmove;
  943. }
  944. return CSstay;
  945. }
  946. STATIC STATUS
  947. del_char()
  948. {
  949. return delete_string(Repeat == NO_ARG ? 1 : Repeat);
  950. }
  951. STATIC STATUS
  952. end_line()
  953. {
  954. if (Point != End) {
  955. Point = End;
  956. return CSmove;
  957. }
  958. return CSstay;
  959. }
  960. STATIC STATUS
  961. accept_line()
  962. {
  963. Line[End] = '\0';
  964. return CSdone;
  965. }
  966. STATIC STATUS
  967. transpose()
  968. {
  969. CHAR c;
  970. if (Point) {
  971. if (Point == End)
  972. left(CSmove);
  973. c = Line[Point - 1];
  974. left(CSstay);
  975. Line[Point - 1] = Line[Point];
  976. TTYshow(Line[Point - 1]);
  977. Line[Point++] = c;
  978. TTYshow(c);
  979. }
  980. return CSstay;
  981. }
  982. STATIC STATUS
  983. quote()
  984. {
  985. unsigned int c;
  986. return (c = TTYget()) == EOF ? CSeof : insert_char((int)c);
  987. }
  988. STATIC STATUS
  989. wipe()
  990. {
  991. int i;
  992. if (Mark > End)
  993. return ring_bell();
  994. if (Point > Mark) {
  995. i = Point;
  996. Point = Mark;
  997. Mark = i;
  998. reposition();
  999. }
  1000. return delete_string(Mark - Point);
  1001. }
  1002. STATIC STATUS
  1003. mk_set()
  1004. {
  1005. Mark = Point;
  1006. return CSstay;
  1007. }
  1008. STATIC STATUS
  1009. exchange()
  1010. {
  1011. unsigned int c;
  1012. if ((c = TTYget()) != CTL('X'))
  1013. return c == EOF ? CSeof : ring_bell();
  1014. if ((c = Mark) <= End) {
  1015. Mark = Point;
  1016. Point = c;
  1017. return CSmove;
  1018. }
  1019. return CSstay;
  1020. }
  1021. STATIC STATUS
  1022. yank()
  1023. {
  1024. if (Yanked && *Yanked)
  1025. return insert_string(Yanked);
  1026. return CSstay;
  1027. }
  1028. STATIC STATUS
  1029. copy_region()
  1030. {
  1031. if (Mark > End)
  1032. return ring_bell();
  1033. if (Point > Mark)
  1034. save_yank(Mark, Point - Mark);
  1035. else
  1036. save_yank(Point, Mark - Point);
  1037. return CSstay;
  1038. }
  1039. STATIC STATUS
  1040. move_to_char()
  1041. {
  1042. unsigned int c;
  1043. int i;
  1044. CHAR *p;
  1045. if ((c = TTYget()) == EOF)
  1046. return CSeof;
  1047. for (i = Point + 1, p = &Line[i]; i < End; i++, p++)
  1048. if (*p == c) {
  1049. Point = i;
  1050. return CSmove;
  1051. }
  1052. return CSstay;
  1053. }
  1054. STATIC STATUS
  1055. fd_word()
  1056. {
  1057. return do_forward(CSmove);
  1058. }
  1059. STATIC STATUS
  1060. fd_kill_word()
  1061. {
  1062. int i;
  1063. (void)do_forward(CSstay);
  1064. if (OldPoint != Point) {
  1065. i = Point - OldPoint;
  1066. Point = OldPoint;
  1067. return delete_string(i);
  1068. }
  1069. return CSstay;
  1070. }
  1071. STATIC STATUS
  1072. bk_word()
  1073. {
  1074. int i;
  1075. CHAR *p;
  1076. i = 0;
  1077. do {
  1078. for (p = &Line[Point]; p > Line && !isalnum(p[-1]); p--)
  1079. left(CSmove);
  1080. for (; p > Line && p[-1] != ' ' && isalnum(p[-1]); p--)
  1081. left(CSmove);
  1082. if (Point == 0)
  1083. break;
  1084. } while (++i < Repeat);
  1085. return CSstay;
  1086. }
  1087. STATIC STATUS
  1088. bk_kill_word()
  1089. {
  1090. (void)bk_word();
  1091. if (OldPoint != Point)
  1092. return delete_string(OldPoint - Point);
  1093. return CSstay;
  1094. }
  1095. STATIC int
  1096. argify(line, avp)
  1097. CHAR *line;
  1098. CHAR ***avp;
  1099. {
  1100. CHAR *c;
  1101. CHAR **p;
  1102. CHAR **new;
  1103. int ac;
  1104. int i;
  1105. i = MEM_INC;
  1106. if ((*avp = p = NEW(CHAR*, i))== NULL)
  1107. return 0;
  1108. for (c = line; isspace(*c); c++)
  1109. continue;
  1110. if (*c == '\n' || *c == '\0')
  1111. return 0;
  1112. for (ac = 0, p[ac++] = c; *c && *c != '\n'; ) {
  1113. if (isspace(*c)) {
  1114. *c++ = '\0';
  1115. if (*c && *c != '\n') {
  1116. if (ac + 1 == i) {
  1117. new = NEW(CHAR*, i + MEM_INC);
  1118. if (new == NULL) {
  1119. p[ac] = NULL;
  1120. return ac;
  1121. }
  1122. COPYFROMTO(new, p, i * sizeof (char **));
  1123. i += MEM_INC;
  1124. DISPOSE(p);
  1125. *avp = p = new;
  1126. }
  1127. p[ac++] = c;
  1128. }
  1129. }
  1130. else
  1131. c++;
  1132. }
  1133. *c = '\0';
  1134. p[ac] = NULL;
  1135. return ac;
  1136. }
  1137. STATIC STATUS
  1138. last_argument()
  1139. {
  1140. CHAR **av;
  1141. CHAR *p;
  1142. STATUS s;
  1143. int ac;
  1144. if (H.Size == 1 || (p = H.Lines[H.Size - 2]) == NULL)
  1145. return ring_bell();
  1146. if ((p = (CHAR *)strdup((char *)p)) == NULL)
  1147. return CSstay;
  1148. ac = argify(p, &av);
  1149. if (Repeat != NO_ARG)
  1150. s = Repeat < ac ? insert_string(av[Repeat]) : ring_bell();
  1151. else
  1152. s = ac ? insert_string(av[ac - 1]) : CSstay;
  1153. if (ac)
  1154. DISPOSE(av);
  1155. DISPOSE(p);
  1156. return s;
  1157. }
  1158. STATIC KEYMAP Map[32] = {
  1159. { CTL('@'), ring_bell },
  1160. { CTL('A'), beg_line },
  1161. { CTL('B'), bk_char },
  1162. { CTL('D'), del_char },
  1163. { CTL('E'), end_line },
  1164. { CTL('F'), fd_char },
  1165. { CTL('G'), ring_bell },
  1166. { CTL('H'), bk_del_char },
  1167. { CTL('J'), accept_line },
  1168. { CTL('K'), kill_line },
  1169. { CTL('L'), redisplay },
  1170. { CTL('M'), accept_line },
  1171. { CTL('N'), h_next },
  1172. { CTL('O'), ring_bell },
  1173. { CTL('P'), h_prev },
  1174. { CTL('Q'), ring_bell },
  1175. { CTL('R'), h_search },
  1176. { CTL('S'), ring_bell },
  1177. { CTL('T'), transpose },
  1178. { CTL('U'), ring_bell },
  1179. { CTL('V'), quote },
  1180. { CTL('W'), wipe },
  1181. { CTL('X'), exchange },
  1182. { CTL('Y'), yank },
  1183. { CTL('Z'), ring_bell },
  1184. { CTL('['), meta },
  1185. { CTL(']'), move_to_char },
  1186. { CTL('^'), ring_bell },
  1187. { CTL('_'), ring_bell },
  1188. { 0, NULL }
  1189. };
  1190. STATIC KEYMAP MetaMap[16]= {
  1191. { CTL('H'), bk_kill_word },
  1192. { DEL, bk_kill_word },
  1193. { ' ', mk_set },
  1194. { '.', last_argument },
  1195. { '<', h_first },
  1196. { '>', h_last },
  1197. { 'b', bk_word },
  1198. { 'd', fd_kill_word },
  1199. { 'f', fd_word },
  1200. { 'l', case_down_word },
  1201. { 'm', toggle_meta_mode },
  1202. { 'u', case_up_word },
  1203. { 'y', yank },
  1204. { 'w', copy_region },
  1205. { 0, NULL }
  1206. };