This is ScrollView.c in view mode; [Download] [Up]
/*
* $RCSfile: ScrollView.c,v $
*
* Copyright (C) 1992 by Adobe Systems Incorporated.
* All rights reserved.
*
* 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 notices appear in all copies and that
* both those copyright notices and this permission notice appear in
* supporting documentation and that the name of Adobe Systems
* Incorporated not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. If any portion of this software is changed, it cannot be
* marketed under Adobe's trademarks and/or copyrights unless Adobe, in
* its sole discretion, approves by a prior writing the quality of the
* resulting implementation.
*
* ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
* ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
* ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
* TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
* PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
*
* PostScript, Display PostScript, and Adobe are trademarks of Adobe Systems
* Incorporated registered in the U.S.A. and other countries.
*
* Author: Adobe Systems Incorporated
*/
/***************************************************************
**
** INCLUDES
*****************************************************************/
#include "Scroll.h"
#include <X11/Xproto.h>
static void doScroll();
/***************************************************************
**
** FUNCTION: setOrigin
**
** DESCRIPTION: Sets the origin of the context to the point that
** corresponds to (AppData.originX, AppData.originY)
** by translating user space. To avoid cumulative
** translation round-off error, always reinitialize the
** coordinate system and translate and scale from there
**
** PARAMETERS: None
**
** RETURN: None.
**
***************************************************************/
static void setOrigin()
{
Point pt;
XPoint xpt;
xpt.x = AppData.originX;
xpt.y = AppData.originY;
convertToOrigDPS(&xpt, &pt);
PSWSetMatrixAndGetTransform(pt.x, pt.y, AppData.scale,
AppData.originX, AppData.originY,
AppData.ctm, AppData.invctm,
&AppData.xOffset, &AppData.yOffset);
} /* setOrigin() */
/***************************************************************
**
** FUNCTION: scrollProc
**
** DESCRIPTION: Callback routine for hitting scroll bars
**
** PARAMETERS: w callback widget ID
** clientData callback client data
** callData callback Motif data structure
**
** RETURN: None.
**
***************************************************************/
void scrollProc (w, clientData, callData)
Widget w;
XtPointer clientData, callData;
{
int x, y;
int deltaX, deltaY;
/*
** Get the new values of the scroll bars
*/
XtVaGetValues(AppData.selfHScroll, XmNvalue, &x, NULL);
XtVaGetValues(AppData.selfVScroll, XmNvalue, &y, NULL);
/*
** Calculate the delta in the scrolling
*/
deltaX = x - AppData.scrollX;
deltaY = y - AppData.scrollY;
/*
** If we are not already scrolling, and there is some scrolling to do,
** then offset the origin and copy the area
*/
if (deltaX == 0 && deltaY == 0) return;
if (!AppData.scrolling) doScroll(deltaX, deltaY);
/*
** Set the scrolling flag
*/
AppData.scrolling = True;
} /* end scrollProc() */
/***************************************************************
**
** FUNCTION: findViewClip
**
** DESCRIPTION: Create a clip list for scrolling updating
**
** PARAMETERS: deltaX X displacement
** deltaY Y displacement
**
** RETURN: clipList List of clipping rectangles
** clipLen Number of rectangles in clip
**
***************************************************************/
static void findViewClip(deltaX, deltaY, clipList, clipLen)
int deltaX, deltaY;
int **clipList;
int *clipLen;
{
static int r[8];
int count;
/*
** If one of the deltas is 0, then the area to update is just a
** single rectangle.
*/
if (deltaX == 0 || deltaY == 0) {
if (deltaX == 0) {
/*
** Just a single horizontal rectangle
*/
r[0] = 0;
r[2] = AppData.drawingWidth;
if (deltaY > 0) {
r[1] = AppData.drawingHeight;
r[3] = deltaY;
} else {
r[1] = -deltaY;
r[3] = -deltaY;
}
} else if (deltaY == 0) {
/*
** Just a single vertical rectangle
*/
r[1] = AppData.drawingHeight;
r[3] = AppData.drawingHeight;
if (deltaX > 0) {
r[0] = AppData.drawingWidth - deltaX;
r[2] = deltaX;
} else {
r[0] = 0;
r[2] = -deltaX;
}
}
count = 1;
} else {
/*
** Scrolling in both areas, so there are two rectangles. It's
** easiest to do if we let them overlap; fortunately that is
** legal! First do the horizontal rectangle.
*/
r[0] = 0;
r[2] = AppData.drawingWidth;
if (deltaY > 0) {
r[1] = AppData.drawingHeight;
r[3] = deltaY;
} else {
r[1] = -deltaY;
r[3] = -deltaY;
}
/*
** Now do vertical rectangle
*/
r[5] = AppData.drawingHeight;
r[7] = AppData.drawingHeight;
if (deltaX > 0) {
r[4] = AppData.drawingWidth - deltaX;
r[6] = deltaX;
} else {
r[4] = 0;
r[6] = -deltaX;
}
count = 2;
}
*clipList = r;
*clipLen = count;
} /* end findViewClip() */
/***************************************************************
**
** FUNCTION: doScroll
**
** DESCRIPTION: Scroll the drawing area by some delta
**
** PARAMETERS: deltaX X displacement
** deltaY Y displacement
**
** RETURN: None.
**
***************************************************************/
static void doScroll(deltaX, deltaY)
int deltaX, deltaY;
{
Drawable d;
Widget draw = AppData.currentDraw;
int *clipList;
int clipLen;
/*
** Set the origin in the X window to the new settings of
** the scrollbars
*/
AppData.originX -= deltaX;
AppData.originY -= deltaY;
/*
** Update the stored position of the scroll bars
*/
AppData.scrollX += deltaX;
AppData.scrollY += deltaY;
AppData.lastXdelta = deltaX;
AppData.lastYdelta = deltaY;
/*
** The drawable we are shifting is either the buffer or the window
*/
if (AppData.scrollStrategy == scroll_self_buffer &&
!AppData.showDrawing) d = AppData.buf;
else d = XtWindow(draw);
/*
** Copy visible area to new location
*/
XCopyArea(XtDisplay(draw), d, d, AppData.gc,
deltaX, deltaY, AppData.drawingWidth,
AppData.drawingHeight, 0, 0);
/*
** Adjust the origin to account for the scrolling. If we're not buffering
** there's nothing more to do. The GraphicsExpose events will cause
** the newly-exposed areas to be filled in.
*/
setOrigin();
if (AppData.scrollStrategy == scroll_self_redraw) return;
/*
** Set view clip to fix-up area and redisplay
*/
findViewClip(deltaX, deltaY, &clipList, &clipLen);
drawSelf(clipList, clipLen);
/*
** Done drawing. If not watching progress, copy the scrolled image
** into the window
*/
if (!AppData.showDrawing) {
XCopyArea(XtDisplay(draw), AppData.buf,
XtWindow(draw), AppData.gc, 0, 0,
AppData.drawingWidth, AppData.drawingHeight, 0, 0);
}
} /* end doScroll() */
/***************************************************************
**
** FUNCTION: graphicsExpose
**
** DESCRIPTION: Callback routine that handles GraphicsExpose and
** NoExpose events. If using buffered drawing, we get a
** NoExpose event for each copy. If not buffered, we get
** GraphicsExpose events to indicate where we need to redraw
** In either case, call scrollProc again to see if the scrollbars
** have moved more since the scroll we're handling. Not
** handling further scroll callbacks until the event arrives
** makes scrolling much more responsive.
**
** PARAMETERS: w window widget
** clientData clientdata
** event event information
** goOn continue to dispatch
**
** RETURN: None.
**
***************************************************************/
void graphicsExpose (w, clientData, event, goOn)
Widget w;
XtPointer clientData;
XEvent *event;
Boolean *goOn;
{
static int *bboxList = NULL;
static int bboxLen = 0, bboxCount = 0;
XExposeEvent *e = &event->xexpose;
if (!AppData.scrolling) return;
switch (event->type) {
case GraphicsExpose:
/*
** GraphicsExpose occur when unbuffered or watching progress
*/
if (AppData.scrollStrategy != scroll_self_redraw) {
/*
** Watching progress; copy from buffer to be sure
*/
XCopyArea(XtDisplay(w), AppData.buf, XtWindow(w), AppData.gc,
e->x, e->y, e->width, e->height, e->x, e->y);
} else {
addExposureToBBox(&bboxList, &bboxLen, &bboxCount, e);
/*
** If no more GraphicsExpose events, set view clip and redraw
*/
if (e->count == 0) {
drawSelf(bboxList, bboxCount/4);
bboxCount = 0;
}
if (e->count == 0) {
AppData.scrolling = False;
AppData.lastXdelta = AppData.lastYdelta = 0;
scrollProc(w, NULL, NULL);
}
}
break;
case NoExpose:
/*
** NoExpose occur in many cases but are only relevant when
** buffered and scrolling
*/
if (AppData.scrollStrategy == scroll_self_buffer &&
AppData.scrolling) {
AppData.scrolling = False;
AppData.lastXdelta = AppData.lastYdelta = 0;
scrollProc(w, NULL, NULL);
}
break;
}
} /* end graphicExpose() */
/***************************************************************
**
** FUNCTION: positionDrawingArea
**
** DESCRIPTION: Routine to position the origin so that the
** point (ix, iy) on the image, in PS coordinates,
** corresponds to the point (vx, vy) on the visible
** window, in X coords.
**
** PARAMETERS:
** ix x coord of point on DPS context (PS coordinates)
** iy y coord of point on DPS context (PS coordinates)
** vx x coors of point on drawing area (X coordinates)
** vy y coors of point on drawing area (X coordinates)
**
** RETURN: None.
**
***************************************************************/
void positionDrawingArea (ix, iy, vx, vy)
float ix;
float iy;
int vx;
int vy;
{
int xoff, yoff;
int hSize, vSize;
float scrollX, scrollY;
/* Convert ix, iy into X units */
ix *= ((float) AppData.scaledWidth) / PAGE_WIDTH;
iy *= ((float) AppData.scaledHeight) / PAGE_HEIGHT;
if (AppData.drawingWidth >= AppData.scaledWidth) {
/*
** The scaled width is narrower than the view window, so
** center the picture and set scroll bar to be unscrollable
*/
xoff = (AppData.drawingWidth - AppData.scaledWidth) / 2.0;
scrollX = 0;
hSize = AppData.scaledWidth;
} else {
/*
** The scaled width is larger than the view window, so
** turn on the scroll bar, and set up its maximum and
** slider size. Do this by converting the image offset into X
** coordinates and subtracting the view offset
*/
scrollX = ix - vx;
scrollX = MAX(scrollX, 0);
scrollX = MIN(scrollX,
AppData.scaledWidth - (int) AppData.drawingWidth);
hSize = AppData.drawingWidth;
xoff = -(int) (scrollX + 0.5);
}
/*
** Now do the same thing for the height. We want to compute the offset
** relative to the lower left corner, but X coordinates are relative
** to the upper left, so the drawing height must be added in. Also, since
** the coordinates go in the other direction, the view offset must be
** added, not subtracted.
*/
if (AppData.drawingHeight >= AppData.scaledHeight) {
yoff = (AppData.drawingHeight - AppData.scaledHeight) / 2.0;
scrollY = AppData.scaledHeight - (int) AppData.drawingHeight;
vSize = AppData.scaledHeight;
} else {
scrollY = iy + vy - (int) AppData.drawingHeight;
scrollY = MAX(scrollY, 0);
scrollY = MIN(scrollY,
AppData.scaledHeight - (int) AppData.drawingHeight);
vSize = AppData.drawingHeight;
yoff = -(int) (scrollY + 0.5);
}
/*
** Update the scrollbars
*/
AppData.scrollX = (int) (scrollX + 0.5);
AppData.scrollY = (int) (AppData.scaledHeight -
(int) AppData.drawingHeight - scrollY + 0.5);
if (AppData.scrollStrategy & SCROLL_AUTO) {
if (xoff <= 0) xoff = 0;
else hSize = AppData.drawingWidth;
if (yoff <= 0) yoff = AppData.scaledHeight;
else {
yoff = (int) AppData.drawingHeight - yoff;
vSize = AppData.drawingHeight;
AppData.scrollY = 0;
}
XmScrollBarSetValues(AppData.autoHScroll, AppData.scrollX,
hSize, 0, 0, True);
XmScrollBarSetValues(AppData.autoVScroll, AppData.scrollY,
vSize, 0, 0, True);
} else {
yoff = AppData.drawingHeight - yoff;
XtVaSetValues(AppData.selfHScroll,
XmNmaximum, (int) AppData.scaledWidth,
XmNvalue, AppData.scrollX, XmNsliderSize, hSize, NULL);
XtVaSetValues(AppData.selfVScroll,
XmNmaximum, (int) AppData.scaledHeight,
XmNvalue, AppData.scrollY, XmNsliderSize, vSize, NULL);
}
/*
** Set the origin in the X window to reflect the new location
*/
AppData.originX = xoff;
AppData.originY = yoff;
setOrigin();
} /* end positionDrawingArea() */
/***************************************************************
**
** FUNCTION: setWindowSize
**
** DESCRIPTION: Set the window size to the specified dimensions
** If they are smaller than the current clip window,
** use the size of the clip window instead
**
** PARAMETERS: width, height Window dimensions
**
** RETURN: None.
**
***************************************************************/
void setWindowSize(width, height)
Dimension width, height;
{
XtVaGetValues(XtParent(AppData.currentDraw),
XtNwidth, &AppData.drawingWidth,
XtNheight, &AppData.drawingHeight, NULL);
if (width < AppData.drawingWidth) width = AppData.drawingWidth;
if (height < AppData.drawingHeight) height = AppData.drawingHeight;
XtVaSetValues(AppData.currentDraw, XtNwidth, width,
XtNheight, height, NULL);
} /* setWindowSize() */
/***************************************************************
**
** FUNCTION: getwindowSize
**
** DESCRIPTION: Updates the window size fields in the AppData structure
**
** PARAMETERS: None
**
** RETURN: None.
**
***************************************************************/
static void getWindowSize()
{
XtVaGetValues(AppData.currentDraw, XtNwidth, &AppData.drawingWidth,
XtNheight, &AppData.drawingHeight, NULL);
} /* end getWindowSize() */
/***************************************************************
**
** FUNCTION: scaleDrawingArea
**
** DESCRIPTION: Recomputes the scaled drawing size. If using auto
** scrolling, resize the drawing area to this size
**
** PARAMETERS: None
**
** RETURN: None.
**
***************************************************************/
void scaleDrawingArea ()
{
AppData.scale = (float) AppData.magnify / 100.0;
AppData.scaledWidth = PAGE_WIDTH * AppData.origXScale * AppData.scale;
AppData.scaledHeight = PAGE_HEIGHT * AppData.origYScale * AppData.scale;
if (AppData.scrollStrategy & SCROLL_AUTO) {
setWindowSize(AppData.scaledWidth, AppData.scaledHeight);
}
} /* end scaleDrawingArea() */
/***************************************************************
**
** FUNCTION: pixmapHandler
**
** DESCRIPTION: New error handler to detect pixmap allocation failure
**
** PARAMETERS: dpy Current display
** error Error event
**
** RETURN: 0
**
***************************************************************/
static Boolean pixmapError;
static int (*oldHandler)();
static int pixmapHandler(dpy, error)
Display *dpy;
XErrorEvent *error;
{
if (error->error_code == BadAlloc &&
error->request_code == X_CreatePixmap) {
pixmapError = True;
return 0;
} else return (*oldHandler) (dpy, error);
} /* pixmapHandler() */
/***************************************************************
**
** FUNCTION: allocPixmap
**
** DESCRIPTION: Allocate a pixmap of the desired size, but if
** it would exceed the memory limit or if the allocation
** fails, return None
**
** PARAMETERS: dpy The display
** win A window on the screen
** w, h The pixmap dimensions
** d Pixmap depth
**
** RETURN: The pixmap, or None
**
***************************************************************/
static Pixmap allocPixmap(dpy, win, w, h, d)
Display *dpy;
Window win;
unsigned int w, h, d;
{
Pixmap p;
unsigned int dBytes;
dBytes = (d + 7) / 8; /* Convert into bytes */
if (w * h * dBytes > AppData.pixmapMaxSize) return None;
XSync(dpy, False);
oldHandler = XSetErrorHandler(pixmapHandler);
pixmapError = False;
p = XCreatePixmap(dpy, win, w, h, d);
XSync(dpy, False);
(void) XSetErrorHandler(oldHandler);
if (pixmapError) return None;
else return p;
} /* end allocPixmap() */
/***************************************************************
**
** FUNCTION: initializePixmap
**
** DESCRIPTION: Free the old pixmap, if any, and allocate a new one
**
** PARAMETERS: width, height Size of pixmap
**
** RETURN: None.
**
***************************************************************/
static void initializePixmap(width, height)
int width, height;
{
int depth;
/*
** Free the old pixmap if it exists
*/
if (AppData.buf != None) {
XFreePixmap(XtDisplay(AppData.time), AppData.buf);
}
AppData.pixmapWidth = width;
AppData.pixmapHeight = height;
/*
** If new size is 0, return
*/
if (width == 0) {
AppData.buf = None;
return;
}
/*
** New size must be at least as large as the drawing area
*/
if (width < AppData.drawingWidth) {
width = AppData.pixmapWidth = AppData.drawingWidth;
}
if (height < AppData.drawingHeight) {
height = AppData.pixmapHeight = AppData.drawingHeight;
}
/*
** Find the drawing area depth and allocate the pixmap
*/
XtVaGetValues(AppData.currentDraw, XtNdepth, &depth, NULL);
AppData.buf = allocPixmap(XtDisplay(AppData.time),
XtWindow(AppData.currentDraw),
width, height, depth);
} /* end initializePixmap() */
/***************************************************************
**
** FUNCTION: initializeContext
**
** DESCRIPTION: Set the context to use a drawable, and set up the
** X offset and the coordinate system for drawing
**
** PARAMETERS: drawable New window or pixmap
** x, y X offset
**
** RETURN: None.
**
***************************************************************/
static void initializeContext(drawable, x, y)
Drawable drawable;
int x, y;
{
PSWSetContextDrawable(drawable, x, y);
AppData.xOffset = x;
AppData.yOffset = y;
} /* end initializeContext() */
/***************************************************************
**
** FUNCTION: setupAndDrawAuto
**
** DESCRIPTION: Setup the context and redraw in auto-scrolling
** mode. Keep the ix, iy position in the drawing
** at vx, vy in the window
**
** PARAMETERS: center Whether to center the image
** ix, iy Position in the drawing
** vx, vy Position in the window
**
** RETURN: None.
**
***************************************************************/
static void setupAndDrawAuto(center, ix, iy, vx, vy)
Boolean center;
float ix, iy;
int vx, vy;
{
int area[4];
Widget w = AppData.currentDraw;
/*
** If the current drawing area is not the auto drawing area,
** unmanage the self-scrolling window and manage the auto-scrolling
** one. Set the size of the auto-scrolled window to the current
** scaled width
*/
if (AppData.currentDraw != AppData.autoDrawingArea) {
XtUnmanageChild(AppData.selfScrolling);
XtManageChild(AppData.autoScrolling);
w = AppData.currentDraw = AppData.autoDrawingArea;
setWindowSize(AppData.scaledWidth, AppData.scaledHeight);
}
if (center) {
ix = PAGE_WIDTH / 2.0;
iy = PAGE_HEIGHT / 2.0;
vx = AppData.drawingWidth / 2;
vy = AppData.drawingHeight / 2;
}
if (AppData.scrollStrategy != scroll_auto_redraw) {
/*
** Create a backing pixmap. If this fails, convert to
** unbuffered drawing
*/
initializePixmap(AppData.scaledWidth, AppData.scaledHeight);
if (AppData.buf == None) {
putUpInfoDialog(AppData.noAutoPixmapMessage);
if (AppData.scrollStrategy == scroll_background) {
XSetWindowBackground(XtDisplay(w), XtWindow(w),
WhitePixelOfScreen(XtScreen(w)));
}
AppData.scrollStrategy = scroll_auto_redraw;
XtVaSetValues(AppData.currentStrategy, XmNset, False, NULL);
XtVaSetValues(AppData.autoRedraw, XmNset, True, NULL);
XtSetSensitive(AppData.watchFrame, False);
}
}
if (AppData.scrollStrategy != scroll_auto_redraw) {
/*
** Set the context to the pixmap and the origin to the center.
** The centered origin minimizes problems with limited imaging
** area.
*/
initializeContext(AppData.buf, AppData.scaledWidth/2,
AppData.scaledHeight/2);
positionDrawingArea(ix, iy, vx, vy);
if (AppData.showDrawing) XClearWindow(XtDisplay(w), XtWindow(w));
/*
** Set the clipping area to the whole page and redraw
*/
area[0] = 0;
area[1] = AppData.pixmapHeight;
area[2] = AppData.pixmapWidth;
area[3] = AppData.pixmapHeight;
drawSelf(area, 1);
} else {
/*
** Unbuffered drawing, so free pixmap and set window as destination
*/
initializePixmap(0, 0);
initializeContext(XtWindow(w), AppData.scaledWidth/2,
AppData.scaledHeight/2);
positionDrawingArea(ix, iy, vx, vy);
}
/*
** Now get the image to appear in the window
*/
if (AppData.scrollStrategy == scroll_background) {
/*
** Using window background, so install as background and clear
*/
XSetWindowBackgroundPixmap(XtDisplay(w), XtWindow(w), AppData.buf);
XClearWindow(XtDisplay(w), XtWindow(w));
} else if (AppData.scrollStrategy == scroll_auto_buffer) {
/*
** Using buffered drawing. If we weren't watching the drawing,
** clear the window. The expose events will cause the buffer
** to be copied into the window
*/
if (!AppData.showDrawing) flushAndClear(w);
} else {
/*
** Unbuffered drawing; clear window and let expose events
** drive the actual drawing
*/
flushAndClear(w);
}
} /* end setupAndDrawAuto() */
/***************************************************************
**
** FUNCTION: setupAndDrawSelf
**
** DESCRIPTION: Setup the context and redraw in self-scrolling
** mode. Keep the ix, iy position in the drawing
** at vx, vy in the window
**
** PARAMETERS: center Whether to center the image
** ix, iy Position in the drawing
** vx, vy Position in the window
**
** RETURN: None.
**
***************************************************************/
static void setupAndDrawSelf(center, ix, iy, vx, vy)
Boolean center;
float ix, iy;
int vx, vy;
{
int area[4];
Widget w = AppData.currentDraw;
/*
** If the current drawing area is not the self drawing area,
** unmanage the auto-scrolling window and manage the self-scrolling
** one. Get the current size of the drawing area
*/
if (AppData.currentDraw != AppData.selfDrawingArea) {
XtUnmanageChild(AppData.autoScrolling);
XtManageChild(AppData.selfScrolling);
w = AppData.currentDraw = AppData.selfDrawingArea;
getWindowSize();
}
if (center) {
ix = PAGE_WIDTH / 2.0;
iy = PAGE_HEIGHT / 2.0;
vx = AppData.drawingWidth / 2;
vy = AppData.drawingHeight / 2;
}
if (AppData.scrollStrategy == scroll_self_buffer) {
/*
** Create a backing pixmap. If this fails, convert to
** unbuffered drawing
*/
initializePixmap(AppData.drawingWidth, AppData.drawingHeight);
if (AppData.buf == None) {
putUpInfoDialog(AppData.noSelfPixmapMessage);
AppData.scrollStrategy = scroll_self_redraw;
XtVaSetValues(AppData.currentStrategy, XmNset, False, NULL);
XtVaSetValues(AppData.selfRedraw, XmNset, True, NULL);
AppData.currentStrategy = AppData.selfRedraw;
XtSetSensitive(AppData.watchFrame, False);
}
}
if (AppData.scrollStrategy == scroll_self_buffer) {
/*
** Set the context to the pixmap
*/
initializeContext(AppData.buf, 0, AppData.drawingHeight);
positionDrawingArea(ix, iy, vx, vy);
if (AppData.showDrawing) XClearWindow(XtDisplay(w), XtWindow(w));
/*
** Set the clipping area to the size of the window and redraw
*/
area[0] = 0;
area[1] = AppData.drawingHeight;
area[2] = AppData.drawingWidth;
area[3] = AppData.drawingHeight;
drawSelf(area, 1);
/*
** If we weren't watching the drawing, clear the window.
** The expose events will cause the bufferto be copied into the window
*/
if (!AppData.showDrawing) flushAndClear(w);
} else {
/*
** Unbuffered drawing, so free pixmap and set window as destination
*/
initializePixmap(0, 0);
initializeContext(XtWindow(w), 0, AppData.drawingHeight);
positionDrawingArea(ix, iy, vx, vy);
/*
** Clear window and let expose events drive the actual drawing
*/
flushAndClear(w);
}
} /* end setupAndDrawSelf() */
/***************************************************************
**
** FUNCTION: setupAndDrawUnmoving
**
** DESCRIPTION: Setup the buffers and redraw, keeping everything
** positioned as it currently is
**
** PARAMETERS: None
**
** RETURN: None.
**
***************************************************************/
void setupAndDrawUnmoving()
{
XPoint xpt;
Point pt;
Position x, y;
xpt.x = 0;
xpt.y = 0;
if (AppData.currentDraw == AppData.autoDrawingArea) {
XtVaGetValues(AppData.autoDrawingArea, XtNx, &x, XtNy, &y, NULL);
xpt.x -= x;
xpt.y -= y;
}
convertToDPS(&xpt, &pt);
setupAndDraw(False, pt.x, pt.y, 0, 0);
} /* end setupAndDrawUnmoving() */
/***************************************************************
**
** FUNCTION: setupAndDraw
**
** DESCRIPTION: Set everything up for drawing, and redraw. Either
** center the drawing or keep (ix, iy) in the image at
** (vx, vy) in the window
**
** PARAMETERS: center Whether to center the image
** ix, iy Fixed point in image
** vx, vy Fixed point in window
**
** RETURN: None.
**
***************************************************************/
void setupAndDraw(center, ix, iy, vx, vy)
Boolean center;
float ix, iy;
int vx, vy;
{
if (AppData.scrollStrategy & SCROLL_AUTO) {
setupAndDrawAuto(center, ix, iy, vx, vy);
} else setupAndDrawSelf(center, ix, iy, vx, vy);
} /* end setupAndDraw() */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.