coolmail-1.3.orig/0042755000175000017500000000000006202712424013434 5ustar hallonhalloncoolmail-1.3.orig/system/0042755000175000017500000000000006027200337014760 5ustar hallonhalloncoolmail-1.3.orig/system/X11/0042755000175000017500000000000006030444576015342 5ustar hallonhalloncoolmail-1.3.orig/system/X11/colors.c0100644000175000017500000000556606027674660017023 0ustar hallonhallon/* colors.c * * By Byron C. Darrah, * 4/28/94, Thursday * Initialize some colors for drawings to use. * For now, this simply makes a color table for 27 colors -- a fixed set of * combinations of the three primary colors, R, G & B. In the future, color * should be enhanced to allow more efficient use of the colormap. Eg: * allocate only colors that are needed, and thereby be able allocate a range * of colors for objects to make use of shading. Another enhancement * could be to take over the colormap of the display entirely, so that * a color table is not needed for lookup of which pixel value has which * desired color. */ #include #include #include #include #include "colors.h" /*---------------------------------------------------------------------------*/ typedef struct { unsigned short red, green, blue; } d_color_t; d_color_t d_colortab[16] = { { 0, 0, 0}, /* Black */ {32768, 0, 0}, /* Dark red */ { 0, 32768, 0}, /* Dark green */ { 0, 0, 32768}, /* Dark blue */ {16384, 16384, 0}, /* Dark brown */ {32768, 0, 32768}, /* Dark magenta */ { 0, 32768, 32768}, /* Dark cyan */ {21845, 21845, 21845}, /* Dark grey */ {43690, 43690, 43690}, /* Light grey */ {65535, 0, 0}, /* Red */ { 0, 65525, 0}, /* Green */ { 0, 0, 65535}, /* Blue */ {32768, 32768, 0}, /* Brown */ {65535, 0, 65535}, /* Magenta */ { 0, 65535, 65535}, /* Cyan */ {65535, 65535, 65535} /* White */ }; /*---------------------------------------------------------------------------*/ /* Allocate colors and build a lookup table for them, so that each time * this program is run, it may get different pixel values for the requested * colors, but the index to these colors in the color table will be the * same. */ int init_colors(Display *disp, unsigned long color_table[], int color) { Colormap cmap; XColor request_color = {0, 0, 0, 0, 0, 0}; int i; cmap = DefaultColormap(disp, DefaultScreen(disp)); for(i = 0; i < NUMCOLORS; i++) { if(color) { request_color.red = d_colortab[i].red; request_color.green = d_colortab[i].green; request_color.blue = d_colortab[i].blue; if(!XAllocColor(disp, cmap, &request_color)) fprintf(stderr, "colors: Bad color allocated.\n"); color_table[i] = request_color.pixel; } else { color_table[i] = ( (d_colortab[i].red || d_colortab[i].green || d_colortab[i].blue) ? XWhitePixel(disp, DefaultScreen(disp)) : XBlackPixel(disp, DefaultScreen(disp))); } } return(0); } /*---------------------------------------------------------------------------*/ coolmail-1.3.orig/system/X11/colors.h0100644000175000017500000000143006027666302017004 0ustar hallonhallon/* colors.h * * By Byron C. Darrah, * 4/28/94, Thursday * Initialize some colors for drawings to use. * For now, this simply makes a color table for 27 colors -- a fixed set of * combinations of the three primary colors, R, G & B. In the future, color * should be enhanced to allow more efficient use of the colormap. Eg: * allocate only colors that are needed, and thereby be able allocate a range * of colors for objects to make use of shading. Another enhancement * could be to take over the colormap of the display entirely, so that * a color table is not needed for lookup of which pixel value has which * desired color. */ #include #define NUMCOLORS 16 #define COLOR_ERROR 500 int init_colors(Display *disp, unsigned long *color_table, int color); coolmail-1.3.orig/system/X11/display_list.c0100644000175000017500000003747006030444023020177 0ustar hallonhallon/* display_list.c * * By Byron C. Darrah * 4/28/94, Thursday * * This module is for actually drawing a prepared list of polygons into a * window on a screen. */ /* Added Sound support: Randall K. Sharpe 09-01-95 */ #include #include #include #include #include #include #include /* #include #include */ #define DISPLAY_LIST_MODULE #include "colors.h" #include "../../display_list.h" #define DEFAULT_GFX_WIDTH 100 #define DEFAULT_GFX_HEIGHT 125 /* The origin is an offset from (0, 0). If the default width and * height are not used, the default origin will automatically * be adjusted as well. */ #define DEFAULT_X_ORIGIN 52 #define DEFAULT_Y_ORIGIN 40 extern char command_str[]; /* Hack to let coolmail use X resource mgr */ extern char mailfile_str[]; /* to obtain the command and mail file. */ extern unsigned int frames; #ifdef AUDIO extern char *sndfile; /* same hack as above */ extern int cool_vol; void audio_beep(void); #endif unsigned long color_table[NUMCOLORS]; int color_mode = 1; Widget toplevel, main_gfx_w; Pixmap draw_pixbuff, refresh_pixbuff; GC main_gfx_gc; XtAppContext xtcontext; char TimedOut = TRUE; char Resized = FALSE; char Selected = FALSE; const char *timeout_property = "TimerExpiration"; Atom xa_timeout; void disp_expose_handler(Widget w, caddr_t client_data, XEvent *event); void disp_config_handler(Widget w, caddr_t client_data, XEvent *event); void disp_select_handler(Widget w, caddr_t client_data, XEvent *event); void disp_nomask_handler(Widget w, caddr_t client_data, XEvent *event); void disp_timeout_handler(XtPointer client_data, XtIntervalId *id); void disp_refresh(void); void disp_config(void); int put_points(polygon_t *cur_poly); int disp_checkgc(char *str); /*---------------------------------------------------------------------------*/ /*--------------------------- EXPORTED FUNCTIONS ----------------------------*/ /*---------------------------------------------------------------------------*/ /* disp_init initializes the graphics output window and the drawing * area buffer (ie: scratch pixmap) */ void disp_init(int *argc, char *argv[], int color) { Arg wargs[2]; XGCValues gcv; /* Initialize the X Intrinsics */ toplevel = XtInitialize(argv[0], "Coolmail", NULL, 0, argc, argv); disp_config(); /* Make use of X Resources, if any */ /* Create a widgit so we can draw in it's window. */ /* First, set arguments for the size of the widget */ XtSetArg(wargs[0], XtNwidth, (Dimension) DEFAULT_GFX_WIDTH); XtSetArg(wargs[1], XtNheight, (Dimension) DEFAULT_GFX_HEIGHT); /* Now create the widget -- Any plain old widget will do, so use * a regular "widgetClass" widget. */ main_gfx_w = XtCreateManagedWidget("picture", widgetClass, toplevel, wargs, 2); /* Realize the widget tree */ XtRealizeWidget(toplevel); /* Now find out what geometry was ACTUALLY used */ disp_getsize(&Gfx_Width, &Gfx_Height); /* Set size variables and allocate memory for drawing */ disp_setsize(Gfx_Width, Gfx_Height); /* Allocate a bunch of colors */ if(color == 0) color_mode = 0; init_colors(XtDisplay(main_gfx_w), color_table, color_mode); /* Create the graphics context for the main_gfx widget */ main_gfx_gc = XCreateGC(XtDisplay(main_gfx_w), XtWindow(main_gfx_w), 0, &gcv); XSetFillRule(XtDisplay(main_gfx_w), main_gfx_gc, EvenOddRule); /* Register event handlers to handle exposures, resizes, and * mouse clicks. */ XtAddEventHandler(main_gfx_w, ExposureMask, FALSE, (XtEventHandler)disp_expose_handler, NULL); XtAddEventHandler(main_gfx_w, StructureNotifyMask, FALSE, (XtEventHandler)disp_config_handler, NULL); XtAddEventHandler(main_gfx_w, ButtonPressMask, FALSE, (XtEventHandler)disp_select_handler, NULL); XtAddEventHandler(main_gfx_w, NoEventMask, True, (XtEventHandler)disp_nomask_handler, NULL); xa_timeout = XInternAtom(XtDisplay(main_gfx_w), timeout_property, FALSE); } /*---------------------------------------------------------------------------*/ /* Hack to use the resource manager to optionally set the value of * some variables that we're not really supposed to know about */ void disp_config(void) { char *str; Boolean mono = False; XtResource mailcmd = {"mailCommand", "MailCommand", XtRString, sizeof(str), 0, XtRString, command_str}; XtResource mailfile = {"inbox", "Inbox", XtRString, sizeof(str), 0, XtRString, mailfile_str}; XtResource monoflag = {"monochrome", "Monochrome", XtRBoolean, sizeof(mono), 0, XtRBoolean, &mono}; XtResource frmcount = {"frameCount", "FrameCount", XtRInt, sizeof(frames), 0, XtRInt, &frames}; #ifdef AUDIO XtResource soundfile = {"soundFile", "SoundFile", XtRString, sizeof(str), 0, XtRString, sndfile}; XtResource volume = {"volume", "Volume", XtRInt, sizeof(cool_vol), 0, XtRInt, &cool_vol}; #endif XtGetApplicationResources(toplevel, &str, &mailcmd, 1, NULL, 0); strcpy(command_str, str); XtGetApplicationResources(toplevel, &str, &mailfile, 1, NULL, 0); strcpy(mailfile_str, str); XtGetApplicationResources(toplevel, &mono, &monoflag, 1, NULL, 0); if (mono) color_mode = 0; XtGetApplicationResources(toplevel, &frames, &frmcount, 1, NULL, 0); if (frames < 2) frames = 2; #ifdef AUDIO XtGetApplicationResources(toplevel, &str, &soundfile, 1, NULL, 0); if(str) sndfile = (char *)strdup(str); XtGetApplicationResources(toplevel, &cool_vol, &volume, 1, NULL, 0); if (cool_vol < 0) cool_vol = 0; else if (cool_vol > 100) cool_vol = 100; #endif } /*---------------------------------------------------------------------------*/ /* This can be filled in later -- for Unix systems, it is not crucial to * deallocate everything explicitly before exitting, since the OS will * reclaim resources automatically. */ void disp_end(void) { ; } /*---------------------------------------------------------------------------*/ /* This is the exported function that is called to actually display a list of * polygons. */ void disp_polygons(polygon_node_t *first_pnode) { polygon_node_t *curnode; polygon_t *cur_poly; /* Clear the drawing area before painting into it */ XSetForeground(XtDisplay(main_gfx_w), main_gfx_gc, BlackPixelOfScreen(XtScreen(main_gfx_w))); XFillRectangle(XtDisplay(main_gfx_w), draw_pixbuff, main_gfx_gc, 0, 0, Gfx_Width, Gfx_Height); /* Now draw each polygon */ for(curnode = first_pnode; curnode; curnode = curnode->next) { cur_poly = curnode->polygon; /* Skip all polygons not in front of the focus (origin) */ if (curnode->k <= 0.0) break; XSetForeground(XtDisplay(main_gfx_w), main_gfx_gc, color_table[cur_poly->color]); XFillPolygon(XtDisplay(main_gfx_w), draw_pixbuff, main_gfx_gc, (XPoint *)(cur_poly->int_points), cur_poly->npoints, Convex, CoordModeOrigin); if(!color_mode) /* Draw the outline of the polygon */ { XSetForeground(XtDisplay(main_gfx_w), main_gfx_gc, BlackPixelOfScreen(XtScreen(main_gfx_w))); XDrawLines(XtDisplay(main_gfx_w), draw_pixbuff, main_gfx_gc, (XPoint *)(cur_poly->int_points), cur_poly->npoints, CoordModeOrigin); XDrawLine(XtDisplay(main_gfx_w), draw_pixbuff, main_gfx_gc, (int)(cur_poly->int_points[0].x), (int)(cur_poly->int_points[0].y), (int)(cur_poly->int_points[cur_poly->npoints-1].x), (int)(cur_poly->int_points[cur_poly->npoints-1].y)); } } /* Copy the drawing from the drawing buffer to the refresh buffer */ XCopyArea(XtDisplay(main_gfx_w), draw_pixbuff, refresh_pixbuff, main_gfx_gc, 0, 0, Gfx_Width, Gfx_Height, 0, 0); disp_refresh(); } /*---------------------------------------------------------------------------*/ /* Pause execution until graphics processing has caught up. */ void disp_sync(void) { XSync(XtDisplay(main_gfx_w), 0); } /*---------------------------------------------------------------------------*/ /* This function is called to freeze the display. * It returns when either: (1) the specified interval (in milliseconds) * has expired, (2) the display area is selected with the mouse, or * (3) the window is resized. Note that another timer even is not requested * if an earlier requesten one has not yet occurred. */ int disp_freeze(unsigned long interval) { XEvent event; if (TimedOut && interval > 0) /* Have at most one TimeOut at a time */ { TimedOut = FALSE; /* Critical - do not move this out of the `if' */ XtAddTimeOut(interval, disp_timeout_handler, NULL); } /* Enter the endless event loop */ while (!((interval > 0 && TimedOut) || Selected || Resized)) { XtNextEvent(&event); switch (event.type) { case ClientMessage: disp_nomask_handler(main_gfx_w, NULL, &event); break; default: XtDispatchEvent(&event); } } if (interval > 0 && TimedOut) return (TIMEOUT); else if (Resized) {Resized = FALSE; return (RESIZE);} else {Selected = FALSE; return (SELECTION);} } /*---------------------------------------------------------------------------*/ void disp_bell(void) { /* HERE change this to go along with beep */ #ifdef AUDIO if (sndfile) /* play the soundfile */ audio_beep(); else /* no sound file chosen then use system bell */ XBell(XtDisplay(main_gfx_w), cool_vol); #else XBell(XtDisplay(main_gfx_w), 50); #endif } /*---------------------------------------------------------------------------*/ /* Perform operations necessary to change the size of the drawing area. * This involves changing the window size variables, as well as the * offset for the cartesian origin, and reallocating the pixmaps associated * with drawing and displaying. */ void disp_setsize(unsigned short width, unsigned short height) { static char first_time = TRUE; /* Check to see if setting the size is really necessary */ if (Gfx_Width == width && Gfx_Height == height && !first_time) return; Gfx_Width = width; Gfx_Height = height; disp_x_scale = ((float)Gfx_Width) / ((float)(DEFAULT_GFX_WIDTH)); disp_y_scale = ((float)Gfx_Height) / ((float)(DEFAULT_GFX_HEIGHT)); Gfx_X_Origin = (int)(0.5 + disp_x_scale * (double)DEFAULT_X_ORIGIN); Gfx_Y_Origin = (int)(0.5 + disp_y_scale * (double)DEFAULT_Y_ORIGIN); /* Free up the pixmaps (Unless they haven't yet been allocated!) */ if (first_time) first_time = FALSE; else { XFreePixmap(XtDisplay(main_gfx_w), draw_pixbuff); XFreePixmap(XtDisplay(main_gfx_w), refresh_pixbuff); } /* Allocate the draw_pixbuff memory for rendering into */ draw_pixbuff = XCreatePixmap(XtDisplay(main_gfx_w), DefaultRootWindow(XtDisplay(main_gfx_w)), Gfx_Width, Gfx_Height, DefaultDepthOfScreen(XtScreen(main_gfx_w))); /* Allocate the refresh_pixbuff for storing finished frames. This * Buffer will drive the actual display. */ refresh_pixbuff = XCreatePixmap(XtDisplay(main_gfx_w), DefaultRootWindow(XtDisplay(main_gfx_w)), Gfx_Width, Gfx_Height, DefaultDepthOfScreen(XtScreen(main_gfx_w))); } /*---------------------------------------------------------------------------*/ /* Get the current output window's size */ void disp_getsize(unsigned short *width, unsigned short *height) { Arg wargs[2]; XtSetArg(wargs[0], XtNwidth, width); XtSetArg(wargs[1], XtNheight, height); XtGetValues(main_gfx_w, wargs, 2); } /*---------------------------------------------------------------------------*/ /*------------------------ INTERNALLY USED FUNCTIONS ------------------------*/ /*---------------------------------------------------------------------------*/ /* Handle exposure of the VR area. * The display is simply refreshed. */ void disp_expose_handler(Widget w, caddr_t client_data, XEvent *event) { if (((XExposeEvent *)event)->count > 0) return; disp_refresh(); } /*---------------------------------------------------------------------------*/ /* This handler is invoked when the output window's structure has * changed. Check to see if the changes involved a window resizing. * If so, trip the Resized flag. */ void disp_config_handler(Widget w, caddr_t client_data, XEvent *event) { XConfigureEvent *config_event = (XConfigureEvent *) event; if (config_event->width != Gfx_Width || config_event->height != Gfx_Height) Resized = TRUE; } /*---------------------------------------------------------------------------*/ /* Handle mouse button presses in the display area. */ void disp_select_handler(Widget w, caddr_t client_data, XEvent *event) { Selected = TRUE; } /*---------------------------------------------------------------------------*/ /* Handle nonmaskable events, such as ClentMessage events. Currently, I * am only interested in timeout events, so I'll just ingore anything else. */ void disp_nomask_handler(Widget w, caddr_t client_data, XEvent *event) { switch(event->type) { case ClientMessage: if(event->xclient.message_type == xa_timeout) TimedOut = TRUE; break; default: break; } } /*---------------------------------------------------------------------------*/ /* Handle a timeout. Since Timeouts are not X events, we need to generate an * X event to wake up the X event loop, which is waiting for an X event * to tell it that something has happenned. */ void disp_timeout_handler(XtPointer client_data, XtIntervalId *id) { static XEvent dummy_event; dummy_event.type = ClientMessage; dummy_event.xclient.message_type = xa_timeout; dummy_event.xclient.format = 8; dummy_event.xclient.data.b[0] = (char) 0; XSendEvent(XtDisplay(main_gfx_w), XtWindow(main_gfx_w), FALSE, ExposureMask, &dummy_event); } /*---------------------------------------------------------------------------*/ /* Copy whatever is in the main_pixbuff to the display area */ void disp_refresh(void) { XCopyArea(XtDisplay(main_gfx_w), refresh_pixbuff, XtWindow(main_gfx_w), main_gfx_gc, 0, 0, Gfx_Width, Gfx_Height, 0, 0); XFlush(XtDisplay(main_gfx_w)); } /*---------------------------------------------------------------------------*/ /*--------------------------- DEBUGGING FUNCTIONS ---------------------------*/ /*---------------------------------------------------------------------------*/ /* Check that the gc is okay by using it to set the foreground color */ int disp_checkgc(char *str) { fprintf(stderr, "GC Check (%s) ... ", str); XSetForeground(XtDisplay(main_gfx_w), main_gfx_gc, BlackPixelOfScreen(XtScreen(main_gfx_w))); fprintf(stderr, "passed.\n"); return(1); } /*---------------------------------------------------------------------------*/ int put_points(polygon_t *cur_poly) { int i; for(i = 0; i < cur_poly->npoints; i++) { printf(" (%d, %d)\n", cur_poly->int_points[i].x, cur_poly->int_points[i].y); } return(0); } /*---------------------------------------------------------------------------*/ /* EOF: display_list.c */ coolmail-1.3.orig/COPYRIGHT0100644000175000017500000000205106030061261014713 0ustar hallonhallon Byron C. Darrah Email: US Postal Mail: 546 Prospectors Rd, Diamond Bar, CA 91765, USA. coolmail, v 1.0 30-Dec-1994 coolmail, v 1.1 06-Jan-1995 coolmail, v 1.2 09-Feb-1995 coolmail, v 1.3 19-Sep-1995 Copyright (C) 1994 Byron C. Darrah Copyright (C) 1995 Byron C. Darrah This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. For a copy of the GNU General Public License, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. The GNU General Public License is, as of this writing, also available at http://www.irsociety.com/webchat/gnu.html coolmail-1.3.orig/Coolmail.ad0100644000175000017500000000042506030445363015501 0ustar hallonhallon! Coolmail Application Defaults ! ! !coolmail.soundFile: /usr/local/lib/sounds/youvegotmail.au !coolmail.frameCount: 15 !coolmail.inbox: /var/spool/mail/username !coolmail.mailCommand: emacs -f rmail coolmail.monochrome: False coolmail*geometry: 76x84-2+2 coolmail.volume: 70 coolmail-1.3.orig/IAFA-PACKAGE0100644000175000017500000000104406030444736015111 0ustar hallonhallonTitle: coolmail Version: 1.3 Description: A mail notification utility with 3D animation for X Windows and un*x. It lets you know when you have mail, and can launch your mail reader when you click on it. Author: darrah@kaiwan.com (Byron C. Darrah) Maintained-by: darrah@kaiwan.com (Byron C. Darrah) Maintained-at: sunsite.unc.edu Platforms: Un*x, X Windows, C Copying-Policy: GNU General Public License Keywords: coolmail email mail notification biff xbiff mailbox xmailbox++ coolmail-1.3.orig/Makefile0100744000175000017500000000624006040402524015067 0ustar hallonhallon#!/usr/bin/make # Makefile for coolmail # ############################################################################ # # TO BUILD COOLMAIL: # ------------------ # (1) If necessary, edit CFLAGS, LINK, INCLUDES, LIB_DIRS, and BINDIR. # (2) Type `make' in this directory to build coolmail. # (3) Type `make install' in this directory to copy it to your BINDIR. # ############################################################################ # Uncomment this if CC is not in your environment. Change it if necessary. #CC = gcc # Please verify that the following six lines are correct. CFLAGS is # a set of options for your C compiler, LINK is the linker command you # want to use. (This may be your C compiler, because most C compilers # know how to invoke the linker.) INCLUDES is any include path that your # compiler should search in addition to its default paths. LIB_DIRS tells # your linker where to find the libraries it will need, and BINDIR and # MANDIR specify the places to install the binary executable and manpage # files for coolmail when you type `make install'. CFLAGS = LINK = $(CC) INCLUDES = -I/usr/X11R5/include LIB_DIRS = -L/usr/X11R6/lib BINDIR = /usr/local/bin MANDIR = /usr/local/man/man1 # Comment these out if you can't or don't want to use the digitized audio # feature. AUDIO = -DAUDIO AUDIO_MODULE = audio.o #### You really don't need to read past this point. #### LIBS = $(LIB_DIRS) -lXt -lX11 -lm -lXext COPTS = $(CFLAGS) $(AUDIO) all: coolmail # Done. new: rm -f *.o coolmail core clean: rm -f *.o core install: @if [ -w $(BINDIR) ] ; then \ echo "Attempting to install coolmail executable." ; \ if [ -f $(BINDIR)/coolmail ] ; then \ echo "Existing copy of coolmail will be OVERWRITTEN." ; \ fi; \ echo "cp coolmail $(BINDIR)/coolmail" ; \ cp coolmail $(BINDIR)/coolmail ; \ else \ echo "ERROR: Unable to write to $(BINDIR)." ; \ echo "Please check that it exists and that you have write access" ; \ echo "to it." ; \ fi; @if [ -w $(MANDIR) ] ; then \ echo "Attempting to install coolmail man page." ; \ echo "cp coolmail.man $(MANDIR)/coolmail.1" ; \ cp coolmail.man $(MANDIR)/coolmail.1 ; \ echo "OK. You may wish to update the whatis database" ; \ echo "for $(MANDIR)." ; \ else \ echo "ERROR: Unable to write to $(MANDIR)." ; \ echo "Please check that it exists and that you have write access" ; \ echo "to it." ; \ fi; coolmail: coolmail.o display_list.o render1.o colors.o $(AUDIO_MODULE) $(LINK) coolmail.o display_list.o render1.o colors.o $(AUDIO_MODULE)\ $(LIBS) -o coolmail display_list.o: system/X11/display_list.c display_list.h render1.h \ system/X11/colors.h $(CC) $(COPTS) $(INCLUDES) system/X11/display_list.c -c r1_sub.o: r1_sub.c display_list.h render1.h $(CC) $(COPTS) $(INCLUDES) r1_sub.c -c coolmail.o: coolmail.c mailbox.h render1.h $(CC) $(COPTS) $(INCLUDES) coolmail.c -c render1.o: render1.c display_list.h render1.h $(CC) $(COPTS) $(INCLUDES) render1.c -c colors.o: system/X11/colors.c system/X11/colors.h $(CC) $(COPTS) $(INCLUDES) system/X11/colors.c -c audio.o: audio.c $(CC) $(COPTS) $(INCLUDES) audio.c -c coolmail-1.3.orig/README0100644000175000017500000001123306027721651014316 0ustar hallonhallonWHAT IS COOLMAIL? This is. Coolmail is like xbiff -- it watches your inbox mail file and lets you know when you have mail. But unlike xbiff, it can launch your favorite mail utility when you click on it, and it has cool animated 3D graphics. I hope you like it. ------------------------------------------------------------------------------ BUILDING COOLMAIL is easy. Type: make - to build coolmail. make install - to install coolmail executable and man page. The BINDIR and MANDIR are defined in the Makefile, and are set to point to /usr/local areas. Most users will have to either change these, or become root before typing `make install'. Please see the Makefile for further documentation on this. Support for digitized sound is optional. By default, it is included. However, if you don't want this, or if your machine doesn't have a /dev/audio device, or if you get errors from make complaining about audio.c, you can remove this feature by commenting out the two lines near the top of the Makefile which define AUDIO and AUDIO_MODULE. PROBLEMS If you can run make with no errors, you can skip this section. If you have problems getting coolmail built with the options you want, please read on for some possibly helpful things to check. The environment variable CC must be defined to be an ANSI C compiler. You can define it before running make, or you can add a "CC=mycompiler" line to the makefile. The standard X libraries must be in the path searched by your linker. If they're not, find out where they are then either add the path to your LD_LIBRARY_PATH environment variable, or add it to the LIB_DIRS macro in the Makefile. The standard X header files must be in the path searched by your compiler. If they're not, find out where they are then add the path to the INCLUDES macro in the Makefile. For example, on DEC OSF1 systems, INCLUDES in the makefile should be set to -I/usr/include/X11, and LIB_DIRS should be set to -L/usr/lib/X11. (Thanks to Alasdair Allan for this information.) If you still have problems, please send me the usual details, including: A description of the symptom and when it occurs, what compiler and OS you used, including the version numbers, and where you got your copy of the coolmail sources. See the section on BUG REPORTS AND SUGGESTIONS below for more information. ------------------------------------------------------------------------------ Usage: coolmail [options] OPTIONS: -af filename Specifies an audio file (.au format) to use instead of the console bell. -e command Specifies a command (usually in quotes) which is used to invoke your favorite mail-reading program. -f filename Watch filename, instead of the default mail file, /var/spool/mail/. -fr n Number of frames to generate for each animation. Set to an appropriate value for your machine's. graphics performance. The default is 15. -h Print some help then exit. -int n Check mail every n seconds, instead of the default, 30 seconds. Note: Xbiff fans may use -update instead of -int. -mono Monochrome mode. -once Ring bell when new mail is first detected, but not when more new mail is detected. -v Verbose mode - Coolmail prints some information on startup. -vol n Value between 0 and 100 for the volume setting for both the console bell and the audio file. The default is 50. In addition, standard X intrinsic arguments are supported. ------------------------------------------------------------------------------ MUCH THANKS To the following beta testers: Mark Pettit and Paul Henson. To Randall Sharpe for the sound support patch, and to Dimitrios P. Bouras and William K. W. Cheung who developed the audio.c module used by Randal. Thanks Also to the many people who provided feedback (sometimes including interesting source code) on previously released versions of coolmail, including (but not limited to): Andrew Cook, Alasdair Allan, Joerg Mertin, Martijn Loots, and Ami Fischman. ------------------------------------------------------------------------------ BUG REPORTS AND SUGGESTIONS Please send bug reports and suggestions to me, Byron C. Darrah, darrah@kaiwan.com. If that address bounces, try bdarr@sed.hac.com. I would especially appreciate hearing about which platforms work or don't work with the audio support; I personally have only SPARC/SunOS and x86/linux systems available to me for testing. ------------------------------------------------------------------------------ coolmail-1.3.orig/README.changes0100644000175000017500000001200006031700204015700 0ustar hallonhalloncoolmail - A cool mail notification utility. By Byron C. Darrah Created: 15-Feb-1995, Wed ------------------------------------------------------------------------------- Version: 1.3 - 19-Sep-1995 Changes: - Added three new features based on many requests recieved by email. (Thanks again to everyone who sent feedback, even if your suggestion or request still hasn't been incorporated yet.) Coolmail can now play sound files as an alternative to ringing your console bell. See the -af and -vol options in the man page. Monochrome displays are now supported. See the -mono option in the man page. The number of animation frames generated is customizable. You can adjust it to get your desired animation speed and smoothness. Files changed: Changed: Makefile, README, coolmail.c, coolmail.man, colors.c, display_list.c, render1.c. Added: Coolmail.ad audio.c ------------------------------------------------------------------------------- Version: 1.2 - 9-Feb-1995 Changes: - Added some quick enhancements based on many requests recieved by email. (Thanks to everyone who sent feedback, even if your suggestion or request hasn't been incorporated yet.) Namely: Coolmail now behaves more intelligently if your mail reader doesn't empty the inbox: If your inbox contains unread mail, the flag will be up, and an envelope will appear. If your inbox contains old mail, the flag will be down but the envelope will still be there. I also added the -update option (an alias for -int for xbiff people) and a -v option (to print verbose information that v1.1 used to print but v1.2 doesn't print by default). Make clean and make new now remove core files. Added the "-once" command flag to optionally reduce how often coolmail rings the bell. There are many other good suggestions, but I'm short on time, so they will have to wait until the next release. Files changed: Changed: Makefile, README, coolmail.c, coolmail.man Added: TODO ------------------------------------------------------------------------------- Version: 1.1 - 6-Jan-1995 Changes: - AAAgh! I knew it! V1.0 had serious bugs. I should have tested more. Fixed a bug in Makefile. Fixed bugs in X resource handling, which caused coolmail to (a) sometimes lock up when spawning the child, and (b) bomb if resized while the mailbox was open. Added a `make install' command. Files changed: Changed: Makefile, README, coolmail.c, ------------------------------------------------------------------------------- Version: 1.0 - 30-Dec-1994 Changes: - Decided to place coolmail under the Gnu Public License (GPL). Files changed: Added: COPYRIGHT ------------------------------------------------------------------------------- Version: 0.92 - 30-Dec-1994 Changes: - Coolmail can now be resized after it is started. Eg: By a user using window manager operations. Files changed: Changed: coolmail.c, coolmail.man, display_list.h, render1.c, render1.h, display_list.c ------------------------------------------------------------------------------- Version: 0.91 - 10-Dec-1994 Changes: - Coolmail uses X resource manager to set the mail command and inbox if available. The resources coolmail now understands are: geometry, inbox, and mailCommand. - Clicking coolmail while your mail app. is open causes coolmail to check your inbox and raise/lower flag without waiting for the next interval. - Further improved animation by rendevouzing the completion of animation with launching of the mail command. - The images are now scaled to the initial window geometry instead of always the same size. Files changed: Changed: display_list.c, display_list.h, render1.c Added: coolmail.man ------------------------------------------------------------------------------- Version: 0.9 - 19-Oct-1994 Changes: - Coolmail now watches the inbox even while visiting your mail utility. - The mailbox "post" is now (properly) wood colored. - Smoother animation due to XFlush now being used with every window refresh. - No more zombie processes under Linux - Added this README.changes file. - Wrote a new README file. - Changed makefile.X11 to Makefile so now you simply type "make" to build coolmail. - Makefile no longer assumes you use gcc but uses CC from your environment. Files changed: Deleted: makefile.X11 (changed to Makefile) Added: README.changes, Makefile Changed: coolmail.c, render1.h, display_list.c, colors.c ------------------------------------------------------------------------------- coolmail-1.3.orig/TODO0100644000175000017500000000062106027722120014115 0ustar hallonhallonHere are some items on my "todo" list for future versions of coolmail: - Add support for using coolmail to launch other commands besides just mail, including graphics that represent other things besides a mailbox. - Change the viewing angle of the mailbox so that the envelope is more visible even when the mailbox is in it's "closed" position. - Enhance the graphic appearance of the mailbox. coolmail-1.3.orig/audio.c0100644000175000017500000001450206030443702014675 0ustar hallonhallon/* * Copyright (c) 1994,1995 Dimitrios P. Bouras and William K. W. Cheung * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name of the X Consortium shall not be * used in advertising or otherwise to promote the sale, use or other dealings * in this Software without prior written authorization from the X Consortium. * * Derived from the MIT X11R5 xbiff, written by Jim Fulton, which is * copyrighted (c) 1988 X Consortium. * * Mailbox XPM additions-modifications: Dimitrios P. Bouras * Audio support and XPM icon animation: William K. W. Cheung * Derived from xmailbox by Dimitrios P. Bouras and William K. W. Cheung * as well as volume by Sam Lantinga. The above copyright notice is * from Dimitros and William's file Mailbox.c in the xmailbox application. * modified and integrated into Coolmail: Randall K. Sharpe */ #include /* for stat() ** needs types.h ***/ #include /* for signal() */ #include /* for printing error messages */ #include /* for getting username */ #include /* for getenv() */ #include #include #include #include #include extern int cool_vol; extern char *sndfile; /* I am only doing sun audio -- RKS */ /* Adapted from */ typedef unsigned u_32; /* we assume sizeof(unsigned) = 4 */ typedef struct { u_32 magic; /* magic number */ u_32 hdr_size; /* size of this header */ u_32 data_size; /* length of data (optional) */ u_32 encoding; /* data encoding format */ u_32 sample_rate; /* samples per second */ u_32 channels; /* number of interleaved channels */ } Audio_filehdr; #ifdef linux #include #define DEV_MIXER "/dev/mixer" #define MAX_VOLUME 100 #define MIN_VOLUME 1 #define RIGHT 0x01 #define LEFT 0x02 typedef struct stereovolume { unsigned char left; unsigned char right; unsigned char pad[2]; } StereoVolume; void setvolume(int which, unsigned char setting, StereoVolume *volptr) { if ( setting < MIN_VOLUME ) setting=MIN_VOLUME; if ( setting > MAX_VOLUME ) setting=MAX_VOLUME; if ( which&RIGHT ) volptr->right=setting; if ( which&LEFT ) volptr->left=setting; } #else #include #endif #ifndef min #define min(x,y) ((x) < (y)? (x): (y)) #endif #define CLOSE_FD(afd) { if (afd > -1) close(afd); afd = -1; } #ifdef linux #define INIT_FD { audiofd = filefd = mixer_fd = -1; } #define END_FD { CLOSE_FD(audiofd); CLOSE_FD(filefd); CLOSE_FD(mixer_fd); return; } #else #define INIT_FD { audiofd = filefd = 0; } #define END_FD { CLOSE_FD(audiofd); CLOSE_FD(filefd); return; } #endif void audio_beep (void) { int audiofd, filefd; int rn, wn, len; unsigned char buf[256]; Audio_filehdr *au_hdr; #ifdef linux StereoVolume origVol, volume; int mixer_fd; #else audio_info_t ais; int origVol; #endif INIT_FD; audiofd = open( "/dev/audio", O_WRONLY | O_NDELAY ); if (audiofd < 0) { fprintf(stderr, "%s: Problem opening /dev/audio.\n", "Coolmail"); END_FD; } #ifdef linux if ( (mixer_fd=open(DEV_MIXER, O_RDWR, 0)) < 0 ) { fprintf(stderr, "Can't open %s: ", DEV_MIXER); END_FD; } if ( ioctl(mixer_fd, MIXER_READ(SOUND_MIXER_VOLUME), &origVol) < 0 ) { perror("Can't obtain current volume settings"); END_FD; } setvolume(LEFT|RIGHT, cool_vol, &volume); if ( ioctl(mixer_fd, MIXER_WRITE(SOUND_MIXER_VOLUME), &volume) < 0 ) { fprintf(stderr, "Can't set current volume settings"); END_FD; } #else if( ioctl( audiofd, AUDIO_GETINFO, &ais ) ) { fprintf(stderr, "%s: Problem retrieving /dev/audio info.\n", "Coolmail"); END_FD; } origVol = ais.play.gain; ais.play.gain = cool_vol; if( ioctl( audiofd, AUDIO_SETINFO, &ais ) ) { fprintf(stderr, "Coolmail: Error %d returned from ioctl.\n", errno); fprintf(stderr, "%s: Problem setting /dev/audio info.\n", "Coolmail"); END_FD; } #endif filefd = open(sndfile, O_RDONLY); if (filefd < 0) { fprintf(stderr, "%s: Couldn't play file \"%s\"\n", "Coolmail", sndfile); END_FD; } /* Read in the audio header */ rn = read(filefd, buf, sizeof(Audio_filehdr)); if (rn > 0 && strncmp(buf, ".snd", 4) != 0) { fprintf(stderr, "%s: Invalid audio file format.\n", "Coolmail"); END_FD; } /* Strip the header */ au_hdr = (Audio_filehdr *)buf; #ifdef linux rn = ntohl(au_hdr->hdr_size) - sizeof(Audio_filehdr); #else rn = au_hdr->hdr_size - sizeof(Audio_filehdr); #endif for( ; rn > 0; ) { len = min(rn, sizeof(buf)); len = read(filefd, buf, len); rn -= len; } while(1) { rn = read(filefd, buf, sizeof(buf)); if (rn < 0) { fprintf(stderr, "%s: Error reading from file \"%s\"\n", "Coolmail", sndfile); END_FD; } if (rn == 0) break; while(1) { wn = write(audiofd, buf, rn); if ( wn < 0 ) { fprintf(stderr, "%s: Error writing to /dev/audio.\n", "Coolmail"); END_FD; } if ( wn != 0 ) break; usleep(1000); } } #ifdef linux CLOSE_FD(audiofd); if ( ioctl(mixer_fd, MIXER_WRITE(SOUND_MIXER_VOLUME), &origVol) < 0 ) { fprintf(stderr, "Can't reset volume settings"); } CLOSE_FD(mixer_fd); #else ais.play.gain = origVol; if( ioctl( audiofd, AUDIO_SETINFO, &ais ) ) { fprintf(stderr, "%s: Problem setting /dev/audio info.\n", "Coolmail"); } #endif END_FD; return; } coolmail-1.3.orig/coolmail.c0100644000175000017500000004246206030443206015400 0ustar hallonhallon/* coolmail.c * * A cool mail notification utility. * * By Byron C. Darrah * Created: 1-June-1994, Wed * Modified: 19-Oct-1994, Tue * Modified: 30-Dec-1994, Fri * Modified: 3-Jan-1994, Tue * Modified: 9-Feb-1995, Thurs * Modified: 21-Feb-1995, Tue * Modified: 01-Sept-95, Fri (Added sound support --Randy Sharpe) * Modified: 19-Sep-1995, Tue * */ #define Version "1.3" #include #include #include #include #include #include #include #include #include #include #ifdef AUDIO #include #endif #include "render1.h" #include "mailbox.h" #define DEFAULT_MAIL_DIR "/var/spool/mail/" #define DEFAULT_COMMAND "xterm -n Elm -e mail\0" #define DEFAULT_INTERVAL 30 #define DEFAULT_FRAMES 15 #ifdef AUDIO #define DEFAULT_VOLUME 50 #endif #ifndef PI #define PI 3.1415926536 #endif polygon_t flag[2], cube2[5], letter[1], post[6], ground[1]; int_point_t flag_ints[2][4], cube2_ints[5][4], letter_ints[1][4], post_ints[6][4], ground_ints[1][4]; char command_str[1024] = DEFAULT_COMMAND; char mailfile_str[1024] = DEFAULT_MAIL_DIR; unsigned long interval = DEFAULT_INTERVAL*1000; unsigned int frames = DEFAULT_FRAMES; int verbose = 0; #ifdef AUDIO char *sndfile = NULL; /* default system sound */ int cool_vol = DEFAULT_VOLUME; #endif float flag_angle = 0.0; int Mailbox_Is_Open = 0, envelope_present = 0, alerted = 0, onceonly = 0; void rotate_in(unsigned int steps); void rotate_out(unsigned int steps); void define_shapes(void); void print_camera(real_point_t pos, real_point_t foc, real_point_t up); void cool_parseargs(int argc, char *argv[]); void cool_init(void); void cool_checkmail(void); int cool_do_command(char *command); void cool_raise_flag(unsigned int steps); void cool_lower_flag(unsigned int steps); void cool_put_envelope(void); void cool_remove_envelope(void); void cool_rotate(float *px, float *py, float cx, float cy, float angle); void cool_get_inboxstatus(char *filename, int *anymail, int *unreadmail, int *newmail); void cool_closemailbox(int n); void cool_alarm(void); int cool_help(int argc, char *argv[]); void cool_usage(void); /*---------------------------------------------------------------------------*/ int main(int argc, char *argv[]) { int reason; char username[L_cuserid]; /* Quickly scan for the -h option -- if it is present don't do anything * but print out some help and exit. */ if (cool_help(argc, argv)) return(0); /* Get the username and use it to create a default mailfile name */ strcat(mailfile_str, cuserid(username)); /* Initialize the renderer */ rend_init(&argc, argv, (float)150.0); cool_parseargs(argc, argv); if (verbose) printf("Coolmail %s watching file: %s\n", Version, mailfile_str); define_shapes(); rend_register_obj(1, 2); rend_register_obj(2, 5); rend_register_obj(3, 1); rend_register_obj(4, 5); rend_register_obj(5, 1); rend_submit_plist(1, flag); rend_submit_plist(2, cube2); rend_submit_plist(4, post); rend_submit_plist(5, ground); cool_init(); reason = rend_freeze(interval); while(1) { switch(reason) { case TIMEOUT: cool_checkmail(); break; case SELECTION: rotate_in(frames); reason = cool_do_command(command_str); alerted = 0; continue; break; default: fprintf(stderr, "coolmail: Renderer unfroze for unknown reason.\n"); assert(0); } reason = rend_freeze(interval); } printf("Reason for termination: %s\n", reason == TIMEOUT ? "Timed out" : "Selected"); rend_end(); return(0); } /*---------------------------------------------------------------------------*/ void rotate_in(unsigned int steps) { float theta, dist; int i; float frames = (float)steps; static float mintheta = 0.4; static float maxtheta = 1.7; static float mindist = 270.0; static float maxdist = 150.0; real_point_t cam_pos = {60.0, 96.0, -20.0}, cam_foc = {60.0, 96.0, 260.0}, cam_up = {60.0, 99.0, -20.0}; for (i = 0; i < steps; i++) { theta = i * (maxtheta - mintheta)/ frames + mintheta; dist = i * (maxdist - mindist) / frames + mindist; cam_pos.z = -dist * cos((double)theta) + cam_foc.z; cam_pos.x = dist * sin((double)theta) + cam_foc.x; cam_up.z = cam_pos.z; cam_up.x = cam_pos.x; rend_set_camera(&cam_pos, &cam_foc, &cam_up); rend_transform_update_all(); rend_frame(); } } /*---------------------------------------------------------------------------*/ void rotate_out(unsigned int steps) { float theta, dist; int i; float frames = (float)steps; static float mintheta = 0.4; static float maxtheta = 1.7; static float mindist = 270.0; static float maxdist = 150.0; real_point_t cam_pos = {60.0, 96.0, -20.0}, cam_foc = {60.0, 96.0, 260.0}, cam_up = {60.0, 99.0, -20.0}; for (i = steps - 1; i >= 0; i--) { theta = i * (maxtheta - mintheta)/ frames + mintheta; dist = i * (maxdist - mindist) / frames + mindist; cam_pos.z = -dist * cos((double)theta) + cam_foc.z; cam_pos.x = dist * sin((double)theta) + cam_foc.x; cam_up.z = cam_pos.z; cam_up.x = cam_pos.x; rend_set_camera(&cam_pos, &cam_foc, &cam_up); rend_transform_update_all(); rend_frame(); } } /*---------------------------------------------------------------------------*/ void print_camera(real_point_t pos, real_point_t foc, real_point_t up) { printf("cam_pos = (%6.2f, %6.2f, %6.2f)\n", pos.x, pos.y, pos.z); printf("cam_foc = (%6.2f, %6.2f, %6.2f)\n", foc.x, foc.y, foc.z); printf("cam_up = (%6.2f, %6.2f, %6.2f)\n", up.x, up.y, up.z); } /*---------------------------------------------------------------------------*/ void define_shapes(void) { /* Define the letter */ letter[0].color = WHITE; letter[0].sim_points = envelope; letter[0].npoints = 4; letter[0].int_points = letter_ints[0]; /* Define the ground */ ground[0].color = GREEN; ground[0].sim_points = ground_plane; ground[0].npoints = 4; ground[0].int_points = ground_ints[0]; /* Define the mailbox flag */ flag[0].color = RED; flag[0].sim_points = flag_1; flag[0].npoints = 4; flag[0].int_points = flag_ints[0]; flag[1].color = RED; flag[1].sim_points = flag_2; flag[1].npoints = 4; flag[1].int_points = flag_ints[1]; /* Define the mailbox itself */ cube2[0].color = DARKCYAN; cube2[0].sim_points = mailbox_front; /* Front */ cube2[0].npoints = 4; cube2[0].int_points = cube2_ints[0]; cube2[1].color = GREY2; cube2[1].sim_points = mailbox_back; /* Back */ cube2[1].npoints = 4; cube2[1].int_points = cube2_ints[1]; cube2[2].color = CYAN; cube2[2].sim_points = mailbox_top; /* Top */ cube2[2].npoints = 4; cube2[2].int_points = cube2_ints[2]; cube2[3].color = DARKBLUE; cube2[3].sim_points = mailbox_bottom; /* Bottom */ cube2[3].npoints = 4; cube2[3].int_points = cube2_ints[3]; cube2[4].color = GREY1; cube2[4].sim_points = mailbox_left; /* Left */ cube2[4].npoints = 4; cube2[4].int_points = cube2_ints[4]; /* Define the post */ post[0].color = DARKBROWN; post[0].sim_points = post_bottom; /* Bottom face */ post[0].npoints = 4; post[0].int_points = post_ints[1]; post[1].color = DARKBROWN; post[1].sim_points = post_front; /* Front face */ post[1].npoints = 4; post[1].int_points = post_ints[2]; post[2].color = DARKBROWN; post[2].sim_points = post_back; /* Back face */ post[2].npoints = 4; post[2].int_points = post_ints[3]; post[3].color = BROWN; post[3].sim_points = post_right; /* Right face */ post[3].npoints = 4; post[3].int_points = post_ints[4]; post[4].color = DARKBROWN; post[4].sim_points = post_left; /* Left face */ post[4].npoints = 4; post[4].int_points = post_ints[5]; } /*---------------------------------------------------------------------------*/ void cool_init(void) { rotate_out(2); /* Initialize the display */ cool_checkmail(); /* Check whether to raise flag & beep */ } /*---------------------------------------------------------------------------*/ /* Check for the existence of new mail. * If there is new mail, raise the flag and sound the alarm. * * This function could probably be made a lot smarter. */ void cool_checkmail(void) { time_t newsize; int anymail, newmail, unreadmail; cool_get_inboxstatus(mailfile_str, &anymail, &unreadmail, &newmail); if (anymail) cool_put_envelope(); else cool_remove_envelope(); if (unreadmail) cool_raise_flag(frames); else cool_lower_flag(frames); if (newmail) cool_alarm(); } /*---------------------------------------------------------------------------*/ void cool_parseargs(int argc, char *argv[]) { int i = 1; while (i < argc) { if (!strcmp(argv[i], "-f")) { i++; strncpy(mailfile_str, argv[i], 1023); } else if (!strcmp(argv[i], "-e")) { i++; strncpy(command_str, argv[i], 1023); } else if (!strcmp(argv[i], "-fr")) { i++; sscanf(argv[i], "%u", &frames); if(frames < 2) frames = 2; } else if (!strcmp(argv[i], "-int") || !strcmp(argv[i], "-update")) { i++; sscanf(argv[i], "%lu", &interval); interval *= 1000; } else if (!strcmp(argv[i], "-once")) { onceonly = 1; } else if (!strcmp(argv[i], "-v")) { verbose++; } #ifdef AUDIO else if (!strcmp(argv[i], "-vol")) { i++; sscanf(argv[i], "%u", &cool_vol); if (cool_vol < 0) cool_vol = 0; else if (cool_vol > 100) cool_vol = 100; } else if (!strcmp(argv[i], "-af")) { i++; sndfile = strdup(argv[i]); } #endif else { fprintf(stderr, "Unknown argument: %s\n", argv[i]); fprintf(stderr, "Type coolmail -h for help.\n"); exit(0); } i++; } } /*---------------------------------------------------------------------------*/ /* Check for the -h option. If found, print help and return nonzero. */ int cool_help(int argc, char *argv[]) { int i; for(i = 1; i < argc; i++) if (!strcmp(argv[i], "-h")) { cool_usage(); return(1); } return(0); } /*---------------------------------------------------------------------------*/ void cool_usage(void) { printf("Usage: coolmail [options]\n\n"); printf("OPTIONS:\n"); printf(" -af filename Specifies an audio file (.au format) to use\n"); printf(" instead of the console bell.\n\n"); printf(" -e command Specifies a command (usually in quotes) which\n"); printf(" is used to invoke your favorite mail-reading\n"); printf(" program.\n\n"); printf(" -f filename Watch filename, instead of the default mail\n"); printf(" file, %s.\n\n", DEFAULT_MAIL_DIR); printf(" -fr n Number of frames to generate for each animation.\n"); printf(" Set to an appropriate value for your machine's.\n"); printf(" graphics performance. The default is %d.\n\n", DEFAULT_FRAMES); printf(" -h Print some help then exit.\n\n"); printf(" -int n Check mail every n seconds, instead of the\n"); printf(" default, %d seconds. Note: Xbiff fans may use\n", DEFAULT_INTERVAL); printf(" -update instead of -int.\n\n"); printf(" -mono Monochrome mode.\n\n"); printf(" -once Ring bell when new mail is first detected, but\n"); printf(" not when more new mail is detected.\n\n"); printf(" -v Verbose mode - Coolmail prints some information\n"); printf(" on startup.\n\n"); printf(" -vol n Value between 0 and 100 for the volume setting\n"); printf(" for both the console bell and the audio file.\n"); printf(" The default is 50.\n\n"); printf(" In addition, standard X intrinsic arguments are supported.\n"); } /*---------------------------------------------------------------------------*/ /* Fork off the renderer update routine, to keep the mailbox window * up to date while we execute the command. */ int cool_do_command(char *command) { int exists, reason; time_t newsize; pid_t child; disp_sync(); if (child = fork()) { /* Parent Process */ Mailbox_Is_Open = 1; signal(SIGCHLD, cool_closemailbox); while(Mailbox_Is_Open) { reason = rend_freeze(interval); cool_checkmail(); } wait(NULL); return(reason); } else { /* Child Process */ pid_t parent = getppid(); system(command); kill(parent, SIGCHLD); exit(0); } } /*---------------------------------------------------------------------------*/ void cool_raise_flag(unsigned int steps) { static float pivot_x = 34.0; static float pivot_y = 80.0; float inc = (PI/2.0)/(float)steps; int poly, point; if (flag_angle > PI/2.0 - inc) return; for (; flag_angle < PI/2.0; flag_angle += inc) { for(poly = 0; poly < 2; poly++) for(point = 0; point < 4; point++) { cool_rotate(&(flag[poly].sim_points[point].x), &(flag[poly].sim_points[point].y), pivot_x, pivot_y, inc); } rend_rm_plist(1); rend_submit_plist(1, flag); rend_frame(); } return; } /*---------------------------------------------------------------------------*/ void cool_lower_flag(unsigned int steps) { static float pivot_x = 34.0; static float pivot_y = 80.0; float inc = (PI/2.0)/(float)steps; int poly, point; if (flag_angle < inc) return; for (; flag_angle > 0.0; flag_angle -= inc) { for(poly = 0; poly < 2; poly++) for(point = 0; point < 4; point++) { cool_rotate(&(flag[poly].sim_points[point].x), &(flag[poly].sim_points[point].y), pivot_x, pivot_y, -inc); } rend_rm_plist(1); rend_submit_plist(1, flag); rend_frame(); } return; } /*---------------------------------------------------------------------------*/ /* Put the envelope in the mailbox */ void cool_put_envelope(void) { if (envelope_present) return; rend_submit_plist(3, letter); rend_frame(); envelope_present = 1; } /*---------------------------------------------------------------------------*/ /* Remove the envelope from the mailbox */ void cool_remove_envelope(void) { if (!envelope_present) return; rend_rm_plist(3); rend_frame(); envelope_present = 0; } /*---------------------------------------------------------------------------*/ /* Sound an alarm to alert the user of new mail */ void cool_alarm(void) { if (!alerted || !onceonly) { rend_bell(); alerted++; } } /*---------------------------------------------------------------------------*/ /* Rotate (px,py) about the point (cx,cy). */ void cool_rotate(float *px, float *py, float cx, float cy, float angle) { double theta; double r; double xdist = (double)(*px-cx), ydist = (double)(*py-cy); r = sqrt((double)(xdist*xdist + ydist * ydist)); if (r == 0) return; theta = acos(xdist/r); if (asin(ydist/r) < 0.0) theta = (2.0*PI - theta); theta += (double)angle; *px = r*cos(theta) + cx; *py = r*sin(theta) + cy; } /*---------------------------------------------------------------------------*/ /* This is called upon receiving a signal from the child process, that the * mail application has completed. */ void cool_closemailbox(int n) { cool_checkmail(); rotate_out(frames); /* Do the animation of the mailbox closing */ signal(SIGCHLD, SIG_DFL); Mailbox_Is_Open = 0; } /*---------------------------------------------------------------------------*/ /* Get file modification time */ void cool_get_inboxstatus(char *filename, int *anymail, int *unreadmail, int *newmail) { static off_t oldsize = 0; off_t newsize; struct stat st; int fd; fd = open (filename, O_RDONLY, 0); if (fd < 0) { *anymail = 0; *newmail = 0; *unreadmail = 0; newsize = 0; } else { fstat(fd, &st); close(fd); newsize = st.st_size; if (newsize > 0) *anymail = 1; else *anymail = 0; if (st.st_mtime >= st.st_atime && newsize > 0) *unreadmail = 1; else *unreadmail = 0; if (newsize > oldsize && *unreadmail) *newmail = 1; else *newmail = 0; } oldsize = newsize; } /*---------------------------------------------------------------------------*/ coolmail-1.3.orig/coolmail.man0100644000175000017500000000513106030441332015717 0ustar hallonhallon.TH COOLMAIL 1 "1.3" "Coolmail" .SH NAME coolmail \- 3D animated mail notificaion utility .SH SYNOPSIS .B coolmail [option ...] .SH DESCRIPTION Coolmail is a mail notification utility with 3D animated graphics. Coolmail watches your inbox and lets you know when you have mail. Clicking on coolmail can launch your mail reading/writing utility. While your mail utility is open, clicking on coolmail will cause it to check your inbox at that instant, without waiting for the next regular interval. .SH OPTIONS .TP 8 -e command Use the specified command to launch your mail utility. Command is a string, and should be in quotes if it contains spaces. .TP 8 -f filename Watch filename, instead of the default mail inbox file. .TP 8 -fr n Set the number of frames to generate for each animation to n. Set this to an suit your preference and your machine's graphics performance. The default is 15. .TP 8 -h Print some help then exit. .TP 8 -int n | -update n Check your mail inbox at n-second intervals. The default is 30 seconds. .TP 8 -mono Run in monochrome mode. .TP 8 -once Ring bell when new mail is first detected, but not when more new mail is detected. .TP 8 -af filename Specifies the audio file to use rather than the standard system beep. .TP 8 -vol n Value between 0 and 100 for the volume setting for both the system beep and the sound file. The default is 50. .TP 8 -v Print version and inbox path. .I Coolmail also accepts the standard X Toolkit options, such as -geometry, etc. .SH EXAMPLES .TP 8 coolmail -e "emacs -f rmail" -int 20 .br Tells coolmail to check the inbox every 20 seconds, and launch the shell command, emacs -f rmail, when the user clicks on coolmail. .SH X DEFAULTS This program understands the core resource names and classes as well as: .PP .TP 8 .B frameCount (\fPclass\fB FrameCount) Specifies the number of frames to be generated per animation. .TP 8 .B inbox (\fPclass\fB Inbox) Specifies the mail inbox that coolmail will watch. .TP 8 .B mailCommand (\fPclass\fB MailCommand) Specifies the command that should be launched to read and write mail. .TP 8 .B monochrome (\fPclass\fB Monochrome) A Boolean value that enables monochrome mode when true. .TP 8 .B soundFile (\fPclass \fB SoundFile) Specifies the audio file to use rather than the standard system beep. .TP 8 .B volume (\fPclass \fB Volume) Value between 0 and 100 for the volume setting for both the system beep and the sound file. .SH COPYRIGHT Copyright 1994 by Byron C. Darrah (darrah@kaiwan.com) .SH AUTHORS Byron C. Darrah (darrah@kaiwan.com) Sound support added by Randall K. Sharpe (rsharpe@ncsa.uiuc.edu) .SH "SEE ALSO" X(1), xrdb(1) coolmail-1.3.orig/display_list.h0100644000175000017500000000635506027666220016320 0ustar hallonhallon/* display_list.h * * By Byron C. Darrah * 4/28/94, Thursday * * This module is for actually drawing a prepared list of polygons into a * window on a screen. * * Here is a brief description of the exported display_list functions: * * o void disp_init(int *argc, char *argv[], int color); * * Initializes a display: Creates a window, allocates display memory, etc. * ie: Does whatever is necessary to get ready to start displaying * lists of polygons. If color is zero, monochrome operation will * be enabled. Otherwise, color mode is used. * * o void disp_end(void); * * Destroys the display, frees resources, etc. This is called when no more * rendering is to be performed. * * o void disp_polygons(polygon_node_t *pnodes); * * Draws polygons. pnodes is a list of polygons. The polygons are * displayed from first to last, until a polygon key value of 0.0 is * encountered. This allows render1 to use the painter's algorithm of * hidden line removal. ie: Before disp_polygons is called, the polygon * list is sorted so that farther-away polygons are closer to the head of * the list. * * o void disp_sync(void); * * Pauses execution until graphics processing requests have completed. * * o void disp_freeze(void); * * Pauses the display, so that it may be examined at length by the user. * At the moment, this is for debugging purposes, and is not guranteed to * ever return. * * o void disp_setsize(unsigned short width, unsigned short height); * * Change the scale of the image. This involves updating some global * variables and reallocating some image memory. This does not * automatically change the window size, but does change how display * operations behave. * * o void disp_getsize(unsigned short *width, unsigned short *height); * * Queries the size of the output window, and returns it's dimentions * in the output parameters width and height. */ #include "render1.h" #ifdef DISPLAY_LIST_MODULE #define DISP_EXTERN #else #define DISP_EXTERN extern #endif /* Define the display size. (This is non-adjustable at runtime, for now) */ DISP_EXTERN unsigned short Gfx_Width; DISP_EXTERN unsigned short Gfx_Height; /* Define the "origin" offset: ie: we want (0,0) to translate to (52, 40), * which is the middle of the display. */ DISP_EXTERN unsigned short Gfx_X_Origin; DISP_EXTERN unsigned short Gfx_Y_Origin; /* The display_list module will set "recommended" scaling factors */ DISP_EXTERN float disp_x_scale; DISP_EXTERN float disp_y_scale; /* Here is the structure for the nodes of the aggregate polygon list */ typedef struct aggregate_pgn_struct { struct aggregate_pgn_struct *next; struct aggregate_pgn_struct *prev; polygon_t *polygon; float k; /* Sort-key for the aggregate list */ } polygon_node_t; /* These four functions are exported to the renderer. */ void disp_init(int *argc, char *argv[], int color); void disp_end(void); void disp_polygons(polygon_node_t *pnodes); void disp_sync(void); int disp_freeze(unsigned long interval); void disp_bell(void); void disp_setsize(unsigned short width, unsigned short height); void disp_getsize(unsigned short *width, unsigned short *height); coolmail-1.3.orig/mailbox.h0100644000175000017500000001031306027200337015231 0ustar hallonhallon/* mailbox.h * * Here are a couple of shapes for displaying a mailbox * * flag has two polygons, and z-rotates about (35, 85, 225). * cube2 has sides of length 60, with front-bottom-left corner at (30,30,230). */ #include "render1.h" /* stem part */ real_point_t flag_1[] = { { 30.0, 85.0, 220.0}, { 70.0, 85.0, 220.0}, { 70.0, 75.0, 220.0}, { 30.0, 75.0, 220.0} }; /* wide part */ real_point_t flag_2[] = { { 70.0, 85.0, 220.0}, { 90.0, 85.0, 220.0}, { 90.0, 60.0, 220.0}, { 70.0, 60.0, 220.0} }; real_point_t envelope[] = { {40.0, 30.0, 280.0}, {40.0, 70.0, 230.0}, {90.0, 70.0, 230.0}, {90.0, 30.0, 280.0} }; /* Average z = 230 */ /* Front face */ real_point_t mailbox_front[] = { {20.0, 30.0, 230.0}, {20.0, 90.0, 230.0}, {100.0, 90.0, 230.0}, {100.0, 30.0, 230.0} }; /* Average z = 230 */ /* Back face */ real_point_t mailbox_back[] = { {20.0, 30.0, 290.0}, {20.0, 90.0, 290.0}, {100.0, 90.0, 290.0}, {100.0, 30.0, 290.0} }; /* Average z = 290 */ /* Top face */ real_point_t mailbox_top[] = { {20.0, 90.0, 230.0}, {20.0, 90.0, 290.0}, {100.0, 90.0, 290.0}, {100.0, 90.0, 230.0} }; /* Bottom face */ real_point_t mailbox_bottom[] = { {20.0, 30.0, 230.0}, {20.0, 30.0, 290.0}, {100.0, 30.0, 290.0}, {100.0, 30.0, 230.0} }; /* Left face */ real_point_t mailbox_left[] = { {20.0, 30.0, 230.0}, {20.0, 30.0, 290.0}, {20.0, 90.0, 290.0}, {20.0, 90.0, 230.0} }; real_point_t post_top[] = { {50.0, 29.9, 250.0}, {50.0, 29.9, 270.0}, {70.0, 29.9, 270.0}, {70.0, 29.9, 250.0} }; real_point_t post_bottom[] = { {50.0, -30.0, 250.0}, {50.0, -30.0, 270.0}, {70.0, -30.0, 270.0}, {70.0, -30.0, 250.0} }; real_point_t post_front[] = { {50.0, 29.9, 250.0}, {70.0, 29.9, 250.0}, {70.0, -30.0, 250.0}, {50.0, -30.0, 250.0} }; real_point_t post_back[] = { {50.0, 29.9, 270.0}, {70.0, 29.9, 270.0}, {70.0, -30.0, 270.0}, {50.0, -30.0, 270.0} }; real_point_t post_right[] = { {70.0, 29.9, 250.0}, {70.0, 29.9, 270.0}, {70.0, -30.0, 270.0}, {70.0, -29.9, 250.0} }; real_point_t post_left[] = { {50.0, 29.9, 250.0}, {50.0, 29.9, 270.0}, {50.0, -30.0, 270.0}, {50.0, -30.0, 250.0} }; real_point_t ground_plane[] = { {-50.0, -30.0, 150.0}, {-50.0, -30.0, 500.0}, {150.0, -30.0, 500.0}, {150.0, -30.0, 150.0} }; coolmail-1.3.orig/r1_sub.c0100644000175000017500000000230006027200337014761 0ustar hallonhallon/* r1_sub.c * * By Byron C. Darrah * 10-May-1994, Tuesday * * This is a short program for testing the system-dependent * display_list routines. It substitues itself for render1 (hence the * name, r1_sub) by calling the display routines directly. * * If the test is successfull, r1_sub will display a blue rectangle on * top of a red diamond. */ #include #include #include #include #include "display_list.h" polygon_t diamond; polygon_t rectangle; int_point_t diamond_points[] = { {100, 25}, {150, 100}, {100, 175}, { 50, 100} }; int_point_t rectangle_points[] = { {50, 50}, {100, 50}, {100, 100}, {50, 100} }; int main(int argc, char *argv[]) { polygon_node_t polys[2]; polys[0].next = polys+1; polys[1].next = NULL; polys[0].k = 6.0; polys[1].k = 1.0; polys[0].polygon = ⋄ polys[1].polygon = &rectangle; diamond.color = RED; diamond.npoints = 4; diamond.int_points = diamond_points; rectangle.color = BLUE; rectangle.npoints = 4; rectangle.int_points = rectangle_points; disp_init(&argc, argv); disp_polygons(polys); disp_freeze(); disp_end(); return(0); } coolmail-1.3.orig/render1.c0100644000175000017500000004340606027674625015161 0ustar hallonhallon/* render1.c * * By Byron C. Darrah * 4/28/94, Thursday * * render1 renders simple lists of polygons. render1 keeps an aggregate * list of all polygons submitted to it, and also keeps an index to this * list keyed by object ID numbers, so that it knows which polygons * belong to which objects. */ /* Here is the implementation of the renderer called render1. */ #include #include #include #include #include "render1.h" #include "display_list.h" typedef float rend_matrix_t[4][4]; rend_matrix_t camera_transformation; float perspective, default_perspective = DEFAULT_PERSPECTIVE; polygon_node_t ag_polygon_list; /* A dummy node to be the head of list */ /* Here is the structure for the nodes of the object ID index to the * aggregate list. */ typedef struct obj_ki_struct { struct obj_ki_struct *next; int obj_id; polygon_node_t *pnodes; /* array of polygon nodes. */ int npolygons; /* size of above array. */ } obj_node_t; obj_node_t obj_id_index; /* This list also has a dummy node for a head */ /*---------------------------------------------------------------------------*/ /*---------------------- INTERNAL FUNCTION PROTOTYPES -----------------------*/ /*---------------------------------------------------------------------------*/ void rend_agg_poly_insert(polygon_node_t *pnode); obj_node_t *rend_obj_lookup(int obj_id); void mtx_mult_4x4(rend_matrix_t f1, rend_matrix_t f2, rend_matrix_t product); void mtx_transform_pt(real_point_t *pos, rend_matrix_t m1, real_point_t *new_pos); void mtx_transform_pg(polygon_node_t *polygon_node); /*---------------------------------------------------------------------------*/ /*--------------------------- EXPORTED FUNCTIONS ----------------------------*/ /*---------------------------------------------------------------------------*/ /* This sets the camera matrix to a default value, initializes the * polygon lists, and the display. */ void rend_init(int *argc, char *argv[], float init_perspect) { real_point_t c_position = {0.0, 0.0, -20.0}; /* Camera positon */ real_point_t c_focus = {0.0, 0.0, 0.0}, /* Camera focus direction */ c_up = {0.0, 10.0, 0.0}; /* Camera up direction */ int i, color = 1; /* Scan for the -mono option in the argument list */ for(i = 0; i < *argc; i++) { if(color) { if(!strcmp(argv[i], "-mono")) { color = 0; (*argc)--; if(i < *argc) argv[i] = argv[i+1]; } } else argv[i] = argv[i+1]; } /* Initialize the display */ disp_init(argc, argv, color); ag_polygon_list.next = NULL; ag_polygon_list.prev = NULL; obj_id_index.next = NULL; obj_id_index.pnodes = NULL; obj_id_index.npolygons = 0; rend_set_camera(&c_position, &c_focus, &c_up); /* Initialize the perspective. If no perspective value was given, * set it to the default perspective. */ if (init_perspect != 0.0) default_perspective = init_perspect; /* Now work in a fudge-factor to cause points to be scaled according * to the display window size. */ if (disp_x_scale < disp_y_scale) perspective = default_perspective * disp_x_scale; else perspective = default_perspective * disp_y_scale; } /*---------------------------------------------------------------------------*/ void rend_end(void) { disp_end(); } /*---------------------------------------------------------------------------*/ /* Synchronize the scale of drawing operations with the size of the * actual output window, and redraw the output frame. */ void rend_setsize(void) { unsigned short width, height; disp_getsize(&width, &height); disp_setsize(width, height); /* Now work in a fudge-factor to cause points to be scaled according * to the display window size. */ if (disp_x_scale < disp_y_scale) perspective = default_perspective * disp_x_scale; else perspective = default_perspective * disp_y_scale; /* Now that the drawing size has been adjusted, redraw the output */ rend_transform_update_all(); rend_frame(); } /*---------------------------------------------------------------------------*/ /* This is used to set the camera matrix, which describes the position * and orientation of the POV. Whenever the camera matrix is changed, * the entire list of polygons must be recomputed. * * The position and orientation of the camera determines what gets displayed * (obviously). As a result, the camera's orientation is used to determine * a transformation which will be applied to all points to map them * to screen coordinates. For more information, see "Faster 3-D Drawing" * by Brian Carmichael, in The AmigaWorld Tech Journal, pg 20, January/February * 1992, or any decent 3-D rendering text. * * Whenever the camera is moved, the aggregate polygon list must be * recomputed (because the mapping of sim-space to screen-space is * changed). This can be done by calling rend_transform_update_all(). * This is an time-expensive operation, so it is good if the calling * application can remove from the aggregate list any objects that are going * to resubmit their polygons before the next frame-render, so these objects * will not have to be redundantly transformed. */ void rend_set_camera(real_point_t *position, real_point_t *focus, real_point_t *up) { rend_matrix_t m1, m2, m3; float cosAy, sinAy, cosAx, sinAx, cosAz, sinAz; float Dxz, Dyz, Dxy; real_point_t new_pos; /* let m1 be the transformation matrix for the translation, which moves * the camera's focus point to the origin. */ m1[0][0] = 1; m1[0][1] = m1[0][2] = m1[0][3] = 0; m1[1][0] = 0; m1[1][1] = 1; m1[1][2] = m1[1][3] = 0; m1[2][0] = m1[2][1] = 0; m1[2][2] = 1; m1[2][3] = 0; m1[3][0] = -position->x; m1[3][1] = -position->y; m1[3][2] = -position->z; m1[3][3] = 1; /* Compute the camera focus relative to the position. */ new_pos.x = focus->x - position->x; new_pos.y = focus->y - position->y; new_pos.z = focus->z - position->z; /* Now compute the cosine and sine of the y-rotation angle, Ay, * between the focus vector and the zy plane. */ Dxz = sqrt((double)(new_pos.x * new_pos.x + new_pos.z * new_pos.z)); if (Dxz != 0.0) { cosAy = new_pos.z / Dxz; sinAy = -new_pos.x / Dxz; } else /* Uh-oh - handle indeterminate case */ { cosAy = 1.0; sinAy = 0.0; } /* let m2 be the transformation matrix for rotating the focus point about * the y-axis onto the zy plane. */ m2[0][0] = cosAy; m2[0][1] = 0; m2[0][2] = -sinAy; m2[0][3] = 0; m2[1][0] = 0; m2[1][1] = 1; m2[1][2] = 0; m2[1][3] = 0; m2[2][0] = sinAy; m2[2][1] = 0; m2[2][2] = cosAy; m2[2][3] = 0; m2[3][0] = 0; m2[3][1] = 0; m2[3][2] = 0; m2[3][3] = 1; /* let m3 be the product of m1 and m2 */ mtx_mult_4x4(m1, m2, m3); /* Update the focus pos by multiplying it by m2. */ new_pos.x = new_pos.x * cosAy + new_pos.z * sinAy; new_pos.z = new_pos.x * -sinAy + new_pos.z * cosAy; /* Now compute the cosine and sine of the x-rotation angle, Ax */ Dyz = sqrt((double)(new_pos.y * new_pos.y + new_pos.z * new_pos.z)); cosAx = new_pos.z/Dyz; sinAx = new_pos.y/Dyz; /* let m2 be the transformation matrix for rotating the focus point about * the x-axis onto the +z-axis. */ m2[0][0] = 1; m2[0][1] = 0; m2[0][2] = 0; m2[0][3] = 0; m2[1][0] = 0; m2[1][1] = cosAx; m2[1][2] = sinAx; m2[1][3] = 0; m2[2][0] = 0; m2[2][1] = -sinAx; m2[2][2] = cosAx; m2[2][3] = 0; m2[3][0] = 0; m2[3][1] = 0; m2[3][2] = 0; m2[3][3] = 1; /* let m1 be the product of m3 and m2 */ mtx_mult_4x4(m3, m2, m1); /* Update the "up" point pos by multiplying it by m1 */ mtx_transform_pt(up, m1, &new_pos); /* Now compute the cosine and sine of the z-axis rotation angle, Az */ Dxy = sqrt((double)(new_pos.x * new_pos.x + new_pos.y * new_pos.y)); cosAz = new_pos.y/Dxy; sinAz = new_pos.x/Dxy; /* let m2 be the transformation matrix for rotating the up point about * the z-axis onto the zy-plane. */ m2[0][0] = cosAz; m2[0][1] = sinAz; m2[0][2] = 0; m2[0][3] = 0; m2[1][0] = -sinAz; m2[1][1] = cosAz; m2[1][2] = 0; m2[1][3] = 0; m2[2][0] = 0; m2[2][1] = 0; m2[2][2] = 1; m2[2][3] = 0; m2[3][0] = 0; m2[3][1] = 0; m2[3][2] = 0; m2[3][3] = 1; /* Now the final multiplication gives us the camera transformation: */ mtx_mult_4x4(m1, m2, camera_transformation); /* If you want to debug by printing out the camera matrix, uncomment this. */ /* fprintf(stderr, "---Camera Matrix---\n"); { int row, col; for(row = 0; row < 4; row++) { for(col = 0; col < 4; col++) fprintf(stderr, "%6.2f ", camera_transformation[row][col]); printf("\n"); } } fprintf(stderr, "-------------------\n"); */ } /*---------------------------------------------------------------------------*/ /* rend_register_obj is called by objects that wish to use the display. * An object that calls this function is "registered", and may submit * lists of polygons for display. * */ void rend_register_obj(int obj_id, int npolygons) { polygon_node_t *newlist; obj_node_t *newobj; if ((newlist = (polygon_node_t *)malloc(sizeof(polygon_node_t) * npolygons)) == NULL) { fprintf(stderr, "rend_register_obj: out of memory"); assert(0); } if ((newobj = (obj_node_t *)malloc(sizeof(obj_node_t))) == NULL) { fprintf(stderr, "rend_register_obj: out of memory"); assert(0); } /* Add the new object to the object ID index list */ newobj->next = obj_id_index.next; obj_id_index.next = newobj; /* Now fill in the data for this object node */ newobj->obj_id = obj_id; newobj->pnodes = newlist; newobj->npolygons = npolygons; } /*---------------------------------------------------------------------------*/ /* An object calls this function to submit an updatedlist of polygons * to the renderer. Render1 knows how many polygons to expect, from * when the object was registered by rend_register_obj. It transforms * the object's polygons to screen space, and adds them to the aggregate * list. Note: An object must be sure that it has removed it's polygons * before resubmitting them, or else the aggregate list will get messed up. */ int rend_submit_plist(int obj_id, polygon_t *polygons) { obj_node_t *obj_record; int i; polygon_node_t *pnode; if((obj_record = rend_obj_lookup(obj_id)) == NULL) { fprintf(stderr, "rend_submit_plist: unknown object %d.\n", obj_id); return (R1_OBJ_UNKNOWN); } /* Add the object's polygons */ for(i = 0; i < obj_record->npolygons; i++) { pnode = obj_record->pnodes+i; pnode->polygon = polygons+i; /* transform the polygons and add them to the aggregate list */ mtx_transform_pg(pnode); rend_agg_poly_insert(pnode); } return(R1_NORMAL); } /*---------------------------------------------------------------------------*/ /* remove an object's polygons from the aggregate display list */ int rend_rm_plist(int obj_id) { obj_node_t *obj_node; polygon_node_t *poly_array; int i; if ((obj_node = rend_obj_lookup(obj_id)) == NULL) return(R1_OBJ_UNKNOWN); poly_array = obj_node->pnodes; /* Since the polygon list is a doubly-linked list, polygons can be * removed from it by simply removing the pointers to them in the * previous and next nodes. The following loop does this. */ for (i = 0; i < obj_node->npolygons; i++) { if (poly_array[i].next) poly_array[i].next->prev = poly_array[i].prev; poly_array[i].prev->next = poly_array[i].next; poly_array[i].next = poly_array[i].prev = NULL; } return(R1_NORMAL); } /*---------------------------------------------------------------------------*/ /* Update the entire list of polygons -- * perform transformations on all polygons and rebuild the aggregate * polygon display list in z-sorted order. */ void rend_transform_update_all(void) { polygon_node_t *templist; polygon_node_t *curnode; /* Make a copy of the aggregate polygon list, then clear it */ templist = ag_polygon_list.next; ag_polygon_list.next = NULL; curnode = templist; while(curnode) { templist = curnode->next; mtx_transform_pg(curnode); /* Transform polygon to screen space. */ rend_agg_poly_insert(curnode); /* Insert the node to the agg. list. */ curnode = templist; /* Get the next node from the templist. */ } } /*---------------------------------------------------------------------------*/ /* Render a display frame -- * This outputs the aggregate polygon list to the display device. */ void rend_frame(void) { disp_polygons(ag_polygon_list.next); } /*---------------------------------------------------------------------------*/ /* Ring the audio bell. */ void rend_bell(void) { disp_bell(); } /*---------------------------------------------------------------------------*/ /* Freeze the image as is. Returns when either the specified interval has * expired, or a mouseclick has occurred in the image window. */ int rend_freeze(unsigned long interval) { int reason; while(1) { if ((reason = disp_freeze(interval)) == RESIZE) rend_setsize(); else return(reason); } } /*---------------------------------------------------------------------------*/ /*--------------------------- INTERNAL FUNCTIONS ----------------------------*/ /*---------------------------------------------------------------------------*/ /* Given a pointer to a polygon_node_t, insert the node into the aggregate * polygon display list. */ void rend_agg_poly_insert(polygon_node_t *pnode) { polygon_node_t *curnode = &ag_polygon_list; /* Find the node that pnode should be inserted after */ while(curnode->next && (curnode->next->k > pnode->k)) curnode = curnode->next; /* Insert the pnode into the aggregate list */ if(curnode->next) curnode->next->prev = pnode; pnode->next = curnode->next; curnode->next = pnode; pnode->prev = curnode; } /*---------------------------------------------------------------------------*/ /* Given an object id, look up the object's entry in the object list. * NULL is returned if the end of the list is reached before the * object id is found. */ obj_node_t *rend_obj_lookup(int obj_id) { obj_node_t *curnode = obj_id_index.next; for(;curnode && curnode->obj_id != obj_id; curnode = curnode->next) ; return(curnode); } /*---------------------------------------------------------------------------*/ /* mtx_mult_4x4 is a function which multiplies two 4x4 matrices and gives the * result. */ void mtx_mult_4x4(rend_matrix_t f1, rend_matrix_t f2, rend_matrix_t product) { int i, row, col; float sum; for (row = 0; row < 4; row++) for (col = 0; col < 4; col++) { sum = f1[row][0] * f2[0][col]; for(i = 1; i < 4; i++) sum += f1[row][i] * f2[i][col]; product[row][col] = sum; } } /*---------------------------------------------------------------------------*/ /* mtx_transform_pt transforms a point by the specified matrix. This is used * by other functions to map a point in simulation space to screen space. * * This routine is optimized based on the assumption that a point is a 1x4 * matrix with the first three elements equal to the x,y,z of the point, and * the last element always equal to one. */ void mtx_transform_pt(real_point_t *pos, rend_matrix_t m1, real_point_t *new_pos) { new_pos->x = pos->x * m1[0][0] + pos->y * m1[1][0] + pos->z * m1[2][0] + m1[3][0]; new_pos->y = pos->x * m1[0][1] + pos->y * m1[1][1] + pos->z * m1[2][1] + m1[3][1]; new_pos->z = pos->x * m1[0][2] + pos->y * m1[1][2] + pos->z * m1[2][2] + m1[3][2]; } /*---------------------------------------------------------------------------*/ /* Given a polygon, transform it to screen space */ void mtx_transform_pg(polygon_node_t *polygon_node) { int i; int clipped = 0; float scale; float d_sum = 0.0; polygon_t *polygon = polygon_node->polygon; for (i = polygon->npoints-1; i >= 0; i--) { real_point_t scrn_pt; int_point_t *int_pt = polygon->int_points+i; /* Tanslate and rotate each point in the polygon into screen space */ mtx_transform_pt(polygon->sim_points+i, camera_transformation, &scrn_pt); /* Perform perspective scaling adjustment on each point */ if (scrn_pt.z > 0.0) { scale = perspective / scrn_pt.z; int_pt->x = Gfx_X_Origin + (int)(scrn_pt.x * scale); int_pt->y = Gfx_Y_Origin - (int)(scrn_pt.y * scale); } /* Keep track of the z-sum */ if (scrn_pt.z > 0.0) { d_sum += (float) sqrt((double)(scrn_pt.x*scrn_pt.x + scrn_pt.y*scrn_pt.y + scrn_pt.z*scrn_pt.z)); } else /* Uh-oh: this point is behind the focus -- clip it */ { d_sum = 0.0; clipped = 1; break; } } /* Store the z-center of the polygon, which is used to determine where * the polygon will fit into the aggregate list. */ if (!clipped) polygon_node->k = d_sum/((float)polygon->npoints); else polygon_node->k = 0.0; } /*---------------------------------------------------------------------------*/ coolmail-1.3.orig/render1.h0100644000175000017500000001405506027671415015156 0ustar hallonhallon/* render1.h * * By Byron C. Darrah * 5/13/94, Thursday * * render1 is a renderer which may be used with the generic vr simulator. * The characteristics of this renderer are: * * - Renders polygonal objects. * - 16 colors (this is very easily changed for the render1 module, but if you * change it, don't forget to implement the new color scheme in the * (system-dependent) display_list module). * - No shading or texture mapping - polygons use flat colors. * * Here is a brief description of each of the functions provided to * interface the renderer: * * * o void rend_init(int *argc, char *argv[], float init_perspect); * * Fire up the renderer for use. Call this once at the beginning of * your simulation, and call rend_end() once at the end. argc and argv * are expected to be what they usually would be, as derived from the * command line, except note that argc is a _pointer_ to an int. This * is because rend_init() may decide to destructively remove certain * arguments from the list. init_perspect is the focal length of the * camera lense (note that the camera position and focus point are * _not_ used to determine the focal length, this is). Roughly, a small * number gives you a wide-angle-style lense, and a big value gives you * telephoto. * * o void rend_end(void); * * Call this routine before exiting a simulation, to shut down the * renderer and free up any resources necessary that have been allocated. * * o void rend_setsize(void); * * Synchronize the scale of drawing operations with the size of the * actual output window. * * o void rend_set_camera(real_point_t *position, * real_point_t *focus, * real_point_t *up); * * This function alters the camera matrix. Note that each time the * camera matrix is updated, all of the polygons currently submitted * to render1 have to be retransformed and resorted, so use this function * with care. You should never need to use this function more than * once per frame. The focus represents a point at which the camera is * aimed. The position is the location of the camera. up represents the * "top" of the camera -- a vector from the postion point to the up point * tells you which way the camera thinks is up. * * o void rend_register_obj(int obj_id, int npolygons); * * Objects call this function to register themselves with the renderer. * Only registered objects may submit polygons. obj_id is the object's * unique id, and npolygons is the number of polygons the object * will use to display itself (ie: for a cube, npolygons is 6). * * o int rend_submit_plist(int obj_id, polygon_t *polygons); * * This is the function objects use to submit their polygons to render1 * for displaying. obj_id is the id of a registered object, and polygons * is an array of polygons. It returns R1_NORMAL when successful, or * R1_OBJ_UNKNOWN if an unregistered object id is given. * * o void rend_rm_plist(int obj_id); * * This is the function objects use to remove their polygons from the * display. Note: this does not unregister an object, it merely * "unsubmits" it's polygons. * * o void rend_transform_update_all(void); * * This functions performs the camera matrix transformation on all * currently submitted polygons. It is used after rend_set_camera(), * to update the polygons with respect to the new camera position. * Note that polygons are automatically transformed whenever they are * submitted. Therefore, if you can guarantee that all submitted * polygons will be either removed or resubmitted before the next frame is * rendered, there is no need to call this function after * rend_set_camera(). * * o void rend_frame(void); * * Actually output all currently submitted polygons to the display. * * o void rend_freeze(void); * * Pause the renderer, leaving the most recently rendered frame visible. * Currently, this function is not guaranteed to ever return. */ #ifndef render1_h #define render1_h #define DEFAULT_PERSPECTIVE 200.0 /* Here are status codes that render1 can return */ #define R1_NORMAL 0 #define R1_OBJ_UNKNOWN 300 #define TIMEOUT 301 #define RESIZE 302 #define SELECTION 303 /*---------------------------------------------------------------------------*/ /* Here are the data structures used to interface the renderer, render1. */ /*---------------------------------------------------------------------------*/ /* Here are the colors currently supported by the renderer. It is up to * The display_list module to actually provide these. */ #define BLACK 0 #define DARKRED 1 #define DARKGREEN 2 #define DARKBLUE 3 #define DARKBROWN 4 #define DARKMAGENTA 5 #define DARKCYAN 6 #define GREY1 7 #define GREY2 8 #define RED 9 #define GREEN 10 #define BLUE 11 #define BROWN 12 #define MAGENTA 13 #define CYAN 14 #define WHITE 15 typedef struct { float x, y, z; } real_point_t; typedef struct { float i, j, k; } vector_t; typedef struct { short x, y; } int_point_t; typedef struct plygon_struct { int color; /* A color table entry */ real_point_t *sim_points; int npoints; int_point_t *int_points; } polygon_t; void rend_init(int *argc, char *argv[], float init_perspect); void rend_end(void); void rend_setsize(void); void rend_set_camera(real_point_t *position, real_point_t *focus, real_point_t *up); void rend_register_obj(int obj_id, int npolygons); int rend_submit_plist(int obj_id, polygon_t *polygons); int rend_rm_plist(int obj_id); void rend_transform_update_all(void); void rend_frame(void); int rend_freeze(unsigned long interval); void rend_bell(void); #endif /* render1_h */ coolmail-1.3.orig/coolmail.1x.gz0100644000175000017500000000227606202711050016120 0ustar hallonhallon( 2coolmail.1xVnFW ti Ȭ4@Sdũږ`*rh.LK}H͡@ыM/gg޼ylyEf2sgG4Z[G"˯vrs)$^3c.juئ""}mB ̲2V+$ѡ:dSi3}AUik[Gڬ3 93z4vCMO*V<J4T֨˘98@\"еa3&"hI3@:PG-m|&E¶6PZ&ZƻݓD<,8e_oXu{.*c<ЎZ0]ޔ5A Ԓ}SR \9N-oeYp):tX:rbɑ9vb|l ;'Q:=EAcuIT;RT {9Rbd[rVbyfn"hCCFmSDFLqqS A>.h~mwÊϪr(Ci ohv>N` wk0Zr?|'CF(B6N'WqT;Fd(P3?Y$"lxATҞCL+ ISV{̶xJ{I𛳡nO|TWڕ4-dBd0-KR)n?n랖z;c(2cTmAuk~y?Y\_7,!V*%Dr$LdƝv0CܸSC]gq0x2.a,6kMDFV:TcaMGi*"[,v|૔`z\}O^{>w[I7~l(vTe^8XǟM;(ecqYK xPt3)m\*^@[vjp-I!.{_b|f[rI췫%jN?T߾YՖ.1tNVH=J&@OR.&>hɢQ.RQ^I׀;Zݪ+8//irGɘ]ƒ+AY