main.c 15 KB

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