main.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <draw.h>
  4. #include <event.h>
  5. #include <bio.h>
  6. #include <keyboard.h>
  7. #include "cons.h"
  8. enum{
  9. Ehost = 4,
  10. };
  11. char *menutext2[] = {
  12. "backup",
  13. "forward",
  14. "reset",
  15. "clear",
  16. "send",
  17. "page",
  18. 0
  19. };
  20. char *menutext3[] = {
  21. "24x80",
  22. "crnl",
  23. "nl",
  24. "raw",
  25. "exit",
  26. 0
  27. };
  28. /* variables associated with the screen */
  29. int x, y; /* character positions */
  30. char *backp;
  31. int backc;
  32. int atend;
  33. int nbacklines;
  34. int xmax, ymax;
  35. int blocked;
  36. int resize_flag;
  37. int pagemode;
  38. int olines;
  39. int peekc;
  40. int cursoron = 1;
  41. Menu menu2;
  42. Menu menu3;
  43. char *histp;
  44. char hist[HISTSIZ];
  45. int yscrmin, yscrmax;
  46. int attr, defattr;
  47. int wctlout;
  48. Image *bordercol;
  49. Image *cursback;
  50. Image *colors[8];
  51. Image *hicolors[8];
  52. Image *red;
  53. Image *fgcolor;
  54. Image *bgcolor;
  55. Image *fgdefault;
  56. Image *bgdefault;
  57. uint rgbacolors[8] = {
  58. 0x000000FF, /* black */
  59. 0xAA0000FF, /* red */
  60. 0x00AA00FF, /* green */
  61. 0xFF5500FF, /* brown */
  62. 0x0000FFFF, /* blue */
  63. 0xAA00AAFF, /* purple */
  64. 0x00AAAAFF, /* cyan */
  65. 0x7F7F7FFF, /* white */
  66. };
  67. ulong rgbahicolors[8] = {
  68. 0x555555FF, /* light black aka grey */
  69. 0xFF5555FF, /* light red */
  70. 0x55FF55FF, /* light green */
  71. 0xFFFF55FF, /* light brown aka yellow */
  72. 0x5555FFFF, /* light blue */
  73. 0xFF55FFFF, /* light purple */
  74. 0x55FFFFFF, /* light cyan */
  75. 0xFFFFFFFF, /* light grey aka white */
  76. };
  77. /* terminal control */
  78. struct ttystate ttystate[2] = { {0, 1}, {0, 1} };
  79. int NS;
  80. int CW;
  81. Consstate *cs;
  82. Mouse mouse;
  83. int debug;
  84. int nocolor;
  85. int logfd = -1;
  86. int outfd = -1;
  87. Biobuf *snarffp = 0;
  88. char *host_buf;
  89. char *hostp; /* input from host */
  90. int host_bsize = 2*BSIZE;
  91. int hostlength; /* amount of input from host */
  92. char echo_input[BSIZE];
  93. char *echop = echo_input; /* characters to echo, after canon */
  94. char sendbuf[BSIZE]; /* hope you can't type ahead more than BSIZE chars */
  95. char *sendp = sendbuf;
  96. char *term;
  97. struct funckey *fk;
  98. /* functions */
  99. void initialize(int, char **);
  100. void ebegin(int);
  101. int waitchar(void);
  102. int rcvchar(void);
  103. void set_input(char *);
  104. void set_host(Event *);
  105. void bigscroll(void);
  106. void readmenu(void);
  107. void eresized(int);
  108. void resize(void);
  109. void send_interrupt(void);
  110. int alnum(int);
  111. void escapedump(int,uchar *,int);
  112. void
  113. main(int argc, char **argv)
  114. {
  115. initialize(argc, argv);
  116. emulate();
  117. }
  118. void
  119. usage(void)
  120. {
  121. fprint(2, "usage: %s [-2abcx] [-f font] [-l logfile]\n", argv0);
  122. exits("usage");
  123. }
  124. void
  125. initialize(int argc, char **argv)
  126. {
  127. int i, blkbg;
  128. char *fontname, *p;
  129. rfork(RFNAMEG|RFNOTEG);
  130. fontname = nil;
  131. term = "vt100";
  132. fk = vt100fk;
  133. blkbg = nocolor = 0;
  134. ARGBEGIN{
  135. case '2':
  136. term = "vt220";
  137. fk = vt220fk;
  138. break;
  139. case 'a':
  140. term = "ansi";
  141. fk = ansifk;
  142. break;
  143. case 'b':
  144. blkbg = 1; /* e.g., for linux colored output */
  145. break;
  146. case 'c':
  147. nocolor = 1;
  148. break;
  149. case 'f':
  150. fontname = EARGF(usage());
  151. break;
  152. case 'l':
  153. p = EARGF(usage());
  154. logfd = create(p, OWRITE, 0666);
  155. if(logfd < 0)
  156. sysfatal("could not create log file: %s: %r", p);
  157. break;
  158. case 'x':
  159. fk = xtermfk;
  160. term = "xterm";
  161. break;
  162. default:
  163. usage();
  164. break;
  165. }ARGEND;
  166. host_buf = malloc(host_bsize);
  167. hostp = host_buf;
  168. hostlength = 0;
  169. if(initdraw(0, fontname, term) < 0){
  170. fprint(2, "%s: initdraw failed: %r\n", term);
  171. exits("initdraw");
  172. }
  173. werrstr(""); /* clear spurious error messages */
  174. ebegin(Ehost);
  175. histp = hist;
  176. menu2.item = menutext2;
  177. menu3.item = menutext3;
  178. pagemode = 0;
  179. blocked = 0;
  180. NS = font->height;
  181. CW = stringwidth(font, "m");
  182. red = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DRed);
  183. bordercol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xCCCCCCCC);
  184. cursback = allocimage(display, Rect(0, 0, CW+1, NS+1), screen->chan, 0, DNofill);
  185. for(i=0; i<8; i++){
  186. colors[i] = allocimage(display, Rect(0,0,1,1), screen->chan, 1,
  187. rgbacolors[i]);
  188. hicolors[i] = allocimage(display, Rect(0,0,1,1), screen->chan, 1,
  189. rgbahicolors[i]);
  190. }
  191. bgdefault = (blkbg? display->black: display->white);
  192. fgdefault = (blkbg? display->white: display->black);
  193. bgcolor = bgdefault;
  194. fgcolor = fgdefault;
  195. resize();
  196. if(argc > 0) {
  197. sendnchars(strlen(argv[0]),argv[0]);
  198. sendnchars(1,"\n");
  199. }
  200. }
  201. void
  202. clear(Rectangle r)
  203. {
  204. draw(screen, r, bgcolor, nil, ZP);
  205. }
  206. void
  207. newline(void)
  208. {
  209. nbacklines--;
  210. if(y >= yscrmax) {
  211. y = yscrmax;
  212. if(pagemode && olines >= yscrmax) {
  213. blocked = 1;
  214. return;
  215. }
  216. scroll(yscrmin+1, yscrmax+1, yscrmin, yscrmax);
  217. } else
  218. y++;
  219. olines++;
  220. }
  221. void
  222. cursoff(void)
  223. {
  224. draw(screen, Rpt(pt(x, y), addpt(pt(x, y), Pt(CW,NS))),
  225. cursback, nil, cursback->r.min);
  226. }
  227. void
  228. curson(int bl)
  229. {
  230. Image *col;
  231. if(!cursoron){
  232. cursoff();
  233. return;
  234. }
  235. draw(cursback, cursback->r, screen, nil, pt(x, y));
  236. if(bl)
  237. col = red;
  238. else
  239. col = bordercol;
  240. border(screen, Rpt(pt(x, y), addpt(pt(x, y), Pt(CW,NS))), 2, col, ZP);
  241. }
  242. int
  243. get_next_char(void)
  244. {
  245. int c = peekc;
  246. uchar buf[1];
  247. peekc = 0;
  248. if(c > 0)
  249. return(c);
  250. while(c <= 0) {
  251. if(backp) {
  252. c = *backp;
  253. if(c && nbacklines >= 0) {
  254. backp++;
  255. if(backp >= &hist[HISTSIZ])
  256. backp = hist;
  257. return(c);
  258. }
  259. backp = 0;
  260. }
  261. c = (uchar)waitchar();
  262. if(c > 0 && logfd >= 0) {
  263. buf[0] = c;
  264. write(logfd, buf, 1);
  265. }
  266. }
  267. *histp++ = c;
  268. if(histp >= &hist[HISTSIZ])
  269. histp = hist;
  270. *histp = '\0';
  271. return(c);
  272. }
  273. int
  274. canon(char *ep, int c)
  275. {
  276. if(c&0200)
  277. return(SCROLL);
  278. switch(c) {
  279. case '\b':
  280. if(sendp > sendbuf)
  281. sendp--;
  282. *ep++ = '\b';
  283. *ep++ = ' ';
  284. *ep++ = '\b';
  285. break;
  286. case 0x15: /* ^U line kill */
  287. sendp = sendbuf;
  288. *ep++ = '^';
  289. *ep++ = 'U';
  290. *ep++ = '\n';
  291. break;
  292. case 0x17: /* ^W word kill */
  293. while(sendp > sendbuf && !alnum(*sendp)) {
  294. *ep++ = '\b';
  295. *ep++ = ' ';
  296. *ep++ = '\b';
  297. sendp--;
  298. }
  299. while(sendp > sendbuf && alnum(*sendp)) {
  300. *ep++ = '\b';
  301. *ep++ = ' ';
  302. *ep++ = '\b';
  303. sendp--;
  304. }
  305. break;
  306. case '\177': /* interrupt */
  307. sendp = sendbuf;
  308. send_interrupt();
  309. return(NEWLINE);
  310. case '\021': /* quit */
  311. case '\r':
  312. case '\n':
  313. if(sendp < &sendbuf[512])
  314. *sendp++ = '\n';
  315. sendnchars((int)(sendp-sendbuf), sendbuf);
  316. sendp = sendbuf;
  317. if(c == '\n' || c == '\r') {
  318. *ep++ = '\n';
  319. }
  320. *ep = 0;
  321. return(NEWLINE);
  322. case '\004': /* EOT */
  323. if(sendp == sendbuf) {
  324. sendnchars(0,sendbuf);
  325. *ep = 0;
  326. return(NEWLINE);
  327. }
  328. /* fall through */
  329. default:
  330. if(sendp < &sendbuf[512])
  331. *sendp++ = c;
  332. *ep++ = c;
  333. break;
  334. }
  335. *ep = 0;
  336. return(OTHER);
  337. }
  338. void
  339. sendfk(char *name)
  340. {
  341. int i;
  342. static int fd;
  343. for(i=0; fk[i].name; i++)
  344. if(strcmp(name, fk[i].name)==0){
  345. sendnchars2(strlen(fk[i].sequence), fk[i].sequence);
  346. return;
  347. }
  348. }
  349. int
  350. waitchar(void)
  351. {
  352. Event e;
  353. int c;
  354. char c2;
  355. int newmouse;
  356. int wasblocked;
  357. int kbdchar = -1;
  358. char echobuf[3*BSIZE];
  359. static int lastc = -1;
  360. for(;;) {
  361. if(resize_flag)
  362. resize();
  363. wasblocked = blocked;
  364. if(backp)
  365. return(0);
  366. if(ecanmouse() && (button2() || button3()))
  367. readmenu();
  368. if(snarffp) {
  369. if((c = Bgetc(snarffp)) < 0) {
  370. if(lastc != '\n')
  371. write(outfd,"\n",1);
  372. Bterm(snarffp);
  373. snarffp = 0;
  374. if(lastc != '\n') {
  375. lastc = -1;
  376. return('\n');
  377. }
  378. lastc = -1;
  379. continue;
  380. }
  381. lastc = c;
  382. c2 = c;
  383. write(outfd, &c2, 1);
  384. return(c);
  385. }
  386. if(!blocked && host_avail())
  387. return(rcvchar());
  388. if(kbdchar > 0) {
  389. if(blocked)
  390. resize();
  391. if(cs->raw) {
  392. switch(kbdchar){
  393. case Kup:
  394. sendfk("up key");
  395. break;
  396. case Kdown:
  397. sendfk("down key");
  398. break;
  399. case Kleft:
  400. sendfk("left key");
  401. break;
  402. case Kright:
  403. sendfk("right key");
  404. break;
  405. case Kpgup:
  406. sendfk("page up");
  407. break;
  408. case Kpgdown:
  409. sendfk("page down");
  410. break;
  411. case KF|1:
  412. sendfk("F1");
  413. break;
  414. case KF|2:
  415. sendfk("F2");
  416. break;
  417. case KF|3:
  418. sendfk("F3");
  419. break;
  420. case KF|4:
  421. sendfk("F4");
  422. break;
  423. case KF|5:
  424. sendfk("F5");
  425. break;
  426. case KF|6:
  427. sendfk("F6");
  428. break;
  429. case KF|7:
  430. sendfk("F7");
  431. break;
  432. case KF|8:
  433. sendfk("F8");
  434. break;
  435. case KF|9:
  436. sendfk("F9");
  437. break;
  438. case KF|10:
  439. sendfk("F10");
  440. break;
  441. case KF|11:
  442. sendfk("F11");
  443. break;
  444. case KF|12:
  445. sendfk("F12");
  446. break;
  447. case '\n':
  448. echobuf[0] = '\r';
  449. sendnchars(1, echobuf);
  450. break;
  451. case '\r':
  452. echobuf[0] = '\n';
  453. sendnchars(1, echobuf);
  454. break;
  455. default:
  456. echobuf[0] = kbdchar;
  457. sendnchars(1, echobuf);
  458. break;
  459. }
  460. } else if(canon(echobuf,kbdchar) == SCROLL) {
  461. if(!blocked)
  462. bigscroll();
  463. } else
  464. strcat(echo_input,echobuf);
  465. blocked = 0;
  466. kbdchar = -1;
  467. continue;
  468. }
  469. curson(wasblocked); /* turn on cursor while we're waiting */
  470. do {
  471. newmouse = 0;
  472. switch(eread(blocked ? Emouse|Ekeyboard :
  473. Emouse|Ekeyboard|Ehost, &e)) {
  474. case Emouse:
  475. mouse = e.mouse;
  476. if(button2() || button3())
  477. readmenu();
  478. else if(resize_flag == 0) {
  479. /* eresized() is triggered by special mouse event */
  480. newmouse = 1;
  481. }
  482. break;
  483. case Ekeyboard:
  484. kbdchar = e.kbdc;
  485. break;
  486. case Ehost:
  487. set_host(&e);
  488. break;
  489. default:
  490. perror("protocol violation");
  491. exits("protocol violation");
  492. }
  493. } while(newmouse == 1);
  494. cursoff(); /* turn cursor back off */
  495. }
  496. }
  497. void
  498. eresized(int new)
  499. {
  500. resize_flag = 1+new;
  501. }
  502. void
  503. putenvint(char *name, int x)
  504. {
  505. char buf[20];
  506. snprint(buf, sizeof buf, "%d", x);
  507. putenv(name, buf);
  508. }
  509. void
  510. exportsize(void)
  511. {
  512. putenvint("XPIXELS", Dx(screen->r)-2*XMARGIN);
  513. putenvint("YPIXELS", Dy(screen->r)-2*XMARGIN);
  514. putenvint("LINES", ymax+1);
  515. putenvint("COLS", xmax+1);
  516. putenv("TERM", term);
  517. }
  518. void
  519. resize(void)
  520. {
  521. if(resize_flag > 1 && getwindow(display, Refnone) < 0){
  522. fprint(2, "can't reattach to window: %r\n");
  523. exits("can't reattach to window");
  524. }
  525. xmax = (Dx(screen->r)-2*XMARGIN)/CW-1;
  526. ymax = (Dy(screen->r)-2*YMARGIN)/NS-1;
  527. if(xmax == 0 || ymax == 0)
  528. exits("window gone");
  529. x = 0;
  530. y = 0;
  531. yscrmin = 0;
  532. yscrmax = ymax;
  533. olines = 0;
  534. exportsize();
  535. clear(screen->r);
  536. resize_flag = 0;
  537. werrstr(""); /* clear spurious error messages */
  538. }
  539. void
  540. setdim(int ht, int wid)
  541. {
  542. int fd;
  543. Rectangle r;
  544. if(ht != -1)
  545. ymax = ht-1;
  546. if(wid != -1)
  547. xmax = wid-1;
  548. r.min = screen->r.min;
  549. r.max = addpt(screen->r.min,
  550. Pt((xmax+1)*CW+2*XMARGIN+2*INSET,
  551. (ymax+1)*NS+2*YMARGIN+2*INSET));
  552. fd = open("/dev/wctl", OWRITE);
  553. if(fd < 0 || fprint(fd, "resize -dx %d -dy %d\n", Dx(r)+2*Borderwidth,
  554. Dy(r)+2*Borderwidth) < 0){
  555. border(screen, r, INSET, bordercol, ZP);
  556. exportsize();
  557. }
  558. if(fd >= 0)
  559. close(fd);
  560. }
  561. void
  562. readmenu(void)
  563. {
  564. if(button3()) {
  565. menu3.item[1] = ttystate[cs->raw].crnl ? "cr" : "crnl";
  566. menu3.item[2] = ttystate[cs->raw].nlcr ? "nl" : "nlcr";
  567. menu3.item[3] = cs->raw ? "cooked" : "raw";
  568. switch(emenuhit(3, &mouse, &menu3)) {
  569. case 0: /* 24x80 */
  570. setdim(24, 80);
  571. return;
  572. case 1: /* newline after cr? */
  573. ttystate[cs->raw].crnl = !ttystate[cs->raw].crnl;
  574. return;
  575. case 2: /* cr after newline? */
  576. ttystate[cs->raw].nlcr = !ttystate[cs->raw].nlcr;
  577. return;
  578. case 3: /* switch raw mode */
  579. cs->raw = !cs->raw;
  580. return;
  581. case 4:
  582. exits(0);
  583. }
  584. return;
  585. }
  586. menu2.item[5] = pagemode? "scroll": "page";
  587. switch(emenuhit(2, &mouse, &menu2)) {
  588. case 0: /* back up */
  589. if(atend == 0) {
  590. backc++;
  591. backup(backc);
  592. }
  593. return;
  594. case 1: /* move forward */
  595. backc--;
  596. if(backc >= 0)
  597. backup(backc);
  598. else
  599. backc = 0;
  600. return;
  601. case 2: /* reset */
  602. backc = 0;
  603. backup(0);
  604. return;
  605. case 3: /* clear screen */
  606. eresized(0);
  607. return;
  608. case 4: /* send the snarf buffer */
  609. snarffp = Bopen("/dev/snarf",OREAD);
  610. return;
  611. case 5: /* pause and clear at end of screen */
  612. pagemode = 1-pagemode;
  613. if(blocked && !pagemode) {
  614. eresized(0);
  615. blocked = 0;
  616. }
  617. return;
  618. }
  619. }
  620. void
  621. backup(int count)
  622. {
  623. register n;
  624. register char *cp;
  625. eresized(0);
  626. n = 3*(count+1)*ymax/4;
  627. cp = histp;
  628. atend = 0;
  629. while (n >= 0) {
  630. cp--;
  631. if(cp < hist)
  632. cp = &hist[HISTSIZ-1];
  633. if(*cp == '\0') {
  634. atend = 1;
  635. break;
  636. }
  637. if(*cp == '\n')
  638. n--;
  639. }
  640. cp++;
  641. if(cp >= &hist[HISTSIZ])
  642. cp = hist;
  643. backp = cp;
  644. nbacklines = ymax-2;
  645. }
  646. Point
  647. pt(int x, int y)
  648. {
  649. return addpt(screen->r.min, Pt(x*CW+XMARGIN,y*NS+YMARGIN));
  650. }
  651. void
  652. scroll(int sy, int ly, int dy, int cy) /* source, limit, dest, which line to clear */
  653. {
  654. draw(screen, Rpt(pt(0, dy), pt(xmax+1, dy+ly-sy)), screen, nil, pt(0, sy));
  655. clear(Rpt(pt(0, cy), pt(xmax+1, cy+1)));
  656. flushimage(display, 1);
  657. }
  658. void
  659. bigscroll(void) /* scroll up half a page */
  660. {
  661. int half = ymax/3;
  662. if(x == 0 && y == 0)
  663. return;
  664. if(y < half) {
  665. clear(Rpt(pt(0,0),pt(xmax+1,ymax+1)));
  666. x = y = 0;
  667. return;
  668. }
  669. draw(screen, Rpt(pt(0, 0), pt(xmax+1, ymax+1)), screen, nil, pt(0, half));
  670. clear(Rpt(pt(0,y-half+1),pt(xmax+1,ymax+1)));
  671. y -= half;
  672. if(olines)
  673. olines -= half;
  674. flushimage(display, 1);
  675. }
  676. int
  677. number(char *p, int *got)
  678. {
  679. int c, n = 0;
  680. if(got)
  681. *got = 0;
  682. while ((c = get_next_char()) >= '0' && c <= '9'){
  683. if(got)
  684. *got = 1;
  685. n = n*10 + c - '0';
  686. }
  687. *p = c;
  688. return(n);
  689. }
  690. /* stubs */
  691. void
  692. sendnchars(int n,char *p)
  693. {
  694. sendnchars2(n, p);
  695. p[n+1] = 0;
  696. }
  697. void
  698. sendnchars2(int n,char *p)
  699. {
  700. if(write(outfd,p,n) < 0) {
  701. close(outfd);
  702. close(0);
  703. close(1);
  704. close(2);
  705. exits("write");
  706. }
  707. }
  708. int
  709. host_avail(void)
  710. {
  711. return(*echop || ((hostp - host_buf) < hostlength));
  712. }
  713. int
  714. rcvchar(void)
  715. {
  716. int c;
  717. if(*echop) {
  718. c = *echop++;
  719. if(!*echop) {
  720. echop = echo_input;
  721. *echop = 0;
  722. }
  723. return c;
  724. }
  725. return *hostp++;
  726. }
  727. void
  728. set_host(Event *e)
  729. {
  730. hostlength = e->n;
  731. if(hostlength > host_bsize) {
  732. host_bsize *= 2;
  733. host_buf = realloc(host_buf,host_bsize);
  734. }
  735. hostp = host_buf;
  736. memmove(host_buf,e->data,hostlength);
  737. host_buf[hostlength]=0;
  738. }
  739. void
  740. ringbell(void){
  741. }
  742. int
  743. alnum(int c)
  744. {
  745. if(c >= 'a' && c <= 'z')
  746. return 1;
  747. if(c >= 'A' && c <= 'Z')
  748. return 1;
  749. if(c >= '0' && c <= '9')
  750. return 1;
  751. return 0;
  752. }
  753. void
  754. escapedump(int fd,uchar *str,int len)
  755. {
  756. int i;
  757. for(i = 0; i < len; i++) {
  758. if((str[i] < ' ' || str[i] > '\177') &&
  759. str[i] != '\n' && str[i] != '\t') fprint(fd,"^%c",str[i]+64);
  760. else if(str[i] == '\177') fprint(fd,"^$");
  761. else if(str[i] == '\n') fprint(fd,"^J\n");
  762. else fprint(fd,"%c",str[i]);
  763. }
  764. }
  765. void
  766. funckey(int key)
  767. {
  768. if(key >= NKEYS)
  769. return;
  770. if(fk[key].name == 0)
  771. return;
  772. sendnchars2(strlen(fk[key].sequence), fk[key].sequence);
  773. }
  774. void
  775. drawstring(Point p, char *str, int attr)
  776. {
  777. int i;
  778. Image *txt, *bg, *tmp;
  779. txt = fgcolor;
  780. bg = bgcolor;
  781. if(attr & TReverse){
  782. tmp = txt;
  783. txt = bg;
  784. bg = tmp;
  785. }
  786. if(attr & THighIntensity){
  787. for(i=0; i<8; i++)
  788. if(txt == colors[i])
  789. txt = hicolors[i];
  790. }
  791. draw(screen, Rpt(p, addpt(p, stringsize(font, str))), bg, nil, p);
  792. string(screen, p, txt, ZP, font, str);
  793. }