|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T V
Length: 21592 (0x5458) Types: TextFile Names: »VPane.c«
└─⟦3d0c2be1b⟧ Bits:30001254 ISODE-5.0 Tape └─⟦eba4602b1⟧ »./isode-5.0.tar.Z« └─⟦d3ac74d73⟧ └─⟦this⟧ »isode-5.0/others/max/VPane.c« └─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0 └─⟦35176feda⟧ »EurOpenD22/isode/isode-6.tar.Z« └─⟦de7628f85⟧ └─⟦this⟧ »isode-6.0/others/max/VPane.c«
#ifndef lint static char *sccsid = "@(#)VPane.c 1.36 6/1/87"; #endif lint /* * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. * * All Rights Reserved * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation, and that the name of Digital Equipment * Corporation not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ /* VPane.c */ #include <X/Xlib.h> #include "Intrinsic.h" #include "VPane.h" #include "Atoms.h" /* Private definitions. */ #define BORDERWIDTH 1 /* Size of borders between panes. */ #define DEFAULTKNOBWIDTH 9 #define DEFAULTKNOBHEIGHT 9 #define DEFAULTKNOBINDENT 16 typedef struct { Window w; /* Subwindow */ int y; /* Location in master window */ int dy; /* Desired location. */ int olddy; /* The last value of dy. */ int min, max; /* Minimum and maximum height. */ short autochange; /* Whether we're allowed to change this */ /* subwindow's height without an */ /* explicite command from user. */ int height; /* Current height. */ int dheight; /* Desired height. */ Window knob; /* The knob for this subwindow. */ Boolean allowresize; /* Whether we should honor geometry requests */ /* from this window to change its height. */ } SubWindowInfo, *SubWindowPtr; typedef struct { Window ourparent; /* Parent of the paned window. */ Window window; /* Window containing everything. */ int foregroundpixel; /* Foreground pixel. */ int backgroundpixel; /* Background pixel. */ int x, y; /* Location of master window. */ int width, height; /* Dimension of master window. */ int borderWidth; /* Borderwidth of master window. */ Pixmap borderpixmap; /* Color of border of master window. */ int knobwidth, knobheight; /* Dimension of knobs. */ int knobindent; /* Location of knobs (offset from */ /* right margin.) */ int knobpixel; /* Color of knobs. */ int heightused; /* Total height used by subwindows. */ int numsubwindows; /* How many windows within it. */ SubWindowInfo *sub; /* Array of info about the sub windows. */ int whichtracking; /* Which knob we are tracking, if any */ int starty; /* Starting y value. */ int whichdirection; /* Which direction to refigure things in. */ SubWindowPtr whichadd; /* Which subwindow to add changes to. */ SubWindowPtr whichsub; /* Which subwindow to sub changes from. */ Boolean refiguremode; /* Whether to refigure things right now. */ int autoraise; /* Whether we raise the window like xterm */ } PanedWindowInfo, *PanedWindowPtr; static PanedWindowInfo glob, globinit; static Resource resources[] = { {XtNwindow, XtCWindow, XtRWindow, sizeof(Window), (caddr_t)&glob.window, NULL}, {XtNforeground, XtCColor, XtRPixel, sizeof(int), (caddr_t)&glob.foregroundpixel, (caddr_t)&XtDefaultFGPixel}, {XtNbackground, XtCColor, XtRPixel, sizeof(int), (caddr_t)&glob.backgroundpixel, (caddr_t)&XtDefaultBGPixel}, {XtNx, XtCX, XtRInt, sizeof(int), (caddr_t)&glob.x, NULL}, {XtNy, XtCY, XtRInt, sizeof(int), (caddr_t)&glob.y, NULL}, {XtNwidth, XtCWidth, XtRInt, sizeof(int), (caddr_t)&glob.width, NULL}, {XtNheight, XtCHeight, XtRInt, sizeof(int), (caddr_t)&glob.height, NULL}, {XtNborderWidth, XtCBorderWidth, XtRInt, sizeof(int), (caddr_t)&glob.borderWidth, NULL}, {XtNborder, XtCColor, XtRPixmap, sizeof(Pixmap), (caddr_t)&glob.borderpixmap, (caddr_t)&XtDefaultFGPixmap}, {XtNknobWidth, XtCWidth, XtRInt, sizeof(int), (caddr_t)&glob.knobwidth, NULL}, {XtNknobHeight, XtCHeight, XtRInt, sizeof(int), (caddr_t)&glob.knobheight, NULL}, {XtNknobIndent, XtCKnobIndent, XtRInt, sizeof(int), (caddr_t)&glob.knobindent, NULL}, {XtNknobPixel, XtCKnobPixel, XtRPixel, sizeof(int), (caddr_t)&glob.knobpixel, NULL}, {XtNautoRaise, XtCAutoRaise, XtRBoolean, sizeof(int), (caddr_t)&glob.autoraise, NULL}, }; static XtContext vPaneContext; static char *CursorNums[3] ={ "sb_down_arrow", "sb_v_double_arrow", "sb_up_arrow" }; static PanedWindowPtr PanedWindowPtrFromWindow(w) Window w; { PanedWindowPtr ctx; if (XtFindContext(w, vPaneContext, (caddr_t *) &ctx)) return 0; return ctx; } static void TryResize(ctx, newwidth, newheight) PanedWindowPtr ctx; int newwidth, newheight; { WindowBox requestBox, replyBox; XtGeometryReturnCode result; requestBox.x = 0; requestBox.y = 0; if (newwidth < 1) newwidth = 1; if (newheight < 1) newheight = 1; requestBox.width = newwidth; requestBox.height = newheight; result = XtMakeGeometryRequest(ctx->window, geometryRESIZE, &requestBox, &replyBox); if (result == XtgeometryAlmost) { requestBox = replyBox; result = XtMakeGeometryRequest(ctx->window, geometryRESIZE, &requestBox, &replyBox); } if (result == XtgeometryYes) { ctx->width = replyBox.width; ctx->height = replyBox.height; } } static RefigureLocations(ctx, position, dir) PanedWindowPtr ctx; int position; int dir; /* -1 = up, 1 = down, 0 = this border only */ { SubWindowPtr sub, firstsub; int i, old, y, cdir; if (ctx->numsubwindows == 0 || !ctx->refiguremode) return; do { ctx->heightused = 0; for (i = 0, sub = ctx->sub; i < ctx->numsubwindows; i++, sub++) { if (sub->dheight < sub->min) sub->dheight = sub->min; if (sub->dheight > sub->max) sub->dheight = sub->max; ctx->heightused += sub->dheight; } ctx->heightused += BORDERWIDTH * (ctx->numsubwindows - 1); if (dir == 0 && ctx->heightused != ctx->height) { for (i = 0, sub = ctx->sub; i < ctx->numsubwindows; i++, sub++) if (sub->dheight != sub->height) sub->dheight += ctx->height - ctx->heightused; } } while (dir == 0 && ctx->heightused != ctx->height); firstsub = ctx->sub + position; sub = firstsub; cdir = dir; while (ctx->heightused != ctx->height) { if (sub->autochange || cdir != dir) { old = sub->dheight; sub->dheight = ctx->height - ctx->heightused + old; if (sub->dheight < sub->min) sub->dheight = sub->min; if (sub->dheight > sub->max) sub->dheight = sub->max; ctx->heightused += (sub->dheight - old); } sub += cdir; while (sub < ctx->sub || sub - ctx->sub == ctx->numsubwindows) { cdir = -cdir; if (cdir == dir) goto doublebreak; sub = firstsub + cdir; } } doublebreak: y = -BORDERWIDTH; for (i = 0, sub = ctx->sub; i < ctx->numsubwindows; i++, sub++) { sub->dy = y; y += sub->dheight + BORDERWIDTH; } } static CommitNewLocations(ctx) PanedWindowPtr ctx; { int i, kx, ky; SubWindowPtr sub; if (ctx->heightused != ctx->height) TryResize(ctx, ctx->width, ctx->height); for (i = 0, sub = ctx->sub; i < ctx->numsubwindows; i++, sub++) { if (sub->dy != sub->y || sub->dheight != sub->height) { WindowBox box; XConfigureWindow(sub->w, box.x = -BORDERWIDTH, box.y = sub->dy, box.width = ctx->width, box.height = sub->dheight); sub->y = sub->dy; sub->height = sub->dheight; } } kx = ctx->width - ctx->knobindent; for (i = 0, sub = ctx->sub; i < ctx->numsubwindows; i++, sub++) { ky = sub->y + sub->height - (ctx->knobheight / 2) + 1; if (i == ctx->numsubwindows - 1) ky = -99; XMoveWindow(sub->knob, kx, ky); } } static RefigureLocationsAndCommit(ctx, position, dir) PanedWindowPtr ctx; int position, dir; { RefigureLocations(ctx, position, dir); CommitNewLocations(ctx); } EraseInternalBorders(ctx) PanedWindowPtr ctx; { int i; for (i = 1; i < ctx->numsubwindows; i++) XLine(ctx->window, 0, ctx->sub[i].y, ctx->width, ctx->sub[i].y, 1, 1, ctx->backgroundpixel, GXcopy, AllPlanes); } DrawInternalBorders(ctx) PanedWindowPtr ctx; { int i; for (i = 1; i < ctx->numsubwindows; i++) XLine(ctx->window, 0, ctx->sub[i].y, ctx->width, ctx->sub[i].y, 1, 1, ctx->foregroundpixel, GXcopy, AllPlanes); } static DrawTrackLines(ctx) PanedWindowPtr ctx; { int i; SubWindowPtr sub; for (i = 1, sub = ctx->sub + 1; i < ctx->numsubwindows; i++, sub++) { if (sub->olddy != sub->dy) { XLine(ctx->window, 0, sub->olddy, ctx->width, sub->olddy, 1, 1, 1, GXinvert, 1); XLine(ctx->window, 0, sub->dy, ctx->width, sub->dy, 1, 1, 1, GXinvert, 1); sub->olddy = sub->dy; } } } static EraseTrackLines(ctx) PanedWindowPtr ctx; { int i; for (i = 1; i < ctx->numsubwindows; i++) XLine(ctx->window, 0, ctx->sub[i].olddy, ctx->width, ctx->sub[i].olddy, 1, 1, 1, GXinvert, 1); } /* Semi-public routines. */ static XtGeometryReturnCode PanedWindowGeometryRequest( w, request, reqBox, replBox) Window w; int request; WindowBox *reqBox, *replBox; { PanedWindowPtr ctx; int i; SubWindowPtr sub; ctx = PanedWindowPtrFromWindow(w); if (!ctx) return XtgeometryNo; for (i=0 ; i<ctx->numsubwindows ; i++) if (ctx->sub[i].w == w) break; if (i >= ctx->numsubwindows) return XtgeometryNo; sub = ctx->sub + i; if (request == geometryRESIZE) { if (!sub->allowresize) return XtgeometryNo; if (ctx->width != reqBox->width) { if (sub->height == reqBox->height) return XtgeometryNo; *replBox = *reqBox; replBox->width = ctx->width; return XtgeometryAlmost; } if (sub->min == sub->height || sub->min > reqBox->height) sub->min = reqBox->height; if (sub->max == sub->height || sub->max < reqBox->height) sub->max = reqBox->height; sub->dheight = reqBox->height; RefigureLocationsAndCommit(ctx, i, 1); return XtgeometryYes; } if (request == geometryGETWINDOWBOX) { replBox->x = -BORDERWIDTH; replBox->y = sub->y; replBox->width = ctx->width; replBox->height = sub->height; replBox->borderWidth = BORDERWIDTH; return XtgeometryYes; } return XtgeometryNo; } static XtEventReturnCode HandleEvents(event) XExposeWindowEvent *event; { PanedWindowPtr ctx; int i; ctx = PanedWindowPtrFromWindow(event->window); if (!ctx) return XteventNotHandled; switch (event->type) { case ResizeWindow: if (ctx->width != event->width || ctx->height != event->height) { if (ctx->width != event->width) { for (i = 0; i < ctx->numsubwindows; i++) { XChangeWindow(ctx->sub[i].w, event->width, ctx->sub[i].height); } } ctx->width = event->width; ctx->height = event->height; RefigureLocationsAndCommit(ctx, ctx->numsubwindows - 1, -1); } return XteventHandled; case EnterWindow: if (ctx -> autoraise) XRaiseWindow (ctx -> window); return XteventHandled; case DestroyWindow: ctx->refiguremode = FALSE; for (i = ctx->numsubwindows-1 ; i >= 0 ; i--) (void) XtSendDestroyNotify(ctx->sub[i].w); (void) XtDeleteContext(ctx->window, vPaneContext); XtClearEventHandlers(ctx->window); XtFree((char *)ctx->sub); XtFree((char *)ctx); return XteventHandled; } return XteventNotHandled; } static XtEventReturnCode HandleSubwindow(event) XEvent *event; { PanedWindowPtr ctx; if (event->type == DestroyWindow) { ctx = PanedWindowPtrFromWindow(event->window); if (ctx) { XtVPanedWindowDeletePane(ctx->window, event->window); return XteventHandled; } } return XteventNotHandled; } static XtEventReturnCode HandleKnob(event) XButtonEvent *event; { PanedWindowPtr ctx; int position, diff, y, i; ctx = PanedWindowPtrFromWindow(event->window); if (!ctx) return XteventNotHandled; switch (event->type) { case ButtonPressed: y = event->y; if (ctx->whichtracking != -1) return XteventNotHandled; for (position = 0; position < ctx->numsubwindows; position++) if (ctx->sub[position].knob == event->window) break; if (position >= ctx->numsubwindows) return XteventNotHandled; XtGrabMouse(event->window, XtGetCursor(CursorNums[event->detail & 0xff]), MouseMoved | ButtonReleased); ctx->whichadd = ctx->whichsub = NULL; ctx->whichdirection = (event->detail & 0xff) - 1; ctx->starty = y; if (ctx->whichdirection >= 0) { ctx->whichadd = ctx->sub + position; while (ctx->whichadd->max == ctx->whichadd->min && ctx->whichadd > ctx->sub) (ctx->whichadd)--; } if (ctx->whichdirection <= 0) { ctx->whichsub = ctx->sub + position + 1; while (ctx->whichsub->max == ctx->whichsub->min && ctx->whichsub < ctx->sub + ctx->numsubwindows - 1) (ctx->whichsub)++; } ctx->whichtracking = position; if (ctx->whichdirection == 1) (ctx->whichtracking)++; XClipDrawThrough(ctx->window); EraseInternalBorders(ctx); for (i = 0; i < ctx->numsubwindows; i++) ctx->sub[i].olddy = -99; /* Fall through */ case MouseMoved: case ButtonReleased: y = event->y; if (ctx->whichtracking == -1) return XteventNotHandled; for (i = 0; i < ctx->numsubwindows; i++) ctx->sub[i].dheight = ctx->sub[i].height; diff = y - ctx->starty; if (ctx->whichadd) ctx->whichadd->dheight = ctx->whichadd->height + diff; if (ctx->whichsub) ctx->whichsub->dheight = ctx->whichsub->height - diff; RefigureLocations(ctx, ctx->whichtracking, ctx->whichdirection); if (event->type != ButtonReleased) { DrawTrackLines(ctx);/* Draw new borders */ return XteventHandled; } XtUngrabMouse(); EraseTrackLines(ctx); CommitNewLocations(ctx); DrawInternalBorders(ctx); XClipClipped(ctx->window); ctx->whichtracking = -1; return XteventHandled; } return XteventNotHandled; } /* Public routines. */ static Boolean initialized = FALSE; extern void VPanedInitialize() { if (initialized) return; initialized = TRUE; vPaneContext = XtUniqueContext(); globinit.window = NULL; globinit.x = globinit.y = 0; globinit.width = globinit.height = globinit.borderWidth = 1; globinit.knobwidth = DEFAULTKNOBWIDTH; globinit.knobheight = DEFAULTKNOBHEIGHT; globinit.knobindent = DEFAULTKNOBINDENT; globinit.knobpixel = -1; } Window XtVPanedWindowCreate(parent, args, argCount) Window parent; ArgList args; int argCount; { PanedWindowPtr ctx; XtNameList names; XtClassList classes; WindowInfo info; if (!initialized) VPanedInitialize(); ctx = (PanedWindowPtr) XtMalloc(sizeof(PanedWindowInfo)); glob = globinit; XtGetResources(resources, XtNumber(resources), args, argCount, parent, "vpane", "VPane", &names, &classes); *ctx = glob; if (ctx->window != NULL) { XQueryWindow(ctx->window, &info); ctx->x = info.x; ctx->y = info.y; ctx->width = info.width; ctx->height = info.height; ctx->borderWidth = info.bdrwidth; } else { ctx->window = XCreateWindow(parent, ctx->x, ctx->y, ctx->width, ctx->height, ctx->borderWidth, ctx->borderpixmap, XMakeTile(ctx->backgroundpixel) ); } XtSetNameAndClass(ctx->window, names, classes); XtFreeNameList(names); XtFreeClassList(classes); if (ctx->knobpixel < 0) ctx->knobpixel = ctx->foregroundpixel; ctx->heightused = 0; ctx->numsubwindows = 0; ctx->sub = (SubWindowInfo *) XtMalloc(1); ctx->whichtracking = -1; ctx->refiguremode = TRUE; (void) XtSaveContext(ctx->window, vPaneContext, (caddr_t) ctx); (void) XtSetEventHandler(ctx->window, HandleEvents, ExposeWindow | EnterWindow, (caddr_t) NULL); return ctx->window; } void XtVPanedWindowDelete(w) Window w; { PanedWindowPtr ctx; int i; ctx = PanedWindowPtrFromWindow(w); if (!ctx) return; XUnmapWindow(w); for (i=ctx->numsubwindows-1 ; i>=0 ; i--) XtVPanedWindowDeletePane(w, ctx->sub[i].w); (void) XtDeleteContext(w, vPaneContext); XtFree((char *) ctx->sub); XtFree((char *) ctx); } void XtVPanedWindowAddPane(parent, paneWindow, position, min, max, autochange) Window parent, paneWindow; int position, min, max, autochange; { PanedWindowPtr ctx; int i, needed; SubWindowPtr sub; WindowInfo info; ctx = PanedWindowPtrFromWindow(parent); if (!ctx) return; ctx->numsubwindows++; ctx->sub = (SubWindowPtr) XtRealloc((char *) ctx->sub, (unsigned) ctx->numsubwindows * sizeof(SubWindowInfo)); for (i = ctx->numsubwindows - 1; i > position; i--) ctx->sub[i] = ctx->sub[i - 1]; XQueryWindow(paneWindow, &info); sub = &(ctx->sub[position]); sub->w = paneWindow; sub->y = info.y; sub->height = sub->dheight = info.height; if (info.width != ctx->width || info.x != -BORDERWIDTH) { XConfigureWindow(paneWindow, -BORDERWIDTH, info.y, ctx->width, info.height); } sub->min = min; sub->max = max; sub->autochange = autochange; needed = sub->height + BORDERWIDTH + ctx->heightused; if (needed > ctx->height) TryResize(ctx, ctx->width, needed); (void) XtSetGeometryHandler(paneWindow, PanedWindowGeometryRequest); sub->knob = XCreateWindow(ctx->window, -99, -99, ctx->knobwidth, ctx->knobheight, 0, XMakeTile(0), XMakeTile(ctx->knobpixel) ); (void) XtSaveContext(sub->w, vPaneContext, (caddr_t) ctx); (void) XtSaveContext(sub->knob, vPaneContext, (caddr_t) ctx); XDefineCursor(sub->knob, XtGetCursor("sb_v_double_arrow")); XMapWindow(sub->w); XMapWindow(sub->knob); (void) XtSetEventHandler(sub->w, HandleSubwindow, ExposeWindow, (caddr_t) NULL); (void) XtSetEventHandler(sub->knob, HandleKnob, ButtonPressed | ButtonReleased | RightDownMotion | MiddleDownMotion | LeftDownMotion, (caddr_t) NULL); RefigureLocationsAndCommit(ctx, position, 1); for (i=0 ; i<ctx->numsubwindows; i++) XRaiseWindow(ctx->sub[i].knob); } /* Change the min and max size of the given sub window. */ void XtVPanedSetMinMax(w, paneWindow, min, max) Window w, paneWindow; int min, max; { PanedWindowPtr ctx; int i; ctx = PanedWindowPtrFromWindow(w); if (!ctx) return; for (i = 0; i < ctx->numsubwindows; i++) { if (ctx->sub[i].w == paneWindow) { ctx->sub[i].min = min; ctx->sub[i].max = max; RefigureLocationsAndCommit(ctx, i, 1); return; } } } /* Delete the given paneWindow from the given paned window. Doesn't actually destroy the paneWindow. */ void XtVPanedWindowDeletePane(w, paneWindow) Window w, paneWindow; { PanedWindowPtr ctx; int i; Boolean j; ctx = PanedWindowPtrFromWindow(w); if (!ctx) return; j = FALSE; for (i = 0; i < ctx->numsubwindows; i++) { if (ctx->sub[i].w == paneWindow) { j = TRUE; (void) XtDeleteContext(ctx->sub[i].w, vPaneContext); (void) XtDeleteContext(ctx->sub[i].knob, vPaneContext); (void) XtSetEventHandler(ctx->sub[i].w, HandleSubwindow, (unsigned long) NULL, (caddr_t) NULL); XtClearEventHandlers(ctx->sub[i].knob); XDestroyWindow(ctx->sub[i].knob); (void) XtSendDestroyNotify(ctx->sub[i].knob); TryResize(ctx, ctx->width, ctx->height - ctx->sub[i].height - BORDERWIDTH); } if (j && i < ctx->numsubwindows - 1) ctx->sub[i] = ctx->sub[i + 1]; } if (!j) return; ctx->numsubwindows--; if (ctx->numsubwindows > 0) { ctx->sub = (SubWindowPtr) XtRealloc((char *) ctx->sub, (unsigned) ctx->numsubwindows * sizeof(SubWindowInfo)); } RefigureLocationsAndCommit(ctx, ctx->numsubwindows - 1, -1); } void XtVPanedAllowResize(window, paneWindow, allowresize) Window window, paneWindow; Boolean allowresize; { PanedWindowPtr ctx; int i; ctx = PanedWindowPtrFromWindow(window); if (ctx) for (i=0 ; i<ctx->numsubwindows ; i++) if (ctx->sub[i].w == paneWindow) ctx->sub[i].allowresize = allowresize; } void XtVPanedRefigureMode(window, mode) Window window; Boolean mode; { PanedWindowPtr ctx; ctx = PanedWindowPtrFromWindow(window); if (ctx) { ctx->refiguremode = mode; if (mode) RefigureLocationsAndCommit(ctx, ctx->numsubwindows - 1, -1); } } void XtVPanedGetValues(w, args, argCount) Window w; ArgList args; int argCount; { PanedWindowPtr ctx; ctx = PanedWindowPtrFromWindow(w); glob = *ctx; XtGetValues(resources, XtNumber(resources), args, argCount); } void XtVPanedSetValues(w, args, argCount) Window w; ArgList args; int argCount; { PanedWindowPtr ctx; ctx = PanedWindowPtrFromWindow(w); glob = *ctx; XtSetValues(resources, XtNumber(resources), args, argCount); *ctx = glob; }