824N/A /*
824N/A * DPSScrollW.c
824N/A *
824N/A * (c) Copyright 1993-1994 Adobe Systems Incorporated.
824N/A * All rights reserved.
824N/A *
824N/A * Permission to use, copy, modify, distribute, and sublicense this software
824N/A * and its documentation for any purpose and without fee is hereby granted,
824N/A * provided that the above copyright notices appear in all copies and that
824N/A * both those copyright notices and this permission notice appear in
824N/A * supporting documentation and that the name of Adobe Systems Incorporated
824N/A * not be used in advertising or publicity pertaining to distribution of the
824N/A * software without specific, written prior permission. No trademark license
824N/A * to use the Adobe trademarks is hereby granted. If the Adobe trademark
824N/A * "Display PostScript"(tm) is used to describe this software, its
824N/A * functionality or for any other purpose, such use shall be limited to a
824N/A * statement that this software works in conjunction with the Display
824N/A * PostScript system. Proper trademark attribution to reflect Adobe's
824N/A * ownership of the trademark shall be given whenever any such reference to
824N/A * the Display PostScript system is made.
824N/A *
824N/A * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
824N/A * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
824N/A * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
824N/A * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
824N/A * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
824N/A * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
824N/A * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
824N/A * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
824N/A * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
824N/A * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
824N/A *
824N/A * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
824N/A * Incorporated which may be registered in certain jurisdictions
824N/A *
824N/A * Author: Adobe Systems Incorporated
824N/A */
824N/A/* $XFree86$ */
824N/A
824N/A#include <X11/IntrinsicP.h>
824N/A#include <X11/StringDefs.h>
824N/A#include <X11/ShellP.h>
824N/A#include <X11/Xproto.h>
824N/A#include <stdlib.h>
824N/A#include <Xm/Xm.h>
824N/A
824N/A/* There are no words to describe how I feel about having to do this */
824N/A
824N/A#if XmVersion > 1001
824N/A#include <Xm/ManagerP.h>
824N/A#else
824N/A#include <Xm/XmP.h>
824N/A#endif
824N/A
824N/A#include <Xm/DrawingA.h>
824N/A#include <Xm/ScrolledW.h>
824N/A#include <Xm/ScrollBar.h>
824N/A
824N/A#include <DPS/dpsXclient.h>
824N/A#include "dpsXcommonI.h"
824N/A#include <DPS/dpsXshare.h>
824N/A#include "DSWwraps.h"
824N/A#include <stdio.h>
824N/A#include <DPS/DPSScrollWP.h>
824N/A
824N/A#undef MIN
824N/A#define MIN(a, b) ((a) < (b) ? (a) : (b))
824N/A#undef MAX
824N/A#define MAX(a, b) ((a) > (b) ? (a) : (b))
824N/A#undef ABS
824N/A#define ABS(x) ((x) >= 0 ? (x) : -(x))
824N/A#undef CEIL
824N/A#define CEIL(x) ((int) ((float)((int)(x)) == (x) ? (x) : (x) + 1))
824N/A
824N/A/* Define macros to get rectangle entries. All rectangles are stored as
824N/A x, y, width, height. NOTE: ONLY FOR USER SPACE RECTANGLES, NOT X
824N/A RECTANGLES!!!! */
824N/A
824N/A#define LEFT(r) ((r)[0])
824N/A#define RIGHT(r) ((r)[0] + (r)[2])
824N/A#define BOTTOM(r) ((r)[1])
824N/A#define TOP(r) ((r)[1] + (r)[3])
824N/A#define WIDTH(r) ((r)[2])
824N/A#define HEIGHT(r) ((r)[3])
824N/A
824N/A/* This is used in converting bounding boxes into user space to ensure
824N/A that we don't end up slopping over into another pixel */
824N/A
824N/A#define DELTA .001
824N/A
824N/A#define Offset(field) XtOffsetOf(DPSScrolledWindowRec, sw.field)
824N/A
824N/Astatic float initScale = 1.0;
824N/A
824N/Astatic XtResource resources[] = {
824N/A {XtNcontext, XtCContext, XtRDPSContext, sizeof(DPSContext),
824N/A Offset(context), XtRImmediate, (XtPointer) NULL},
824N/A {XtNareaWidth, XtCAreaWidth, XtRInt, sizeof(int),
824N/A Offset(area_width), XtRImmediate, (XtPointer) ((int) (8.5*72))},
824N/A {XtNareaHeight, XtCAreaHeight, XtRInt, sizeof(int),
824N/A Offset(area_height), XtRImmediate, (XtPointer) (11*72)},
824N/A {XtNscale, XtCScale, XtRFloat, sizeof(float),
824N/A Offset(scale), XtRFloat, (XtPointer) &initScale},
824N/A {XtNctm, XtCCtm, XtRFloatArray, sizeof(float *),
824N/A Offset(ctm_ptr), XtRImmediate, (XtPointer) NULL},
824N/A {XtNinvCtm, XtCInvCtm, XtRFloatArray, sizeof(float *),
824N/A Offset(inv_ctm_ptr), XtRImmediate, (XtPointer) NULL},
824N/A {XtNuseBackingPixmap, XtCUseBackingPixmap, XtRBoolean, sizeof(Boolean),
824N/A Offset(use_backing_pixmap), XtRImmediate, (XtPointer) True},
824N/A {XtNuseFeedbackPixmap, XtCUseFeedbackPixmap, XtRBoolean, sizeof(Boolean),
824N/A Offset(use_feedback_pixmap), XtRImmediate, (XtPointer) True},
824N/A {XtNbackingPixmap, XtCBackingPixmap, XtRPixmap, sizeof(Pixmap),
824N/A Offset(backing_pixmap), XtRImmediate, (XtPointer) None},
824N/A {XtNfeedbackPixmap, XtCFeedbackPixmap, XtRPixmap, sizeof(Pixmap),
824N/A Offset(feedback_pixmap), XtRImmediate, (XtPointer) None},
824N/A {XtNdocumentSizePixmaps, XtCDocumentSizePixmaps,
824N/A XtRBoolean, sizeof(Boolean),
824N/A Offset(document_size_pixmaps), XtRImmediate, (XtPointer) False},
824N/A {XtNwindowGState, XtCWindowGState, XtRDPSGState, sizeof(DPSGState),
824N/A Offset(window_gstate), XtRImmediate, (XtPointer) 0},
824N/A {XtNbackingGState, XtCBackingGState, XtRDPSGState, sizeof(DPSGState),
824N/A Offset(backing_gstate), XtRImmediate, (XtPointer) 0},
824N/A {XtNfeedbackGState, XtCFeedbackGState, XtRDPSGState, sizeof(DPSGState),
824N/A Offset(feedback_gstate), XtRImmediate, (XtPointer) 0},
824N/A {XtNdirtyAreas, XtCDirtyAreas, XtRFloatArray, sizeof(float *),
824N/A Offset(dirty_areas), XtRImmediate, (XtPointer) NULL},
824N/A {XtNnumDirtyAreas, XtCNumDirtyAreas, XtRShort, sizeof(short),
824N/A Offset(num_dirty_areas), XtRImmediate, (XtPointer) 0},
824N/A {XtNpixmapLimit, XtCPixmapLimit, XtRInt, sizeof(int),
824N/A Offset(pixmap_limit), XtRImmediate, (XtPointer) -1},
824N/A {XtNabsolutePixmapLimit, XtCAbsolutePixmapLimit, XtRInt, sizeof(int),
824N/A Offset(absolute_pixmap_limit), XtRImmediate, (XtPointer) 0},
824N/A {XtNwatchProgress, XtCWatchProgress, XtRBoolean, sizeof(Boolean),
824N/A Offset(watch_progress), XtRImmediate, (XtPointer) False},
824N/A {XtNwatchProgressDelay, XtCWatchProgressDelay, XtRInt, sizeof(int),
824N/A Offset(watch_progress_delay), XtRImmediate, (XtPointer) 1000},
824N/A {XtNminimalDrawing, XtCMinimalDrawing, XtRBoolean, sizeof(Boolean),
824N/A Offset(minimal_drawing), XtRImmediate, (XtPointer) False},
824N/A {XtNapplicationScrolling, XtCApplicationScrolling,
824N/A XtRBoolean, sizeof(Boolean),
824N/A Offset(application_scrolling), XtRImmediate, (XtPointer) False},
824N/A {XtNsetupCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
824N/A Offset(setup_callback), XtRCallback, (XtPointer) NULL},
824N/A {XtNexposeCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
824N/A Offset(expose_callback), XtRCallback, (XtPointer) NULL},
824N/A {XtNbackgroundCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
824N/A Offset(background_callback), XtRCallback, (XtPointer) NULL},
824N/A {XtNfeedbackCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
824N/A Offset(feedback_callback), XtRCallback, (XtPointer) NULL},
824N/A {XtNresizeCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
824N/A Offset(resize_callback), XtRCallback, (XtPointer) NULL},
824N/A};
824N/A
824N/Astatic Boolean GiveFeedbackPixmap(Widget w, Pixmap p, int width, int height, int depth, Screen *screen);
824N/Astatic Boolean SetValues(Widget old, Widget req, Widget new, ArgList args, Cardinal *num_args);
824N/Astatic Boolean TakeFeedbackPixmap(Widget w, Pixmap *p, int *width, int *height, int *depth, Screen **screen);
824N/Astatic XtGeometryResult GeometryManager(Widget w, XtWidgetGeometry *desired, XtWidgetGeometry *allowed);
824N/Astatic XtGeometryResult QueryGeometry(Widget w, XtWidgetGeometry *desired, XtWidgetGeometry *allowed);
824N/Astatic void AbortPendingDrawing(Widget w);
824N/Astatic void AddExposureToPending(DPSScrolledWindowWidget dsw, XExposeEvent *ev);
824N/Astatic void AddRectsToDirtyArea(DPSScrolledWindowWidget dsw, float *newRect, int n);
824N/Astatic void AddRectsToPending(DPSScrolledWindowWidget dsw, int *newRect, int n);
824N/Astatic void AddToDirtyArea(Widget w, float *rect, long n);
824N/Astatic void AddUserSpaceRectsToPending(DPSScrolledWindowWidget dsw, float *newRect, int n);
824N/Astatic void CallFeedbackCallback(DPSScrolledWindowWidget dsw, float *r, int n);
824N/Astatic void CheckFeedbackPixmap(DPSScrolledWindowWidget dsw);
824N/Astatic void ClassPartInitialize(WidgetClass widget_class);
824N/Astatic void ConvertPSToX(Widget w, double psX, double psY, int *xX, int *xY);
824N/Astatic void ConvertToOrigPS(DPSScrolledWindowWidget dsw, int xX, int xY, float *psX, float *psY);
824N/Astatic void ConvertToPS(DPSScrolledWindowWidget dsw, float xX, float xY, float *psX, float *psY);
824N/Astatic void ConvertToX(DPSScrolledWindowWidget dsw, float psX, float psY, int *xX, int *xY);
824N/Astatic void ConvertXToPS(Widget w, long xX, long xY, float *psX, float *psY);
824N/Astatic void CopyRectsToCurrentDrawing(DPSScrolledWindowWidget dsw, float *newRect, int n);
824N/Astatic void CopyRectsToDirtyArea(DPSScrolledWindowWidget dsw, float *newRect, int n);
824N/Astatic void CopyToFeedbackPixmap(DPSScrolledWindowWidget dsw, float *rects, int n);
824N/Astatic void Destroy(Widget widget);
824N/Astatic void DrawingAreaExpose(Widget w, XtPointer clientData, XtPointer callData);
824N/Astatic void DrawingAreaGraphicsExpose(Widget w, XtPointer clientData, XEvent *event, Boolean *goOn);
824N/Astatic void EndFeedbackDrawing(Widget w, int restore);
824N/Astatic void FinishDrawing(DPSScrolledWindowWidget dsw);
824N/Astatic void FinishPendingDrawing(Widget w);
824N/Astatic void GetDrawingInfo(Widget w, DSWDrawableType *type, Drawable *drawable, DPSGState *gstate, DPSContext *context);
824N/Astatic void GetScrollInfo(Widget w, int *h_value, int *h_size, int *h_max, int *v_value, int *v_size, int *v_max);
824N/Astatic void HScrollCallback(Widget w, XtPointer clientData, XtPointer callData);
824N/Astatic void Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args);
824N/Astatic void Realize(Widget w, XtValueMask *mask, XSetWindowAttributes *attr);
824N/Astatic void Resize(Widget w);
824N/Astatic void ScrollBy(Widget w, long dx, long dy);
824N/Astatic void ScrollMoved(DPSScrolledWindowWidget dsw);
824N/Astatic void ScrollPoint(Widget w, double psX, double psY, long xX, long xY);
824N/Astatic void ScrollTo(Widget w, long x, long y);
824N/Astatic void SetFeedbackDirtyArea(Widget w, float *rects, int count, XtPointer continue_feedback_data);
824N/Astatic void SetScale(Widget w, double scale, long fixedX, long fixedY);
824N/Astatic void SetScaleAndScroll(Widget w, double scale, double psX, double psY, long xX, long xY);
824N/Astatic void StartFeedbackDrawing(Widget w, XtPointer start_feedback_data);
824N/Astatic void UpdateDrawing(Widget w, float *rects, int count);
824N/Astatic void VScrollCallback(Widget w, XtPointer clientData, XtPointer callData);
824N/A
824N/ADPSScrolledWindowClassRec dpsScrolledWindowClassRec = {
824N/A /* Core class part */
824N/A {
824N/A /* superclass */ (WidgetClass) &xmManagerClassRec,
824N/A /* class_name */ "DPSScrolledWindow",
824N/A /* widget_size */ sizeof(DPSScrolledWindowRec),
824N/A /* class_initialize */ NULL,
824N/A /* class_part_initialize */ ClassPartInitialize,
824N/A /* class_inited */ False,
824N/A /* initialize */ Initialize,
824N/A /* initialize_hook */ NULL,
824N/A /* realize */ Realize,
824N/A /* actions */ NULL,
824N/A /* num_actions */ 0,
824N/A /* resources */ resources,
824N/A /* num_resources */ XtNumber(resources),
824N/A /* xrm_class */ NULLQUARK,
824N/A /* compress_motion */ True,
824N/A /* compress_exposure */ XtExposeCompressMultiple,
824N/A /* compress_enterleave */ True,
824N/A /* visible_interest */ False,
824N/A /* destroy */ Destroy,
824N/A /* resize */ Resize,
824N/A /* expose */ NULL,
824N/A /* set_values */ SetValues,
824N/A /* set_values_hook */ NULL,
824N/A /* set_values_almost */ XtInheritSetValuesAlmost,
824N/A /* get_values_hook */ NULL,
824N/A /* accept_focus */ NULL,
824N/A /* version */ XtVersion,
824N/A /* callback offsets */ NULL,
824N/A /* tm_table */ NULL,
824N/A /* query_geometry */ QueryGeometry,
824N/A /* display_accelerator */ NULL,
824N/A /* extension */ NULL,
824N/A },
824N/A /* Composite class part */
824N/A {
824N/A /* geometry_manager */ GeometryManager,
824N/A /* change_managed */ NULL,
824N/A /* insert_child */ XtInheritInsertChild,
824N/A /* delete_child */ XtInheritDeleteChild,
824N/A /* extension */ NULL,
824N/A },
824N/A /* Constraint class part */
824N/A {
824N/A /* resources */ NULL,
824N/A /* num_resources */ 0,
824N/A /* constraint_size */ 0,
824N/A /* initialize */ NULL,
824N/A /* destroy */ NULL,
824N/A /* set_values */ NULL,
824N/A /* extension */ NULL,
824N/A },
824N/A /* Manager class part */
824N/A {
824N/A /* translations */ XtInheritTranslations,
824N/A /* syn_resources */ NULL,
824N/A /* num_syn_resources */ 0,
824N/A /* syn_constraint_resources */ NULL,
824N/A /* num_syn_constraint_resources */ 0,
824N/A /* parent_process */ XmInheritParentProcess,
824N/A /* extension */ NULL,
824N/A },
824N/A /* DPSScrolledWindow class part */
824N/A {
824N/A /* set_scale */ SetScale,
824N/A /* scroll_point */ ScrollPoint,
824N/A /* scroll_by */ ScrollBy,
824N/A /* scroll_to */ ScrollTo,
824N/A /* set_scale_and_scroll */ SetScaleAndScroll,
824N/A /* convert_x_to_ps */ ConvertXToPS,
824N/A /* convert_ps_to_x */ ConvertPSToX,
824N/A /* add_to_dirty_area */ AddToDirtyArea,
824N/A /* take_feedback_pixmap */ TakeFeedbackPixmap,
824N/A /* give_feedback_pixmap */ GiveFeedbackPixmap,
824N/A /* start_feedback_drawing */ StartFeedbackDrawing,
824N/A /* end_feedback_drawing */ EndFeedbackDrawing,
824N/A /* set_feedback_dirty_area */ SetFeedbackDirtyArea,
824N/A /* finish_pending_drawing */ FinishPendingDrawing,
824N/A /* abort_pending_drawing */ AbortPendingDrawing,
824N/A /* get_drawing_info */ GetDrawingInfo,
824N/A /* update_drawing */ UpdateDrawing,
824N/A /* get_scroll_info */ GetScrollInfo,
824N/A /* extension */ NULL,
824N/A }
824N/A};
824N/A
824N/AWidgetClass dpsScrolledWindowWidgetClass =
824N/A (WidgetClass) &dpsScrolledWindowClassRec;
824N/A
824N/A/***** UTILITY FUNCTIONS *****/
824N/A
824N/Astatic void PrintRectList(float *r, short num_r)
824N/A{
824N/A int i;
824N/A
824N/A for (i = 0; i < num_r; i++) {
824N/A printf("Rectangle %d: ", i);
824N/A printf("X %g Y %g W %g H %g\n", r[0], r[1], r[2], r[3]);
824N/A r += 4;
824N/A }
824N/A}
824N/A
824N/A/* Make sure the list pointed to by r can hold n more rectangles. Always
824N/A grow by at least min_grow */
824N/A
824N/Astatic void GrowRectList(
824N/A float **r,
824N/A short *r_size,
824N/A short num_r,
824N/A int n, int min_grow)
824N/A{
824N/A if (*r_size < num_r + n) {
824N/A if (min_grow > 1 && num_r + n - *r_size < min_grow) {
824N/A *r_size += min_grow;
824N/A } else *r_size = num_r + n;
824N/A *r = (float *) XtRealloc((char *) *r, *r_size * 4 * sizeof(float));
824N/A }
824N/A}
824N/A
824N/Astatic void GrowIntRectList(
824N/A int **r,
824N/A short *r_size,
824N/A short num_r,
824N/A int n, int min_grow)
824N/A{
824N/A if (*r_size < num_r + n) {
824N/A if (min_grow > 1 && num_r + n - *r_size < min_grow) {
824N/A *r_size += min_grow;
824N/A } else *r_size = num_r + n;
824N/A *r = (int *) XtRealloc((char *) *r, *r_size * 4 * sizeof(int));
824N/A }
824N/A}
824N/A
824N/Astatic Boolean Intersects(float *r1, float *r2)
824N/A{
824N/A if (RIGHT(r1) <= LEFT(r2)) return False;
824N/A if (RIGHT(r2) <= LEFT(r1)) return False;
824N/A if (TOP(r1) <= BOTTOM(r2)) return False;
824N/A if (TOP(r2) <= BOTTOM(r1)) return False;
824N/A
824N/A return True;
824N/A}
824N/A
824N/A/* Subtract sub from src, putting result into dst. Return rectangle count */
824N/A
824N/Astatic int Subtract(float *src, float *sub, float *dst)
824N/A{
824N/A int n = 0;
824N/A
824N/A /* If bottom of sub is greater than bottom of src, there's a
824N/A rectangle across the bottom */
824N/A if (BOTTOM(sub) > BOTTOM(src)) {
824N/A LEFT(dst) = LEFT(src);
824N/A BOTTOM(dst) = BOTTOM(src);
824N/A WIDTH(dst) = WIDTH(src);
824N/A HEIGHT(dst) = BOTTOM(sub) - BOTTOM(src);
824N/A n++;
824N/A dst += 4;
824N/A }
824N/A
824N/A /* If left of sub is greater than left of src, there's a left rectangle. */
824N/A if (LEFT(sub) > LEFT(src)) {
824N/A LEFT(dst) = LEFT(src);
824N/A BOTTOM(dst) = MAX(BOTTOM(src), BOTTOM(sub));
824N/A WIDTH(dst) = LEFT(sub) - LEFT(src);
824N/A HEIGHT(dst) = MIN(TOP(src), TOP(sub)) - BOTTOM(dst);
824N/A n++;
824N/A dst += 4;
824N/A }
824N/A
824N/A /* If right of sub is less than right of src, there's a right rect */
824N/A if (RIGHT(sub) < RIGHT(src)) {
824N/A LEFT(dst) = RIGHT(sub);
824N/A BOTTOM(dst) = MAX(BOTTOM(src), BOTTOM(sub));
824N/A WIDTH(dst) = RIGHT(src) - RIGHT(sub);
824N/A HEIGHT(dst) = MIN(TOP(src), TOP(sub)) - BOTTOM(dst);
824N/A n++;
824N/A dst += 4;
824N/A }
824N/A
824N/A /* If top of sub is less than top of src, there's a top rectangle */
824N/A if (TOP(sub) < TOP(src)) {
824N/A LEFT(dst) = LEFT(src);
824N/A BOTTOM(dst) = TOP(sub);
824N/A WIDTH(dst) = WIDTH(src);
824N/A HEIGHT(dst) = TOP(src) - TOP(sub);
824N/A n++;
824N/A dst += 4;
824N/A }
824N/A
824N/A return n;
824N/A}
824N/A
824N/Astatic void Copy(float *src, float *dst)
824N/A{
824N/A LEFT(dst) = LEFT(src);
824N/A BOTTOM(dst) = BOTTOM(src);
824N/A WIDTH(dst) = WIDTH(src);
824N/A HEIGHT(dst) = HEIGHT(src);
824N/A}
824N/A
824N/Astatic void Intersection(float *r1, float *r2, float *dst)
824N/A{
824N/A LEFT(dst) = MAX(LEFT(r1), LEFT(r2));
824N/A BOTTOM(dst) = MAX(BOTTOM(r1), BOTTOM(r2));
824N/A WIDTH(dst) = MIN(RIGHT(r1), RIGHT(r2)) - LEFT(dst);
824N/A HEIGHT(dst) = MIN(TOP(r1), TOP(r2)) - BOTTOM(dst);
824N/A}
824N/A
824N/A/* These are used by the SubtractRects and IntersectRects procedures */
824N/A
824N/Astatic float *rbuf = NULL;
824N/Astatic short rbuf_size = 0;
824N/A#define GROW_BUF 10
824N/A
824N/A/* Replace the rectangle list in src with src minus sub */
824N/A
824N/Astatic void SubtractRects(
824N/A float **src,
824N/A short *src_size,
824N/A short *num_src,
824N/A float *sub,
824N/A int num_sub)
824N/A{
824N/A short num_rbuf;
824N/A float *r;
824N/A int i;
824N/A
824N/A /* Go through, subtracting the first sub rectangle from each src
824N/A rectangle. Put the result in the internal buffer, then copy this
824N/A list to the src. Repeat for each sub rectangle. */
824N/A
824N/A while (num_sub > 0) {
824N/A num_rbuf = 0;
824N/A for (r = *src, i = 0; i < *num_src; r += 4, i++) {
824N/A if (Intersects(r, sub)) {
824N/A /* Subtract sub from r, putting result into rbuf. First
824N/A make sure there are at least 4 spaces in the buffer */
824N/A GrowRectList(&rbuf, &rbuf_size, num_rbuf, 4, GROW_BUF);
824N/A
824N/A /* Do the subtraction */
824N/A num_rbuf += Subtract(r, sub, rbuf + (num_rbuf*4));
824N/A } else {
824N/A /* Copy r into buffer */
824N/A GrowRectList(&rbuf, &rbuf_size, num_rbuf, 1, GROW_BUF);
824N/A Copy(r, rbuf + (num_rbuf*4));
824N/A num_rbuf++;
824N/A }
824N/A }
824N/A
824N/A /* Copy buffered rectangles back into src */
824N/A GrowRectList(src, src_size, 0, num_rbuf, 1);
824N/A for (i = 0; i < num_rbuf * 4; i++) (*src)[i] = rbuf[i];
824N/A *num_src = num_rbuf;
824N/A
824N/A /* Check if we've taken everything away */
824N/A if (*num_src == 0) return;
824N/A
824N/A /* Skip on to the next sub rectangle */
824N/A num_sub--;
824N/A sub += 4;
824N/A }
824N/A}
824N/A
824N/A/* Replace list r1 with the intersection of r1 and r2 */
824N/A
824N/Astatic void IntersectRects(
824N/A float **r1,
824N/A short *r1_size,
824N/A short *num_r1,
824N/A float *r2,
824N/A int num_r2)
824N/A{
824N/A short num_rbuf = 0;
824N/A float *r;
824N/A int i;
824N/A
824N/A /* Fairly straightforward. Intersect each rectangle in r1 with each
824N/A rectangle in r2, then copy the results to r1 */
824N/A
824N/A while (num_r2 > 0) {
824N/A for (r = *r1, i = 0; i < *num_r1; r += 4, i++) {
824N/A if (Intersects(r, r2)) {
824N/A GrowRectList(&rbuf, &rbuf_size, num_rbuf, 1, GROW_BUF);
824N/A Intersection(r, r2, rbuf + (num_rbuf*4));
824N/A num_rbuf++;
824N/A }
824N/A }
824N/A num_r2--;
824N/A r2 += 4;
824N/A }
824N/A
824N/A /* Copy intersection rectangles back into r1 */
824N/A GrowRectList(r1, r1_size, 0, num_rbuf, 1);
824N/A for (i = 0; i < num_rbuf * 4; i++) (*r1)[i] = rbuf[i];
824N/A *num_r1 = num_rbuf;
824N/A}
824N/A
824N/Astatic void SimplifyRects(float *rect, short *num)
824N/A{
824N/A int i, j, k;
824N/A float *r, *r1;
824N/A
824N/A i = 0;
824N/A while (i < *num) {
824N/A r = rect + (i * 4);
824N/A if (WIDTH(r) == 0 || HEIGHT(r) == 0) {
824N/A for (k = 4*(i+1); k < *num * 4; k++) rect[k-4] = rect[k];
824N/A (*num)--;
824N/A goto LOOPEND;
824N/A }
824N/A j = i+1;
824N/A while (j < *num) {
824N/A r1 = rect + (j * 4);
824N/A if (TOP(r1) <= TOP(r) && BOTTOM(r1) >= BOTTOM(r) &&
824N/A LEFT(r1) >= LEFT(r) && RIGHT(r1) <= RIGHT(r)) {
824N/A for (k = 4*(j+1); k < *num * 4; k++) rect[k-4] = rect[k];
824N/A (*num)--;
824N/A } else if (TOP(r) <= TOP(r1) && BOTTOM(r) >= BOTTOM(r1) &&
824N/A LEFT(r) >= LEFT(r1) && RIGHT(r) <= RIGHT(r1)) {
824N/A for (k = 4*(i+1); k < *num * 4; k++) rect[k-4] = rect[k];
824N/A (*num)--;
824N/A goto LOOPEND;
824N/A } else j++;
824N/A }
824N/A i++;
824N/ALOOPEND:;
824N/A }
824N/A}
824N/A
824N/Astatic void ComputeOffsets(DPSScrolledWindowWidget dsw, int *dx, int *dy)
824N/A{
824N/A if (dsw->sw.doing_feedback && dsw->sw.feedback_pixmap != None) {
824N/A *dx = *dy = 0;
824N/A } else {
824N/A if (dsw->sw.pixmap_width == dsw->sw.drawing_area->core.width) *dx = 0;
824N/A else *dx = -dsw->sw.origin_x;
824N/A if (dsw->sw.pixmap_height == dsw->sw.drawing_area->core.height) *dy = 0;
824N/A else *dy = CEIL(dsw->sw.drawing_height) - dsw->sw.origin_y;
824N/A }
824N/A}
824N/A
824N/Astatic void ClassPartInitialize(WidgetClass widget_class)
824N/A{
824N/A register DPSScrolledWindowWidgetClass wc =
824N/A (DPSScrolledWindowWidgetClass) widget_class;
824N/A DPSScrolledWindowWidgetClass super =
824N/A (DPSScrolledWindowWidgetClass) wc->core_class.superclass;
824N/A
824N/A if (wc->sw_class.set_scale == InheritSetScale) {
824N/A wc->sw_class.set_scale = super->sw_class.set_scale;
824N/A }
824N/A if (wc->sw_class.scroll_point == InheritScrollPoint) {
824N/A wc->sw_class.scroll_point = super->sw_class.scroll_point;
824N/A }
824N/A if (wc->sw_class.scroll_by == InheritScrollBy) {
824N/A wc->sw_class.scroll_by = super->sw_class.scroll_by;
824N/A }
824N/A if (wc->sw_class.scroll_to == InheritScrollTo) {
824N/A wc->sw_class.scroll_to = super->sw_class.scroll_to;
824N/A }
824N/A if (wc->sw_class.set_scale_and_scroll == InheritSetScaleAndScroll) {
824N/A wc->sw_class.set_scale_and_scroll =
824N/A super->sw_class.set_scale_and_scroll;
824N/A }
824N/A if (wc->sw_class.convert_x_to_ps == InheritConvertXToPS) {
824N/A wc->sw_class.convert_x_to_ps = super->sw_class.convert_x_to_ps;
824N/A }
824N/A if (wc->sw_class.convert_ps_to_x == InheritConvertPSToX) {
824N/A wc->sw_class.convert_ps_to_x = super->sw_class.convert_ps_to_x;
824N/A }
824N/A if (wc->sw_class.add_to_dirty_area == InheritAddToDirtyArea) {
824N/A wc->sw_class.add_to_dirty_area = super->sw_class.add_to_dirty_area;
824N/A }
824N/A if (wc->sw_class.take_feedback_pixmap == InheritTakeFeedbackPixmap) {
824N/A wc->sw_class.take_feedback_pixmap =
824N/A super->sw_class.take_feedback_pixmap;
824N/A }
824N/A if (wc->sw_class.give_feedback_pixmap == InheritGiveFeedbackPixmap) {
824N/A wc->sw_class.give_feedback_pixmap =
824N/A super->sw_class.give_feedback_pixmap;
824N/A }
824N/A if (wc->sw_class.start_feedback_drawing == InheritStartFeedbackDrawing) {
824N/A wc->sw_class.start_feedback_drawing =
824N/A super->sw_class.start_feedback_drawing;
824N/A }
824N/A if (wc->sw_class.end_feedback_drawing == InheritEndFeedbackDrawing) {
824N/A wc->sw_class.end_feedback_drawing =
824N/A super->sw_class.end_feedback_drawing;
824N/A }
824N/A if (wc->sw_class.set_feedback_dirty_area == InheritSetFeedbackDirtyArea) {
824N/A wc->sw_class.set_feedback_dirty_area =
824N/A super->sw_class.set_feedback_dirty_area;
824N/A }
824N/A if (wc->sw_class.finish_pending_drawing == InheritFinishPendingDrawing) {
824N/A wc->sw_class.finish_pending_drawing =
824N/A super->sw_class.finish_pending_drawing;
824N/A }
824N/A if (wc->sw_class.abort_pending_drawing == InheritAbortPendingDrawing) {
824N/A wc->sw_class.abort_pending_drawing =
824N/A super->sw_class.abort_pending_drawing;
824N/A }
824N/A if (wc->sw_class.get_drawing_info == InheritGetDrawingInfo) {
824N/A wc->sw_class.get_drawing_info = super->sw_class.get_drawing_info;
824N/A }
824N/A if (wc->sw_class.update_drawing == InheritUpdateDrawing) {
824N/A wc->sw_class.update_drawing = super->sw_class.update_drawing;
824N/A }
824N/A if (wc->sw_class.get_scroll_info == InheritGetScrollInfo) {
824N/A wc->sw_class.get_scroll_info = super->sw_class.get_scroll_info;
824N/A }
824N/A}
824N/A
824N/Astatic void CreateChildren(DPSScrolledWindowWidget dsw)
824N/A{
824N/A Widget w;
824N/A
824N/A w = dsw->sw.scrolled_window =
824N/A XtVaCreateManagedWidget("scrolledWindow",
824N/A xmScrolledWindowWidgetClass,
824N/A (Widget) dsw,
824N/A XtNwidth, dsw->core.width,
824N/A XtNheight, dsw->core.height,
824N/A XmNscrollingPolicy, XmAPPLICATION_DEFINED,
824N/A NULL);
824N/A
824N/A dsw->sw.h_scroll =
824N/A XtVaCreateManagedWidget("horizontalScrollBar",
824N/A xmScrollBarWidgetClass, w,
824N/A XmNorientation, XmHORIZONTAL,
824N/A NULL);
824N/A XtAddCallback(dsw->sw.h_scroll, XmNvalueChangedCallback, HScrollCallback,
824N/A (XtPointer) dsw);
824N/A XtAddCallback(dsw->sw.h_scroll, XmNdragCallback, HScrollCallback,
824N/A (XtPointer) dsw);
824N/A
824N/A dsw->sw.v_scroll =
824N/A XtVaCreateManagedWidget("verticalScrollBar",
824N/A xmScrollBarWidgetClass, w,
824N/A XmNorientation, XmVERTICAL,
824N/A NULL);
824N/A XtAddCallback(dsw->sw.v_scroll, XmNvalueChangedCallback, VScrollCallback,
824N/A (XtPointer) dsw);
824N/A XtAddCallback(dsw->sw.v_scroll, XmNdragCallback, VScrollCallback,
824N/A (XtPointer) dsw);
824N/A
824N/A
824N/A dsw->sw.drawing_area =
824N/A XtVaCreateManagedWidget("drawingArea",
824N/A xmDrawingAreaWidgetClass, w, NULL);
824N/A XtAddCallback(dsw->sw.drawing_area, XtNexposeCallback, DrawingAreaExpose,
824N/A (XtPointer) dsw);
824N/A XtAddRawEventHandler(dsw->sw.drawing_area, 0, True,
824N/A DrawingAreaGraphicsExpose, (XtPointer) dsw);
824N/A
824N/A XmScrolledWindowSetAreas(w, dsw->sw.h_scroll, dsw->sw.v_scroll,
824N/A dsw->sw.drawing_area);
824N/A}
824N/A
824N/A/* ARGSUSED */
824N/A
824N/Astatic void Initialize(Widget request, Widget new, ArgList args, Cardinal *num_args)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) new;
824N/A XGCValues gcVal;
824N/A Bool inited;
824N/A
824N/A if (dsw->sw.area_width <= 0) dsw->sw.area_width = 8.5*72;
824N/A if (dsw->sw.area_height <= 0) dsw->sw.area_height = 11*72;
824N/A if (dsw->sw.scale <= 0) dsw->sw.scale = 1.0;
824N/A dsw->sw.ctm_ptr = dsw->sw.ctm;
824N/A dsw->sw.inv_ctm_ptr = dsw->sw.inv_ctm;
824N/A dsw->sw.backing_pixmap = None;
824N/A dsw->sw.feedback_pixmap = None;
824N/A dsw->sw.window_gstate = 0;
824N/A dsw->sw.backing_gstate = 0;
824N/A dsw->sw.feedback_gstate = 0;
824N/A dsw->sw.scrolling = False;
824N/A dsw->sw.num_pending_expose = dsw->sw.pending_expose_size = 0;
824N/A dsw->sw.pending_expose = NULL;
824N/A dsw->sw.num_pending_dirty = dsw->sw.pending_dirty_size = 0;
824N/A dsw->sw.pending_dirty = NULL;
824N/A dsw->sw.num_current_drawing = dsw->sw.current_drawing_size = 0;
824N/A dsw->sw.current_drawing = NULL;
824N/A dsw->sw.num_prev_dirty_areas = dsw->sw.prev_dirty_areas_size = 0;
824N/A dsw->sw.prev_dirty_areas = NULL;
824N/A dsw->sw.drawing_stage = DSWStart;
824N/A dsw->sw.work = 0;
824N/A dsw->sw.big_pixmap = False;
824N/A
824N/A /* Set the initial dirty area to everything */
824N/A
824N/A dsw->sw.dirty_areas_size = 0;
824N/A dsw->sw.dirty_areas = NULL;
824N/A
824N/A GrowRectList(&dsw->sw.dirty_areas, &dsw->sw.dirty_areas_size, 0, 1, 1);
824N/A dsw->sw.num_dirty_areas = 1;
824N/A LEFT(dsw->sw.dirty_areas) = 0.0;
824N/A BOTTOM(dsw->sw.dirty_areas) = 0.0;
824N/A WIDTH(dsw->sw.dirty_areas) = dsw->sw.area_width;
824N/A HEIGHT(dsw->sw.dirty_areas) = dsw->sw.area_height;
824N/A
824N/A /* Make the scratch list have at least one element */
824N/A
824N/A dsw->sw.num_scratch = dsw->sw.scratch_size = 0;
824N/A dsw->sw.scratch = NULL;
824N/A GrowRectList(&dsw->sw.scratch, &dsw->sw.scratch_size, 0, 1, 1);
824N/A
824N/A /* Get the context */
824N/A
824N/A if (dsw->sw.context == NULL) {
824N/A dsw->sw.context = XDPSGetSharedContext(XtDisplay(dsw));
824N/A }
824N/A
824N/A /* Watch progress only works with pass-through event dispatching */
824N/A
824N/A if (dsw->sw.watch_progress &&
824N/A XDPSSetEventDelivery(XtDisplay(dsw), dps_event_query) !=
824N/A dps_event_pass_through) dsw->sw.watch_progress = False;
824N/A
824N/A if (_XDPSTestComponentInitialized(dsw->sw.context,
824N/A dps_init_bit_dsw, &inited) ==
824N/A dps_status_unregistered_context) {
824N/A XDPSRegisterContext(dsw->sw.context, False);
824N/A }
824N/A
824N/A dsw->sw.use_saved_scroll = False;
824N/A dsw->sw.context_inited = False;
824N/A dsw->sw.doing_feedback = False;
824N/A dsw->sw.feedback_displayed = False;
824N/A
824N/A CreateChildren(dsw);
824N/A
824N/A dsw->sw.ge_gc = XtGetGC(dsw->sw.drawing_area, 0, (XGCValues *) NULL);
824N/A
824N/A gcVal.graphics_exposures = False;
824N/A dsw->sw.no_ge_gc = XtGetGC(dsw->sw.drawing_area, GCGraphicsExposures,
824N/A &gcVal);
824N/A}
824N/A
824N/Astatic void Destroy(Widget widget)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) widget;
824N/A
824N/A if (dsw->sw.backing_pixmap != None) {
824N/A XFreePixmap(XtDisplay(dsw), dsw->sw.backing_pixmap);
824N/A }
824N/A if (dsw->sw.feedback_pixmap != None) {
824N/A XFreePixmap(XtDisplay(dsw), dsw->sw.feedback_pixmap);
824N/A }
824N/A
824N/A if (dsw->sw.window_gstate != 0) {
824N/A XDPSFreeContextGState(dsw->sw.context, dsw->sw.window_gstate);
824N/A }
824N/A if (dsw->sw.backing_gstate != 0) {
824N/A XDPSFreeContextGState(dsw->sw.context, dsw->sw.backing_gstate);
824N/A }
824N/A if (dsw->sw.feedback_gstate != 0) {
824N/A XDPSFreeContextGState(dsw->sw.context, dsw->sw.feedback_gstate);
824N/A }
824N/A
824N/A if (dsw->sw.pending_expose != NULL) {
824N/A XtFree((char *) dsw->sw.pending_expose);
824N/A }
824N/A if (dsw->sw.current_drawing != NULL) {
824N/A XtFree((char *) dsw->sw.current_drawing);
824N/A }
824N/A if (dsw->sw.prev_dirty_areas != NULL) {
824N/A XtFree((char *) dsw->sw.prev_dirty_areas);
824N/A }
824N/A if (dsw->sw.dirty_areas != NULL) XtFree((char *) dsw->sw.dirty_areas);
824N/A if (dsw->sw.pending_dirty != NULL) XtFree((char *) dsw->sw.pending_dirty);
824N/A if (dsw->sw.scratch != NULL) XtFree((char *) dsw->sw.scratch);
824N/A
824N/A XtReleaseGC(widget, dsw->sw.ge_gc);
824N/A XtReleaseGC(widget, dsw->sw.no_ge_gc);
824N/A}
824N/A
824N/Astatic void SetOriginAndGetTransform(DPSScrolledWindowWidget dsw)
824N/A{
824N/A float psX, psY;
824N/A
824N/A ConvertToOrigPS(dsw, dsw->sw.origin_x, dsw->sw.origin_y, &psX, &psY);
824N/A _DPSSWSetMatrixAndGetTransform(dsw->sw.context, psX, psY, dsw->sw.scale,
824N/A dsw->sw.origin_x, dsw->sw.origin_y,
824N/A dsw->sw.ctm, dsw->sw.inv_ctm,
824N/A &dsw->sw.x_offset, &dsw->sw.y_offset);
824N/A}
824N/A
824N/Astatic void SetPixmapOrigin(DPSScrolledWindowWidget dsw)
824N/A{
824N/A float psX, psY;
824N/A
824N/A ConvertToOrigPS(dsw, dsw->sw.origin_x, dsw->sw.origin_y, &psX, &psY);
824N/A _DPSSWSetMatrix(dsw->sw.context, psX, psY, dsw->sw.scale,
824N/A dsw->sw.origin_x, dsw->sw.origin_y);
824N/A}
824N/A
824N/Astatic void SetPixmapOffset(DPSScrolledWindowWidget dsw)
824N/A{
824N/A int ox, oy;
824N/A
824N/A if (dsw->sw.pixmap_width <= (int) dsw->sw.drawing_area->core.width) ox = 0;
824N/A else ox = -dsw->sw.origin_x;
824N/A if (dsw->sw.pixmap_height <= (int) dsw->sw.drawing_area->core.height) {
824N/A oy = dsw->sw.drawing_area->core.height;
824N/A } else oy = dsw->sw.pixmap_height - dsw->sw.origin_y +
824N/A dsw->sw.drawing_area->core.height;
824N/A
824N/A DPSsetXoffset(dsw->sw.context, ox, oy);
824N/A}
824N/A
824N/Astatic Boolean pixmapError;
824N/Astatic int (*oldHandler)(Display *, XErrorEvent *);
824N/A
824N/Astatic int PixmapHandler(Display *dpy, XErrorEvent *error)
824N/A{
824N/A if (error->error_code == BadAlloc &&
824N/A error->request_code == X_CreatePixmap) {
824N/A pixmapError = True;
824N/A return 0;
824N/A } else return (*oldHandler) (dpy, error);
824N/A}
824N/A
824N/Astatic Pixmap AllocPixmap(DPSScrolledWindowWidget dsw, unsigned w, unsigned h)
824N/A{
824N/A Pixmap p;
824N/A unsigned int dBytes;
824N/A Widget wid = dsw->sw.drawing_area;
824N/A unsigned area = (w * h);
824N/A
824N/A if (dsw->sw.pixmap_limit > 0) {
824N/A if (area > (unsigned)dsw->sw.pixmap_limit) return None;
824N/A } else if (dsw->sw.pixmap_limit < 0
824N/A && area > (unsigned)(dsw->sw.unscaled_width * dsw->sw.unscaled_height)
824N/A && area > (unsigned)(wid->core.width * wid->core.height)) return None;
824N/A
824N/A if (dsw->sw.absolute_pixmap_limit > 0) {
824N/A dBytes = (wid->core.depth + 7) / 8; /* Convert into bytes */
824N/A if (area * dBytes > (unsigned)dsw->sw.absolute_pixmap_limit * 1024) {
824N/A return None;
824N/A }
824N/A }
824N/A
824N/A XSync(XtDisplay(dsw), False);
824N/A oldHandler = XSetErrorHandler(PixmapHandler);
824N/A pixmapError = False;
824N/A p = XCreatePixmap(XtDisplay(dsw), XtWindow(dsw->sw.drawing_area), w, h,
824N/A wid->core.depth);
824N/A XSync(XtDisplay(dsw), False);
824N/A (void) XSetErrorHandler(oldHandler);
824N/A if (pixmapError) return None;
824N/A else return p;
824N/A}
824N/A
824N/Astatic void CreateBackingPixmap(DPSScrolledWindowWidget dsw)
824N/A{
824N/A Pixmap p;
824N/A
824N/A if (dsw->sw.document_size_pixmaps) {
824N/A dsw->sw.pixmap_width =
824N/A MAX(CEIL(dsw->sw.drawing_width),
824N/A (int) dsw->sw.drawing_area->core.width);
824N/A dsw->sw.pixmap_height =
824N/A MAX(CEIL(dsw->sw.drawing_height),
824N/A (int) dsw->sw.drawing_area->core.height);
824N/A
824N/A p = dsw->sw.backing_pixmap =
824N/A AllocPixmap(dsw, dsw->sw.pixmap_width, dsw->sw.pixmap_height);
824N/A if (p != None) {
824N/A dsw->sw.big_pixmap =
824N/A dsw->sw.pixmap_width >
824N/A (int) dsw->sw.drawing_area->core.width ||
824N/A dsw->sw.pixmap_height >
824N/A (int) dsw->sw.drawing_area->core.height;
824N/A return;
824N/A }
824N/A }
824N/A dsw->sw.big_pixmap = False;
824N/A dsw->sw.pixmap_width = dsw->sw.drawing_area->core.width;
824N/A dsw->sw.pixmap_height = dsw->sw.drawing_area->core.height;
824N/A p = dsw->sw.backing_pixmap =
824N/A AllocPixmap(dsw, dsw->sw.pixmap_width, dsw->sw.pixmap_height);
824N/A if (p == None) dsw->sw.pixmap_width = dsw->sw.pixmap_height = 0;
824N/A}
824N/A
824N/Astatic void FreeBackingPixmap(DPSScrolledWindowWidget dsw)
824N/A{
824N/A if (dsw->sw.backing_pixmap == None) return;
824N/A XFreePixmap(XtDisplay(dsw), dsw->sw.backing_pixmap);
824N/A dsw->sw.backing_pixmap = None;
824N/A dsw->sw.big_pixmap = False;
824N/A dsw->sw.pixmap_width = dsw->sw.pixmap_height = 0;
824N/A XDPSFreeContextGState(dsw->sw.context, dsw->sw.backing_gstate);
824N/A}
824N/A
824N/Astatic void SetDrawingAreaPosition(
824N/A DPSScrolledWindowWidget dsw,
824N/A float ix,
824N/A float iy,
824N/A int vx,
824N/A int vy,
824N/A Boolean setOrigin)
824N/A{
824N/A int xoff, yoff;
824N/A int hSize, vSize;
824N/A float scrollX, scrollY;
824N/A
824N/A /* Convert ix, iy into X units */
824N/A
824N/A ix *= dsw->sw.drawing_width / dsw->sw.area_width;
824N/A iy *= dsw->sw.drawing_height / dsw->sw.area_height;
824N/A
824N/A if ((int)dsw->sw.drawing_area->core.width >= CEIL(dsw->sw.drawing_width)) {
824N/A /* The scaled width is narrower than the view window, so
824N/A center the picture and set scroll bar to be unscrollable */
824N/A
824N/A xoff = ((int) dsw->sw.drawing_area->core.width -
824N/A CEIL(dsw->sw.drawing_width))
824N/A / 2.0;
824N/A scrollX = 0;
824N/A hSize = CEIL(dsw->sw.drawing_width);
824N/A } else {
824N/A /* The scaled width is larger than the view window, so
824N/A turn on the scroll bar, and set up its maximum and
824N/A slider size. Do this by converting the image offset into X
824N/A coordinates and subtracting the view offset */
824N/A
824N/A scrollX = ix - vx;
824N/A scrollX = MAX(scrollX, 0);
824N/A scrollX = MIN(scrollX, CEIL(dsw->sw.drawing_width) -
824N/A (int) dsw->sw.drawing_area->core.width);
824N/A hSize = dsw->sw.drawing_area->core.width;
824N/A xoff = -(int) (scrollX + 0.5);
824N/A }
824N/A
824N/A /* Now do the same thing for the height. We want to compute the offset
824N/A relative to the lower left corner, but X coordinates are relative
824N/A to the upper left, so the drawing height must be added in. Also, since
824N/A the coordinates go in the other direction, the view offset must be
824N/A added, not subtracted. */
824N/A
824N/A if ((int) dsw->sw.drawing_area->core.height >=
824N/A CEIL(dsw->sw.drawing_height)) {
824N/A yoff = ((int) dsw->sw.drawing_area->core.height -
824N/A CEIL(dsw->sw.drawing_height)) / 2.0;
824N/A scrollY = CEIL(dsw->sw.drawing_height) -
824N/A (int) dsw->sw.drawing_area->core.height;
824N/A vSize = CEIL(dsw->sw.drawing_height);
824N/A } else {
824N/A scrollY = iy + vy - (int) dsw->sw.drawing_area->core.height;
824N/A scrollY = MAX(scrollY, 0);
824N/A scrollY = MIN(scrollY, CEIL(dsw->sw.drawing_height) -
824N/A (int) dsw->sw.drawing_area->core.height);
824N/A vSize = dsw->sw.drawing_area->core.height;
824N/A yoff = -(int) (scrollY + 0.5);
824N/A }
824N/A
824N/A /* Update the scrollbars */
824N/A dsw->sw.scroll_x = (int) (scrollX + 0.5);
824N/A dsw->sw.scroll_y = (int) (CEIL(dsw->sw.drawing_height) -
824N/A (int) dsw->sw.drawing_area->core.height -
824N/A scrollY + 0.5);
824N/A
824N/A yoff = dsw->sw.drawing_area->core.height - yoff;
824N/A
824N/A dsw->sw.scroll_h_value = dsw->sw.scroll_x;
824N/A dsw->sw.scroll_h_size = hSize;
824N/A dsw->sw.scroll_h_max = CEIL(dsw->sw.drawing_width);
824N/A dsw->sw.scroll_v_value = dsw->sw.scroll_y;
824N/A dsw->sw.scroll_v_size = vSize;
824N/A dsw->sw.scroll_v_max = CEIL(dsw->sw.drawing_height);
824N/A
824N/A if (!dsw->sw.application_scrolling) {
824N/A XtVaSetValues(dsw->sw.h_scroll, XmNmaximum, dsw->sw.scroll_h_max,
824N/A XmNvalue, dsw->sw.scroll_x, XmNsliderSize, hSize, NULL);
824N/A XtVaSetValues(dsw->sw.v_scroll, XmNmaximum, dsw->sw.scroll_v_max,
824N/A XmNvalue, dsw->sw.scroll_y, XmNsliderSize, vSize, NULL);
824N/A }
824N/A
824N/A if (setOrigin) {
824N/A /* Set the origin in the X window to reflect the new location */
824N/A dsw->sw.origin_x = xoff;
824N/A dsw->sw.origin_y = yoff;
824N/A }
824N/A}
824N/A
824N/Astatic void DrawBackground(
824N/A DPSScrolledWindowWidget dsw,
824N/A DSWDrawableType which)
824N/A{
824N/A DSWExposeCallbackRec e;
824N/A
824N/A e.type = which;
824N/A e.directions = DSWFinish;
824N/A e.results = DSWUndefined;
824N/A e.first = True;
824N/A e.background = True;
824N/A if (which == DSWBackingPixmap) {
824N/A e.drawable = dsw->sw.backing_pixmap;
824N/A e.gstate = dsw->sw.backing_gstate;
824N/A } else if (which == DSWFeedbackPixmap) {
824N/A e.drawable = dsw->sw.feedback_pixmap;
824N/A e.gstate = dsw->sw.feedback_gstate;
824N/A } else {
824N/A e.drawable = XtWindow(dsw->sw.drawing_area);
824N/A e.gstate = dsw->sw.window_gstate;
824N/A }
824N/A e.context = dsw->sw.context;
824N/A
824N/A SimplifyRects(dsw->sw.current_drawing, &dsw->sw.num_current_drawing);
824N/A
824N/A XDPSSetContextGState(dsw->sw.context, e.gstate);
824N/A _DPSSWSetRectViewClip(dsw->sw.context, dsw->sw.current_drawing,
824N/A dsw->sw.num_current_drawing * 4);
824N/A
824N/A e.rects = dsw->sw.current_drawing;
824N/A e.rect_count = dsw->sw.num_current_drawing;
824N/A
824N/A do {
824N/A XtCallCallbackList((Widget) dsw, dsw->sw.background_callback,
824N/A (XtPointer) &e);
824N/A if (e.results == DSWUndefined) {
824N/A if (XtHasCallbacks((Widget) dsw, XtNbackgroundCallback) !=
824N/A XtCallbackHasNone) {
824N/A XtAppWarningMsg(XtWidgetToApplicationContext((Widget) dsw),
824N/A "returnError", "backgroundCallback",
824N/A "DPSScrollError",
824N/A "Background callback did not set result field",
824N/A (String *) NULL, (Cardinal *) NULL);
824N/A }
824N/A e.results = DSWFinished;
824N/A }
824N/A } while (e.results != DSWFinished);
824N/A
824N/A
824N/A DPSinitviewclip(dsw->sw.context);
824N/A}
824N/A
824N/Astatic void ClipToDrawingSize(
824N/A DPSScrolledWindowWidget dsw,
824N/A DSWDrawableType which)
824N/A{
824N/A int i;
824N/A float r[4];
824N/A
824N/A if (CEIL(dsw->sw.drawing_width) >= (int) dsw->sw.drawing_area->core.width &&
824N/A CEIL(dsw->sw.drawing_height) >= (int) dsw->sw.drawing_area->core.height) return;
824N/A
824N/A /* Copy current drawing area to scratch */
824N/A
824N/A GrowRectList(&dsw->sw.scratch, &dsw->sw.scratch_size, 0,
824N/A dsw->sw.num_current_drawing, 1);
824N/A dsw->sw.num_scratch = dsw->sw.num_current_drawing;
824N/A for (i = 0; i < dsw->sw.num_current_drawing * 4; i++) {
824N/A dsw->sw.scratch[i] = dsw->sw.current_drawing[i];
824N/A }
824N/A
824N/A /* Construct a rectangle of the drawing area */
824N/A
824N/A ConvertToPS(dsw, dsw->sw.origin_x + DELTA, dsw->sw.origin_y - DELTA,
824N/A r, r+1);
824N/A ConvertToPS(dsw, dsw->sw.origin_x + CEIL(dsw->sw.drawing_width) - DELTA,
824N/A dsw->sw.origin_y - CEIL(dsw->sw.drawing_height) + DELTA,
824N/A r+2, r+3);
824N/A r[2] -= r[0];
824N/A r[3] -= r[1];
824N/A
824N/A /* Subtract the area of the drawing from the current drawing list */
824N/A
824N/A SubtractRects(&dsw->sw.current_drawing, &dsw->sw.current_drawing_size,
824N/A &dsw->sw.num_current_drawing, r, 1);
824N/A
824N/A if (dsw->sw.num_current_drawing != 0) {
824N/A DrawBackground(dsw, which);
824N/A /* Now intersect the rectangle with the current drawing area */
824N/A IntersectRects(&dsw->sw.scratch, &dsw->sw.scratch_size,
824N/A &dsw->sw.num_scratch, r, 1);
824N/A /* If nothing left, we won't be drawing anything more, so
824N/A synchronize. Otherwise wait until we're done drawing */
824N/A if (dsw->sw.num_scratch == 0) DPSWaitContext(dsw->sw.context);
824N/A }
824N/A
824N/A /* Copy scratch back into the current drawing list */
824N/A GrowRectList(&dsw->sw.current_drawing, &dsw->sw.current_drawing_size, 0,
824N/A dsw->sw.num_scratch, 1);
824N/A dsw->sw.num_current_drawing = dsw->sw.num_scratch;
824N/A for (i = 0; i < dsw->sw.num_scratch * 4; i++) {
824N/A dsw->sw.current_drawing[i] = dsw->sw.scratch[i];
824N/A }
824N/A}
824N/A
824N/Astatic DSWResults ClipAndDraw(
824N/A DPSScrolledWindowWidget dsw,
824N/A DSWDrawableType which,
824N/A DSWDirections howMuch,
824N/A Boolean first)
824N/A{
824N/A DSWExposeCallbackRec e;
824N/A
824N/A e.type = which;
824N/A e.directions = howMuch;
824N/A e.results = DSWUndefined;
824N/A e.first = first;
824N/A e.background = False;
824N/A if (which == DSWBackingPixmap) {
824N/A e.drawable = dsw->sw.backing_pixmap;
824N/A e.gstate = dsw->sw.backing_gstate;
824N/A } else if (which == DSWFeedbackPixmap) {
824N/A e.drawable = dsw->sw.feedback_pixmap;
824N/A e.gstate = dsw->sw.feedback_gstate;
824N/A } else {
824N/A e.drawable = XtWindow(dsw->sw.drawing_area);
824N/A e.gstate = dsw->sw.window_gstate;
824N/A }
824N/A e.context = dsw->sw.context;
824N/A
824N/A if (first) {
824N/A XDPSSetContextGState(dsw->sw.context, e.gstate);
824N/A if (howMuch != DSWAbort) {
824N/A ClipToDrawingSize(dsw, which);
824N/A SimplifyRects(dsw->sw.current_drawing,
824N/A &dsw->sw.num_current_drawing);
824N/A if (dsw->sw.num_current_drawing == 0) return DSWFinished;
824N/A _DPSSWSetRectViewClip(dsw->sw.context, dsw->sw.current_drawing,
824N/A dsw->sw.num_current_drawing * 4);
824N/A }
824N/A }
824N/A
824N/A e.rects = dsw->sw.current_drawing;
824N/A e.rect_count = dsw->sw.num_current_drawing;
824N/A
824N/A do {
824N/A XtCallCallbackList((Widget) dsw, dsw->sw.expose_callback,
824N/A (XtPointer) &e);
824N/A if (e.results == DSWUndefined) {
824N/A if (XtHasCallbacks((Widget) dsw,
824N/A XtNexposeCallback) != XtCallbackHasNone) {
824N/A XtAppWarningMsg(XtWidgetToApplicationContext((Widget) dsw),
824N/A "returnError", "exposeCallback",
824N/A "DPSScrollError",
824N/A "Expose callback did not set result field",
824N/A (String *) NULL, (Cardinal *) NULL);
824N/A }
824N/A e.results = DSWFinished;
824N/A }
824N/A } while ((e.results != DSWFinished && howMuch == DSWFinish) ||
824N/A (e.results != DSWFinished && e.results != DSWAborted &&
824N/A howMuch == DSWAbortOrFinish) ||
824N/A (e.results != DSWAborted && howMuch == DSWAbort));
824N/A
824N/A if (e.results == DSWFinished) {
824N/A DPSinitviewclip(dsw->sw.context);
824N/A DPSWaitContext(dsw->sw.context);
824N/A }
824N/A return e.results;
824N/A}
824N/A
824N/Astatic void SplitExposeEvent(
824N/A DPSScrolledWindowWidget dsw,
824N/A XExposeEvent *ev)
824N/A{
824N/A float *r;
824N/A float llx, lly, urx, ury;
824N/A int xr[4];
824N/A int i;
824N/A int dx, dy;
824N/A
824N/A ComputeOffsets(dsw, &dx, &dy);
824N/A
824N/A /* Put the expose event into the scratch list */
824N/A dsw->sw.num_scratch = 1;
824N/A r = dsw->sw.scratch;
824N/A ConvertToPS(dsw, ev->x + DELTA, ev->y + ev->height - DELTA, &llx, &lly);
824N/A ConvertToPS(dsw, ev->x + ev->width - DELTA, ev->y + DELTA, &urx, &ury);
824N/A LEFT(r) = llx;
824N/A BOTTOM(r) = lly;
824N/A WIDTH(r) = urx - llx;
824N/A HEIGHT(r) = ury - lly;
824N/A
824N/A /* Subtract the dirty area from the exposed area and copy the resulting
824N/A area to the window */
824N/A SubtractRects(&dsw->sw.scratch, &dsw->sw.scratch_size,
824N/A &dsw->sw.num_scratch,
824N/A dsw->sw.dirty_areas, dsw->sw.num_dirty_areas);
824N/A for (i = 0; i < dsw->sw.num_scratch; i++) {
824N/A r = dsw->sw.scratch + 4*i;
824N/A ConvertToX(dsw, LEFT(r), TOP(r), xr, xr+1);
824N/A ConvertToX(dsw, RIGHT(r), BOTTOM(r), xr+2, xr+3);
824N/A xr[2] -= xr[0];
824N/A xr[3] -= xr[1];
824N/A XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
824N/A XtWindow(dsw->sw.drawing_area), dsw->sw.no_ge_gc,
824N/A xr[0] + dx, xr[1] + dy, xr[2], xr[3], xr[0], xr[1]);
824N/A }
824N/A
824N/A /* Now do it again, but intersect the exposed area with the dirty area
824N/A and add the intersection to the pending list */
824N/A
824N/A dsw->sw.num_scratch = 1;
824N/A r = dsw->sw.scratch;
824N/A LEFT(r) = llx;
824N/A BOTTOM(r) = lly;
824N/A WIDTH(r) = urx - llx;
824N/A HEIGHT(r) = ury - lly;
824N/A IntersectRects(&dsw->sw.scratch, &dsw->sw.scratch_size,
824N/A &dsw->sw.num_scratch,
824N/A dsw->sw.dirty_areas, dsw->sw.num_dirty_areas);
824N/A AddUserSpaceRectsToPending(dsw, dsw->sw.scratch, dsw->sw.num_scratch);
824N/A}
824N/A
824N/A/* ARGSUSED */
824N/A
824N/Astatic Bool CheckWatchProgressEvent(
824N/A Display *dpy,
824N/A XEvent *e,
824N/A char *arg)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) arg;
824N/A
824N/A return (e->xany.window == dsw->sw.backing_pixmap &&
824N/A (e->type == GraphicsExpose || e->type == NoExpose)) ||
824N/A (e->xany.window == XtWindow(dsw->sw.drawing_area) &&
824N/A e->type == Expose);
824N/A}
824N/A
824N/Astatic void CopyWindowToBackingPixmap(
824N/A DPSScrolledWindowWidget dsw)
824N/A{
824N/A int llx, lly, urx, ury;
824N/A XEvent e;
824N/A XExposeEvent *ev = (XExposeEvent *) &e;
824N/A int i;
824N/A float *r;
824N/A int copies = 0;
824N/A int dx, dy;
824N/A
824N/A ComputeOffsets(dsw, &dx, &dy);
824N/A
824N/A for (i = 0; i < dsw->sw.num_dirty_areas; i++) {
824N/A r = dsw->sw.dirty_areas + i*4;
824N/A ConvertToX(dsw, LEFT(r), BOTTOM(r), &llx, &lly);
824N/A ConvertToX(dsw, RIGHT(r), TOP(r), &urx, &ury);
824N/A XCopyArea(XtDisplay(dsw), XtWindow(dsw->sw.drawing_area),
824N/A dsw->sw.backing_pixmap, dsw->sw.ge_gc,
824N/A llx, ury, urx-llx, lly-ury, llx + dx, ury + dy);
824N/A copies++;
824N/A }
824N/A
824N/A /* Unfortunately the Intrinsics won't let us get ahold of the the
824N/A GraphicsExpose events for the pixmap, so we have to wait and
824N/A get them the old fashioned way. Yuck. */
824N/A
824N/A while (copies > 0) {
824N/A XIfEvent(XtDisplay(dsw), &e, CheckWatchProgressEvent,
824N/A (char *) dsw);
824N/A if (e.type == Expose) {
824N/A SplitExposeEvent(dsw, ev);
824N/A continue;
824N/A } else if (e.type == GraphicsExpose) {
824N/A ev->x -= dx;
824N/A ev->y -= dy;
824N/A AddExposureToPending(dsw, ev);
824N/A if (ev->count == 0) copies--;
824N/A } else copies--; /* NoExpose */
824N/A }
824N/A CopyRectsToCurrentDrawing(dsw, dsw->sw.pending_dirty,
824N/A dsw->sw.num_pending_dirty);
824N/A
824N/A dsw->sw.num_pending_dirty = 0;
824N/A dsw->sw.num_pending_expose = 0;
824N/A if (dsw->sw.num_current_drawing == 0) {
824N/A dsw->sw.drawing_stage = DSWDone;
824N/A dsw->sw.num_dirty_areas = 0;
824N/A } else {
824N/A /* The dirty area is now the intersection of the old dirty area and
824N/A the newly-created current drawing list */
824N/A IntersectRects(&dsw->sw.dirty_areas, &dsw->sw.dirty_areas_size,
824N/A &dsw->sw.num_dirty_areas,
824N/A dsw->sw.current_drawing, dsw->sw.num_current_drawing);
824N/A }
824N/A}
824N/A
824N/A/* Subtract the window area from the dirty area, and make the
824N/A result be the new current drawing list */
824N/A
824N/Astatic void SetCurrentDrawingToBackground(
824N/A DPSScrolledWindowWidget dsw)
824N/A{
824N/A int i;
824N/A float r[4];
824N/A
824N/A ConvertToPS(dsw, 0 + DELTA, dsw->sw.drawing_area->core.height - DELTA,
824N/A r, r+1);
824N/A ConvertToPS(dsw, dsw->sw.drawing_area->core.width - DELTA, 0 + DELTA,
824N/A r+2, r+3);
824N/A r[2] -= r[0];
824N/A r[3] -= r[1];
824N/A
824N/A SubtractRects(&dsw->sw.dirty_areas, &dsw->sw.dirty_areas_size,
824N/A &dsw->sw.num_dirty_areas, r, 1);
824N/A
824N/A GrowRectList(&dsw->sw.current_drawing, &dsw->sw.current_drawing_size,
824N/A 0, dsw->sw.num_dirty_areas, 1);
824N/A for (i = 0; i < 4 * dsw->sw.num_dirty_areas; i++) {
824N/A dsw->sw.current_drawing[i] = dsw->sw.dirty_areas[i];
824N/A }
824N/A dsw->sw.num_current_drawing = dsw->sw.num_dirty_areas;
824N/A}
824N/A
824N/Astatic void CopyPendingExpose(DPSScrolledWindowWidget dsw)
824N/A{
824N/A int dx, dy;
824N/A int i;
824N/A int *r;
824N/A
824N/A ComputeOffsets(dsw, &dx, &dy);
824N/A
824N/A for (i = 0; i < dsw->sw.num_pending_expose; i++) {
824N/A r = dsw->sw.pending_expose + 4*i;
824N/A XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
824N/A XtWindow(dsw->sw.drawing_area),
824N/A dsw->sw.no_ge_gc,
824N/A LEFT(r) + dx, BOTTOM(r) + dy, WIDTH(r), HEIGHT(r),
824N/A LEFT(r), BOTTOM(r));
824N/A }
824N/A dsw->sw.num_pending_expose = dsw->sw.num_pending_dirty = 0;
824N/A}
824N/A
824N/Astatic void UpdateWindowFromBackingPixmap(
824N/A DPSScrolledWindowWidget dsw,
824N/A float *rects,
824N/A int n)
824N/A{
824N/A int dx, dy;
824N/A int llx, lly, urx, ury;
824N/A int i;
824N/A float *r;
824N/A
824N/A ComputeOffsets(dsw, &dx, &dy);
824N/A
824N/A for (i = 0; i < n; i++) {
824N/A r = rects + 4*i;
824N/A ConvertToX(dsw, LEFT(r), BOTTOM(r), &llx, &lly);
824N/A ConvertToX(dsw, RIGHT(r), TOP(r), &urx, &ury);
824N/A
824N/A XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
824N/A XtWindow(dsw->sw.drawing_area),
824N/A dsw->sw.no_ge_gc,
824N/A llx+dx-1, ury+dy-1, urx-llx+2, lly-ury+2, llx-1, ury-1);
824N/A }
824N/A}
824N/A
824N/Astatic void UpdateWindowFromFeedbackPixmap(
824N/A DPSScrolledWindowWidget dsw,
824N/A float *rects,
824N/A int n)
824N/A{
824N/A int llx, lly, urx, ury;
824N/A int i;
824N/A float *r;
824N/A
824N/A for (i = 0; i < n; i++) {
824N/A r = rects + (i * 4);
824N/A ConvertToX(dsw, LEFT(r), BOTTOM(r), &llx, &lly);
824N/A ConvertToX(dsw, RIGHT(r), TOP(r), &urx, &ury);
824N/A
824N/A XCopyArea(XtDisplay(dsw), dsw->sw.feedback_pixmap,
824N/A XtWindow(dsw->sw.drawing_area), dsw->sw.no_ge_gc,
824N/A llx-1, ury-1, urx-llx+2, lly-ury+2, llx-1, ury-1);
824N/A }
824N/A}
824N/A
824N/A/* This is the heart of the drawing code; it does one piece of drawing.
824N/A It can be called either directly or as a work procedure */
824N/A
824N/Astatic Boolean DoDrawing(XtPointer clientData)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) clientData;
824N/A DSWResults results;
824N/A DSWDrawableType which;
824N/A
824N/A if (dsw->sw.drawing_stage == DSWStart && dsw->sw.watch_progress &&
824N/A dsw->sw.backing_pixmap != None && dsw->sw.num_current_drawing == 0) {
824N/A dsw->sw.drawing_stage = DSWDrewVisible;
824N/A CopyWindowToBackingPixmap(dsw);
824N/A }
824N/A
824N/A switch (dsw->sw.drawing_stage) {
824N/A case DSWStart:
824N/A case DSWDrawingVisible:
824N/A if (dsw->sw.watch_progress || dsw->sw.backing_pixmap == None) {
824N/A which = DSWWindow;
824N/A } else which = DSWBackingPixmap;
824N/A results = ClipAndDraw(dsw, which, DSWDrawSome,
824N/A (dsw->sw.drawing_stage == DSWStart));
824N/A if (results == DSWFinished) {
824N/A if (dsw->sw.watch_progress && dsw->sw.backing_pixmap != None) {
824N/A dsw->sw.drawing_stage = DSWDrewVisible;
824N/A CopyWindowToBackingPixmap(dsw);
824N/A } else {
824N/A if (dsw->sw.minimal_drawing && dsw->sw.big_pixmap) {
824N/A dsw->sw.drawing_stage = DSWDrewVisible;
824N/A SetCurrentDrawingToBackground(dsw);
824N/A } else {
824N/A dsw->sw.drawing_stage = DSWDone;
824N/A dsw->sw.num_dirty_areas = 0;
824N/A }
824N/A if (dsw->sw.num_pending_expose != 0 &&
824N/A dsw->sw.backing_pixmap != None) {
824N/A CopyPendingExpose(dsw);
824N/A }
824N/A }
824N/A } else dsw->sw.drawing_stage = DSWDrawingVisible;
824N/A break;
824N/A
824N/A case DSWDrewVisible:
824N/A case DSWDrawingBackground:
824N/A results = ClipAndDraw(dsw, DSWBackingPixmap, DSWDrawSome,
824N/A (dsw->sw.drawing_stage == DSWDrewVisible));
824N/A if (results == DSWFinished) {
824N/A dsw->sw.drawing_stage = DSWDone;
824N/A dsw->sw.num_dirty_areas = 0;
824N/A }
824N/A else dsw->sw.drawing_stage = DSWDrawingBackground;
824N/A break;
824N/A
824N/A case DSWDone:
824N/A break;
824N/A }
824N/A
824N/A if (dsw->sw.drawing_stage == DSWDone && dsw->sw.num_pending_dirty != 0) {
824N/A CopyRectsToCurrentDrawing(dsw, dsw->sw.pending_dirty,
824N/A dsw->sw.num_pending_dirty);
824N/A CopyRectsToDirtyArea(dsw, dsw->sw.pending_dirty,
824N/A dsw->sw.num_pending_dirty);
824N/A dsw->sw.num_pending_dirty = 0;
824N/A dsw->sw.num_pending_expose = 0;
824N/A dsw->sw.drawing_stage = DSWStart;
824N/A }
824N/A
824N/A if (dsw->sw.drawing_stage == DSWDone) {
824N/A dsw->sw.work = 0;
824N/A if (dsw->sw.watch_progress) {
824N/A /* Some of the background drawing may have been to areas that
824N/A are visible */
824N/A UpdateWindowFromBackingPixmap(dsw, dsw->sw.current_drawing,
824N/A dsw->sw.num_current_drawing);
824N/A }
824N/A dsw->sw.num_current_drawing = 0;
824N/A if (dsw->sw.scrolling) {
824N/A dsw->sw.scrolling = False;
824N/A ScrollMoved(dsw);
824N/A }
824N/A return True;
824N/A } else return False;
824N/A}
824N/A
824N/Astatic void StartDrawing(DPSScrolledWindowWidget dsw)
824N/A{
824N/A float r[4];
824N/A
824N/A CopyRectsToCurrentDrawing(dsw, dsw->sw.dirty_areas,
824N/A dsw->sw.num_dirty_areas);
824N/A
824N/A if (dsw->sw.watch_progress || dsw->sw.backing_pixmap == None) {
824N/A /* Intersect the current drawing area with the pending dirty area
824N/A (The pending dirty area represents the window exposures that
824N/A have happened so far) */
824N/A IntersectRects(&dsw->sw.current_drawing, &dsw->sw.current_drawing_size,
824N/A &dsw->sw.num_current_drawing,
824N/A dsw->sw.pending_dirty, dsw->sw.num_pending_dirty);
824N/A dsw->sw.num_pending_dirty = dsw->sw.num_pending_expose = 0;
824N/A } else {
824N/A if (!dsw->sw.big_pixmap || dsw->sw.minimal_drawing) {
824N/A /* Intersect the current drawing area to the window to start */
824N/A ConvertToPS(dsw, 0 + DELTA,
824N/A dsw->sw.drawing_area->core.height - DELTA, r, r+1);
824N/A ConvertToPS(dsw, dsw->sw.drawing_area->core.width - DELTA,
824N/A 0 + DELTA, r+2, r+3);
824N/A r[2] -= r[0];
824N/A r[3] -= r[1];
824N/A IntersectRects(&dsw->sw.current_drawing,
824N/A &dsw->sw.current_drawing_size,
824N/A &dsw->sw.num_current_drawing, r, 1);
824N/A }
824N/A }
824N/A
824N/A if (dsw->sw.num_current_drawing == 0 && !dsw->sw.watch_progress) {
824N/A dsw->sw.drawing_stage = DSWFinished;
824N/A dsw->sw.num_dirty_areas = 0;
824N/A return;
824N/A }
824N/A
824N/A dsw->sw.drawing_stage = DSWStart;
824N/A if (!DoDrawing((XtPointer) dsw)) {
824N/A dsw->sw.work =
824N/A XtAppAddWorkProc(XtWidgetToApplicationContext((Widget) dsw),
824N/A DoDrawing, (XtPointer) dsw);
824N/A }
824N/A}
824N/A
824N/Astatic void RedisplaySliver(DPSScrolledWindowWidget dsw, int deltaX, int deltaY)
824N/A{
824N/A float r[8];
824N/A int xr[8];
824N/A int n;
824N/A int xllx, xlly, xurx, xury;
824N/A float llx, lly, urx, ury;
824N/A
824N/A /* If one of the deltas is 0, then the area to update is just a
824N/A single rectangle. */
824N/A if (deltaX == 0 || deltaY == 0) {
824N/A if (deltaX == 0) {
824N/A /* Just a single horizontal rectangle */
824N/A
824N/A xllx = 0;
824N/A xurx = dsw->sw.drawing_area->core.width;
824N/A if (deltaY > 0) {
824N/A xlly = dsw->sw.drawing_area->core.height;
824N/A xury = dsw->sw.drawing_area->core.height - deltaY;
824N/A } else {
824N/A xlly = -deltaY;
824N/A xury = 0;
824N/A }
824N/A
824N/A } else if (deltaY == 0) {
824N/A /* Just a single vertical rectangle */
824N/A xlly = dsw->sw.drawing_area->core.height;
824N/A xury = 0;
824N/A if (deltaX > 0) {
824N/A xllx = dsw->sw.drawing_area->core.width - deltaX;
824N/A xurx = dsw->sw.drawing_area->core.width;
824N/A } else {
824N/A xllx = 0;
824N/A xurx = -deltaX;
824N/A }
824N/A }
824N/A /* Convert the rectangle into PS coordinates */
824N/A ConvertToPS(dsw, xllx + DELTA, xlly - DELTA, &llx, &lly);
824N/A ConvertToPS(dsw, xurx - DELTA, xury + DELTA, &urx, &ury);
824N/A r[0] = llx;
824N/A r[1] = lly;
824N/A r[2] = urx - llx;
824N/A r[3] = ury - lly;
824N/A xr[0] = xllx;
824N/A xr[1] = xury;
824N/A xr[2] = xurx - xllx;
824N/A xr[3] = xlly - xury;
824N/A n = 1;
824N/A
824N/A } else {
824N/A /* Scrolling in both directions, so there are two rectangles.
824N/A It's easiest to do if we let them overlap; fortunately that is
824N/A legal! First do the horizontal rectangle. */
824N/A xllx = 0;
824N/A xurx = dsw->sw.drawing_area->core.width;
824N/A if (deltaY > 0) {
824N/A xlly = dsw->sw.drawing_area->core.height;
824N/A xury = dsw->sw.drawing_area->core.height - deltaY;
824N/A } else {
824N/A xlly = -deltaY;
824N/A xury = 0;
824N/A }
824N/A ConvertToPS(dsw, xllx + DELTA, xlly - DELTA, &llx, &lly);
824N/A ConvertToPS(dsw, xurx - DELTA, xury + DELTA, &urx, &ury);
824N/A
824N/A /* Store in point array */
824N/A r[0] = llx;
824N/A r[1] = lly;
824N/A r[2] = urx - llx;
824N/A r[3] = ury - lly;
824N/A xr[0] = xllx;
824N/A xr[1] = xury;
824N/A xr[2] = xurx - xllx;
824N/A xr[3] = xlly - xury;
824N/A
824N/A /* Now do vertical rectangle and store in point array */
824N/A xlly = dsw->sw.drawing_area->core.height;
824N/A xury = 0;
824N/A if (deltaX > 0) {
824N/A xllx = dsw->sw.drawing_area->core.width - deltaX;
824N/A xurx = dsw->sw.drawing_area->core.width;
824N/A } else {
824N/A xllx = 0;
824N/A xurx = -deltaX;
824N/A }
824N/A ConvertToPS(dsw, xllx + DELTA, xlly - DELTA, &llx, &lly);
824N/A ConvertToPS(dsw, xurx - DELTA, xury + DELTA, &urx, &ury);
824N/A r[4] = llx;
824N/A r[5] = lly;
824N/A r[6] = urx - llx;
824N/A r[7] = ury - lly;
824N/A xr[4] = xllx;
824N/A xr[5] = xury;
824N/A xr[6] = xurx - xllx;
824N/A xr[7] = xlly - xury;
824N/A n = 2;
824N/A }
824N/A
824N/A AddRectsToDirtyArea(dsw, r, n);
824N/A AddRectsToPending(dsw, xr, n);
824N/A StartDrawing(dsw);
824N/A}
824N/A
824N/Astatic void SetUpInitialPixmap(DPSScrolledWindowWidget dsw)
824N/A{
824N/A float *r = dsw->sw.dirty_areas;
824N/A int llx, lly, urx, ury;
824N/A
824N/A CreateBackingPixmap(dsw);
824N/A if (dsw->sw.backing_pixmap != None) {
824N/A XDPSSetContextDrawable(dsw->sw.context, dsw->sw.backing_pixmap,
824N/A dsw->sw.pixmap_height);
824N/A
824N/A SetPixmapOffset(dsw);
824N/A SetPixmapOrigin(dsw);
824N/A XDPSCaptureContextGState(dsw->sw.context, &dsw->sw.backing_gstate);
824N/A
824N/A if (dsw->sw.pixmap_width != CEIL(dsw->sw.drawing_width) ||
824N/A dsw->sw.pixmap_height != CEIL(dsw->sw.drawing_height)) {
824N/A
824N/A /* Make the dirty area match the window */
824N/A if (dsw->sw.pixmap_width > (int)dsw->sw.drawing_area->core.width) {
824N/A llx = dsw->sw.origin_x;
824N/A urx = llx + CEIL(dsw->sw.drawing_width);
824N/A } else {
824N/A llx = 0;
824N/A urx = dsw->sw.drawing_area->core.width;
824N/A }
824N/A if (dsw->sw.pixmap_height >
824N/A (int) dsw->sw.drawing_area->core.height) {
824N/A lly = dsw->sw.origin_y;
824N/A ury = dsw->sw.origin_y - CEIL(dsw->sw.drawing_height);
824N/A } else {
824N/A lly = dsw->sw.drawing_area->core.height;
824N/A ury = 0;
824N/A }
824N/A ConvertToPS(dsw, llx + DELTA, lly - DELTA, r, r+1);
824N/A ConvertToPS(dsw, urx - DELTA, ury + DELTA, r+2, r+3);
824N/A r[2] -= r[0];
824N/A r[3] -= r[1];
824N/A dsw->sw.num_dirty_areas = 1;
824N/A }
824N/A if (dsw->sw.doing_feedback) {
824N/A CopyRectsToCurrentDrawing(dsw, dsw->sw.dirty_areas,
824N/A dsw->sw.num_dirty_areas);
824N/A FinishDrawing(dsw);
824N/A } else if (!dsw->sw.watch_progress) StartDrawing(dsw);
824N/A }
824N/A}
824N/A
824N/A/* ARGSUSED */
824N/A
824N/Astatic void TimerStart(XtPointer clientData, XtIntervalId *id)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) clientData;
824N/A
824N/A if (dsw->sw.drawing_stage == DSWStart) StartDrawing(dsw);
824N/A}
824N/A
824N/Astatic void SetUpInitialInformation(DPSScrolledWindowWidget dsw)
824N/A{
824N/A int i;
824N/A float llx, lly, urx, ury;
824N/A float xScale, yScale;
824N/A XExposeEvent ev;
824N/A XStandardColormap colorCube, grayRamp;
824N/A int match;
824N/A
824N/A /* If the context's colormap matches the widget's colormap, assume that
824N/A everything is already set up right in the color cube department. This
824N/A allows an application to supply us with a custom color cube by
824N/A installing it in the context before calling us */
824N/A
824N/A _DPSSWColormapMatch(dsw->sw.context,
824N/A dsw->sw.drawing_area->core.colormap, &match);
824N/A
824N/A if (match) {
824N/A XDPSSetContextParameters(dsw->sw.context, XtScreen(dsw),
824N/A dsw->sw.drawing_area->core.depth,
824N/A XtWindow(dsw->sw.drawing_area),
824N/A dsw->sw.drawing_area->core.height, NULL, NULL,
824N/A XDPSContextScreenDepth | XDPSContextDrawable);
824N/A } else {
824N/A grayRamp.colormap = colorCube.colormap =
824N/A dsw->sw.drawing_area->core.colormap;
824N/A
824N/A XDPSCreateStandardColormaps(XtDisplay(dsw), XtWindow(dsw),
824N/A (Visual *) NULL, 0, 0, 0, 0,
824N/A &colorCube, &grayRamp, False);
824N/A
824N/A XDPSSetContextParameters(dsw->sw.context, XtScreen(dsw),
824N/A dsw->sw.drawing_area->core.depth,
824N/A XtWindow(dsw->sw.drawing_area),
824N/A dsw->sw.drawing_area->core.height,
824N/A (XDPSStandardColormap *) &colorCube,
824N/A (XDPSStandardColormap *) &grayRamp,
824N/A XDPSContextScreenDepth | XDPSContextDrawable |
824N/A XDPSContextRGBMap | XDPSContextGrayMap);
824N/A }
824N/A
824N/A DPSinitgraphics(dsw->sw.context);
824N/A _DPSSWGetTransform(dsw->sw.context, dsw->sw.ctm, dsw->sw.orig_inv_ctm);
824N/A dsw->sw.x_offset = 0;
824N/A dsw->sw.y_offset = dsw->sw.drawing_area->core.height;
824N/A for (i = 0; i < 6; i++) dsw->sw.inv_ctm[i] = dsw->sw.orig_inv_ctm[i];
824N/A
824N/A ConvertToPS(dsw, 0.0, 100.0, &llx, &lly);
824N/A ConvertToPS(dsw, 100.0, 0.0, &urx, &ury);
824N/A xScale = ABS(100.0 / (urx - llx));
824N/A yScale = ABS(100.0 / (ury - lly));
824N/A
824N/A if (dsw->sw.scale != 1.0) {
824N/A DPSscale(dsw->sw.context, dsw->sw.scale, dsw->sw.scale);
824N/A _DPSSWGetTransform(dsw->sw.context, dsw->sw.ctm, dsw->sw.inv_ctm);
824N/A }
824N/A
824N/A dsw->sw.drawing_width = dsw->sw.area_width * xScale * dsw->sw.scale;
824N/A dsw->sw.drawing_height = dsw->sw.area_height * yScale * dsw->sw.scale;
824N/A
824N/A dsw->sw.unscaled_width = dsw->sw.drawing_width / dsw->sw.scale + 1;
824N/A dsw->sw.unscaled_height = dsw->sw.drawing_height / dsw->sw.scale + 1;
824N/A
824N/A if (!dsw->sw.use_saved_scroll) {
824N/A dsw->sw.scroll_pic_x = dsw->sw.area_width / 2;
824N/A dsw->sw.scroll_pic_y = dsw->sw.area_height / 2;
824N/A dsw->sw.scroll_win_x = dsw->sw.drawing_area->core.width / 2;
824N/A dsw->sw.scroll_win_y = dsw->sw.drawing_area->core.height / 2;
824N/A }
824N/A
824N/A SetDrawingAreaPosition(dsw, dsw->sw.scroll_pic_x, dsw->sw.scroll_pic_y,
824N/A dsw->sw.scroll_win_x, dsw->sw.scroll_win_y, True);
824N/A SetOriginAndGetTransform(dsw);
824N/A XDPSCaptureContextGState(dsw->sw.context, &dsw->sw.window_gstate);
824N/A
824N/A dsw->sw.drawing_stage = DSWStart;
824N/A
824N/A if (dsw->sw.use_backing_pixmap) SetUpInitialPixmap(dsw);
824N/A
824N/A if (dsw->sw.doing_feedback) return;
824N/A
824N/A if (dsw->sw.watch_progress || dsw->sw.backing_pixmap == None) {
824N/A /* If watching progress or no pixmap, clear the window to ensure
824N/A that things get started */
824N/A XClearArea(XtDisplay(dsw), XtWindow(dsw->sw.drawing_area),
824N/A 0, 0, 0, 0, True);
824N/A XSync(XtDisplay(dsw), False);
824N/A if (dsw->sw.watch_progress && dsw->sw.watch_progress_delay > 0) {
824N/A /* Set a timer so that we start drawing if nothing is visible */
824N/A (void) XtAppAddTimeOut(XtWidgetToApplicationContext((Widget) dsw),
824N/A dsw->sw.watch_progress_delay,
824N/A TimerStart, (XtPointer) dsw);
824N/A }
824N/A } else {
824N/A /* Put a synthetic expose event in the pending queue */
824N/A ev.x = ev.y = 0;
824N/A ev.width = dsw->sw.drawing_area->core.width;
824N/A ev.height = dsw->sw.drawing_area->core.height;
824N/A SplitExposeEvent(dsw, &ev);
824N/A }
824N/A}
824N/A
824N/Astatic void Realize(
824N/A Widget w,
824N/A XtValueMask *mask,
824N/A XSetWindowAttributes *attr)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
824N/A DSWSetupCallbackRec setup;
824N/A
824N/A /* Let my parent do all the hard work */
824N/A (*dpsScrolledWindowClassRec.core_class.superclass->core_class.realize)
824N/A (w, mask, attr);
824N/A
824N/A /* We delay calling the setup callback so that the caller can use
824N/A XtAddCallback to add it */
824N/A setup.context = dsw->sw.context;
824N/A XtCallCallbackList((Widget) dsw, dsw->sw.setup_callback,
824N/A (XtPointer) &setup);
824N/A
824N/A /* Now, explicitly realize my children */
824N/A XtRealizeWidget(dsw->sw.scrolled_window);
824N/A
824N/A /* Et voila, now we have windows! */
824N/A SetUpInitialInformation(dsw);
824N/A}
824N/A
824N/Astatic void AbortOrFinish(DPSScrolledWindowWidget dsw)
824N/A{
824N/A DSWResults results;
824N/A DSWDrawableType which;
824N/A
824N/A if (dsw->sw.work != 0) {
824N/A XtRemoveWorkProc(dsw->sw.work);
824N/A dsw->sw.work = 0;
824N/A }
824N/A
824N/A switch (dsw->sw.drawing_stage) {
824N/A case DSWStart:
824N/A return;
824N/A /* break; */
824N/A
824N/A case DSWDrawingVisible:
824N/A if (dsw->sw.watch_progress || dsw->sw.backing_pixmap == None) {
824N/A which = DSWWindow;
824N/A } else which = DSWBackingPixmap;
824N/A results = ClipAndDraw(dsw, which, DSWAbortOrFinish, False);
824N/A if (results == DSWAborted) {
824N/A dsw->sw.drawing_stage = DSWStart;
824N/A if (dsw->sw.backing_pixmap == None || dsw->sw.watch_progress) {
824N/A /* Add the current drawing area back into the pending
824N/A expose area */
824N/A AddUserSpaceRectsToPending(dsw, dsw->sw.current_drawing,
824N/A dsw->sw.num_current_drawing);
824N/A }
824N/A return;
824N/A }
824N/A if (dsw->sw.watch_progress && dsw->sw.backing_pixmap != None) {
824N/A dsw->sw.drawing_stage = DSWDrewVisible;
824N/A CopyWindowToBackingPixmap(dsw);
824N/A if (dsw->sw.num_current_drawing != 0) {
824N/A results = ClipAndDraw(dsw, DSWBackingPixmap,
824N/A DSWAbortOrFinish, True);
824N/A }
824N/A if (results == DSWAborted) {
824N/A dsw->sw.drawing_stage = DSWStart;
824N/A return;
824N/A }
824N/A } else {
824N/A if (dsw->sw.backing_pixmap != None) {
824N/A if (dsw->sw.num_pending_expose != 0) {
824N/A CopyPendingExpose(dsw);
824N/A }
824N/A
824N/A if (dsw->sw.minimal_drawing && dsw->sw.big_pixmap) {
824N/A dsw->sw.drawing_stage = DSWDrewVisible;
824N/A SetCurrentDrawingToBackground(dsw);
824N/A results = ClipAndDraw(dsw, which,
824N/A DSWAbortOrFinish, True);
824N/A if (results == DSWAborted) {
824N/A dsw->sw.drawing_stage = DSWStart;
824N/A return;
824N/A }
824N/A }
824N/A }
824N/A }
824N/A break;
824N/A
824N/A case DSWDrewVisible:
824N/A case DSWDrawingBackground:
824N/A results = ClipAndDraw(dsw, DSWBackingPixmap, DSWAbortOrFinish,
824N/A (dsw->sw.drawing_stage == DSWDrewVisible));
824N/A if (results == DSWAborted) {
824N/A dsw->sw.drawing_stage = DSWStart;
824N/A return;
824N/A }
824N/A break;
824N/A
824N/A case DSWDone:
824N/A break;
824N/A }
824N/A
824N/A dsw->sw.drawing_stage = DSWDone;
824N/A dsw->sw.num_dirty_areas = 0;
824N/A return;
824N/A}
824N/A
824N/Astatic void AbortDrawing(DPSScrolledWindowWidget dsw)
824N/A{
824N/A DSWDrawableType which;
824N/A
824N/A if (dsw->sw.work != 0) {
824N/A XtRemoveWorkProc(dsw->sw.work);
824N/A dsw->sw.work = 0;
824N/A }
824N/A
824N/A switch (dsw->sw.drawing_stage) {
824N/A case DSWStart:
824N/A case DSWDone:
824N/A case DSWDrewVisible:
824N/A break;
824N/A
824N/A case DSWDrawingVisible:
824N/A if (dsw->sw.watch_progress || dsw->sw.backing_pixmap == None) {
824N/A which = DSWWindow;
824N/A } else which = DSWBackingPixmap;
824N/A (void) ClipAndDraw(dsw, which, DSWAbort, False);
824N/A break;
824N/A
824N/A case DSWDrawingBackground:
824N/A (void) ClipAndDraw(dsw, DSWBackingPixmap, DSWAbort, False);
824N/A break;
824N/A
824N/A }
824N/A
824N/A dsw->sw.num_pending_expose = dsw->sw.num_pending_dirty = 0;
824N/A}
824N/A
824N/Astatic void FinishDrawing(DPSScrolledWindowWidget dsw)
824N/A{
824N/A DSWDrawableType which;
824N/A
824N/A if (dsw->sw.work != 0) {
824N/A XtRemoveWorkProc(dsw->sw.work);
824N/A dsw->sw.work = 0;
824N/A }
824N/A
824N/A switch (dsw->sw.drawing_stage) {
824N/A case DSWStart:
824N/A case DSWDrawingVisible:
824N/A if (dsw->sw.watch_progress || dsw->sw.backing_pixmap == None) {
824N/A which = DSWWindow;
824N/A } else which = DSWBackingPixmap;
824N/A if (dsw->sw.drawing_stage == DSWStart) {
824N/A ClipToDrawingSize(dsw, which);
824N/A if (dsw->sw.num_current_drawing == 0) return;
824N/A }
824N/A (void) ClipAndDraw(dsw, which, DSWFinish,
824N/A dsw->sw.drawing_stage == DSWStart);
824N/A if (dsw->sw.watch_progress && dsw->sw.backing_pixmap != None) {
824N/A dsw->sw.drawing_stage = DSWDrewVisible;
824N/A CopyWindowToBackingPixmap(dsw);
824N/A if (dsw->sw.num_current_drawing != 0) {
824N/A (void) ClipAndDraw(dsw, DSWBackingPixmap, DSWFinish, True);
824N/A }
824N/A } else {
824N/A if (dsw->sw.backing_pixmap != None) {
824N/A if (dsw->sw.num_pending_expose != 0) {
824N/A CopyPendingExpose(dsw);
824N/A }
824N/A
824N/A if (dsw->sw.minimal_drawing && dsw->sw.big_pixmap) {
824N/A dsw->sw.drawing_stage = DSWDrewVisible;
824N/A SetCurrentDrawingToBackground(dsw);
824N/A (void) ClipAndDraw(dsw, which, DSWFinish, True);
824N/A }
824N/A }
824N/A }
824N/A break;
824N/A
824N/A case DSWDrewVisible:
824N/A case DSWDrawingBackground:
824N/A (void) ClipAndDraw(dsw, DSWBackingPixmap, DSWFinish,
824N/A (dsw->sw.drawing_stage == DSWDrewVisible));
824N/A break;
824N/A
824N/A case DSWDone:
824N/A break;
824N/A }
824N/A
824N/A dsw->sw.drawing_stage = DSWDone;
824N/A dsw->sw.num_dirty_areas = 0;
824N/A}
824N/A
824N/Astatic void DoScroll(
824N/A DPSScrolledWindowWidget dsw,
824N/A int deltaX, int deltaY)
824N/A{
824N/A /* Set the PS origin in the X window to the new settings of
824N/A the scrollbars */
824N/A dsw->sw.origin_x -= deltaX;
824N/A dsw->sw.origin_y -= deltaY;
824N/A
824N/A /* Update the graphics states for the window and backing pixmap to
824N/A reflect new origin */
824N/A (void) XDPSSetContextGState(dsw->sw.context, dsw->sw.window_gstate);
824N/A SetOriginAndGetTransform(dsw);
824N/A (void) XDPSUpdateContextGState(dsw->sw.context, dsw->sw.window_gstate);
824N/A
824N/A if (dsw->sw.backing_pixmap != None && !dsw->sw.big_pixmap) {
824N/A (void) XDPSSetContextGState(dsw->sw.context, dsw->sw.backing_gstate);
824N/A SetPixmapOrigin(dsw);
824N/A (void) XDPSUpdateContextGState(dsw->sw.context,
824N/A dsw->sw.backing_gstate);
824N/A }
824N/A
824N/A /* Update the stored position of the scroll bars */
824N/A dsw->sw.scroll_x += deltaX;
824N/A dsw->sw.scroll_y += deltaY;
824N/A}
824N/A
824N/Astatic void ShiftPendingExpose(
824N/A DPSScrolledWindowWidget dsw,
824N/A int deltaX, int deltaY)
824N/A{
824N/A int i;
824N/A int *r;
824N/A
824N/A for (i = 0; i < dsw->sw.num_pending_expose; i++) {
824N/A r = dsw->sw.pending_expose + 4*i;
824N/A r[0] -= deltaX;
824N/A r[1] -= deltaY;
824N/A }
824N/A}
824N/A
824N/Astatic void HScrollCallback(
824N/A Widget w,
824N/A XtPointer clientData, XtPointer callData)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) clientData;
824N/A XmScrollBarCallbackStruct *sb = (XmScrollBarCallbackStruct *) callData;
824N/A
824N/A if (!dsw->sw.application_scrolling) {
824N/A dsw->sw.scroll_h_value = sb->value;
824N/A ScrollMoved(dsw);
824N/A }
824N/A}
824N/A
824N/Astatic void VScrollCallback(
824N/A Widget w,
824N/A XtPointer clientData, XtPointer callData)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) clientData;
824N/A XmScrollBarCallbackStruct *sb = (XmScrollBarCallbackStruct *) callData;
824N/A
824N/A if (!dsw->sw.application_scrolling) {
824N/A dsw->sw.scroll_v_value = sb->value;
824N/A ScrollMoved(dsw);
824N/A }
824N/A}
824N/A
824N/A/* ARGSUSED */
824N/A
824N/Astatic void ScrollMoved(DPSScrolledWindowWidget dsw)
824N/A{
824N/A int deltaX, deltaY;
824N/A
824N/A /* If we haven't started drawing yet, it must be because we're waiting
824N/A for GraphicsExpose events. Delay scrolling until they come in */
824N/A if (dsw->sw.scrolling && dsw->sw.drawing_stage == DSWStart) return;
824N/A
824N/A /* Calculate the delta in the scrolling */
824N/A deltaX = dsw->sw.scroll_h_value - dsw->sw.scroll_x;
824N/A deltaY = dsw->sw.scroll_v_value - dsw->sw.scroll_y;
824N/A
824N/A /* If there is some scrolling to do, then scroll the pixmap and
824N/A copy the pixmap to the window */
824N/A if (deltaX == 0 && deltaY == 0) return;
824N/A
824N/A ShiftPendingExpose(dsw, deltaX, deltaY);
824N/A
824N/A AbortOrFinish(dsw);
824N/A
824N/A DoScroll(dsw, deltaX, deltaY);
824N/A
824N/A if (!dsw->sw.big_pixmap) {
824N/A /* Copy visible area to new location */
824N/A if (dsw->sw.backing_pixmap != None) {
824N/A XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
824N/A dsw->sw.backing_pixmap, dsw->sw.no_ge_gc,
824N/A deltaX, deltaY, dsw->sw.drawing_area->core.width,
824N/A dsw->sw.drawing_area->core.height, 0, 0);
824N/A if (!dsw->sw.doing_feedback || dsw->sw.feedback_pixmap == None) {
824N/A XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
824N/A XtWindow(dsw->sw.drawing_area), dsw->sw.no_ge_gc,
824N/A 0, 0, dsw->sw.drawing_area->core.width,
824N/A dsw->sw.drawing_area->core.height, 0, 0);
824N/A }
824N/A RedisplaySliver(dsw, deltaX, deltaY);
824N/A } else {
824N/A if (!dsw->sw.doing_feedback || dsw->sw.feedback_pixmap == None) {
824N/A XCopyArea(XtDisplay(dsw), XtWindow(dsw->sw.drawing_area),
824N/A XtWindow(dsw->sw.drawing_area), dsw->sw.ge_gc,
824N/A deltaX, deltaY, dsw->sw.drawing_area->core.width,
824N/A dsw->sw.drawing_area->core.height, 0, 0);
824N/A }
824N/A if (dsw->sw.doing_feedback) RedisplaySliver(dsw, deltaX, deltaY);
824N/A else dsw->sw.drawing_stage = DSWStart;
824N/A }
824N/A }
824N/A
824N/A if (dsw->sw.doing_feedback) {
824N/A float *r;
824N/A
824N/A FinishDrawing(dsw);
824N/A
824N/A r = dsw->sw.prev_dirty_areas;
824N/A ConvertToPS(dsw, 0 + DELTA, dsw->sw.drawing_area->core.height - DELTA,
824N/A r, r+1);
824N/A ConvertToPS(dsw, dsw->sw.drawing_area->core.width - DELTA, 0 + DELTA,
824N/A r+2, r+3);
824N/A r[2] -= r[0];
824N/A r[3] -= r[1];
824N/A dsw->sw.num_prev_dirty_areas = 1;
824N/A
824N/A if (dsw->sw.feedback_pixmap != None) {
824N/A XDPSSetContextDrawable(dsw->sw.context, dsw->sw.feedback_pixmap,
824N/A dsw->sw.drawing_area->core.height);
824N/A SetPixmapOrigin(dsw);
824N/A XDPSCaptureContextGState(dsw->sw.context,
824N/A &dsw->sw.feedback_gstate);
824N/A
824N/A /* Initialize the feedback pixmap with a copy of the drawing */
824N/A if (dsw->sw.backing_pixmap != None) {
824N/A CopyToFeedbackPixmap(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A } else {
824N/A CopyRectsToCurrentDrawing(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A (void) ClipAndDraw(dsw, DSWFeedbackPixmap, DSWFinish, True);
824N/A }
824N/A if (!dsw->sw.feedback_displayed) {
824N/A XCopyArea(XtDisplay(dsw), dsw->sw.feedback_pixmap,
824N/A XtWindow(dsw->sw.drawing_area),
824N/A dsw->sw.no_ge_gc, 0, 0,
824N/A dsw->sw.drawing_area->core.width,
824N/A dsw->sw.drawing_area->core.height, 0, 0);
824N/A }
824N/A }
824N/A
824N/A if (dsw->sw.feedback_displayed) {
824N/A CallFeedbackCallback(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A }
824N/A if (dsw->sw.feedback_pixmap != None) {
824N/A UpdateWindowFromFeedbackPixmap(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A }
824N/A dsw->sw.num_pending_dirty = dsw->sw.num_pending_expose = 0;
824N/A
824N/A } else {
824N/A if (dsw->sw.backing_pixmap != None &&
824N/A dsw->sw.drawing_stage == DSWDone) {
824N/A ComputeOffsets(dsw, &deltaX, &deltaY);
824N/A if (!dsw->sw.big_pixmap) dsw->sw.scrolling = True;
824N/A
824N/A XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
824N/A XtWindow(dsw->sw.drawing_area), dsw->sw.no_ge_gc,
824N/A deltaX, deltaY,
824N/A dsw->sw.drawing_area->core.width,
824N/A dsw->sw.drawing_area->core.height, 0, 0);
824N/A } else dsw->sw.scrolling = True;
824N/A }
824N/A}
824N/A
824N/Astatic void AddExposureToPending(
824N/A DPSScrolledWindowWidget dsw,
824N/A XExposeEvent *ev)
824N/A{
824N/A float *f;
824N/A int *i;
824N/A
824N/A if (dsw->sw.backing_pixmap == None || dsw->sw.watch_progress ||
824N/A dsw->sw.doing_feedback) {
824N/A GrowRectList(&dsw->sw.pending_dirty, &dsw->sw.pending_dirty_size,
824N/A dsw->sw.num_pending_dirty, 1, 1);
824N/A
824N/A f = dsw->sw.pending_dirty + (dsw->sw.num_pending_dirty * 4);
824N/A ConvertToPS(dsw, ev->x + DELTA, ev->y + ev->height - DELTA, f, f+1);
824N/A ConvertToPS(dsw, ev->x + ev->width - DELTA, ev->y + DELTA, f+2, f+3);
824N/A f[2] -= f[0];
824N/A f[3] -= f[1];
824N/A dsw->sw.num_pending_dirty++;
824N/A }
824N/A
824N/A GrowIntRectList(&dsw->sw.pending_expose, &dsw->sw.pending_expose_size,
824N/A dsw->sw.num_pending_expose, 1, 1);
824N/A
824N/A i = dsw->sw.pending_expose + (dsw->sw.num_pending_expose * 4);
824N/A i[0] = ev->x;
824N/A i[1] = ev->y;
824N/A i[2] = ev->width;
824N/A i[3] = ev->height;
824N/A dsw->sw.num_pending_expose++;
824N/A}
824N/A
824N/Astatic void AddRectsToPending(
824N/A DPSScrolledWindowWidget dsw,
824N/A int *newRect,
824N/A int n)
824N/A{
824N/A int *r;
824N/A int i;
824N/A float *f;
824N/A
824N/A if (dsw->sw.backing_pixmap == None || dsw->sw.watch_progress) {
824N/A GrowRectList(&dsw->sw.pending_dirty, &dsw->sw.pending_dirty_size,
824N/A dsw->sw.num_pending_dirty, n, 1);
824N/A
824N/A for (i = 0; i < n; i++) {
824N/A f = dsw->sw.pending_dirty + (dsw->sw.num_pending_dirty * 4);
824N/A r = newRect + (i * 4);
824N/A ConvertToPS(dsw, r[0] + DELTA, r[1] + r[3] - DELTA, f, f+1);
824N/A ConvertToPS(dsw, r[0] + r[2] - DELTA, r[1] + DELTA, f+2, f+3);
824N/A f[2] -= f[0];
824N/A f[3] -= f[1];
824N/A dsw->sw.num_pending_dirty++;
824N/A }
824N/A }
824N/A
824N/A GrowIntRectList(&dsw->sw.pending_expose, &dsw->sw.pending_expose_size,
824N/A dsw->sw.num_pending_expose, n, 1);
824N/A
824N/A r = dsw->sw.pending_expose + (dsw->sw.num_pending_expose * 4);
824N/A for (i = 0; i < 4*n; i++) r[i] = newRect[i];
824N/A dsw->sw.num_pending_expose += n;
824N/A}
824N/A
824N/Astatic void AddUserSpaceRectsToPending(
824N/A DPSScrolledWindowWidget dsw,
824N/A float *newRect,
824N/A int n)
824N/A{
824N/A int *r;
824N/A int i;
824N/A float *f;
824N/A
824N/A if (dsw->sw.backing_pixmap == None || dsw->sw.watch_progress) {
824N/A GrowRectList(&dsw->sw.pending_dirty, &dsw->sw.pending_dirty_size,
824N/A dsw->sw.num_pending_dirty, n, 1);
824N/A
824N/A f = dsw->sw.pending_dirty + (dsw->sw.num_pending_dirty * 4);
824N/A for (i = 0; i < 4*n; i++) f[i] = newRect[i];
824N/A dsw->sw.num_pending_dirty += n;
824N/A }
824N/A
824N/A GrowIntRectList(&dsw->sw.pending_expose, &dsw->sw.pending_expose_size,
824N/A dsw->sw.num_pending_expose, n, 1);
824N/A
824N/A for (i = 0; i < n; i++) {
824N/A r = dsw->sw.pending_expose + (dsw->sw.num_pending_expose * 4);
824N/A f = newRect + (i * 4);
824N/A ConvertToX(dsw, LEFT(f), TOP(f), r, r+1);
824N/A ConvertToX(dsw, RIGHT(f), BOTTOM(f), r+2, r+3);
824N/A r[2] -= r[0];
824N/A r[3] -= r[1];
824N/A dsw->sw.num_pending_expose++;
824N/A }
824N/A}
824N/A
824N/Astatic void CopyRectsToCurrentDrawing(
824N/A DPSScrolledWindowWidget dsw,
824N/A float *newRect,
824N/A int n)
824N/A{
824N/A float *r;
824N/A int i;
824N/A
824N/A GrowRectList(&dsw->sw.current_drawing, &dsw->sw.current_drawing_size,
824N/A 0, n, 1);
824N/A
824N/A r = dsw->sw.current_drawing;
824N/A for (i = 0; i < 4*n; i++) r[i] = newRect[i];
824N/A dsw->sw.num_current_drawing = n;
824N/A}
824N/A
824N/Astatic void CopyRectsToDirtyArea(
824N/A DPSScrolledWindowWidget dsw,
824N/A float *newRect,
824N/A int n)
824N/A{
824N/A float *r;
824N/A int i;
824N/A
824N/A GrowRectList(&dsw->sw.dirty_areas, &dsw->sw.dirty_areas_size, 0, n, 1);
824N/A
824N/A r = dsw->sw.dirty_areas;
824N/A for (i = 0; i < 4*n; i++) r[i] = newRect[i];
824N/A dsw->sw.num_dirty_areas = n;
824N/A}
824N/A
824N/Astatic void AddRectsToDirtyArea(
824N/A DPSScrolledWindowWidget dsw,
824N/A float *newRect,
824N/A int n)
824N/A{
824N/A float *r;
824N/A int i;
824N/A
824N/A GrowRectList(&dsw->sw.dirty_areas, &dsw->sw.dirty_areas_size,
824N/A dsw->sw.num_dirty_areas, n, 1);
824N/A
824N/A r = dsw->sw.dirty_areas + (4 * dsw->sw.num_dirty_areas);
824N/A for (i = 0; i < 4*n; i++) r[i] = newRect[i];
824N/A dsw->sw.num_dirty_areas += n;
824N/A}
824N/A
824N/Astatic void CopyRectsToPrevDirtyArea(
824N/A DPSScrolledWindowWidget dsw,
824N/A float *newRect,
824N/A int n)
824N/A{
824N/A float *r;
824N/A int i;
824N/A
824N/A GrowRectList(&dsw->sw.prev_dirty_areas,
824N/A &dsw->sw.prev_dirty_areas_size, 0, n, 1);
824N/A
824N/A r = dsw->sw.prev_dirty_areas;
824N/A for (i = 0; i < 4*n; i++) r[i] = newRect[i];
824N/A dsw->sw.num_prev_dirty_areas = n;
824N/A}
824N/A
824N/A/* ARGSUSED */
824N/A
824N/Astatic void DrawingAreaGraphicsExpose(
824N/A Widget w,
824N/A XtPointer clientData,
824N/A XEvent *event,
824N/A Boolean *goOn)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) clientData;
824N/A XExposeEvent *ev = (XExposeEvent *) event;
824N/A
824N/A switch (event->type) {
824N/A case GraphicsExpose:
824N/A /* GraphicsExpose occur during unbuffered scrolling */
824N/A if (dsw->sw.backing_pixmap == None && dsw->sw.scrolling) {
824N/A /* Unbuffered scrolling case */
824N/A AddExposureToPending(dsw, ev);
824N/A
824N/A if (ev->count == 0) {
824N/A AddRectsToDirtyArea(dsw, dsw->sw.pending_dirty,
824N/A dsw->sw.num_pending_dirty);
824N/A StartDrawing(dsw);
824N/A dsw->sw.num_pending_dirty = dsw->sw.num_pending_expose = 0;
824N/A }
824N/A }
824N/A break;
824N/A }
824N/A}
824N/A
824N/Astatic Boolean MoreExposes(Widget w)
824N/A{
824N/A XEvent event;
824N/A
824N/A if (XPending(XtDisplay(w)) > 0) {
824N/A if (XCheckTypedWindowEvent(XtDisplay(w), XtWindow(w),
824N/A Expose, &event)) {
824N/A XPutBackEvent(XtDisplay(w), &event);
824N/A return True;;
824N/A }
824N/A }
824N/A return False;
824N/A}
824N/A
824N/Astatic void DrawingAreaExpose(
824N/A Widget w,
824N/A XtPointer clientData, XtPointer callData)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) clientData;
824N/A XmDrawingAreaCallbackStruct *d = (XmDrawingAreaCallbackStruct *) callData;
824N/A XExposeEvent *ev = (XExposeEvent *) d->event;
824N/A int dx, dy;
824N/A
824N/A if (dsw->sw.doing_feedback) {
824N/A if (dsw->sw.feedback_pixmap != None) {
824N/A XCopyArea(XtDisplay(dsw), dsw->sw.feedback_pixmap,
824N/A XtWindow(dsw->sw.drawing_area),
824N/A dsw->sw.no_ge_gc,
824N/A ev->x, ev->y, ev->width, ev->height, ev->x, ev->y);
824N/A } else {
824N/A if (dsw->sw.backing_pixmap != None) {
824N/A ComputeOffsets(dsw, &dx, &dy);
824N/A
824N/A XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
824N/A XtWindow(dsw->sw.drawing_area),
824N/A dsw->sw.no_ge_gc, ev->x + dx, ev->y + dy,
824N/A ev->width, ev->height, ev->x, ev->y);
824N/A }
824N/A AddExposureToPending(dsw, ev);
824N/A if (ev->count != 0 || MoreExposes(w)) return;
824N/A
824N/A if (dsw->sw.backing_pixmap == None) {
824N/A CopyRectsToCurrentDrawing(dsw, dsw->sw.pending_dirty,
824N/A dsw->sw.num_pending_dirty);
824N/A dsw->sw.drawing_stage = DSWStart;
824N/A FinishDrawing(dsw);
824N/A }
824N/A if (dsw->sw.feedback_displayed) {
824N/A CallFeedbackCallback(dsw, dsw->sw.pending_dirty,
824N/A dsw->sw.num_pending_dirty);
824N/A }
824N/A dsw->sw.num_pending_dirty = dsw->sw.num_pending_expose = 0;
824N/A }
824N/A return;
824N/A }
824N/A
824N/A if (dsw->sw.backing_pixmap != None) {
824N/A if (dsw->sw.drawing_stage == DSWStart && dsw->sw.watch_progress) {
824N/A SplitExposeEvent(dsw, ev);
824N/A if (ev->count == 0) {
824N/A if (MoreExposes(w)) return;
824N/A StartDrawing(dsw);
824N/A dsw->sw.num_pending_dirty = dsw->sw.num_pending_expose = 0;
824N/A }
824N/A return;
824N/A }
824N/A
824N/A if (dsw->sw.drawing_stage < DSWDrewVisible) {
824N/A SplitExposeEvent(dsw, ev);
824N/A return;
824N/A }
824N/A ComputeOffsets(dsw, &dx, &dy);
824N/A
824N/A XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
824N/A XtWindow(dsw->sw.drawing_area),
824N/A dsw->sw.no_ge_gc,
824N/A ev->x + dx, ev->y + dy, ev->width, ev->height, ev->x, ev->y);
824N/A } else {
824N/A AddExposureToPending(dsw, ev);
824N/A if (ev->count == 0) {
824N/A if (MoreExposes(w)) return;
824N/A if (dsw->sw.drawing_stage == DSWDone ||
824N/A dsw->sw.drawing_stage == DSWStart) {
824N/A CopyRectsToDirtyArea(dsw, dsw->sw.pending_dirty,
824N/A dsw->sw.num_pending_dirty);
824N/A StartDrawing(dsw);
824N/A dsw->sw.num_pending_dirty = dsw->sw.num_pending_expose = 0;
824N/A }
824N/A }
824N/A }
824N/A}
824N/A
824N/Astatic void Resize(Widget w)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
824N/A DSWResizeCallbackRec r;
824N/A float x, y;
824N/A
824N/A if (XtIsRealized(w)) (void) AbortOrFinish(dsw);
824N/A
824N/A r.oldw = dsw->sw.scrolled_window->core.width;
824N/A r.oldh = dsw->sw.scrolled_window->core.height;
824N/A r.neww = dsw->core.width;
824N/A r.newh = dsw->core.height;
824N/A r.x = r.y = 0;
824N/A
824N/A XtCallCallbackList(w, dsw->sw.resize_callback, (XtPointer) &r);
824N/A
824N/A if (XtIsRealized(w)) {
824N/A ConvertToPS(dsw, (float) r.x, (float) r.y, &x, &y);
824N/A } else if (r.x != 0 || r.y != 0) ScrollBy(w, r.x, r.y);
824N/A
824N/A XtResizeWidget(dsw->sw.scrolled_window, w->core.width, w->core.height, 0);
824N/A
824N/A if (!XtIsRealized(w)) return;
824N/A
824N/A if (dsw->sw.backing_pixmap != None &&
824N/A dsw->sw.pixmap_width == CEIL(dsw->sw.drawing_width) &&
824N/A dsw->sw.pixmap_height == CEIL(dsw->sw.drawing_height) &&
824N/A dsw->sw.pixmap_width >= (int) dsw->sw.drawing_area->core.width &&
824N/A dsw->sw.pixmap_height >= (int) dsw->sw.drawing_area->core.width) {
824N/A
824N/A XDPSSetContextGState(dsw->sw.context, dsw->sw.window_gstate);
824N/A DPSinitclip(dsw->sw.context);
824N/A DPSinitviewclip(dsw->sw.context);
824N/A SetDrawingAreaPosition(dsw, x, y, r.x, r.y, True);
824N/A SetOriginAndGetTransform(dsw);
824N/A XDPSUpdateContextGState(dsw->sw.context, dsw->sw.window_gstate);
824N/A XClearArea(XtDisplay(dsw), XtWindow(dsw->sw.drawing_area),
824N/A 0, 0, 0, 0, True);
824N/A } else {
824N/A dsw->sw.use_saved_scroll = True;
824N/A dsw->sw.scroll_pic_x = x;
824N/A dsw->sw.scroll_pic_y = y;
824N/A dsw->sw.scroll_win_x = r.x;
824N/A dsw->sw.scroll_win_y = r.y;
824N/A
824N/A if (dsw->sw.backing_pixmap != None) {
824N/A XFreePixmap(XtDisplay(dsw), dsw->sw.backing_pixmap);
824N/A XDPSFreeContextGState(dsw->sw.context, dsw->sw.backing_gstate);
824N/A }
824N/A dsw->sw.backing_pixmap = None;
824N/A dsw->sw.big_pixmap = False;
824N/A dsw->sw.pixmap_width = dsw->sw.pixmap_height = 0;
824N/A
824N/A dsw->sw.num_dirty_areas = 1;
824N/A LEFT(dsw->sw.dirty_areas) = 0.0;
824N/A BOTTOM(dsw->sw.dirty_areas) = 0.0;
824N/A WIDTH(dsw->sw.dirty_areas) = dsw->sw.area_width;
824N/A HEIGHT(dsw->sw.dirty_areas) = dsw->sw.area_height;
824N/A
824N/A SetUpInitialInformation(dsw);
824N/A }
824N/A
824N/A if (dsw->sw.doing_feedback) {
824N/A float *r;
824N/A int dx, dy;
824N/A
824N/A CheckFeedbackPixmap(dsw);
824N/A r = dsw->sw.prev_dirty_areas;
824N/A ConvertToPS(dsw, 0 + DELTA, dsw->sw.drawing_area->core.height - DELTA,
824N/A r, r+1);
824N/A ConvertToPS(dsw, dsw->sw.drawing_area->core.width - DELTA, 0 + DELTA,
824N/A r+2, r+3);
824N/A r[2] -= r[0];
824N/A r[3] -= r[1];
824N/A dsw->sw.num_prev_dirty_areas = 1;
824N/A
824N/A if (dsw->sw.feedback_pixmap != None) {
824N/A /* Initialize the feedback pixmap with a copy of the drawing */
824N/A if (dsw->sw.backing_pixmap != None) {
824N/A CopyToFeedbackPixmap(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A } else {
824N/A CopyRectsToCurrentDrawing(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A (void) ClipAndDraw(dsw, DSWFeedbackPixmap, DSWFinish, True);
824N/A }
824N/A XCopyArea(XtDisplay(dsw), dsw->sw.feedback_pixmap,
824N/A XtWindow(dsw->sw.drawing_area),
824N/A dsw->sw.no_ge_gc, 0, 0,
824N/A dsw->sw.drawing_area->core.width,
824N/A dsw->sw.drawing_area->core.height, 0, 0);
824N/A } else {
824N/A if (dsw->sw.backing_pixmap != None) {
824N/A ComputeOffsets(dsw, &dx, &dy);
824N/A
824N/A XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
824N/A XtWindow(dsw->sw.drawing_area),
824N/A dsw->sw.no_ge_gc, dx, dy,
824N/A dsw->sw.drawing_area->core.width,
824N/A dsw->sw.drawing_area->core.height, 0, 0);
824N/A } else {
824N/A CopyRectsToCurrentDrawing(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A dsw->sw.drawing_stage = DSWStart;
824N/A FinishDrawing(dsw);
824N/A }
824N/A }
824N/A if (dsw->sw.feedback_displayed) {
824N/A CallFeedbackCallback(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A }
824N/A if (dsw->sw.feedback_pixmap != None) {
824N/A UpdateWindowFromFeedbackPixmap(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A }
824N/A dsw->sw.num_pending_dirty = dsw->sw.num_pending_expose = 0;
824N/A }
824N/A}
824N/A
824N/Astatic void CheckFeedbackPixmap(DPSScrolledWindowWidget dsw)
824N/A{
824N/A if (dsw->sw.feedback_pixmap != None &&
824N/A (dsw->sw.feedback_width < (int) dsw->sw.drawing_area->core.width ||
824N/A dsw->sw.feedback_height < (int) dsw->sw.drawing_area->core.height)) {
824N/A XFreePixmap(XtDisplay(dsw), dsw->sw.feedback_pixmap);
824N/A dsw->sw.feedback_pixmap = None;
824N/A dsw->sw.feedback_width = dsw->sw.feedback_height = 0;
824N/A }
824N/A if (dsw->sw.use_feedback_pixmap && dsw->sw.feedback_pixmap == None) {
824N/A dsw->sw.feedback_pixmap =
824N/A AllocPixmap(dsw, dsw->sw.drawing_area->core.width,
824N/A dsw->sw.drawing_area->core.height);
824N/A if (dsw->sw.feedback_pixmap != None) {
824N/A dsw->sw.feedback_width = dsw->sw.drawing_area->core.width;
824N/A dsw->sw.feedback_height = dsw->sw.drawing_area->core.height;
824N/A }
824N/A }
824N/A if (dsw->sw.feedback_pixmap != None) {
824N/A XDPSSetContextDrawable(dsw->sw.context, dsw->sw.feedback_pixmap,
824N/A dsw->sw.drawing_area->core.height);
824N/A SetPixmapOrigin(dsw);
824N/A XDPSCaptureContextGState(dsw->sw.context, &dsw->sw.feedback_gstate);
824N/A }
824N/A}
824N/A
824N/Astatic void UpdateGStates(DPSScrolledWindowWidget dsw)
824N/A{
824N/A /* Create graphics states for the window and backing pixmap in
824N/A the new context */
824N/A XDPSSetContextDrawable(dsw->sw.context, XtWindow(dsw->sw.drawing_area),
824N/A dsw->sw.drawing_area->core.height);
824N/A DPSinitgraphics(dsw->sw.context);
824N/A if (dsw->sw.scale != 1.0) {
824N/A DPSscale(dsw->sw.context, dsw->sw.scale, dsw->sw.scale);
824N/A }
824N/A
824N/A SetOriginAndGetTransform(dsw);
824N/A (void) XDPSCaptureContextGState(dsw->sw.context, &dsw->sw.window_gstate);
824N/A if (dsw->sw.backing_pixmap != None) {
824N/A XDPSSetContextDrawable(dsw->sw.context, dsw->sw.backing_pixmap,
824N/A dsw->sw.pixmap_height);
824N/A
824N/A SetPixmapOffset(dsw);
824N/A SetPixmapOrigin(dsw);
824N/A XDPSCaptureContextGState(dsw->sw.context, &dsw->sw.backing_gstate);
824N/A }
824N/A}
824N/A
824N/Astatic void CheckPixmapSize(DPSScrolledWindowWidget dsw)
824N/A{
824N/A Boolean freeIt = False;
824N/A int w = dsw->sw.pixmap_width, h = dsw->sw.pixmap_height;
824N/A Widget wid = dsw->sw.drawing_area;
824N/A unsigned int dBytes;
824N/A
824N/A if (dsw->sw.pixmap_limit > 0) {
824N/A if (w * h > dsw->sw.pixmap_limit) freeIt = True;
824N/A } else if (dsw->sw.pixmap_limit < 0 &&
824N/A w * h > dsw->sw.unscaled_width * dsw->sw.unscaled_height &&
824N/A w * h > (int) wid->core.width * (int) wid->core.height) {
824N/A freeIt = True;
824N/A }
824N/A
824N/A if (dsw->sw.absolute_pixmap_limit > 0) {
824N/A dBytes = (wid->core.depth + 7) / 8; /* Convert into bytes */
824N/A if (w * h * dBytes > (unsigned)dsw->sw.absolute_pixmap_limit * 1024) {
824N/A freeIt = True;
824N/A }
824N/A }
824N/A if (freeIt) {
824N/A XFreePixmap(XtDisplay(dsw), dsw->sw.backing_pixmap);
824N/A dsw->sw.backing_pixmap = None;
824N/A dsw->sw.big_pixmap = False;
824N/A dsw->sw.pixmap_width = dsw->sw.pixmap_height = 0;
824N/A XDPSFreeContextGState(dsw->sw.context, dsw->sw.backing_gstate);
824N/A }
824N/A}
824N/A
824N/Astatic void ResizeArea(DPSScrolledWindowWidget dsw)
824N/A{
824N/A AbortDrawing(dsw);
824N/A
824N/A /* Make everything dirty */
824N/A dsw->sw.num_dirty_areas = 1;
824N/A LEFT(dsw->sw.dirty_areas) = 0.0;
824N/A BOTTOM(dsw->sw.dirty_areas) = 0.0;
824N/A WIDTH(dsw->sw.dirty_areas) = dsw->sw.area_width;
824N/A HEIGHT(dsw->sw.dirty_areas) = dsw->sw.area_height;
824N/A
824N/A if (dsw->sw.big_pixmap) {
824N/A XFreePixmap(XtDisplay(dsw), dsw->sw.backing_pixmap);
824N/A dsw->sw.backing_pixmap = None;
824N/A dsw->sw.big_pixmap = False;
824N/A dsw->sw.pixmap_width = dsw->sw.pixmap_height = 0;
824N/A XDPSFreeContextGState(dsw->sw.context, dsw->sw.backing_gstate);
824N/A }
824N/A
824N/A if (!dsw->sw.use_saved_scroll) {
824N/A /* Keep the upper left in the same place */
824N/A dsw->sw.scroll_win_x = 0;
824N/A dsw->sw.scroll_win_y = 0;
824N/A ConvertToPS(dsw, 0.0, 0.0,
824N/A &dsw->sw.scroll_pic_x, &dsw->sw.scroll_pic_y);
824N/A dsw->sw.use_saved_scroll = True;
824N/A }
824N/A
824N/A SetUpInitialInformation(dsw);
824N/A}
824N/A
824N/Astatic void ClearDirtyAreas(DPSScrolledWindowWidget dsw)
824N/A{
824N/A int i;
824N/A float *r;
824N/A int llx, lly, urx, ury;
824N/A
824N/A for (i = 0; i < dsw->sw.num_dirty_areas; i++) {
824N/A r = dsw->sw.dirty_areas + (i * 4);
824N/A ConvertToX(dsw, LEFT(r), BOTTOM(r), &llx, &lly);
824N/A ConvertToX(dsw, RIGHT(r), TOP(r), &urx, &ury);
824N/A XClearArea(XtDisplay(dsw), XtWindow(dsw->sw.drawing_area),
824N/A llx, ury, urx-llx, lly-ury, True);
824N/A }
824N/A}
824N/A
824N/Astatic void HandleFeedbackPixmapChange(DPSScrolledWindowWidget dsw)
824N/A{
824N/A if (!dsw->sw.use_feedback_pixmap) {
824N/A /* Get rid of one if we have it */
824N/A if (dsw->sw.feedback_pixmap != None) {
824N/A XFreePixmap(XtDisplay(dsw), dsw->sw.feedback_pixmap);
824N/A dsw->sw.feedback_pixmap = None;
824N/A dsw->sw.feedback_width = dsw->sw.feedback_height = 0;
824N/A }
824N/A } else {
824N/A if (dsw->sw.doing_feedback) {
824N/A float *r;
824N/A
824N/A CheckFeedbackPixmap(dsw);
824N/A if (dsw->sw.feedback_pixmap == None) return;
824N/A
824N/A r = dsw->sw.prev_dirty_areas;
824N/A ConvertToPS(dsw, 0 + DELTA,
824N/A dsw->sw.drawing_area->core.height - DELTA, r, r+1);
824N/A ConvertToPS(dsw, dsw->sw.drawing_area->core.width - DELTA,
824N/A 0 + DELTA, r+2, r+3);
824N/A r[2] -= r[0];
824N/A r[3] -= r[1];
824N/A dsw->sw.num_prev_dirty_areas = 1;
824N/A
824N/A /* Initialize the feedback pixmap with a copy of the drawing */
824N/A if (dsw->sw.backing_pixmap != None) {
824N/A CopyToFeedbackPixmap(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A } else {
824N/A CopyRectsToCurrentDrawing(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A (void) ClipAndDraw(dsw, DSWFeedbackPixmap, DSWFinish, True);
824N/A }
824N/A if (dsw->sw.feedback_displayed) {
824N/A CallFeedbackCallback(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A }
824N/A }
824N/A }
824N/A}
824N/A
824N/A/* ARGSUSED */
824N/A
824N/Astatic Boolean SetValues(
824N/A Widget old, Widget req, Widget new,
824N/A ArgList args,
824N/A Cardinal *num_args)
824N/A{
824N/A DPSScrolledWindowWidget olddsw = (DPSScrolledWindowWidget) old;
824N/A DPSScrolledWindowWidget newdsw = (DPSScrolledWindowWidget) new;
824N/A Bool inited;
824N/A
824N/A#define NE(field) newdsw->sw.field != olddsw->sw.field
824N/A#define DONT_CHANGE(field) \
824N/A if (NE(field)) newdsw->sw.field = olddsw->sw.field;
824N/A
824N/A DONT_CHANGE(ctm_ptr);
824N/A DONT_CHANGE(inv_ctm_ptr);
824N/A DONT_CHANGE(backing_pixmap);
824N/A DONT_CHANGE(feedback_pixmap);
824N/A DONT_CHANGE(window_gstate);
824N/A DONT_CHANGE(backing_gstate);
824N/A DONT_CHANGE(feedback_gstate);
824N/A
824N/A if (NE(context)) {
824N/A DSWSetupCallbackRec setup;
824N/A
824N/A if (newdsw->sw.context == NULL) {
824N/A newdsw->sw.context = XDPSGetSharedContext(XtDisplay(newdsw));
824N/A }
824N/A if (_XDPSTestComponentInitialized(newdsw->sw.context,
824N/A dps_init_bit_dsw, &inited) ==
824N/A dps_status_unregistered_context) {
824N/A XDPSRegisterContext(newdsw->sw.context, False);
824N/A }
824N/A if (XtIsRealized(newdsw)) {
824N/A setup.context = newdsw->sw.context;
824N/A XtCallCallbackList((Widget) newdsw, newdsw->sw.setup_callback,
824N/A (XtPointer) &setup);
824N/A }
824N/A UpdateGStates(newdsw);
824N/A }
824N/A
824N/A /* Watch progress only works with pass-through event dispatching */
824N/A
824N/A if (NE(watch_progress)) {
824N/A if (newdsw->sw.watch_progress &&
824N/A XDPSSetEventDelivery(XtDisplay(newdsw), dps_event_query) !=
824N/A dps_event_pass_through) newdsw->sw.watch_progress = False;
824N/A }
824N/A
824N/A if (NE(application_scrolling) && !newdsw->sw.application_scrolling) {
824N/A XtVaSetValues(newdsw->sw.h_scroll, XmNmaximum, newdsw->sw.scroll_h_max,
824N/A XmNvalue, newdsw->sw.scroll_h_value,
824N/A XmNsliderSize, newdsw->sw.scroll_h_size, NULL);
824N/A XtVaSetValues(newdsw->sw.v_scroll, XmNmaximum, newdsw->sw.scroll_v_max,
824N/A XmNvalue, newdsw->sw.scroll_v_value,
824N/A XmNsliderSize, newdsw->sw.scroll_v_size, NULL);
824N/A }
824N/A
824N/A if (newdsw->sw.doing_feedback) {
824N/A DONT_CHANGE(scale);
824N/A DONT_CHANGE(area_width);
824N/A DONT_CHANGE(area_height);
824N/A }
824N/A
824N/A if (NE(pixmap_limit) || NE(absolute_pixmap_limit)) CheckPixmapSize(newdsw);
824N/A
824N/A if (NE(area_width) || NE(area_height) || NE(scale)) ResizeArea(newdsw);
824N/A
824N/A /* It's too confusing to let any of these things change in the middle
824N/A of drawing */
824N/A
824N/A if (NE(use_backing_pixmap) || NE(watch_progress) ||
824N/A NE(minimal_drawing) || NE(document_size_pixmaps)) {
824N/A Boolean freeIt = False, setUp = False;
824N/A AbortOrFinish(newdsw);
824N/A if (NE(use_backing_pixmap)) {
824N/A if (newdsw->sw.use_backing_pixmap) setUp = True;
824N/A else freeIt = True;
824N/A }
824N/A if (NE(document_size_pixmaps)) {
824N/A if (newdsw->sw.backing_pixmap != None) freeIt = True;
824N/A setUp = True;
824N/A }
824N/A if (freeIt) FreeBackingPixmap(newdsw);
824N/A if (setUp) SetUpInitialPixmap(newdsw);
824N/A }
824N/A
824N/A if (NE(dirty_areas)) {
824N/A float *r = newdsw->sw.dirty_areas;
824N/A int n = newdsw->sw.num_dirty_areas;
824N/A DONT_CHANGE(dirty_areas);
824N/A DONT_CHANGE(num_dirty_areas);
824N/A AbortOrFinish(newdsw);
824N/A AddRectsToDirtyArea(newdsw, r, n);
824N/A if (newdsw->sw.watch_progress || newdsw->sw.backing_pixmap == None) {
824N/A ClearDirtyAreas(newdsw);
824N/A newdsw->sw.drawing_stage = DSWStart;
824N/A } else {
824N/A AddUserSpaceRectsToPending(newdsw, r, n);
824N/A StartDrawing(newdsw);
824N/A }
824N/A }
824N/A
824N/A if (NE(use_feedback_pixmap)) HandleFeedbackPixmapChange(newdsw);
824N/A
824N/A return False;
824N/A#undef DONT_CHANGE
824N/A}
824N/A
824N/Astatic XtGeometryResult GeometryManager(
824N/A Widget w,
824N/A XtWidgetGeometry *desired, XtWidgetGeometry *allowed)
824N/A{
824N/A /* Pass geometry requests up to our parent */
824N/A return XtMakeGeometryRequest(XtParent(w), desired, allowed);
824N/A}
824N/A
824N/Astatic XtGeometryResult QueryGeometry(
824N/A Widget w,
824N/A XtWidgetGeometry *desired, XtWidgetGeometry *allowed)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
824N/A
824N/A /* Pass geometry requests down to our child */
824N/A return XtQueryGeometry(dsw->sw.scrolled_window, desired, allowed);
824N/A}
824N/A
824N/Astatic void CopyToFeedbackPixmap(
824N/A DPSScrolledWindowWidget dsw,
824N/A float *rects,
824N/A int n)
824N/A{
824N/A int llx, lly, urx, ury;
824N/A int dx, dy;
824N/A int i;
824N/A float *r;
824N/A
824N/A ComputeOffsets(dsw, &dx, &dy);
824N/A
824N/A for (i = 0; i < n; i++) {
824N/A r = rects + (i * 4);
824N/A ConvertToX(dsw, LEFT(r), BOTTOM(r), &llx, &lly);
824N/A ConvertToX(dsw, RIGHT(r), TOP(r), &urx, &ury);
824N/A
824N/A XCopyArea(XtDisplay(dsw), dsw->sw.backing_pixmap,
824N/A dsw->sw.feedback_pixmap, dsw->sw.no_ge_gc,
824N/A llx+dx-1, ury+dy-1, urx-llx+2, lly-ury+2, llx-1, ury-1);
824N/A }
824N/A}
824N/A
824N/Astatic void CallFeedbackCallback(
824N/A DPSScrolledWindowWidget dsw,
824N/A float *r,
824N/A int n)
824N/A{
824N/A DSWFeedbackCallbackRec f;
824N/A
824N/A f.start_feedback_data = dsw->sw.start_feedback_data;
824N/A f.continue_feedback_data = dsw->sw.continue_feedback_data;
824N/A if (dsw->sw.feedback_pixmap == None) {
824N/A f.type = DSWWindow;
824N/A f.drawable = XtWindow(dsw->sw.drawing_area);
824N/A f.gstate = dsw->sw.window_gstate;
824N/A } else {
824N/A f.type = DSWFeedbackPixmap;
824N/A f.drawable = dsw->sw.feedback_pixmap;
824N/A f.gstate = dsw->sw.feedback_gstate;
824N/A }
824N/A f.context = dsw->sw.context;
824N/A f.dirty_rects = r;
824N/A f.dirty_count = n;
824N/A
824N/A XDPSSetContextGState(dsw->sw.context, f.gstate);
824N/A _DPSSWSetRectViewClip(dsw->sw.context, r, n * 4);
824N/A XtCallCallbackList((Widget) dsw, dsw->sw.feedback_callback,
824N/A (XtPointer) &f);
824N/A DPSWaitContext(dsw->sw.context);
824N/A}
824N/A
824N/Astatic void SetScale(
824N/A Widget w,
824N/A double scale,
824N/A long fixedX, long fixedY)
824N/A{
824N/A float psX, psY;
824N/A
824N/A ConvertToPS((DPSScrolledWindowWidget) w, (float) fixedX, (float) fixedY,
824N/A &psX, &psY);
824N/A SetScaleAndScroll(w, scale, psX, psY, fixedX, fixedY);
824N/A}
824N/A
824N/Avoid DSWSetScale(
824N/A Widget w,
824N/A double scale,
824N/A long fixedX, long fixedY)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.set_scale) (w, scale, fixedX, fixedY);
824N/A}
824N/A
824N/Astatic void ScrollPoint(
824N/A Widget w,
824N/A double psX, double psY,
824N/A long xX, long xY)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
824N/A
824N/A if (!XtIsRealized(w)) {
824N/A dsw->sw.use_saved_scroll = True;
824N/A dsw->sw.scroll_pic_x = psX;
824N/A dsw->sw.scroll_pic_y = psY;
824N/A dsw->sw.scroll_win_x = xX;
824N/A dsw->sw.scroll_win_y = xY;
824N/A return;
824N/A } else {
824N/A SetDrawingAreaPosition(dsw, psX, psY, xX, xY, False);
824N/A ScrollMoved(dsw);
824N/A }
824N/A}
824N/A
824N/Avoid DSWScrollPoint(
824N/A Widget w,
824N/A double psX, double psY,
824N/A long xX, long xY)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.scroll_point) (w, psX, psY, xX, xY);
824N/A}
824N/A
824N/Astatic void ScrollBy(Widget w, long dx, long dy)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
824N/A int value;
824N/A
824N/A if (dx == 0 && dy == 0) return;
824N/A
824N/A if (!XtIsRealized(w) && dsw->sw.use_saved_scroll) {
824N/A dsw->sw.scroll_win_x += dx;
824N/A dsw->sw.scroll_win_y += dy;
824N/A } else {
824N/A value = dsw->sw.scroll_h_value + dx;
824N/A
824N/A if (value < 0) value = 0;
824N/A else if (value > dsw->sw.scroll_h_max - dsw->sw.scroll_h_size) {
824N/A value = dsw->sw.scroll_h_max - dsw->sw.scroll_h_size;
824N/A }
824N/A dsw->sw.scroll_h_value = value;
824N/A
824N/A if (!dsw->sw.application_scrolling) {
824N/A XtVaSetValues(dsw->sw.h_scroll, XmNvalue, value, NULL);
824N/A }
824N/A
824N/A value = dsw->sw.scroll_v_value + dy;
824N/A
824N/A if (value < 0) value = 0;
824N/A else if (value > dsw->sw.scroll_v_max - dsw->sw.scroll_v_size) {
824N/A value = dsw->sw.scroll_v_max - dsw->sw.scroll_v_size;
824N/A }
824N/A dsw->sw.scroll_v_value = value;
824N/A
824N/A if (!dsw->sw.application_scrolling) {
824N/A XtVaSetValues(dsw->sw.v_scroll, XmNvalue, value, NULL);
824N/A }
824N/A
824N/A ScrollMoved(dsw);
824N/A }
824N/A}
824N/A
824N/Avoid DSWScrollBy(Widget w, long dx, long dy)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.scroll_by) (w, dx, dy);
824N/A}
824N/A
824N/Astatic void ScrollTo(Widget w, long x, long y)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
824N/A int max, size;
824N/A
824N/A if (XtIsRealized(w)) {
824N/A if (x < 0) x = 0;
824N/A else if (x > dsw->sw.scroll_h_max - dsw->sw.scroll_h_size) {
824N/A x = dsw->sw.scroll_h_max - dsw->sw.scroll_h_size;
824N/A }
824N/A dsw->sw.scroll_h_value = x;
824N/A
824N/A if (y < 0) y = 0;
824N/A else if (y > dsw->sw.scroll_v_max - dsw->sw.scroll_v_size) {
824N/A y = dsw->sw.scroll_v_max - dsw->sw.scroll_v_size;
824N/A }
824N/A dsw->sw.scroll_v_value = y;
824N/A
824N/A if (!dsw->sw.application_scrolling) {
824N/A XtVaSetValues(dsw->sw.h_scroll, XmNvalue, x, NULL);
824N/A XtVaSetValues(dsw->sw.v_scroll, XmNvalue, y, NULL);
824N/A }
824N/A
824N/A ScrollMoved(dsw);
824N/A }
824N/A}
824N/A
824N/Avoid DSWScrollTo(Widget w, long x, long y)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.scroll_to) (w, x, y);
824N/A}
824N/A
824N/Astatic void SetScaleAndScroll(
824N/A Widget w,
824N/A double scale,
824N/A double psX, double psY,
824N/A long xX, long xY)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
824N/A Arg arg;
824N/A union {
824N/A int i;
824N/A float f;
824N/A } kludge;
824N/A
824N/A dsw->sw.use_saved_scroll = True;
824N/A dsw->sw.scroll_pic_x = psX;
824N/A dsw->sw.scroll_pic_y = psY;
824N/A dsw->sw.scroll_win_x = xX;
824N/A dsw->sw.scroll_win_y = xY;
824N/A
824N/A kludge.f = scale;
824N/A arg.name = XtNscale;
824N/A if (sizeof(float) > sizeof(XtArgVal)) arg.value = (XtArgVal) &kludge.f;
824N/A else arg.value = (XtArgVal) kludge.i;
824N/A XtSetValues(w, &arg, 1);
824N/A}
824N/A
824N/Avoid DSWSetScaleAndScroll(
824N/A Widget w,
824N/A double scale,
824N/A double psX, double psY,
824N/A long xX, long xY)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.set_scale_and_scroll) (w, scale, psX, psY, xX, xY);
824N/A}
824N/A
824N/Astatic void ConvertXToPS(
824N/A Widget w,
824N/A long xX, long xY,
824N/A float *psX, float *psY)
824N/A{
824N/A ConvertToPS((DPSScrolledWindowWidget) w, (float) xX, (float) xY, psX, psY);
824N/A}
824N/A
824N/Avoid DSWConvertXToPS(
824N/A Widget w,
824N/A long xX, long xY,
824N/A float *psX, float *psY)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.convert_x_to_ps) (w, xX, xY, psX, psY);
824N/A}
824N/A
824N/Astatic void ConvertPSToX(
824N/A Widget w,
824N/A double psX, double psY,
824N/A int *xX, int *xY)
824N/A{
824N/A ConvertToX((DPSScrolledWindowWidget) w, psX, psY, xX, xY);
824N/A}
824N/A
824N/Avoid DSWConvertPSToX(
824N/A Widget w,
824N/A double psX, double psY,
824N/A int *xX, int *xY)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.convert_ps_to_x) (w, psX, psY, xX, xY);
824N/A}
824N/A
824N/Astatic void AddToDirtyArea(
824N/A Widget w,
824N/A float *rect,
824N/A long n)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
824N/A
824N/A if (n == 1 && rect[0] == 0 && rect[1] == 0 &&
824N/A rect[2] == -1 && rect[2] == -1) {
824N/A rect[2] = dsw->sw.area_width;
824N/A rect[3] = dsw->sw.area_height;
824N/A }
824N/A
824N/A XtVaSetValues(w, XtNdirtyAreas, rect, XtNnumDirtyAreas, n, NULL);
824N/A}
824N/A
824N/Avoid DSWAddToDirtyArea(
824N/A Widget w,
824N/A float *rect,
824N/A long n)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.add_to_dirty_area) (w, rect, n);
824N/A}
824N/A
824N/Astatic Boolean TakeFeedbackPixmap(
824N/A Widget w,
824N/A Pixmap *p,
824N/A int *width, int *height, int *depth,
824N/A Screen **screen)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
824N/A
824N/A if (dsw->sw.doing_feedback) return False;
824N/A
824N/A *p = dsw->sw.feedback_pixmap;
824N/A if (*p == None) {
824N/A *width = *height = *depth;
824N/A *screen = NULL;
824N/A return True;
824N/A }
824N/A
824N/A *width = dsw->sw.feedback_width;
824N/A *height = dsw->sw.feedback_height;
824N/A *depth = dsw->sw.drawing_area->core.depth;
824N/A *screen = dsw->core.screen;
824N/A
824N/A dsw->sw.feedback_pixmap = None;
824N/A dsw->sw.feedback_width = dsw->sw.feedback_height = 0;
824N/A return True;
824N/A}
824N/A
824N/ABoolean DSWTakeFeedbackPixmap(
824N/A Widget w,
824N/A Pixmap *p,
824N/A int *width, int *height, int *depth,
824N/A Screen **screen)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A return (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.take_feedback_pixmap) (w, p, width, height,
824N/A depth, screen);
824N/A}
824N/A
824N/Astatic void StartFeedbackDrawing(
824N/A Widget w,
824N/A XtPointer start_feedback_data)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
824N/A float *r;
824N/A
824N/A FinishDrawing(dsw);
824N/A CheckFeedbackPixmap(dsw);
824N/A if (dsw->sw.feedback_pixmap != None) {
824N/A /* Initialize the feedback pixmap with a copy of the drawing */
824N/A GrowRectList(&dsw->sw.prev_dirty_areas, &dsw->sw.prev_dirty_areas_size,
824N/A 0, 1, 1);
824N/A r = dsw->sw.prev_dirty_areas;
824N/A ConvertToPS(dsw, 0 + DELTA, dsw->sw.drawing_area->core.height - DELTA,
824N/A r, r+1);
824N/A ConvertToPS(dsw, dsw->sw.drawing_area->core.width - DELTA, 0 + DELTA,
824N/A r+2, r+3);
824N/A r[2] -= r[0];
824N/A r[3] -= r[1];
824N/A dsw->sw.num_prev_dirty_areas = 1;
824N/A
824N/A if (dsw->sw.backing_pixmap != None) {
824N/A CopyToFeedbackPixmap(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A } else {
824N/A CopyRectsToCurrentDrawing(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A (void) ClipAndDraw(dsw, DSWFeedbackPixmap, DSWFinish, True);
824N/A }
824N/A }
824N/A dsw->sw.num_prev_dirty_areas = 0;
824N/A dsw->sw.doing_feedback = True;
824N/A dsw->sw.start_feedback_data = start_feedback_data;
824N/A}
824N/A
824N/Avoid DSWStartFeedbackDrawing(
824N/A Widget w,
824N/A XtPointer start_feedback_data)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.start_feedback_drawing) (w, start_feedback_data);
824N/A}
824N/A
824N/Astatic void EndFeedbackDrawing(
824N/A Widget w,
824N/A int restore)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
824N/A
824N/A if (restore) {
824N/A if (dsw->sw.backing_pixmap != None) {
824N/A UpdateWindowFromBackingPixmap(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A } else {
824N/A CopyRectsToCurrentDrawing(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A (void) ClipAndDraw(dsw, DSWWindow, DSWFinish, True);
824N/A }
824N/A }
824N/A if (dsw->sw.feedback_gstate != 0) {
824N/A XDPSFreeContextGState(dsw->sw.context, dsw->sw.feedback_gstate);
824N/A }
824N/A dsw->sw.doing_feedback = dsw->sw.feedback_displayed = False;
824N/A}
824N/A
824N/Avoid DSWEndFeedbackDrawing(
824N/A Widget w,
824N/A Bool restore)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.end_feedback_drawing) (w, restore);
824N/A}
824N/A
824N/Astatic void SetFeedbackDirtyArea(
824N/A Widget w,
824N/A float *rects,
824N/A int count,
824N/A XtPointer continue_feedback_data)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
824N/A int i;
824N/A float *r;
824N/A
824N/A for (i = 0; i < count; i++) {
824N/A r = rects + (i * 4);
824N/A if (WIDTH(r) < 0) {
824N/A LEFT(r) += WIDTH(r);
824N/A WIDTH(r) = -WIDTH(r);
824N/A }
824N/A if (HEIGHT(r) < 0) {
824N/A BOTTOM(r) += HEIGHT(r);
824N/A HEIGHT(r) = -HEIGHT(r);
824N/A }
824N/A }
824N/A
824N/A if (dsw->sw.backing_pixmap != None) {
824N/A if (dsw->sw.feedback_pixmap != None) {
824N/A CopyToFeedbackPixmap(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A } else {
824N/A UpdateWindowFromBackingPixmap(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A }
824N/A } else {
824N/A CopyRectsToCurrentDrawing(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A (void) ClipAndDraw(dsw, (dsw->sw.feedback_pixmap == None ?
824N/A DSWWindow : DSWFeedbackPixmap),
824N/A DSWFinish, True);
824N/A }
824N/A dsw->sw.continue_feedback_data = continue_feedback_data;
824N/A CallFeedbackCallback(dsw, rects, count);
824N/A
824N/A if (dsw->sw.feedback_pixmap != None) {
824N/A CopyRectsToDirtyArea(dsw, dsw->sw.prev_dirty_areas,
824N/A dsw->sw.num_prev_dirty_areas);
824N/A AddRectsToDirtyArea(dsw, rects, count);
824N/A SimplifyRects(dsw->sw.dirty_areas, &dsw->sw.num_dirty_areas);
824N/A UpdateWindowFromFeedbackPixmap(dsw, dsw->sw.dirty_areas,
824N/A dsw->sw.num_dirty_areas);
824N/A dsw->sw.num_dirty_areas = 0;
824N/A }
824N/A CopyRectsToPrevDirtyArea(dsw, rects, count);
824N/A dsw->sw.feedback_displayed = True;
824N/A}
824N/A
824N/Avoid DSWSetFeedbackDirtyArea(
824N/A Widget w,
824N/A float *rects,
824N/A int count,
824N/A XtPointer continue_feedback_data)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.set_feedback_dirty_area) (w, rects, count,
824N/A continue_feedback_data);
824N/A}
824N/A
824N/Astatic void FinishPendingDrawing(Widget w)
824N/A{
824N/A FinishDrawing((DPSScrolledWindowWidget) w);
824N/A}
824N/A
824N/Avoid DSWFinishPendingDrawing(Widget w)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.finish_pending_drawing) (w);
824N/A}
824N/A
824N/Astatic void AbortPendingDrawing(Widget w)
824N/A{
824N/A AbortDrawing((DPSScrolledWindowWidget) w);
824N/A}
824N/A
824N/Avoid DSWAbortPendingDrawing(Widget w)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.abort_pending_drawing) (w);
824N/A}
824N/A
824N/Astatic void UpdateDrawing(
824N/A Widget w,
824N/A float *rects,
824N/A int count)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
824N/A int i;
824N/A float *r;
824N/A int llx, lly, urx, ury;
824N/A int dx, dy;
824N/A
824N/A if (dsw->sw.backing_pixmap == None) {
824N/A AddToDirtyArea(w, rects, count);
824N/A return;
824N/A }
824N/A
824N/A ComputeOffsets(dsw, &dx, &dy);
824N/A
824N/A for (i = 0; i < count; i++) {
824N/A r = rects + (i * 4);
824N/A ConvertToX(dsw, LEFT(r), BOTTOM(r), &llx, &lly);
824N/A ConvertToX(dsw, RIGHT(r), TOP(r), &urx, &ury);
824N/A XCopyArea(XtDisplay(dsw), XtWindow(dsw->sw.drawing_area),
824N/A dsw->sw.backing_pixmap, dsw->sw.no_ge_gc,
824N/A llx-1, ury-1, urx-llx+2, lly-ury+2, llx+dx-1, ury+dy-1);
824N/A }
824N/A}
824N/A
824N/Avoid DSWUpdateDrawing(
824N/A Widget w,
824N/A float *rects,
824N/A int count)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.update_drawing) (w, rects, count);
824N/A}
824N/A
824N/Astatic void GetScrollInfo(
824N/A Widget w,
824N/A int *h_value, int *h_size, int *h_max, int *v_value, int *v_size, int *v_max)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
824N/A
824N/A if (h_value != NULL) *h_value = dsw->sw.scroll_h_value;
824N/A if (h_size != NULL) *h_size = dsw->sw.scroll_h_size;
824N/A if (h_max != NULL) *h_max = dsw->sw.scroll_h_max;
824N/A if (v_value != NULL) *v_value = dsw->sw.scroll_v_value;
824N/A if (v_size != NULL) *v_size = dsw->sw.scroll_v_size;
824N/A if (v_max != NULL) *v_max = dsw->sw.scroll_v_max;
824N/A}
824N/A
824N/Avoid DSWGetScrollInfo(
824N/A Widget w,
824N/A int *h_value, int *h_size, int *h_max, int *v_value, int *v_size, int *v_max)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.get_scroll_info) (w, h_value, h_size, h_max,
824N/A v_value, v_size, v_max);
824N/A}
824N/A
824N/Astatic void GetDrawingInfo(
824N/A Widget w,
824N/A DSWDrawableType *type,
824N/A Drawable *drawable,
824N/A DPSGState *gstate,
824N/A DPSContext *context)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
824N/A
824N/A if (dsw->sw.backing_pixmap != None) {
824N/A *type = DSWBackingPixmap;
824N/A *drawable = dsw->sw.backing_pixmap;
824N/A *gstate = dsw->sw.backing_gstate;
824N/A } else {
824N/A *type = DSWWindow;
824N/A *drawable = XtWindow(dsw->sw.drawing_area);
824N/A *gstate = dsw->sw.window_gstate;
824N/A }
824N/A *context = dsw->sw.context;
824N/A}
824N/A
824N/Avoid DSWGetDrawingInfo(
824N/A Widget w,
824N/A DSWDrawableType *type,
824N/A Drawable *drawable,
824N/A DPSGState *gstate,
824N/A DPSContext *context)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.get_drawing_info) (w, type, drawable, gstate, context);
824N/A}
824N/A
824N/Astatic Boolean GiveFeedbackPixmap(
824N/A Widget w,
824N/A Pixmap p,
824N/A int width, int height, int depth,
824N/A Screen *screen)
824N/A{
824N/A DPSScrolledWindowWidget dsw = (DPSScrolledWindowWidget) w;
824N/A
824N/A if ((unsigned) depth != dsw->sw.drawing_area->core.depth
824N/A || screen != dsw->core.screen
824N/A || dsw->sw.feedback_pixmap != None) return False;
824N/A
824N/A dsw->sw.feedback_pixmap = p;
824N/A dsw->sw.feedback_width = width;
824N/A dsw->sw.feedback_height = height;
824N/A
824N/A return True;
824N/A}
824N/A
824N/ABoolean DSWGiveFeedbackPixmap(
824N/A Widget w,
824N/A Pixmap p,
824N/A int width, int height, int depth,
824N/A Screen *screen)
824N/A{
824N/A XtCheckSubclass(w, dpsScrolledWindowWidgetClass, NULL);
824N/A
824N/A return (*((DPSScrolledWindowWidgetClass) XtClass(w))->
824N/A sw_class.give_feedback_pixmap) (w, p, width, height,
824N/A depth, screen);
824N/A}
824N/A
824N/Astatic void ConvertToX(
824N/A DPSScrolledWindowWidget dsw,
824N/A float psX,
824N/A float psY,
824N/A int *xX,
824N/A int *xY)
824N/A{
824N/A *xX = dsw->sw.ctm[0] * psX + dsw->sw.ctm[2] * psY + dsw->sw.ctm[4] +
824N/A dsw->sw.x_offset + 0.5;
824N/A *xY = dsw->sw.ctm[1] * psX + dsw->sw.ctm[3] * psY + dsw->sw.ctm[5] +
824N/A dsw->sw.y_offset + 0.5;
824N/A}
824N/A
824N/Astatic void ConvertToPS(
824N/A DPSScrolledWindowWidget dsw,
824N/A float xX, float xY,
824N/A float *psX, float *psY)
824N/A{
824N/A xX -= dsw->sw.x_offset;
824N/A xY -= dsw->sw.y_offset;
824N/A
824N/A *psX = dsw->sw.inv_ctm[0] * xX + dsw->sw.inv_ctm[2] * xY +
824N/A dsw->sw.inv_ctm[4];
824N/A *psY = dsw->sw.inv_ctm[1] * xX + dsw->sw.inv_ctm[3] * xY +
824N/A dsw->sw.inv_ctm[5];
824N/A}
824N/A
824N/Astatic void ConvertToOrigPS(
824N/A DPSScrolledWindowWidget dsw,
824N/A int xX, int xY,
824N/A float *psX, float *psY)
824N/A{
824N/A xX -= dsw->sw.x_offset;
824N/A xY -= dsw->sw.y_offset;
824N/A
824N/A *psX = dsw->sw.orig_inv_ctm[0] * xX + dsw->sw.orig_inv_ctm[2] * xY +
824N/A dsw->sw.orig_inv_ctm[4];
824N/A *psY = dsw->sw.orig_inv_ctm[1] * xX + dsw->sw.orig_inv_ctm[3] * xY +
824N/A dsw->sw.orig_inv_ctm[5];
824N/A}