|
|
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);
}