mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-08-29 17:39:28 +02:00
and forcing it to be passed as an argument to all the callback functions for the search routines that require it. Magic now compiles and runs with the new code, but there are a number of known issues that need to be fixed up. Committing now so that I can rebase on the last update to the master branch.
990 lines
28 KiB
C
990 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 <assert.h>
|
|
#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;
|
|
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, dinfo, w)
|
|
Tile *tile; /* Tile in the redisplay plane. */
|
|
TileType dinfo; /* Split tile information (unused) */
|
|
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, dinfo, notUsed)
|
|
Tile *tile;
|
|
TileType dinfo; /* (unused) */
|
|
ClientData notUsed; /* (unused) */
|
|
{
|
|
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;
|
|
}
|