|
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: 18658 (0x48e2) Types: TextFile Names: »VPane.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─⟦526ad3590⟧ »EUUGD11/gnu-31mar87/X.V10.R4.tar.Z« └─⟦2109abc41⟧ └─⟦this⟧ »./X.V10R4/Toolkit/DECToolkit/src/VPane.c«
/* * $Source: /u1/X/DECToolkit/src/RCS/VPane.c,v $ * $Header: VPane.c,v 1.1 86/12/17 09:03:33 swick Exp $ */ #ifndef lint static char *rcsid_VPane_c = "$Header: VPane.c,v 1.1 86/12/17 09:03:33 swick Exp $"; #endif lint #ifndef lint static char *sccsid = "@(#)VPane.c 1.4 12/11/86"; #endif lint /* * COPYRIGHT 1986 * DIGITAL EQUIPMENT CORPORATION * MAYNARD, MASSACHUSETTS * ALL RIGHTS RESERVED. * * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR * ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. * * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS, * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT * SET FORTH ABOVE. * * * 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. */ /* Basic code outline by Smokey Wallace Modification by Harry Hersh */ #include <stdio.h> #include <X/Xlib.h> #include <X/cursors/double_arrow.cursor> #include <X/cursors/double_arrow_mask.cursor> #include "Toolkit.h" /* Paned window are a major organizing device for application programs. * The consist of an overall frame, within which tiled subwindows can be * added, removed, and varied in height, both by the user and by the program. * The subwindows extend the full width of the window frame. The subwindows * within a paned window frame are completely general: they are typically * used as variable windows for text or graphics editing and for other * applications where a user would want direct control over the relative * size of windows. */ /* Private definitions. */ /* -----> Defines */ #define BORDERWIDTH 1 #define KNOBWIDTH 9 #define KNOBHEIGHT 9 typedef struct { Window w; /* Subwindow */ int y; /* Location in master window */ int min, max; /* Minimum and maximum height. */ short autochange; /* Whether we're allowed this subwindow's height without an explicite command from the user. */ int height; /* Current height. */ int dheight; /* Desired height. */ Window knob; /* The knob for this subwindow. */ } PanelInfo, *PanelPtr; typedef struct { Window window; /* Window containing everything. */ int width, height; /* Dimension of master window. */ int heightused; /* Total height used by subwindows. */ int numpanels; /* How many windows within it. */ PanelInfo *sub; /* Array of info about the sub windows. */ int whichtracking; /* Which knob we are tracking, if any */ int tracklocation; /* The current track line. */ int refiguremode; /* Whether to refigure things right now. */ } WindowFrameInfo, *WindowFramePtr; /* -----> Static Variables */ static int initialized = FALSE; static int WindowFrameEntry; static Initialize() { WindowFrameEntry = UniqueEntryType(); initialized = TRUE; } /* -----> Utilities */ static WindowFramePtr WindowFramePtrFromWindow(w) Window w; { WindowFramePtr ctx; if (FindEntry(w, WindowFrameEntry, &ctx) != ERRNONE) return FALSE; return ctx; } static TryResize(ctx, newwidth, newheight) WindowFramePtr ctx; int newwidth, newheight; { WindowBox requestBox, replyBox; int result; requestBox.x = 0; requestBox.y = 0; if (newwidth < 1) newwidth = 1; if (newheight < 1) newheight = 1; requestBox.w = newwidth; requestBox.h = newheight; result = TMakeGeometryRequest(ctx->window, resize, &requestBox, &replyBox); if (result == REQUESTALMOST) { requestBox = replyBox; result = TMakeGeometryRequest(ctx->window, resize, &requestBox, &replyBox); } if (result == REQUESTYES) { ctx->width = replyBox.w; ctx->height = replyBox.h; return TRUE; } return FALSE; } static RefigureVLocations(ctx, position) WindowFramePtr ctx; int position; { PanelPtr sub; int i, old, y, kx, ky; if (ctx->numpanels == 0 || !ctx->refiguremode) return; ctx->heightused = 0; for (i = 0, sub = ctx->sub; i < ctx->numpanels; 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->numpanels - 1); sub = &(ctx->sub[position]); while (ctx->heightused != ctx->height) { if (sub->autochange) { 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++; if (sub - ctx->sub == ctx->numpanels) sub = ctx->sub; if (sub - ctx->sub == position) break; } if (ctx->heightused != ctx->height) TryResize(ctx, ctx->width, ctx->height); y = -BORDERWIDTH; for (i = 0, sub = ctx->sub; i < ctx->numpanels; i++, sub++) { if (y != sub->y || sub->dheight != sub->height) { if (sub->dheight == sub->height) XMoveWindow(sub->w, -BORDERWIDTH, y); else XConfigureWindow(sub->w, -BORDERWIDTH, y, ctx->width, sub->dheight); sub->y = y; sub->height = sub->dheight; } y += sub->dheight + BORDERWIDTH; } kx = ctx->width - KNOBWIDTH; for (i = 0, sub = ctx->sub; i < ctx->numpanels; i++, sub++) { ky = sub->y + sub->height - (KNOBHEIGHT / 2); if (i == ctx->numpanels - 1) ky = -99; XMoveWindow(sub->knob, kx, ky); } } static DrawVTrackLine(ctx) WindowFramePtr ctx; { XLine(ctx->window, 0, ctx->tracklocation, ctx->width, ctx->tracklocation, 1, 1, ~0, GXinvert, AllPlanes); } /* =================================================================== */ /* Semi-public Procedures. */ static WindowFrameGeometryRequest() { return REQUESTNO; } static HandleExposeWindow(event) XExposeWindowEvent *event; { WindowFramePtr ctx; int i; if (event->type == ResizeWindow && event->subwindow == 0) { ctx = WindowFramePtrFromWindow(event->window); if (!ctx) return ERRNOTFOUND; if (ctx->width != event->width || ctx->height != event->height) { if (ctx->width != event->width) { for (i = 0; i < ctx->numpanels; i++) { XChangeWindow(ctx->sub[i].w, event->width, ctx->sub[i].height); } } ctx->width = event->width; ctx->height = event->height; for (i = ctx->numpanels - 1; i > 0 && !(ctx->sub[i].autochange); i--); RefigureVLocations(ctx, i); } return PROCESSED; } return NOTHANDLED; } static HandleKnob(event) XButtonEvent *event; { WindowFramePtr ctx; int position, diff, x, y; Window subw; ctx = WindowFramePtrFromWindow(event->window); if (!ctx) return ERRNOTFOUND; for (position = 0; position < ctx->numpanels; position++) if (ctx->sub[position].knob == event->window) break; if (position >= ctx->numpanels) return NOTHANDLED; XInterpretLocator(ctx->window, &x, &y, &subw, event->location); switch (event->type) { case ButtonPressed: if (ctx->whichtracking != -1) return NOTHANDLED; ctx->whichtracking = position; ctx->tracklocation = -99; XClipDrawThrough(ctx->window); /* Fall through */ case MouseMoved: case ButtonReleased: if (ctx->whichtracking == -1) return NOTHANDLED; DrawVTrackLine(ctx); /* Erase old line */ ctx->tracklocation = y; if (event->type != ButtonReleased) { DrawVTrackLine(ctx);/* Draw new line */ return PROCESSED; } position = ctx->whichtracking; diff = ctx->tracklocation - (ctx->sub[position].y + ctx->sub[position].height); ctx->sub[position].dheight += diff; if (position == ctx->numpanels - 2) ctx->sub[position + 1].dheight -= diff; XClipClipped(ctx->window); RefigureVLocations(ctx, position + 1); ctx->whichtracking = -1; return PROCESSED; } return NOTHANDLED; } /* =================================================================== */ /* Public Procedures. */ /* * This procedure makes a paned window frame from an existing window * for one or more vertically arranged tiled windows. */ Status TMakeVWindowFrame(w) Window w; { WindowFramePtr ctx; WindowInfo info; /* -----> Perform initialization */ if (!initialized) Initialize(); /* -----> Set up data frame data structure */ ctx = (WindowFramePtr) Tmalloc(sizeof(WindowFrameInfo)); SaveEntry(w, WindowFrameEntry, ctx); XQueryWindow(w, &info); ctx->window = w; ctx->width = info.width; ctx->height = info.height; ctx->heightused = 0; ctx->numpanels = 0; ctx->sub = (PanelInfo *) Tmalloc(1); ctx->whichtracking = -1; ctx->refiguremode = TRUE; TSetXEventDispatch(w, HandleExposeWindow, ExposeWindow, 0); } /* ================================================================= */ /* * Deletes the paned window Frame, including the OpaqueFrame * structure associated with it. */ Status TDeleteVWindowFrame(w) Window w; { WindowFramePtr ctx; int i; ctx = WindowFramePtrFromWindow(w); if(!ctx) return ERRNOTFOUND; XUnmapWindow(w); for (i=ctx->numpanels-1 ; i>=0 ; i--) TDeleteFromVWindowFrame(w, ctx->sub[i].w); DeleteEntry(w, WindowFrameEntry); free(ctx->numpanels); free(ctx); } /* ================================================================= */ /* * Adds a sub-window to the paned window in a particular location by * readjusting the height of any permitted sub-windows within their * specified bounds. */ Window TAddToVWindowFrame(w, arglist) Window w; /* Window frame */ Targ * arglist; { WindowFramePtr ctx; Window pw; int i, needed, position; int status; PanelPtr sub; Pixmap border, bkground; int y; int min, max; short autochange; int height; int dheight; ctx = WindowFramePtrFromWindow(w); if(!ctx) return ERRNOTFOUND; ctx->numpanels++; ctx->sub = (PanelPtr) Trealloc(ctx->sub, ctx->numpanels * sizeof(PanelInfo)); /* -----> Set Defaults */ pw = NULL; position = ctx -> numpanels - 1; border = BlackPixmap; bkground = WhitePixmap; y = ctx -> height; height = ctx -> height / ctx -> numpanels; min = KNOBHEIGHT + 1; max = ctx -> height; autochange = TRUE; /* -----> Parse Arguments */ while (arglist -> name) { switch (arglist -> name) { case T_PANED_WINDOW: pw = (Window) arglist ->data; break; case T_PANED_ORIENT: break; case T_PANED_POSITION: position = (int) arglist -> data; break; case T_PANED_HEIGHT: height = (int) arglist -> data; break; case T_PANED_WIDTH: break; case T_PANED_MIN: min = (int) arglist -> data; break; case T_PANED_MAX: max = (int) arglist -> data; break; case T_PANED_AUTOCHANGE: autochange = (short) arglist -> data; break; case T_PANED_BRCOLOR: border = (int) arglist -> data; break; case T_PANED_BACKGROUND: bkground = (int) arglist -> data; break; default: break; } arglist++; } for (i = ctx->numpanels - 1; i > position; i--) ctx->sub[i] = ctx->sub[i - 1]; sub = &(ctx->sub[position]); sub->w = pw; sub->y = y; sub->height = sub->dheight = height; sub->autochange = autochange; sub->min = min; sub->max = max; /* -----> Create Window Pane */ if (pw == NULL) sub->w = XCreateWindow (w, -BORDERWIDTH, sub->y, ctx->width, sub->height, BORDERWIDTH, border, bkground); else XConfigureWindow (sub->w, -BORDERWIDTH, sub->y, ctx->width, sub->height); needed = sub->height + BORDERWIDTH + ctx->heightused; if (needed > ctx->height) TryResize(ctx, ctx->width, needed); TSetGeometryRequest(sub->w, WindowFrameGeometryRequest); sub->knob = XCreateWindow(ctx->window, -99, -99, KNOBWIDTH, KNOBHEIGHT, 0, 0, BlackPixmap); SaveEntry(sub->knob, WindowFrameEntry, ctx); #ifdef CURSORS XDefineCursor(sub->knob, GetCursor("double_arrow")); #else XDefineCursor(sub->knob, XCreateCursor( double_arrow_width, double_arrow_height, double_arrow_bits, double_arrow_mask_bits, double_arrow_x_hot, double_arrow_y_hot, BlackPixel, WhitePixel, GXcopy)); #endif XMapWindow(sub->w); if (min != max) XMapWindow(sub->knob); TSetXEventDispatch(sub->knob, HandleKnob, knobMask, 0); RefigureVLocations(ctx, position); for (i=0 ; i<ctx->numpanels; i++) XRaiseWindow(ctx->sub[i].knob); return(sub->w); } /* ================================================================= */ /* * Removes a sub-window from the paned window and readjust any permitted * sub-windows within their specified bounds. */ Status TDeleteFromVWindowFrame(w, subwindow) Window w, subwindow; { WindowFramePtr ctx; int i, j, r; ctx = WindowFramePtrFromWindow(w); if (!ctx) return ERRNOTFOUND; j = FALSE; for (i = 0; i < ctx->numpanels; i++) { if (ctx->sub[i].w == subwindow) { j = TRUE; DeleteEntry(ctx->sub[i].knob, WindowFrameEntry); XDestroyWindow(ctx->sub[i].knob); r = TryResize(ctx, ctx->width, ctx->height - ctx->sub[i].height - BORDERWIDTH); } if (j && i < ctx->numpanels - 1) ctx->sub[i] = ctx->sub[i + 1]; } if (!j) return; ctx->numpanels--; if (ctx->numpanels > 0) { ctx->sub = (PanelPtr) Trealloc(ctx->sub, ctx->numpanels * sizeof(PanelInfo)); } for (i=ctx->numpanels - 1; i>0 ; i--) if (ctx->sub[i].autochange) break; RefigureVLocations(ctx, i); } /* =================================================================== */ /* * Enables or disables adjustments to pane boundaries. * */ TPanedVRefigureMode(window, mode) Window window; short mode; { WindowFramePtr ctx; int i; ctx = WindowFramePtrFromWindow(window); if (ctx) { ctx->refiguremode = mode; if (mode) { for (i = ctx->numpanels - 1; i > 0; i--) if (ctx->sub[i].autochange) break; RefigureVLocations(ctx, i); } } } /* =================================================================== */ /* * This procedure returns the currently set of arguments, and * other state information. If any errors are detected * during the parsing of the input arguments, an exit will occur. * */ Status TGetVPaneAttr (tw, arglist) Window tw; /* tool window (pane) */ Targ *arglist; { int return_code; /* return code from window creation */ int i; WindowFramePtr ctx; Window *parent, **children; int *nchildren; PanelPtr pane; /* -----> First find parent, then the frame, then the right pane */ return_code = XQueryTree(tw, parent, nchildren, children); if (!return_code) return ERRNOTFOUND; ctx = WindowFramePtrFromWindow(parent); if (!ctx) return ERRNOTFOUND; for (i = 0; i < ctx->numpanels; i++) if(ctx->sub[i].w == tw) pane = &(ctx->sub[i]); if (!pane) return ERRNOTFOUND; /* -----> Parsing input parameters */ while (arglist -> name) { switch (arglist -> name) { case T_PANED_ORIENT: arglist -> data = (caddr_t) VERTICAL; break; case T_PANED_POSITION: arglist -> data = (caddr_t) FALSE; break; case T_PANED_HEIGHT: arglist -> data = (caddr_t) pane -> height; break; case T_PANED_WIDTH: arglist -> data = (caddr_t) ctx -> width; break; case T_PANED_MIN: arglist -> data = (caddr_t) pane -> min; break; case T_PANED_MAX: arglist -> data = (caddr_t) pane -> max; break; case T_PANED_AUTOCHANGE: arglist -> data = (caddr_t) pane ->autochange; break; default: break; } arglist++; } } /* =================================================================== */ /* * This procedure sets or changes arguments for a paned window. * If any errors are detected during the parsing of the input arguments, * an exit will occur. */ Status TSetVPaneAttr (tw, arglist) Window tw; /* tool window */ Targ *arglist; { int return_code; /* return code from window creation */ int i; WindowFramePtr ctx; Window *parent, **children; int *nchildren; PanelPtr pane; /* -----> First find parent, then the frame, then the right pane */ return_code = XQueryTree(tw, parent, nchildren, children); if (!return_code) return ERRNOTFOUND; ctx = WindowFramePtrFromWindow(parent); if (!ctx) return ERRNOTFOUND; for (i = 0; i < ctx->numpanels; i++) if(ctx->sub[i].w == tw) pane = &(ctx->sub[i]); if (!pane) return ERRNOTFOUND; /* -----> Parsing input parameters */ while (arglist -> name) { switch (arglist -> name) { case T_PANED_ORIENT: arglist -> data = (caddr_t) FALSE; break; case T_PANED_POSITION: arglist -> data = (caddr_t) FALSE; break; case T_PANED_HEIGHT: arglist -> data = (caddr_t) pane -> height; break; case T_PANED_WIDTH: arglist -> data = (caddr_t) ctx -> width; break; case T_PANED_MIN: arglist -> data = (caddr_t) pane -> min; break; case T_PANED_MAX: arglist -> data = (caddr_t) pane -> max; break; case T_PANED_AUTOCHANGE: arglist -> data = (caddr_t) pane ->autochange; break; default: break; } arglist++; } RefigureVLocations(ctx, 1); }