v08i077: chaos, Part01/10
Ken Marks x2425
balr!panasun!ken at uunet.UU.NET
Tue Aug 21 04:03:21 AEST 1990
Submitted-by: balr!panasun!ken at uunet.UU.NET (Ken Marks (x2425))
Posting-number: Volume 8, Issue 77
Archive-name: chaos/part01
This is a network based Mandelbrot generator for X11.
See the README and man pages for more info.
Ken Marks ...uunet!tellab5!balr!panasun!ken -or- ken at panasun
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 1 (of 10)."
# Contents: README MANIFEST common drone fonts gencmap headers maps
# master widgets widgets/Canvas.c widgets/Label.c
# Wrapped by ken at panasun on Mon Jul 30 14:59:47 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1722 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XOverview
X--------
XThis code was developed on a SUN 3/60 and a SPARCstation 1 with the help of
XSaber-C which has been a blessing. The code has been also been tested on
Xa DECstation 3100 and a SUN 386i. The messages passed between the chaos
Xclient and the drone daemons are byte-order independent and therefore drones
Xmay be run on a variety of different machines.
X
X
XBuilding, Installing and Executing
X----------------------------------
X
X 1. From the top level type "xmkmf" to create a makefile for
X the top level. (Sample makefiles are supplied for users who
X cannot use Imakefiles.)
X
X 2. Type "make World".
X
X 3. Watch for any errors during the build.
X
X 4. As root, type "make install". If you want manual pages installed,
X also type "make install.man".
X
X 5. Read the man pages for chaos(6), drone(6), and gencmap(6).
X
X 6. Copy the contents of master/Chaos.ad to the end of your .Xdefaults
X file and customize as desired.
X
X 7. If you wish to run drones remotely on other hosts, add them to the
X access control list with xhost. For example, to allow drones to
X be run on hosts "calvin" and "hobbes", type "xhost calvin hobbes".
X
X 8. Type "chaos" and have fun.
X
X
XBugs and Enhancements
X---------------------
X
XThere will undoubtedly be be some bugs remaining in the code although Saber-C
Xwas used to point out a lot of insideous bugs that would have caused me hours
Xof greif otherwise. When bugs or portability issues arise, please send them
Xback to me so that I may include the patches in future releases of the code.
X
XAny enhancements are welcome but please direct them back to me so that I can
Xkeep a single version of the code.
X
XKen Marks ...uunet!tellab5!balr!panasun!ken -or- ken at panasun
END_OF_FILE
if test 1722 -ne `wc -c <'README'`; then
echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(3537 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X File Name Archive # Description
X-----------------------------------------------------------
X COPYRIGHT 10
X Imakefile 10
X MANIFEST 1
X README 1
X TODO 6
X common 1
X common/Imakefile 10
X common/byteSwap.c 10
X common/colormap.c 7
X common/error.c 10
X common/file.c 8
X common/imageIO.c 9
X common/ipc.c 8
X common/makefile 10
X common/showEvent.c 2
X drone 1
X drone/Imakefile 10
X drone/doPropNotify.c 8
X drone/drone.c 9
X drone/drone.man 10
X drone/init.c 9
X drone/makefile 10
X drone/mandelbrot.c 7
X drone/propNotify.c 8
X fonts 1
X fonts/Imakefile 10
X fonts/chaos-bold.bdf 6
X fonts/chaos-norm.bdf 6
X fonts/makefile 10
X fonts/push-norm.bdf 3
X fonts/push-rev.bdf 4
X gencmap 1
X gencmap/Imakefile 2
X gencmap/gencmap.c 2
X gencmap/gencmap.man 9
X gencmap/makefile 10
X headers 1
X headers/Canvas.h 10
X headers/CanvasP.h 9
X headers/Chaos.h 10
X headers/Colormap.h 10
X headers/Compound.h 10
X headers/CompoundP.h 10
X headers/DlgShell.h 10
X headers/DlgShellP.h 10
X headers/Ipc.h 9
X headers/Label.h 10
X headers/LabelP.h 10
X headers/List.h 10
X headers/ListP.h 9
X headers/LocalDefs.h 5
X headers/Menu.h 10
X headers/MenuItems.h 10
X headers/MenuP.h 10
X headers/Palette.h 10
X headers/PaletteP.h 10
X headers/Push.h 10
X headers/PushP.h 10
X headers/Queue.h 10
X headers/Slider.h 10
X headers/SliderP.h 9
X headers/Task.h 10
X headers/Text.h 10
X headers/TextP.h 10
X headers/patchlevel.h 8
X makefile 10
X maps 1
X maps/default.map 8
X maps/gray4.map 9
X maps/gray8.map 9
X maps/hsb.map 9
X maps/hsb2.map 9
X maps/hsb3.map 9
X maps/hsb4.map 9
X maps/hsb8.map 9
X maps/octo.map 9
X maps/random.map 9
X maps/rgb.map 9
X maps/special.map 9
X maps/special2.map 9
X maps/special3.map 8
X maps/special4.map 8
X maps/special8.map 8
X maps/white.map 8
X maps/zebra.map 9
X master 1
X master/Chaos.ad 8
X master/Imakefile 10
X master/chaos.man 7
X master/colormapDb.c 4
X master/droneDb.c 6
X master/fileDb.c 7
X master/makefile 10
X master/master.c 3
X master/messageDb.c 8
X master/queue.c 8
X master/settingsDb.c 7
X master/task.c 8
X widgets 1
X widgets/Canvas.c 1
X widgets/Compound.c 4
X widgets/DlgShell.c 6
X widgets/Imakefile 10
X widgets/Label.c 1
X widgets/List.c 2
X widgets/Menu.c 5
X widgets/Palette.c 3
X widgets/Push.c 7
X widgets/Slider.c 5
X widgets/Text.c 5
X widgets/makefile 10
END_OF_FILE
if test 3537 -ne `wc -c <'MANIFEST'`; then
echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test ! -d 'common' ; then
echo shar: Creating directory \"'common'\"
mkdir 'common'
fi
if test ! -d 'drone' ; then
echo shar: Creating directory \"'drone'\"
mkdir 'drone'
fi
if test ! -d 'fonts' ; then
echo shar: Creating directory \"'fonts'\"
mkdir 'fonts'
fi
if test ! -d 'gencmap' ; then
echo shar: Creating directory \"'gencmap'\"
mkdir 'gencmap'
fi
if test ! -d 'headers' ; then
echo shar: Creating directory \"'headers'\"
mkdir 'headers'
fi
if test ! -d 'maps' ; then
echo shar: Creating directory \"'maps'\"
mkdir 'maps'
fi
if test ! -d 'master' ; then
echo shar: Creating directory \"'master'\"
mkdir 'master'
fi
if test ! -d 'widgets' ; then
echo shar: Creating directory \"'widgets'\"
mkdir 'widgets'
fi
if test -f 'widgets/Canvas.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'widgets/Canvas.c'\"
else
echo shar: Extracting \"'widgets/Canvas.c'\" \(37474 characters\)
sed "s/^X//" >'widgets/Canvas.c' <<'END_OF_FILE'
X/*
X * Copyright (c) Ken W. Marks 1989, 1990.
X */
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <math.h>
X#include <X11/IntrinsicP.h>
X#include <X11/StringDefs.h>
X#include <X11/XWDFile.h>
X#include <Chaos.h>
X#include <LocalDefs.h>
X#include <Ipc.h>
X#include <Menu.h>
X#include <MenuItems.h>
X#include <CanvasP.h>
X#include <Task.h>
X#include <Queue.h>
X#include <Colormap.h>
X
Xstatic Cardinal pad_amount[] = {0, 3, 2, 1};
X
X/* macro for padding a length to an even multiple of 4 (uses pad_amount[]) */
X#define PAD(length) ((length) + pad_amount[(length) & 3])
X
X#define STARTING_RADIUS 2.5
X
X#define IN_BOUNDS_X(w, x) ((int) ((x) < 0 ? 0 : \
X (x) >= (w)->core.width ? \
X (w)->core.width - 1 : (x)))
X
X#define IN_BOUNDS_Y(w, y) ((int) ((y) < 0 ? 0 : \
X (y) >= (w)->core.height ? \
X (w)->core.height - 1 : (y)))
X
X#define MAX_SAVE_IMAGE_SIZE 65536
X
X
X#define offset(field) XtOffset(CanvasWidget,canvas.field)
X#define goffset(field) XtOffset(Widget,core.field)
X
Xstatic XtResource resources[] = {
X {XtNwidth, XtCWidth, XtRDimension, sizeof(Dimension),
X goffset(width), XtRString, "512"},
X {XtNheight, XtCHeight, XtRDimension, sizeof(Dimension),
X goffset(height), XtRString, "512"},
X};
X
X#undef offset
X#undef goffset
X
Xstatic void CanvasInitialize(), CanvasRealize(), CanvasResize();
Xstatic void CanvasRedisplay();
X
Xstatic void CanvasRegister(), CanvasUnregister(), CanvasMessage();
Xstatic void CanvasBtnDown(), CanvasBtnUp(), CanvasMotion();
Xstatic void CanvasMoveBox();
Xstatic void CanvasQuit();
Xstatic void CanvasReverse();
Xstatic void CanvasStartStop();
Xextern void MenuPopup();
X
Xstatic XtActionsRec canvas_actions[] =
X{
X {"unregister", CanvasUnregister},
X {"receive_msg", CanvasMessage},
X {"press", CanvasBtnDown},
X {"release", CanvasBtnUp},
X {"move", CanvasMotion},
X {"popup", MenuPopup},
X {"quit", CanvasQuit},
X {"reverse", CanvasReverse},
X {"start_stop", CanvasStartStop},
X};
X
Xstatic char canvas_translations[] =
X"<Destroy>: unregister()\n\
X <Prop>: receive_msg()\n\
X <Btn1Down>: press()\n\
X <Btn1Up>: release()\n\
X <Btn1Motion>: move()\n\
X <Btn3Down>: popup(menu_popup.menu)\n\
X Ctrl<Key>C: quit()\n\
X <Key>Q: quit()\n\
X <Key>Return: reverse()\n\
X <Key>0x20: start_stop()\n\
X";
X
X#define superclass (&widgetClassRec)
X
XCanvasClassRec canvasClassRec = {
X {
X /* core fields */
X /* superclass */ (WidgetClass) superclass,
X /* class_name */ "Canvas",
X /* widget_size */ sizeof(CanvasRec),
X /* class_initialize */ NULL,
X /* class_part_initialize */ NULL,
X /* class_inited */ FALSE,
X /* initialize */ CanvasInitialize,
X /* initialize_hook */ NULL,
X /* realize */ CanvasRealize,
X /* actions */ canvas_actions,
X /* num_actions */ XtNumber(canvas_actions),
X /* resources */ resources,
X /* resource_count */ XtNumber(resources),
X /* xrm_class */ NULL,
X /* compress_motion */ TRUE,
X /* compress_exposure */ TRUE,
X /* compress_enterleave */ TRUE,
X /* visible_interest */ FALSE,
X /* destroy */ NULL,
X /* resize */ CanvasResize,
X /* expose */ CanvasRedisplay,
X /* set_values */ NULL,
X /* set_values_hook */ NULL,
X /* set_values_almost */ XtInheritSetValuesAlmost,
X /* get_values_hook */ NULL,
X /* accept_focus */ NULL,
X /* version */ XtVersion,
X /* callback_private */ NULL,
X /* tm_table */ canvas_translations,
X /* query_geometry */ NULL,
X }
X};
X
XWidgetClass canvasWidgetClass = (WidgetClass) & canvasClassRec;
X
X
X/************************************************************/
X/******************** Private Procedures ********************/
X/************************************************************/
X
X
X/*ARGSUSED*/
Xstatic void CanvasInitialize(request, new)
XWidget request; /* unused */
XWidget new;
X{
X CanvasWidget w = (CanvasWidget) new;
X Screen *screen = XtScreen(w);
X extern Boolean retain_aspect_ratio;
X extern int iteration_limit;
X extern int task_width;
X extern int task_height;
X
X w->canvas.p_inc = (double) (2 * STARTING_RADIUS) / (w->core.width - 1);
X w->canvas.q_inc = (double) (2 * STARTING_RADIUS) / (w->core.height - 1);
X
X w->canvas.p_inc = w->canvas.q_inc = MAX(w->canvas.p_inc, w->canvas.q_inc);
X
X w->canvas.p_lo = (double) -(w->core.width * w->canvas.p_inc / 2);
X w->canvas.p_hi = (double) (w->canvas.p_lo + w->canvas.p_inc *
X (w->core.width - 1));
X
X w->canvas.q_lo = (double) -(w->core.height * w->canvas.q_inc / 2);
X w->canvas.q_hi = (double) (w->canvas.q_lo + w->canvas.q_inc *
X (w->core.height - 1));
X
X w->canvas.task_x = 0;
X w->canvas.task_y = 0;
X w->canvas.num_drones = 0;
X
X w->canvas.num_colors = CellsOfScreen(screen);
X w->canvas.pixmap = NULL;
X w->canvas.image = NULL;
X
X w->canvas.serial = 0;
X w->canvas.method = MANDELBROT;
X
X w->canvas.finished = False;
X w->canvas.paused = False;
X w->canvas.needs_saving = True;
X
X /* set up the initial iteration limit */
X w->canvas.curr_limit = iteration_limit;
X
X /* set up the initial aspect ratio retention state */
X w->canvas.retain_aspect_ratio = retain_aspect_ratio;
X
X /* set size to zero to force initial change in CanvasChangeTaskSize() */
X w->canvas.curr_task_width = 0;
X w->canvas.curr_task_height = 0;
X
X CanvasChangeTaskSize(new, (unsigned int) task_width,
X (unsigned int) task_height);
X}
X
X
Xstatic void CanvasRealize(widget, valueMask, attrs)
XWidget widget;
XXtValueMask *valueMask;
XXSetWindowAttributes *attrs;
X{
X CanvasWidget w = (CanvasWidget) widget;
X Display *dpy = XtDisplay(w);
X Screen *screen = XtScreen(w);
X XtGCMask valuemask;
X XGCValues gcv;
X extern Colormap colormap;
X extern Widget top_level;
X
X /* we assign the colormap here since we know that the top level shell has
X * been realized. */
X colormap = CreateColormap(dpy, screen, XtWindow(top_level));
X
X XtCreateWindow(widget, InputOutput, (Visual *) CopyFromParent,
X *valueMask, attrs);
X
X gcv.function = GXinvert;
X gcv.plane_mask = 0xff;
X valuemask = GCFunction | GCPlaneMask;
X w->canvas.xor_gc = XtGetGC((Widget) w, valuemask, &gcv);
X
X gcv.background = w->core.background_pixel;
X gcv.fill_style = FillSolid;
X valuemask = GCBackground | GCFillStyle;
X w->canvas.normal_gc = XtGetGC((Widget) w, valuemask, &gcv);
X
X gcv.foreground = BLACK;
X gcv.background = WHITE;
X gcv.fill_style = FillTiled;
X gcv.tile = XmuCreateStippledPixmap(screen, BlackPixelOfScreen(screen),
X WhitePixelOfScreen(screen), (unsigned) DefaultDepthOfScreen(screen));
X
X valuemask = GCForeground | GCBackground | GCTile | GCFillStyle;
X w->canvas.clear_gc = XtGetGC((Widget) w, valuemask, &gcv);
X
X /* Call CanvasResize() to initialize pixmap at creation time since the
X * CanvasRedisplay() will be called before CanvasResize() would. */
X (*XtClass(widget)->core_class.resize) (widget);
X}
X
X
Xstatic void CanvasResize(widget)
XWidget widget;
X{
X CanvasWidget w = (CanvasWidget) widget;
X Display *dpy = XtDisplay(w);
X Window window = XtWindow(w);
X static unsigned int height = 0, width = 0;
X
X if (XtIsRealized(widget) &&
X (height != w->core.height || width != w->core.width))
X {
X height = w->core.height;
X width = w->core.width;
X
X CanvasChangeSize(widget);
X
X MakeTasksStale();
X WasteTasks();
X
X if (w->canvas.pixmap)
X XFreePixmap(dpy, w->canvas.pixmap);
X
X w->canvas.pixmap = XCreatePixmap(dpy, window, width, height,
X w->core.depth);
X if (!w->canvas.pixmap)
X {
X eprintf("Insufficient space for pixmap");
X abort();
X }
X
X XFillRectangle(dpy, w->canvas.pixmap, w->canvas.clear_gc,
X 0, 0, width, height);
X }
X}
X
X
X/*ARGSUSED*/
Xstatic void CanvasRedisplay(widget, event, region)
XWidget widget;
XXExposeEvent *event;
XRegion region; /* unused */
X{
X CanvasWidget w = (CanvasWidget) widget;
X Display *dpy = XtDisplay(w);
X Window window = XtWindow(w);
X
X /* Reset any previously drawn zoom box */
X CanvasMoveBox(w, -1, -1, -1, -1);
X
X if (XtIsRealized(widget) == False)
X return;
X
X if (event == NULL)
X XCopyArea(dpy, w->canvas.pixmap, window, w->canvas.normal_gc,
X 0, 0, w->core.width, w->core.height, 0, 0);
X else
X XCopyArea(dpy, w->canvas.pixmap, window, w->canvas.normal_gc,
X event->x, event->y, (unsigned) event->width,
X (unsigned) event->height, event->x, event->y);
X}
X
X
Xstatic void CanvasRegister(widget, resp, offset)
XWidget widget;
XRegistrationResponse *resp;
Xunsigned long *offset;
X{
X CanvasWidget w = (CanvasWidget) widget;
X Display *dpy = XtDisplay(w);
X Task *task;
X extern Widget menu;
X extern void ByteSwapLong();
X extern void DroneRegister();
X char hostname[32];
X
X /* Copy hostname before we get a chance to byteswap */
X strcpy(hostname, resp->hostname);
X
X if (resp->byte_order != 0x11223344)
X ByteSwapLong((char *) resp, sizeof(RegistrationResponse));
X
X DroneRegister(resp->window, hostname);
X
X task = AllocTask();
X task->window = resp->window;
X
X if (w->canvas.finished == True || w->canvas.paused == True)
X {
X /* If the widget is not currently drawing, add the new drone to the
X * wait list. */
X TaskNQ(waitQ, task);
X#ifdef DEBUG
X dprintf("Enqueued new drone (window=0x%x) on wait list\n",
X task->window);
X#endif
X }
X else
X {
X /* If the widget is actively drawing, give the drone a task and send
X * it on its way. */
X CanvasFillTask(widget, task);
X TaskNQ(runQ, task);
X if (SendTask(task) == False)
X eprintf("SendTask() failed\n");
X#ifdef DEBUG
X dprintf("Enqueued new drone (window=0x%x) on run list\n",
X task->window);
X#endif
X }
X
X /* select for DestroyNotify events on the drone's window */
X XSelectInput(dpy, task->window, StructureNotifyMask);
X
X /* unstipple draw & redraw menu items when 1st drone added */
X if (w->canvas.num_drones++ == 0)
X {
X (void) MenuChangeSensitivity(menu, MENU_DRAW_ITEM, True);
X (void) MenuChangeSensitivity(menu, MENU_REDRAW_ITEM, True);
X }
X *offset += PAD(sizeof(RegistrationResponse));
X}
X
X
X#define CHEEZY_OPTIMIZATION
X
Xvoid CanvasImageResponse(widget, resp, offset)
XWidget widget;
XImageResponse *resp;
Xunsigned long *offset;
X{
X CanvasWidget w = (CanvasWidget) widget;
X Display *dpy = XtDisplay(w);
X Window window = XtWindow(w);
X Task *task;
X#ifdef CHEEZY_OPTIMIZATION
X int ii;
X char *ptr;
X#else
X int x, y;
X#endif
X unsigned char *value;
X int num_colors = w->canvas.num_colors;
X long width = resp->width;
X long height = resp->height;
X
X if (resp->byte_order != 0x11223344)
X {
X#ifdef DEBUG
X dprintf("ImageResponse\n");
X dprintf(" byte_order: 0x%x\n", resp->byte_order);
X dprintf(" type: %d\n", resp->type);
X dprintf(" serial: %d\n", resp->serial);
X dprintf(" width: %d\n", resp->width);
X dprintf(" height: %d\n", resp->height);
X dprintf(" max_iter: %d\n", resp->max_iter);
X#endif
X eprintf("Incorrect byte ordering (0x%x)\n", resp->byte_order);
X abort();
X }
X if ((task = TaskDQ(runQ, (Window) NULL, resp->serial)) != NULL)
X {
X#ifdef DEBUG
X dprintf("Task located on the runQ\n");
X#endif
X /* dp points past the ImageResponse header */
X value = (unsigned char *) &resp[1];
X
X#ifdef CHEEZY_OPTIMIZATION
X if (num_colors != 256)
X for (ii = height * width, value += ii; ii >= 0; --ii, --value)
X *value %= num_colors;
X
X if (width == w->canvas.image->width)
X (void) memcpy(w->canvas.image->data, (char *) value,
X (int) (height * width));
X else
X {
X /* narrow ImageResponse - copy line at a time */
X ptr = w->canvas.image->data;
X for (ii = height; ii > 0; --ii, value += width,
X ptr += w->canvas.image->width)
X (void) memcpy(ptr, (char *) value, (int) width);
X }
X#else
X if (num_colors == 256)
X /* No need to perform modulus */
X for (y = 0; y < height; ++y)
X for (x = 0; x < width; ++x)
X XPutPixel(w->canvas.image, x, y, *(value++));
X else
X for (y = 0; y < height; ++y)
X for (x = 0; x < width; ++x)
X XPutPixel(w->canvas.image, x, y, *(value++) %
X num_colors);
X#endif
X
X XPutImage(dpy, w->canvas.pixmap, w->canvas.normal_gc,
X w->canvas.image, 0, 0, task->x, task->y, (unsigned) width,
X (unsigned) height);
X
X XCopyArea(dpy, w->canvas.pixmap, window,
X w->canvas.normal_gc, task->x, task->y, (unsigned) width,
X (unsigned) height, task->x, task->y);
X
X /* We need to save everything on the next zoom */
X w->canvas.needs_saving = True;
X }
X else
X {
X /* Was this a stale response from a drone? */
X if ((task = TaskDQ(staleQ, (Window) NULL, resp->serial)) == NULL)
X {
X eprintf("Received bad ImageResponse\n");
X abort();
X }
X#ifdef DEBUG
X dprintf("Task located on the staleQ\n");
X#endif
X }
X
X if (w->canvas.finished == False && w->canvas.paused == False)
X {
X CanvasFillTask(widget, task);
X
X#ifdef DEBUG
X dprintf("Sending following task to run queue:\n");
X PrintTask(task);
X#endif
X
X TaskNQ(runQ, task);
X if (SendTask(task) == False)
X eprintf("SendTask() failed\n");
X }
X else
X {
X
X#ifdef DEBUG
X dprintf("Sending drone 0x%x to the wait queue:\n", task->window);
X#endif
X
X TaskNQ(waitQ, task);
X }
X *offset += PAD(DATA_SIZE(width, height));
X}
X
X
X/***********************************************************/
X/******************** Action Procedures ********************/
X/***********************************************************/
X
X
X/*ARGSUSED*/
Xstatic void CanvasUnregister(widget, event, params, num_params)
XWidget widget;
XXEvent *event;
XString *params; /* unused */
XCardinal *num_params; /* unused */
X{
X CanvasWidget w = (CanvasWidget) widget;
X XDestroyWindowEvent *ev = (XDestroyWindowEvent *) event;
X Task *task;
X extern Widget menu;
X extern void DroneUnregister();
X
X#ifdef DEBUG
X dprintf("Drone (window=0x%x) has terminated:\n", ev->window);
X#endif
X
X /* update the drone control dialogbox */
X DroneUnregister(ev->window);
X
X /* remove task for window which was destroyed. */
X
X if ((task = TaskDQ(runQ, ev->window, (long) NULL)) != NULL)
X {
X /* Window's task structure was on the run list. The task is placed on
X * the zombie list here for later re-assigned to a new drone */
X
X#ifdef DEBUG
X dprintf("Task removed from run list\n");
X#endif
X
X TaskNQ(zombieQ, task);
X }
X else if ((task = TaskDQ(waitQ, ev->window, (long) NULL)) != NULL)
X {
X /* Window's task structure was on the wait list. Since it wasn't doing
X * anything (but waiting) when it terminated, we can simply purge it
X * from our lists. */
X
X#ifdef DEBUG
X dprintf("Task removed from wait list\n");
X#endif
X
X FreeTask(task);
X }
X else if ((task = TaskDQ(staleQ, ev->window, (long) NULL)) != NULL)
X {
X /* Window's task structure was on the stale list. Since it was
X * calculating a stale task when it terminated, we can simply purge it
X * from our lists. */
X
X#ifdef DEBUG
X dprintf("Task removed from stale list\n");
X#endif
X
X FreeTask(task);
X }
X else
X {
X eprintf("Task structure for drone (window=0x%x) not found!\n",
X ev->window);
X abort();
X }
X
X /* stipple draw and redraw menu items when last drone removed */
X if (--w->canvas.num_drones == 0)
X {
X (void) MenuChangeSensitivity(menu, MENU_DRAW_ITEM, False);
X (void) MenuChangeSensitivity(menu, MENU_REDRAW_ITEM, False);
X }
X}
X
X
X/*ARGSUSED*/
Xstatic void CanvasMessage(widget, event, params, num_params)
XWidget widget;
XXEvent *event;
XString *params; /* unused */
XCardinal *num_params; /* unused */
X{
X XPropertyEvent *ev = (XPropertyEvent *) event;
X char *msg;
X unsigned long msg_len;
X unsigned long offset;
X GenericMessage generic;
X static int read_ahead = 0;
X
X if (ev->atom != MAILBOX)
X {
X /* must have been some other property (handle as usual) */
X return;
X }
X
X if (ev->state != PropertyNewValue)
X {
X /* generally, ignore the PropertyDelete events. they are generated by
X * our destructive reads on the property and since we can't stop them
X * we must simply ignore them. */
X return;
X }
X
X /* The counter read_ahead will become greater than zero when multiple
X * messages are read from the property in response to a single
X * PropertyNotify event. By keeping track of how many messages we have
X * "read ahead" of the events, we do not attempt to read from an empty
X * property. */
X if (read_ahead-- > 0)
X return;
X
X if (RecvMsg(&msg, &msg_len) == False)
X {
X eprintf("RecvMsg() failed\n");
X return;
X }
X
X offset = 0;
X do
X {
X (void) memcpy((char *) &generic, &msg[offset], sizeof(GenericMessage));
X if (generic.byte_order != 0x11223344)
X ByteSwapLong((char *) &generic, 2 * sizeof(long));
X
X if (generic.type == REGISTRATION_RESPONSE)
X CanvasRegister(widget, (RegistrationResponse *) & msg[offset],
X &offset);
X else if (generic.type == IMAGE_RESPONSE)
X CanvasImageResponse(widget, (ImageResponse *) & msg[offset],
X &offset);
X else
X {
X eprintf("Unknown message type: %d\n", generic.type);
X abort();
X }
X ++read_ahead;
X } while (offset < msg_len);
X free(msg);
X}
X
X
Xstatic void CanvasMoveBox(w, x1, y1, x2, y2)
XCanvasWidget w;
Xint x1, y1;
Xint x2, y2;
X{
X Display *dpy = XtDisplay(w);
X Window window = XtWindow(w);
X static int last_x1 = -1, last_y1 = -1;
X static int last_x2 = -1, last_y2 = -1;
X static Boolean prev_box = False;
X int tmp;
X
X if (x1 == last_x1 && y1 == last_y1 && x2 == last_x2 && y2 == last_y2)
X return;
X
X if (prev_box)
X XDrawRectangle(dpy, window, w->canvas.xor_gc, last_x1, last_y1,
X (unsigned) (last_x2 - last_x1), (unsigned) (last_y2 - last_y1));
X
X /* Make sure x1 < x2 */
X if (x1 > x2)
X {
X tmp = x1;
X x1 = x2;
X x2 = tmp;
X }
X
X /* Make sure y1 < y2 */
X if (y1 > y2)
X {
X tmp = y1;
X y1 = y2;
X y2 = tmp;
X }
X
X last_x1 = x1;
X last_y1 = y1;
X last_x2 = x2;
X last_y2 = y2;
X
X if (x1 != x2 && y1 != y2)
X {
X XDrawRectangle(dpy, window, w->canvas.xor_gc, x1, y1,
X (unsigned) (x2 - x1), (unsigned) (y2 - y1));
X prev_box = True;
X }
X else
X {
X prev_box = False;
X }
X}
X
X
X/*ARGSUSED*/
Xstatic void CanvasBtnDown(widget, event, params, num_params)
XWidget widget;
XXEvent *event;
XString *params; /* unused */
XCardinal *num_params; /* unused */
X{
X CanvasWidget w = (CanvasWidget) widget;
X XButtonEvent *ev = (XButtonEvent *) & event->xbutton;
X
X
X w->canvas.x_from = ev->x;
X w->canvas.y_from = ev->y;
X
X CanvasMoveBox(w, w->canvas.x_from, w->canvas.y_from,
X w->canvas.x_from, w->canvas.y_from);
X}
X
X
X/*ARGSUSED*/
Xstatic void CanvasBtnUp(widget, event, params, num_params)
XWidget widget;
XXEvent *event;
XString *params; /* unused */
XCardinal *num_params; /* unused */
X{
X CanvasWidget w = (CanvasWidget) widget;
X XButtonEvent *ev = (XButtonEvent *) & event->xbutton;
X int tmp;
X extern Widget menu;
X
X w->canvas.x_to = IN_BOUNDS_X(w, ev->x);
X w->canvas.y_to = IN_BOUNDS_Y(w, ev->y);
X CanvasMoveBox(w, w->canvas.x_from, w->canvas.y_from, w->canvas.x_to,
X w->canvas.y_to);
X
X /* Make sure the final points are in "proper" order */
X
X /* Make sure w->canvas.x_from < w->canvas.x_to */
X if (w->canvas.x_from > w->canvas.x_to)
X {
X tmp = w->canvas.x_from;
X w->canvas.x_from = w->canvas.x_to;
X w->canvas.x_to = tmp;
X }
X
X /* Make sure w->canvas.y_from < w->canvas.y_to */
X if (w->canvas.y_from > w->canvas.y_to)
X {
X tmp = w->canvas.y_from;
X w->canvas.y_from = w->canvas.y_to;
X w->canvas.y_to = tmp;
X }
X
X /* stipple zoom menu item if NULL zoom range */
X if (w->canvas.y_from == w->canvas.y_to
X && w->canvas.x_from == w->canvas.x_to)
X (void) MenuChangeSensitivity(menu, MENU_ZOOM_ITEM, False);
X else
X (void) MenuChangeSensitivity(menu, MENU_ZOOM_ITEM, True);
X}
X
X
X/*ARGSUSED*/
Xstatic void CanvasMotion(widget, event, params, num_params)
XWidget widget;
XXEvent *event;
XString *params; /* unused */
XCardinal *num_params; /* unused */
X{
X CanvasWidget w = (CanvasWidget) widget;
X XMotionEvent *ev = (XMotionEvent *) & event->xmotion;
X
X CanvasMoveBox(w, w->canvas.x_from, w->canvas.y_from, IN_BOUNDS_X(w, ev->x),
X IN_BOUNDS_Y(w, ev->y));
X}
X
X
X/*ARGSUSED*/
Xstatic void CanvasQuit(widget, event, params, num_params)
XWidget widget; /* unused */
XXEvent *event; /* unused */
XString *params; /* unused */
XCardinal *num_params; /* unused */
X{
X extern void CleanupAndDie();
X
X CleanupAndDie();
X}
X
X
X/*ARGSUSED*/
Xstatic void CanvasReverse(widget, event, params, num_params)
XWidget widget; /* unused */
XXEvent *event; /* unused */
XString *params; /* unused */
XCardinal *num_params; /* unused */
X{
X extern Widget colormap_dialogbox;
X extern Rotation rotation_dir;
X
X if (rotation_dir == forward)
X rotation_dir = backward;
X else
X rotation_dir = forward;
X}
X
X
X/*ARGSUSED*/
Xstatic void CanvasStartStop(widget, event, params, num_params)
XWidget widget; /* unused */
XXEvent *event; /* unused */
XString *params; /* unused */
XCardinal *num_params; /* unused */
X{
X extern Boolean rotating;
X
X rotating = !rotating;
X}
X
X
X/***********************************************************/
X/******************** Public Procedures ********************/
X/***********************************************************/
X
X
Xvoid CanvasClear(widget)
XWidget widget;
X{
X CanvasWidget w = (CanvasWidget) widget;
X Display *dpy = XtDisplay(w);
X Window window = XtWindow(w);
X extern int iteration_limit;
X extern int task_width;
X extern int task_height;
X
X /* Reset any previously drawn zoom box */
X CanvasMoveBox(w, -1, -1, -1, -1);
X
X w->canvas.task_x = 0;
X w->canvas.task_y = 0;
X w->canvas.finished = False;
X w->canvas.paused = False;
X
X /* New iteration limit should now be observed */
X w->canvas.curr_limit = iteration_limit;
X
X /* Check and see if a new task size should now be observed */
X CanvasChangeTaskSize(widget, (unsigned int) task_width,
X (unsigned int) task_height);
X
X XFillRectangle(dpy, w->canvas.pixmap, w->canvas.clear_gc,
X 0, 0, w->core.width, w->core.height);
X
X XCopyArea(dpy, w->canvas.pixmap, window, w->canvas.normal_gc,
X 0, 0, w->core.width, w->core.height, 0, 0);
X}
X
X
Xvoid CanvasZoom(widget)
XWidget widget;
X{
X CanvasWidget w = (CanvasWidget) widget;
X double p_mid, q_mid;
X double x_zoom, y_zoom;
X int x_avg, y_avg;
X int width;
X int height;
X
X#ifdef DEBUG
X dprintf("p_lo=%.10G p_hi=%.10G p_inc=%.10G\n",
X w->canvas.p_lo, w->canvas.p_hi, w->canvas.p_inc);
X
X dprintf("q_lo=%.10G q_hi=%.10G q_inc=%.10G\n",
X w->canvas.q_lo, w->canvas.q_hi, w->canvas.q_inc);
X#endif
X
X x_avg = (w->canvas.x_from + w->canvas.x_to) / 2;
X y_avg = (w->canvas.y_from + w->canvas.y_to) / 2;
X
X p_mid = w->canvas.p_lo + w->canvas.p_inc * x_avg;
X q_mid = w->canvas.q_lo + w->canvas.q_inc * y_avg;
X
X width = w->canvas.x_to - w->canvas.x_from;
X height = w->canvas.y_to - w->canvas.y_from;
X
X x_zoom = (double) w->core.width / width;
X y_zoom = (double) w->core.height / height;
X
X if (w->canvas.retain_aspect_ratio)
X x_zoom = y_zoom = MIN(x_zoom, y_zoom);
X
X w->canvas.p_inc /= x_zoom;
X w->canvas.q_inc /= y_zoom;
X
X w->canvas.p_lo = p_mid - w->canvas.p_inc * w->core.width / 2;
X w->canvas.q_lo = q_mid - w->canvas.q_inc * w->core.height / 2;
X
X w->canvas.p_hi = w->canvas.p_lo + w->canvas.p_inc * (w->core.width - 1);
X w->canvas.q_hi = w->canvas.q_lo + w->canvas.q_inc * (w->core.height - 1);
X
X#ifdef DEBUG
X dprintf("p_lo=%.10G p_hi=%.10G p_inc=%.10G\n",
X w->canvas.p_lo, w->canvas.p_hi, w->canvas.p_inc);
X
X dprintf("q_lo=%.10G q_hi=%.10G q_inc=%.10G\n",
X w->canvas.q_lo, w->canvas.q_hi, w->canvas.q_inc);
X#endif
X}
X
X
Xvoid CanvasChangeSize(widget)
XWidget widget;
X{
X CanvasWidget w = (CanvasWidget) widget;
X double p_mid, q_mid;
X
X#ifdef DEBUG
X dprintf("p_lo=%.10G p_hi=%.10G p_inc=%.10G\n",
X w->canvas.p_lo, w->canvas.p_hi, w->canvas.p_inc);
X
X dprintf("q_lo=%.10G q_hi=%.10G q_inc=%.10G\n",
X w->canvas.q_lo, w->canvas.q_hi, w->canvas.q_inc);
X#endif
X
X p_mid = (w->canvas.p_hi + w->canvas.p_lo) / 2;
X q_mid = (w->canvas.q_hi + w->canvas.q_lo) / 2;
X
X w->canvas.p_inc = (double) (w->canvas.p_hi - w->canvas.p_lo) /
X (w->core.width - 1);
X w->canvas.q_inc = (double) (w->canvas.q_hi - w->canvas.q_lo) /
X (w->core.height - 1);
X
X if (w->canvas.retain_aspect_ratio)
X w->canvas.p_inc = w->canvas.q_inc =
X MAX(w->canvas.p_inc, w->canvas.q_inc);
X
X w->canvas.p_lo = p_mid - w->canvas.p_inc * w->core.width / 2;
X w->canvas.q_lo = q_mid - w->canvas.q_inc * w->core.height / 2;
X
X w->canvas.p_hi = w->canvas.p_lo + w->canvas.p_inc * (w->core.width - 1);
X w->canvas.q_hi = w->canvas.q_lo + w->canvas.q_inc * (w->core.height - 1);
X
X#ifdef DEBUG
X dprintf("p_lo=%.10G p_hi=%.10G p_inc=%.10G\n",
X w->canvas.p_lo, w->canvas.p_hi, w->canvas.p_inc);
X
X dprintf("q_lo=%.10G q_hi=%.10G q_inc=%.10G\n",
X w->canvas.q_lo, w->canvas.q_hi, w->canvas.q_inc);
X#endif
X
X w->canvas.task_x = 0;
X w->canvas.task_y = 0;
X w->canvas.finished = True;
X}
X
X
Xvoid CanvasFillTask(widget, task)
XWidget widget;
XTask *task;
X{
X CanvasWidget w = (CanvasWidget) widget;
X Task *unfinished;
X Task *zombie;
X Window saved_window;
X extern int task_width;
X extern int task_height;
X
X /* We need to save everything on the next zoom */
X w->canvas.needs_saving = True;
X
X /* Check first to see if any unfinished task should be completed */
X if ((unfinished = TaskDQ(unfinishedQ, (Window) NULL, (long) NULL)) != NULL)
X {
X /* save the window from the task structure */
X saved_window = task->window;
X
X /* copy in the info from the unfinished task */
X (void) memcpy((char *) task, (char *) unfinished, sizeof(Task));
X
X /* restore original window to task */
X task->window = saved_window;
X
X /* don't need this task anymore */
X FreeTask(unfinished);
X return;
X }
X
X /* Check next to see if any zombie task should be rejuvinated */
X if ((zombie = TaskDQ(zombieQ, (Window) NULL, (long) NULL)) != NULL)
X {
X /* save the window from the task structure */
X saved_window = task->window;
X
X /* copy in the info from the zombie task */
X (void) memcpy((char *) task, (char *) zombie, sizeof(Task));
X
X /* restore original window to task */
X task->window = saved_window;
X
X /* R.I.P. ex-zombie */
X FreeTask(zombie);
X return;
X }
X
X /* Otherwise, fill in the info for the next task... */
X
X task->serial = ++(w->canvas.serial);
X task->limit = w->canvas.curr_limit;
X task->method = w->canvas.method;
X
X /* If we are at the start of the canvas, check to see if we should update
X * the current task width and height. */
X if (w->canvas.task_x == 0 && w->canvas.task_y == 0)
X CanvasChangeTaskSize(widget, (unsigned int) task_width,
X (unsigned int) task_height);
X
X task->width = MIN(w->canvas.curr_task_width, w->core.width -
X w->canvas.task_x);
X task->height = MIN(w->canvas.curr_task_height, w->core.height -
X w->canvas.task_y);
X
X task->x = w->canvas.task_x;
X task->y = w->canvas.task_y;
X task->p_lo = w->canvas.p_lo + task->x * w->canvas.p_inc;
X task->p_hi = task->p_lo + (task->width - 1) * w->canvas.p_inc;
X task->q_lo = w->canvas.q_lo + task->y * w->canvas.q_inc;
X task->q_hi = task->q_lo + (task->height - 1) * w->canvas.q_inc;
X
X w->canvas.finished = False;
X
X w->canvas.task_x += w->canvas.curr_task_width;
X if (w->canvas.task_x >= w->core.width)
X {
X w->canvas.task_x = 0;
X w->canvas.task_y += w->canvas.curr_task_height;
X if (w->canvas.task_y >= w->core.height)
X {
X /* Reset for next drawing session */
X w->canvas.task_x = 0;
X w->canvas.task_y = 0;
X w->canvas.finished = True;
X }
X }
X}
X
X
Xvoid CanvasChangeTaskSize(widget, width, height)
XWidget widget;
Xunsigned int width;
Xunsigned int height;
X{
X CanvasWidget w = (CanvasWidget) widget;
X Display *dpy = XtDisplay(w);
X Screen *screen = XtScreen(w);
X
X /* no need to update if nothing changed */
X if (w->canvas.curr_task_width == width &&
X w->canvas.curr_task_height == height)
X return;
X
X if (w->canvas.image)
X XDestroyImage(w->canvas.image);
X
X w->canvas.image = XCreateImage(dpy, DefaultVisualOfScreen(screen),
X DefaultDepthOfScreen(screen), ZPixmap, 0, malloc(width * height),
X width, height, 8, 0);
X
X w->canvas.curr_task_width = width;
X w->canvas.curr_task_height = height;
X}
X
X
Xvoid CanvasChangeRetainAspect(widget)
XWidget widget;
X{
X CanvasWidget w = (CanvasWidget) widget;
X
X w->canvas.retain_aspect_ratio = !w->canvas.retain_aspect_ratio;
X}
X
X
Xvoid CanvasUnpause(widget)
XWidget widget;
X{
X CanvasWidget w = (CanvasWidget) widget;
X
X w->canvas.paused = False;
X}
X
X
Xvoid CanvasTouchCanvas(widget)
XWidget widget;
X{
X CanvasWidget w = (CanvasWidget) widget;
X
X w->canvas.needs_saving = TRUE;
X}
X
X
XBoolean CanvasNeedsSaving(widget)
XWidget widget;
X{
X CanvasWidget w = (CanvasWidget) widget;
X
X return (w->canvas.needs_saving);
X}
X
X
XBoolean CanvasSaveImage(fd, widget)
Xint fd;
XWidget widget;
X{
X CanvasWidget w = (CanvasWidget) widget;
X Display *dpy = XtDisplay(w);
X XImage *image;
X int image_height, image_width;
X int curr_y = 0;
X XWindowAttributes win_attrib;
X XWDFileHeader header;
X XColor *colors;
X char *name = "Chaos-Image";
X int name_len = strlen(name) + 1;
X unsigned long swap_test = 1;
X Boolean header_written = False;
X int ii;
X extern void ByteSwapShort();
X extern void ByteSwapLong();
X
X image_width = w->core.width;
X image_height = MAX_SAVE_IMAGE_SIZE / image_width;
X image_height = MIN(image_height, w->core.height);
X
X if (!XGetWindowAttributes(dpy, XtWindow(w), &win_attrib))
X {
X eprintf("CanvasSaveImage: cannot get attributes\n");
X return (False);
X }
X
X while (curr_y < w->core.height)
X {
X image = XGetImage(dpy, w->canvas.pixmap, 0, curr_y, image_width,
X image_height, AllPlanes, ZPixmap);
X
X if (header_written == False)
X {
X header_written = True;
X colors = GetColors(w->canvas.num_colors);
X
X header.header_size = (CARD32) sizeof(header) + name_len;
X header.file_version = (CARD32) XWD_FILE_VERSION;
X header.pixmap_format = (CARD32) ZPixmap;
X header.pixmap_depth = (CARD32) image->depth;
X header.pixmap_width = (CARD32) w->core.width;
X header.pixmap_height = (CARD32) w->core.height;
X header.xoffset = (CARD32) image->xoffset;
X header.byte_order = (CARD32) image->byte_order;
X header.bitmap_unit = (CARD32) image->bitmap_unit;
X header.bitmap_bit_order = (CARD32) image->bitmap_bit_order;
X header.bitmap_pad = (CARD32) image->bitmap_pad;
X header.bits_per_pixel = (CARD32) image->bits_per_pixel;
X header.bytes_per_line = (CARD32) image->bytes_per_line;
X header.visual_class = (CARD32) win_attrib.visual->class;
X header.red_mask = (CARD32) win_attrib.visual->red_mask;
X header.green_mask = (CARD32) win_attrib.visual->green_mask;
X header.blue_mask = (CARD32) win_attrib.visual->blue_mask;
X header.bits_per_rgb = (CARD32) win_attrib.visual->bits_per_rgb;
X header.colormap_entries = (CARD32) win_attrib.visual->map_entries;
X header.ncolors = w->canvas.num_colors;
X header.window_width = (CARD32) win_attrib.width;
X header.window_height = (CARD32) win_attrib.height;
X header.window_x = 0;
X header.window_y = 0;
X header.window_bdrwidth = (CARD32) win_attrib.border_width;
X
X if (*(char *) &swap_test)
X {
X ByteSwapLong((char *) &header, sizeof(XWDFileHeader));
X for (ii = 0; ii < w->canvas.num_colors; ++ii)
X {
X ByteSwapLong((char *) &colors[ii].pixel, sizeof(long));
X ByteSwapShort((char *) &colors[ii].red,
X 3 * sizeof(short));
X }
X }
X
X (void) write(fd, (char *) &header, sizeof(XWDFileHeader));
X (void) write(fd, name, name_len);
X (void) write(fd, (char *) colors, sizeof(XColor) *
X w->canvas.num_colors);
X free((char *) colors);
X }
X (void) write(fd, image->data, image->bytes_per_line * image->height);
X XDestroyImage(image);
X curr_y += image_height;
X if (curr_y + image_height > w->core.height)
X image_height = w->core.height - curr_y;
X }
X return (True);
X}
X
X
XBoolean CanvasLoadImage(fd, widget)
Xint fd;
XWidget widget;
X{
X CanvasWidget w = (CanvasWidget) widget;
X Display *dpy = XtDisplay(w);
X Screen *screen = XtScreen(w);
X XImage *image;
X char *image_data;
X XWDFileHeader header;
X XColor *colors;
X XSizeHints hints;
X unsigned int image_height, image_width, image_size;
X int curr_y = 0;
X int ii;
X unsigned long swap_test = 1;
X extern Colormap colormap;
X extern Widget top_level;
X extern void ColormapResetControls();
X Boolean resized = False;
X extern long lseek();
X
X (void) read(fd, (char *) &header, sizeof(XWDFileHeader));
X
X if (*(char *) &swap_test)
X ByteSwapLong((char *) &header, sizeof(XWDFileHeader));
X
X /* skip past name (at end of header) */
X (void) lseek(fd, (long) header.header_size, 0);
X
X colors = (XColor *) malloc((unsigned) (sizeof(XColor) * header.ncolors));
X (void) read(fd, (char *) colors, (int) (sizeof(XColor) * header.ncolors));
X
X if (*(char *) &swap_test)
X for (ii = 0; ii < header.ncolors; ++ii)
X {
X ByteSwapLong((char *) &colors[ii].pixel, sizeof(long));
X ByteSwapShort((char *) &colors[ii].red, 3 * sizeof(short));
X }
X
X PutColors(colors, (int) header.ncolors);
X StoreColormap(dpy, colormap);
X (void) free((char *) colors);
X
X /* since a new colormap has been loaded, remove the text from the colormap
X * dialogbox text input field and reset listbox. */
X ColormapResetControls();
X
X if (header.pixmap_width != w->core.width ||
X header.pixmap_height != w->core.height)
X {
X /* We need to resize the before we can load in the image */
X hints.width = header.pixmap_width;
X hints.height = header.pixmap_height;
X hints.flags = USSize;
X
X XSetNormalHints(dpy, XtWindow(top_level), &hints);
X
X XtConfigureWidget(top_level, top_level->core.x, top_level->core.y,
X header.pixmap_width, header.pixmap_height,
X top_level->core.border_width);
X
X resized = True;
X }
X
X image_width = header.pixmap_width;
X image_height = MAX_SAVE_IMAGE_SIZE / image_width;
X image_height = MIN(image_height, header.pixmap_height);
X image_size = PAD(image_width) * image_height;
X
X if ((image_data = malloc(image_size)) == NULL)
X {
X eprintf("Cannot malloc %d bytes\n", image_size);
X return (False);
X }
X
X image = XCreateImage(dpy, DefaultVisualOfScreen(screen),
X DefaultDepthOfScreen(screen), ZPixmap, 0, image_data,
X image_width, image_height, 32, 0);
X
X while (curr_y < w->core.height)
X {
X if (read(fd, image->data, image->bytes_per_line * image->height) < 0)
X {
X XDestroyImage(image);
X return (False);
X }
X
X XPutImage(dpy, w->canvas.pixmap, w->canvas.normal_gc, image,
X 0, 0, 0, curr_y, image_width, image_height);
X
X curr_y += image_height;
X if (curr_y + image_height > w->core.height)
X image->height = w->core.height - curr_y;
X }
X XDestroyImage(image);
X
X if (resized == False)
X /* slap the new pixmap up on the screen */
X CanvasRedisplay(widget, (XExposeEvent *) NULL, (Region) NULL);
X
X return (True);
X}
X
X
XBoolean CanvasSaveState(fd, widget)
Xint fd;
XWidget widget;
X{
X CanvasWidget w = (CanvasWidget) widget;
X CanvasSaveStateStruct package;
X unsigned long swap_test = 1;
X
X package.width = (long) w->core.width;
X package.height = (long) w->core.height;
X package.task_x = (long) w->canvas.task_x;
X package.task_y = (long) w->canvas.task_y;
X package.limit = (long) w->canvas.curr_limit;
X package.finished = (long) w->canvas.finished;
X package.curr_task_width = (long) w->canvas.curr_task_width;
X package.curr_task_height = (long) w->canvas.curr_task_height;
X
X /* do the necessary swapping before laying in the strings */
X if (*(char *) &swap_test)
X ByteSwapLong((char *) &package, sizeof(CanvasSaveStateStruct));
X
X (void) sprintf(package.p_lo, "%.20G", w->canvas.p_lo);
X (void) sprintf(package.p_hi, "%.20G", w->canvas.p_hi);
X (void) sprintf(package.q_lo, "%.20G", w->canvas.q_lo);
X (void) sprintf(package.q_hi, "%.20G", w->canvas.q_hi);
X (void) sprintf(package.p_inc, "%.20G", w->canvas.p_inc);
X (void) sprintf(package.q_inc, "%.20G", w->canvas.q_inc);
X
X (void) write(fd, (char *) &package, sizeof(CanvasSaveStateStruct));
X return (True);
X}
X
X
XBoolean CanvasLoadState(fd, widget)
Xint fd;
XWidget widget;
X{
X CanvasWidget w = (CanvasWidget) widget;
X CanvasSaveStateStruct package;
X unsigned long swap_test = 1;
X extern void SettingsSetLimit();
X
X (void) read(fd, (char *) &package, sizeof(CanvasSaveStateStruct));
X
X /* grab the strings before doing the necessary swapping */
X w->canvas.p_lo = atof(package.p_lo);
X w->canvas.p_hi = atof(package.p_hi);
X w->canvas.q_lo = atof(package.q_lo);
X w->canvas.q_hi = atof(package.q_hi);
X w->canvas.p_inc = atof(package.p_inc);
X w->canvas.q_inc = atof(package.q_inc);
X
X if (*(char *) &swap_test)
X ByteSwapLong((char *) &package, sizeof(CanvasSaveStateStruct));
X
X w->core.width = (Dimension) package.width;
X w->core.height = (Dimension) package.height;
X w->canvas.task_x = (short) package.task_x;
X w->canvas.task_y = (short) package.task_y;
X w->canvas.curr_limit = (short) package.limit;
X w->canvas.finished = (Boolean) package.finished;
X
X /* We don't need to save everything again unless we change something */
X w->canvas.needs_saving = False;
X
X /* Pause until told to restart drawing */
X w->canvas.paused = True;
X
X /* Update the current limit in the settings dialogbox */
X SettingsSetLimit((int) package.limit);
X
X CanvasChangeTaskSize(widget, (unsigned int) package.curr_task_width,
X (unsigned int) package.curr_task_height);
X
X return (True);
X}
END_OF_FILE
if test 37474 -ne `wc -c <'widgets/Canvas.c'`; then
echo shar: \"'widgets/Canvas.c'\" unpacked with wrong size!
fi
# end of 'widgets/Canvas.c'
fi
if test -f 'widgets/Label.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'widgets/Label.c'\"
else
echo shar: Extracting \"'widgets/Label.c'\" \(6500 characters\)
sed "s/^X//" >'widgets/Label.c' <<'END_OF_FILE'
X/*
X * Copyright (c) Ken W. Marks 1989, 1990.
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <X11/IntrinsicP.h>
X#include <X11/StringDefs.h>
X#include <Chaos.h>
X#include <LocalDefs.h>
X#include <LabelP.h>
X
X#define LABEL_ALLOC_COUNT 10
X
Xstatic void LabelInitialize();
Xstatic void LabelRedisplay();
Xstatic void LabelDestroy();
X
X#define offset(field) XtOffset(LabelWidget, field)
X
Xstatic XtResource resources[] = {
X {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
X offset(label.foreground), XtRString, "XtDefaultForeground"},
X {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
X offset(label.font), XtRString, "chaos-bold"},
X {XtNlabel, XtCLabel, XtRString, sizeof(String),
X offset(label.label), XtRString, NULL},
X {XtNinternalWidth, XtCWidth, XtRDimension, sizeof(Dimension),
X offset(label.internal_width), XtRImmediate, (caddr_t) 4},
X {XtNinternalHeight, XtCHeight, XtRDimension, sizeof(Dimension),
X offset(label.internal_height), XtRImmediate, (caddr_t) 2},
X};
X
X#define superclass (&simpleClassRec)
X
XLabelClassRec labelClassRec = {
X {
X /* core_class fields */
X /* superclass */ (WidgetClass) superclass,
X /* class_name */ "Label",
X /* widget_size */ sizeof(LabelRec),
X /* class_initialize */ NULL,
X /* class_part_initialize */ NULL,
X /* class_inited */ FALSE,
X /* initialize */ LabelInitialize,
X /* initialize_hoo */ NULL,
X /* realize */ XtInheritRealize,
X /* actions */ NULL,
X /* num_actions */ 0,
X /* resources */ resources,
X /* num_resources */ XtNumber(resources),
X /* xrm_class */ NULLQUARK,
X /* compress_motion */ TRUE,
X /* compress_exposure */ TRUE,
X /* compress_enterleave */ TRUE,
X /* visible_interest */ FALSE,
X /* destroy */ LabelDestroy,
X /* resize */ NULL,
X /* expose */ LabelRedisplay,
X /* set_values */ NULL,
X /* set_values_hook */ NULL,
X /* set_values_almost */ XtInheritSetValuesAlmost,
X /* get_values_hook */ NULL,
X /* accept_focus */ NULL,
X /* version */ XtVersion,
X /* callback_private */ NULL,
X /* tm_table */ NULL,
X /* query_geometry */ NULL,
X /* display_accelerator */ XtInheritDisplayAccelerator,
X /* extension */ NULL
X },
X {
X /* Simple class fields initialization */
X /* change_sensitive */ XtInheritChangeSensitive
X }
X};
X
XWidgetClass labelWidgetClass = (WidgetClass) & labelClassRec;
X
X
X/************************************************************/
X/******************** Private Procedures ********************/
X/************************************************************/
X
X
Xstatic void LabelGetGC(w)
XLabelWidget w;
X{
X XGCValues values;
X
X values.foreground = w->label.foreground;
X values.background = w->core.background_pixel;
X values.font = w->label.font->fid;
X
X w->label.normal_gc = XtGetGC((Widget) w, (unsigned) GCForeground |
X GCBackground | GCFont, &values);
X}
X
X
Xstatic void LabelSetSize(w)
XLabelWidget w;
X{
X XtWidgetGeometry my_request;
X char *label = w->label.label;
X char *start = label;
X char *end = label;
X int line_width;
X
X w->label.label_len = strlen(label);
X w->label.num_lines = 0;
X w->label.label_width = 0;
X
X while (1)
X {
X if (*end == '\0' || *end == '\n' || (*end == '\\' && end[1] == 'n'))
X {
X if (w->label.num_lines >= w->label.num_lines_alloced)
X {
X w->label.num_lines_alloced += LABEL_ALLOC_COUNT;
X w->label.line_start =
X (int *) realloc((char *) w->label.line_start,
X w->label.num_lines_alloced * sizeof(int));
X w->label.line_len = (int *) realloc((char *) w->label.line_len,
X w->label.num_lines_alloced * sizeof(int));
X }
X w->label.line_start[w->label.num_lines] = (int) (start - label);
X w->label.line_len[w->label.num_lines] = (int) (end - start);
X
X line_width = (end - start) * w->label.char_width;
X if (line_width > w->label.label_width)
X w->label.label_width = line_width;
X w->label.num_lines++;
X if (*end == '\0')
X break;
X if (*end != '\n')
X ++end;
X start = end + 1;
X }
X ++end;
X }
X
X w->label.label_height = w->label.num_lines * w->label.char_height;
X
X my_request.request_mode = CWWidth | CWHeight;
X my_request.width = w->label.label_width + 2 * w->label.internal_width;
X my_request.height = w->label.label_height + 2 * w->label.internal_height;
X
X XtMakeGeometryRequest((Widget) w, &my_request, NULL);
X}
X
X
X/* ARGSUSED */
Xstatic void LabelInitialize(request, new)
XWidget request, new;
X{
X LabelWidget w = (LabelWidget) new;
X XFontStruct *fs = w->label.font;
X
X if (w->label.label == NULL)
X {
X eprintf("XtNLabel not set\n");
X abort();
X }
X
X w->label.label = STRCOPY(w->label.label);
X w->label.num_lines_alloced = LABEL_ALLOC_COUNT;
X w->label.line_start = (int *) malloc(LABEL_ALLOC_COUNT * sizeof(int));
X w->label.line_len = (int *) malloc(LABEL_ALLOC_COUNT * sizeof(int));
X w->label.char_height = fs->max_bounds.ascent + fs->max_bounds.descent;
X w->label.char_width = fs->max_bounds.width;
X w->label.label_x = w->label.internal_width;
X w->label.label_y = w->label.internal_height + fs->max_bounds.ascent;
X
X LabelGetGC(w);
X LabelSetSize(w);
X}
X
X
X/* ARGSUSED */
Xstatic void LabelRedisplay(widget, event, region)
XWidget widget;
XXEvent *event;
XRegion region;
X{
X LabelWidget w = (LabelWidget) widget;
X Display *dpy = XtDisplay(w);
X Window window = XtWindow(w);
X Position line_y = w->label.label_y;
X int *line_start = w->label.line_start;
X int *line_len = w->label.line_len;
X char *label;
X int ii;
X
X if (XtIsRealized(widget) == False)
X return;
X
X for (ii = 0; ii < w->label.num_lines; ++ii)
X {
X label = &(w->label.label[*line_start]);
X
X XDrawImageString(dpy, window, w->label.normal_gc, w->label.label_x,
X line_y, label, *line_len);
X
X line_y += w->label.char_height;
X ++line_start;
X ++line_len;
X }
X}
X
X
Xstatic void LabelDestroy(widget)
XWidget widget;
X{
X LabelWidget w = (LabelWidget) widget;
X
X XtReleaseGC(widget, w->label.normal_gc);
X}
X
X
X/***********************************************************/
X/******************** Public Procedures ********************/
X/***********************************************************/
X
X
Xvoid LabelChangeLabel(widget, label)
XWidget widget;
Xchar *label;
X{
X LabelWidget w = (LabelWidget) widget;
X
X if (label == NULL)
X {
X eprintf("Label may not be NULL\n");
X abort();
X }
X
X free(w->label.label);
X w->label.label = STRCOPY(label);
X LabelSetSize(w);
X LabelRedisplay(widget, (XEvent *) NULL, (Region) NULL);
X}
END_OF_FILE
if test 6500 -ne `wc -c <'widgets/Label.c'`; then
echo shar: \"'widgets/Label.c'\" unpacked with wrong size!
fi
# end of 'widgets/Label.c'
fi
echo shar: End of archive 1 \(of 10\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 10 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
dan
----------------------------------------------------
O'Reilly && Associates argv at sun.com / argv at ora.com
Opinions expressed reflect those of the author only.
More information about the Comp.sources.x
mailing list