985 lines
28 KiB
C
985 lines
28 KiB
C
/* 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 <stdio.h>
|
|
|
|
#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;
|
|
int 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))
|
|
if ((area == (Rect *)NULL) || GEO_SURROUND(&biggerArea, &w->w_screenArea))
|
|
(*GrCreateBackingStorePtr)(w);
|
|
}
|
|
|
|
int
|
|
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 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
* ----------------------------------------------------------------------------
|
|
* 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;
|
|
}
|