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

  1. From: guido@cwi.nl (Guido van Rossum)
  2. Newsgroups: alt.sources
  3. Subject: STDWIN 0.9.5, Part 04/19
  4. Message-ID: <3068@charon.cwi.nl>
  5. Date: 4 Mar 91 11:57:42 GMT
  6.  
  7. Archive-name: stdwin/part04
  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 4 (of 19)."
  16. # Contents:  Appls/test/test1.c Packs/vt/vt.c Ports/x11/window.c
  17. # Wrapped by guido@voorn.cwi.nl on Mon Mar  4 12:37:24 1991
  18. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  19. if test -f 'Appls/test/test1.c' -a "${1}" != "-c" ; then 
  20.   echo shar: Will not clobber existing file \"'Appls/test/test1.c'\"
  21. else
  22. echo shar: Extracting \"'Appls/test/test1.c'\" \(251 characters\)
  23. sed "s/^X//" >'Appls/test/test1.c' <<'END_OF_FILE'
  24. X/* Basic test -- open and close a window; no output or events. */
  25. X
  26. X#include "stdwin.h"
  27. X
  28. Xmain(argc, argv)
  29. X    int argc;
  30. X    char **argv;
  31. X{
  32. X    WINDOW *win;
  33. X    winitargs(&argc, &argv);
  34. X    win= wopen("Basic test", (void (*)()) 0);
  35. X    wclose(win);
  36. X    wdone();
  37. X    exit(0);
  38. X}
  39. END_OF_FILE
  40. if test 251 -ne `wc -c <'Appls/test/test1.c'`; then
  41.     echo shar: \"'Appls/test/test1.c'\" unpacked with wrong size!
  42. fi
  43. # end of 'Appls/test/test1.c'
  44. fi
  45. if test -f 'Packs/vt/vt.c' -a "${1}" != "-c" ; then 
  46.   echo shar: Will not clobber existing file \"'Packs/vt/vt.c'\"
  47. else
  48. echo shar: Extracting \"'Packs/vt/vt.c'\" \(20134 characters\)
  49. sed "s/^X//" >'Packs/vt/vt.c' <<'END_OF_FILE'
  50. X/* Virtual Terminal -- basic output routines */
  51. X
  52. X#include "vtimpl.h"
  53. X
  54. X#ifdef macintosh
  55. X/* Bold mode uses the "Bold" font, found in VersaTerm;
  56. X   this matches Monaco and is available only in 9 pt. */
  57. X#define DO_BOLD
  58. X#define SETBOLD() wsetfont("Bold")
  59. X#define SETNORMAL() wsetfont("Monaco")
  60. X#endif
  61. X
  62. X/* Forward */
  63. XSTATIC void vtdrawproc _ARGS((WINDOW *win,
  64. X                int left, int top, int right, int bottom));
  65. XSTATIC void vtdraw _ARGS((VT *vt, int r1, int c1, int r2, int c2));
  66. XSTATIC void vtchrange _ARGS((VT *vt, int r1, int c1, int r2, int c2));
  67. X
  68. X/* Administration for vtfind */
  69. X
  70. Xstatic VT **vtlist;    /* Registered VT structs */
  71. Xstatic int nvt;        /* Number of registered VT structs */
  72. X
  73. X/* Open a VT window of given size */
  74. X
  75. XVT *
  76. Xvtopen(title, rows, cols, save)
  77. X    char *title;
  78. X    int rows, cols;
  79. X    int save; /* Number of rows scroll-back capacity */
  80. X{
  81. X    int row;
  82. X    VT *vt = ALLOC(VT);
  83. X
  84. X    if (vt == NULL)
  85. X        return NULL;
  86. X    rows += save; /* Documentsize: cols * (rows + scrollback) */
  87. X    vt->rows = rows;
  88. X    vt->cols = cols;
  89. X    vt->topterm = save;
  90. X    vt->cwidth = wcharwidth('0');
  91. X    vt->cheight = wlineheight();
  92. X
  93. X    vt->llen = NALLOC(short, rows);
  94. X    vt->data = NALLOC(char *, rows);
  95. X    vt->flags = NALLOC(unsigned char *, rows);
  96. X    for (row = 0; row < rows; ++row) {
  97. X        if (vt->data != NULL)
  98. X            vt->data[row] = NALLOC(char, cols);
  99. X        if (vt->flags != NULL)
  100. X            vt->flags[row] = NALLOC(unsigned char, cols);
  101. X    }
  102. X    /* Assume that if one NALLOC fails, all following ones
  103. X       for the same size also fail... */
  104. X    if (vt->llen == NULL ||
  105. X        vt->data == NULL ||
  106. X        vt->data[rows-1] == NULL ||
  107. X        vt->flags == NULL ||
  108. X        vt->flags[rows-1] == NULL) {
  109. X        vt->win = NULL;
  110. X        vtclose(vt);
  111. X        return NULL;
  112. X    }
  113. X
  114. X    vt->win = wopen(title, vtdrawproc);
  115. X    if (vt->win == NULL) {
  116. X        vtclose(vt);
  117. X        return NULL;
  118. X    }
  119. X    
  120. X    wsetdocsize(vt->win, cols * vt->cwidth, rows * vt->cheight);
  121. X    wsetwincursor(vt->win, wfetchcursor("ibeam"));
  122. X
  123. X    vt->nlcr = FALSE;
  124. X    vt->drawing = FALSE;
  125. X    vtreset(vt); /* Clear additional fields */
  126. X    L_APPEND(nvt, vtlist, VT *, vt);
  127. X
  128. X    return vt;
  129. X}
  130. X
  131. X/* Close a VT window.
  132. X   Also used to clean-up when vtopen failed half-way */
  133. X
  134. Xvoid
  135. Xvtclose(vt)
  136. X    VT *vt;
  137. X{
  138. X    int i, row;
  139. X
  140. X    for (i = 0; i < nvt; ++i) {
  141. X        if (vt == vtlist[i]) {
  142. X            L_REMOVE(nvt, vtlist, VT *, i);
  143. X            break;
  144. X        }
  145. X    }
  146. X
  147. X    if (vt->win != NULL)
  148. X        wclose(vt->win);
  149. X    for (row = 0; row < vt->rows; ++row) {
  150. X        if (vt->data != NULL)
  151. X            FREE(vt->data[row]);
  152. X        if (vt->flags != NULL)
  153. X            FREE(vt->flags[row]);
  154. X    }
  155. X    FREE(vt->data);
  156. X    FREE(vt->flags);
  157. X    FREE(vt);
  158. X}
  159. X
  160. X/* Output a string to a VT window.
  161. X   This does not do escape sequence parsing or control character
  162. X   interpretation, but honors the 'modes' the VT can be in
  163. X   (insert, inverse/underline etc.) and the scrolling region.
  164. X   It updates the cursor position and scrolls if necessary.
  165. X   Note that after one or more calls to vtputstring it is necessary
  166. X   to call vtsync(vt)! */
  167. X
  168. Xvoid
  169. Xvtputstring(vt, text, len)
  170. X    VT *vt;
  171. X    char *text;
  172. X    int len;
  173. X{
  174. X    int row = vt->cur_row;
  175. X    int col = vt->cur_col;
  176. X    short *llen = vt->llen;
  177. X    int scr_top = (vt->scr_top == vt->topterm) ? 0 : vt->scr_top;
  178. X    int scr_bot = (vt->cur_row >= vt->scr_bot) ? vt->rows : vt->scr_bot;
  179. X    int wrap = 0; /* Number of times wrapped around */
  180. X    int last_drawn_col;
  181. X
  182. X#ifndef NDEBUG
  183. X    if (scr_top < 0 || scr_top > vt->rows) {
  184. X        fprintf(stderr, "vtputstring: scr_top = %d\n", scr_top);
  185. X        vtpanic("vtputstring bad scr_top");
  186. X    }
  187. X
  188. X    if (scr_bot < 0 || scr_bot > vt->rows) {
  189. X        fprintf(stderr, "vtputstring: scr_bot = %d\n", scr_bot);
  190. X        vtpanic("vtputstring bad scr_bot");
  191. X    }
  192. X#endif
  193. X
  194. X    /* Compute text length if necessary */
  195. X    if (len < 0)
  196. X        len = strlen(text);
  197. X
  198. X    /* This is a 'do' loop so that a call with an empty
  199. X       string will still normalize the cursor position */
  200. X
  201. X    /* XXX This loop is 100 lines long!  Sorry. */
  202. X    
  203. X    do {
  204. X        int llen_row, n, oldcol;
  205. X
  206. X        /* Normalize the cursor position.
  207. X           When we get past the bottom edge we must scroll,
  208. X           but the actual scrolling is delayed until later:
  209. X           here we just wrap around and remember how many
  210. X           times we've wrapped.
  211. X           Thus, scrolling multiple lines is effected as
  212. X           a 'jump' scroll up -- not so nice-looking,
  213. X           but essential with current performance limitations
  214. X           of bitblit hardware.
  215. X           When faster machines become available we may need
  216. X           an option to turn this optimization off in favour
  217. X           of smooth scrolling. */
  218. X
  219. X        if (col >= vt->cols) {
  220. X            col = 0;
  221. X            ++row;
  222. X            if (wrap > 0 && row < scr_bot)
  223. X                llen[row] = 0;    /* Clear line    */
  224. X        }
  225. X        if (row >= scr_bot) {
  226. X            /* Should be able to turn this off? */
  227. X            if (wrap == 0) last_drawn_col = col;
  228. X            ++wrap;
  229. X            row = scr_top;
  230. X            llen[row] = 0;
  231. X        }
  232. X        oldcol = col; /* For vtdraw call below */
  233. X
  234. X        /* If the cursor is beyond the current line length,
  235. X           eg because of cursor positioning, pad with space.
  236. X           Set llen_row to the new line length. */
  237. X        llen_row = llen[row];
  238. X        if (llen_row < col) {
  239. X            do {
  240. X                vt->data[row][llen_row] = ' ';
  241. X                vt->flags[row][llen_row] = 0;
  242. X            } while (++llen_row < col);
  243. X        }
  244. X
  245. X        /* Set n to the number of characters that can be
  246. X           inserted in the current line */
  247. X        n = vt->cols - col;
  248. X        CLIPMAX(n, len);
  249. X
  250. X        /* When inserting, shift the rest of the line right.
  251. X           The last characters may fall of the edge. */
  252. X        if (vt->insert && llen_row > col && col+n < vt->cols) {
  253. X            int k;
  254. X            llen_row += n;
  255. X            CLIPMAX(llen_row, vt->cols);
  256. X            vtscroll(vt, row, col, row+1, llen_row, 0, n);
  257. X            for (k = llen_row - n; --k >= col; ) {
  258. X                vt->data[row][k+n] = vt->data[row][k];
  259. X                vt->flags[row][k+n] = vt->flags[row][k];
  260. X            }
  261. X        }
  262. X
  263. X        /* Copy the characters into the line data */
  264. X#ifndef NDEBUG
  265. X        if (col + n > vt->cols || row >= vt->rows) {
  266. X            fprintf(stderr, "col=%d, n=%d, row=%d\n", col,n,row);
  267. X            vtpanic("Bad index in vtputstring");
  268. X        }
  269. X#endif
  270. X        strncpy(vt->data[row] + col, text, n);
  271. X
  272. X        /* Update loop administration, maintaining the invariant:
  273. X           'len' characters starting at 'text' still to do */
  274. X        len -= n;
  275. X        text += n;
  276. X
  277. X        /* Set the corresponding flag bits.
  278. X           The current column is set as a side effect. */
  279. X        while (--n >= 0)
  280. X            vt->flags[row][col++] = vt->gflags;
  281. X
  282. X        /* Update line length */
  283. X        CLIPMIN(llen_row, col);
  284. X        llen[row] = llen_row;
  285. X
  286. X        /* Maybe draw the characters now */
  287. X        if (vt->lazy) {
  288. X            D( printf("vtputstring: ") );
  289. X            vtchrange(vt, row, oldcol, row, col);
  290. X        }
  291. X        else if (wrap == 0) {
  292. X            VTBEGINDRAWING(vt);
  293. X            werase(oldcol*vt->cwidth, row*vt->cheight,
  294. X                col*vt->cwidth, (row+1)*vt->cheight);
  295. X
  296. X            D( printf("vtputstring: ") );
  297. X            last_drawn_col = col;
  298. X            vtdraw(vt, row, oldcol, row + 1, col);
  299. X        }
  300. X
  301. X        /* Loop while more work to do */
  302. X
  303. X    } while (len > 0);
  304. X
  305. X#if 0
  306. X    /* XXX Why not? */
  307. X    vtsetcursor(vt, row, col);
  308. X#endif
  309. X
  310. X    /* Process delayed scrolling. */
  311. X
  312. X    if (wrap > 0) {
  313. X        /* Yes, we need to scroll.
  314. X           When wrap > 1, we have scrolled more than a screenful;
  315. X           then the vtscroll call is skipped, but we must still
  316. X           circulate the lines internally. */
  317. X
  318. X        /* Picture:
  319. X
  320. X           scr_top ___________________ (first line affected)
  321. X              .    ___________________
  322. X              .    ______ row ________
  323. X              .    ___________________ (last line affected)
  324. X           scr_bot
  325. X
  326. X           Data move: circulate down so that the data at row
  327. X           moves to scr_bot - 1.
  328. X           Screen bits move: the line below row must
  329. X           become scr_top.
  330. X           We must also invalidate the characters changed
  331. X           before we started scrolling, but we must do this
  332. X           after the vtscroll call, because some STDWIN
  333. X           versions don't properly scroll invalidated bits.
  334. X        */
  335. X
  336. X        if (row + 1 != scr_bot) vtcirculate(vt,
  337. X                    scr_top, scr_bot,
  338. X                    scr_bot - (row + 1));
  339. X        if (wrap == 1) {
  340. X            int n = (row + 1) - scr_top;
  341. X            D( printf("Wrapped once; n=%d\n", n) );
  342. X            vtscroll(vt, scr_top, 0, scr_bot, vt->cols, -n, 0);
  343. X            if (!vt->lazy)
  344. X                vtdraw(vt, scr_bot - n, last_drawn_col,
  345. X                    scr_bot, vt->cols);
  346. X        }
  347. X        else { /* Scrolled more than the scrolling region */
  348. X            D( printf("Whole scrolling region: ") );
  349. X            if (!vt->lazy)
  350. X                vtdraw(vt, scr_top, 0, scr_bot, vt->cols);
  351. X        }
  352. X        row = scr_bot - 1;
  353. X    }
  354. X
  355. X    /* Set the new cursor position */
  356. X    vtsetcursor(vt, row, col);
  357. X}
  358. X
  359. X/* Subroutine to invalidate the text range from (r1, c1) to (r2, c2).
  360. X   This is not the same as vtchange; this function deals with text
  361. X   ranges, while vtchange deals with rectangles. */
  362. X
  363. XSTATIC void
  364. Xvtchrange(vt, r1, c1, r2, c2)
  365. X    VT *vt;
  366. X{
  367. X    D( printf("vtchrange [%d,%d]~[%d,%d]\n", c1, r1, c2, r2) );
  368. X    if (c1 >= vt->cols) {
  369. X        MON_EVENT("vtchrange: c1 >= vt->cols");
  370. X        ++r1; c1 = 0;
  371. X    }
  372. X    if (r1 >= r2) {
  373. X        vtchange(vt, r1, c1, r2+1, c2);
  374. X    }
  375. X    else {
  376. X        vtchange(vt, r1, c1, r1+1, vt->cols);
  377. X        vtchange(vt, r1+1, 0, r2, vt->cols);
  378. X        vtchange(vt, r2, 0, r2+1, c2);
  379. X    }
  380. X}
  381. X
  382. X/* Set cursor position.
  383. X   This sets the STDWIN text caret and calls wshow for the character
  384. X   at the cursor.
  385. X   The cursor position is clipped to the screen dimensions,
  386. X   but it may sit on the right edge just beyond the last character. */
  387. X
  388. Xvoid
  389. Xvtsetcursor(vt, row, col)
  390. X    VT *vt;
  391. X    int row, col;
  392. X{
  393. X    CLIPMAX(row, vt->rows - 1);
  394. X    CLIPMIN(row, 0);
  395. X    CLIPMAX(col, vt->cols);
  396. X    CLIPMIN(col, 0);
  397. X    vt->cur_row = row;
  398. X    vt->cur_col = col;
  399. X    CLIPMAX(col, vt->cols - 1);
  400. X    if (!vt->lazy) {
  401. X        VTENDDRAWING(vt);
  402. X        wsetcaret(vt->win, col * vt->cwidth, row * vt->cheight);
  403. X        vtshow(vt, row, col, row + 1, col);
  404. X    }
  405. X}
  406. X
  407. X/* Set scrolling region.  Lines in [top...bot) can scroll.
  408. X   If the parameters are valid, set the region and move to (0, 0);
  409. X   if there is an error, reset the region and don't move.
  410. X   (NB: the move is to (0, 0), not to the top of the region!) */
  411. X
  412. Xvoid
  413. Xvtsetscroll(vt, top, bot)
  414. X    VT *vt;
  415. X    int top, bot;
  416. X{
  417. X    vtsync(vt);
  418. X    if (top >= vt->topterm && top < bot && bot <= vt->rows) {
  419. X        vt->scr_top = top;
  420. X        vt->scr_bot = bot;
  421. X        vtsetcursor(vt, vt->topterm, 0);
  422. X        /* vtshow(vt, vt->topterm, 0, vt->rows, vt->cols); */
  423. X    }
  424. X    else {
  425. X        vt->scr_top = vt->topterm;
  426. X        vt->scr_bot = vt->rows;
  427. X    }
  428. X    vtshow(vt, vt->scr_top, 0, vt->scr_bot, vt->cols);
  429. X}
  430. X
  431. X/* Major reset */
  432. X
  433. Xvoid
  434. Xvtreset(vt)
  435. X    VT *vt;
  436. X{
  437. X    int row;
  438. X
  439. X    vtchange(vt, 0, 0, vt->rows, vt->cols);
  440. X    vtshow(vt, vt->topterm, 0, vt->rows, vt->cols);
  441. X
  442. X    for (row = 0; row < vt->rows; ++row)
  443. X        vt->llen[row] = 0;
  444. X
  445. X    vt->toscroll = 0;
  446. X    vtsetflags(vt, 0);
  447. X    vtsetinsert(vt, FALSE);
  448. X    vtsetscroll(vt, 0, 0);
  449. X    vtsetcursor(vt, vt->topterm, 0);
  450. X    vt->sel_col1 = vt->sel_row1 = 0;
  451. X    vt->sel_col2 = vt->sel_row2 = 0;
  452. X    vt->save_row = vt->save_col = 0;
  453. X    vt->keypadmode = FALSE;
  454. X    vt->lazy = FALSE;
  455. X    vt->mitmouse = FALSE;
  456. X    vt->visualbell = FALSE;
  457. X    vt->flagschanged = TRUE;
  458. X    vt->action = NULL; /* This invalidates all other parsing fields */
  459. X}
  460. X
  461. X/* Draw procedure - this one is called because stdwin discovered an expose */
  462. X
  463. XSTATIC void
  464. Xvtdrawproc(win, left, top, right, bottom)
  465. X    WINDOW *win;
  466. X    int left, top, right, bottom;
  467. X{
  468. X    VT *vt = vtfind(win);
  469. X
  470. X#ifndef NDEBUG
  471. X    if (vt == NULL) vtpanic("vtdrawproc not for VT window");
  472. X    if (vt->drawing) vtpanic("vtdrawproc while drawing");
  473. X#endif
  474. X
  475. X    vt->drawing = 1;    /* Stdwin did this implicitely */
  476. X    {
  477. X        int cw = vt->cwidth;
  478. X        int ch = vt->cheight;
  479. X        int col1 = left / cw;
  480. X        int col2 = (right + cw - 1) / cw;
  481. X        int row1 = top / ch;
  482. X        int row2 = (bottom + ch - 1) / vt->cheight;
  483. X
  484. X        D( printf("vtdrawproc: ") );
  485. X        vtdraw(vt, row1, col1, row2, col2);
  486. X    }
  487. X    vt->drawing = 0;    /* Stdwin will do this implicitely */
  488. X}
  489. X
  490. XSTATIC void
  491. Xset_textstyle(vt, flags)
  492. X    VT *vt;
  493. X    int flags;
  494. X{
  495. X#if 0
  496. X    /* This isn't right, for various reasons.  And do we need it? */
  497. X    static int previous_flags = -3;    /* Or anything < 0    */
  498. X
  499. X    if (flags == previous_flags) return;
  500. X    D( printf("Set_textstyle: 0x%x => 0x%x\n", previous_flags, flags) );
  501. X    previous_flags = flags;
  502. X#endif
  503. X    wsetplain();
  504. X    if (flags & VT_UNDERLINE) wsetunderline();
  505. X    if (flags & VT_INVERSE) wsetinverse();
  506. X#ifdef DO_BOLD
  507. X    if (flags & VT_BOLD) SETBOLD();
  508. X    else SETNORMAL();
  509. X#endif
  510. X}
  511. X
  512. X/* Draw procedure - doesn't draw [row2, col2], or any other
  513. X   char at row2, takes care of underlining, inverse video etc */
  514. X
  515. XSTATIC void
  516. Xvtdraw(vt, row1, col1, row2, col2)
  517. X    VT *vt;
  518. X    int row1, col1, row2, col2;
  519. X{
  520. X    int cw = vt->cwidth;
  521. X    int ch = vt->cheight;
  522. X    register unsigned char cur_flags;
  523. X    int row;
  524. X
  525. X    VTBEGINDRAWING(vt);
  526. X    D( printf("vtdraw [%d,%d]~[%d,%d]\n", col1, row1, col2, row2) );
  527. X
  528. X    CLIPMIN(col1, 0);
  529. X    CLIPMAX(col2, vt->cols);
  530. X    CLIPMIN(row1, 0);
  531. X    CLIPMAX(row2, vt->rows);
  532. X
  533. X    for (row = row1; row < row2; ++row) {
  534. X    register int col;
  535. X    char *data_row = vt->data[row] + col1;
  536. X    register unsigned char *flags_row = vt->flags[row] + col1;
  537. X    int h = col1*cw;
  538. X    int v = row*ch;
  539. X    int first = col1;
  540. X    register int last = vt->llen[row];
  541. X
  542. X    CLIPMAX(last, col2);    /* Don't draw more than asked for */
  543. X
  544. X    /* Set flags */
  545. X    cur_flags = flags_row[0];
  546. X    set_textstyle(vt, cur_flags);
  547. X
  548. X    /* Attempt to draw as much text as possible in one wdrawtext */
  549. X    for (col = first; col < last; ++col) {
  550. X        if (*flags_row++ != cur_flags) {
  551. X        int n = col-first;
  552. X        /* n cannot be < 0; ==0 means this
  553. X           line has different flags */
  554. X        if (n > 0) {
  555. X            wdrawtext(h, v, data_row, n);
  556. X            first = col;
  557. X            data_row += n;
  558. X            h += n*cw;
  559. X        }
  560. X
  561. X        cur_flags = flags_row[-1];    /* Set new flags */
  562. X        set_textstyle(vt, cur_flags);
  563. X        }
  564. X    }
  565. X    /* Draw leftover text on this line and perhaps some black spaces: */
  566. X    if (col > first) wdrawtext(h, v, data_row, col-first);
  567. X    }
  568. X}
  569. X
  570. X/* Find the VT corresponding to a WINDOW */
  571. X
  572. XVT *
  573. Xvtfind(win)
  574. X    WINDOW *win;
  575. X{
  576. X    int i;
  577. X    for (i = 0; i < nvt; ++i) {
  578. X        if (vtlist[i]->win == win)
  579. X            return vtlist[i];
  580. X    }
  581. X    return NULL;
  582. X}
  583. X
  584. X/* Subroutine to circulate lines.
  585. X   For i in r1 ... r2-1, move line i to position i+n (modulo r2-r1).
  586. X
  587. X   For ABS(n)==1, we have a fast solution that always works.
  588. X   For larger n, we have a slower solution allocating a temporary buffer;
  589. X   if we can't, we repeat the fast solution ABS(n) times (really slow).
  590. X
  591. X   We assume reasonable input:
  592. X    0 <= r1 < r2 <= vt->rows,
  593. X    0 < abs(n) < r2-r1.
  594. X*/
  595. X
  596. Xvoid
  597. Xvtcirculate(vt, r1, r2, n)
  598. X    register VT *vt;
  599. X    int r1, r2;
  600. X    int n;
  601. X{
  602. X    if (n == -1) { /* Fast solution, move 1 up */
  603. X        char *tdata = vt->data[r1];
  604. X        unsigned char *tflags = vt->flags[r1];
  605. X        short tllen = vt->llen[r1];
  606. X        register int i;
  607. X        MON_EVENT("circulate -1");
  608. X        for (i = r1+1; i < r2; ++i) {
  609. X            vt->data[i-1] = vt->data[i];
  610. X            vt->flags[i-1] = vt->flags[i];
  611. X            vt->llen[i-1] = vt->llen[i];
  612. X        }
  613. X        vt->data[i-1] = tdata;
  614. X        vt->flags[i-1] = tflags;
  615. X        vt->llen[i-1] = tllen;
  616. X    }
  617. X    else if (n == 1) { /* Fast solution, move 1 down */
  618. X        char *tdata = vt->data[r2-1];
  619. X        unsigned char *tflags = vt->flags[r2-1];
  620. X        short tllen = vt->llen[r2-1];
  621. X        register int i;
  622. X        MON_EVENT("circulate 1");
  623. X        for (i = r2-1; i > r1; --i) {
  624. X            vt->data[i] = vt->data[i-1];
  625. X            vt->flags[i] = vt->flags[i-1];
  626. X            vt->llen[i] = vt->llen[i-1];
  627. X        }
  628. X        vt->data[i] = tdata;
  629. X        vt->flags[i] = tflags;
  630. X        vt->llen[i] = tllen;
  631. X    }
  632. X    else if (n != 0) {
  633. X        if (!slowcirculate(vt, r1, r2, n)) {
  634. X            /* Couldn't -- do ABS(n) times the fast case... */
  635. X            int step;
  636. X            if (n < 0) {
  637. X                n = -n;
  638. X                step = -1;
  639. X            }
  640. X            else step = 1;
  641. X            while (--n >= 0)
  642. X                vtcirculate(vt, r1, r2, step);
  643. X        }
  644. X    }
  645. X}
  646. X
  647. X/* Slow version of the above; move lines r1..r2-1 n lines up */
  648. X
  649. XSTATIC bool
  650. Xslowcirculate(vt, r1, r2, n)
  651. X    register VT *vt;
  652. X    int r1, r2;
  653. X    int n; /* May be negative */
  654. X{
  655. X    char **tdata; /* Data buffer */
  656. X    unsigned char **tflags; /* Flags buffer */
  657. X    short *tllen; /* Line length buffer */
  658. X    bool ok;
  659. X
  660. X    if (n < 0) n += (r2 - r1);
  661. X    tdata = NALLOC(char *, n);
  662. X    tflags = NALLOC(unsigned char *, n);
  663. X    tllen = NALLOC(short, n);
  664. X
  665. X    MON_EVENT("slowcirculate");
  666. X    /* Did all the malloc's work? */
  667. X    ok = tdata != NULL && tflags != NULL && tllen != NULL;
  668. X    if (ok) {
  669. X        register int i;
  670. X        r2 -= n; /* Now r2 "points" beyond the last target line */
  671. X        /* Save data, flags and lengths to be overwritten */
  672. X        for (i = 0; i < n; ++i) {
  673. X            tdata[i] = vt->data[r2+i];
  674. X            tflags[i] = vt->flags[r2+i];
  675. X            tllen[i] = vt->llen[r2+i];
  676. X        }
  677. X        /* Copy "lower" part of the lines to r1..r1+n-1 (=r2-1) */
  678. X        for (i = r2; --i >= r1; ) {
  679. X            vt->data[i+n] = vt->data[i];
  680. X            vt->flags[i+n] = vt->flags[i];
  681. X            vt->llen[i+n] = vt->llen[i];
  682. X        }
  683. X        /* Restore saved lines in r1..r1+n-1 */
  684. X        for (i = 0; i < n; ++i) {
  685. X            vt->data[r1+i] = tdata[i];
  686. X            vt->flags[r1+i] = tflags[i];
  687. X            vt->llen[r1+i] = tllen[i];
  688. X        }
  689. X    }
  690. X
  691. X    FREE(tdata);
  692. X    FREE(tflags);
  693. X    FREE(tllen);
  694. X
  695. X    return ok;
  696. X}
  697. X
  698. X/* VT interface to wchange */
  699. X
  700. Xvoid
  701. Xvtchange(vt, r1, c1, r2, c2)
  702. X    VT *vt;
  703. X    int r1, c1, r2, c2;
  704. X{
  705. X    VTENDDRAWING(vt);
  706. X    D( printf("vtchange [%d, %d]~[%d, %d]\n", c1, r1, c2, r2) );
  707. X    wchange(vt->win,
  708. X        c1 * vt->cwidth, r1 * vt->cheight,
  709. X        c2 * vt->cwidth, r2 * vt->cheight);
  710. X}
  711. X
  712. X/* VT interface to wshow */
  713. X
  714. Xvoid
  715. Xvtshow(vt, r1, c1, r2, c2)
  716. X    VT *vt;
  717. X    int r1, c1, r2, c2;
  718. X{
  719. X    VTENDDRAWING(vt);
  720. X    wshow(vt->win,
  721. X        c1 * vt->cwidth, r1 * vt->cheight,
  722. X        c2 * vt->cwidth, r2 * vt->cheight);
  723. X}
  724. X
  725. X/* VT interface to wscroll.
  726. X   In lazy mode, the actual scrolling may be postponed
  727. X   (by setting vt->toscroll). */
  728. X
  729. Xvoid
  730. Xvtscroll(vt, r1, c1, r2, c2, drow, dcol)
  731. X    VT *vt;
  732. X    int r1, c1, r2, c2;
  733. X    int drow, dcol; /* Translation vector */
  734. X{
  735. X    int scr_top = vt->scr_top;
  736. X    if (scr_top == vt->topterm)
  737. X        scr_top = 0;
  738. X
  739. X    D( printf("vtscroll %d lines\n", drow) );
  740. X
  741. X    if (vt->lazy && dcol == 0 && r1 == scr_top && r2 == vt->scr_bot &&
  742. X        c1 == 0 && c2 == vt->cols) {
  743. X        if (drow * vt->toscroll < 0)
  744. X            vtsync(vt);
  745. X        vt->toscroll += drow;
  746. X    }
  747. X    else {
  748. X        if (vt->toscroll != 0 && r1 < vt->scr_bot && r2 > scr_top)
  749. X            vtsync(vt); /* Execute leftover scrolling first */
  750. X
  751. X        /* Convert to STDWIN coordinates */
  752. X        c1 *= vt->cwidth;
  753. X        c2 *= vt->cwidth;
  754. X        dcol *= vt->cwidth;
  755. X
  756. X        r1 *= vt->cheight;
  757. X        r2 *= vt->cheight;
  758. X        drow *= vt->cheight;
  759. X
  760. X        VTENDDRAWING(vt);
  761. X        wnocaret(vt->win);
  762. X        wscroll(vt->win, c1, r1, c2, r2, dcol, drow);
  763. X
  764. X        /* Despite what the stdwin document says,
  765. X           wscroll doesn't generate wchanges anymore */
  766. X        if (vt->lazy) {
  767. X            if (drow < 0) {        /* Scrolled upwards    */
  768. X                wchange(vt->win, c1, r2+drow, c2, r2);
  769. X                D( printf("^: wchange(%d, %d, %d, %d)\n",
  770. X                        c1, r2+drow, c2, r2) );
  771. X            }
  772. X            else if (drow > 0) {    /* Scrolled downwards    */
  773. X                wchange(vt->win, c1, r1, c2, r1+drow);
  774. X                D( printf("V: wchange(%d, %d, %d, %d)\n",
  775. X                        c1, r1, c2, r1+drow) );
  776. X            }
  777. X            if (dcol < 0) {        /* Scrolled to the left    */
  778. X                wchange(vt->win, c2+dcol, r1, c2, r2);
  779. X                D( printf("<: wchange(%d, %d, %d, %d)\n",
  780. X                        c2+dcol, r1, c2, r2) );
  781. X            }
  782. X            else if (dcol > 0) {    /* Scrolled to the right */
  783. X                wchange(vt->win, c1, r1, c1+dcol, r2);
  784. X                D( printf(">: wchange(%d, %d, %d, %d)\n",
  785. X                        c1, r1, c1+dcol, r2) );
  786. X            }
  787. X        }
  788. X    }
  789. X}
  790. X
  791. X/* Execute delayed scrolling.
  792. X   Don't call from within drawproc: wscroll while drawing is BAD. */
  793. X
  794. Xvoid
  795. Xvtsync(vt)
  796. X    VT *vt;
  797. X{
  798. X    VTENDDRAWING(vt);
  799. X    if (vt->toscroll != 0) {
  800. X        int scr_top = vt->scr_top;
  801. X#if 0
  802. X        /* XXX Why not? */
  803. X        if (vt->toscroll < 0) vtpanic("vtsync: toscroll < 0");
  804. X#endif
  805. X        if (scr_top == vt->topterm)
  806. X            scr_top = 0;
  807. X        D( printf("VtSync [,%d]~[,%d] %d: wscroll\n",
  808. X            scr_top, vt->scr_bot, vt->toscroll) );
  809. X        wscroll(vt->win,
  810. X            0, scr_top * vt->cheight,
  811. X            vt->cols * vt->cwidth, vt->scr_bot * vt->cheight,
  812. X            0, vt->toscroll * vt->cheight);
  813. X
  814. X        D( printf("vtsync: ") );
  815. X        /* I could get speedup from remembering
  816. X         * min and max columns for the call here
  817. X         */
  818. X        vtchange(vt, vt->scr_bot + vt->toscroll, 0,
  819. X            vt->scr_bot, vt->cols);
  820. X        vt->toscroll = 0;
  821. X    }
  822. X    /* vtsetcursor doesn't do this if vt->lazy: */
  823. X    if (vt->lazy) {
  824. X        MON_EVENT("vtsync for lazy");
  825. X        wsetcaret(vt->win,
  826. X            vt->cur_col * vt->cwidth,
  827. X            vt->cur_row * vt->cheight);
  828. X        vtshow(vt, vt->cur_row,vt->cur_col, vt->cur_row+1,vt->cur_col);
  829. X    }
  830. X}
  831. X
  832. X/* Internal VT interface to winvert.
  833. X   Must be called between wbegindrawing and wenddrawing. */
  834. X
  835. Xvoid
  836. Xvtinvert(vt, row1, col1, row2, col2)
  837. X    VT *vt;
  838. X    int row1, col1, row2, col2;
  839. X{
  840. X    /* XXX Here was some code */
  841. X
  842. X    if (row1 == row2) {
  843. X        /* Whole selection within one line */
  844. X        winvert(col1 * vt->cwidth, row1 * vt->cheight,
  845. X            col2 * vt->cwidth, (row2 + 1) * vt->cheight);
  846. X    }
  847. X    else {
  848. X        /* Invert first line of the selection */
  849. X        winvert(col1 * vt->cwidth, row1 * vt->cheight,
  850. X            vt->cols * vt->cwidth, (row1 + 1) * vt->cheight);
  851. X
  852. X        /* Invert intermediate lines, if any */
  853. X        if (row1 + 1 < row2) {
  854. X            winvert(0, (row1 + 1) * vt->cheight,
  855. X                vt->cols * vt->cwidth, row2 * vt->cheight);
  856. X        }
  857. X
  858. X        /* Invert last line */
  859. X        winvert(0, row2 * vt->cheight,
  860. X            col2 * vt->cwidth, (row2 + 1) * vt->cheight);
  861. X    }
  862. X}
  863. END_OF_FILE
  864. if test 20134 -ne `wc -c <'Packs/vt/vt.c'`; then
  865.     echo shar: \"'Packs/vt/vt.c'\" unpacked with wrong size!
  866. fi
  867. # end of 'Packs/vt/vt.c'
  868. fi
  869. if test -f 'Ports/x11/window.c' -a "${1}" != "-c" ; then 
  870.   echo shar: Will not clobber existing file \"'Ports/x11/window.c'\"
  871. else
  872. echo shar: Extracting \"'Ports/x11/window.c'\" \(30704 characters\)
  873. sed "s/^X//" >'Ports/x11/window.c' <<'END_OF_FILE'
  874. X/* X11 STDWIN -- Window operations */
  875. X
  876. X#include "x11.h"
  877. X#include "llevent.h"
  878. X#include <X11/Xutil.h> /* For Rectangle{In,Out,Part} */
  879. X
  880. X
  881. X/* Margin size around inner window (space for scroll and menu bars) */
  882. X
  883. X#define LMARGIN        16
  884. X/*
  885. X#define TMARGIN        (MIN((_wmf->ascent + _wmf->descent), 16) + 2)
  886. X*/
  887. X#define TMARGIN        18
  888. X#define RMARGIN        0
  889. X#define BMARGIN        16
  890. X#define IMARGIN        2
  891. X
  892. X
  893. X/* Event masks */
  894. X
  895. X/* Mask for 'wo' */
  896. X#define OUTER_MASK    ( KeyPressMask \
  897. X            | FocusChangeMask \
  898. X            | EnterWindowMask \
  899. X            | LeaveWindowMask \
  900. X            | StructureNotifyMask \
  901. X            )
  902. X
  903. X/* Mask for other windows except 'wi' */
  904. X#define OTHER_MASK    ( ButtonPressMask \
  905. X            | ButtonReleaseMask \
  906. X            | ButtonMotionMask \
  907. X            | ExposureMask \
  908. X            )
  909. X
  910. X    
  911. X/* Private globals */
  912. X
  913. Xstatic int def_h, def_v;
  914. Xstatic int def_width, def_height;
  915. X
  916. X#define DEF_WIDTH (def_width > 0 ? def_width : 80*wcharwidth('n'))
  917. X#define DEF_HEIGHT (def_height > 0 ? def_height : 22*wlineheight())
  918. X
  919. X
  920. X/* WINDOW list.
  921. X   Each WINDOW must be registered here, so it can be found back
  922. X   by _whichwin */
  923. X
  924. Xstatic WINDOW **winlist;
  925. Xstatic int nwins;
  926. X
  927. X
  928. X/* Find a WINDOW pointer, given a Window.
  929. X   Hunt through the WINDOW list, for each element comparing the given wid
  930. X   with the wids of all (sub)Windows */
  931. X
  932. XWINDOW *
  933. X_whichwin(w)
  934. X    register Window w;
  935. X{
  936. X    register int i;
  937. X    
  938. X    for (i= nwins; --i >= 0; ) {
  939. X        register WINDOW *win= winlist[i];
  940. X        register int j;
  941. X        for (j= NSUBS; --j >= 0; ) {
  942. X            if (w == win->subw[j].wid)
  943. X                return win;
  944. X        }
  945. X    }
  946. X    _wdebug(2, "_whichwin: can't find Window %x", w);
  947. X    return NULL;
  948. X}
  949. X
  950. X
  951. X/* Return some window */
  952. X
  953. XWINDOW *
  954. X_w_somewin()
  955. X{
  956. X    if (nwins <= 0)
  957. X        return NULL;
  958. X    return winlist[0];
  959. X}
  960. X
  961. X
  962. X/* Set the max size of windows created later (ignored for now) */
  963. X
  964. Xvoid
  965. Xwsetmaxwinsize(width, height)
  966. X    int width, height;
  967. X{
  968. X}
  969. X
  970. X
  971. X/* Set the initial size of windows created later */
  972. X
  973. Xvoid
  974. Xwsetdefwinsize(width, height)
  975. X    int width, height;
  976. X{
  977. X    if (width <= 0)
  978. X        def_width= 0;
  979. X    else {
  980. X        CLIPMAX(width, WidthOfScreen(_ws) - 40 - LMARGIN - RMARGIN);
  981. X        CLIPMIN(width, 40);
  982. X        def_width= width;
  983. X    }
  984. X    if (height <= 0)
  985. X        def_height= 0;
  986. X    else {
  987. X        CLIPMAX(height, HeightOfScreen(_ws) - 40 - TMARGIN - BMARGIN);
  988. X        CLIPMIN(height, 40);
  989. X        def_height= height;
  990. X    }
  991. X}
  992. X
  993. Xvoid
  994. Xwgetdefwinsize(pwidth, pheight)
  995. X    int *pwidth, *pheight;
  996. X{
  997. X    *pheight = def_height;
  998. X    *pwidth = def_width;
  999. X}
  1000. X
  1001. X
  1002. X/* Set the initial position of windows created later */
  1003. X
  1004. Xvoid
  1005. Xwsetdefwinpos(h, v)
  1006. X    int h, v;
  1007. X{
  1008. X    CLIPMIN(h, 0);
  1009. X    CLIPMIN(v, 0);
  1010. X    def_h= h;
  1011. X    def_v= v;
  1012. X}
  1013. X
  1014. Xvoid
  1015. Xwgetdefwinpos(ph, pv)
  1016. X    int *ph, *pv;
  1017. X{
  1018. X    *ph = def_h;
  1019. X    *pv = def_v;
  1020. X}
  1021. X
  1022. X
  1023. X/* Read a Bitmap from a file and convert it to a Pixmap.
  1024. X   XXX Actually I don't convert it to a Pixmap; this may mean that perhaps
  1025. X   you won't be able to set an icon on a color display, depending
  1026. X   on the intelligence of the window manager.
  1027. X   XXX Note that to fix this you must create separate functions to read
  1028. X   Bitmaps and Pixmaps, as Bitmaps have a real use (for icon masks). */
  1029. X
  1030. X#define readpixmap readbitmap
  1031. X
  1032. X/* Read a bitmap from file */
  1033. X
  1034. Xstatic Pixmap
  1035. Xreadbitmap(filename)
  1036. X    char *filename;
  1037. X{
  1038. X    unsigned int width, height;
  1039. X    int xhot, yhot;
  1040. X    Pixmap bitmap;
  1041. X    int err= XReadBitmapFile(_wd, RootWindowOfScreen(_ws), filename,
  1042. X        &width, &height, &bitmap, &xhot, &yhot);
  1043. X    if (err != BitmapSuccess) {
  1044. X        _wwarning("can't read bitmap file %s, error code %d",
  1045. X            filename, err);
  1046. X        return None;
  1047. X    }
  1048. X    return bitmap;
  1049. X}
  1050. X
  1051. X
  1052. X/* Open a WINDOW.
  1053. X   Some defaults should only be used for the first window opened,
  1054. X   e.g., window geometry (otherwise all windows would overlay each other!)
  1055. X   and the "iconic" property.  Icon bitmaps will be used by all windows. */
  1056. X
  1057. XWINDOW *
  1058. Xwopen(title, drawproc)
  1059. X    char *title;
  1060. X    void (*drawproc)();
  1061. X{
  1062. X    static bool used_defaults;
  1063. X    WINDOW *win;
  1064. X    XSizeHints sizehints;
  1065. X    
  1066. X    /* Allocate zeroed storage for the WINDOW structure
  1067. X       and fill in the easy non-zero values */
  1068. X    win= (WINDOW*) calloc(sizeof(WINDOW), 1);
  1069. X    if (win == NULL) {
  1070. X        _werror("wopen: can't alloc storage for window");
  1071. X        return NULL;
  1072. X    }
  1073. X    win->drawproc= drawproc;
  1074. X    win->careth= win->caretv= -1;
  1075. X    win->attr= wattr;
  1076. X    
  1077. X    /* Parse user-specified geometry default.
  1078. X       This overrides what the application specified.
  1079. X       Note that the x and y stored internally are exclusive or borders,
  1080. X       while X geometries specify x and y including the border.
  1081. X       XXX Also note that the obsolete sizehints members x, y, width and
  1082. X       height are used later to actually create the window. */
  1083. X    {
  1084. X        char *geom;
  1085. X        sizehints.x= def_h <= 0 ? 0 : def_h - 2*IBORDER;
  1086. X        sizehints.y= def_v <= 0 ? 0 : def_v - 2*IBORDER;
  1087. X        sizehints.width= DEF_WIDTH + LMARGIN + RMARGIN;
  1088. X        sizehints.height= DEF_HEIGHT + TMARGIN + BMARGIN;
  1089. X        sizehints.flags= PSize;
  1090. X        if (def_h > 0 || def_v > 0)
  1091. X            sizehints.flags |= PPosition | USPosition;
  1092. X            /* USPosition added to fool twm */
  1093. X        if (!used_defaults &&
  1094. X            (geom= _wgetdefault("geometry", "Geometry")) != NULL){
  1095. X            unsigned int width, height;
  1096. X            int flags= XParseGeometry(geom,
  1097. X                &sizehints.x, &sizehints.y, &width, &height);
  1098. X            if (flags & WidthValue)
  1099. X                sizehints.width = width;
  1100. X            if (flags & HeightValue)
  1101. X                sizehints.height = height;
  1102. X            if (flags & XNegative)
  1103. X                sizehints.x=
  1104. X                    WidthOfScreen(_ws) + sizehints.x
  1105. X                    - sizehints.width - 2*IBORDER;
  1106. X            if (flags & YNegative)
  1107. X                sizehints.y=
  1108. X                    HeightOfScreen(_ws) + sizehints.y
  1109. X                    - sizehints.height - 2*IBORDER;
  1110. X            
  1111. X            /* Use the user-specified size as the default
  1112. X               size for future windows */
  1113. X            
  1114. X            if (flags & WidthValue)
  1115. X                def_width=
  1116. X                    sizehints.width - LMARGIN - RMARGIN;
  1117. X            if (flags & HeightValue)
  1118. X                def_height=
  1119. X                    sizehints.height - TMARGIN - BMARGIN;
  1120. X            
  1121. X            /* If the user has given as position,
  1122. X               pretend a size is also given, otherwise
  1123. X               UWM will still ask for interactive
  1124. X               window placement.  I'm in good company:
  1125. X               "the" Toolkit also does this. */
  1126. X            
  1127. X            if (flags & (XValue|YValue))
  1128. X                sizehints.flags |= USPosition|USSize;
  1129. X            else if (flags & (WidthValue|HeightValue))
  1130. X                sizehints.flags |= USSize;
  1131. X            
  1132. X#if 1
  1133. X            /* XXX This doesn't compile in R3.
  1134. X               It's safe to take it out. */
  1135. X            
  1136. X            /* Derive the gravity hint from the geometry */
  1137. X            
  1138. X            if ((flags & XNegative) || (flags & YNegative)) {
  1139. X                sizehints.flags |= PWinGravity;
  1140. X                if (flags & XNegative) {
  1141. X                    if (flags & YNegative)
  1142. X                        sizehints.win_gravity =
  1143. X                            SouthEastGravity;
  1144. X                    else
  1145. X                        sizehints.win_gravity =
  1146. X                            NorthEastGravity;
  1147. X                }
  1148. X                else
  1149. X                    sizehints.win_gravity =
  1150. X                        SouthWestGravity;
  1151. X            }
  1152. X#endif            
  1153. X            /* XXX Do we need a resource to specify the min
  1154. X               size (or base size), max size and size
  1155. X               increment?  Better to let the application
  1156. X               decide based upon the font used? */
  1157. X        }
  1158. X    }
  1159. X    
  1160. X    /* Set the initial geometry from the size hints just computed */
  1161. X    win->wo.border= 2*IBORDER;
  1162. X    win->wo.x= sizehints.x + win->wo.border;
  1163. X    win->wo.y= sizehints.y + win->wo.border;
  1164. X    win->wo.width= sizehints.width;
  1165. X    win->wo.height= sizehints.height;
  1166. X    
  1167. X    /* Set the foreground and background pixel values */
  1168. X    win->fga= _wgetpixel("foreground", "Foreground",
  1169. X                        BlackPixelOfScreen(_ws));
  1170. X    win->bga= _wgetpixel("background", "Background",
  1171. X                        WhitePixelOfScreen(_ws));
  1172. X    win->fgo= _wgetpixel("menuForeground", "Foreground", win->fga);
  1173. X    win->bgo= _wgetpixel("menuBackground", "Background", win->bga);
  1174. X    
  1175. X    /* Swap the pixel values if 'reverse' specified */
  1176. X    if (_wgetbool("reverse", "Reverse", 0)) {
  1177. X        unsigned long temp= win->fga;
  1178. X        win->fga= win->bga;
  1179. X        win->bga= temp;
  1180. X        temp= win->fgo;
  1181. X        win->fgo= win->bgo;
  1182. X        win->bgo= temp;
  1183. X    }
  1184. X    
  1185. X    /* Create the outer Window */
  1186. X    if (!_wcreate(&win->wo, RootWindowOfScreen(_ws), 0, FALSE,
  1187. X        win->fgo, win->bgo)) {
  1188. X        FREE(win);
  1189. X        return NULL;
  1190. X    }
  1191. X    
  1192. X    /* Create the inner subWindows */
  1193. X    if (!_wmakesubwins(win)) {
  1194. X        FREE(win);
  1195. X        return NULL;
  1196. X    }
  1197. X    
  1198. X    /* Create the Graphics Contexts */
  1199. X    win->gc= _wgcreate(win->wo.wid, _wmf->fid, win->fgo, win->bgo);
  1200. X    win->gca= _wgcreate(win->wa.wid, _wf->fid, win->fga, win->bga);
  1201. X    
  1202. X    /* Change selected Window properties */
  1203. X    _wsetmasks(win);
  1204. X    _w_setgrayborder(win);
  1205. X    
  1206. X    /* Set the "invalid" region to empty (rely on Expose events) */
  1207. X    win->inval= XCreateRegion();
  1208. X    
  1209. X    /* Initialize the menu bar stuff */
  1210. X    _waddmenus(win);
  1211. X    
  1212. X    /* Set window properties */
  1213. X    
  1214. X    /* Set window and icon names */
  1215. X    {
  1216. X        char *windowname = title;
  1217. X        char *iconname = NULL;
  1218. X        char *p;
  1219. X        
  1220. X        /* Resources may override these for the first window */
  1221. X        if (!used_defaults) {
  1222. X            if ((p = _wgetdefault("title", "Title")) != NULL)
  1223. X                windowname = iconname = p;
  1224. X            if ((p = _wgetdefault("iconName", "IconName")) != NULL)
  1225. X                iconname = p;
  1226. X        }
  1227. X        
  1228. X        XStoreName(_wd, win->wo.wid, windowname);
  1229. X        /* Only store the icon name if specified -- the WM will
  1230. X           derive a default from the title otherwise. */
  1231. X        if (iconname != NULL)
  1232. X            XSetIconName(_wd, win->wo.wid, iconname);
  1233. X    }
  1234. X    
  1235. X    /* Set command line (computed by winitargs()) */
  1236. X    XChangeProperty(_wd, win->wo.wid,
  1237. X        XA_WM_COMMAND, XA_STRING, 8, PropModeReplace,
  1238. X        (unsigned char *)_wm_command, _wm_command_len);
  1239. X        /* XXX The ICCCM prescribes that exactly one window
  1240. X           of a given client has this property.  Later. */
  1241. X    
  1242. X    /* Set normal size hints (computed above) */
  1243. X    XSetNormalHints(_wd, win->wo.wid, &sizehints);
  1244. X    
  1245. X    /* Set WM Hints */
  1246. X    {
  1247. X        XWMHints wmhints;
  1248. X        char *value;
  1249. X        wmhints.flags= InputHint | StateHint;
  1250. X        wmhints.input= _wgetbool("input", "Input", 1);
  1251. X        if (!used_defaults &&
  1252. X            _wgetbool("iconic", "Iconic", 0))
  1253. X            wmhints.initial_state= IconicState;
  1254. X        else
  1255. X            wmhints.initial_state= NormalState;
  1256. X        if (!used_defaults && (value=
  1257. X            _wgetdefault("iconGeometry", "IconGeometry"))
  1258. X                != NULL) {
  1259. X            unsigned int width, height;
  1260. X            int flags= XParseGeometry(value,
  1261. X                &wmhints.icon_x, &wmhints.icon_y,
  1262. X                &width, &height);
  1263. X            if (flags & XNegative)
  1264. X                wmhints.icon_x=
  1265. X                    WidthOfScreen(_ws) - wmhints.icon_x;
  1266. X            if (flags & YNegative)
  1267. X                wmhints.icon_y=
  1268. X                    HeightOfScreen(_ws) - wmhints.icon_y;
  1269. X            if (flags & (XValue|YValue)) {
  1270. X                wmhints.flags |= IconPositionHint;
  1271. X                _wdebug(1, "icon pos: %d,%d",
  1272. X                    wmhints.icon_x, wmhints.icon_y);
  1273. X            }
  1274. X            else
  1275. X                _wdebug(1, "no icon pos");
  1276. X        }
  1277. X        value= _wgetdefault("iconBitmap", "IconBitmap");
  1278. X        if (value != NULL)  {
  1279. X            wmhints.icon_pixmap= readpixmap(value);
  1280. X            if (wmhints.icon_pixmap != None)
  1281. X                wmhints.flags |= IconPixmapHint;
  1282. X        }
  1283. X        value= _wgetdefault("iconMask", "IconMask");
  1284. X        if (value != NULL)  {
  1285. X            wmhints.icon_mask= readbitmap(value);
  1286. X            if (wmhints.icon_mask != None)
  1287. X                wmhints.flags |= IconMaskHint;
  1288. X        }
  1289. X        /* XXX What about window groups? */
  1290. X        XSetWMHints(_wd, win->wo.wid, &wmhints);
  1291. X    }
  1292. X    
  1293. X    /* Set class (same as strings used by _wgetdefault() */
  1294. X    {
  1295. X        XClassHint classhint;
  1296. X        classhint.res_name= _wprogname;
  1297. X        classhint.res_class= "Stdwin";
  1298. X        XSetClassHint(_wd, win->wo.wid, &classhint);
  1299. X    }
  1300. X    
  1301. X    /* Set client machine */
  1302. X    XChangeProperty(_wd, win->wo.wid,
  1303. X        XA_WM_CLIENT_MACHINE, XA_STRING, 8, PropModeReplace,
  1304. X        (unsigned char *)_whostname, strlen(_whostname));
  1305. X    
  1306. X    /* Set protocols property */
  1307. X    {
  1308. X        static Atom protocols[] = {
  1309. X            0 /*XA_WM_DELETE_WINDOW*/,
  1310. X        };
  1311. X        protocols[0] = _wm_delete_window;
  1312. X        XChangeProperty(_wd, win->wo.wid,
  1313. X            _wm_protocols, XA_ATOM, 32, PropModeReplace,
  1314. X            (unsigned char *)protocols,
  1315. X            sizeof(protocols) / sizeof(protocols[0]));
  1316. X    }
  1317. X    
  1318. X    /* Store the WINDOW pointer in the list of windows */
  1319. X    L_APPEND(nwins, winlist, WINDOW *, win);
  1320. X    
  1321. X    /* Now we're ready, finally show the window, on top of others */
  1322. X    XMapRaised(_wd, win->wo.wid);
  1323. X    
  1324. X    /* Note that we've used the once-only defaults */
  1325. X    used_defaults= TRUE;
  1326. X    
  1327. X    /* Don't forget to return the WINDOW pointer */
  1328. X    return win;
  1329. X}
  1330. X
  1331. X
  1332. X/* Make a window the active window -- ICCCM version.
  1333. X   - De-iconify.
  1334. X   - Raise the window.
  1335. X   Any events that may follow from this are handled later when we get them.
  1336. X*/
  1337. X
  1338. Xvoid
  1339. Xwsetactive(win)
  1340. X    WINDOW *win;
  1341. X{
  1342. X    XMapRaised(_wd, win->wo.wid); /* The ICCCM way to de-iconify */
  1343. X    XRaiseWindow(_wd, win->wo.wid);
  1344. X}
  1345. X
  1346. X
  1347. X/* Get a pixel value from the resource database */
  1348. X
  1349. Xunsigned long
  1350. X_wgetpixel(resname, resclassname, defpixel)
  1351. X    char *resname;
  1352. X    char *resclassname;
  1353. X    unsigned long defpixel;
  1354. X{
  1355. X    char *cname;
  1356. X    Colormap cmap;
  1357. X    XColor hard, exact;
  1358. X    
  1359. X    cname= _wgetdefault(resname, resclassname);
  1360. X    if (cname == NULL)
  1361. X        return defpixel;
  1362. X    cmap= DefaultColormapOfScreen(_ws);
  1363. X    if (!XParseColor(_wd, cmap, cname, &exact)) {
  1364. X        _wwarning("%s: no such color", cname);
  1365. X        return defpixel;
  1366. X    }
  1367. X    hard= exact;
  1368. X    if (!XAllocColor(_wd, cmap, &hard)) {
  1369. X        _wwarning("%s: can't allocate color cell", cname);
  1370. X        return defpixel;
  1371. X    }
  1372. X    return hard.pixel;
  1373. X}
  1374. X
  1375. X
  1376. X/* Return a gray pixmap */
  1377. X
  1378. XPixmap
  1379. X_w_gray() {
  1380. X#include <X11/bitmaps/gray>
  1381. X/* defines gray_bits, gray_width, gray_height */
  1382. X    
  1383. X    static Pixmap gray;
  1384. X    
  1385. X    if (gray == 0) {
  1386. X        gray= XCreatePixmapFromBitmapData(_wd,
  1387. X            RootWindowOfScreen(_ws),
  1388. X            gray_bits, gray_width, gray_height,
  1389. X            BlackPixelOfScreen(_ws),
  1390. X            WhitePixelOfScreen(_ws),
  1391. X            DefaultDepthOfScreen(_ws));
  1392. X    }
  1393. X    
  1394. X    return gray;
  1395. X}
  1396. X
  1397. X
  1398. X/* Set the border pixmap of a window to a gray pattern */
  1399. X
  1400. Xvoid
  1401. X_w_setgrayborder(win)
  1402. X    WINDOW *win;
  1403. X{
  1404. X    XSetWindowBorderPixmap(_wd, win->wo.wid, _w_gray());
  1405. X}
  1406. X
  1407. X
  1408. X/* Create a Graphics Context using the given Window and Font ids.
  1409. X   Don't set the font if Font id is zero.
  1410. X   The plane mask is set to the XOR of the fg and bg colors;
  1411. X   if the window bg color is the same as the GC bg color,
  1412. X   this makes painting, erasing and XOR'ing possible
  1413. X   on color displays.  (On monochrome displays, one of the colors
  1414. X   is 1, one is 0, so the XOR is 1, which means all the planes we have.
  1415. X*/
  1416. X
  1417. XGC
  1418. X_wgcreate(wid, fid, fg, bg)
  1419. X    Window wid;
  1420. X    Font fid;
  1421. X    unsigned long fg, bg;
  1422. X{
  1423. X    int mask= GCForeground|GCBackground|GCPlaneMask;
  1424. X    XGCValues v;
  1425. X    
  1426. X    v.plane_mask= fg ^ bg;
  1427. X    v.foreground= fg;
  1428. X    v.background= bg;
  1429. X    if (fid != 0) {
  1430. X        v.font= fid;
  1431. X        mask |= GCFont;
  1432. X    }
  1433. X    return XCreateGC(_wd, wid, mask, &v);
  1434. X}
  1435. X
  1436. X
  1437. X/* Create a Window for a given windata struct and set its event mask.
  1438. X   If map is TRUE, also map it.
  1439. X   Initially, a window is not dirty (it'll get Expose events for that) */
  1440. X
  1441. Xbool
  1442. X_wcreate1(wp, parent, cursor, map, fg, bg, nowm)
  1443. X    struct windata *wp;
  1444. X    Window parent;
  1445. X    int cursor;
  1446. X    bool map;
  1447. X    unsigned long fg, bg;
  1448. X    bool nowm;
  1449. X{
  1450. X    XSetWindowAttributes attributes;
  1451. X    unsigned long valuemask=
  1452. X        CWBackPixel|CWBorderPixel|CWBitGravity|CWBackingStore;
  1453. X    
  1454. X    attributes.background_pixel= bg;
  1455. X    attributes.border_pixel= fg;
  1456. X    attributes.bit_gravity= NorthWestGravity;
  1457. X    if (nowm) {
  1458. X        attributes.override_redirect = 1;
  1459. X        valuemask |= CWOverrideRedirect;
  1460. X    }
  1461. X/*
  1462. X    attributes.backing_store= WhenMapped;
  1463. X*/
  1464. X    attributes.backing_store= NotUseful; /* Seems to be Harmful... */
  1465. X
  1466. X    if (cursor > 0) {
  1467. X        attributes.cursor= XCreateFontCursor(_wd, cursor);
  1468. X        valuemask |= CWCursor;
  1469. X    }
  1470. X    
  1471. X    /* We must subtract border width from x and y before
  1472. X       passing them to WCreateSimpleWindow, since
  1473. X       they refer to the upper left corner of the border! */
  1474. X    
  1475. X    wp->wid= XCreateWindow(
  1476. X            _wd,
  1477. X            parent,
  1478. X            wp->x - wp->border,    /* x */
  1479. X            wp->y - wp->border,    /* y */
  1480. X            wp->width,
  1481. X            wp->height,
  1482. X            wp->border,        /* border width */
  1483. X            CopyFromParent,        /* depth */
  1484. X            InputOutput,        /* class */
  1485. X            CopyFromParent,        /* visual */
  1486. X            valuemask,
  1487. X            &attributes
  1488. X        );
  1489. X    if (!wp->wid) {
  1490. X        _werror("_wcreate: can't create (sub)Window");
  1491. X        return FALSE;
  1492. X    }
  1493. X    _wdebug(2, "_wcreate: wid=0x%x", wp->wid);
  1494. X    if (map)
  1495. X        XMapWindow(_wd, wp->wid);
  1496. X    wp->dirty= FALSE;
  1497. X    return TRUE;
  1498. X}
  1499. X
  1500. X
  1501. X/* Set the save-under property for a window given by a windata struct */
  1502. X
  1503. Xvoid
  1504. X_wsaveunder(wp, flag)
  1505. X    struct windata *wp;
  1506. X    Bool flag;
  1507. X{
  1508. X    static int saveUnder = -1;
  1509. X    XSetWindowAttributes attrs;
  1510. X    
  1511. X    /* The user may explicitly turn off save-unders by specifying
  1512. X        Stdwin*SaveUnder: off
  1513. X       since they are broken on some servers */
  1514. X    
  1515. X    if (saveUnder < 0) {
  1516. X        /* First time here: check resource database */
  1517. X        saveUnder = _wgetbool("saveUnder", "SaveUnder", 1);
  1518. X        if (!saveUnder)
  1519. X            _wdebug(1, "user doesn't want save-unders");
  1520. X    }
  1521. X    
  1522. X    if (!saveUnder)
  1523. X        return;
  1524. X    
  1525. X    attrs.save_under= flag;
  1526. X    XChangeWindowAttributes(_wd, wp->wid, CWSaveUnder, &attrs);
  1527. X}
  1528. X
  1529. X
  1530. X/* Set gravity for a window given by a windata struct */
  1531. X
  1532. Xstatic void
  1533. X_wgravity(wp, grav)
  1534. X    struct windata *wp;
  1535. X    int grav;
  1536. X{
  1537. X    XSetWindowAttributes attrs;
  1538. X    attrs.win_gravity= grav;
  1539. X    XChangeWindowAttributes(_wd, wp->wid, CWWinGravity, &attrs);
  1540. X}
  1541. X
  1542. X
  1543. X/* Move and resize a window given by a windata struct */
  1544. X
  1545. Xvoid
  1546. X_wmove(wp)
  1547. X    struct windata *wp;
  1548. X{
  1549. X    XMoveResizeWindow(_wd, wp->wid,
  1550. X        wp->x - wp->border, wp->y - wp->border, wp->width, wp->height);
  1551. X}
  1552. X
  1553. X
  1554. X/* (Re)compute the sizes and positions of all subwindows.
  1555. X   If aflag is set, the application subwindow is resized as well.
  1556. X   Note a check (in SZ) to prevent windows ever to get a size <= 0 */
  1557. X
  1558. Xstatic
  1559. X_wsizesubwins(win)
  1560. X    WINDOW *win;
  1561. X{
  1562. X    int bmargin= win->wi.height - win->doc.height - win->wa.y;
  1563. X    int rmargin= win->wi.width - win->doc.width - win->wa.x;
  1564. X
  1565. X#define SZ(elem, nx, ny, nw, nh, nb) \
  1566. X        (win->elem.x= (nx), \
  1567. X        win->elem.y= (ny), \
  1568. X        win->elem.width= (nw) > 0 ? (nw) : 1, \
  1569. X        win->elem.height= (nh) > 0 ? (nh) : 1, \
  1570. X        win->elem.border= (nb))
  1571. X
  1572. X    /* Interior window in the middle */
  1573. X    SZ(wi, LMARGIN, TMARGIN,
  1574. X        win->wo.width - LMARGIN - RMARGIN,
  1575. X        win->wo.height - TMARGIN - BMARGIN, 0);
  1576. X    /* Menu bar at the top */
  1577. X    SZ(mbar, 0, 0, win->wo.width, TMARGIN - IBORDER, IBORDER);
  1578. X    /* Vbar left */
  1579. X    SZ(vbar, 0, win->wi.y, LMARGIN - IBORDER, win->wi.height, IBORDER);
  1580. X    /* Hbar at bottom (top would be ugly because of mbar) */
  1581. X    SZ(hbar, win->wi.x, win->wo.height - BMARGIN + IBORDER,
  1582. X        win->wi.width, BMARGIN - IBORDER, IBORDER);
  1583. X
  1584. X#undef SZ
  1585. X    
  1586. X    /* The document window (wa) is sized differently.
  1587. X       If it fits in the window, it is made the same size
  1588. X       and aligned at (0,0) no questions asked.
  1589. X       Otherwise, it is moved so that the window never shows more
  1590. X       outside it than before (if at all possible). */
  1591. X    
  1592. X    if (win->doc.width <= win->wi.width) {
  1593. X        win->wa.x= IMARGIN;
  1594. X        win->wa.width= win->wi.width;
  1595. X    }
  1596. X    else {
  1597. X        CLIPMIN(rmargin, IMARGIN);
  1598. X        CLIPMIN(win->wa.x, win->wi.width - win->wa.width - rmargin);
  1599. X        CLIPMAX(win->wa.x, IMARGIN);
  1600. X        win->wa.width= win->doc.width;
  1601. X        CLIPMIN(win->wa.width, win->wi.width - win->wa.x);
  1602. X    }
  1603. X    if (win->doc.height <= win->wi.height) {
  1604. X        win->wa.y= 0;
  1605. X        win->wa.height= win->wi.height;
  1606. X    }
  1607. X    else {
  1608. X        CLIPMIN(bmargin, 0);
  1609. X        CLIPMIN(win->wa.y, win->wi.height - win->wa.height - bmargin);
  1610. X        CLIPMAX(win->wa.y, 0);
  1611. X        win->wa.height= win->doc.height;
  1612. X        CLIPMIN(win->wa.height, win->wi.height - win->wa.y);
  1613. X    }
  1614. X}
  1615. X
  1616. X
  1617. X/* Create the permanently visible subwindows.
  1618. X   Return TRUE if all creations succeeded.
  1619. X   The inner window is created after all bars, so it lies on top,
  1620. X   and will receive clicks in its border */
  1621. X
  1622. Xstatic bool
  1623. X_wmakesubwins(win)
  1624. X    WINDOW *win;
  1625. X{
  1626. X    Window w= win->wo.wid;
  1627. X    unsigned long fg= win->fgo, bg= win->bgo;
  1628. X    
  1629. X    _wsizesubwins(win);
  1630. X    if (!(    _wcreate(&win->mbar, w, XC_arrow, TRUE, fg, bg) &&
  1631. X        _wcreate(&win->vbar, w, XC_sb_v_double_arrow, TRUE, fg, bg) &&
  1632. X        _wcreate(&win->hbar, w, XC_sb_h_double_arrow, TRUE, fg, bg) &&
  1633. X        _wcreate(&win->wi, w, 0, TRUE, fg, bg) &&
  1634. X        _wcreate(&win->wa, win->wi.wid, XC_crosshair, TRUE,
  1635. X            fg, win->bga)))
  1636. X        return FALSE;
  1637. X    _wgravity(&win->hbar, SouthWestGravity);
  1638. X    return TRUE;
  1639. X}
  1640. X
  1641. X
  1642. X/* Resize all subwindows and move them to their new positions.
  1643. X   The application and current menu windows (WA, MWIN) are not resized.
  1644. X   The application window may be moved, however, to prevent exposing
  1645. X   parts outside the document that weren't visible earlier. */
  1646. X
  1647. Xvoid
  1648. X_wmovesubwins(win)
  1649. X    WINDOW *win;
  1650. X{
  1651. X    int i;
  1652. X    _wsizesubwins(win);
  1653. X    
  1654. X    for (i= 1; i <= WA; ++i)
  1655. X        _wmove(&win->subw[i]);
  1656. X    
  1657. X    /* Invalidate scroll bars after a resize */
  1658. X    win->hbar.dirty= win->vbar.dirty= _w_dirty= TRUE;
  1659. X}
  1660. X
  1661. X
  1662. X/* Set normal event masks for all (sub)Windows of a WINDOW */
  1663. X
  1664. Xvoid
  1665. X_wsetmasks(win)
  1666. X    WINDOW *win;
  1667. X{
  1668. X    int i;
  1669. X    
  1670. X    XSelectInput(_wd, win->wo.wid, OUTER_MASK);
  1671. X    for (i= 1; i <= WA; ++i) {
  1672. X        if (win->subw[i].wid != 0)
  1673. X            XSelectInput(_wd, win->subw[i].wid,
  1674. X                (i == WI) ? NoEventMask : OTHER_MASK);
  1675. X    }
  1676. X}
  1677. X
  1678. X
  1679. X/* Generate any pending size event. */
  1680. X
  1681. Xbool
  1682. X_w_doresizes(ep)
  1683. X    EVENT *ep;
  1684. X{
  1685. X    int i;
  1686. X
  1687. X    for (i= nwins; --i >= 0; ) {
  1688. X        WINDOW *win= winlist[i];
  1689. X        if (win->resized) {
  1690. X            win->resized= FALSE;
  1691. X            ep->type= WE_SIZE;
  1692. X            ep->window= win;
  1693. X            if (i == 0)
  1694. X                _w_resized= FALSE;
  1695. X            return TRUE;
  1696. X        }
  1697. X    }
  1698. X    _w_resized= FALSE;
  1699. X    return FALSE;
  1700. X}
  1701. X
  1702. X
  1703. X/* Perform any pending window updates.
  1704. X   If the application subwindow needs an update,
  1705. X   either call its draw procedure or generate a WE_DRAW event
  1706. X   in the given event record (and then stop).
  1707. X   Return TRUE if an event was generated */
  1708. X
  1709. Xbool
  1710. X_w_doupdates(ep)
  1711. X    EVENT *ep;
  1712. X{
  1713. X    int i;
  1714. X
  1715. X    for (i= nwins; --i >= 0; ) {
  1716. X        if (update(winlist[i], ep)) {
  1717. X            if (i == 0)
  1718. X                _w_dirty= FALSE;
  1719. X            return TRUE;
  1720. X        }
  1721. X    }
  1722. X    _w_dirty= FALSE;
  1723. X    return FALSE;
  1724. X}
  1725. X
  1726. Xvoid
  1727. Xwupdate(win)
  1728. X    WINDOW *win;
  1729. X{
  1730. X    (void) update(win, (EVENT *)NULL);
  1731. X}
  1732. X
  1733. X/* Update any parts of a window that need updating.
  1734. X   If the application window needs redrawing and there is no drawproc
  1735. X   and the 'ep' argument is non-nil,
  1736. X   construct a DRAW event and return TRUE. */
  1737. X
  1738. Xstatic bool
  1739. Xupdate(win, ep)
  1740. X    WINDOW *win;
  1741. X    EVENT *ep;
  1742. X{
  1743. X    bool ret= FALSE;
  1744. X    
  1745. X    if (win->mbar.dirty)
  1746. X        _wdrawmbar(win);
  1747. X    if (win->hbar.dirty)
  1748. X        _wdrawhbar(win);
  1749. X    if (win->vbar.dirty)
  1750. X        _wdrawvbar(win);
  1751. X    win->mbar.dirty= win->hbar.dirty= win->vbar.dirty= FALSE;
  1752. X    /* wi and wo have nothing that can be drawn! */
  1753. X    
  1754. X    if (win->wa.dirty && (win->drawproc != NULL || ep != NULL)) {
  1755. X        XRectangle clip;
  1756. X        int left, top, right, bottom;
  1757. X        XClipBox(win->inval, &clip);
  1758. X        left= clip.x;
  1759. X        top= clip.y;
  1760. X        right= left + clip.width;
  1761. X        bottom= top + clip.height;
  1762. X        CLIPMIN(left, -win->wa.x);
  1763. X        CLIPMIN(top, -win->wa.y);
  1764. X        CLIPMAX(right, win->wi.width - win->wa.x);
  1765. X        CLIPMAX(bottom, win->wi.height - win->wa.y);
  1766. X        _wdebug(3, "clip: (%d,%d) to (%d,%d)",
  1767. X            left, top, right, bottom);
  1768. X        if (left < right && top < bottom) {
  1769. X            _whidecaret(win);
  1770. X            if (win->drawproc != NULL) {
  1771. X                /* A bug in X11R2 XSetRegion prevents this
  1772. X                   from working: */
  1773. X#ifndef R2
  1774. X                /* Version for R3 or later */
  1775. X                XSetRegion(_wd, win->gca, win->inval);
  1776. X#else
  1777. X                /* Version for R2 */
  1778. X                XSetClipRectangles(_wd, win->gca,
  1779. X                    0, 0, &clip, 1, Unsorted);
  1780. X#endif
  1781. X                wbegindrawing(win);
  1782. X                werase(left, top, right, bottom);
  1783. X                (*win->drawproc)(win,
  1784. X                    left, top, right, bottom);
  1785. X                wenddrawing(win);
  1786. X                XSetClipMask(_wd, win->gca, (Pixmap)None);
  1787. X            }
  1788. X            else {
  1789. X                XClearArea(_wd, win->wa.wid,
  1790. X                    clip.x, clip.y,
  1791. X                    clip.width, clip.height, FALSE);
  1792. X                ep->type= WE_DRAW;
  1793. X                ep->window= win;
  1794. X                ep->u.area.left= left;
  1795. X                ep->u.area.top= top;
  1796. X                ep->u.area.right= right;
  1797. X                ep->u.area.bottom= bottom;
  1798. X                ret= TRUE;
  1799. X            }
  1800. X            _wshowcaret(win);
  1801. X        }
  1802. X        XDestroyRegion(win->inval);
  1803. X        win->inval= XCreateRegion();
  1804. X        win->wa.dirty= FALSE;
  1805. X    }
  1806. X    return ret;
  1807. X}
  1808. X
  1809. X
  1810. X/* Close a window */
  1811. X
  1812. Xvoid
  1813. Xwclose(win)
  1814. X    WINDOW *win;
  1815. X{
  1816. X    int i;
  1817. X    for (i= 0; i < nwins; ++i) {
  1818. X        if (winlist[i] == win)
  1819. X            break;
  1820. X    }
  1821. X    if (i >= nwins) {
  1822. X        _werror("wclose: unknown window");
  1823. X        return;
  1824. X    }
  1825. X    L_REMOVE(nwins, winlist, WINDOW *, i);
  1826. X    _w_deactivate(win);
  1827. X    _w_delmenus(win);
  1828. X    XFreeGC(_wd, win->gc);
  1829. X    XFreeGC(_wd, win->gca);
  1830. X    XDestroyWindow(_wd, win->wo.wid);
  1831. X    XFlush(_wd); /* Make the effect immediate */
  1832. X    FREE(win);
  1833. X}
  1834. X
  1835. X
  1836. X/* Change a window's title */
  1837. X
  1838. Xvoid
  1839. Xwsettitle(win, title)
  1840. X    WINDOW *win;
  1841. X    char *title;
  1842. X{
  1843. X    XStoreName(_wd, win->wo.wid, title);
  1844. X    /* The icon name will not change */
  1845. X}
  1846. X
  1847. X
  1848. X/* Return a window's current title -- straight from the window property */
  1849. X
  1850. Xchar *
  1851. Xwgettitle(win)
  1852. X    WINDOW *win;
  1853. X{
  1854. X    static char *title = NULL;
  1855. X    
  1856. X    if (title != NULL)
  1857. X        free(title); /* Free result of previous call */
  1858. X    title = NULL; /* Just in case */
  1859. X    if (!XFetchName(_wd, win->wo.wid, &title))
  1860. X        _wwarning("wgettitle: no title set");
  1861. X    return title;
  1862. X}
  1863. X
  1864. X
  1865. X/* Change a window's icon name */
  1866. X
  1867. Xvoid
  1868. Xwseticontitle(win, title)
  1869. X    WINDOW *win;
  1870. X    char *title;
  1871. X{
  1872. X    XSetIconName(_wd, win->wo.wid, title);
  1873. X}
  1874. X
  1875. X
  1876. X/* Return a window's current icon name -- straight from the window property */
  1877. X
  1878. Xchar *
  1879. Xwgeticontitle(win)
  1880. X    WINDOW *win;
  1881. X{
  1882. X    static char *title = NULL;
  1883. X    
  1884. X    if (title != NULL)
  1885. X        free(title); /* Free result of previous call */
  1886. X    title = NULL; /* Just in case */
  1887. X    if (!XGetIconName(_wd, win->wo.wid, &title))
  1888. X        _wdebug(1, "wgeticontitle: no icon name set");
  1889. X        /* This may occur normally so don't make it a warning */
  1890. X    return title;
  1891. X}
  1892. X
  1893. X
  1894. X/* Get a window's size.
  1895. X   This is really the size of the visible part of the document. */
  1896. X
  1897. Xvoid
  1898. Xwgetwinsize(win, pwidth, pheight)
  1899. X    WINDOW *win;
  1900. X    int *pwidth, *pheight;
  1901. X{
  1902. X    *pwidth= win->wi.width - IMARGIN;
  1903. X    *pheight= win->wi.height;
  1904. X}
  1905. X
  1906. X
  1907. X/* Get a window's position relative to the root */
  1908. X
  1909. Xvoid
  1910. Xwgetwinpos(win, ph, pv)
  1911. X    WINDOW *win;
  1912. X    int *ph, *pv;
  1913. X{
  1914. X    Window child;
  1915. X    
  1916. X    if (!XTranslateCoordinates(    _wd,
  1917. X                    win->wo.wid,
  1918. X                    RootWindowOfScreen(_ws),
  1919. X                    0, 0,
  1920. X                    ph, pv,
  1921. X                    &child)) {
  1922. X        
  1923. X        _wwarning("wgetwinpos: XTranslateCoordinates failed");
  1924. X        *ph = 0;
  1925. X        *pv = 0;
  1926. X    }
  1927. X}
  1928. X
  1929. X
  1930. X/* "Change" part of a document, i.e., post a WE_DRAW event */
  1931. X
  1932. Xvoid
  1933. Xwchange(win, left, top, right, bottom)
  1934. X    WINDOW *win;
  1935. X    int left, top, right, bottom;
  1936. X{
  1937. X    _wdebug(3, "wchange: %d %d %d %d", left, top, right, bottom);
  1938. X    if (left < right && top < bottom) {
  1939. X        XRectangle r;
  1940. X        r.x= left;
  1941. X        r.y= top;
  1942. X        r.width= right - left;
  1943. X        r.height= bottom - top;
  1944. X        XUnionRectWithRegion(&r, win->inval, win->inval);
  1945. X        win->wa.dirty= TRUE;
  1946. X        _w_dirty= TRUE;
  1947. X    }
  1948. X}
  1949. X
  1950. X
  1951. X/* "Scroll" part of a document, i.e., copy bits and erase the place
  1952. X   where they came from.  May cause WE_DRAW events if source bits are
  1953. X   covered. */
  1954. X
  1955. Xvoid
  1956. Xwscroll(win, left, top, right, bottom, dh, dv)
  1957. X    WINDOW *win;
  1958. X    int left, top, right, bottom;
  1959. X    int dh, dv;
  1960. X{
  1961. X    int src_x= left, src_y= top;
  1962. X    int dest_x= left, dest_y= top;
  1963. X    int width= right - left - ABS(dh);
  1964. X    int height= bottom - top - ABS(dv);
  1965. X    
  1966. X    if (dh == 0 && dv == 0)
  1967. X        return;
  1968. X    
  1969. X    if (dh < 0)
  1970. X        src_x += -dh;
  1971. X    else
  1972. X        dest_x += dh;
  1973. X    if (dv < 0)
  1974. X        src_y += -dv;
  1975. X    else
  1976. X        dest_y += dv;
  1977. X    
  1978. X    _wdebug(2, "wscroll: src(%d,%d)size(%d,%d)dest(%d,%d)",
  1979. X        src_x, src_y, width, height, dest_x, dest_y);
  1980. X    _whidecaret(win);
  1981. X    XCopyArea(_wd, win->wa.wid, win->wa.wid, win->gca,
  1982. X        src_x, src_y, width, height, dest_x, dest_y);
  1983. X    _wshowcaret(win);
  1984. X    
  1985. X    if (XRectInRegion(win->inval, left, top, right-left, bottom-top)
  1986. X                            != RectangleOut) {
  1987. X        /* Scroll the overlap between win->inval and the
  1988. X           scrolled rectangle:
  1989. X            scroll := <the entire scrolling rectangle>
  1990. X            overlap := inval * scroll
  1991. X            inval -:= overlap
  1992. X            shift overlap by (dh, dv)
  1993. X            overlap := overlap * scroll
  1994. X            inval +:= overlap
  1995. X        */
  1996. X        Region scroll = XCreateRegion();
  1997. X        Region overlap = XCreateRegion();
  1998. X        XRectangle r;
  1999. X        r.x = left;
  2000. X        r.y = top;
  2001. X        r.width = right-left;
  2002. X        r.height = bottom-top;
  2003. X        XUnionRectWithRegion(&r, scroll, scroll);
  2004. X        XIntersectRegion(win->inval, scroll, overlap);
  2005. X        XSubtractRegion(win->inval, overlap, win->inval);
  2006. X        XOffsetRegion(overlap, dh, dv);
  2007. X        XIntersectRegion(overlap, scroll, overlap);
  2008. X        XUnionRegion(win->inval, overlap, win->inval);
  2009. X        XDestroyRegion(overlap);
  2010. X        XDestroyRegion(scroll);
  2011. X
  2012. X        /* There's still a bug left: exposure events in the queue
  2013. X           (like GraphicsExposures caused be previous scrolls!)
  2014. X           should be offset as well, bu this is too complicated
  2015. X           to fix right now... */
  2016. X    }
  2017. X    
  2018. X    /* Clear the bits scrolled in */
  2019. X    
  2020. X    if (dh > 0)
  2021. X        XClearArea(_wd, win->wa.wid,
  2022. X            left, top, dh, bottom-top, FALSE);
  2023. X    else if (dh < 0)
  2024. X        XClearArea(_wd, win->wa.wid,
  2025. X            right+dh, top, -dh, bottom-top, FALSE);
  2026. X    if (dv > 0)
  2027. X        XClearArea(_wd, win->wa.wid,
  2028. X            left, top, right-left, dv, FALSE);
  2029. X    else if (dv < 0)
  2030. X        XClearArea(_wd, win->wa.wid,
  2031. X            left, bottom+dv, right-left, -dv, FALSE);
  2032. X}
  2033. X
  2034. X
  2035. X/* Change the "origin" of a window (position of document, really) */
  2036. X
  2037. Xvoid
  2038. Xwsetorigin(win, orgh, orgv)
  2039. X    WINDOW *win;
  2040. X    int orgh, orgv;
  2041. X{
  2042. X    bool moveit= FALSE;
  2043. X    
  2044. X    CLIPMIN(orgh, 0);
  2045. X    CLIPMIN(orgv, 0);
  2046. X    if (win->wa.x != -orgh) {
  2047. X        win->hbar.dirty= moveit= TRUE;
  2048. X        win->wa.x= -orgh;
  2049. X    }
  2050. X    if (win->wa.y != -orgv) {
  2051. X        win->vbar.dirty= moveit= TRUE;
  2052. X        win->wa.y= -orgv;
  2053. X    }
  2054. X    if (moveit)
  2055. X        XMoveWindow(_wd, win->wa.wid, -orgh, -orgv);
  2056. X}
  2057. X
  2058. X
  2059. X/* Get the "origin" (see above) of a window */
  2060. X
  2061. Xvoid
  2062. Xwgetorigin(win, ph, pv)
  2063. X    WINDOW *win;
  2064. X    int *ph, *pv;
  2065. X{
  2066. X    *ph= -win->wa.x;
  2067. X    CLIPMIN(*ph, 0);
  2068. X    *pv= -win->wa.y;
  2069. X}
  2070. X
  2071. X
  2072. X/* Set the document size.  Zero means don't use a scroll bar */
  2073. X
  2074. Xvoid
  2075. Xwsetdocsize(win, width, height)
  2076. X    WINDOW *win;
  2077. X    int width, height;
  2078. X{
  2079. X    bool dirty= FALSE;
  2080. X    
  2081. X    CLIPMIN(width, 0);
  2082. X    CLIPMIN(height, 0);
  2083. X    if (win->doc.width != width) {
  2084. X        win->doc.width= width;
  2085. X        if (width <= win->wo.width - IMARGIN) {
  2086. X            win->wa.x= IMARGIN;
  2087. X            win->wa.width= win->wi.width;
  2088. X        }
  2089. X        else {
  2090. X            win->wa.width= width;
  2091. X            CLIPMIN(win->wa.width, win->wi.width - win->wa.x);
  2092. X        }
  2093. X        win->hbar.dirty= dirty= TRUE;
  2094. X    }
  2095. X    if (win->doc.height != height) {
  2096. X        win->doc.height= height;
  2097. X        if (height <= win->wo.height) {
  2098. X            win->wa.y= 0;
  2099. X            win->wa.height= win->wi.height;
  2100. X        }
  2101. X        else {
  2102. X            win->wa.height= height;
  2103. X        }
  2104. X        win->vbar.dirty= dirty= TRUE;
  2105. X    }
  2106. X    if (dirty) {
  2107. X        _w_dirty= TRUE;
  2108. X        _wmove(&win->wa);
  2109. X    }
  2110. X}
  2111. X
  2112. X
  2113. X/* Return the document size last set by wsetdocsize() */
  2114. X
  2115. Xvoid
  2116. Xwgetdocsize(win, pwidth, pheight)
  2117. X    WINDOW *win;
  2118. X    int *pwidth, *pheight;
  2119. X{
  2120. X    *pwidth = win->doc.width;
  2121. X    *pheight = win->doc.height;
  2122. X}
  2123. X
  2124. X
  2125. X/* Change the cursor for a window */
  2126. X
  2127. Xvoid
  2128. Xwsetwincursor(win, cursor)
  2129. X    WINDOW *win;
  2130. X    CURSOR *cursor;
  2131. X{
  2132. X    Cursor c;
  2133. X    if (cursor == NULL)
  2134. X        c = None;
  2135. X    else
  2136. X        c = (Cursor) cursor;
  2137. X    XDefineCursor(_wd, win->wa.wid, c);
  2138. X}
  2139. X
  2140. X
  2141. X/* Scroll the document in the window to ensure that the given rectangle
  2142. X   is visible, if at all possible.  Don't scroll more than necessary. */
  2143. X
  2144. Xvoid
  2145. Xwshow(win, left, top, right, bottom)
  2146. X    WINDOW *win;
  2147. X    int left, top, right, bottom;
  2148. X{
  2149. X    int orgh= -win->wa.x;
  2150. X    int orgv= -win->wa.y;
  2151. X    int winwidth, winheight;
  2152. X    int extrah, extrav;
  2153. X    
  2154. X    _wdebug(3, "wshow: %d %d %d %d", left, top, right, bottom);
  2155. X    
  2156. X    wgetwinsize(win, &winwidth, &winheight);
  2157. X    
  2158. X    if (left >= orgh &&
  2159. X        top >= orgv &&
  2160. X        right <= orgh + winwidth &&
  2161. X        bottom <= orgv + winheight)
  2162. X        return; /* Already visible */
  2163. X    
  2164. X    extrah= (winwidth - (right - left)) / 2;
  2165. X    CLIPMAX(extrah, win->doc.width - right);
  2166. X    CLIPMIN(extrah, 0);
  2167. X    orgh= right + extrah - winwidth;
  2168. X    CLIPMAX(orgh, left);
  2169. X    CLIPMIN(orgv, 0);
  2170. X    
  2171. X    extrav= (winheight - (bottom - top)) / 2;
  2172. X    CLIPMAX(extrav, win->doc.height - bottom);
  2173. X    CLIPMIN(extrav, 0);
  2174. X    orgv= bottom + extrav - winheight;
  2175. X    CLIPMAX(orgv, top);
  2176. X    CLIPMIN(orgv, 0);
  2177. X    
  2178. X    wsetorigin(win, orgh, orgv);
  2179. X}
  2180. X
  2181. X
  2182. X/* Sound the bell (beep) */
  2183. X
  2184. Xvoid
  2185. Xwfleep()
  2186. X{
  2187. X    XBell(_wd, 0);
  2188. X}
  2189. X
  2190. X
  2191. X/* Helper functions for the menu mananger: */
  2192. X
  2193. X_waddtoall(mp)
  2194. X    MENU *mp;
  2195. X{
  2196. X    int i;
  2197. X    
  2198. X    for (i= nwins; --i >= 0; )
  2199. X        wmenuattach(winlist[i], mp);
  2200. X}
  2201. X
  2202. X
  2203. X_wdelfromall(mp)
  2204. X    MENU *mp;
  2205. X{
  2206. X    int i;
  2207. X    
  2208. X    for (i= nwins; --i >= 0; )
  2209. X        wmenudetach(winlist[i], mp);
  2210. X}
  2211. X
  2212. X
  2213. X/* Helper function for the timer manager: */
  2214. X
  2215. XWINDOW *
  2216. X_wnexttimer()
  2217. X{
  2218. X    int i;
  2219. X    WINDOW *cand= NULL;
  2220. X    
  2221. X    for (i= nwins; --i >= 0; ) {
  2222. X        WINDOW *win= winlist[i];
  2223. X        long t= win->timer;
  2224. X        if (t != 0) {
  2225. X            if (cand == NULL || t < cand->timer)
  2226. X                cand= win;
  2227. X        }
  2228. X    }
  2229. X    return cand;
  2230. X}
  2231. X
  2232. X
  2233. X/* Delete all windows -- called by wdone() */
  2234. X
  2235. X_wkillwindows()
  2236. X{
  2237. X    while (nwins > 0)
  2238. X        wclose(winlist[nwins-1]);
  2239. X}
  2240. END_OF_FILE
  2241. if test 30704 -ne `wc -c <'Ports/x11/window.c'`; then
  2242.     echo shar: \"'Ports/x11/window.c'\" unpacked with wrong size!
  2243. fi
  2244. # end of 'Ports/x11/window.c'
  2245. fi
  2246. echo shar: End of archive 4 \(of 19\).
  2247. cp /dev/null ark4isdone
  2248. MISSING=""
  2249. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
  2250.     if test ! -f ark${I}isdone ; then
  2251.     MISSING="${MISSING} ${I}"
  2252.     fi
  2253. done
  2254. if test "${MISSING}" = "" ; then
  2255.     echo You have unpacked all 19 archives.
  2256.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2257. else
  2258.     echo You still need to unpack the following archives:
  2259.     echo "        " ${MISSING}
  2260. fi
  2261. ##  End of shell archive.
  2262. exit 0
  2263.