DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ H T

⟦0dd16d23b⟧ TextFile

    Length: 18592 (0x48a0)
    Types: TextFile
    Names: »HPane.c«

Derivation

└─⟦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/HPane.c« 

TextFile

/*
 *	$Source: /u1/X/DECToolkit/src/RCS/HPane.c,v $
 *	$Header: HPane.c,v 1.1 86/12/17 09:01:58 swick Exp $
 */

#ifndef lint
static char *rcsid_HPane_c = "$Header: HPane.c,v 1.1 86/12/17 09:01:58 swick Exp $";
#endif	lint

#ifndef lint
static  char    *sccsid = "@(#)HPane.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 "Toolkit.h"
#include "horiz_arrow.cursor"
#include "horiz_arrow_mask.cursor"

/* Paned window are a major organizing device for application programs.
 * They consist of an overall frame, within which tiled subwindows can be
 * added, removed, and varied in width, both by the user and by the program.
 * The subwindows extend the full height 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 x;		/* Location in master window */
    int min, max;	/* Minimum and maximum width. */
    short autochange;	/* Whether we're allowed this subwindow's width
			   without an explicite command from the user. */
    int width;		/* Current width. */
    int dwidth;		/* Desired width. */
    Window knob;	/* The knob for this subwindow. */
} PanelInfo, *PanelPtr;

