Annotation of researchv9/X11/src/X.V11R1/lib/oldXtk/ScrollWin.c, revision 1.1.1.1

1.1       root        1: /* $Header: ScrollWin.c,v 1.1 87/09/11 07:59:43 toddb Exp $ */
                      2: #ifndef lint
                      3: static char *sccsid = "@(#)ScrolledWin.c       1.4     2/25/87";
                      4: #endif lint
                      5: 
                      6: /*
                      7:  * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
                      8:  * 
                      9:  *                         All Rights Reserved
                     10:  * 
                     11:  * Permission to use, copy, modify, and distribute this software and its 
                     12:  * documentation for any purpose and without fee is hereby granted, 
                     13:  * provided that the above copyright notice appear in all copies and that
                     14:  * both that copyright notice and this permission notice appear in 
                     15:  * supporting documentation, and that the name of Digital Equipment
                     16:  * Corporation not be used in advertising or publicity pertaining to
                     17:  * distribution of the software without specific, written prior permission.  
                     18:  * 
                     19:  * 
                     20:  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
                     21:  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
                     22:  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
                     23:  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
                     24:  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
                     25:  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
                     26:  * SOFTWARE.
                     27:  */
                     28: 
                     29: 
                     30: /* File: ScrolledWin.c */
                     31: 
                     32: #include "Xlib.h"
                     33: #include "Intrinsic.h"
                     34: #include "Scroll.h"
                     35: #include "Atoms.h"
                     36: 
                     37: typedef struct _WidgetDataRec{
                     38:     Display *dpy;              /* Display connection for this widget */
                     39:     Window outer;              /* Encompassing window including scrollbars */
                     40:     Window frame;              /* Window containing the view of the data */
                     41:     Window inner;              /* Window with the data itself */
                     42:     Position x, y;             /* Location of outer within parent. */
                     43:     Dimension outerwidth, outerheight; /* Dimensions of encompassing window */
                     44:     WindowBox framebox;                /* Dimensions of framing (clipping) window */
                     45:     WindowBox innerbox;                /* Dimensions of the data */
                     46:     Dimension thickness;       /* Thickness of scroll bars */
                     47:     Boolean forcebars;         /* Whether we should always display */
                     48:                                /* the selected bars. */
                     49:     Boolean allowhoriz;                /* Whether we allow horizontal scrollbars. */
                     50:     Boolean allowvert;         /* Whether we allow vertical scrollbars. */
                     51:     Boolean usebottom;         /* True iff horiz bars appear at bottom. */
                     52:     Boolean useright;          /* True iff vert bars appear at right. */
                     53:     Window horizinuse, vertinuse; /* What scrollbars we currently have */
                     54: } WidgetDataRec, *WidgetData;
                     55: 
                     56: static WidgetDataRec globaldata;
                     57: static WidgetDataRec globalinit = {
                     58:     NULL,              /* Display dpy; */
                     59:     NULL,              /* Encompassing window including scrollbars */
                     60:     NULL,              /* Window containing the view of the data */
                     61:     NULL,              /* Window with the data itself */
                     62:     0,0,               /* Location of outer within parent. */
                     63:     1,1,               /* Dimensions of encompassing window */
                     64:     {0,0,1,1,0},       /* framebox location, dimensions, border width */
                     65:     {0,0,1,1,0},       /* innerbox location, dimensions, border width */
                     66:     0,                 /* Thickness of scroll bars */
                     67:     FALSE,             /* Whether we should always display */
                     68:                        /* the selected bars. */
                     69:     FALSE,             /* Whether we allow horizontal scrollbars. */
                     70:     FALSE,             /* Whether we allow vertical scrollbars. */
                     71:     FALSE,             /* True iff horiz bars appear at bottom. */
                     72:     FALSE,             /* True iff vert bars appear at right. */
                     73:     (Window)NULL,(Window)NULL,  /* What scrollbars we currently have */
                     74: };
                     75: 
                     76: 
                     77: 
                     78: extern int ScrollUpDownProc(), ThumbProc();
                     79: 
                     80: static Arg addBarArgs[] = {
                     81:     {XtNorientation,       (XtArgVal) NULL},
                     82:     {XtNlowerRight,        (XtArgVal) NULL},
                     83:     {XtNvalue,             (XtArgVal) NULL},
                     84:     {XtNscrollUpDownProc,   (XtArgVal) ScrollUpDownProc},
                     85:     {XtNthumbProc,         (XtArgVal) ThumbProc},
                     86: };
                     87: 
                     88: static Resource resources[] = {
                     89:     {XtNinnerWidth, XtCWidth, XrmRInt, sizeof(int),
                     90:         (caddr_t)&globaldata.innerbox.width, NULL},
                     91:     {XtNinnerHeight, XtCHeight, XrmRInt, sizeof(int),
                     92:         (caddr_t)&globaldata.innerbox.height, NULL},
                     93:     {XtNinnerWindow, XtCWindow, XrmRWindow, sizeof(Window),
                     94:         (caddr_t)&globaldata.inner, NULL},
                     95:     {XtNforceBars, XtCBoolean, XrmRBoolean, sizeof(Boolean),
                     96:         (caddr_t)&globaldata.forcebars, NULL},
                     97:     {XtNallowHoriz, XtCBoolean, XrmRBoolean, sizeof(Boolean),
                     98:         (caddr_t)&globaldata.allowhoriz, NULL},
                     99:     {XtNallowVert, XtCBoolean, XrmRBoolean, sizeof(Boolean),
                    100:         (caddr_t)&globaldata.allowvert, NULL},
                    101:     {XtNuseBottom, XtCBoolean, XrmRBoolean, sizeof(Boolean),
                    102:         (caddr_t)&globaldata.usebottom, NULL},
                    103:     {XtNuseRight, XtCBoolean, XrmRBoolean, sizeof(Boolean),
                    104:         (caddr_t)&globaldata.useright, NULL},
                    105: };
                    106: 
                    107: static XContext scrolledWindowContext;
                    108: 
                    109: static Boolean initialized = FALSE;
                    110: 
                    111: static void ScrolledWindowInitialize ()
                    112: {
                    113:     if (initialized)
                    114:        return;
                    115:     initialized = TRUE;
                    116: 
                    117:     scrolledWindowContext = XUniqueContext();
                    118:     globalinit.forcebars = globalinit.allowhoriz = globalinit.allowvert = FALSE;
                    119:     globalinit.usebottom = globalinit.useright = FALSE;
                    120: }
                    121: 
                    122: static WidgetData ScrolledWindowContextFromWindow(dpy, w)
                    123:   Display *dpy;
                    124:   Window w;
                    125: {
                    126:     WidgetData data;
                    127:     if (!XFindContext(dpy, w, scrolledWindowContext, (caddr_t *) &data)) 
                    128:        return data;
                    129:     return 0;
                    130: }
                    131:     
                    132: static SetBar(dpy, w, fx, wd, tw)
                    133:   Display *dpy;
                    134:   Window w;
                    135:   Position fx;
                    136:   Dimension wd, tw;
                    137: {
                    138:     float   from, width;
                    139:     from = (float) fx / tw;
                    140:     width = (float) wd / tw;
                    141:     XtScrollBarSetThumb(dpy, w, from, width);
                    142: }
                    143: 
                    144: static RedrawThumbs(data)
                    145:   WidgetData data;
                    146: {
                    147:     if (data->horizinuse)
                    148:        SetBar(data->dpy, data->horizinuse, -(data->innerbox.x), data->framebox.width,
                    149:                data->innerbox.width);
                    150:     if (data->vertinuse)
                    151:        SetBar(data->dpy, data->vertinuse, -(data->innerbox.y), data->framebox.height,
                    152:                data->innerbox.height);
                    153: }
                    154: 
                    155: 
                    156: 
                    157: static MoveInner(data, nx, ny)
                    158:   WidgetData data;
                    159:   int nx, ny;
                    160: {
                    161:     if (-nx + data->framebox.width > data->innerbox.width)
                    162:        nx = -(data->innerbox.width - data->framebox.width);
                    163:     if (-ny + data->framebox.height > data->innerbox.height)
                    164:        ny = -(data->innerbox.height - data->framebox.height);
                    165:     if (nx > 0) nx = 0;
                    166:     if (ny > 0) ny = 0;
                    167:     if (nx != data->innerbox.x || ny != data->innerbox.y) {
                    168:        XMoveWindow(data->dpy,data->inner, nx, ny);
                    169:        data->innerbox.x = nx;
                    170:        data->innerbox.y = ny;
                    171:        (void)XtSendConfigureNotify(data->dpy, data->inner, &(data->innerbox));
                    172:     }
                    173:     RedrawThumbs(data);
                    174: }
                    175: 
                    176: static ResizeEverything(data)
                    177:     WidgetData data;
                    178: {
                    179:     int   lw, lh;
                    180:     Boolean needshoriz, needsvert;
                    181:     int oldinnerwidth = data->innerbox.width;
                    182:     int oldinnerheight = data->innerbox.height;
                    183: 
                    184:     data->thickness = XtScrollMgrGetThickness(data->dpy, data->outer);
                    185:     if (data->forcebars) {
                    186:        needshoriz = data->allowhoriz;
                    187:        needsvert = data->allowvert;
                    188:        data->framebox.width =
                    189:         data->outerwidth - (needsvert ? data->thickness : 0);
                    190:        data->framebox.height =
                    191:         data->outerheight - (needshoriz ? data->thickness : 0);
                    192:        if (!needshoriz)
                    193:            data->innerbox.width = data->framebox.width;
                    194:        if (!needsvert)
                    195:            data->innerbox.height = data->framebox.height;
                    196:     }
                    197:     else {
                    198:        data->framebox.width = data->outerwidth;
                    199:        data->framebox.height = data->outerheight;
                    200:        do {
                    201:            lw = data->framebox.width;
                    202:            lh = data->framebox.height;
                    203:            needshoriz = (Boolean)(data->innerbox.width > data->framebox.width);
                    204:            needsvert =
                    205:                (Boolean)(data->innerbox.height > data->framebox.height);
                    206:            if (!(data->allowhoriz)) {
                    207:                data->innerbox.width = data->framebox.width;
                    208:                needshoriz = FALSE;
                    209:            }
                    210:            if (!(data->allowvert)) {
                    211:                data->innerbox.height = data->framebox.height;
                    212:                needsvert = FALSE;
                    213:            }
                    214:            data->framebox.width = data->outerwidth -
                    215:                (needsvert ? data->thickness : 0);
                    216:            data->framebox.height = data->outerheight -
                    217:                (needshoriz ? data->thickness : 0);
                    218:        } while (lw != data->framebox.width || lh != data->framebox.height);
                    219:     }
                    220:     if (oldinnerwidth != data->innerbox.width ||
                    221:            oldinnerheight != data->innerbox.height) {
                    222:        XResizeWindow(data->dpy, data->inner,
                    223:                      data->innerbox.width, data->innerbox.height);
                    224:        (void)XtSendConfigureNotify(data->dpy, data->inner, &(data->innerbox));
                    225:     }
                    226:        
                    227:     if (needshoriz && data->horizinuse == 0) {
                    228:        addBarArgs[0].value = (XtArgVal)XtorientHorizontal;
                    229:        addBarArgs[1].value = (XtArgVal)(data->usebottom);
                    230:        addBarArgs[2].value = (XtArgVal)(data->outer);
                    231:        data->horizinuse =
                    232:            XtScrollMgrAddBar(data->dpy, data->outer, addBarArgs, XtNumber(addBarArgs));
                    233:        XMapWindow(data->dpy,data->horizinuse);
                    234:     }
                    235:     else
                    236:        if (!needshoriz && data->horizinuse) {
                    237:            XtDeleteScrollBar(data->dpy, data->outer, data->horizinuse);
                    238:            data->horizinuse = 0;
                    239:        }
                    240:     if (needsvert && data->vertinuse == 0) {
                    241:        addBarArgs[0].value = (XtArgVal)XtorientVertical;
                    242:        addBarArgs[1].value = (XtArgVal)(data->useright);
                    243:        addBarArgs[2].value = (XtArgVal)(data->outer);
                    244:        data->vertinuse =
                    245:            XtScrollMgrAddBar(data->dpy, data->outer, addBarArgs, XtNumber(addBarArgs));
                    246:        XMapWindow(data->dpy,data->vertinuse);
                    247:     }
                    248:     else
                    249:        if (!needsvert && data->vertinuse) {
                    250:            XtDeleteScrollBar(data->dpy, data->outer, data->vertinuse);
                    251:            data->vertinuse = 0;
                    252:        }
                    253:     data->framebox.width = data->outerwidth - (needsvert ? data->thickness : 0);
                    254:     data->framebox.height = data->outerheight - (needshoriz ? data->thickness : 0);
                    255:     RedrawThumbs(data);
                    256: }
                    257: 
                    258: 
                    259: 
                    260: /* Semi-public routines */
                    261: 
                    262: 
                    263: static ScrollUpDownProc(dpy, swin, outer, pix)
                    264: Display *dpy;
                    265: Window swin, outer;
                    266: int pix;
                    267: {
                    268:     WidgetData data;
                    269:     int     nx, ny;
                    270:     data = ScrolledWindowContextFromWindow(dpy, outer);
                    271:     if (!data) return;
                    272:     nx = data->innerbox.x - ((swin == data->horizinuse) ? pix : 0);
                    273:     ny = data->innerbox.y - ((swin == data->vertinuse) ? pix : 0);
                    274:     MoveInner(data, nx, ny);
                    275: }
                    276: 
                    277: static ThumbProc(dpy, swin, outer, percent)
                    278:   Display *dpy;
                    279:   Window swin, outer;
                    280:   float percent;
                    281: {
                    282:     WidgetData data;
                    283:     int     nx, ny;
                    284:     data = ScrolledWindowContextFromWindow(dpy, outer);
                    285:     if (!data) return;
                    286:     nx = data->innerbox.x;
                    287:     ny = data->innerbox.y;
                    288:     if (swin == data->horizinuse)
                    289:        nx = -(percent * data->innerbox.width);
                    290:     if (swin == data->vertinuse)
                    291:        ny = -(percent * data->innerbox.height);
                    292:     MoveInner(data, nx, ny);
                    293: }
                    294: 
                    295: static XtGeometryReturnCode
                    296: ScrolledWindowGeometryRequest(dpy, window, request, requestBox, replyBox)
                    297: Display *dpy;
                    298: Window window;
                    299: XtGeometryRequest request;
                    300: WindowBox *requestBox, *replyBox;
                    301: {
                    302:     WidgetData data;
                    303:     XtGeometryReturnCode    reply;
                    304:     WindowBox myrequest;
                    305:     data = ScrolledWindowContextFromWindow(dpy, window);
                    306:     if (!data || window != data->inner || request != XtgeometryResize)
                    307:        return XtgeometryNo;
                    308:     *replyBox = *requestBox;
                    309:     reply = XtgeometryYes;
                    310:     if ((!(data->allowhoriz) && requestBox->width != data->innerbox.width) ||
                    311:            (!(data->allowvert) && requestBox->height != data->innerbox.height)) {
                    312:        myrequest = *requestBox;
                    313:        if (data->horizinuse) myrequest.height += data->thickness;
                    314:        if (data->vertinuse) myrequest.width += data->thickness;
                    315:        if (data->allowhoriz) myrequest.width = data->outerwidth;
                    316:        if (data->allowvert) myrequest.height = data->outerheight;
                    317:        reply = XtMakeGeometryRequest(data->dpy, data->outer, XtgeometryResize, &myrequest,
                    318:                                      replyBox);
                    319:        if (reply != XtgeometryYes) {
                    320:            replyBox->width = data->innerbox.width;
                    321:            replyBox->height = data->innerbox.height;
                    322:            reply = XtgeometryNo;
                    323:            if (data->allowhoriz) replyBox->width = requestBox->width;
                    324:            if (data->allowvert) replyBox->height = requestBox->height;
                    325:            if (data->innerbox.width != replyBox->width ||
                    326:                    data->innerbox.height != replyBox->height) {
                    327:                reply = XtgeometryAlmost;
                    328:            }
                    329:        }
                    330:     }
                    331:     if (reply == XtgeometryYes) {
                    332:        if (requestBox->width != data->innerbox.width ||
                    333:                requestBox->height != data->innerbox.height) {
                    334:            XResizeWindow(dpy, window,
                    335:                          requestBox->width, requestBox->height);
                    336:            data->innerbox.width = requestBox->width;
                    337:            data->innerbox.height = requestBox->height;
                    338:            (void) XtSendConfigureNotify(dpy, window, &(data->innerbox));
                    339:            ResizeEverything(data);
                    340:            MoveInner(data, data->innerbox.x, data->innerbox.y);
                    341:                                /* Check inner location */
                    342:        }
                    343:     }
                    344:     return reply;
                    345: }
                    346: 
                    347: 
                    348: static XtEventReturnCode HandleEvents(event)
                    349:   XEvent *event;
                    350: {
                    351:     WidgetData data;
                    352:     data = ScrolledWindowContextFromWindow(event->xany.display, event->xany.window);
                    353:     if (!data) return XteventNotHandled;
                    354:     switch(event->type) {
                    355:        case ConfigureNotify:
                    356:            if (data->outerwidth != event->xconfigure.width ||
                    357:                data->outerheight != event->xconfigure.height) {
                    358:                data->outerwidth = event->xconfigure.width;
                    359:                data->outerheight = event->xconfigure.height;
                    360:                ResizeEverything(data);
                    361:                MoveInner(data, data->innerbox.x, data->innerbox.y);
                    362:            }
                    363:            return XteventHandled;
                    364:        case DestroyNotify:
                    365:            (void)XDeleteContext(data->dpy,data->outer,scrolledWindowContext);
                    366:            (void)XDeleteContext(data->dpy,data->frame,scrolledWindowContext);
                    367:            (void) XtSendDestroyNotify(data->dpy, data->inner);
                    368:            /* Let the scrollbarmgr send messages to the scrollbars. */
                    369:            XtFree((char*)data);
                    370:            return XteventHandled;
                    371:     }
                    372:     return XteventNotHandled;
                    373: }
                    374: 
                    375: 
                    376: 
                    377: /* Public routines */
                    378: 
                    379: /* Create a scrolled window in the given one. */
                    380: 
                    381: Window XtScrolledWindowCreate(dpy, parent, args, argCount)
                    382:     Display *dpy;
                    383:     Window  parent;
                    384:     ArgList args;
                    385:     int            argCount;
                    386: {
                    387:     WidgetData data;
                    388:     Dimension bw;
                    389:     unsigned int depth;
                    390:     Drawable root;
                    391:     XrmNameList names;
                    392:     XrmClassList classes;
                    393: 
                    394:     if (!initialized) ScrolledWindowInitialize();
                    395:     globaldata = globalinit;
                    396:     globaldata.dpy = dpy;
                    397:     XtGetResources(dpy, resources, XtNumber(resources), args, argCount, parent,
                    398:        "scrolledWin", "ScrolledWin", &names, &classes);
                    399:     data = (WidgetData) XtMalloc(sizeof(WidgetDataRec));
                    400:     *data = globaldata;
                    401:     data->outer = XtScrollMgrCreate(dpy, parent, args, argCount);
                    402:     data->frame = XtScrollMgrGetChild(data->dpy, data->outer);
                    403: 
                    404:     XtSetNameAndClass(data->dpy, data->frame, names, classes);
                    405:     XrmFreeNameList(names);
                    406:     XrmFreeClassList(classes);
                    407: 
                    408:     if (data->inner != NULL) {
                    409:        XWindowChanges wc;
                    410:        unsigned int valuemask;
                    411:        valuemask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
                    412:        wc.x = data->innerbox.x; wc.y = data ->innerbox.y; wc.width = data ->innerbox.width;
                    413:        wc.height=data->innerbox.height; wc.border_width = 1;
                    414:        XConfigureWindow(data->dpy,data->inner,valuemask,&wc);
                    415:        XReparentWindow(data->dpy,data->inner,parent,data->x,data->y);
                    416: 
                    417:     } else {
                    418:        data->inner = XtCreateWindow(data->dpy, data->frame, 0, 0,
                    419:                                     data->innerbox.width,
                    420:                                     data->innerbox.height,
                    421:                                     0, (Pixel)0, (Pixel)0, NorthWestGravity);
                    422:     }
                    423:     (void) XSaveContext(data->dpy, data->outer, scrolledWindowContext, (caddr_t) data);
                    424:     (void) XSaveContext(data->dpy, data->inner, scrolledWindowContext, (caddr_t) data);
                    425:     (void) XtSetGeometryHandler(data->dpy, data->inner, ScrolledWindowGeometryRequest);
                    426:     data->innerbox.x = data->innerbox.y = 0;
                    427:     (void) XGetGeometry(data->dpy, data->outer, &root, &(data->x), &(data->y),
                    428:                       &(data->outerwidth), &(data->outerheight), &bw, &depth);
                    429:     data->horizinuse = data->vertinuse = (Window) NULL;
                    430:     ResizeEverything(data);
                    431:     XMapWindow(data->dpy,data->inner);
                    432:     XMapSubwindows(data->dpy,data->outer);
                    433:     XtSetEventHandler(data->dpy, data->outer, HandleEvents, StructureNotifyMask,
                    434:      (caddr_t) NULL);
                    435:     return data->outer;
                    436: }
                    437: 
                    438: 
                    439: Window XtScrolledWindowGetChild(dpy, outer)
                    440: Display *dpy;
                    441: Window outer;
                    442: {
                    443:     WidgetData data;
                    444:     data = ScrolledWindowContextFromWindow(dpy, outer);
                    445:     if (data) return data->inner;
                    446:     else return NULL;
                    447: }
                    448: 
                    449: void XtScrolledWindowSetChild(dpy, parent, child)
                    450: Display *dpy;
                    451: Window parent, child;
                    452: {
                    453:     WidgetData data;
                    454:     Dimension bw;
                    455:     unsigned int depth;
                    456:     Drawable root;
                    457:     data = ScrolledWindowContextFromWindow(dpy, parent);
                    458:     if (data) {
                    459:        XUnmapWindow(data->dpy,data->inner);
                    460:        (void) XDeleteContext(data->dpy, data->inner, scrolledWindowContext);
                    461:        data->inner = child;
                    462:        (void) XGetGeometry(data->dpy,data->inner,&root,&(data->innerbox.x),
                    463:          &(data->innerbox.y), &(data->innerbox.width),
                    464:          &(data->innerbox.height), &bw, &depth);
                    465:        (void) XSaveContext(data->dpy, data->inner, scrolledWindowContext, (caddr_t) data);
                    466:        (void) XtSetGeometryHandler(data->dpy, data->inner, ScrolledWindowGeometryRequest);
                    467:        ResizeEverything(data);
                    468:        XMapWindow(data->dpy, data->inner);
                    469:     }
                    470: }
                    471: 
                    472: Window XtScrolledWindowGetFrame(dpy, parent)
                    473:     Display *dpy;
                    474:     Window parent;
                    475: {
                    476:     WidgetData data;
                    477:     data = ScrolledWindowContextFromWindow(dpy, parent);
                    478:     if (data) return data->frame;
                    479:     else return NULL;
                    480: }
                    481: 
                    482: /* Unlink everything that was done to make this a scrolled window.  All the
                    483:    windows are actually destroyed, except for the parent one. */
                    484: 
                    485: Window XtUnmakeScrolledWindow(dpy, parent)
                    486:   Display *dpy;
                    487:   Window parent;
                    488: {
                    489:     WidgetData data;
                    490:     data = ScrolledWindowContextFromWindow(dpy, parent);
                    491:     if (!data) return;
                    492:     (void) XDeleteContext(data->dpy, data->inner, scrolledWindowContext);
                    493:     (void) XDeleteContext(data->dpy, parent, scrolledWindowContext);
                    494:     XDestroyWindow(data->dpy,data->inner);
                    495:     XtScrollMgrDestroy(data->dpy, parent);
                    496:     XtFree((caddr_t) data);
                    497: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.