/* windDisplay.c - * * Display the borders of the window, including the caption area. * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* */ #ifndef lint static char rcsid[] __attribute__ ((unused)) = "$Header$"; #endif /* not lint */ #include #include #include "tcltk/tclmagic.h" #include "utils/magic.h" #include "utils/utils.h" #include "textio/textio.h" #include "utils/geometry.h" #include "graphics/glyphs.h" #include "windows/windows.h" #include "windows/windInt.h" #include "graphics/graphics.h" #include "utils/styles.h" #include "tiles/tile.h" #include "utils/hash.h" #include "database/database.h" #include "utils/undo.h" #include "utils/signals.h" #include "utils/malloc.h" /* The following Plane is used to keep track of areas of the * screen that have changed. ERROR_P tiles are used to record * areas of the screen (in pixels) that must be redisplayed. * * If windows have speparate coordinate spaces (as on a SUN), this plane * is ignored and the one in w->w_redrawAreas is used instead. */ global Plane *windRedisplayArea = NULL; static Plane *windCurRedrawPlane = NULL; /* used for sharing between procs */ static LinkedRect *windCoveredAreas = NULL; global GrGlyphs *windGlyphs = NULL; /* windCaptionPixels is the height of the caption strip. It is internal to * this module. */ int windCaptionPixels = 0; /* Are the windows in their own coordinate system? */ bool windSomeSeparateRedisplay = FALSE; /* * ---------------------------------------------------------------------------- * * windCheckOnlyWindow -- * * Check if the TopWindow is the only window---if so, we shouldn't * generate bothersome messages about the cursor not being in a window, * because there is no confusion. * * We want to make sure that we don't count windows which are not of * the same client type. * * ---------------------------------------------------------------------------- */ int windCheckOnlyWindow(MagWindow **w, WindClient client) { MagWindow *sw, *tw; int wct = 0; if (*w != NULL) return 0; if (windTopWindow != NULL) { for (sw = windTopWindow; sw != NULL; sw = sw->w_nextWindow) { if (sw->w_client == client) { wct++; tw = sw; } } if (wct == 1) *w = tw; } return 0; } /* * ---------------------------------------------------------------------------- * windFreeList -- * * Free up a list of linked rectangles. * * Results: * None. * * Side effects: * Storage is reclaimed. The original pointer is NULLed out. * ---------------------------------------------------------------------------- */ void windFreeList(llr) LinkedRect **llr; /* A pointer to a list of linked rectangles */ { LinkedRect *lr, *freelr; lr = *llr; while (lr != (LinkedRect *) NULL) { freelr = lr; lr = lr->r_next; freeMagic( (char *) freelr); } *llr = (LinkedRect *) NULL; } /* * ---------------------------------------------------------------------------- * windReClip -- * * Traverse the linked list of windows, updating w_clipAgainst * for each window. * * Results: * None. * * Side effects: * Changes w_clipAgainst for some windows. * ---------------------------------------------------------------------------- */ void windReClip() { MagWindow *w1, *w2; /* an O(n**2) operation!! */ windFreeList(&windCoveredAreas); for (w1 = windBottomWindow; w1 != (MagWindow *) NULL; w1 = w1->w_prevWindow) { LinkedRect *tmp; /* add window onto windCoveredAreas */ tmp = (LinkedRect *) mallocMagic((unsigned) (sizeof (LinkedRect))); tmp->r_next = windCoveredAreas; tmp->r_r = w1->w_frameArea; windCoveredAreas = tmp; /* free up the old clipping areas and make new ones */ windFreeList( &(w1->w_clipAgainst) ); w1->w_clipAgainst = (LinkedRect *) NULL; /* Leave w_clipAgainst to be NULL if we are using some other * window package, because that package will handle overlapping * windows. */ if (WindPackageType == WIND_MAGIC_WINDOWS) { for (w2 = w1->w_prevWindow; w2 != (MagWindow *) NULL; w2 = w2->w_prevWindow) { if ( GEO_TOUCH( &(w1->w_frameArea), &(w2->w_frameArea) )) { tmp = (LinkedRect *) mallocMagic((unsigned) (sizeof (LinkedRect))); tmp->r_next = w1->w_clipAgainst; tmp->r_r = w2->w_frameArea; w1->w_clipAgainst = tmp; } } } } } /* * ---------------------------------------------------------------------------- * * WindSeparateRedisplay -- * * Tells the window manager to record redisplay areas for this window * separately -- probably because the window has its own separate * coordinate system. (Used on the Sun with Suntools or X.) * * Results: * None. * * Side Effects: * None. * * ---------------------------------------------------------------------------- */ void WindSeparateRedisplay(w) MagWindow *w; { windSomeSeparateRedisplay = TRUE; if (w->w_redrawAreas != (ClientData)NULL) return; w->w_redrawAreas = (ClientData) DBNewPlane((ClientData) TT_SPACE); } /* * ---------------------------------------------------------------------------- * WindIconChanged -- * * Mark the icon for this window as needing to be redisplayed. * * Results: * None. * * Side effects: * None. * ---------------------------------------------------------------------------- */ void WindIconChanged(w) MagWindow *w; { ASSERT(w != NULL, "WindIconChanged"); w->w_flags |= WIND_REDRAWICON; } /* * ---------------------------------------------------------------------------- * WindAreaChanged -- * * Notify the window package that a certain area of the screen has * changed, and now needs to be redrawn. * * Results: * None. * * Side effects: * The area is noted as having changed in window w. When * WindUpdate is called, this area will be redisplayed, but * only in w. If w is NULL, then this area will be redisplayed * in all windows. If area is NULL, then the whole area of * the window will be redisplayed. If both are NULL, then * the whole screen will be redisplayed. * ---------------------------------------------------------------------------- */ void WindAreaChanged(w, area) MagWindow *w; /* The window that changed. */ Rect *area; /* The area in screen coordinates. * NULL means the whole screen. Caller * should clip this rectangle to the area * of the window. */ { Rect biggerArea; bool windChangedFunc(); /* Forward declaration. */ if (w == NULL) { if (windSomeSeparateRedisplay) { MagWindow *nw; for (nw = windTopWindow; nw != NULL; nw = nw->w_nextWindow) WindAreaChanged(nw, area); return; } else windCurRedrawPlane = windRedisplayArea; } else { if (w->w_redrawAreas != (ClientData)NULL) windCurRedrawPlane = (Plane *) w->w_redrawAreas; else windCurRedrawPlane = windRedisplayArea; } if (area == (Rect *) NULL) { /* Everything changed -- all the window's area as well as the icon. */ if (w != (MagWindow *) NULL) { area = &w->w_allArea; WindIconChanged(w); } else { MagWindow *nw; area = &GrScreenRect; for (nw = windTopWindow; nw != NULL; nw = nw->w_nextWindow) WindIconChanged(nw); } } /* We have to increase the upper x- and y-coordinates of * the redisplay area by one. This is because a pixel is * considered to include its entire area (up to the beginning * of the next pixel). Without this code and corresponding * hacks in WindUpdate and windBackgroundFunc, little slivers * get left lying around. */ biggerArea = *area; biggerArea.r_xtop += 1; biggerArea.r_ytop += 1; /* If no window is given, or if the window is unobscured, * then just paint an error tile over the area to be redisplayed. * Otherwise, clip the area against all the obscuring areas * for the window. Be careful to keep undo away from this. */ UndoDisable(); if ((w == NULL) || (w->w_clipAgainst == NULL)) DBPaintPlane(windCurRedrawPlane, &biggerArea, DBStdPaintTbl(TT_ERROR_P, PL_DRC_ERROR), (PaintUndoInfo *) NULL); else { (void) GeoDisjoint(&biggerArea, &w->w_clipAgainst->r_r, windChangedFunc, (ClientData) w->w_clipAgainst->r_next); } UndoEnable(); /* If the area is NULL or encompasses the whole screen area, and */ /* there is no backing store, then we should create it so that it */ /* will be copied into on the next display redraw. */ if ((w != NULL) && (w->w_backingStore == (ClientData)NULL) && (!(w->w_flags & WIND_OBSCURED)) && (GrCreateBackingStorePtr != NULL)) { assert(area); // area is non-null if (GEO_SURROUND(&biggerArea, &w->w_screenArea)) (*GrCreateBackingStorePtr)(w); } } bool windChangedFunc(area, next) Rect *area; /* Area that is still unobscured. */ LinkedRect *next; /* Next obscuring area. */ { /* If we're at the end of obscuring areas, paint an error * tile to mark what's to be redisplayed. Otherwise, * clip against the next obscuring area. */ if (next == NULL) DBPaintPlane(windCurRedrawPlane, area, DBStdPaintTbl(TT_ERROR_P, PL_DRC_ERROR), (PaintUndoInfo *) NULL); else (void) GeoDisjoint(area, &next->r_r, windChangedFunc, (ClientData) next->r_next); return FALSE; } /* * ---------------------------------------------------------------------------- * windBarLocations -- * * Find the scroll bars and icons in the window. * Each argument must point to a different piece of memory. * * Results: * None. * * Side effects: * Returns a bunch of rectangles describing the locations of things. * See comments next to the argument list for details. * ---------------------------------------------------------------------------- */ void windBarLocations(w, leftBar, botBar, up, down, right, left, zoom) MagWindow *w; /* The window under consideration. */ /* The following are rectangles that will be filled * in by this procedure. The values will be in the * same coordinate sytem as w->w_allArea. */ Rect *leftBar; /* The location of the left scrollbar area (not the * bar itself). */ Rect *botBar; /* The location of the bottom scrollbar area. */ Rect *up; /* The location of the 'up arrow' icon above the * left scroll bar. */ Rect *down; /* The location of the 'down arrow' icon below the * left scroll bar. */ Rect *right; /* The location of the 'right arrow' icon to the right * of the bottom scroll bar. */ Rect *left; /* The location of the 'left arrow' icon to the left of * the bottom scroll bar. */ Rect *zoom; /* The location of the 'zoom' icon in the lower-left * corner of the window. */ { /* left scroll bar area */ leftBar->r_xbot = w->w_allArea.r_xbot + THIN_LINE; leftBar->r_ybot = w->w_allArea.r_ybot + THIN_LINE + WindScrollBarWidth + BOT_BORDER(w); leftBar->r_xtop = leftBar->r_xbot + WindScrollBarWidth - GrPixelCorrect; leftBar->r_ytop = w->w_allArea.r_ytop - THIN_LINE - WindScrollBarWidth - TOP_BORDER(w); /* bottom scroll bar area */ botBar->r_ybot = w->w_allArea.r_ybot + THIN_LINE; botBar->r_xbot = w->w_allArea.r_xbot + THIN_LINE + WindScrollBarWidth + LEFT_BORDER(w); botBar->r_ytop = botBar->r_ybot + WindScrollBarWidth - GrPixelCorrect; botBar->r_xtop = w->w_allArea.r_xtop - THIN_LINE - WindScrollBarWidth - RIGHT_BORDER(w); /* border icons */ down->r_xbot = up->r_xbot = leftBar->r_xbot; down->r_xtop = up->r_xtop = leftBar->r_xtop; up->r_ybot = leftBar->r_ytop + THIN_LINE + 1; up->r_ytop = up->r_ybot + WindScrollBarWidth - 1; down->r_ytop = leftBar->r_ybot - THIN_LINE - 1; down->r_ybot = down->r_ytop - WindScrollBarWidth + 1; left->r_ybot = right->r_ybot = botBar->r_ybot; left->r_ytop = right->r_ytop = botBar->r_ytop; right->r_xbot = botBar->r_xtop + THIN_LINE + 1; right->r_xtop = right->r_xbot + WindScrollBarWidth - 1; left->r_xtop = botBar->r_xbot - THIN_LINE - 1; left->r_xbot = left->r_xtop - WindScrollBarWidth + 1; zoom->r_xbot = w->w_allArea.r_xbot + THIN_LINE; zoom->r_ybot = w->w_allArea.r_ybot + THIN_LINE; zoom->r_xtop = zoom->r_xbot + WindScrollBarWidth - 1; zoom->r_ytop = zoom->r_ybot + WindScrollBarWidth - 1; } /* * ---------------------------------------------------------------------------- * WindDrawBorder -- * * Draw the border of windows. A window lock is created & then destroyed. * * Results: * None. * * Side effects: * Redisplays the scroll bar & caption areas of a window's border. * ---------------------------------------------------------------------------- */ void WindDrawBorder(w, clip) MagWindow *w; Rect *clip; { Rect r; Rect leftBar, botBar, up, down, left, right, zoom; Rect leftElev, botElev; int bar, bbox, viewl, viewu; Point capp; Rect capr; GrLock(w, FALSE); GrClipTo(clip); /* Redisplay the caption if it overlaps the area. */ capr = w->w_allArea; capr.r_ybot = capr.r_ytop - TOP_BORDER(w) + GrPixelCorrect; capp.p_x = (capr.r_xbot + capr.r_xtop) / 2; capp.p_y = (capr.r_ybot + capr.r_ytop + 1) / 2; if (GEO_TOUCH(&capr, clip)) { if (w->w_flags & WIND_BORDER) GrClipBox(&capr, STYLE_BORDER); if ((w->w_flags & WIND_CAPTION) && (w->w_caption != NULL)) { (void) GrPutText(w->w_caption, STYLE_CAPTION, &capp, GEO_CENTER, GR_TEXT_DEFAULT, FALSE, &capr, (Rect *) NULL); } } if ((w->w_flags & WIND_BORDER) != 0) { /* right border */ r = w->w_allArea; r.r_xbot = w->w_allArea.r_xtop - RIGHT_BORDER(w) + GrPixelCorrect; r.r_ytop = w->w_allArea.r_ytop - TOP_BORDER(w); if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); if ((w->w_flags & WIND_SCROLLBARS) == 0) { /* windows without scroll bars */ /* left border */ r = w->w_allArea; r.r_xtop = w->w_allArea.r_xbot + LEFT_BORDER(w) - GrPixelCorrect; r.r_ytop = w->w_allArea.r_ytop - TOP_BORDER(w); if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); /* bottom border */ r = w->w_allArea; r.r_ytop = w->w_allArea.r_ybot + BOT_BORDER(w) - GrPixelCorrect; if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); } } if ((w->w_flags & WIND_SCROLLBARS) != 0) { /* windows with scroll bars */ /* left vertical lines */ r = w->w_allArea; r.r_ytop = w->w_allArea.r_ytop - TOP_BORDER(w); r.r_xtop = r.r_xbot + THIN_LINE - GrPixelCorrect; if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); r.r_xbot += WindScrollBarWidth + THIN_LINE; r.r_xtop = r.r_xbot + THIN_LINE - GrPixelCorrect; if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); /* bottom horizontal lines */ r = w->w_allArea; r.r_ytop = r.r_ybot + THIN_LINE - GrPixelCorrect; if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); r.r_ybot += WindScrollBarWidth + THIN_LINE; r.r_ytop = r.r_ybot + THIN_LINE - GrPixelCorrect; if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); /* scroll bars */ windBarLocations(w, &leftBar, &botBar, &up, &down, &right, &left, &zoom); GrClipBox(&leftBar, STYLE_CAPTION); GrClipBox(&botBar, STYLE_CAPTION); if (w->w_bbox == NULL) { TxError("Warning: scroll bars but no w->w_bbox!\n"); TxError("Report this to a magic implementer.\n"); goto leave; }; /* left scroll bar */ bar = MAX(1, leftBar.r_ytop - leftBar.r_ybot + 1); bbox = MAX(1, w->w_bbox->r_ytop - w->w_bbox->r_ybot + 1); viewl = w->w_surfaceArea.r_ybot - w->w_bbox->r_ybot + 1; viewu = w->w_surfaceArea.r_ytop - w->w_bbox->r_ybot + 1; leftElev.r_xbot = leftBar.r_xbot + 2; leftElev.r_xtop = leftBar.r_xtop - 3 + GrPixelCorrect; leftElev.r_ybot = (bar * viewl) / bbox + leftBar.r_ybot; leftElev.r_ytop = (bar * viewu) / bbox + leftBar.r_ybot; leftElev.r_ytop = MIN(leftElev.r_ytop, leftBar.r_ytop - 2); leftElev.r_ybot = MIN(leftElev.r_ybot, leftElev.r_ytop - 3); leftElev.r_ybot = MAX(leftElev.r_ybot, leftBar.r_ybot + 2); leftElev.r_ytop = MAX(leftElev.r_ytop, leftElev.r_ybot + 1 + GrPixelCorrect + GrPixelCorrect); GrClipBox(&leftElev, STYLE_ELEVATOR); r.r_xbot = leftBar.r_xbot; r.r_xtop = leftBar.r_xtop; r.r_ybot = leftBar.r_ybot - THIN_LINE; r.r_ytop = leftBar.r_ybot - GrPixelCorrect; if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); r.r_ybot = leftBar.r_ytop + GrPixelCorrect; r.r_ytop = leftBar.r_ytop + THIN_LINE; if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); /* bottom scroll bar */ bar = MAX(1, botBar.r_xtop - botBar.r_xbot + 1); bbox = MAX(1, w->w_bbox->r_xtop - w->w_bbox->r_xbot + 1); viewl = w->w_surfaceArea.r_xbot - w->w_bbox->r_xbot + 1; viewu = w->w_surfaceArea.r_xtop - w->w_bbox->r_xbot + 1; botElev.r_ybot = botBar.r_ybot + 2; botElev.r_ytop = botBar.r_ytop - 3 + GrPixelCorrect; botElev.r_xbot = (bar * viewl) / bbox + botBar.r_xbot; botElev.r_xtop = (bar * viewu) / bbox + botBar.r_xbot; botElev.r_xtop = MIN(botElev.r_xtop, botBar.r_xtop - 2); botElev.r_xbot = MIN(botElev.r_xbot, botElev.r_xtop - 3); botElev.r_xbot = MAX(botElev.r_xbot, botBar.r_xbot + 2); botElev.r_xtop = MAX(botElev.r_xtop, botElev.r_xbot + 1 + GrPixelCorrect + GrPixelCorrect); GrClipBox(&botElev, STYLE_ELEVATOR); r.r_ybot = botBar.r_ybot; r.r_ytop = botBar.r_ytop; r.r_xbot = botBar.r_xbot - THIN_LINE; r.r_xtop = botBar.r_xbot - GrPixelCorrect; if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); r.r_xbot = botBar.r_xtop + GrPixelCorrect; r.r_xtop = botBar.r_xtop + THIN_LINE; if (GEO_TOUCH(&r, clip)) GrClipBox(&r, STYLE_BORDER); /* icons */ GrDrawGlyph(windGlyphs->gr_glyph[0], &(up.r_ll)); GrDrawGlyph(windGlyphs->gr_glyph[1], &(down.r_ll)); GrDrawGlyph(windGlyphs->gr_glyph[2], &(left.r_ll)); GrDrawGlyph(windGlyphs->gr_glyph[3], &(right.r_ll)); GrDrawGlyph(windGlyphs->gr_glyph[4], &(zoom.r_ll)); } leave: GrUnlock(w); } /* * ---------------------------------------------------------------------------- * WindCaption -- * * Set the caption on the window. * * Results: * None. * * Side effects: * The caption is changed in the data structure and is redisplayed on the * screen (if any of it is visible). If anything overlaps the caption and * the caption was redisplayed then the overlap material will be * redisplayed. * * If the new caption is identical to the old then only redisplay is done. * ---------------------------------------------------------------------------- */ void WindCaption(w, caption) MagWindow *w; char *caption; /* The string that is to be copied into the caption. * (The string is copied, not just pointed at.) */ { Rect r; if (w->w_caption != caption) (void) StrDup( &(w->w_caption), caption); r = w->w_allArea; r.r_ybot = r.r_ytop - TOP_BORDER(w) + 1; WindAreaChanged(w, &r); if (GrUpdateIconPtr)(*GrUpdateIconPtr)(w,w->w_caption); } /* * ---------------------------------------------------------------------------- * windNewView -- * * The window's view has moved -- update the scroll bars. * * Results: * None. * * Side effects: * Records areas for redisplay. * ---------------------------------------------------------------------------- */ void windNewView(w) MagWindow *w; { Rect leftBar, botBar, up, down, right, left, zoom; if ((w->w_flags & WIND_SCROLLBARS) != 0) { windBarLocations(w, &leftBar, &botBar, &up, &down, &right, &left, &zoom); WindAreaChanged(w, &leftBar); WindAreaChanged(w, &botBar); } } /* * ---------------------------------------------------------------------------- * WindRedisplay -- * * Redisplay the entire window, including the border areas. * Called without any window locks. * * Results: * None. * * Side effects: * Areas of the screen will be redrawn. * ---------------------------------------------------------------------------- */ void WindRedisplay(w) MagWindow *w; { WindAreaChanged(w, &(w->w_allArea)); } /* * ---------------------------------------------------------------------------- * windRedrawIcon -- * * Redraw a windows icon. * * Results: * None. * * Side effects: * None. * ---------------------------------------------------------------------------- */ void windRedrawIcon(w) MagWindow *w; { Point p; clientRec *cl; char *name; /* Prepare for graphics. */ cl = (clientRec *) w->w_client; GrLock(w, FALSE); GrClipBox(&w->w_allArea, STYLE_ERASEALL); if (cl->w_icon != NULL) { /* Draw the glyph */ GrDrawGlyph(cl->w_icon, &(w->w_allArea.r_ll)); } /* Now label the icon */ if (w->w_iconname != NULL) name = w->w_iconname; else name = cl->w_clientName; p.p_y = w->w_allArea.r_ybot; p.p_x = (w->w_allArea.r_xbot + w->w_allArea.r_xtop) / 2; GrPutText(name, STYLE_BORDER, &p, GEO_NORTH, GR_TEXT_SMALL, TRUE, &w->w_allArea, (Rect *) NULL); /* We are done */ w->w_flags &= ~WIND_REDRAWICON; GrUnlock(w); } /* * ---------------------------------------------------------------------------- * WindUpdate -- * * Update the screen areas that were previously passed to WindAreaChanged. * Calls clients without any window locks. * * Results: * None. * * Side effects: * Clients will be called to update portions of the screen. * ---------------------------------------------------------------------------- */ bool WindAnotherUpdatePlease; void WindUpdate() { clientRec *cr; MagWindow *w; TileTypeBitMask windTileMask; extern int windUpdateFunc(); /* Forward declaration. */ extern int windBackgroundFunc(); /* Forward declaration. */ Rect r; WindAnotherUpdatePlease = FALSE; /* First, if there was a SigWinch (as on a Sun160), then call the * graphics module so that it can record additional areas to be * redisplayed. */ if (SigGotSigWinch) { SigGotSigWinch = FALSE; if (GrDamagedPtr != NULL) (*GrDamagedPtr)(); } #ifdef MAGIC_WRAPPER /* Honor the display redraw suspension state */ if (GrDisplayStatus == DISPLAY_SUSPEND) return; GrDisplayStatus = DISPLAY_IN_PROGRESS; SigSetTimer(0); #endif TTMaskSetOnlyType(&windTileMask, TT_ERROR_P); /* Make a scan through each of the windows, in order from top * down. For each window, redisplay the areas of that window * that have changed, then erase the area of that window from * the redisplay plane. Since our window areas INCLUDE their * border pixels on both sides, expand the area on the top and * right sides before erasing. Without this expansion, and * corresponding hacks in WindAreaChanged and windBackgroundFunc, * slivers will accidentally be left undisplayed. */ UndoDisable(); for (w = windTopWindow; w != NULL; w = w->w_nextWindow) { if (w->w_flags & WIND_ISICONIC) { if (w->w_flags & WIND_REDRAWICON) windRedrawIcon(w); } else { if (w->w_redrawAreas == (ClientData)NULL) windCurRedrawPlane = windRedisplayArea; else windCurRedrawPlane = (Plane *) w->w_redrawAreas; (void) DBSrPaintArea((Tile *) NULL, windCurRedrawPlane, &w->w_allArea, &windTileMask, windUpdateFunc, (ClientData) w); if (windCurRedrawPlane == windRedisplayArea) { /* Erase this window from our list, since we have redrawn it. */ r = w->w_allArea; r.r_xtop += 1; r.r_ytop += 1; DBPaintPlane(windRedisplayArea, &r, DBStdEraseTbl(TT_ERROR_P, PL_DRC_ERROR), (PaintUndoInfo *) NULL); } else { /* We are finished with this window's redisplay plane. Clear * any remaining redisplay tiles, as we may have interrupted * the redislay and don't want this stuff any more. */ DBClearPaintPlane(windCurRedrawPlane); } } } if (WindPackageType == WIND_MAGIC_WINDOWS) { /* For any tiles left that intersect the screen, draw the background * color (there are no windows over these tiles). */ (void) DBSrPaintArea((Tile *) NULL, windRedisplayArea, &GrScreenRect, &windTileMask, windBackgroundFunc, (ClientData) NULL); /* Clear any remaining redisplay tiles, as we may have interrupted * the redislay and don't want this stuff any more. */ DBClearPaintPlane(windRedisplayArea); }; UndoEnable(); /* Now give the clients a chance to update anything that they wish */ for (cr = windFirstClientRec; cr != (clientRec *) NULL; cr = cr->w_nextClient) { if (cr->w_update != NULL) (*(cr->w_update)) (); } GrFlush(); #ifdef MAGIC_WRAPPER SigRemoveTimer(); GrDisplayStatus = DISPLAY_IDLE; #endif /* See comment in windows.h */ if (WindAnotherUpdatePlease) WindUpdate(); } /* * ---------------------------------------------------------------------------- * * windUpdateFunc -- * * This procedure is invoked during WindUpdate for each tile that * intersects a particular window. If the tile type is TT_ERROR_P * then the intersection between the tile and the window is * redisplayed. * * Results: * Always returns 0 to keep the search from aborting. * * Side effects: * Information is redisplayed on the screen. * * ---------------------------------------------------------------------------- */ int windUpdateFunc(tile, w) Tile *tile; /* Tile in the redisplay plane. */ MagWindow *w; /* Window we're currently interested in. */ { Rect area; /* If this is a space tile, there's nothing to do. */ if (TiGetType(tile) == TT_SPACE) return 0; TiToRect(tile, &area); GeoClip(&area, &w->w_allArea); GeoClip(&area, &GrScreenRect); if ((area.r_xbot > area.r_xtop) || (area.r_ybot > area.r_ytop)) /* nothing to display */ return 0; /* Skip the border stuff if it isn't going to change. This * test has to be especially tricky because of the decision * that pixel at (0,0) extends from (0,0) up to but not including * (1,1). */ if (!((w->w_screenArea.r_xbot <= area.r_xbot) && (w->w_screenArea.r_xtop+1 >= area.r_xtop) && (w->w_screenArea.r_ybot <= area.r_ybot) && (w->w_screenArea.r_ytop+1 >= area.r_ytop))) { /* Redisplay the border areas. */ WindDrawBorder(w, &area); }; /* Now call the client to redisplay the interior of the window. */ if (GEO_TOUCH(&(w->w_screenArea), &area)) { Rect clientArea; WindScreenToSurface(w, &area, &clientArea); GeoClip(&area, &w->w_screenArea); if ( ((clientRec *) (w->w_client))->w_redisplay != NULL) { (*(( (clientRec *) (w->w_client))->w_redisplay)) (w, &clientArea, &area); } } return 0; } /* * ---------------------------------------------------------------------------- * * windBackgroundFunc -- * * Called for each tile left after redisplaying all of the windows. * This procedure just draws the background colors in any remaining * areas that have changed. * * Results: * Always returns 0 to keep the search from aborting. * * Side effects: * The background color gets drawn on the screen. * * ---------------------------------------------------------------------------- */ /* ARGSUSED */ int windBackgroundFunc(tile, notUsed) Tile *tile; ClientData notUsed; { Rect area; if (TiGetType(tile) == (TileType) TT_SPACE) return 0; TiToRect(tile, &area); /* Since windows include their border pixels, we have to be * a bit careful. If the upper or right edge of the area isn't * the edge of the screen, it is a window. In that case, decrement * the coordinate so we don't overwrite the edge of the window. */ if (area.r_xtop < GrScreenRect.r_xtop) area.r_xtop -= 1; if (area.r_ytop < GrScreenRect.r_ytop) area.r_ytop -= 1; GrLock(GR_LOCK_SCREEN, FALSE); GrClipBox(&area, STYLE_BACKGROUND); GrUnlock(GR_LOCK_SCREEN); return 0; }