25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

819 lines
20KB

  1. /* vim128.c - a small modal editor for the Commodore 128, built with cc65.
  2. *
  3. * cl65 -t c128 -O -o vim128.prg vim128.c
  4. *
  5. * A port of the Power C / C64 editor (vim.c, vscreen.c, vview.c, vedit.c).
  6. * The Power C version needed hand-written machine code and direct screen
  7. * pokes; here cc65's conio draws the screen, so the same program works on the
  8. * 40 column VIC screen and on the 80 column VDC screen (it uses whatever
  9. * screensize() reports).
  10. *
  11. * move h j k l / arrows, 0 $ gg G
  12. * insert i a A I o O (RUN/STOP or ESC leaves insert mode, DEL backspaces)
  13. * change x dd p
  14. * colon :w :w name :wq :x :q :q!
  15. *
  16. * The buffer holds the file exactly as it sits on disk: PETSCII bytes with $0d
  17. * between lines. Keys are PETSCII too: unshifted letters arrive as $41-$5a and
  18. * shifted ones as $c1-$da, which is what KL() and KU() below spell.
  19. */
  20. #include <conio.h>
  21. #include <cbm.h>
  22. #include <c128.h>
  23. #include <string.h>
  24. #define BUFMAX 19000u /* bytes of file text */
  25. #define MAXLN 600 /* lines */
  26. #define MAXCOL 80 /* longest line kept */
  27. #define NAMEMAX 20
  28. /* cc65 translates character literals to PETSCII for the c128 target, so 'h'
  29. is already $48 (what the unshifted key sends) and 'G' is $c7 (shifted). */
  30. #define KL(c) (c) /* unshifted letter, e.g. KL('h') */
  31. #define KU(c) (c) /* shifted letter, e.g. KU('G') */
  32. #define K_STOP 3
  33. #define K_ESC 27
  34. #define K_DEL 20
  35. #define K_RET 13
  36. #define K_DOWN 17
  37. #define K_UP 145
  38. #define K_RIGHT 29
  39. #define K_LEFT 157
  40. static unsigned char bfr[BUFMAX]; /* file text, $0d separated */
  41. static unsigned blen; /* bytes used */
  42. static unsigned lptr[MAXLN]; /* offset of each line start */
  43. static int nlines;
  44. static int cy, cx; /* cursor line and column */
  45. static int top, leftcol; /* first line / column on screen */
  46. static char fname[NAMEMAX + 1];
  47. static int mode; /* 0 normal, 1 insert */
  48. static int dirty; /* changed since the last save */
  49. static int pend; /* first key of dd / gg */
  50. static const char *note; /* one-shot status message */
  51. static unsigned char ybuf[MAXCOL]; /* the yanked line */
  52. static int ylen, yok;
  53. static int redraw; /* 1 cursor row, 2 whole screen */
  54. static int split; /* a long line was split on load */
  55. static unsigned char dev; /* disk device */
  56. static unsigned char sw, sh; /* screen width, height */
  57. static int rows; /* text rows = sh - 1 (last is status) */
  58. static int ltop, lleft, lcy, lcx;
  59. /* ------------------------------------------------------------------ screen */
  60. static void putstr(int r, int c, const char *s)
  61. {
  62. gotoxy(c, r);
  63. while (*s && c < sw) {
  64. cputc(*s++);
  65. c++;
  66. }
  67. }
  68. static char lstat[84];
  69. static void clrstat(int c)
  70. {
  71. lstat[0] = 0; /* status row no longer as drawn */
  72. /* the very last cell is left alone: writing it can make the screen
  73. editor wrap */
  74. gotoxy(c, sh - 1);
  75. while (c < sw - 1) {
  76. cputc(' ');
  77. c++;
  78. }
  79. }
  80. static void sinit(void)
  81. {
  82. screensize(&sw, &sh);
  83. rows = sh - 1;
  84. cbm_k_bsout(14); /* lower/upper case character set */
  85. cbm_k_bsout(8); /* ...and lock it against SHIFT+C= */
  86. bgcolor(COLOR_BLUE);
  87. bordercolor(COLOR_BLACK);
  88. textcolor(COLOR_WHITE);
  89. cursor(0);
  90. revers(0);
  91. clrscr();
  92. if (sw > 40) fast(); /* 2 MHz: only with the 80 column screen,
  93. the VIC display is blanked in fast mode */
  94. }
  95. static void sdone(void)
  96. {
  97. slow();
  98. revers(0);
  99. bgcolor(COLOR_BLACK);
  100. bordercolor(COLOR_LIGHTBLUE);
  101. textcolor(COLOR_LIGHTGREEN);
  102. clrscr();
  103. cursor(1);
  104. }
  105. static int skey(void)
  106. {
  107. return cgetc();
  108. }
  109. /* --------------------------------------------------------------- buffer */
  110. /* end offset (exclusive of the $0d) of line ln */
  111. static unsigned linend(int ln)
  112. {
  113. if (ln + 1 < nlines) return lptr[ln + 1] - 1;
  114. return blen;
  115. }
  116. static int linelen(int ln)
  117. {
  118. return (int) (linend(ln) - lptr[ln]);
  119. }
  120. static void clampx(void)
  121. {
  122. int len = linelen(cy);
  123. if (cx > len) cx = len;
  124. if (cx < 0) cx = 0;
  125. }
  126. static void buildidx(void)
  127. {
  128. unsigned i;
  129. nlines = 1;
  130. lptr[0] = 0;
  131. for (i = 0; i < blen; i++) {
  132. if (bfr[i] == 13 && nlines < MAXLN - 1) lptr[nlines++] = i + 1;
  133. }
  134. }
  135. static void adjust(int from, int delta) /* lptr[from..nlines-1] += delta */
  136. {
  137. int i;
  138. for (i = from; i < nlines; i++) lptr[i] += delta;
  139. }
  140. static void bmove(unsigned from, unsigned to, unsigned n)
  141. {
  142. unsigned char *s, *d;
  143. if (n == 0 || from == to) return;
  144. s = bfr + from;
  145. d = bfr + to;
  146. if (d < s) {
  147. while (n--) *d++ = *s++;
  148. } else {
  149. s += n;
  150. d += n;
  151. while (n--) *--d = *--s;
  152. }
  153. }
  154. static int bins(unsigned pos, int ch)
  155. {
  156. if (blen >= BUFMAX - 1) return 0;
  157. bmove(pos, pos + 1, blen - pos);
  158. bfr[pos] = ch;
  159. blen++;
  160. dirty = 1;
  161. return 1;
  162. }
  163. static void delrange(unsigned pos, unsigned n)
  164. {
  165. bmove(pos + n, pos, blen - pos - n);
  166. blen -= n;
  167. dirty = 1;
  168. }
  169. static int inschar(int ch)
  170. {
  171. if (linelen(cy) >= MAXCOL) {
  172. note = "line full (80)";
  173. return 0;
  174. }
  175. if (!bins(lptr[cy] + cx, ch)) return 0;
  176. adjust(cy + 1, 1);
  177. cx++;
  178. if (redraw < 1) redraw = 1;
  179. return 1;
  180. }
  181. static int newline(void)
  182. {
  183. unsigned pos;
  184. int i;
  185. if (nlines >= MAXLN - 1) return 0;
  186. pos = lptr[cy] + cx;
  187. if (!bins(pos, 13)) return 0;
  188. for (i = nlines; i > cy + 1; i--) lptr[i] = lptr[i - 1];
  189. lptr[cy + 1] = pos + 1;
  190. nlines++;
  191. adjust(cy + 2, 1);
  192. redraw = 2;
  193. cy++;
  194. cx = 0;
  195. return 1;
  196. }
  197. static int delchar(void)
  198. {
  199. if (cx >= linelen(cy)) return 0;
  200. delrange(lptr[cy] + cx, 1);
  201. adjust(cy + 1, -1);
  202. if (redraw < 1) redraw = 1;
  203. return 1;
  204. }
  205. static void bkspace(void)
  206. {
  207. int pl, i;
  208. if (cx > 0) {
  209. cx--;
  210. delchar();
  211. return;
  212. }
  213. if (cy == 0) return;
  214. pl = linelen(cy - 1);
  215. if (pl + linelen(cy) > MAXCOL) {
  216. note = "joined line would pass 80";
  217. return;
  218. }
  219. delrange(lptr[cy] - 1, 1);
  220. for (i = cy; i < nlines - 1; i++) lptr[i] = lptr[i + 1];
  221. nlines--;
  222. adjust(cy, -1);
  223. redraw = 2;
  224. cy--;
  225. cx = pl;
  226. }
  227. static void delline(void)
  228. {
  229. int i;
  230. unsigned s, e, n;
  231. s = lptr[cy];
  232. e = linend(cy);
  233. ylen = e - s;
  234. if (ylen > MAXCOL) ylen = MAXCOL;
  235. for (i = 0; i < ylen; i++) ybuf[i] = bfr[s + i];
  236. yok = 1;
  237. if (nlines == 1) {
  238. blen = 0;
  239. dirty = 1;
  240. } else if (cy + 1 < nlines) {
  241. n = lptr[cy + 1] - s;
  242. delrange(s, n);
  243. for (i = cy; i < nlines - 1; i++) lptr[i] = lptr[i + 1];
  244. nlines--;
  245. adjust(cy, -(int) n);
  246. } else { /* last line: take its leading $0d */
  247. delrange(s - 1, blen - s + 1);
  248. nlines--;
  249. cy--;
  250. }
  251. cx = 0;
  252. redraw = 2;
  253. }
  254. static void paste(void)
  255. {
  256. int i;
  257. if (!yok) return;
  258. cx = linelen(cy);
  259. if (!newline()) return;
  260. for (i = 0; i < ylen; i++) inschar(ybuf[i]);
  261. cx = 0;
  262. }
  263. /* cursor keys, the same in both modes. 1 if k was one of them */
  264. static int arrow(int k)
  265. {
  266. if (k == K_DOWN) {
  267. if (cy + 1 < nlines) { cy++; clampx(); }
  268. return 1;
  269. }
  270. if (k == K_UP) {
  271. if (cy > 0) { cy--; clampx(); }
  272. return 1;
  273. }
  274. if (k == K_RIGHT) {
  275. cx++;
  276. clampx();
  277. return 1;
  278. }
  279. if (k == K_LEFT) {
  280. if (cx > 0) cx--;
  281. return 1;
  282. }
  283. return 0;
  284. }
  285. /* ------------------------------------------------------------------- view */
  286. static void scroll(void)
  287. {
  288. if (cy < top) top = cy;
  289. if (cy > top + rows - 1) top = cy - rows + 1;
  290. if (top < 0) top = 0;
  291. if (cx < leftcol) leftcol = cx;
  292. if (cx > leftcol + sw - 1) leftcol = cx - sw + 1;
  293. if (leftcol < 0) leftcol = 0;
  294. }
  295. static unsigned char rlen[50]; /* columns drawn on each row last time */
  296. /* the character shown at screen row r, column col (blank past the line) */
  297. static int cellch(int r, int col)
  298. {
  299. int line = top + r;
  300. unsigned p;
  301. int ch = ' ';
  302. if (line < nlines) {
  303. p = lptr[line] + leftcol + col;
  304. if (p < linend(line)) ch = bfr[p];
  305. }
  306. if (ch < 32 || (ch >= 128 && ch < 160)) ch = ' ';
  307. return ch;
  308. }
  309. /* repaint row r from column 'from' to the end of the text, plus whatever old
  310. text must be blanked. Only the cells that can have changed are written:
  311. each character costs a real VDC/VIC access. */
  312. static void drawrow(int r, int from)
  313. {
  314. int line = top + r, vl = 0, col, end;
  315. if (line < nlines) {
  316. vl = linelen(line) - leftcol;
  317. if (vl < 0) vl = 0;
  318. if (vl > sw) vl = sw;
  319. }
  320. end = vl > rlen[r] ? vl : rlen[r];
  321. if (from < end) {
  322. gotoxy(from, r);
  323. for (col = from; col < end; col++) cputc(cellch(r, col));
  324. }
  325. rlen[r] = vl;
  326. }
  327. static void drawcell(int r, int col, int rev)
  328. {
  329. if (r < 0 || r >= rows || col < 0 || col >= sw) return;
  330. if (rev) revers(1);
  331. cputcxy(col, r, cellch(r, col));
  332. if (rev) revers(0);
  333. }
  334. static char *dnum(char *t, int v)
  335. {
  336. char d[6];
  337. int n = 0;
  338. if (v == 0) {
  339. *t++ = '0';
  340. return t;
  341. }
  342. while (v > 0 && n < 5) {
  343. d[n++] = '0' + (v % 10);
  344. v /= 10;
  345. }
  346. while (n > 0) *t++ = d[--n];
  347. return t;
  348. }
  349. static void dstat(void)
  350. {
  351. char t[84];
  352. const char *s;
  353. char *p;
  354. int i, n, pos;
  355. if (note) s = note;
  356. else if (mode) s = "-- insert --";
  357. else if (fname[0] == 0) s = "[no name]";
  358. else s = fname;
  359. n = 0;
  360. for (i = 0; s[i] && i < sw - 14; i++) t[n++] = s[i];
  361. pos = sw - 14; /* modified flag */
  362. while (n < pos) t[n++] = ' ';
  363. t[n++] = dirty ? '+' : ' ';
  364. t[n++] = ' ';
  365. p = dnum(t + n, cy + 1);
  366. *p++ = '/';
  367. p = dnum(p, nlines);
  368. while (p < t + sw - 1) *p++ = ' ';
  369. *p = 0;
  370. if (strcmp(t, lstat) == 0) return; /* unchanged: skip the writes */
  371. strcpy(lstat, t);
  372. revers(1);
  373. putstr(sh - 1, 0, t);
  374. revers(0);
  375. }
  376. static void dall(void)
  377. {
  378. int crow = cy - top;
  379. int ccol = cx - leftcol;
  380. int r, from;
  381. if (redraw == 2 || top != ltop || leftcol != lleft) {
  382. for (r = 0; r < rows; r++) drawrow(r, 0);
  383. } else {
  384. /* put the old cursor cell back to normal, then repaint what the edit
  385. touched: the cursor row from the old cursor column on */
  386. drawcell(lcy - top, lcx - lleft, 0);
  387. from = lcx - lleft;
  388. if (ccol < from) from = ccol;
  389. if (from < 0) from = 0;
  390. if (redraw == 1) drawrow(crow, from);
  391. }
  392. drawcell(crow, ccol, 1);
  393. if (crow >= 0 && crow < rows && ccol >= rlen[crow] && ccol < sw)
  394. rlen[crow] = ccol + 1; /* a cursor past the text must be blanked later */
  395. ltop = top;
  396. lleft = leftcol;
  397. lcy = cy;
  398. lcx = cx;
  399. redraw = 0;
  400. dstat();
  401. }
  402. /* ------------------------------------------------------------ prompt/disk */
  403. /* read a line of PETSCII into s, echoed from column c of the status row */
  404. static int getln(int c, char *s, int max)
  405. {
  406. int n = 0, k;
  407. s[0] = 0;
  408. for (;;) {
  409. k = skey();
  410. if (k == K_RET) break;
  411. if (k == K_STOP || k == K_ESC) {
  412. n = 0;
  413. s[0] = 0;
  414. break;
  415. }
  416. if (k == K_DEL) {
  417. if (n > 0) s[--n] = 0;
  418. } else {
  419. if (k >= 0xc1 && k <= 0xda) k -= 0x80;
  420. if (k >= 32 && k < 127 && n < max) {
  421. s[n++] = k;
  422. s[n] = 0;
  423. }
  424. }
  425. clrstat(c);
  426. putstr(sh - 1, c, s);
  427. }
  428. return n;
  429. }
  430. static int askyn(const char *q)
  431. {
  432. int k;
  433. clrstat(0);
  434. putstr(sh - 1, 0, q);
  435. for (;;) {
  436. k = skey();
  437. if (k == KL('y') || k == KU('Y')) return 1;
  438. if (k == KL('n') || k == KU('N') || k == K_STOP || k == K_ESC) return 0;
  439. }
  440. }
  441. static void askname(void)
  442. {
  443. clrstat(0);
  444. putstr(sh - 1, 0, "file: ");
  445. getln(6, fname, NAMEMAX);
  446. }
  447. /* the drive's error channel (open as file 15): the two digit code of the last
  448. command. 0-19 are fine, 62 is file not found. open of a missing file
  449. succeeds on a CBM drive - only this channel tells. */
  450. static int dosst(void)
  451. {
  452. unsigned char ch;
  453. int n = 0, d = 0;
  454. for (;;) {
  455. if (cbm_read(15, &ch, 1) != 1) break;
  456. if (ch == 13) break;
  457. if (d < 2 && ch >= '0' && ch <= '9') {
  458. n = n * 10 + ch - '0';
  459. d++;
  460. }
  461. }
  462. if (d < 2) return 99;
  463. return n;
  464. }
  465. /* build "name,s,r" (or "@0:name,s,w") in PETSCII */
  466. static void mkname(char *on, int save)
  467. {
  468. int i = 0, j = 0;
  469. if (save) {
  470. on[i++] = '@';
  471. on[i++] = '0';
  472. on[i++] = ':';
  473. }
  474. while (fname[j] && j < NAMEMAX) on[i++] = fname[j++];
  475. on[i++] = ',';
  476. on[i++] = 0x53; /* PETSCII S, not ASCII */
  477. on[i++] = ',';
  478. on[i++] = save ? 0x57 : 0x52; /* W or R */
  479. on[i] = 0;
  480. }
  481. /* read fname into bfr. 1 on success, 0 if the file is not there.
  482. lines longer than 80 are split - the editor's line limit */
  483. static int loadf2(void);
  484. static int loadf(void)
  485. {
  486. int r;
  487. slow();
  488. r = loadf2();
  489. if (sw > 40) fast();
  490. return r;
  491. }
  492. static int loadf2(void)
  493. {
  494. unsigned char tmp[64];
  495. char on[32];
  496. int n, i, ch, c, prev = 0, col = 0;
  497. if (fname[0] == 0) return 1;
  498. mkname(on, 0);
  499. if (cbm_open(15, dev, 15, "") != 0) return 0;
  500. if (cbm_open(5, dev, 2, on) != 0) {
  501. cbm_close(15);
  502. return 0;
  503. }
  504. if (dosst() >= 20) {
  505. cbm_close(5);
  506. cbm_close(15);
  507. return 0;
  508. }
  509. blen = 0;
  510. split = 0;
  511. for (;;) {
  512. n = cbm_read(5, tmp, sizeof tmp);
  513. if (n <= 0) break;
  514. for (i = 0; i < n; i++) {
  515. ch = tmp[i];
  516. if (ch == 26) goto done;
  517. if (ch == 10 && prev == 13) { /* CRLF seen as two bytes */
  518. prev = ch;
  519. continue;
  520. }
  521. c = (ch == 10) ? 13 : ch;
  522. if (c != 13 && col >= MAXCOL) {
  523. if (blen < BUFMAX - 1) bfr[blen++] = 13;
  524. col = 0;
  525. split = 1;
  526. }
  527. if (blen < BUFMAX - 1) bfr[blen++] = c;
  528. col = (c == 13) ? 0 : col + 1;
  529. prev = ch;
  530. }
  531. }
  532. done:
  533. cbm_close(5);
  534. cbm_close(15); /* last: it closes everything */
  535. return 1;
  536. }
  537. /* write the buffer to fname, replacing any old copy. 1 on success */
  538. static int savef2(void);
  539. static int savef(void)
  540. {
  541. int r;
  542. slow();
  543. r = savef2();
  544. if (sw > 40) fast();
  545. return r;
  546. }
  547. static int savef2(void)
  548. {
  549. char on[32];
  550. unsigned char cr = 13;
  551. int ok;
  552. mkname(on, 1);
  553. if (cbm_open(15, dev, 15, "") != 0) return 0;
  554. if (cbm_open(5, dev, 3, on) != 0) {
  555. cbm_close(15);
  556. return 0;
  557. }
  558. if (blen > 0) cbm_write(5, bfr, blen);
  559. if (blen > 0 && bfr[blen - 1] != 13) cbm_write(5, &cr, 1);
  560. ok = (dosst() < 20);
  561. cbm_close(5);
  562. cbm_close(15);
  563. return ok;
  564. }
  565. /* the ":" command line. returns 1 when the editor should quit */
  566. static int doscmd(void)
  567. {
  568. char cmd[24];
  569. int n, p = 1, ok = 0, qf = 0;
  570. clrstat(0);
  571. putstr(sh - 1, 0, ":");
  572. n = getln(1, cmd, 20);
  573. clrstat(0);
  574. if (n == 0) return 0;
  575. if (cmd[0] == KL('q')) {
  576. if (cmd[1] == '!') return 1;
  577. if (dirty) {
  578. note = "unsaved - :q! quits";
  579. return 0;
  580. }
  581. return 1;
  582. }
  583. if (cmd[0] == KL('w')) ok = 1;
  584. if (cmd[0] == KL('x')) {
  585. ok = 1;
  586. qf = 1;
  587. }
  588. if (!ok) {
  589. note = "unknown command";
  590. return 0;
  591. }
  592. if (cmd[0] == KL('w') && cmd[1] == KL('q')) {
  593. qf = 1;
  594. p = 2;
  595. }
  596. while (cmd[p] == ' ') p++;
  597. if (cmd[p]) {
  598. n = 0;
  599. while (cmd[p] && n < NAMEMAX) fname[n++] = cmd[p++];
  600. fname[n] = 0;
  601. }
  602. if (fname[0] == 0) {
  603. note = "no file name";
  604. return 0;
  605. }
  606. if (savef()) {
  607. dirty = 0;
  608. note = "written";
  609. return qf;
  610. }
  611. note = "cannot write";
  612. return 0;
  613. }
  614. /* ------------------------------------------------------------------- main */
  615. int main(void)
  616. {
  617. int k, ok, p;
  618. dev = *(unsigned char *) 0x00ba; /* device we were loaded from */
  619. if (dev < 8) dev = 8;
  620. sinit();
  621. blen = 0;
  622. nlines = 1;
  623. lptr[0] = 0;
  624. cy = cx = top = leftcol = 0;
  625. fname[0] = 0;
  626. mode = dirty = pend = ylen = yok = split = 0;
  627. note = 0;
  628. redraw = 2;
  629. ltop = lleft = lcy = 0;
  630. for (;;) { /* a file to edit */
  631. askname();
  632. if (fname[0] == 0) { /* no name: an empty buffer */
  633. ok = 1;
  634. break;
  635. }
  636. ok = loadf();
  637. if (ok) break;
  638. if (askyn("not found - create it? (y/n) ")) break;
  639. }
  640. buildidx();
  641. if (!ok) { /* keep the name: :w creates it */
  642. nlines = 1;
  643. blen = 0;
  644. note = "new file";
  645. }
  646. if (split) note = "long lines split at 80";
  647. clrscr();
  648. memset(rlen, 0, sizeof rlen);
  649. lstat[0] = 0;
  650. for (;;) {
  651. scroll();
  652. dall();
  653. k = skey();
  654. note = 0;
  655. if (mode) { /* ---- insert mode */
  656. if (k == K_STOP || k == K_ESC) {
  657. mode = 0;
  658. if (cx > 0) cx--;
  659. } else if (k == K_RET) {
  660. newline();
  661. } else if (k == K_DEL) {
  662. bkspace();
  663. } else if (arrow(k)) {
  664. ;
  665. } else if ((k >= 32 && k < 128) || k >= 161) {
  666. inschar(k);
  667. }
  668. continue;
  669. }
  670. if (pend) { /* ---- second key of dd / gg */
  671. p = pend;
  672. pend = 0;
  673. if (p == KL('d') && k == KL('d')) delline();
  674. if (p == KL('g') && k == KL('g')) {
  675. cy = 0;
  676. cx = 0;
  677. }
  678. clampx();
  679. continue;
  680. }
  681. if (arrow(k)) {
  682. ;
  683. } else if (k == KL('h')) {
  684. if (cx > 0) cx--;
  685. } else if (k == KL('l')) {
  686. cx++;
  687. clampx();
  688. } else if (k == KL('j')) {
  689. arrow(K_DOWN);
  690. } else if (k == KL('k')) {
  691. arrow(K_UP);
  692. } else if (k == '0') {
  693. cx = 0;
  694. } else if (k == '$') {
  695. cx = linelen(cy);
  696. } else if (k == KU('G')) {
  697. cy = nlines - 1;
  698. cx = 0;
  699. } else if (k == KL('d')) {
  700. pend = KL('d');
  701. } else if (k == KL('g')) {
  702. pend = KL('g');
  703. } else if (k == KL('x')) {
  704. delchar();
  705. clampx();
  706. } else if (k == KL('p')) {
  707. paste();
  708. } else if (k == KL('i')) {
  709. mode = 1;
  710. } else if (k == KL('a')) {
  711. cx++;
  712. clampx();
  713. mode = 1;
  714. } else if (k == KU('A')) {
  715. cx = linelen(cy);
  716. mode = 1;
  717. } else if (k == KU('I')) {
  718. cx = 0;
  719. mode = 1;
  720. } else if (k == KL('o')) {
  721. cx = linelen(cy);
  722. newline();
  723. mode = 1;
  724. } else if (k == KU('O')) {
  725. cx = 0;
  726. newline();
  727. cy--;
  728. mode = 1;
  729. } else if (k == ':') {
  730. if (doscmd() == 1) {
  731. sdone();
  732. return 0;
  733. }
  734. }
  735. }
  736. }

Powered by TurnKey Linux.