home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2970 < prev    next >
Internet Message Format  |  1991-03-04  |  56KB

  1. From: guido@cwi.nl (Guido van Rossum)
  2. Newsgroups: alt.sources
  3. Subject: STDWIN 0.9.5, Part 09/19
  4. Message-ID: <3073@charon.cwi.nl>
  5. Date: 4 Mar 91 11:58:02 GMT
  6.  
  7. Archive-name: stdwin/part09
  8.  
  9. #! /bin/sh
  10. # This is a shell archive.  Remove anything before this line, then unpack
  11. # it by saving it into a file and typing "sh file".  To overwrite existing
  12. # files, type "sh file -c".  You can also feed this as standard input via
  13. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  14. # will see the following message at the end:
  15. #        "End of archive 9 (of 19)."
  16. # Contents:  Packs/vt/vtansi.c Ports/alfa/stdwin.c Ports/mac/draw.c
  17. #   Ports/x11/menu.c Ports/x11/timer.c
  18. # Wrapped by guido@voorn.cwi.nl on Mon Mar  4 12:37:27 1991
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'Packs/vt/vtansi.c' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'Packs/vt/vtansi.c'\"
  22. else
  23. echo shar: Extracting \"'Packs/vt/vtansi.c'\" \(11653 characters\)
  24. sed "s/^X//" >'Packs/vt/vtansi.c' <<'END_OF_FILE'
  25. X/* ANSI escape sequence interpreter */
  26. X
  27. X/* There is some ugly code here, since I assume that code looking
  28. X   at the input a character at a time is very time-critical.
  29. X   Action functions are called with the start of the text to process,
  30. X   and return a pointer to where they left off.
  31. X   When an action function hits the end of the string,
  32. X   it returns NULL and sets the action pointer to the function to
  33. X   call next (often itself), or to NULL for the default.
  34. X   A non-NULL return implies that the default action function must
  35. X   be called next and the action pointer is irrelevant.
  36. X   Remember that the general form of most ANSI escape sequences is
  37. X    ESC [ <n1> ; <n2> ; ... <c>
  38. X   where <c> is the command code and <n1>, <n2> etc. are optional
  39. X   numerical parameters.
  40. X*/
  41. X
  42. X#include "vtimpl.h"
  43. X
  44. X#ifdef DEBUG
  45. X /* Let it be heard that a command was not recognized */
  46. X#define FAIL() wfleep()
  47. X#else
  48. X/* Silently ignore unrecognized commands */
  49. X#define FAIL() 0
  50. X#endif
  51. X
  52. X/* Function prototypes */
  53. X
  54. XSTATIC char *def_action _ARGS((VT *vt, char *text, char *end));
  55. XSTATIC char *esc_action _ARGS((VT *vt, char *text, char *end));
  56. XSTATIC char *ansi_params _ARGS((VT *vt, char *text, char *end));
  57. XSTATIC char *ansi_execute _ARGS((VT *vt, char *text));
  58. XSTATIC void vtsetoptions _ARGS((VT *vt, bool flag));
  59. XSTATIC void vtsetattrlist _ARGS((VT *vt));
  60. X
  61. X/* Output a string, interpreting ANSI escapes */
  62. X
  63. Xvoid
  64. Xvtansiputs(vt, text, len)
  65. X    VT *vt;
  66. X    char *text;
  67. X    int len;
  68. X{
  69. X    char *end;
  70. X
  71. X#ifndef NDEBUG
  72. X    if (vt->scr_top < 0 || vt->scr_top > vt->rows) {
  73. X        fprintf(stderr, "vtansiputs: scr_top = %d\n", vt->scr_top);
  74. X        vtpanic("vtansiputs: bad scr_top");
  75. X    }
  76. X#endif
  77. X
  78. X    if (len < 0)
  79. X        len = strlen(text);
  80. X    end = text + len;
  81. X
  82. X    D( printf("vtansiputs %d chars\n", len) );
  83. X    
  84. X    /* Pick up where the last call left us behind  */
  85. X    if (vt->action != NULL)
  86. X        text = (*vt->action)(vt, text, end);
  87. X
  88. X    /* Start in default state until text exhausted */
  89. X    while (text != NULL)
  90. X        text = def_action(vt, text, end);
  91. X
  92. X    /* Execute delayed scrolling */
  93. X    vtsync(vt);
  94. X    D( printf("vtansiputs returns\n") );
  95. X}
  96. X
  97. X/* Default action function */
  98. X
  99. XSTATIC char *
  100. Xdef_action(vt, text, end)
  101. X    VT *vt;
  102. X    char *text, *end;
  103. X{
  104. Xagain:
  105. X    for (;;) {
  106. X        if (text >= end) {
  107. X            vt->action = NULL;
  108. X            return NULL;
  109. X        }
  110. X        if (PRINTABLE(*text))
  111. X            break;
  112. X        switch (*text++) {
  113. X
  114. X        case ESC:    /* ESC */
  115. X            return esc_action(vt, text, end);
  116. X        
  117. X        case BEL:    /* Bell */
  118. X            if (vt->visualbell) {
  119. X                VTBEGINDRAWING(vt);
  120. X                vtinvert(vt, 0, 0, vt->rows, vt->cols);
  121. X                VTENDDRAWING(vt);
  122. X                VTBEGINDRAWING(vt);
  123. X                vtinvert(vt, 0, 0, vt->rows, vt->cols);
  124. X                VTENDDRAWING(vt);
  125. X            }
  126. X            else {
  127. X                wfleep();
  128. X            }
  129. X            break;
  130. X        
  131. X        case BS:    /* Backspace -- move 1 left */
  132. X            /* Rely on vtsetcursor's clipping */
  133. X            vtsetcursor(vt, vt->cur_row, vt->cur_col - 1);
  134. X            /* Don't erase --
  135. X               that's part of intelligent echoing */
  136. X            break;
  137. X        
  138. X        case TAB:    /* Tab -- move to next tab stop */
  139. X            /* Rely on vtsetcursor's clipping */
  140. X            /* TO DO: use programmable tab stops! */
  141. X            vtsetcursor(vt, vt->cur_row,
  142. X                (vt->cur_col & ~7) + 8);
  143. X            /* Normalize cursor (may cause scroll!) */
  144. X            vtputstring(vt, "", 0);
  145. X            break;
  146. X        
  147. X        case LF:    /* Linefeed -- move down one line */
  148. X            if (vt->nlcr)    /* First a \r? */
  149. X                vtsetcursor(vt, vt->cur_row, 0);
  150. X            vtlinefeed(vt, 1);
  151. X            break;
  152. X        
  153. X        case FF:    /* Formfeed */
  154. X            /* vtreset(vt); */
  155. X            break;
  156. X        
  157. X        case CR:    /* Return -- to col 0 on same line */
  158. X            vtsetcursor(vt, vt->cur_row, 0);
  159. X            break;
  160. X        
  161. X        case ' ':    /* In case isprint(c) fails for space */
  162. X            vtputstring(vt, " ", 1);
  163. X            break;
  164. X
  165. X        default:
  166. X            D( printf("Unrecognized unprintable character 0x%x\n",
  167. X                                text[-1]) );
  168. X            FAIL();
  169. X            break;
  170. X        }
  171. X    }
  172. X
  173. X    /* We fall through the previous loop when we get a printable
  174. X       character */
  175. X    
  176. X    {
  177. X        char *p = text;
  178. X        
  179. X        while (PRINTABLE(*++p)) {
  180. X            /* At least one character guaranteed! */
  181. X            if (p >= end)
  182. X                break;
  183. X        }
  184. X        vtputstring(vt, text, (int)(p-text));
  185. X        text = p;
  186. X        goto again;
  187. X    }
  188. X}
  189. X
  190. X/* Action function called after ESC seen */
  191. X
  192. XSTATIC char *
  193. Xesc_action(vt, text, end)
  194. X    VT *vt;
  195. X    char *text, *end;
  196. X{
  197. X    if (text >= end) {
  198. X        vt->action = esc_action;
  199. X        return NULL;
  200. X    }
  201. X    switch (*text++) {
  202. X/*
  203. X    case '(':
  204. X    case ')':
  205. X    case '*':
  206. X    case '+':
  207. X        return cset_action(vt, text, end);
  208. X*/
  209. X    case '=':
  210. X        vt->keypadmode = TRUE;
  211. X        break;
  212. X    case '>':
  213. X        vt->keypadmode = FALSE;
  214. X        break;
  215. X    case '7':
  216. X        vtsavecursor(vt);
  217. X        break;
  218. X    case '8':
  219. X        vtrestorecursor(vt);
  220. X        break;
  221. X    case 'D':
  222. X        vtlinefeed(vt, 1);
  223. X        break;
  224. X    case 'E':
  225. X        /* Next Line */
  226. X        break;
  227. X    case 'H':
  228. X        /* Tab set */
  229. X        break;
  230. X    case 'M':
  231. X        vtrevlinefeed(vt, 1);
  232. X        break;
  233. X    case '[':
  234. X        vt->nextarg = vt->args;
  235. X        *vt->nextarg = -1;
  236. X        vt->modarg = '\0';
  237. X        return ansi_params(vt, text, end);
  238. X    case 'c':
  239. X        vtreset(vt);
  240. X        break;
  241. X    default:
  242. X        D( printf("Urecognized: esc-%c (0x%x)\n",
  243. X                text[-1], text[-1]) );
  244. X        FAIL();
  245. X        break;
  246. X    }
  247. X    return text;
  248. X}
  249. X
  250. X/* Action function called after ESC-[ plus possible parameters seen */
  251. X
  252. XSTATIC char *
  253. Xansi_params(vt, text, end)
  254. X    VT *vt;
  255. X    char *text, *end;
  256. X{
  257. Xagain:
  258. X    if (text >= end) {
  259. X        vt->action = ansi_params;
  260. X        return NULL;
  261. X    }
  262. X    if (isdigit(*text)) {
  263. X        long a = *vt->nextarg;
  264. X        if (a < 0) /* Still unused? */
  265. X            a = 0;
  266. X        do {
  267. X            a = a*10 + (*text - '0');
  268. X            CLIPMAX(a, 0x7fff); /* Avoid overflow */
  269. X        } while (++text < end && isdigit(*text));
  270. X        *vt->nextarg = a; /* Remember arg under construction */
  271. X        if (text >= end)
  272. X            goto again;
  273. X    }
  274. X    switch (*text) {
  275. X
  276. X    case ';': /* Arg no longer under construction */
  277. X        ++text;
  278. X        if (vt->nextarg < &vt->args[VTNARGS-1])
  279. X            ++vt->nextarg; /* Else: overflow; who cares? */
  280. X        *vt->nextarg = -1; /* Mark unused */
  281. X        goto again;
  282. X
  283. X    case '?':
  284. X        ++text;
  285. X        if (vt->nextarg == vt->args && /* No arguments yet */
  286. X            *vt->nextarg < 0 && vt->modarg == '\0') {
  287. X            vt->modarg = '?';
  288. X            goto again;
  289. X        }
  290. X        else { /* Illegal here */
  291. X            D( printf("Wrong argcount in DEC private mode\n") );
  292. X            FAIL();
  293. X            return text;
  294. X        }
  295. X
  296. X    default:
  297. X        return ansi_execute(vt, text);
  298. X    }
  299. X}
  300. X
  301. X/* Called after complete ESC [ ? <number> h is parsed.
  302. X   This is called DEC private mode set. Most stuff is not
  303. X   implemented. The vt is guarantueed to contain the one
  304. X   and only argument allowed here. */
  305. X
  306. XSTATIC void
  307. Xvtprivset(vt)
  308. X    VT *vt;
  309. X{
  310. X    switch (vt->args[0]) {
  311. X    case 1:    /* Application cursor keys */
  312. X        if (!vt->keypadmode) {
  313. X            vt->keypadmode = 1;
  314. X            vt->flagschanged = 1;
  315. X        }
  316. X        break;
  317. X#if 0
  318. X    case 3: /* 132 column mode */
  319. X    case 4: /* Smooth (slow) scroll */
  320. X#endif
  321. X    case 5: /* Reverse video */
  322. X        wfleep();
  323. X        break;
  324. X#if 0
  325. X    case 6: /* Origin mode */
  326. X    case 7: /* Wraparound mode */
  327. X    case 8: /* Autorepeat keys */
  328. X#endif
  329. X    case 9: /* Send MIT mouse row & column on Button Press */
  330. X        if (!vt->mitmouse) { /* If not already so */
  331. X            vt->mitmouse = 1;
  332. X            vt->flagschanged = 1;
  333. X        }
  334. X        break;
  335. X#if 0
  336. X    case 38: /* Enter Tektronix Mode */
  337. X    case 40: /* Allow 80 <-> 132 mode */
  338. X    case 41: /* Curses(5) fix */
  339. X    case 44: /* Turn on margin bell */
  340. X    case 45: /* Reverse wraparound mode */
  341. X    case 46: /* Start logging */
  342. X    case 47: /* Use alternate screen buffer */
  343. X    case 1000: /* Send vt200 mouse row & column on Button Press */
  344. X    case 1003: /* Send vt200 Hilite mouse row & column on Button Press */
  345. X#endif
  346. X    default:
  347. X        D( printf("Unsupported DEC private mode set:") );
  348. X        D( printf("esc [ ? %d h\n", vt->args[0]) );
  349. X        wfleep();
  350. X    }
  351. X}
  352. X
  353. X/* Called after complete ESC [ ? <number> l is parsed.
  354. X   This is called DEC private mode reset. The vt is guarantueed
  355. X   to contain the one and only argument allowed here. */
  356. X
  357. XSTATIC void
  358. Xvtprivreset(vt)
  359. X    VT *vt;
  360. X{
  361. X    switch (vt->args[0]) {
  362. X    case 1: /* Normal cursor keys */
  363. X        if (vt->keypadmode) {
  364. X            vt->keypadmode = 0;
  365. X            vt->flagschanged = 1;
  366. X        }
  367. X        break;
  368. X#if 0    /* These are not supprted: */
  369. X    case 3: /* 80 column mode */
  370. X    case 4: /* Jumpscroll */
  371. X#endif
  372. X    case 5: /* Normal video (i.e. not reverse) */
  373. X        /* XXX Why this beep? */
  374. X        wfleep();
  375. X        break;
  376. X#if 0
  377. X    case 6: /* Normal cursor mode */
  378. X    case 7: /* No wraparound */
  379. X    case 8: /* No autorepeat */
  380. X        break;
  381. X#endif
  382. X    case 9: /* Don't send mouse row & column on button press */
  383. X    case 1000:    /* Same */
  384. X    case 1003:    /* Same */
  385. X        if (vt->mitmouse) { /* If not already so */
  386. X            vt->mitmouse = 0;
  387. X            vt->flagschanged = 1;
  388. X        }
  389. X        break;
  390. X#if 0
  391. X    case 40: /* Disallow 80 <-> 132 mode */
  392. X    case 41: /* No curses(5) fix */
  393. X    case 44: /* Turn off Margin bell */
  394. X    case 45: /* No reverse wraparound */
  395. X    case 46: /* Stop logging */
  396. X    case 47: /* Use normal screen buffer (opposed to alternate buffer) */
  397. X        break;
  398. X#endif
  399. X    default:
  400. X        D( printf("Unsupported DEC private mode reset:") );
  401. X        D( printf("esc [ ? %d l\n", vt->args[0]) );
  402. X        wfleep();
  403. X        break;
  404. X    }
  405. X}
  406. X
  407. X/* Action function called at last char of ANSI sequence.
  408. X   (This is only called when the char is actually seen,
  409. X   so there is no need for an 'end' parameter). */
  410. X
  411. XSTATIC char *
  412. Xansi_execute(vt, text)
  413. X    VT *vt;
  414. X    char *text;
  415. X{
  416. X    int a1 = vt->args[0];
  417. X    int a2 = (vt->nextarg > vt->args) ? vt->args[1] : -1;
  418. X
  419. X    if (vt->modarg == '?') {
  420. X        /* These escape sequences have exactly one numeric parameter */
  421. X        if (a1 < 0 || a2 > 0) {
  422. X            wfleep();
  423. X            return text+1;
  424. X        }
  425. X        switch (*text++) {
  426. X        case 'h':    /* DEC Private mode Set */
  427. X            vtprivset(vt);
  428. X            break;
  429. X        case 'l':    /* DEC Private mode Reset */
  430. X            vtprivreset(vt);
  431. X            break;
  432. X        /* To do: add private mode memory to vt-descriptor? */
  433. X        case 'r':    /* DEC Private mode Restore */
  434. X        case 's':    /* DEC Private mode Save */
  435. X        default:
  436. X            /* Not supported or simply wrong */
  437. X            wfleep();
  438. X        }
  439. X        return text;
  440. X    }
  441. X
  442. X    CLIPMIN(a1, 1);
  443. X    CLIPMIN(a2, 1);
  444. X
  445. X    switch (*text++) {
  446. X    case '@': vtinschars(vt, a1);        break;
  447. X    case 'A': vtarrow(vt, WC_UP, a1);    break;
  448. X    case 'B': vtarrow(vt, WC_DOWN, a1);    break;
  449. X    case 'C': vtarrow(vt, WC_RIGHT, a1);    break;
  450. X    case 'D': vtarrow(vt, WC_LEFT, a1);    break;
  451. X    case 'H':
  452. X    case 'f': if (vt->nextarg > &vt->args[0])
  453. X            vtsetcursor(vt, vt->topterm + a1 - 1, a2 - 1);
  454. X          else vtsetcursor(vt, vt->topterm, 0);
  455. X          break;
  456. X    case 'J':
  457. X        switch (vt->args[0]) {
  458. X        case -1:
  459. X        case 0:
  460. X            vteosclear(vt, vt->topterm, 0);
  461. X            break;
  462. X        case 1:
  463. X            /* clear above cursor */
  464. X            break;
  465. X        case 2:
  466. X            vteosclear(vt, vt->cur_row, vt->cur_col);
  467. X            break;
  468. X        default:
  469. X            FAIL();
  470. X            break;
  471. X        }
  472. X        break;
  473. X    case 'K':
  474. X        switch (vt->args[0]) {
  475. X        case -1:
  476. X        case 0:
  477. X            vteolclear(vt, vt->cur_row, vt->cur_col);
  478. X            break;
  479. X        case 1:
  480. X            /* Clear left of cursor */
  481. X            break;
  482. X        case 2:
  483. X            vteolclear(vt, vt->cur_row, 0);
  484. X            break;
  485. X        default:
  486. X            FAIL();
  487. X            break;
  488. X        }
  489. X        break;
  490. X    case 'L': vtinslines(vt, a1);        break;
  491. X    case 'M': vtdellines(vt, a1);        break;
  492. X    case 'P': vtdelchars(vt, a1);        break;
  493. X    case 'S': vtlinefeed(vt, a1);        break;
  494. X    case 'T': vtrevlinefeed(vt, a1);    break;
  495. X    case 'c': vtsendid(vt); break;
  496. X    case 'g': /* Tab clear */        break;
  497. X        /* 0: current col; 3: all */
  498. X    case 'h': vtsetoptions(vt, TRUE);    break;
  499. X    case 'l': vtsetoptions(vt, FALSE);    break;
  500. X    case 'm': vtsetattrlist(vt);        break;
  501. X    case 'n':
  502. X        if (a1 == 6) vtsendpos(vt);
  503. X        /* 5: echo 'ESC [ 0 n' */
  504. X        break;
  505. X    case 'r':
  506. X        vtsetscroll(vt, vt->topterm+vt->args[0]-1, vt->topterm+a2);
  507. X        break;
  508. X    case 'x': /* Send terminal params */
  509. X        break;
  510. X    default:
  511. X        FAIL();
  512. X        break;
  513. X    }
  514. X
  515. X    return text;
  516. X}
  517. X
  518. X/* Set/reset numbered options given in args array */
  519. X
  520. XSTATIC void
  521. Xvtsetoptions(vt, flag)
  522. X    VT *vt;
  523. X    bool flag; /* Set/reset */
  524. X{
  525. X    short *a;
  526. X    for (a = vt->args; a <= vt->nextarg; ++a) {
  527. X        switch (*a) {
  528. X        case 4:
  529. X            vtsetinsert(vt, flag);
  530. X            break;
  531. X        case -1:
  532. X            /* Empty parameter, don't beep */
  533. X            break;
  534. X        default:
  535. X            FAIL();
  536. X            break;
  537. X        }
  538. X    }
  539. X}
  540. X
  541. X/* Set/reset output mode attributes given in args array */
  542. X
  543. XSTATIC void
  544. Xvtsetattrlist(vt)
  545. X    VT *vt;
  546. X{
  547. X    short *a;
  548. X    for (a = vt->args; a <= vt->nextarg; ++a) {
  549. X        switch (*a) {
  550. X        case -1:
  551. X            if (a == vt->args)
  552. X                vtresetattr(vt);
  553. X            break;
  554. X        case 0:
  555. X            vtresetattr(vt);
  556. X            break;
  557. X        default:
  558. X            vtsetattr(vt, *a);
  559. X            break;
  560. X        }
  561. X    }
  562. X}
  563. END_OF_FILE
  564. if test 11653 -ne `wc -c <'Packs/vt/vtansi.c'`; then
  565.     echo shar: \"'Packs/vt/vtansi.c'\" unpacked with wrong size!
  566. fi
  567. # end of 'Packs/vt/vtansi.c'
  568. fi
  569. if test -f 'Ports/alfa/stdwin.c' -a "${1}" != "-c" ; then 
  570.   echo shar: Will not clobber existing file \"'Ports/alfa/stdwin.c'\"
  571. else
  572. echo shar: Extracting \"'Ports/alfa/stdwin.c'\" \(9984 characters\)
  573. sed "s/^X//" >'Ports/alfa/stdwin.c' <<'END_OF_FILE'
  574. X/* TERMCAP STDWIN -- BASIC ROUTINES. */
  575. X
  576. X#include "alfa.h"
  577. X
  578. X#if defined(unix) || defined(AMOEBA)
  579. X#define DO_SIGNAL
  580. X#define DO_SYSTEM
  581. X#endif
  582. X
  583. X#ifdef DO_SIGNAL
  584. X#include <sys/types.h>
  585. X#include <signal.h>
  586. X#include "sigtype.h"
  587. Xstatic SIGTYPE handler(); /* Forward */
  588. X#endif
  589. X
  590. Xint lines, columns;
  591. X
  592. X/* Initialization call.
  593. X   Should be called only once, before any others.
  594. X   Will exit when the initialization fails. */
  595. X
  596. Xvoid
  597. Xwinit()
  598. X{
  599. X    winitargs((int*)NULL, (char***)NULL);
  600. X}
  601. X
  602. X/*ARGSUSED*/
  603. Xvoid
  604. Xwinitargs(pargc, pargv)
  605. X    int *pargc;
  606. X    char ***pargv;
  607. X{
  608. X    int flags;
  609. X    int err;
  610. X    
  611. X#ifdef DO_SIGNAL
  612. X    (void) signal(SIGINT, handler);
  613. X#ifdef NDEBUG
  614. X    (void) signal(SIGQUIT, handler);
  615. X#endif
  616. X    (void) signal(SIGILL, handler);
  617. X    (void) signal(SIGIOT, handler);
  618. X    (void) signal(SIGEMT, handler);
  619. X    (void) signal(SIGFPE, handler);
  620. X    (void) signal(SIGBUS, handler);
  621. X    (void) signal(SIGSEGV, handler);
  622. X    (void) signal(SIGSYS, handler);
  623. X    (void) signal(SIGTERM, handler);
  624. X#endif /* DO_SIGNAL */
  625. X    
  626. X    getttykeydefs(0);    /* File descriptor 0 */
  627. X    err= trmstart(&lines, &columns, &flags);
  628. X    if (err != 0) {
  629. X        fprintf(stderr, "STDWIN: trmstart error %d\n", err);
  630. X        exit(2);
  631. X    }
  632. X    gettckeydefs();
  633. X    if (lines > MAXLINES)
  634. X        lines= MAXLINES;
  635. X    trmputdata(0, lines-1, 0, "");
  636. X    initsyswin();
  637. X    _winitmenus();
  638. X}
  639. X
  640. X/* Termination call.
  641. X   Should be called before the program exits
  642. X   (else the terminal will be left in almost raw mode). */
  643. X
  644. Xvoid
  645. Xwdone()
  646. X{
  647. X    if (lines > 0) {
  648. X        /* Move cursor to last screen line. */
  649. X        trmputdata(lines-1, lines-1, 0, "");
  650. X        trmsync(lines-1, 0);
  651. X    }
  652. X    lines= 0;
  653. X    trmend();
  654. X}
  655. X
  656. X#ifdef DO_SIGNAL
  657. X
  658. X/* Signal handler.
  659. X   Print a message and exit. */
  660. X
  661. Xstatic SIGTYPE
  662. Xhandler(sig)
  663. X    int sig;
  664. X{
  665. X    wdone();
  666. X    signal(sig, SIG_DFL);
  667. X    kill(0, sig);        /* Kill all others in our process group */
  668. X    kill(getpid(), sig);    /* Commit suicide */
  669. X    /* (On BSD, the signal is delivered to us only after we return.) */
  670. X}
  671. X
  672. X#endif /* DO_SIGNAL */
  673. X
  674. X/* Essential data structures. */
  675. X
  676. XWINDOW winlist[MAXWINDOWS] /* = {FALSE, ...}, ... */;
  677. X
  678. XWINDOW *wasfront;    /* What the application thinks is active */
  679. XWINDOW *front;        /* The window that is really active */
  680. X    /* If these are not equal, an activate or deactivate event
  681. X       will be generated by wevent before anything else. */
  682. X
  683. Xchar uptodate[MAXLINES] /* = FALSE, ... */;
  684. X
  685. X/* Open a window. */
  686. X
  687. XWINDOW *
  688. Xwopen(title, drawproc)
  689. X    char *title;
  690. X    void (*drawproc)();
  691. X{
  692. X    int id;
  693. X    WINDOW *win;
  694. X    
  695. X    for (win= &winlist[0]; win < &winlist[MAXWINDOWS]; ++win) {
  696. X        if (!win->open)
  697. X            break;
  698. X    }
  699. X    id= win - &winlist[0];
  700. X    if (id >= MAXWINDOWS)
  701. X        return NULL;    /* Too many windows open */
  702. X    win->open= TRUE;
  703. X    _wreshuffle();
  704. X    win->resized = FALSE;    /* Don't begin with a redraw event */
  705. X    win->tag= 0;
  706. X    win->drawproc= drawproc;
  707. X    win->title= strdup(title);
  708. X    win->attr= wattr;
  709. X    
  710. X    win->offset= -win->top;
  711. X    win->curh= win->curv= -1;
  712. X    win->timer= 0;
  713. X    
  714. X    initmenubar(&win->mbar);
  715. X    
  716. X    front= win;
  717. X    return win;
  718. X}
  719. X
  720. X/* Divide the available lines over the available windows.
  721. X   Line 0 is for window 0, the system window, and is different:
  722. X   it has no title, and is always one line high, except when it's
  723. X   the only window. */
  724. X
  725. Xvoid
  726. X_wreshuffle()
  727. X{
  728. X    int nwins= 0;
  729. X    int nlines= lines;
  730. X    int top= 0;
  731. X    WINDOW *win;
  732. X    
  733. X    /* Count open windows. */
  734. X    for (win= winlist; win < &winlist[MAXWINDOWS]; ++win) {
  735. X        if (win->open)
  736. X            ++nwins;
  737. X    }
  738. X    /* Assign each open window its share of the screen. */
  739. X    for (win= winlist; win < &winlist[MAXWINDOWS]; ++win) {
  740. X        if (win->open) {
  741. X            int i= nlines/nwins;    /* This window's share */
  742. X            int id= win - winlist;
  743. X#ifdef LM_S_PROB
  744. X            int oldtop= win->top, oldbot= win->bottom;
  745. X            int dv, scrbot;
  746. X#endif
  747. X            /* Cause redraw event for old title position: */
  748. X            if (win->top > 0)
  749. X                uptodate[win->top-1]= FALSE;
  750. X            if (id == 0) {    /* System window */
  751. X                win->top= top;
  752. X                if (nwins > 1)
  753. X                    i=1;
  754. X            }
  755. X            else
  756. X                win->top= top+1;
  757. X            win->bottom= top + i;
  758. X            nlines -= i;
  759. X            --nwins;
  760. X#ifndef LM_S_PROB
  761. X            /* This is overkill;
  762. X               we should try not cause a redraw of all lines! */
  763. X            for (i= top; i < win->bottom; ++i) {
  764. X                uptodate[i]= FALSE;
  765. X            }
  766. X#else
  767. X            /* LM's probeersel */
  768. X            dv= oldtop-win->top;
  769. X            scrbot=win->bottom;
  770. X            if (oldbot-dv < scrbot) scrbot=oldbot-dv;
  771. X            scrollupdate(win->top, scrbot, dv);
  772. X            trmscrollup(win->top, scrbot-1, dv);
  773. X            for (i= top; i < win->bottom; ++i)
  774. X                if (!(win->top <= i && i < scrbot ||
  775. X                      win->top <= i+dv && i+dv < scrbot))
  776. X                uptodate[i]= FALSE;
  777. X#endif
  778. X            top= win->bottom;
  779. X            /* Cause redraw event for new title position: */
  780. X            if (win->top > 0)
  781. X                uptodate[win->top-1]= FALSE;
  782. X            /* Cause resize event: */
  783. X            win->resized= TRUE;
  784. X            /* Scroll back if negative line numbers visible: */
  785. X            if (win->top + win->offset < 0)
  786. X                wshow(win, 0, 0,
  787. X                    columns, win->bottom - win->top);
  788. X#if 0 /* We don't really want to for showing the caret... */
  789. X            /* Show caret: */
  790. X            if (win->curv >= 0)
  791. X                wshow(win, win->curh, win->curv,
  792. X                    win->curh, win->curv);
  793. X#endif
  794. X        }
  795. X    }
  796. X}
  797. X
  798. X/* Close a window. */
  799. X
  800. Xvoid
  801. Xwclose(win)
  802. X    WINDOW *win;
  803. X{
  804. X    int id= win - winlist;
  805. X    
  806. X    if (id < 0 || id >= MAXWINDOWS || !win->open)
  807. X        return;
  808. X    killmenubar(&win->mbar);
  809. X    if (win == wasfront)
  810. X        wasfront= NULL;
  811. X    if (win == front)
  812. X        front= NULL;
  813. X    win->open= FALSE;
  814. X    if (win->title != NULL) {
  815. X        free(win->title);
  816. X        win->title= NULL;
  817. X    }
  818. X    _wreshuffle();
  819. X    /* Select another window. */
  820. X    if (front == NULL) {
  821. X        /* Search below the window we just closed. */
  822. X        for (; win < &winlist[MAXWINDOWS]; ++win) {
  823. X            if (win->open) {
  824. X                front= win;
  825. X                break; /* First hit is OK */
  826. X            }
  827. X        }
  828. X        if (front == NULL) {
  829. X            /* Try searching above it. */
  830. X            for (win= winlist+1; win < &winlist[MAXWINDOWS];
  831. X                                ++win) {
  832. X                if (win->open)
  833. X                    front= win;
  834. X                /* NO break -- we need the last hit */
  835. X            }
  836. X        }
  837. X        if (front == NULL) {
  838. X            /* Exasperation time. */
  839. X            front= &winlist[0]; /* The system window */
  840. X        }
  841. X        _wnewtitle(front); /* Make sure the title is redrawn */
  842. X    }
  843. X}
  844. X
  845. X/* Dummies for functions not supported by this version. */
  846. X
  847. X/*ARGSUSED*/
  848. Xvoid
  849. Xwsetdefwinpos(h, v)
  850. X    int h, v;
  851. X{
  852. X}
  853. X
  854. X/*ARGSUSED*/
  855. Xvoid
  856. Xwsetdefwinsize(width, height)
  857. X    int width, height;
  858. X{
  859. X}
  860. X
  861. X/*ARGSUSED*/
  862. Xvoid
  863. Xwsetmaxwinsize(width, height)
  864. X    int width, height;
  865. X{
  866. X}
  867. X
  868. X/* Make a window the active window. */
  869. X
  870. Xvoid
  871. Xwsetactive(win)
  872. X    WINDOW *win;
  873. X{
  874. X    int id= win - winlist;
  875. X    
  876. X    if (id < 0 || id >= MAXWINDOWS || !win->open)
  877. X        return;
  878. X    _wnewtitle(front);
  879. X    front= win;
  880. X    _wnewtitle(front);
  881. X}
  882. X
  883. X/* Select next, previous window.
  884. X   Note: these will never select the system window unless it is already
  885. X   selected (which can only occur if there are no other windows open). */
  886. X
  887. Xvoid
  888. X_wselnext()
  889. X{
  890. X    WINDOW *win;
  891. X    
  892. X    for (win= front+1; win < &winlist[MAXWINDOWS]; ++win) {
  893. X        if (win->open) {
  894. X            wsetactive(win);
  895. X            return;
  896. X        }
  897. X    }
  898. X    for (win= winlist+1; win < front; ++win) {
  899. X        if (win->open) {
  900. X            wsetactive(win);
  901. X            return;
  902. X        }
  903. X    }
  904. X}
  905. X
  906. Xvoid
  907. X_wselprev()
  908. X{
  909. X    WINDOW *win;
  910. X    
  911. X    for (win= front-1; win > winlist; --win) {
  912. X        if (win->open) {
  913. X            wsetactive(win);
  914. X            return;
  915. X        }
  916. X    }
  917. X    for (win= &winlist[MAXWINDOWS-1]; win > front; --win) {
  918. X        if (win->open) {
  919. X            wsetactive(win);
  920. X            return;
  921. X        }
  922. X    }
  923. X}
  924. X
  925. X/* Force a redraw of the entire screen.
  926. X   (This routine only sets 'invalid' bits for all lines;
  927. X   the actual redraw is done later in wgetevent or wupdate.) */
  928. X
  929. Xvoid
  930. X_wredraw()
  931. X{
  932. X    int i;
  933. X    
  934. X    for (i= 0; i < lines; ++i)
  935. X        uptodate[i]= FALSE;
  936. X    _wreshuffle();
  937. X    trmundefined();
  938. X    trmputdata(0, lines-1, 0, "");
  939. X}
  940. X
  941. X/* Temporarily restore cooked tty mode. */
  942. X
  943. X_wcooked()
  944. X{
  945. X    trmputdata(lines-1, lines-1, 0, "");
  946. X    trmsync(lines-1, 0);
  947. X    trmend();
  948. X}
  949. X
  950. X/* Back to window mode.
  951. X   If 'wait' flag is set, wait until a character is typed before
  952. X   continuing. clearing the screen. */
  953. X
  954. X_wstdwin(wait)
  955. X    bool wait;
  956. X{
  957. X    int flags;
  958. X    
  959. X    if (wait) {
  960. X        printf("\nCR to continue... ");
  961. X        fflush(stdout);
  962. X    }
  963. X    (void) trmstart(&lines, &columns, &flags);
  964. X    if (wait)
  965. X        (void) trminput();
  966. X    _wredraw();
  967. X    wmessage((char *)NULL); /* Reset menu bar */
  968. X}
  969. X
  970. X/* Suspend the process (BSD Unix only). */
  971. X
  972. Xvoid
  973. X_wsuspend()
  974. X{
  975. X    _wcooked();
  976. X    trmsuspend();
  977. X    _wstdwin(FALSE);
  978. X}
  979. X
  980. X/* Execute a shell command, if possible and necessary outside the window
  981. X   manager.  If the 'wait' parameter is set, the window manager pauses
  982. X   until a character is typed before continuing. */
  983. X
  984. Xint
  985. Xwsystem(cmd, wait)
  986. X    char *cmd;
  987. X    bool wait;
  988. X{
  989. X#ifdef DO_SYSTEM
  990. X    int status;
  991. X    _wcooked();
  992. X    status= system(cmd);
  993. X    _wstdwin(wait);
  994. X    return status;
  995. X#else
  996. X    return -1;
  997. X#endif
  998. X}
  999. X
  1000. X/* Return active window. */
  1001. X
  1002. XWINDOW *
  1003. Xwgetactive()
  1004. X{
  1005. X    return front;
  1006. X}
  1007. X
  1008. X/* Change a window's title. */
  1009. X
  1010. Xvoid
  1011. Xwsettitle(win, title)
  1012. X    WINDOW *win;
  1013. X    char *title;
  1014. X{
  1015. X    if (win->title != NULL)
  1016. X        free(win->title);
  1017. X    win->title= strdup(title);
  1018. X    _wnewtitle(win);
  1019. X}
  1020. X
  1021. X/* Change the mouse cursor -- dummy */
  1022. X
  1023. X/*ARGSUSED*/
  1024. Xvoid
  1025. Xwsetwincursor(win, cursor)
  1026. X    WINDOW *win;
  1027. X    CURSOR *cursor;
  1028. X{
  1029. X}
  1030. X
  1031. X/* Fetch a mouse cursor -- always return NULL */
  1032. X
  1033. X/*ARGSUSED*/
  1034. XCURSOR *
  1035. Xwfetchcursor(name)
  1036. X    char *name;
  1037. X{
  1038. X    return NULL;
  1039. X}
  1040. X
  1041. X/* Set a window's extent (document size). Not implemented here. */
  1042. X
  1043. X/*ARGSUSED*/
  1044. Xvoid
  1045. Xwsetdocsize(win, width, height)
  1046. X    WINDOW *win;
  1047. X    int width, height;
  1048. X{
  1049. X}
  1050. X
  1051. X/*ARGSUSED*/
  1052. Xvoid
  1053. Xwgetdocsize(win, pwidth, pheight)
  1054. X    WINDOW *win;
  1055. X    int *pwidth, *pheight;
  1056. X{
  1057. X    *pwidth = *pheight = 0;
  1058. X}
  1059. X
  1060. X/* Get a window's origin with respect to document. */
  1061. X
  1062. Xvoid
  1063. Xwgetorigin(win, ph, pv)
  1064. X    WINDOW *win;
  1065. X    int *ph, *pv;
  1066. X{
  1067. X    *ph= 0;
  1068. X    *pv= win->top + win->offset;
  1069. X}
  1070. X
  1071. X/* Get a window's origin with respect to screen. */
  1072. X
  1073. Xvoid
  1074. Xwgetwinpos(win, ph, pv)
  1075. X    WINDOW *win;
  1076. X    int *ph, *pv;
  1077. X{
  1078. X    *ph= 0;
  1079. X    *pv= win->top;
  1080. X}
  1081. X
  1082. X/* Get a window's window size. */
  1083. X
  1084. Xvoid
  1085. Xwgetwinsize(win, pwidth, pheight)
  1086. X    WINDOW *win;
  1087. X    int *pwidth, *pheight;
  1088. X{
  1089. X    *pwidth= columns;
  1090. X    *pheight= win->bottom - win->top;
  1091. X}
  1092. X
  1093. X/* Get the screen size in pixels. */
  1094. X
  1095. Xvoid
  1096. Xwgetscrsize(ph, pv)
  1097. X    int *ph, *pv;
  1098. X{
  1099. X    *ph= columns;
  1100. X    *pv= lines;
  1101. X}
  1102. X
  1103. X/* Get the screen size in mm.
  1104. X   Of course we don't know it; we pretend that the average character
  1105. X   is 3 mm wide and 6 mm high, which is a reasonable approximation
  1106. X   of reality on my terminal (an HP2621). */
  1107. X
  1108. Xvoid
  1109. Xwgetscrmm(ph, pv)
  1110. X    int *ph, *pv;
  1111. X{
  1112. X    *ph= columns * 3;
  1113. X    *pv= lines * 6;
  1114. X}
  1115. X
  1116. Xvoid
  1117. Xwfleep()
  1118. X{
  1119. X    trmbell();
  1120. X}
  1121. END_OF_FILE
  1122. if test 9984 -ne `wc -c <'Ports/alfa/stdwin.c'`; then
  1123.     echo shar: \"'Ports/alfa/stdwin.c'\" unpacked with wrong size!
  1124. fi
  1125. # end of 'Ports/alfa/stdwin.c'
  1126. fi
  1127. if test -f 'Ports/mac/draw.c' -a "${1}" != "-c" ; then 
  1128.   echo shar: Will not clobber existing file \"'Ports/mac/draw.c'\"
  1129. else
  1130. echo shar: Extracting \"'Ports/mac/draw.c'\" \(10989 characters\)
  1131. sed "s/^X//" >'Ports/mac/draw.c' <<'END_OF_FILE'
  1132. X/* MAC STDWIN -- DOCUMENT DRAWING. */
  1133. X
  1134. X/* Contents of this file:
  1135. X   
  1136. X   wchange, wscroll;
  1137. X   wbegindrawing, wenddrawing, _wupdate, wupdate;
  1138. X   text attribute manipulation (internal and external);
  1139. X   text measuring;
  1140. X   text drawing;
  1141. X   coordinate conversion tools;
  1142. X   ordinary drawing.
  1143. X   
  1144. X   XXX Should be split, only things used between w{begin,end}drawing
  1145. X   belong here.
  1146. X
  1147. X   BEWARE OF COORDINATE SYSTEMS!
  1148. X   
  1149. X   The window's origin is not always the same.
  1150. X   When the aplication isn't drawing (i.e., outside w{begin,end}drawing),
  1151. X   the origin is (0, 0); this is necessary because the control mgr
  1152. X   doesn't like it otherwise.
  1153. X   When the application is drawing, the origin is set to win->(orgh, orgv)
  1154. X   so the drawing primitives don't need to do their own coordinate
  1155. X   transformation.
  1156. X   Routines called while not drawing must do their own transformations.
  1157. X   
  1158. X   XXX Routines that may be called any time are in trouble!
  1159. X   (There shouldn't be any.)
  1160. X*/
  1161. X
  1162. X#include "macwin.h"
  1163. X#ifdef MPW
  1164. X#include <Fonts.h>
  1165. X#endif
  1166. X
  1167. Xstatic WINDOW *drawing;
  1168. Xstatic TEXTATTR drawsaveattr;
  1169. Xstatic int baseline;
  1170. Xstatic int lineheight;
  1171. X
  1172. X/* Function prototypes */
  1173. X
  1174. XSTATIC void getwattr _ARGS((GrafPtr port, TEXTATTR *attr));
  1175. XSTATIC void setwattr _ARGS((TEXTATTR *attr));
  1176. XSTATIC void getfinfo _ARGS((void));
  1177. X
  1178. Xvoid
  1179. Xwchange(win, left, top, right, bottom)
  1180. X    WINDOW *win;
  1181. X    int left, top, right, bottom;
  1182. X{
  1183. X    Rect r;
  1184. X    
  1185. X    SetPort(win->w);
  1186. X    
  1187. X    if (drawing) dprintf("warning: wchange called while drawing");
  1188. X    makerect(win, &r, left, top, right, bottom);
  1189. X    InvalRect(&r);
  1190. X}
  1191. X
  1192. Xvoid
  1193. Xwscroll(win, left, top, right, bottom, dh, dv)
  1194. X    WINDOW *win;
  1195. X    int left, top, right, bottom;
  1196. X    int dh, dv;
  1197. X{
  1198. X    Rect r;
  1199. X    
  1200. X    if (drawing) dprintf("warning: wchange called while drawing");
  1201. X    makerect(win, &r, left, top, right, bottom);
  1202. X    scrollby(win, &r, dh, dv);
  1203. X}
  1204. X
  1205. X/* Scroll a rectangle (given in window coordinates) by dh, dv.
  1206. X   Also used from scroll.c. */
  1207. X/* XXX need less visible name */
  1208. X
  1209. Xvoid
  1210. Xscrollby(win, pr, dh, dv)
  1211. X    WINDOW *win;
  1212. X    Rect *pr;
  1213. X    int dh, dv;
  1214. X{
  1215. X    RgnHandle rgn= NewRgn();
  1216. X    
  1217. X    SetPort(win->w);
  1218. X    
  1219. X    rmcaret(win);
  1220. X    
  1221. X    if (!EmptyRgn(( (WindowPeek)win->w )->updateRgn)) {
  1222. X        RgnHandle ur= NewRgn();
  1223. X        int left, top;
  1224. X        Rect r;
  1225. X        
  1226. X        /* Scroll the part of the update region that intersects
  1227. X           the scrolling area. */
  1228. X        CopyRgn(( (WindowPeek)win->w )->updateRgn, ur);
  1229. X        /* portBits.bounds is the screen in local coordinates! */
  1230. X        left= win->w->portBits.bounds.left;
  1231. X        top= win->w->portBits.bounds.top;
  1232. X        OffsetRgn(ur, left, top); /* Global to Local */
  1233. X        RectRgn(rgn, pr);
  1234. X        SectRgn(rgn, ur, ur);
  1235. X        if (!EmptyRgn(ur)) {
  1236. X            ValidRgn(ur);
  1237. X            OffsetRgn(ur, dh, dv);
  1238. X            SectRgn(rgn, ur, ur);
  1239. X            InvalRgn(ur);
  1240. X        }
  1241. X        DisposeRgn(ur);
  1242. X    }
  1243. X    
  1244. X    ScrollRect(pr, dh, dv, rgn);
  1245. X    InvalRgn(rgn);
  1246. X    
  1247. X    DisposeRgn(rgn);
  1248. X}
  1249. X
  1250. X
  1251. X/* Internal version of wupdate -- also used from event.c */
  1252. X
  1253. Xvoid
  1254. X_wupdate(win, pr)
  1255. X    WINDOW *win;
  1256. X    Rect *pr;
  1257. X{
  1258. X    RgnHandle rgn= NewRgn();
  1259. X    
  1260. X    SetPort(win->w);
  1261. X    
  1262. X    rmcaret(win);
  1263. X    BeginUpdate(win->w);
  1264. X    EraseRect(&win->w->portRect);
  1265. X    DrawGrowIcon(win->w);
  1266. X    DrawControls(win->w);
  1267. X    getwinrect(win, pr);
  1268. X    RectRgn(rgn, pr);
  1269. X    SectRgn(rgn, win->w->visRgn, rgn);
  1270. X    *pr= (*rgn)->rgnBBox;
  1271. X    OffsetRect(pr, win->orgh, win->orgv);
  1272. X    if (win->drawproc != NULL && !EmptyRect(pr)) {
  1273. X        wbegindrawing(win);
  1274. X        (*win->drawproc)(win, pr->left, pr->top, pr->right, pr->bottom);
  1275. X        wenddrawing(win);
  1276. X    }
  1277. X    EndUpdate(win->w);
  1278. X    DisposeRgn(rgn);
  1279. X}
  1280. X
  1281. X/* Process an update event -- call the window's draw procedure. */
  1282. X/* XXX This function shouldn't be in the stdwin spec (why was it ever?) */
  1283. X
  1284. Xvoid
  1285. Xwupdate(win)
  1286. X    WINDOW *win;
  1287. X{
  1288. X    if (win->drawproc != NULL) {
  1289. X        Rect r;
  1290. X        _wupdate(win, &r);
  1291. X    }
  1292. X}
  1293. X
  1294. Xvoid
  1295. Xwbegindrawing(win)
  1296. X    WINDOW *win;
  1297. X{
  1298. X    Rect r;
  1299. X    
  1300. X    if (drawing != NULL) {
  1301. X        dprintf("warning: recursive call to wbegindrawing");
  1302. X        /* Fix it */
  1303. X        wenddrawing(drawing);
  1304. X    }
  1305. X    if (win == NULL) {
  1306. X        dprintf("warning: wbegindrawing(NULL) ignored");
  1307. X        return;
  1308. X    }
  1309. X    drawing= win;
  1310. X    SetPort(win->w);
  1311. X    SetOrigin(win->orgh, win->orgv);
  1312. X    rmcaret(win);
  1313. X    getwinrect(win, &r);
  1314. X    ClipRect(&r);
  1315. X    PenNormal();
  1316. X    wgettextattr(&drawsaveattr);
  1317. X    wsettextattr(&win->attr);
  1318. X}
  1319. X
  1320. Xvoid
  1321. Xwenddrawing(win)
  1322. X    WINDOW *win;
  1323. X{
  1324. X    Rect r;
  1325. X    
  1326. X    if (drawing == NULL) {
  1327. X        dprintf("warning: wenddrawing ignored while not drawing");
  1328. X        return;
  1329. X    }
  1330. X    if (drawing != win) {
  1331. X        dprintf("warning: wenddrawing ignored for wrong window");
  1332. X        return;
  1333. X    }
  1334. X    SetOrigin(0, 0);
  1335. X    SetRect(&r, -32000, -32000, 32000, 32000);
  1336. X    ClipRect(&r);
  1337. X    wsettextattr(&drawsaveattr);
  1338. X    drawing= NULL;
  1339. X}
  1340. X
  1341. X/* Get the current text attributes of a GrafPort. */
  1342. X
  1343. Xstatic void
  1344. Xgetwattr(port, attr)
  1345. X    GrafPtr port;
  1346. X    TEXTATTR *attr;
  1347. X{
  1348. X    SetPort(port); /* XXX Is this necessary to validate txFont etc.? */
  1349. X    
  1350. X    attr->font= port->txFont;
  1351. X    attr->style= port->txFace;
  1352. X    attr->size= port->txSize;
  1353. X}
  1354. X
  1355. X/* Start using the given text attributes in the current grafport. */
  1356. X
  1357. Xstatic void
  1358. Xsetwattr(attr)
  1359. X    TEXTATTR *attr;
  1360. X{
  1361. X    TextFont(attr->font);
  1362. X    TextFace(attr->style & ~TX_INVERSE);
  1363. X    TextSize(attr->size);
  1364. X}
  1365. X
  1366. X/* Get font info and baseline from current GrafPort */
  1367. X
  1368. Xstatic void
  1369. Xgetfinfo()
  1370. X{
  1371. X    FontInfo finfo;
  1372. X    GetFontInfo(&finfo);
  1373. X    baseline= finfo.ascent + finfo.leading;
  1374. X    lineheight= baseline + finfo.descent;
  1375. X}
  1376. X
  1377. X/* Initialize 'wattr'.  Uses the screen's grafport. */
  1378. X
  1379. Xint _w_font= applFont;
  1380. Xint _w_size= 9;
  1381. X
  1382. Xvoid
  1383. Xinitwattr()
  1384. X{
  1385. X    TEXTATTR saveattr;
  1386. X    
  1387. X    SetPort(screen);
  1388. X    
  1389. X    getwattr(screen, &saveattr);
  1390. X    TextFont(_w_font);
  1391. X    TextSize(_w_size);
  1392. X    getwattr(screen, &wattr);
  1393. X    getfinfo();
  1394. X    setwattr(&saveattr);
  1395. X}
  1396. X
  1397. X/* TEXT ATTRIBUTES. */
  1398. X
  1399. Xvoid
  1400. Xwgettextattr(attr)
  1401. X    TEXTATTR *attr;
  1402. X{
  1403. X    *attr= wattr;
  1404. X}
  1405. X
  1406. Xvoid
  1407. Xwsettextattr(attr)
  1408. X    TEXTATTR *attr;
  1409. X{
  1410. X    wattr= *attr;
  1411. X    if (drawing != NULL) {
  1412. X        setwattr(attr);
  1413. X        getfinfo();
  1414. X    }
  1415. X}
  1416. X
  1417. Xvoid
  1418. Xwgetwintextattr(win, attr)
  1419. X    WINDOW *win;
  1420. X    TEXTATTR *attr;
  1421. X{
  1422. X    *attr= win->attr;
  1423. X}
  1424. X
  1425. Xvoid
  1426. Xwsetwintextattr(win, attr)
  1427. X    WINDOW *win;
  1428. X    TEXTATTR *attr;
  1429. X{
  1430. X    win->attr= *attr;
  1431. X    if (drawing != NULL)
  1432. X        dprintf("warning: wsetwintextattr called while drawing");
  1433. X}
  1434. X
  1435. Xvoid
  1436. Xwsetfont(fontname)
  1437. X    char *fontname;
  1438. X{
  1439. X    if (fontname == NULL || *fontname == EOS)
  1440. X        wattr.font= _w_font;
  1441. X    else {
  1442. X        short fnum= 0;
  1443. X        GetFNum(PSTRING(fontname), &fnum);
  1444. X        if (fnum == 0)
  1445. X            dprintf("can't find font %s", fontname);
  1446. X        wattr.font= fnum;
  1447. X    }
  1448. X    if (drawing != NULL) {
  1449. X        TextFont(wattr.font);
  1450. X        getfinfo();
  1451. X    }
  1452. X    
  1453. X}
  1454. X
  1455. Xvoid
  1456. Xwsetsize(size)
  1457. X    int size;
  1458. X{
  1459. X    wattr.size= size;
  1460. X    if (drawing != NULL) {
  1461. X        TextSize(size);
  1462. X        getfinfo();
  1463. X    }
  1464. X}
  1465. X
  1466. Xvoid
  1467. Xwsetstyle(face)
  1468. X    Style face;
  1469. X{
  1470. X    wattr.style= face;
  1471. X    if (drawing != NULL) {
  1472. X        TextFace(face & ~TX_INVERSE);
  1473. X        getfinfo();
  1474. X    }
  1475. X}
  1476. X
  1477. Xvoid
  1478. Xwsetplain()
  1479. X{
  1480. X    wsetstyle(0);
  1481. X}
  1482. X
  1483. Xvoid
  1484. Xwsetinverse()
  1485. X{
  1486. X    wattr.style |= TX_INVERSE;
  1487. X}
  1488. X
  1489. Xvoid
  1490. Xwsetbold()
  1491. X{
  1492. X    wsetstyle(bold);
  1493. X}
  1494. X
  1495. Xvoid
  1496. Xwsetitalic()
  1497. X{
  1498. X    wsetstyle(italic);
  1499. X}
  1500. X
  1501. Xvoid
  1502. Xwsetbolditalic()
  1503. X{
  1504. X    wsetstyle(bold|italic);
  1505. X}
  1506. X
  1507. Xvoid
  1508. Xwsetunderline()
  1509. X{
  1510. X    wsetstyle(underline);
  1511. X}
  1512. X
  1513. Xvoid
  1514. Xwsethilite()
  1515. X{
  1516. X    wsetstyle(TX_INVERSE);
  1517. X}
  1518. X
  1519. X/* TEXT MEASURING. */
  1520. X
  1521. Xint
  1522. Xwlineheight()
  1523. X{
  1524. X    if (drawing == NULL) {
  1525. X        TEXTATTR saveattr;
  1526. X        getwattr(screen, &saveattr);
  1527. X        setwattr(&wattr);
  1528. X        getfinfo();
  1529. X        setwattr(&saveattr);
  1530. X    }
  1531. X    return lineheight;
  1532. X}
  1533. X
  1534. Xint
  1535. Xwbaseline()
  1536. X{
  1537. X    if (drawing == NULL)
  1538. X        (void) wlineheight();
  1539. X    return baseline;
  1540. X}
  1541. X
  1542. Xint
  1543. Xwtextwidth(str, len)
  1544. X    char *str;
  1545. X    int len;
  1546. X{
  1547. X    TEXTATTR saveattr;
  1548. X    int width;
  1549. X    
  1550. X    if (drawing == NULL) {
  1551. X        getwattr(screen, &saveattr);
  1552. X        setwattr(&wattr);
  1553. X    }
  1554. X    if (len < 0)
  1555. X        len= strlen(str);
  1556. X    width= TextWidth(str, 0, len);
  1557. X    if (drawing == NULL)
  1558. X        setwattr(&saveattr);
  1559. X    return width;
  1560. X}
  1561. X
  1562. Xint
  1563. Xwcharwidth(c)
  1564. X    int c;
  1565. X{
  1566. X    char cbuf[1];
  1567. X    cbuf[0]= c;
  1568. X    return wtextwidth(cbuf, 1);
  1569. X}
  1570. X
  1571. X/* TEXT DRAWING. */
  1572. X
  1573. Xvoid
  1574. Xwdrawtext(h, v, str, len)
  1575. X    int h, v;
  1576. X    char *str;
  1577. X    int len;
  1578. X{
  1579. X    Point pen;
  1580. X    
  1581. X    if (len < 0)
  1582. X        len= strlen(str);
  1583. X    MoveTo(h, v + baseline);
  1584. X    DrawText(str, 0, len);
  1585. X    GetPen(&pen);
  1586. X    if (wattr.style & TX_INVERSE) {
  1587. X        Rect r;
  1588. X        SetRect(&r, h, v, pen.h, v + lineheight);
  1589. X        InvertRect(&r);
  1590. X    }
  1591. X}
  1592. X
  1593. Xvoid
  1594. Xwdrawchar(h, v, c)
  1595. X    int h, v;
  1596. X    int c;
  1597. X{
  1598. X    if ((wattr.style & TX_INVERSE) == 0) {
  1599. X        /* Attempt to optimize for appls. like dpv */
  1600. X        MoveTo(h, v + baseline);
  1601. X        DrawChar(c);
  1602. X    }
  1603. X    else {
  1604. X        char cbuf[1];
  1605. X        cbuf[0]= c;
  1606. X        wdrawtext(h, v, cbuf, 1);
  1607. X    }
  1608. X}
  1609. X
  1610. X/* COORDINATE CONVERSIONS ETC. */
  1611. X
  1612. X/* Create a rect in current window coordinates (as for getwinrect)
  1613. X   from a rectangle given in document coordinates.
  1614. X   This works both while drawing and while not drawing.
  1615. X   The resulting rectangle is clipped to the winrect. */
  1616. X
  1617. Xvoid
  1618. Xmakerect(win, pr, left, top, right, bottom)
  1619. X    WINDOW *win;
  1620. X    Rect *pr;
  1621. X    int left, top, right, bottom;
  1622. X{
  1623. X    Rect r;
  1624. X    SetRect(pr, left, top, right, bottom);
  1625. X    if (!drawing)
  1626. X        OffsetRect(pr, - win->orgh, - win->orgv);
  1627. X    getwinrect(win, &r);
  1628. X    (void) SectRect(&r, pr, pr);
  1629. X}
  1630. X
  1631. X/* Retrieve the 'winrect', i.e., the contents area exclusive
  1632. X   of the scroll bars and grow icon.
  1633. X   Coordinates are in window coordinates, i.e.,
  1634. X   the origin is (0, 0) outside w{begin,end}drawing,
  1635. X   but (win->orgh, win->orgv) between calls to these routines. */
  1636. X
  1637. Xvoid
  1638. Xgetwinrect(win, pr)
  1639. X    WINDOW *win;
  1640. X    Rect *pr;
  1641. X{
  1642. X    *pr= win->w->portRect;
  1643. X    pr->right -= BAR;
  1644. X    pr->bottom -= BAR;
  1645. X}
  1646. X
  1647. X/* ACTUAL DRAW ROUTINES. */
  1648. X
  1649. Xvoid
  1650. Xwdrawline(h1, v1, h2, v2)
  1651. X{
  1652. X    MoveTo(h1, v1);
  1653. X    Line(h2-h1, v2-v1);
  1654. X}
  1655. X
  1656. Xvoid
  1657. Xwxorline(h1, v1, h2, v2)
  1658. X{
  1659. X    MoveTo(h1, v1);
  1660. X    PenMode(patXor);
  1661. X    Line(h2-h1, v2-v1);
  1662. X    PenNormal();
  1663. X}
  1664. X
  1665. Xvoid
  1666. Xwdrawbox(left, top, right, bottom)
  1667. X    int left, top, right, bottom;
  1668. X{
  1669. X    Rect r;
  1670. X    
  1671. X    SetRect(&r, left, top, right, bottom);
  1672. X    FrameRect(&r);
  1673. X}
  1674. X
  1675. Xvoid
  1676. Xwerase(left, top, right, bottom)
  1677. X    int left, top, right, bottom;
  1678. X{
  1679. X    Rect r;
  1680. X    
  1681. X    SetRect(&r, left, top, right, bottom);
  1682. X    EraseRect(&r);
  1683. X}
  1684. X
  1685. Xvoid
  1686. Xwinvert(left, top, right, bottom)
  1687. X    int left, top, right, bottom;
  1688. X{
  1689. X    Rect r;
  1690. X    
  1691. X    SetRect(&r, left, top, right, bottom);
  1692. X    InvertRect(&r);
  1693. X}
  1694. X
  1695. Xvoid
  1696. Xwpaint(left, top, right, bottom)
  1697. X    int left, top, right, bottom;
  1698. X{
  1699. X    Rect r;
  1700. X    
  1701. X    SetRect(&r, left, top, right, bottom);
  1702. X    FillRect(&r, QD(black));
  1703. X}
  1704. X
  1705. Xvoid
  1706. Xwshade(left, top, right, bottom, perc)
  1707. X    int left, top, right, bottom;
  1708. X    int perc;
  1709. X{
  1710. X    Rect r;
  1711. X    unsigned char *p; /* really Pattern * or PatPtr */
  1712. X    
  1713. X    perc= (perc + 12)/25;
  1714. X    CLIPMIN(perc, 0);
  1715. X    
  1716. X    switch (perc) {
  1717. X    case 0:    p= &QD(white)[0];    break;
  1718. X    case 1: p= &QD(ltGray)[0];    break;
  1719. X    case 2: p= &QD(gray)[0];     break;
  1720. X    case 3: p= &QD(dkGray)[0];    break;
  1721. X    default: p= &QD(black)[0];    break;
  1722. X    }
  1723. X    
  1724. X    SetRect(&r, left, top, right, bottom);
  1725. X
  1726. X    FillRect(&r, p);
  1727. X}
  1728. X
  1729. Xvoid
  1730. Xwdrawcircle(h, v, radius)
  1731. X    int h, v;
  1732. X    int radius;
  1733. X{
  1734. X    Rect r;
  1735. X    
  1736. X    /* XXX Isn't there an off-by-one error here? */
  1737. X    SetRect(&r, h-radius, v-radius, h+radius, v+radius);
  1738. X    FrameOval(&r);
  1739. X}
  1740. X
  1741. X/* Draw counterclockwise elliptical arc.
  1742. X   h, v are center; hrad, vrad are half axes; ang1 and ang2 are start
  1743. X   and stop angles in degrees, with respect to 3 o'clock. */
  1744. X
  1745. Xvoid
  1746. Xwdrawelarc(h, v, hrad, vrad, ang1, ang2)
  1747. X{
  1748. X    Rect r;
  1749. X    /* XXX Does this work? No off-by-one errors? */
  1750. X    SetRect(&r, h-hrad, v-vrad, h+hrad, v+vrad);
  1751. X    FrameArc(&r, 90-ang1, ang1-ang2); /* ??? */
  1752. X}
  1753. X
  1754. X/* CLIPPING */
  1755. X
  1756. Xvoid
  1757. Xwcliprect(left, top, right, bottom)
  1758. X    int left, top, right, bottom;
  1759. X{
  1760. X    Rect r1, r2;
  1761. X    SetRect(&r1, left, top, right, bottom);
  1762. X    getwinrect(drawing, &r2);
  1763. X    SectRect(&r1, &r2, /*dst:*/ &r2);
  1764. X    ClipRect(&r2);
  1765. X
  1766. X}
  1767. X
  1768. Xvoid
  1769. Xwnoclip()
  1770. X{
  1771. X    Rect r;
  1772. X    getwinrect(drawing, &r);
  1773. X    ClipRect(&r);
  1774. X}
  1775. END_OF_FILE
  1776. if test 10989 -ne `wc -c <'Ports/mac/draw.c'`; then
  1777.     echo shar: \"'Ports/mac/draw.c'\" unpacked with wrong size!
  1778. fi
  1779. # end of 'Ports/mac/draw.c'
  1780. fi
  1781. if test -f 'Ports/x11/menu.c' -a "${1}" != "-c" ; then 
  1782.   echo shar: Will not clobber existing file \"'Ports/x11/menu.c'\"
  1783. else
  1784. echo shar: Extracting \"'Ports/x11/menu.c'\" \(11775 characters\)
  1785. sed "s/^X//" >'Ports/x11/menu.c' <<'END_OF_FILE'
  1786. X/* X11 STDWIN -- Menu handling */
  1787. X
  1788. X#include "x11.h"
  1789. X#include "llevent.h" /* For _w_dirty */
  1790. X
  1791. Xstatic bool local; /* When zero, menus are created global */
  1792. X
  1793. Xstatic int nmenus;
  1794. Xstatic MENU **menulist; /* Only global menus */
  1795. X
  1796. Xstatic MENU *sysmenu; /* System menu, included in each window's mbar */
  1797. X
  1798. Xstatic
  1799. Xmbardirty(win)
  1800. X    WINDOW *win;
  1801. X{
  1802. X    _w_dirty= win->mbar.dirty= TRUE;
  1803. X}
  1804. X
  1805. Xvoid
  1806. Xwmenusetdeflocal(flag)
  1807. X    bool flag;
  1808. X{
  1809. X    local= flag;
  1810. X}
  1811. X
  1812. Xvoid
  1813. Xwmenuattach(win, mp)
  1814. X    WINDOW *win;
  1815. X    MENU *mp;
  1816. X{
  1817. X    int i;
  1818. X    
  1819. X    for (i= 0; i < win->nmenus; ++i) {
  1820. X        if (win->menulist[i] == mp)
  1821. X            return; /* Already attached */
  1822. X    }
  1823. X    L_APPEND(win->nmenus, win->menulist, MENU *, mp);
  1824. X    mbardirty(win);
  1825. X}
  1826. X
  1827. Xvoid
  1828. Xwmenudetach(win, mp)
  1829. X    WINDOW *win;
  1830. X    MENU *mp;
  1831. X{
  1832. X    int i;
  1833. X    
  1834. X    for (i= 0; i < win->nmenus; ++i) {
  1835. X        if (win->menulist[i] == mp) {
  1836. X            L_REMOVE(win->nmenus, win->menulist, MENU *, i);
  1837. X            mbardirty(win);
  1838. X            break;
  1839. X        }
  1840. X    }
  1841. X}
  1842. X
  1843. X_waddmenus(win)
  1844. X    WINDOW *win;
  1845. X{
  1846. X    int i;
  1847. X    
  1848. X    /* Create system menu if first time here */
  1849. X    if (sysmenu == NULL) {
  1850. X        bool savelocal= local;
  1851. X        wmenusetdeflocal(TRUE);
  1852. X        sysmenu= wmenucreate(0, "X");
  1853. X        if (sysmenu != NULL)
  1854. X            wmenuadditem(sysmenu, "Close", -1);
  1855. X        wmenusetdeflocal(savelocal);
  1856. X    }
  1857. X    
  1858. X    /* Initialize the nonzero variables used by the menu module */
  1859. X    win->curmenu= win->curitem= -1;
  1860. X    
  1861. X    /* Add system menu and all global menus to the menu list */
  1862. X    if (sysmenu != NULL) {
  1863. X        L_APPEND(win->nmenus, win->menulist, MENU *, sysmenu);
  1864. X    }
  1865. X    for (i= 0; i < nmenus; ++i) {
  1866. X        L_APPEND(win->nmenus, win->menulist, MENU *, menulist[i]);
  1867. X    }
  1868. X    if (nmenus > 0)
  1869. X        mbardirty(win);
  1870. X}
  1871. X
  1872. X_w_delmenus(win)
  1873. X    WINDOW *win;
  1874. X{
  1875. X    /* Delete the menu list before closing a window */
  1876. X    L_DEALLOC(win->nmenus, win->menulist);
  1877. X}
  1878. X
  1879. XMENU *
  1880. Xwmenucreate(id, title)
  1881. X    int id;
  1882. X    char *title;
  1883. X{
  1884. X    MENU *mp= ALLOC(MENU);
  1885. X    
  1886. X    if (mp == NULL)
  1887. X        return NULL;
  1888. X    mp->id= id;
  1889. X    mp->title= strdup(title);
  1890. X    mp->nitems= 0;
  1891. X    mp->itemlist= NULL;
  1892. X    if (!local) {
  1893. X        L_APPEND(nmenus, menulist, MENU *, mp);
  1894. X        _waddtoall(mp);
  1895. X    }
  1896. X    return mp;
  1897. X}
  1898. X
  1899. Xvoid
  1900. Xwmenudelete(mp)
  1901. X    MENU *mp;
  1902. X{
  1903. X    int i;
  1904. X    
  1905. X    for (i= 0; i < nmenus; ++i) {
  1906. X        if (menulist[i] == mp) {
  1907. X            L_REMOVE(nmenus, menulist, MENU *, i);
  1908. X            break;
  1909. X        }
  1910. X    }
  1911. X    _wdelfromall(mp);
  1912. X    
  1913. X    for (i= 0; i < mp->nitems; ++i)
  1914. X        FREE(mp->itemlist[i].text);
  1915. X    FREE(mp->itemlist);
  1916. X    FREE(mp);
  1917. X}
  1918. X
  1919. Xint
  1920. Xwmenuadditem(mp, text, shortcut)
  1921. X    MENU *mp;
  1922. X    char *text;
  1923. X    int shortcut;
  1924. X{
  1925. X    struct item it;
  1926. X    
  1927. X    it.text= strdup(text);
  1928. X    if (shortcut < 0)
  1929. X        it.sctext= NULL;
  1930. X    else {
  1931. X        char buf[50];
  1932. X        sprintf(buf, "M-%c", shortcut);
  1933. X        it.sctext= strdup(buf);
  1934. X    }
  1935. X    it.shortcut= shortcut;
  1936. X    it.enabled=  it.text != NULL && it.text[0] != EOS;
  1937. X    it.checked= FALSE;
  1938. X    L_APPEND(mp->nitems, mp->itemlist, struct item, it);
  1939. X    return mp->nitems - 1;
  1940. X}
  1941. X
  1942. Xvoid
  1943. Xwmenusetitem(mp, i, text)
  1944. X    MENU *mp;
  1945. X    int i;
  1946. X    char *text;
  1947. X{
  1948. X    if (i < 0 || i >= mp->nitems)
  1949. X        return;
  1950. X    FREE(mp->itemlist[i].text);
  1951. X    mp->itemlist[i].text= strdup(text);
  1952. X}
  1953. X
  1954. Xvoid
  1955. Xwmenuenable(mp, i, flag)
  1956. X    MENU *mp;
  1957. X    int i;
  1958. X    bool flag;
  1959. X{
  1960. X    if (i < 0 || i >= mp->nitems)
  1961. X        return;
  1962. X    mp->itemlist[i].enabled= flag;
  1963. X}
  1964. X
  1965. Xvoid
  1966. Xwmenucheck(mp, i, flag)
  1967. X    MENU *mp;
  1968. X    int i;
  1969. X    bool flag;
  1970. X{
  1971. X    if (i < 0 || i >= mp->nitems)
  1972. X        return;
  1973. X    mp->itemlist[i].checked= flag;
  1974. X}
  1975. X
  1976. X/* --- system-dependent code starts here --- */
  1977. X
  1978. X/*
  1979. XXXX Stuff recomputed more than I like:
  1980. X    - length of menu titles and menu item texts
  1981. X    - menu item text widths
  1982. X*/
  1983. X
  1984. X#define NOITEM (-1)
  1985. X#define NOMENU (-1)
  1986. X
  1987. X/* Precomputed values (assume _wdrawmbar is always called first) */
  1988. Xstatic int baseline;
  1989. Xstatic int lineheight;
  1990. Xstatic int halftitledist;
  1991. X#define titledist (2*halftitledist)
  1992. Xstatic int shortcutdist;
  1993. X
  1994. Xstatic
  1995. X_wmenusetup()
  1996. X{
  1997. X    shortcutdist= XTextWidth(_wmf, "    ", 4);
  1998. X    halftitledist= XTextWidth(_wmf, "0", 1);
  1999. X    baseline= _wmf->ascent;
  2000. X    lineheight= _wmf->ascent + _wmf->descent;
  2001. X}
  2002. X
  2003. X/* Draw the menu bar.
  2004. X   Called via the normal exposure event mechanism. */
  2005. X
  2006. X_wdrawmbar(win)
  2007. X    WINDOW *win;
  2008. X{
  2009. X    int i;
  2010. X    int x;
  2011. X    int y;
  2012. X    
  2013. X    _wmenusetup();
  2014. X    x= titledist;
  2015. X    y= baseline - 1 + (win->mbar.height - lineheight) / 2;
  2016. X    
  2017. X    XClearWindow(_wd, win->mbar.wid);
  2018. X    for (i= 0; i < win->nmenus; ++i) {
  2019. X        char *title= win->menulist[i]->title;
  2020. X        int len= strlen(title);
  2021. X        XDrawString(_wd, win->mbar.wid, win->gc, x, y, title, len);
  2022. X        x += XTextWidth(_wmf, title, len) + titledist;
  2023. X    }
  2024. X}
  2025. X
  2026. Xstatic
  2027. Xinverttitle(win, it)
  2028. X    WINDOW *win;
  2029. X    int it;
  2030. X{
  2031. X    int x= leftedge(win, it);
  2032. X    MENU *mp= win->menulist[it];
  2033. X    char *title= mp->title;
  2034. X    int len= strlen(title);
  2035. X    int width= XTextWidth(_wmf, title, len);
  2036. X    
  2037. X    _winvert(win->mbar.wid, win->gc,
  2038. X        x-halftitledist, 0, width+titledist, win->mbar.height);
  2039. X}
  2040. X
  2041. Xstatic int
  2042. Xleftedge(win, it)
  2043. X    WINDOW *win;
  2044. X    int it;
  2045. X{
  2046. X    int i;
  2047. X    int x= titledist;
  2048. X    
  2049. X    for (i= 0; i < it; ++i) {
  2050. X        char *title= win->menulist[i]->title;
  2051. X        int len= strlen(title);
  2052. X        int width= XTextWidth(_wmf, title, len);
  2053. X        x += width + titledist;
  2054. X    }
  2055. X    
  2056. X    return x;
  2057. X}
  2058. X
  2059. X/* Draw the current menu */
  2060. X
  2061. Xstatic
  2062. Xdrawmenu(win)
  2063. X    WINDOW *win;
  2064. X{
  2065. X    int i;
  2066. X    int x= halftitledist;
  2067. X    int y= baseline;
  2068. X    MENU *mp= win->menulist[win->curmenu];
  2069. X    
  2070. X    for (i= 0; i < mp->nitems; ++i) {
  2071. X        char *text= mp->itemlist[i].text;
  2072. X        int len= strlen(text);
  2073. X        char *marker= NULL;
  2074. X        if (!mp->itemlist[i].enabled) {
  2075. X            if (len > 0)
  2076. X                marker= "-";
  2077. X        }
  2078. X        else if (mp->itemlist[i].checked)
  2079. X            marker= "*";
  2080. X        if (marker != NULL) {
  2081. X            int width= XTextWidth(_wmf, marker, 1);
  2082. X            XDrawString(_wd, win->mwin.wid, win->gc,
  2083. X                (x-width)/2, y, marker, 1);
  2084. X        }
  2085. X        XDrawString(_wd, win->mwin.wid, win->gc, x, y, text, len);
  2086. X        text= mp->itemlist[i].sctext;
  2087. X        if (text != NULL) {
  2088. X            int width;
  2089. X            len= strlen(text);
  2090. X            width= XTextWidth(_wmf, text, len);
  2091. X            XDrawString(_wd, win->mwin.wid, win->gc,
  2092. X                win->mwin.width - width - halftitledist, y,
  2093. X                text, len);
  2094. X        }
  2095. X        y += lineheight;
  2096. X    }
  2097. X}
  2098. X
  2099. X/* Create the window for the menu.
  2100. X   It is a direct child of the outer window, but aligned with the
  2101. X   top of the inner window */
  2102. X
  2103. Xstatic
  2104. Xmakemenu(win)
  2105. X    WINDOW *win;
  2106. X{
  2107. X    int i;
  2108. X    int maxwidth= 0;
  2109. X    MENU *mp= win->menulist[win->curmenu];
  2110. X    Window child_dummy;
  2111. X    
  2112. X    /* Compute the maximum item width.
  2113. X       Item width is the sum of:
  2114. X       - 1/2 title width (left margin, also used for tick marks)
  2115. X       - text width of item text
  2116. X       - if there is a shortcut:
  2117. X           - shortcutdist (some space between text and shortcut)
  2118. X           - text width of shortcut text
  2119. X       - 1/2 title width (right margin)
  2120. X    */
  2121. X
  2122. X    for (i= 0; i < mp->nitems; ++i) {
  2123. X        char *text= mp->itemlist[i].text;
  2124. X        int len= strlen(text);
  2125. X        int width= XTextWidth(_wmf, text, len);
  2126. X        text= mp->itemlist[i].sctext;
  2127. X        if (text != NULL) {
  2128. X            len= strlen(text);
  2129. X            width += XTextWidth(_wmf, text, len) + shortcutdist;
  2130. X        }
  2131. X        if (width > maxwidth)
  2132. X            maxwidth= width;
  2133. X    }
  2134. X    
  2135. X    win->mwin.width= maxwidth + titledist;
  2136. X    win->mwin.height= mp->nitems * lineheight + 1;
  2137. X    CLIPMAX(win->mwin.width, WidthOfScreen(_ws));
  2138. X    CLIPMAX(win->mwin.height, HeightOfScreen(_ws));
  2139. X    
  2140. X    if (!XTranslateCoordinates(_wd, win->wo.wid,
  2141. X        RootWindowOfScreen(_ws),
  2142. X        leftedge(win, win->curmenu) -halftitledist + win->mbar.x,
  2143. X        win->wi.y,
  2144. X        &win->mwin.x,
  2145. X        &win->mwin.y,
  2146. X        &child_dummy)) {
  2147. X        
  2148. X        _wwarning("makemenu: XTranslateCoordinates failed");
  2149. X        win->mwin.x = win->mwin.y = 0;
  2150. X    }
  2151. X    
  2152. X    CLIPMAX(win->mwin.x, WidthOfScreen(_ws) - win->mwin.width);
  2153. X    CLIPMAX(win->mwin.y, HeightOfScreen(_ws) - win->mwin.height);
  2154. X    CLIPMIN(win->mwin.x, 0);
  2155. X    CLIPMIN(win->mwin.y, 0);
  2156. X    
  2157. X    win->mwin.dirty= TRUE;
  2158. X    win->mwin.border= IBORDER;
  2159. X    
  2160. X    (void) _wcreate1(&win->mwin, RootWindowOfScreen(_ws), XC_arrow, FALSE,
  2161. X        win->fgo, win->bgo, 1);
  2162. X    _wsaveunder(&win->mwin, True);
  2163. X    XMapWindow(_wd, win->mwin.wid);
  2164. X    i = XGrabPointer(_wd,        /* display */
  2165. X        win->mwin.wid,        /* grab_window */
  2166. X        False,            /* owner_events */
  2167. X        ButtonMotionMask | ButtonReleaseMask,
  2168. X                    /* event_masks */
  2169. X        GrabModeAsync,        /* pointer_mode */
  2170. X        GrabModeAsync,        /* keyboard_mode */
  2171. X        None,            /* confine_to */
  2172. X        None,            /* cursor */
  2173. X        _w_lasttime        /* timestamp */
  2174. X        );
  2175. X    if (i != GrabSuccess) {
  2176. X        _wwarning("makemenu: XGrabPointer failed (err %d)", i);
  2177. X        /* Didn't get the grab -- forget about it */
  2178. X    }
  2179. X}
  2180. X
  2181. X/* Handle mouse state change in menu bar */
  2182. X
  2183. X_whitmbar(bsp, ep)
  2184. X    struct button_state *bsp;
  2185. X    EVENT *ep;
  2186. X{
  2187. X    WINDOW *win= bsp->win;
  2188. X
  2189. X    if (win->curmenu >= 0) {
  2190. X        /* We already created a menu.
  2191. X           This is probably an event that was queued before
  2192. X           the menu window was created. */
  2193. X        _wdebug(1, "_whitmbar: mouse in mwin");
  2194. X    }
  2195. X    
  2196. X    if (!bsp->down)
  2197. X        hidemenu(win);
  2198. X    else if (bsp->y >= 0 && bsp->y <= win->mbar.height &&
  2199. X            bsp->x >= 0 && bsp->x <= win->mbar.width)
  2200. X        showmenu(win, whichmenu(win, bsp->x));
  2201. X}
  2202. X
  2203. X/* Handle mouse state change in menu.
  2204. X   (This is called with a fake button state from _whitmbar,
  2205. X   since the menu bar has grabbed the pointer) */
  2206. X
  2207. X/*static*/ /* Now called from event.c */
  2208. X_whitmwin(bsp, ep)
  2209. X    struct button_state *bsp;
  2210. X    EVENT *ep;
  2211. X{
  2212. X    WINDOW *win= bsp->win;
  2213. X    MENU *mp= win->menulist[win->curmenu];
  2214. X    int it;
  2215. X    
  2216. X    if (bsp->x >= 0 && bsp->x <= win->mwin.width)
  2217. X        it= whichitem(mp, bsp->y);
  2218. X    else
  2219. X        it= NOITEM;
  2220. X    _wdebug(5, "_whitmwin: hit item %d", it);
  2221. X    hiliteitem(win, it);
  2222. X    
  2223. X    if (!bsp->down) {
  2224. X        hidemenu(win);
  2225. X        XFlush(_wd); /* Show it right now */
  2226. X        if (it >= 0) {
  2227. X            if (mp->id == 0) {
  2228. X                ep->type= WE_COMMAND;
  2229. X                ep->u.command= WC_CLOSE;
  2230. X                ep->window= win;
  2231. X            }
  2232. X            else {
  2233. X                ep->type= WE_MENU;
  2234. X                ep->u.m.id= mp->id;
  2235. X                ep->u.m.item= it;
  2236. X                ep->window= win;
  2237. X            }
  2238. X        }
  2239. X    }
  2240. X}
  2241. X
  2242. X/* Show and hide menus */
  2243. X
  2244. Xstatic
  2245. Xshowmenu(win, newmenu)
  2246. X    WINDOW *win;
  2247. X    int newmenu;
  2248. X{
  2249. X    if (newmenu != win->curmenu) {
  2250. X        hidemenu(win);
  2251. X        if (newmenu >= 0) {
  2252. X            win->curmenu= newmenu;
  2253. X            win->curitem= NOITEM;
  2254. X            inverttitle(win, win->curmenu);
  2255. X            makemenu(win);
  2256. X            drawmenu(win);
  2257. X        }
  2258. X    }
  2259. X}
  2260. X
  2261. Xstatic
  2262. Xhidemenu(win)
  2263. X    WINDOW *win;
  2264. X{
  2265. X    if (win->curmenu >= 0) {
  2266. X        hiliteitem(win, NOITEM);
  2267. X        XDestroyWindow(_wd, win->mwin.wid);
  2268. X        win->mwin.wid= 0;
  2269. X        inverttitle(win, win->curmenu);
  2270. X        win->curmenu= NOMENU;
  2271. X    }
  2272. X}
  2273. X
  2274. X/* Compute which menu was hit */
  2275. X
  2276. Xstatic int
  2277. Xwhichmenu(win, xhit)
  2278. X    WINDOW *win;
  2279. X    int xhit;
  2280. X{
  2281. X    int i;
  2282. X    int x= halftitledist;
  2283. X    
  2284. X    if (xhit < x)
  2285. X        return NOMENU;
  2286. X    
  2287. X    for (i= 0; i < win->nmenus; ++i) {
  2288. X        char *title= win->menulist[i]->title;
  2289. X        int len= strlen(title);
  2290. X        x += XTextWidth(_wmf, title, len) + titledist;
  2291. X        if (xhit < x)
  2292. X            return i;
  2293. X    }
  2294. X    
  2295. X    return NOMENU;
  2296. X}
  2297. X
  2298. X/* (Un)hilite the given menu item */
  2299. X
  2300. Xstatic
  2301. Xhiliteitem(win, it)
  2302. X    WINDOW *win;
  2303. X    int it;
  2304. X{
  2305. X    if (it != win->curitem) {
  2306. X        if (win->curitem >= 0)
  2307. X            invertitem(win, win->curitem);
  2308. X        if (it >= 0)
  2309. X            invertitem(win, it);
  2310. X        win->curitem= it;
  2311. X    }
  2312. X}
  2313. X
  2314. Xstatic
  2315. Xinvertitem(win, it)
  2316. X    WINDOW *win;
  2317. X    int it;
  2318. X{
  2319. X    int top, size;
  2320. X    
  2321. X    size= lineheight;
  2322. X    top= it*size;
  2323. X    _winvert(win->mwin.wid, win->gc, 0, top, win->mwin.width, size);
  2324. X}
  2325. X
  2326. X/* Compute which item was hit */
  2327. X
  2328. Xstatic int
  2329. Xwhichitem(mp, yhit)
  2330. X    MENU *mp;
  2331. X    int yhit;
  2332. X{
  2333. X    int it= yhit < 0 ? NOITEM : yhit / lineheight;
  2334. X    
  2335. X    _wdebug(4, "whichitem: yhit=%d, it=%d", yhit, it);
  2336. X    if (it >= 0 && it < mp->nitems && mp->itemlist[it].enabled)
  2337. X        return it;
  2338. X    else
  2339. X        return NOITEM;
  2340. X}
  2341. X
  2342. X/* Generate a menu selection event from a meta-key press.
  2343. X   *ep has the window already filled in. */
  2344. X
  2345. Xbool
  2346. X_w_menukey(c, ep)
  2347. X    int c;
  2348. X    EVENT *ep;
  2349. X{
  2350. X    WINDOW *win= ep->window;
  2351. X    int i;
  2352. X    int altc;
  2353. X    bool althit= FALSE;
  2354. X    
  2355. X    c &= 0xff;
  2356. X    
  2357. X    if (islower(c))
  2358. X        altc= toupper(c);
  2359. X    else if (isupper(c))
  2360. X        altc= tolower(c);
  2361. X    else
  2362. X        altc= 0;
  2363. X    
  2364. X    for (i= 0; i < win->nmenus; ++i) {
  2365. X        MENU *mp= win->menulist[i];
  2366. X        int j;
  2367. X        for (j= 0; j < mp->nitems; ++j) {
  2368. X            if (mp->itemlist[j].shortcut == c) {
  2369. X                ep->type= WE_MENU;
  2370. X                ep->u.m.id= mp->id;
  2371. X                ep->u.m.item= j;
  2372. X                return TRUE;
  2373. X            }
  2374. X            else if (altc != 0 && !althit &&
  2375. X                mp->itemlist[j].shortcut == altc) {
  2376. X                ep->u.m.id= mp->id;
  2377. X                ep->u.m.item= j;
  2378. X                althit= TRUE;
  2379. X            }
  2380. X        }
  2381. X    }
  2382. X    if (althit)
  2383. X        ep->type= WE_MENU;
  2384. X    return althit;
  2385. X}
  2386. X
  2387. X/* Delete all menus -- called by wdone().
  2388. X   (In fact local menus aren't deleted since they aren't in the menu list). */
  2389. X
  2390. X_wkillmenus()
  2391. X{
  2392. X    while (nmenus > 0)
  2393. X        wmenudelete(menulist[nmenus-1]);
  2394. X    if (sysmenu != NULL) {
  2395. X        wmenudelete(sysmenu);
  2396. X        sysmenu= NULL;
  2397. X    }
  2398. X}
  2399. END_OF_FILE
  2400. if test 11775 -ne `wc -c <'Ports/x11/menu.c'`; then
  2401.     echo shar: \"'Ports/x11/menu.c'\" unpacked with wrong size!
  2402. fi
  2403. # end of 'Ports/x11/menu.c'
  2404. fi
  2405. if test -f 'Ports/x11/timer.c' -a "${1}" != "-c" ; then 
  2406.   echo shar: Will not clobber existing file \"'Ports/x11/timer.c'\"
  2407. else
  2408. echo shar: Extracting \"'Ports/x11/timer.c'\" \(5523 characters\)
  2409. sed "s/^X//" >'Ports/x11/timer.c' <<'END_OF_FILE'
  2410. X/* X11 STDWIN -- Alarm timers (BSD-specific) */
  2411. X
  2412. X#ifdef AMOEBA
  2413. X#include "amtimer.c"
  2414. X#else /* !AMOEBA */
  2415. X
  2416. X#include "x11.h"
  2417. X
  2418. X#include <errno.h>
  2419. X
  2420. X/* Alarm timer values must be stored as absolute times,
  2421. X   but since they are in tenths of a second and stored in a long,
  2422. X   there isn't enough space to store the true absolute time.
  2423. X   Therefore, they are stored relative to the second when the
  2424. X   first call to wsettimer was made, which is saved in torigin */
  2425. X
  2426. Xstatic long torigin;        /* Seconds */
  2427. Xstatic long nexttimer;        /* Deciseconds */
  2428. X
  2429. X/* Compute a new value for nexttimer.
  2430. X   Return the relevant window as a convenience */
  2431. X
  2432. Xstatic WINDOW *
  2433. Xsetnexttimer()
  2434. X{
  2435. X    WINDOW *win= _wnexttimer();
  2436. X    
  2437. X    if (win == NULL)
  2438. X        nexttimer= 0;
  2439. X    else
  2440. X        nexttimer= win->timer;
  2441. X    _wdebug(3, "setnexttimer: nexttimer at %d for %x", nexttimer, win);
  2442. X    return win;
  2443. X}
  2444. X
  2445. X/* Set the alarm timer for a given window */
  2446. X
  2447. Xvoid wsettimer(win, deciseconds)
  2448. X    WINDOW *win;
  2449. X    int deciseconds;
  2450. X{
  2451. X    _wdebug(3, "wsettimer: deciseconds=%d", deciseconds);
  2452. X    win->timer= 0;
  2453. X    if (deciseconds > 0) {
  2454. X        struct timeval tv;
  2455. X        struct timezone tz;
  2456. X        
  2457. X        if (gettimeofday(&tv, &tz) < 0) {
  2458. X            _wwarning("wsettimer: can't get time of day");
  2459. X        }
  2460. X        else {
  2461. X            if (torigin == 0) {
  2462. X                torigin= tv.tv_sec;
  2463. X                _wdebug(3, "wsettimer: torigin %d", torigin);
  2464. X            }
  2465. X            win->timer= deciseconds + 10 * (tv.tv_sec - torigin) +
  2466. X                tv.tv_usec/100000;
  2467. X            _wdebug(4, "wsettimer(%d): timer set to %d",
  2468. X                deciseconds, win->timer);
  2469. X        }
  2470. X    }
  2471. X    (void) setnexttimer();
  2472. X}
  2473. X
  2474. X/* Return a pointer suitable as timeout parameter for BSD select(2).
  2475. X   If no alarms are currently set, return a NULL pointer */
  2476. X
  2477. Xstatic struct timeval *
  2478. Xtimeout()
  2479. X{
  2480. X    if (nexttimer == 0) {
  2481. X        _wdebug(4, "timeout: no timers set");
  2482. X        return NULL;
  2483. X    }
  2484. X    else {
  2485. X        static struct timeval tv;
  2486. X        struct timezone tz;
  2487. X        
  2488. X        if (gettimeofday(&tv, &tz) < 0) {
  2489. X            _wwarning("timeout: can't get time of day");
  2490. X            return NULL;
  2491. X        }
  2492. X        else {
  2493. X            long tout;
  2494. X            tout= nexttimer
  2495. X                - (tv.tv_sec - torigin) * 10
  2496. X                - tv.tv_usec / 100000;
  2497. X            if (tout <= 0)
  2498. X                tv.tv_sec= tv.tv_usec= 0;
  2499. X            else {
  2500. X                tv.tv_sec= tout / 10; 
  2501. X                tv.tv_usec= (tout % 10) * 100000;
  2502. X            }
  2503. X            _wdebug(4, "timeout: delay %d sec %d usec",
  2504. X                tv.tv_sec, tv.tv_usec);
  2505. X            return &tv;
  2506. X        }
  2507. X    }
  2508. X}
  2509. X
  2510. X/* Check if an alarm has gone off, and if so, generate an appropriate event.
  2511. X   This can be called at any time, but for efficiency reasons it should
  2512. X   only be called when an alarm has actually gone of (i.e., select has
  2513. X   timed out).  If an alarm has gone off, it will always be found by
  2514. X   this function */
  2515. X
  2516. Xstatic bool
  2517. Xdotimer(ep)
  2518. X    EVENT *ep;
  2519. X{
  2520. X    WINDOW *win= setnexttimer();
  2521. X    struct timeval *tp;
  2522. X    
  2523. X    if (win == NULL) {
  2524. X        _wdebug(1, "dotimer: no event found (spurious call)");
  2525. X        return FALSE;
  2526. X    }
  2527. X    tp= timeout();
  2528. X    if (tp == NULL) {
  2529. X        _wdebug(1, "dotimer: unexpected NULL timeout()");
  2530. X        return FALSE;
  2531. X    }
  2532. X    if (tp->tv_sec == 0 && tp->tv_usec == 0) {
  2533. X        _wdebug(3, "dotimer: reporting timer event");
  2534. X        ep->type= WE_TIMER;
  2535. X        ep->window= win;
  2536. X        win->timer= 0;
  2537. X        (void) setnexttimer();
  2538. X        return TRUE;
  2539. X    }
  2540. X    else {
  2541. X        _wdebug(1, "dotimer: it is not yet time");
  2542. X        return FALSE;
  2543. X    }
  2544. X}
  2545. X
  2546. X/* Check for timer events.
  2547. X   Call this after XPending returns 0, just before calling XNextEvent */
  2548. X
  2549. Xbool
  2550. X_w_checktimer(ep, mayblock)
  2551. X    EVENT *ep;
  2552. X    bool mayblock;
  2553. X{
  2554. X    for (;;) {
  2555. X        struct timeval *tp= timeout();
  2556. X        /* This is naive.  BSD 4.3 really uses an array of longs
  2557. X           as arguments to select.  Hope there aren't >32 fds, or
  2558. X           the socket and pipe are among the first 32 files opened */
  2559. X        unsigned long rd, wd, xd;
  2560. X        int fd, nfd;
  2561. X        int nfound;
  2562. X        if (tp != NULL)
  2563. X            _wdebug(4, "_wchecktimer: sec=%d, usec=%d",
  2564. X                tp->tv_sec, tp->tv_usec);
  2565. X        if (!mayblock) {
  2566. X            if (tp != NULL)
  2567. X                _wdebug(4, "_wchecktimer: !mayblock");
  2568. X            return tp != NULL &&
  2569. X                tp->tv_sec == 0 && tp->tv_usec == 0 &&
  2570. X                dotimer(ep);
  2571. X        }
  2572. X        fd= _wd->fd;
  2573. X        rd= 1 << fd;
  2574. X        nfd= fd+1;
  2575. X#ifdef PIPEHACK
  2576. X        if (_wpipe[0] >= 0) {
  2577. X            rd |= (1 << _wpipe[0]);
  2578. X            if (_wpipe[0]+1 > nfd)
  2579. X                nfd= _wpipe[0]+1;
  2580. X        }
  2581. X#endif
  2582. X        wd= xd= 0;
  2583. X        if (tp == NULL)
  2584. X            _wdebug(4, "wchecktimer: select w/o timeout");
  2585. X        else
  2586. X            _wdebug(4,
  2587. X                "_wchecktimer: select call, sec=%d, usec=%d",
  2588. X                tp->tv_sec, tp->tv_usec);
  2589. X#ifdef AMOEBA
  2590. X        /* Amoeba is far superior to unix:
  2591. X           we don't need something as silly as select... */
  2592. X        nfound= EIO;
  2593. X#else
  2594. X        nfound= select(nfd, &rd, &wd, &xd, tp);
  2595. X#endif
  2596. X        _wdebug(4, "_wchecktimer: select returned %d", nfound);
  2597. X        /* Note: if select returns negative, we also break
  2598. X           out of the loop -- better drop a timer event than
  2599. X           loop forever on a select error.
  2600. X           The only exception is EINTR, which may have been caused
  2601. X           by an application's signal handler */
  2602. X        if (nfound < 0) {
  2603. X            if (errno == EINTR) {
  2604. X                _wdebug(4, "_wchecktimer: select interrupted");
  2605. X                continue;
  2606. X            }
  2607. X            else {
  2608. X#ifdef AMOEBA
  2609. X                if (errno != EIO)
  2610. X#endif
  2611. X                _wwarning(
  2612. X                    "_wchecktimer: select failed, errno=%d",
  2613. X                    errno);
  2614. X            }
  2615. X        }
  2616. X        if (nfound != 0)
  2617. X            break;
  2618. X        if (dotimer(ep))
  2619. X            return TRUE;
  2620. X    }
  2621. X    _wdebug(4, "_wchecktimer: returning FALSE");
  2622. X    return FALSE;
  2623. X}
  2624. X
  2625. X/* P.S.: It is not necessary to recompute nextalarm when windows are
  2626. X   deleted.  This can at most cause a spurious time-out, after which
  2627. X   dotimeout() is called again which recomputes nextalarm as a side
  2628. X   effect (twice, even).  Applications incur a slight overhead if they
  2629. X   delete a window with a timer set and no other windows have timers
  2630. X   set; in this case a larger part of the timeout code is called until
  2631. X   the alarm goes off (which is then ignored!). */
  2632. X
  2633. X#endif /* !AMOEBA */
  2634. END_OF_FILE
  2635. if test 5523 -ne `wc -c <'Ports/x11/timer.c'`; then
  2636.     echo shar: \"'Ports/x11/timer.c'\" unpacked with wrong size!
  2637. fi
  2638. # end of 'Ports/x11/timer.c'
  2639. fi
  2640. echo shar: End of archive 9 \(of 19\).
  2641. cp /dev/null ark9isdone
  2642. MISSING=""
  2643. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  2644.     if test ! -f ark${I}isdone ; then
  2645.     MISSING="${MISSING} ${I}"
  2646.     fi
  2647. done
  2648. if test "${MISSING}" = "" ; then
  2649.     echo You have unpacked all 19 archives.
  2650.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2651. else
  2652.     echo You still need to unpack the following archives:
  2653.     echo "        " ${MISSING}
  2654. fi
  2655. ##  End of shell archive.
  2656. exit 0
  2657.