ken@uunet.UU.NET (Ken Marks (x2425)) (08/21/90)
Submitted-by: balr!panasun!ken@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@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@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@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@sun.com / argv@ora.com Opinions expressed reflect those of the author only.