typedef struct {
    Window window;	/* Window containing everything. */
    int width, height;	/* Dimension of master window. */
    int widthused;	/* Total width 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 RefigureHLocations(ctx, position)
WindowFramePtr ctx;
int position;
{
    PanelPtr sub;
    int     i, old, x, kx, ky;
    if (ctx->numpanels == 0 || !ctx->refiguremode)
	return;
    ctx->widthused = 0;
    for (i = 0, sub = ctx->sub; i < ctx->numpanels; i++, sub++) {
	if (sub->dwidth < sub->min)
	    sub->dwidth = sub->min;
	if (sub->dwidth > sub->max)
	    sub->dwidth = sub->max;
	ctx->widthused += sub->dwidth;
    }
    ctx->widthused += BORDERWIDTH * (ctx->numpanels - 1);
    sub = &(ctx->sub[position]);
    while (ctx->widthused != ctx->width) {
	if (sub->autochange) {
	    old = sub->dwidth;
	    sub->dwidth = ctx->width - ctx->widthused + old;
	    if (sub->dwidth < sub->min)
		sub->dwidth = sub->min;
	    if (sub->dwidth > sub->max)
		sub->width = sub->max;
	    ctx->widthused += (sub->dwidth - old);
	}
	sub++;
	if (sub - ctx->sub == ctx->numpanels)
	    sub = ctx->sub;
	if (sub - ctx->sub == position)
	    break;
    }
    if (ctx->widthused != ctx->width)
	TryResize(ctx, ctx->width, ctx->height);
    x = -BORDERWIDTH;
    for (i = 0, sub = ctx->sub; i < ctx->numpanels; i++, sub++) {
	if (x != sub->x || sub->dwidth != sub->width) {
	    if (sub->dwidth == sub->width)
		XMoveWindow(sub->w, x, -BORDERWIDTH);
	    else
		XConfigureWindow(sub->w, x, -BORDERWIDTH,
			sub->dwidth, ctx->height);
	    sub->x = x;
	    sub->width = sub->dwidth;
	}
	x += sub->dwidth + BORDERWIDTH;
    }
    ky = ctx->height - KNOBHEIGHT;
    for (i = 0, sub = ctx->sub; i < ctx->numpanels; i++, sub++) {
	kx = sub->x + sub->width - (KNOBWIDTH / 2);
	if (i == ctx->numpanels - 1)
	    kx = -99;
	XMoveWindow(sub->knob, kx, ky);
    }
}


static DrawHTrackLine(ctx)
WindowFramePtr ctx;
{
    XLine(ctx->window, ctx->tracklocation, 0, ctx->tracklocation, ctx->height,
            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->height != event->height || ctx->width != event->width) {
	    if (ctx->height != event->height) {
		for (i = 0; i < ctx->numpanels; i++) {
		    XChangeWindow(ctx->sub[i].w,
			    ctx->sub[i].width, event->height);
		}
	    }
	    ctx->width = event->width;
	    ctx->height = event->height;
	    for (i = ctx->numpanels - 1;
		    i > 0 && !(ctx->sub[i].autochange);
		    i--);
	    RefigureHLocations(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;
	    DrawHTrackLine(ctx);	/* Erase old line */
	    ctx->tracklocation = x;
	    if (event->type != ButtonReleased) {
		DrawHTrackLine(ctx);/* Draw new line */
		return PROCESSED;
	    }
	    position = ctx->whichtracking;
	    diff = ctx->tracklocation -
		(ctx->sub[position].x + ctx->sub[position].width);
	    ctx->sub[position].dwidth += diff;
	    if (position == ctx->numpanels - 2)
		ctx->sub[position + 1].dwidth -= diff;
	    XClipClipped(ctx->window);
	    RefigureHLocations(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 horizontally arranged tiled windows.
 */

Status TMakeHWindowFrame(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->widthused = 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 TDeleteHWindowFrame(w)
Window w;
{
    WindowFramePtr ctx;
    int i;
    ctx = WindowFramePtrFromWindow(w);
    if(!ctx)
       return ERRNOTFOUND;
    XUnmapWindow(w);
    for (i=ctx->numpanels-1 ; i>=0 ; i--) 
	TDeleteFromHWindowFrame(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 TAddToHWindowFrame(w, arglist)
Window w;			/* Window frame */
Targ * arglist;
{
    WindowFramePtr ctx;
    Window    pw;
    int       i, needed, position;
    int       status;
    PanelPtr  sub;
    Pixmap    border, bkground;
    int x;
    int min, max;
    short autochange;
    int width;	
    int dwidth;

    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;
    x          = ctx -> width;
    width      = ctx -> width / ctx -> numpanels;
    min        = KNOBWIDTH + 1;
    max        = ctx -> width;
    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:
             break;
          case T_PANED_WIDTH:
             width = (int) arglist -> data;
             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->x = x;
    sub->width = sub->dwidth = width;
    sub->autochange = autochange;
    sub->min = min;
    sub->max = max;

/* -----> Create Window Pane */

    if (sub->w == NULL) 
	sub->w = XCreateWindow(w, sub->x, -BORDERWIDTH, sub->width, 
			ctx->height, BORDERWIDTH, border, bkground);
    else
	XConfigureWindow(sub->w, sub->x, -BORDERWIDTH, sub->width,
			ctx->height);
    needed = sub->width + BORDERWIDTH + ctx->widthused;
    if (needed > ctx->width)
	TryResize(ctx, needed, ctx->height);
    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("horiz_arrow"));
#else
    XDefineCursor(sub->knob, XCreateCursor(
                             horiz_arrow_width, horiz_arrow_height,
                             horiz_arrow_bits,  horiz_arrow_mask_bits,
                             horiz_arrow_x_hot, horiz_arrow_y_hot,
                             BlackPixel, WhitePixel, GXcopy));
#endif


    XMapWindow(sub->w);
    if (min != max)
       XMapWindow(sub->knob);
    TSetXEventDispatch(sub->knob, HandleKnob, knobMask, 0);
    RefigureHLocations(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 TDeleteFromHWindowFrame(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->sub[i].width - BORDERWIDTH,
		    ctx->height);
	}
	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;
    RefigureHLocations(ctx, i);
}

/* =================================================================== */

/*
 * Enables or disables adjustments to pane boundaries.
 *
 */

TPanedHRefigureMode(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;
	    RefigureHLocations(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 TGetHPaneAttr (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) FALSE;
            break;
         case T_PANED_POSITION:
            arglist -> data = (caddr_t) FALSE;
            break;
         case T_PANED_HEIGHT:
            arglist -> data = (caddr_t) ctx -> height;
            break;
         case T_PANED_WIDTH:
            arglist -> data = (caddr_t) pane -> 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 TSetHPaneAttr (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) HORIZONTAL;
            break;
         case T_PANED_POSITION:
            arglist -> data = (caddr_t) FALSE;
            break;
         case T_PANED_HEIGHT:
            arglist -> data = (caddr_t) ctx -> height;
            break;
         case T_PANED_WIDTH:
            arglist -> data = (caddr_t) pane -> 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++;
   }

   RefigureHLocations (ctx, 1);
}