home *** CD-ROM | disk | FTP | other *** search
- /*
- winexpos.c 3/9/88
-
- % window exposure routines.
- by Ted.
-
- OWL 1.1
- Copyright (c) 1988, by Oakland Group, Inc.
- ALL RIGHTS RESERVED.
-
- Revision History:
- -----------------
- 8/17/88 jmd removed eNOMEM
- 9/12/88 jmd Added in and out data to objects
- 10/14/88 ted Moved wmgr_IsObscuredPixBox out to winobsc.c
- 12/09/88 ted Added ddisp_Cache/Flush calls for mouse.
- 12/11/88 ted Added dhard_Claim/Release calls for reentrancy.
- 3/15/89 ted Removed dmgr/wmgr args - now we use global structure.
- 6/23/89 jmd Added background window shadow support
- 8/10/89 ted Added shadow tiling.
- 9/01/89 jmd Changed kid enum to int
- */
-
- #include "oakhead.h"
- #include "disppriv.h"
- #include "vadecl.h"
-
- #define xDEBUG
- #ifdef DEBUG
- static int diddle = -1;
- #endif
- #define xDEBUG2
- #ifdef DEBUG2
- static boolean diddle2 = TRUE;
- #endif
- /* -------------------------------------------------------------------------- */
-
- /* ID's for the various subtiles ("kids") a tile is broken into. */
- /* Note: These values MUST match the diagram below */
-
- #define TOPBAR 0
- #define LEFTBOX 1
- #define TOPNIB 2 /* Only in shadow case */
- #define XSHADOW 3 /* Only in shadow case */
- #define RTBOX 4
- #define BOTNIB 5 /* Only in shadow case */
- #define YSHADOW 6 /* Only in shadow case */
- #define BOTBAR 7
- #define ALLDONE 8
-
- #define FIRSTKID TOPBAR
-
- /* This is an illustration of how a tile is split into sub-tiles around
- a window found underneath it:
-
- 0000000000000
- 1111WWWW22222
- 1111WWWW34444
- 1111WWWW34444
- 1111WWWW34444
- 5555566664444
- 7777777777777
- */
- typedef struct tile_struct {
- win_type win;
- int inlayer; /* flag for inlayer win in employed stack */
- int emsg; /* message to pass down */
- VOID *emsgdata; /* msgdata to pass down */
- int ikid; /* flag for gender of current kid */
- struct tile_struct *dad;
- struct tile_struct *kid;
- opbox box; /* box of this tile */
- opcoord boxtop; /* falling ceiling of box to use */
- opbox winbox; /* box of tile window clipped against its parent windows */
- opcoord rtshad; /* clipped remnant of right shadow */
- opcoord botshad; /* clipped remnant of bottom shadow */
- } *tile_type;
-
- /* -------------------------------------------------------------------------- */
- OSTATIC boolean OWLPRIV tile_KidCreate(_arg4(VOID *, tile_type, win_type, win_type));
- OSTATIC tile_type OWLPRIV tile_Create(_arg2(VOID *, tile_type));
-
- #define tile_Free(td, tile) \
- va_freeelem((varray)(td), (va_index) va_getelemtag((varray)(td), tile))
- /* -------------------------------------------------------------------------- */
-
- void win_Expose(win, msg, emsgdata)
- win_type win;
- int msg;
- VOID *emsgdata;
- /*
- Exposes all unobscured parts of win (but not border).
- */
- {
- opbox tbox;
-
- if (win == NULL) {
- return;
- }
- tbox.xmin = win_GetXmin(win);
- tbox.ymin = win_GetYmin(win);
- tbox.xmax = tbox.xmin + win_GetPixWidth(win);
- tbox.ymax = tbox.ymin + win_GetPixHeight(win);
-
- wmgr_ExposePixBox(win, NULL, &tbox, msg, emsgdata);
- }
- /* -------------------------------------------------------------------------- */
-
- void win_ExposePixBox(win, relboxp, msg, emsgdata)
- win_type win;
- opbox *relboxp;
- int msg;
- VOID *emsgdata;
- /*
- Exposes all unobscured parts of win in relboxp.
- Note that relboxp is relative to the window.
- */
- {
- opbox tbox;
-
- if (win == NULL) {
- return;
- }
- opbox_copy(&tbox, relboxp);
- opbox_trans(&tbox, win_GetXmin(win), win_GetYmin(win));
-
- wmgr_ExposePixBox(win, NULL, &tbox, msg, emsgdata);
- }
- /* -------------------------------------------------------------------------- */
-
- boolean OWLPRIV wmgr_ExposePixBox(topwin, botwin, boxp, exposemsg, emsgdata)
- win_type topwin; /* window to expose equal to or below */
- win_type botwin; /* window to not expose equal to or below */
- opbox *boxp; /* box within which to do the exposure */
- int exposemsg; /* do-what flag to pass to exposefunc */
- VOID *emsgdata;
- /*
- Finds all the rectangular pieces of windows that combine to tile the 'boxp'.
- Note that boxp is relative to the whole display, not any window.
- For each piece belonging to a window in the employed list equal to or
- below 'topwin' and above 'botwin, calls that window with 'exposemsg'
- and the coordinates of the exposed piece of window.
- */
- {
- tile_type tile, ttile;
- ptd_struct ptdata;
- #ifdef DEBUG
- int ididd;
- #endif
-
- owl_Assert(disp_Ok(), OE_WE_DISP);
-
- owl_Assert(curr_wmgr->tilerdata != NULL, OE_WE_TDATA);
-
- /* Set up starting conditions */
- tile = tile_Create(curr_wmgr->tilerdata, NULL); /* dad tile */
- if (tile == NULL) {
- return(FALSE);
- }
- hard_Claim(); /* Here for re-entrancy protection */
-
- tile->win = win_GetBelow(curr_wmgr->employedhead); /* init top tile win */
- if (topwin == curr_wmgr->employedhead) {
- topwin = win_GetBelow(curr_wmgr->employedhead);
- }
-
- /* Set up coords: box clipped to display */
- opbox_copy(&tile->box, boxp);
- if (opbox_empty(&tile->box) || !disp_clipbox(&tile->box)) {
- tile_Free(curr_wmgr->tilerdata, tile); /* tile is empty to start out, so quit */
- hard_Release();
- return(TRUE);
- }
- tile->inlayer = FALSE;
- tile->emsg = exposemsg;
- tile->emsgdata = emsgdata;
-
- disp_Cache();
-
- /* Recurse through the stack of windows until done */
- for (;;) {
- if (tile_KidCreate(curr_wmgr->tilerdata, tile, topwin, botwin)) {
- tile = tile->kid; /* Do kid next time around loop */
- continue;
- }
- /* No kids left - end of this family line - draw tile then free it */
- /* Note: tile can have shadow children even w/its window obscured */
- if (tile->inlayer && !opbox_empty(&tile->winbox)) {
- #ifdef DEBUG
- /* every time we get a tile, diddle it until a keystroke comes */
- if (diddle &&
- (tile->emsg == WINM_PAINT || tile->emsg == WINM_SHADOW)) {
- for (ididd = diddle; ididd != 0; ) {
- ptdata.win = disp_GetDispWin();
- ptdata.relboxp = &tile->winbox;
-
- ptd_Clear(&ptdata, 0);
- ptd_Clear(&ptdata, 7);
- if (ididd == -1) {
- if (kb_Check()) {
- kb_Read();
- break;
- }
- }
- else ididd--;
- }
- }
- #endif
- if (tile->win == NULL) { /* if no window, just clear box */
- if (tile->emsg == WINM_PAINT || tile->emsg == WINM_SHADOW) {
- ptdata.win = disp_GetDispWin();
- ptdata.relboxp = &tile->winbox;
- ptdata.emsgdata = tile->emsgdata;
-
- ptd_Clear(&ptdata, (tile->emsg == WINM_PAINT) ?
- win_GetBgColor(ptdata.win) :
- disp_GetAttrBgColor(win_GetShadowAttr(ptdata.win)));
- }
- }
- else { /* Plot piece of window */
- ptdata.win = tile->win;
- opbox_trans(&tile->winbox, -win_GetXmin(tile->win),
- -win_GetYmin(tile->win));
- ptdata.relboxp = &tile->winbox;
- ptdata.emsgdata = tile->emsgdata;
- win_Do(tile->win, tile->emsg, &ptdata, NULL);
- }
- }
- /* Free the current leaf; back up the tree one node */
- ttile = tile;
- tile = tile->dad;
- tile_Free(curr_wmgr->tilerdata, ttile);
-
- /* If back to top of tree, quit */
- if (tile == NULL) {
- break;
- }
- tile->kid = NULL;
- }
- disp_Flush();
- hard_Release();
- return(TRUE);
- }
- /* -------------------------------------------------------------------------- */
-
- static boolean OWLPRIV tile_KidCreate(td, tile, topwin, botwin)
- VOID *td;
- tile_type tile;
- win_type topwin;
- win_type botwin;
- /*
- Make a new kid tile for tile, containing a sub_rectangle.
- Shaves off parts of tile box that are not in tile win and gives the shavings
- to the kids.
- Skip over non-intersecting windows, but check them for the 'inlayer' flag.
- Return FALSE if no kid can be created for the given tile (either
- the tile is completely within the next window under it, or the end of
- the employed window list has been reached. (The latter should never happen).
- */
- {
- tile_type newtile;
- opbox kidbox;
- opcoord botshad, rtshad;
- opcoord topshad, lshad;
- boolean doshad, gotone;
- opcoord newtop;
- #ifdef DEBUG2
- ptd_struct ptdata;
- opbox tbox, tsbox;
- #endif
-
- /* If this tile is virgin, find a suitable window for it. */
- if (tile->ikid == FIRSTKID) {
- /* Skip over non-intersecting windows, checking for inlayer */
- for (;;) {
- /* Set inlayer flag: */
- /* If topwin == NULL, last tile (VACUUM) is inlayer anyway. */
- if (tile->win == topwin) tile->inlayer = TRUE;
-
- /* If botwin == NULL, all tiles below or equal topwin are inlayer */
- if (tile->win == NULL) {
- opbox_copy(&tile->winbox, &tile->box);
- return(FALSE);
- }
- if (tile->win == botwin) {
- tile->inlayer = FALSE;
- return(FALSE);
- }
- /* Skip right past uninvolved windows - also set up tile->winbox */
-
- /* Only look at employed windows */
- if (win_IsEmployed(tile->win)) {
-
- doshad = (tile->emsg == WINM_PAINT || tile->emsg == WINM_SAVE ||
- tile->emsg == WINM_SCROLL || tile->emsg == WINM_CLEAR);
-
- /* Only look at windows not completely clipped by their parents */
- if (win_ParentClip(tile->win, &tile->winbox, doshad)) {
-
- /* Set up shadow dimensions; shadow only under certain messages */
- if (doshad) {
- rtshad = tile->winbox.xmax - win_pixboxp(tile->win)->xmax;
- if (rtshad < 0) rtshad = 0;
- else tile->winbox.xmax -= rtshad;
-
- botshad = tile->winbox.ymax - win_pixboxp(tile->win)->ymax;
- if (botshad < 0) botshad = 0;
- else tile->winbox.ymax -= botshad;
-
- lshad = win_pixboxp(tile->win)->xmin +
- win_GetShadowX(tile->win) -
- tile->winbox.xmin;
- if (lshad < 0) lshad = 0;
-
- topshad = win_pixboxp(tile->win)->ymin +
- win_GetShadowY(tile->win) -
- tile->winbox.ymin;
- if (topshad < 0) topshad = 0;
- }
- else rtshad = botshad = 0;
-
- /* Only look at windows at least partly inside this tile */
- opbox_copy(&kidbox, &tile->box);
-
- /* Test for winbox overlapping starting tile */
- gotone = (kidbox.xmin < tile->winbox.xmax &&
- kidbox.xmax > tile->winbox.xmin &&
- kidbox.ymin < tile->winbox.ymax &&
- kidbox.ymax > tile->winbox.ymin);
-
- /* Test for shadow box overlapping starting tile */
- if (gotone ||
- ((botshad != 0 || rtshad != 0) &&
- (kidbox.xmin < tile->winbox.xmax + rtshad &&
- kidbox.xmax > tile->winbox.xmin + lshad &&
- kidbox.ymin < tile->winbox.ymax + botshad &&
- kidbox.ymax > tile->winbox.ymin + topshad))) {
- #ifdef DEBUG2
- /* diddle the winbox and its shadow that we will be tiling. */
- if (diddle2 &&
- (tile->emsg == WINM_PAINT || tile->emsg == WINM_SHADOW)) {
- opbox_copy(&tbox, &tile->winbox);
- opbox_copy(&tsbox, &tbox);
- opbox_trans(&tsbox, rtshad, botshad);
- opbox_clipbox(&tile->box, &tbox);
- opbox_clipbox(&tile->box, &tsbox);
- for (;;) {
- ptdata.win = disp_GetDispWin();
-
- ptdata.relboxp = &tbox;
- ptd_Clear(&ptdata, 0);
- ptdata.relboxp = &tsbox;
- ptd_Clear(&ptdata, 0);
-
- ptdata.relboxp = &tbox;
- ptd_Clear(&ptdata, 1); /* blue */
- ptdata.relboxp = &tsbox;
- ptd_Clear(&ptdata, 1); /* blue */
-
- if (kb_Check()) {
- kb_Read();
- break;
- }
- }
- }
- #endif
- tile->boxtop = tile->box.ymin;
- tile->rtshad = rtshad;
- tile->botshad = botshad;
- break;
- }
- }
- }
- tile->win = win_GetBelow(tile->win); /* skip to next window. */
- }
- }
- else { /* If this tile has already had a kid, it must have a good window */
- opbox_copy(&kidbox, &tile->box);
-
- /* Set up shadow dimensions; shadow only under certain messages */
- doshad = (tile->emsg == WINM_PAINT || tile->emsg == WINM_SAVE ||
- tile->emsg == WINM_SCROLL || tile->emsg == WINM_CLEAR);
- if (doshad) {
- rtshad = tile->rtshad;
- botshad = tile->botshad;
- lshad = win_pixboxp(tile->win)->xmin + win_GetShadowX(tile->win) -
- tile->winbox.xmin;
- if (lshad < 0) lshad = 0;
- topshad = win_pixboxp(tile->win)->ymin + win_GetShadowY(tile->win) -
- tile->winbox.ymin;
- if (topshad < 0) topshad = 0;
- }
- else rtshad = botshad = 0;
- }
- /* Loop until a real subtile is found - find kid box. */
- newtop = tile->boxtop;
- for (gotone = FALSE; gotone == FALSE; tile->ikid++) {
- kidbox.ymin = tile->boxtop; /* keep this up to date as we go around again */
- if (tile->boxtop >= tile->box.ymax) {
- /* All done if we've squished the tile box to nothing */
- tile->ikid = ALLDONE;
- }
- switch (tile->ikid) {
- case TOPBAR:
- if (kidbox.ymin < tile->winbox.ymin) {
- /* There's a strip at the top */
- kidbox.ymax = tile->winbox.ymin;
- gotone = TRUE;
- }
- newtop = tile->winbox.ymin; /* Chop this to save later testing */
- break;
- case LEFTBOX:
- if (kidbox.xmin < tile->winbox.xmin &&
- kidbox.ymin < tile->winbox.ymax) {
- /* There's a strip at the left */
- kidbox.xmax = tile->winbox.xmin;
- if (kidbox.ymax > tile->winbox.ymax) {
- kidbox.ymax = tile->winbox.ymax;
- }
- gotone = TRUE;
- }
- break;
- case TOPNIB:
- if (topshad != 0) {
- if (kidbox.xmax > tile->winbox.xmax &&
- kidbox.ymin < tile->winbox.ymin + topshad) {
- /* There's a nib strip at the top right */
- kidbox.xmin = tile->winbox.xmax;
- if (kidbox.ymax > tile->winbox.ymin + topshad) {
- kidbox.ymax = tile->winbox.ymin + topshad;
- }
- gotone = TRUE;
- }
- newtop = tile->winbox.ymin + topshad; /* Chop this to save later testing */
- }
- break;
- case XSHADOW:
- if (rtshad != 0 &&
- kidbox.xmax > tile->winbox.xmax &&
- kidbox.ymin < tile->winbox.ymax) {
- /* There's a shadow strip at the right */
- if (kidbox.xmin < tile->winbox.xmax) {
- kidbox.xmin = tile->winbox.xmax;
- }
- if (kidbox.xmax > tile->winbox.xmax + rtshad) {
- kidbox.xmax = tile->winbox.xmax + rtshad;
- }
- if (kidbox.ymax > tile->winbox.ymax) {
- kidbox.ymax = tile->winbox.ymax;
- }
- gotone = TRUE;
- }
- break;
- case RTBOX:
- if (kidbox.xmax > tile->winbox.xmax + rtshad) {
- /* There's a strip at the right */
- kidbox.xmin = tile->winbox.xmax + rtshad;
- if (kidbox.ymax > tile->winbox.ymax + botshad) {
- kidbox.ymax = tile->winbox.ymax + botshad;
- }
- gotone = TRUE;
- }
- newtop = tile->winbox.ymax; /* Chop this to save later testing */
- break;
- case BOTNIB:
- if (botshad != 0 &&
- kidbox.xmin < tile->winbox.xmin + lshad) {
- /* There's a nib strip at the bottom left */
- if (kidbox.xmax > tile->winbox.xmin + lshad) {
- kidbox.xmax = tile->winbox.xmin + lshad;
- }
- if (kidbox.ymax > tile->winbox.ymax + botshad) {
- kidbox.ymax = tile->winbox.ymax + botshad;
- }
- gotone = TRUE;
- }
- break;
- case YSHADOW:
- if (botshad != 0) {
- if (TRUE) { /* Must intersect to get here */
- /* There's a bottom shadow strip */
- if (kidbox.xmin < tile->winbox.xmin + lshad) {
- kidbox.xmin = tile->winbox.xmin + lshad;
- }
- if (kidbox.xmax > tile->winbox.xmax + rtshad) {
- kidbox.xmax = tile->winbox.xmax + rtshad;
- }
- if (kidbox.ymax > tile->winbox.ymax + botshad) {
- kidbox.ymax = tile->winbox.ymax + botshad;
- }
- gotone = TRUE;
- }
- newtop = tile->winbox.ymax + botshad; /* Chop this to save later testing */
- }
- break;
- case BOTBAR:
- if (TRUE) { /* Must intersect to get here */
- /* There's a strip at the bottom */
- kidbox.ymin = tile->winbox.ymax + botshad;
- gotone = TRUE;
- }
- break;
- default:
- case ALLDONE: /* Total overlap; no more strips, no more kids */
- /* Clip winbox to within starting tile */
- opbox_clipbox(&tile->box, &tile->winbox);
- return(FALSE);
- }
- /* keep this up to date as we go around again */
- if (tile->boxtop < newtop) {
- tile->boxtop = newtop;
- }
- }
- newtile = tile_Create(td, tile);
- if (newtile == NULL) {
- tile->win = NULL;
- opbox_clipbox(&tile->box, &tile->winbox);
- return(FALSE);
- }
- opbox_copy(&newtile->box, &kidbox);
- if (tile->ikid - 1 == XSHADOW || tile->ikid - 1 == YSHADOW) {
- if (tile->emsg == WINM_SAVE) {
- newtile->emsg = WINM_SHADOWSAVE;
- }
- else newtile->emsg = WINM_SHADOW;
- tile->emsgdata = NULL;
- }
- tile->kid = newtile;
- #ifdef DEBUG2
- /* diddle the new tile. */
- if (diddle2 &&
- (tile->emsg == WINM_PAINT || tile->emsg == WINM_SHADOW)) {
- for (;;) {
- ptdata.win = disp_GetDispWin();
- ptdata.relboxp = &kidbox;
-
- ptd_Clear(&ptdata, 0);
- ptd_Clear(&ptdata, 4); /* red */
- if (kb_Check()) {
- kb_Read();
- break;
- }
- }
- }
- #endif
- return(TRUE);
- }
- /* -------------------------------------------------------------------------- */
- /* The tile allocation scheme. Because each tile has only one kid and dad, */
- /* and no list splicing is done, we are assured that the tiles will be */
- /* allocated and freed in a LIFO manner */
- /* This fact insures that the varray free mechanism will work efficiently */
-
- #define INITSTACK 20
- /* -------------------------------------------------------------------------- */
-
- boolean OWLPRIV wmgr_OpenTiler()
- {
- curr_wmgr->tilerdata =
- (VOID *) va_make(INITSTACK, sizeof(struct tile_struct), NULL, FALSE, 0);
- return(curr_wmgr->tilerdata != NULL);
- }
- /* -------------------------------------------------------------------------- */
-
- void OWLPRIV wmgr_CloseTiler()
- {
- if (curr_wmgr->tilerdata != NULL) {
- va_free((varray) curr_wmgr->tilerdata);
- curr_wmgr->tilerdata = NULL;
- }
- }
- /* -------------------------------------------------------------------------- */
-
- static tile_type OWLPRIV tile_Create(td, dad)
- VOID *td;
- tile_type dad;
- /*
- allocate a new tile structure, filling in relevant values from its dad.
- */
- {
- tile_type tile;
- va_index id;
-
- id = va_findfree((varray) td);
- tile = (tile_type) va_elem((varray) td, id);
-
- if (tile != NULL) {
- va_setelemtag((varray) td, tile, (va_tag)id);
-
- tile->ikid = FIRSTKID; /* flag for gender of current kid */
- tile->kid = NULL; /* current kid */
-
- tile->dad = dad;
-
- if (dad != NULL) {
- tile->win = win_GetBelow(dad->win);
- tile->inlayer = dad->inlayer;
- tile->emsg = dad->emsg;
- tile->emsgdata = dad->emsgdata;
- }
- }
- return(tile);
- }
- /* -------------------------------------------------------------------------- */
-
-