v13i048: xmail, Part06/11

Michael Wagnitz stratus!voder!nsc!berlioz.nsc.com!michael at uunet.UU.NET
Sun Jun 16 05:44:45 AEST 1991


Submitted-by: stratus!voder!nsc!berlioz.nsc.com!michael at uunet.UU.NET (Michael Wagnitz)
Posting-number: Volume 13, Issue 48
Archive-name: xmail/part06

#! /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 6 (of 11)."
# Contents:  CHANGES Mailwatch.c
# Wrapped by michael at harley on Fri May  3 13:35:51 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'CHANGES' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'CHANGES'\"
else
echo shar: Extracting \"'CHANGES'\" \(22045 characters\)
sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
X
X                                                                 April, 1991
X
X   The following changes have been effected for Patchlevel 3 of xmail.
X
X  Many, many bugs have been fixed, and the overall size of the resident image
Xhas been cut almost in half.  I also believe I have correct all memory leaks.
X
X  Support is now provided for displaying the content of an X-Face: header, as
Xa compile time option.  If you currently have the compface library routines
Xprovided by James Ashton, see the Imakefile and change the flags accordingly.
XThe compface library routines are available from the Rich Burridge Archive
XServer, at <rb-archive-server at Aus.Sun.COM>.  Send the one word subject "Help"
Xif you have never used this archive-server before.  These routines are
Xalso included as part of Rich Burridge's faces program, also available from
Xthat same address.
X
X
XImakefile:	Eliminated R3 support and changed number and type of defines
X
XHelpText.c:	Modified some text and added information messages for commands
X
XMailwatch.c:	Added support to display either user or mail host name in icon
X		Changing the icon tag also changes the application title for
X		window managers, for those cases when more than one copy of the
X		program being run.  Removed support for X11R[23].
X
Xactions.c:	Removed support for X11R3.  Changed ``Send'' completion popup
X		to use callbacks instead of action routines.  Eliminated need
X		for DoAutograph() and DoDone() action routines.  Changed routine
X		SelectionNumber() to use greater-than mark as reference instead
X		of current insertion pointer, because forward/backward-page
X		et.al. messed with current insertion pointer location.  Added
X		support for WM_DELETE_WINDOW protocol requests to DoQuit().
X		Added information messages for each command button.  Message
X		content is triggered by enter/leave notify events, ala xrn.
X		Cleaned up error messages to use XtError().  Consolidated
X		various popup positioning routines into SetXY().  Changed
X		SetCursor() from XtActionProc to void and moved it to utils.c
X
XcallMail.c:	Added (UNTESTED) support for non-BSD style communications.
X		The additional code was taken from the X11R4 sources for xterm.
X		Non-BSD routines are untested by the author, as I do not have
X		access to a System-V environment.  Eliminated hanging of the
X		parent (for approximately 15 seconds) on close of the slave
X		connection due to child terminated for lack of mail before
X		the parent could issue it's close statement.  Fixed the bug for
X		not displaying tabs in messages.
X
Xcallbacks.c:	Call the alias() extraction routine recursively, to accommodate
X		nested user aliases.  Also pass the recipient list to sendmail
X		on the command line, in lieu of the ``-t'' option, to eliminate
X		a bug which sometimes caused sendmail to think the author of
X		the message was actually one of the recipients.  Add the USENIX
X		X-Face: header to outgoing messages, if a ``.face'' file exists
X		in the user's home directory.  Corrected a bug because System-V
X		sprintf() does not return a pointer to the buffer.  Corrected
X		redundant usage of XtNameToWidget() calls.  Changed occurrences
X		for all of index() to strchr() to eliminate bug under SunOS_4+.
X		Changed search for author in incoming messages to use ``From:'',
X		``Return-Path:'', and finally ``From '' header fields.  Changed
X		control loop for confirms and ``Send'' completion popups so
X		that they will be displayed even if the parent is obscured.
X		Changed ``outfolder'' to work as documented in Mail man page.
X		Fixed Done routine to not create header files when aborting a
X		message composition.
X
Xdefs.h:		Eliminated some global variables and support for X11R3.  Added
X		declaration for editorCommand resource, and support for those
X		environments which do not include a wait3() system call.
X
Xdirectory.c:	Changed define declaration to USE_DIRENT, because structure
X		dependency is not SUN_OS dependent.
X
Xenvirons.c:	Changed occurrences of index() to strchr().  Added support for
X		braced and quoted environment variables.  Added recursive
X		parsing of the .mailrc file for ``source''d files.  Added
X		recursive parsing of the aliases for addresses, carbon, and
X		blind copies.  Merged the extraction of aliases and set options
X		from the mailrc file into one routine.  This routine now also
X		supports continuation lines, and returns the LAST occurance of
X		the targeted set option.  This last point fixes a bug where the
X		user declared a prompt string more than once in the mailrc
X		file.  Mail would use the second one, while previous version of
X		xmail were looking for the first and hanging indefinitely.
X
Xhandler.c:	Added info_handler() to write command button window explanation
X		messages in the status window on enter/leave-notify events.
X		Fixed bug in placing marker for current message.  Changed all
X		occurrences of index() to strchr().  Fixed bug in index_handler
X		when the current message index went to zero due to a loss of
X		sync with the incoming text from Mail.  This would occur if the
X		user pressed the read next/previous message keys too rapidly.
X
Xmail.c:		Added support for the editorCommand resource, ala xrn.  This
X		resource allows the user to specify an ``sprintf''-able string
X		which defines the editor to use when composing messages.  Users
X		must supply two ``%s'' entry points, one for the name of the
X		X display connection and one for the name of the edited file.
X		Fallback to the previous VISUAL methodology, if editorCommand
X		specification does not meet requirements.  Corrected a bug
X		which prevented the ``Send'' popup from appearing if the parent
X		shell was partially or totally obscured.  Made the ``Send''
X		popup reusable, instead of destroying and recreating it each
X		time.  Accommodated people who insist on setting a wide border.
X
Xnational.bm:	Resized the logo to a larger format, to better fit the titleBar.
X
Xparser.c:	Corrected a bug for those cases when the mail process would
X		disappear unexpectedly.  Loss of connection no longer causes
X		a runaway condition.  Fixed a bug in the START process which
X		chewed up CPU seconds when started iconic.  Restored function-
X		ality for the no-autoprint option, which also fixed a bug of
X		occasionally seeing titlebar or status info in the text window
X		when issuing read previous/next commands in rapid fashion.
X
Xrevtable.h:	Used in un-compressing X-Face headers.
X
Xutils.c:	Added support for proportionally spaced fonts, using routine
X		figureWidth().  Added support for X-Face headers on in-coming
X		messages.  If found, the X-Face will be displayed in the upper
X		right-hand corner of the text window.  Modified Bell() routine
X		to not replace message text in status window if previous text
X		was for an error.
X
Xwindows.c:	Moved a majority of the action translation tables to the XMail
X		class resource file, to allow the user more flexibility.
X
Xxmail.c:	Changed the startup procedure to not start in the system folder
X		if starting iconic, to prevent ``newmail'' flag from being reset
X		before the user has opened the icon for the first time.  Added
X		separate font declarations for help, text, and button fonts.
X		Added resources and command line options for disabling the new
X		info feature and for specifying the editorCommand format string.
X		Fixed calculations for overall shell size if user has specified
X		a proportional font or wide borders, to keep xmail shell within
X		root window boundaries.
X
XThe following persons have sent in suggestions, complaints, and/or patches
Xwhich have contributed to the development of this patchlevel.  In most cases,
XI was able to respond directly to the submitter using the address indicated.
XIn some cases, mail would bounce and I could not reach them with a thank-you.
XIn any case, I wish to express my deepest gratitude to all for their interest
Xand assistance.  If I have inadvertently managed to leave someone's name off
Xof this list, please forgive me (and thanks again).
X
XAlan M. Baum	<abaum at amb.cs.gmr.com>
X	requested the ability to recursively parse an alias during ``Send''
X
XDana A. Chee	<dana at thumper.bellcore.com>
X	one of many to request resources be moved to the application defaults
X
XDamian Chu	<dac at doc.imperial.ac.uk>
X	forced me (%^) to add WM_DELETE_WINDOW protocol support  (thanks)
X 
XNed Danieley	<ndd at sunbar.mc.duke.edu>
XFrank Peters	<fwp1 at cc.msstate.edu>				and
XThomas Oeser	<thomas%apgraph%ap542 at ztivax.siemens.com>
X	identified problems (non-RFC822 compliance) with address parsing
X
XNorm Jacobs	<jacobs at mot.com>
X	provided suggested code patches for System-V socket connections
X
XCasey Leedom	<casey at gauss.llnl.gov>
X	identified bugs in the translation tables and suggested the addition
X	of the editorCommand resource specification
X	
XSteve Losen	<scl at virginia.edu>
X	identified bugs in the translation and regular expressions tables
X
XAndrew McRae	<andrew at megadata.mega.oz.au>			and
XPeter Morreale	<morreale at bierstadt.scd.ucar.edu>
X	identified the existence of memory leaks in patchlevel 2
X
XFrans Meulenbroeks <meulenbr at cst.philips.nl>
X	suggested the need to use the ``source'' command in .mailrc
X
XMarc H. Scholl	<scholl at inf.ethz.ch>
X	suggested changes in the ``outfolder'' variable interpretation
X
XBrian V. Smith	<envbvs at epb2.lbl.gov>
X	noted that the ``Send'' popup would not appear if the xmail parent
X	window (or icon) was obscured
X
X
X---------------------- end of changes for patchlevel 3 -----------------------
X
X                                                                August, 1990
X
X   The following changes have been effected for Patchlevel 2 of xmail.
X
X
XImakefile:	Reordered R3 and R4 dependencies to allow for R4 make depend.
X
XHelpText.c:	Corrected some text and added help for text window key actions.
X
XMailwatch.c:	Added option to start icon in reverse video.  Also added
X		option to display the username in the icon window, for those
X		times when xmail processes for more than one user are desired.
X
Xactions.c:	Changed Newmail action to NOT automatically remove the
X		current folder list when changing to the system mail folder.
X		'Drop Folders' is now a separate action selectable within the
X		Newmail command menu.  Fixed SetFolders routine to not prepend
X		the home directory to folder names beginning with either a
X		dot (.) or foreword slash (/).  Also added a COMMIT option
X		to change of folder (when current folder has deleted mail)
X		or cancel of composed message.  Commit option is tailorable
X		by -e (expert) flag, 'Preserve' menu selection, and/or resource
X		specification.  Re-edit of the current message composition is
X		now supported within the 'Send' popup 'Deliver' sub-menu.
X		Deletions in the 'Send' popup text fields will no longer force
X		the cursor position to the end of the line.  Additional error
X		messages from the mail program are also trapped.  To better
X		support variations in 'Berkeley' mail, 'set no' commands are
X		no changed to 'unset' commands.  Both forms are also parsed.
X		To allow pasting of selected text within the various windows,
X		message indexing is now indicated by a preceding greater-
X		than symbol (>) instead of highlighting using the selection
X		mechanism.
X
Xcallbacks.c:	Mechanisms for delivering mail messages are now forked to a
X		child process if possible, instead of the previous synchronous
X		system calls.  Better support for file and folder recipients
X		to messages are also included.  Changes in folder or quitting
X		with a modified folder are now confirmed, unless the expert
X		flag has been specified.  Callbacks for re-editing message
X		composition and for dropping the current folders list are also
X		added.
X
Xconfirm.c:	This is a new routine which supplys the confirmation method.
X
Xdefs.h:		Changes to accommodate 'make depend' under X11R4 .vs. X11R3.
X		Added command line option flag: expert.
X
Xdirectory.c:	Modified list display to be more box like, to help prevent
X		the menu from running off the bottom of the screen.
X
Xenvirons.c:	Improved alias parsing routines to separate real people from
X		file and folder names as recipients of mail messages.  Also
X		expanded environment variables in GetMailEnv calls.
X
Xglobals.h:	Added definitions for new routines and flags.
X
Xhandler.c:	Removed widget privates dependencies in SystemFolder routine
X		by correctly calling XtGetValues for the label of the widget.
X
Xicon.mail:	Modified bitmaps for both icons to allow for placing the
X		username under the mailbox, when requested.
X
Xmail.c:		Added editMail routine to support re-edits of message text.
X
Xparser.c:	Added ability to export the match function to other routines
X		for better handling of errors from mail.  Changed 'set no'
X		calls to 'unset's, for support of SONY NEWS OS mail program.
X		Changed message index highlighting to use the greater-than
X		symbol (>) instead.  Revert to default mail prompt of received
X		during startup, for case where user's .mailrc file fails to
X		parse before the intended prompt can be set.
X
Xutils.c:	Changed message index selection highlighting to use symbol.
X
Xwindows.c:	Added new command menu options.  Provided for cut and paste
X		operations in File and text windows.  Added second help
X		window to text area for mapping of keyboard keys to command
X		actions.  Added keyboard cursor motion commands to the Index
X		and Text windows.  Added routine to parse the icon geometry.
X
Xxmail.c:	Added support for new options: -e (expert), -iconic, and
X		-rv (reverse video on the icon).  Also default to no position
X		(0,0) for icon if not explicitly specified.
X
Xxmail.man:	Many changes to document patchlevel 2 enhancements and fixes.
X
Xxmailregex.h:	Added support for use outside of the parser routines.  Also
X		added additional error messages for users with problems in
X		their environment or .mailrc file.
X
XXMail.ad:	Changed the color specifications in the applications defaults
X		from names to hex values, to provide support when the server
X		fails to parse color names (a rare but annoying occurrence).
X		Added definitions for the new command menu buttons.
X
X
XAgain, I'd like to thank the contributors of suggestions and actual patches.
XI'd also like to thank those persons who sent in complaints and suggestions.
XIf I somehow managed to forget some of those persons, I hope they can
Xforgive me.
X
X*) Jeff Dauber was first to request the ability to re-edit new messages.
X
X*) Mark Scholl was responsible for requesting the addition of a Confirmation
X   option.
X
X*) More illegal pointer combination fixes, the ParseIconGeometry() routine,
X   and the expansion of environment variables within the GetMailEnv() routine
X   were supplied by Christos Zoulas.
X
X*) Tom Dunigan and Peter Marshall both pointed out the error of my ways in
X   handling RFC822 addresses, and supplied much needed help in making the
X   corrections.
X
X*) Peter Marshal also initiated changes to allow a greater variety of editor
X   choices, including better support for the emacs invocation.  He was also
X   one of the first to complain about the delays during delivery of messages,
X   which drove the efforts to fork off those tasks.
X
X*) David Elliott suggested the no-default icon position, the missing paste
X   ability in the File window, and the need to support 'unset' versus 'set no'
X   construct in mail.
X
X*) Suggestions from Casey Leedom precipitated the revision of the Makefile
X   depends to provide better support for make depend under Sun and X11R4.
X
X*) Questions from John Meissen prompted modifications to the way the file
X   handlers are modified when calling mail and forking edit children.  He also
X   pointed out the probability of a MAIL environment variable pointing to
X   the intended mail spool and made suggestions for changing the code.
X
X---------------------- end of changes for patchlevel 2 -----------------------
X
X                                                                   May, 1990
X
X   The following changes have been effected for Patchlevel 1 of xmail.
X
X
XImakefile:	Made improvements in dependencies and SunOS defines.
X		Removed requirement for linkage to system math library.
X
XHelpText.c:	Text revised and reformatted to better fit the help window
X
XMailwatch.c:	Corrected illegal pointer combinations and added resources
X		to allow the user to specify the number of times to ring the
X		bell when new mail has arrived.  Fixed new mail bell to ring
X		only if flag is not already up.
X
XMailwatch.h:	Eliminated warning for duplicate XtNfile definition
X
Xactions.c:	Corrected illegal pointer combinations, added support for
X		improved index handler and Blind carbon copies.  Also added
X		support for .mailrc "printmail" definition, and improved error
X		messages when attempting to select non-existent or undefined
X		mail folders.  Used integer math instead of sqrt() function to
X		calculate box dimensions for aliases list.
X
XcallMail.c:	Corrected attempts to write to read-only strings, and fixed
X		case where fork child dies for improper command arguments or
X		illegal or unfound image execution which tried to write error
X		messages to the xmail pipe instead of the terminal screen.
X		A dying child process now also terminates the xmail process.
X
Xcallbacks.c:	Added support for external sendmail function, improved index
X		handler, and mail variable 'alwaysignore' which is now used
X		to determine header levels for reply, forward, and printed
X		messages.  If recipient selection fails to find a value for
X		the <Return_Path:> to a message, the <From:> designate is now
X		used, to eliminate failures to provide a <To:> addressee.
X		Also fixed bug in replyalls which failed to pick up names from
X		the original To: field when preparing addresses for the reply.
X
Xdefs.h:		Changed TITLE definition to accommodate use of PATCHLEVEL.
X
Xenvirons.c:	Alias support has been extended to include the word 'group'
X		when manually extracting mail aliases from the user's .mailrc
X		file.  Support has also been included for continuation lines.
X		Mechanisms to expand the MAILRC environment variable definition
X		have been eliminated, so that xmail behaves more like mail.
X		Corrected a bug in getMailEnv to return 'True' for variables
X		which have no additional value, such as 'hold' or 'autoprint'.
X		Changed strchr() calls to index().
X
Xhandler.c:	Function icon_handler() has been added to switch xmail to a
X		dummy mail folder whenever the application is iconified, and
X		to switch back to the previous folder on de-iconification.
X		Improved index_handler() to eliminate repaints of the index
X		window for every deletion or undeletion.  Also added code to
X		display as many new message headers as possible, to eliminate
X		unnecessary scrolling of the index window.
X
Xmail.c:		Changed the fputs() to a write() to help eliminate i/o hanging,
X		added Blind Carbon Copy support to the sendMail function, and
X		added XMail class resources to the xterm message entry window.
X		Changed strrchr() call declarations to rindex().
X
Xparser.c:	Eliminated multiple redraws of the index window during message
X		deletions, and corrected index message markers for 'N'ew,
X		'D'eleted, and undeleted mail messages.  Corrected a bug in the
X		delete processing to not reread entire message and corrected a
X		bug to erase index and text window datas if no current folder.
X
Xutils.c:	Added use of PATCHLEVEL in determining TITLE version revision
X		and changed calls for strchr() to index().
X
Xwindows.c:	Changed name of "hold" button to "preserve", to better match
X		error message text when used incorrectly, eliminated making
X		the preserve button insensitive, to allow use of "set" menu
X		in any folder, added a "set" menu to the "preserve" command
X		button, to toggle mail variables, "alwaysignore", "autoprint",
X		and "hold", and corrected character processing in the file
X		window, to allow deletion and insertion within the line,
X		instead of always at the end.  Added use of PATCHLEVEL in
X		determining TITLE version revision
X
Xxmail.c:	added support for the -iconic command line option, corrected
X		resource handling for iconGeometry, and improved default font
X		handling for minimum dimensions of the xmail application window.
X		Also fixed processing of geometry specifications for the top
X		level window.  Update the 'what' database string to reflect
X		current version.
X
X
X
XI would like to thank the many contributors of suggestions and actual patches.
XI would also like to thank those persons who sent in complaints, as they were
Xoften the predictors of the many other corrections and enhancements to xmail. 
X
X*) Message size tests in parser.c were extended to include support for DEC
X   mail return on size requests, to prevent core dumps under Ultrix UWS 2.2
X   thanks to patches from Dirk Grunwald <grunwald at foobar.Colorado.EDU>
X
X*) Corrections to Imakefile to eliminate the need to set SunOS dependency
X   flags manually were driven by suggestions from Casey Leedom
X   <casey at gauss.llnl.gov> and David Elliott <dce at smsc.sony.com>.
X
X*) The regular expressions definitions in xmailregex.h were corrected as a
X   result of suggestions from Casey Leedom.
X
X*) Suggestions from Casey Leedom, Mark Williams <msw at cpsc.UCalgary.CA>,
X   and Mark Scholl <scholl at inf.ethz.ch> helped identify a problem in the
X   communications links with mail.  writeMail() now uses a write instead
X   of fputs, and the connection parameters are set for APPEND instead of
X   non-blocking i/o, to eliminate run-away cpu cycles.
X
X*) Many, many illegal pointer combination errors were identified and corrected
X   by Christos Zoulas <christos at guillemin.EE.cornell.edu>
X
X*) Thanks go to Robert Viduya <robert at shangri-la.gatech.ude> for suggestions
X   and assistance in adding an icon handler to switch to a dummy mail folder
X   during iconification, to prevent collisions in mail if run from another
X   process while xmail is running.
X
X*) Support for an alternate sendmail function was provided after receiving
X   suggestions from Jim Blythe <jsblythe%uk.co.gec-mrc at nsfnet-relay.ac.uk>
X
X*) Blind carbon copy support and correction of several bugs were suggested
X   by Jeff Dauber <dauber at parns.nsc.com>
X
X*) Support for mail variables autoprint and hold were corrected thanks to
X   requests from Dwayne Lee <dwayne at asic.nsc.com>
X
END_OF_FILE
if test 22045 -ne `wc -c <'CHANGES'`; then
    echo shar: \"'CHANGES'\" unpacked with wrong size!
fi
# end of 'CHANGES'
fi
if test -f 'Mailwatch.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Mailwatch.c'\"
else
echo shar: Extracting \"'Mailwatch.c'\" \(20783 characters\)
sed "s/^X//" >'Mailwatch.c' <<'END_OF_FILE'
X/*
X * @(#)Mailwatch.c - MODIFIED for use as an active icon in the xmail program.
X *
X * Author:  Dan Heller <island!argv at sun.com>
X * This code was stolen from Mailbox.c --the widget which supports "xbiff"
X * written by Jim Fulton which was apparently stolen from Clock.c, the widget
X * which supports "xclock."  Note, you are witnessing the big bang theory of
X * software development (everything is a subclass of universeWidgetClass).
X *
X * Major changes:
X * XtRemoveTimeOut() is called before calling XtAddTimeOut().  The original
X * xbiff would eventually timeout all the time rather than every 30 seconds
X * because the old timer was never removed.
X *
X * User can specify any icon he chooses for either the up flag or the down
X * flag.  Icons don't need to be the same size (defaults to flagup/flagdown).
X *
X * When new mail comes in, a user supplied callback function is invoked.
X *
X * The mailbox flag goes up when there is new mail _and_ the user hasn't
X * read it yet.  As soon as the user updates the access time on the mailbox,
X * the flag goes down.  This removes the incredibly annoying habit xbiff
X * had where you read some mail but not delete it from the mailbox and the
X * flag would remain up.
X *
X * Destroy() will now destroy the flagup and flagdown pixmaps.
X *
X** November 1990 - Michael C. Wagnitz - National Semiconductor Corporation
X** The following modifications were made for use in xmail.
X**
X** Added options to display username or mail server host name in icon window.
X**
X** November 1989 - Michael C. Wagnitz - National Semiconductor Corporation
X**
X** Removed button handler, custom cursor, and 'from()' reader functions.
X** Added reset_mailbox() function, my own icons (56x56 bits), and also
X** added timer initialization to Initialize() routine (we might not ever be
X** Realized, if the user never iconifies my parent).  This also fixes a Sun4
X** bug for trying to remove an initial interval_id with a garbage address.
X** Also changed check_mailbox() to test access time vs. modified and zero size
X** of file, rather than trying to track our last access or increase in size.
X**
X** Copyright 1990 by National Semiconductor Corporation
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose is hereby granted without fee, provided that
X** the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation, and that the name of National Semiconductor Corporation not
X** be used in advertising or publicity pertaining to distribution of the
X** software without specific, written prior permission.
X**
X** NATIONAL SEMICONDUCTOR CORPORATION MAKES NO REPRESENTATIONS ABOUT THE
X** SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS"
X** WITHOUT EXPRESS OR IMPLIED WARRANTY.  NATIONAL SEMICONDUCTOR CORPORATION
X** DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
X** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN NO
X** EVENT SHALL NATIONAL SEMICONDUCTOR CORPORATION BE LIABLE FOR ANY SPECIAL,
X** INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
X** LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
X** OR OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
X** PERFORMANCE OF THIS SOFTWARE.
X**
X** The following software modules were created and are Copyrighted by National
X** Semiconductor Corporation:
X**
X** 1. reset_mailbox,
X** 2. set_host,
X** 3. set_user,
X** 4. set_none, and
X** 5. GetMailHostName.
X**
X** Author:  Michael C. Wagnitz - National Semiconductor Corporation
X**
X*/
X
X
X#include <X11/Xos.h>
X#include <X11/IntrinsicP.h>		/* for toolkit stuff */
X#include <X11/cursorfont.h>		/* for cursor constants */
X#include <X11/StringDefs.h>		/* for useful atom names */
X#include "MailwatchP.h"			/* for implementation mailbox stuff */
X#include <stdio.h>			/* for printing error messages */
X#include <sys/stat.h>			/* for stat() */
X#include <sys/param.h>			/* for MAXHOSTNAMELEN */
X#include <pwd.h>			/* for getting username */
X#include <errno.h>
X#include "icon.mail"			/* for flag up (mail present) bits */
X#include "icon.nomail"			/* for flag down (mail not here) */
X
X#include <X11/Xaw/XawInit.h>
X#include <X11/Xmu/Converters.h>		/* for XmuCvtStringToBitmap */
X
X#define between(x, i, y)   ((i) < (x) ? (x) : (i) > (y) ? (y) : (i))
X
X#define REMOVE_TIMEOUT(id) if (!id) ; else XtRemoveTimeOut(id)
X
Xstatic struct stat	stbuf;
Xstatic Boolean		SetValues();
Xstatic Pixmap		make_pixmap();
Xstatic GC		GetNormalGC(), GetInvertGC();
Xstatic void		GetMailFile(), GetUserName(), GetMailHostName(),
X			CloseDown(), check_mailbox(), redraw_mailbox(),
X			ClassInitialize(), Initialize(), Destroy(),
X			Realize(), Redisplay(), clock_tic(), set_title();
Xextern void		reset_mailbox(), set_host(), set_user(), set_none();
Xextern Widget		toplevel;
X
X#define min(a,b) ((a) < (b) ? (a) : (b))
X#define max(a,b) ((a) > (b) ? (a) : (b))
X
Xstatic char defaultTranslations[] =
X    "<Key>h:		set-host()	\n\
X     <Key>u:		set-user()	\n\
X     <Key>space:	set-none()";
X
Xstatic XtActionsRec actionsList[] = {
X    { "set-host",	set_host	},
X    { "set-user",	set_user	},
X    { "set-none",	set_none	},
X};
X
X/* Initialization of defaults */
X#define offset(field) XtOffset(MailwatchWidget,mailbox.field)
X#define goffset(field) XtOffset(Widget,core.field)
X
X
Xstatic XtResource resources[] = {
X    {XtNupdate, XtCInterval, XtRInt, sizeof(int),
X	offset(update), XtRImmediate, (caddr_t) 30 },
X    {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
X	offset(foreground_pixel), XtRString, XtDefaultForeground },
X    {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
X	goffset(background_pixel), XtRString, XtDefaultBackground },
X    {XtNreverseVideo, XtCBoolean, XtRBoolean, sizeof(Boolean),
X	offset(reverseVideo), XtRImmediate, (caddr_t) False },
X    {XtNbell, XtCBoolean, XtRBoolean, sizeof(Boolean),
X	offset(bell), XtRImmediate, (caddr_t) True },
X    {XtNfile, XtCFile, XtRString, sizeof(String),
X	offset(filename), XtRString, NULL},
X    {XtNnoMailFlag, XtCPixmap, XtRBitmap, sizeof(Pixmap),
X	offset(nomail.bitmap), XtRString, NULL},
X    {XtNmailFlag, XtCPixmap, XtRBitmap, sizeof(Pixmap),
X	offset(mail.bitmap), XtRString, NULL},
X    {XtNcallback, XtCCallback, XtRCallback, sizeof(caddr_t),
X	offset(callback), XtRCallback, NULL},
X    {"useName", XtCBoolean, XtRBoolean, sizeof(Boolean),
X	offset(useName), XtRString, "FALSE" },
X    {"useHost", XtCBoolean, XtRBoolean, sizeof(Boolean),
X	offset(useHost), XtRString, "FALSE" },
X    { XtNfont, XtCFont, XtRFontStruct, sizeof (XFontStruct *),
X	offset(font), XtRString, "fixed"},
X};
X
X#undef offset
X#undef goffset
X
XMailwatchClassRec mailwatchClassRec = {
X    {	/* core fields */
X	/* superclass		*/ &widgetClassRec,
X	/* class_name		*/ "Mailwatch",
X	/* widget_size		*/ sizeof(MailwatchRec),
X	/* class_initialize	*/ ClassInitialize,
X	/* class_part_initialize*/ NULL,
X	/* class_inited 	*/ FALSE,
X	/* initialize		*/ Initialize,
X	/* initialize_hook	*/ NULL,
X	/* realize		*/ Realize,
X	/* actions		*/ actionsList,
X	/* num_actions		*/ XtNumber(actionsList),
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		*/ Destroy,
X	/* resize		*/ NULL,
X	/* expose		*/ Redisplay,
X	/* set_values		*/ SetValues,
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		*/ defaultTranslations,
X	/* query_geometry	*/ NULL,
X    }
X};
X
XWidgetClass mailwatchWidgetClass = (WidgetClass) & mailwatchClassRec;
X
X/*
X * private procedures
X */
Xstatic Pixmap
Xmake_pixmap (dpy, w, bitmap, depth, widthp, heightp)
XDisplay		*dpy;
XMailwatchWidget	w;
XPixmap		bitmap;
Xint		depth;
Xint		*widthp, *heightp;
X{
X Window root;
X int x, y;
X unsigned int width, height, bw, dep;
X unsigned long fore, back;
X
X 
X if (bitmap == 0 ||
X     ! XGetGeometry(dpy, bitmap, &root, &x, &y, &width, &height, &bw, &dep))
X    return None;
X
X *widthp = (int) width;
X *heightp = (int) height;
X fore = w->mailbox.foreground_pixel;
X back = w->core.background_pixel;
X return XmuCreatePixmapFromBitmap(dpy, w->core.window, bitmap, 
X				      width, height, depth, fore, back);
X}
X
X
Xstatic void
XClassInitialize()
X{
X static XtConvertArgRec screenConvertArg[] = {
X    { XtWidgetBaseOffset, (caddr_t) XtOffset(Widget, core.screen), sizeof(Screen *) }
X    };
X
X XawInitializeWidgetSet();
X XtAddConverter (XtRString, XtRBitmap, XmuCvtStringToBitmap,
X		    screenConvertArg, XtNumber(screenConvertArg));
X return;
X} /* ClassInitialize */
X
X
Xstatic void
XInitialize(request, new)
XWidget request, new;
X{
X    MailwatchWidget w = (MailwatchWidget) new;
X
X    GetUserName(w);
X
X    GetMailHostName(w);
X
X    if (!w->mailbox.filename)
X	GetMailFile(w);
X
X    if (w->mailbox.reverseVideo) {
X	Pixel tmp;
X
X	tmp = w->mailbox.foreground_pixel;
X	w->mailbox.foreground_pixel = w->core.background_pixel;
X	w->core.background_pixel = tmp;
X    }
X
X    GetNormalGC(w);
X
X    GetInvertGC(w);
X
X    w->mailbox.flag_up = FALSE;		/* because it hasn't been shown yet */
X    w->mailbox.mail.pixmap = None;
X    w->mailbox.nomail.pixmap = None;
X
X    w->mailbox.last_access = (stat(w->mailbox.filename, &stbuf) == 0) ?
X                             stbuf.st_atime : 0 ;	/* last accessed */
X    return;
X}
X
X
Xstatic void
Xclock_tic(client_data, id)
Xcaddr_t client_data;
XXtIntervalId *id;
X{
X    MailwatchWidget w = (MailwatchWidget) client_data;
X
X    check_mailbox(w, FALSE);
X}
X
X
Xstatic void
Xset_title(str)
XString	str;
X{
X Display	*dpy = XtDisplay(toplevel);
X Window		win  = XtWindow(toplevel);
X String		c, name, title;
X
X
X XFetchName(dpy, win, &name);
X if (! name)
X    name = XtNewString("xmail");
X else
X    if ((c = (char *)strrchr(name, '_')) != NULL)
X        *c = '\0';
X
X if (! *str)
X    title = XtMalloc(strlen(name) + 1);
X else
X    title = XtMalloc(strlen(name) + strlen(str) + 2);
X
X if (! title)
X    XtError("xmail: Insufficient memory to allocate title space");
X
X if (! *str)
X    sprintf(title, "%s", name);
X else
X    sprintf(title, "%s_%s", name, str);
X
X XStoreName(dpy, win, title);
X
X XtFree(name);
X XtFree(title);
X} /* end - set_title */
X
X
Xvoid
Xset_host(m)
XMailwatchWidget		m;
X{
X register Display	*dpy = XtDisplay(m);
X register Window	win = XtWindow(m);
X register int		x, y, h, w;
X
X
X set_title(m->mailbox.mailhost);
X
X m->mailbox.useHost = True;
X m->mailbox.useName = False;
X h = m->mailbox.font->max_bounds.width - m->mailbox.font->max_bounds.lbearing;
X w = strlen(m->mailbox.mailhost);
X h = (h * w) - 2;
X x = max(m->core.width - h, 2);			/* if (x < 2) x = 2; */
X x /= 2;
X y = m->core.height - m->mailbox.font->descent;
X
X XFillRectangle(dpy, win, m->mailbox.invert_GC,
X                      0, y - m->mailbox.font->ascent, m->core.width,
X                      m->mailbox.font->ascent + m->mailbox.font->descent);
X
X XDrawString(dpy, win, m->mailbox.normal_GC, x, y, m->mailbox.mailhost, w);
X} /* end - set_host */
X
X
Xvoid
Xset_user(m)
XMailwatchWidget		m;
X{
X register Display	*dpy = XtDisplay(m);
X register Window	win = XtWindow(m);
X register int		x, y, h, w;
X
X
X set_title(m->mailbox.username);
X
X m->mailbox.useHost = False;
X m->mailbox.useName = True;
X h = m->mailbox.font->max_bounds.width - m->mailbox.font->max_bounds.lbearing;
X w = strlen(m->mailbox.username);
X h = (h * w) - 2;
X x = max(m->core.width - h, 2);			/* if (x < 2) x = 2; */
X x /= 2;
X y = m->core.height - m->mailbox.font->descent;
X
X XFillRectangle(dpy, win, m->mailbox.invert_GC,
X                      0, y - m->mailbox.font->ascent, m->core.width,
X                      m->mailbox.font->ascent + m->mailbox.font->descent);
X
X XDrawString(dpy, win, m->mailbox.normal_GC, x, y, m->mailbox.username, w);
X} /* end - set_user */
X
X
Xvoid
Xset_none(m)
XMailwatchWidget		m;
X{
X set_title("");
X m->mailbox.useHost = m->mailbox.useName = False;
X redraw_mailbox(m);
X} /* end - set_none */
X
X
Xstatic GC
XGetNormalGC(w)
XMailwatchWidget w;
X{
X    XtGCMask valuemask;
X    XGCValues xgcv;
X
X    valuemask = GCForeground | GCBackground | GCFunction | GCGraphicsExposures;
X    xgcv.foreground = w->mailbox.foreground_pixel;
X    xgcv.background = w->core.background_pixel;
X    xgcv.function = GXcopy;
X    xgcv.graphics_exposures = False;
X    w->mailbox.normal_GC = XtGetGC((Widget) w, valuemask, &xgcv);
X}
X
Xstatic GC
XGetInvertGC(w)
XMailwatchWidget w;
X{
X    XtGCMask valuemask;
X    XGCValues xgcv;
X
X    valuemask = GCForeground | GCBackground | GCFunction | GCGraphicsExposures;
X    xgcv.foreground = w->core.background_pixel;
X    xgcv.background = w->mailbox.foreground_pixel;
X    xgcv.function = GXcopy;
X    xgcv.graphics_exposures = False;	/* this is Bool, not Boolean */
X    w->mailbox.invert_GC = XtGetGC((Widget) w, valuemask, &xgcv);
X}
X
X
Xstatic void
XRealize(gw, valuemaskp, attr)
XWidget gw;
XXtValueMask *valuemaskp;
XXSetWindowAttributes *attr;
X{
X MailwatchWidget w = (MailwatchWidget) gw;
X register Display *dpy = XtDisplay(w);
X int depth = w->core.depth;
X
X
X XtCreateWindow(gw, InputOutput, (Visual *) CopyFromParent, *valuemaskp, attr);
X/*
X* build up the pixmaps that we'll put into the image
X*/
X if (w->mailbox.mail.bitmap == None)
X     w->mailbox.mail.bitmap = XCreateBitmapFromData(dpy, w->core.window,
X					mail_bits, mail_width, mail_height);
X
X if (w->mailbox.nomail.bitmap == None)
X     w->mailbox.nomail.bitmap = XCreateBitmapFromData(dpy, w->core.window,
X				no_mail_bits, no_mail_width, no_mail_height);
X
X w->mailbox.nomail.pixmap = make_pixmap (dpy, w, w->mailbox.nomail.bitmap,
X					   depth,
X					   &w->mailbox.nomail.width,
X					   &w->mailbox.nomail.height);
X
X w->mailbox.mail.pixmap = make_pixmap (dpy, w, w->mailbox.mail.bitmap,
X					  depth,
X					  &w->mailbox.mail.width,
X					  &w->mailbox.mail.height);
X    /* the size of the icon should be the size of the larger icon. */
X if (w->core.width == 0)
X     w->core.width = max(w->mailbox.mail.width, w->mailbox.nomail.width);
X if (w->core.height == 0)
X     w->core.width = max(w->mailbox.mail.height, w->mailbox.nomail.height);
X
X/* set status check timer */
X w->mailbox.interval_id = XtAddTimeOut(w->mailbox.update * 1000,
X	                                        clock_tic, (caddr_t) w);
X}
X
Xstatic void
XDestroy(gw)
XWidget gw;
X{
X    MailwatchWidget w = (MailwatchWidget) gw;
X    Display	*dpy = XtDisplay(gw);
X
X    XtFree(w->mailbox.filename);
X    XtFree(w->mailbox.username);
X    XtFree(w->mailbox.mailhost);
X    REMOVE_TIMEOUT(w->mailbox.interval_id);
X    XtReleaseGC(w, w->mailbox.normal_GC);
X    XFreePixmap(dpy, w->mailbox.mail.bitmap);
X    XFreePixmap(dpy, w->mailbox.mail.pixmap);
X    XFreePixmap(dpy, w->mailbox.mail.mask);
X    XFreePixmap(dpy, w->mailbox.nomail.bitmap);
X    XFreePixmap(dpy, w->mailbox.nomail.pixmap);
X    XFreePixmap(dpy, w->mailbox.nomail.mask);
X}
X
Xstatic void
XRedisplay(gw)
XWidget gw;
X{
X    MailwatchWidget w = (MailwatchWidget) gw;
X
X    REMOVE_TIMEOUT(w->mailbox.interval_id);
X    check_mailbox(w, TRUE);
X}
X
X
X/*
X** Modified to NOT update the mail file timestamp via utimes(), and to
X** ignore state change where mail adds a status record to the message.
X** The first eliminates collisions with mail during delivery, and the
X** second eliminates false triggers for new mail.  The number of times
X** the terminal bell is rung is controlled by the same .mailrc resource
X** (bell) used by Sunview's mailtool.
X*/
Xstatic void
Xcheck_mailbox(w, force_redraw)
XMailwatchWidget w;
XBoolean force_redraw;
X{
X int		i, redraw = 0;
X char		*p = NULL;
X
X
X if (stat(w->mailbox.filename, &stbuf) < 0) {		/* no mail file */
X    if (w->mailbox.flag_up == TRUE) {
X       force_redraw = 0;
X       UnsetNewmail(w, NULL, NULL);
X      }
X   } else {
X    if (stbuf.st_atime > stbuf.st_mtime &&
X        stbuf.st_atime >= w->mailbox.last_access) {	/* mail was seen */
X       w->mailbox.last_access = stbuf.st_atime;
X       if (w->mailbox.flag_up == TRUE) {
X          force_redraw = 0;
X          UnsetNewmail(w, NULL, NULL);
X         }
X      } else {
X       if (stbuf.st_size != 0 && 
X           stbuf.st_mtime > w->mailbox.last_access) {	/* got new mail */
X          w->mailbox.last_access = stbuf.st_mtime;
X          if (w->mailbox.flag_up == FALSE) {
X             if (w->mailbox.bell) {
X                i = 1;
X                if (p = (char *)GetMailrc("bell"))
X                   sscanf(p, "%d", &i);
X                i = between(1, i, 5);
X                for (; i > 0; i--)
X                    XBell(XtDisplay(w), MAILBOX_VOLUME);
X               }
X             w->mailbox.flag_up = TRUE;
X             redraw = TRUE;
X             XtCallCallbacks(w, XtNcallback, NULL);
X            }
X         }
X      }
X   }
X
X if (redraw || force_redraw)
X    redraw_mailbox(w);
X
X /* reset timer */
X w->mailbox.interval_id = XtAddTimeOut(w->mailbox.update * 1000,
X	clock_tic, (caddr_t) w);
X} /* check_mailbox */
X
X/*
X** Retrieve the user's mailbox filename - use MAIL environment value, if set
X*/
Xstatic void
XGetMailFile(w)
XMailwatchWidget w;
X{
X if (! (w->mailbox.filename = (char *) GetMailEnv("MAIL"))) {
X    if (! (w->mailbox.filename = (String) XtMalloc(strlen(MAILBOX_DIRECTORY) + 1
X	  + strlen(w->mailbox.username) + 1))) {
X       fprintf(stderr, "Mailbox widget: can't allocate enough memory.\n");
X       CloseDown(w, 1);
X      }
X    sprintf(w->mailbox.filename,"%s/%s\0",MAILBOX_DIRECTORY,w->mailbox.username);
X   }
X} /* GetMailFile */
X
X
X/*
X** Retrieve the mailbox user's name
X*/
Xstatic void
XGetUserName(w)
XMailwatchWidget w;
X{
X char *username = (char *)getlogin();
X
X if (! username) {
X    struct passwd *pw = getpwuid(getuid());
X
X    if (! pw) {
X       fprintf(stderr, "Mailbox widget: can't find your username.\n");
X       CloseDown(w, 1);
X      }
X    username = pw->pw_name;
X   }
X
X if (! (w->mailbox.username = XtNewString(username))) {
X    XtWarning("Mailbox widget: can't allocate space for username.\n");
X    CloseDown(w, 1);
X   }
X} /* GetUserName */
X
X
X/*
X** Retrieve the mail server's host name
X*/
Xstatic void
XGetMailHostName(w)
XMailwatchWidget w;
X{
X FILE	*stream, *popen();
X char	buf[BUFSIZ], hostname[MAXHOSTNAMELEN], *mailhost = NULL;
X int	n;
X
X
X sprintf(buf, "/usr/lib/sendmail -bv %s < /dev/null", w->mailbox.username);
X if (stream = popen(buf, "r")) {
X    if (fgets(buf, BUFSIZ, stream)) {
X       for (n = 0; buf[n] && buf[n] != '@'; n++);
X       if (! buf[n])
X          n = strlen(w->mailbox.username);
X       mailhost = &buf[++n];			/* starting beyond username */
X       for (; buf[n] && buf[n] != '.'; n++);	/* until we find ellipsis */
X       buf[n] = '\0';
X      }
X    pclose(stream);
X   }
X
X if (*mailhost == NULL) {
X    gethostname(hostname, MAXHOSTNAMELEN);
X    mailhost = hostname;
X   }
X
X if (! (w->mailbox.mailhost = XtNewString(mailhost))) {
X    XtWarning("Mailbox widget: can't allocate space for mailhost.\n");
X    CloseDown(w, 1);
X   }
X} /* GetMailHostName */
X
X
Xstatic void
XCloseDown(w, status)
XMailwatchWidget w;
Xint status;
X{
X    Display *dpy = XtDisplay(w);
X
X    XtDestroyWidget(w);
X    XCloseDisplay(dpy);
X    _exit(status);
X}
X
Xstatic Boolean
XSetValues(gcurrent, grequest, gnew)
XWidget gcurrent, grequest, gnew;
X{
X    MailwatchWidget current = (MailwatchWidget) gcurrent;
X    MailwatchWidget new = (MailwatchWidget) gnew;
X    Boolean redisplay = FALSE;
X
X    if (current->mailbox.update != new->mailbox.update) {
X	REMOVE_TIMEOUT(current->mailbox.interval_id);
X	new->mailbox.interval_id = XtAddTimeOut(new->mailbox.update * 1000,
X	    clock_tic,
X	    (caddr_t) gnew);
X    }
X    if (current->mailbox.foreground_pixel != new->mailbox.foreground_pixel ||
X	current->core.background_pixel != new->core.background_pixel) {
X	XtReleaseGC(current, current->mailbox.normal_GC);
X	GetNormalGC(new);
X	redisplay = TRUE;
X    }
X    return (redisplay);
X}
X
X/*
X * drawing code
X */
Xstatic void
Xredraw_mailbox(m)
XMailwatchWidget m;
X{
X    register Display	*dpy = XtDisplay(m);
X    register Window	win = XtWindow(m);
X    register int	x, y;
X    Pixel		back = m->core.background_pixel;
X    GC			gc = m->mailbox.normal_GC;
X    struct _mbimage	*im;
X
X
X    if (m->mailbox.flag_up)			/* paint the "up" position */
X	im = &m->mailbox.mail;
X    else					/* paint the "down" position */
X	im = &m->mailbox.nomail;
X
X    /* center the picture in the window */
X    x = ((int)m->core.width - im->width) / 2;
X    y = ((int)m->core.height - im->height) / 2;
X
X    XSetWindowBackground(dpy, win, back);
X    XClearWindow(dpy, win);
X    XCopyArea(dpy, im->pixmap, win, gc, 0, 0, im->width, im->height, x, y);
X
X    if (m->mailbox.useHost || m->mailbox.useName) {
X       if (m->mailbox.useHost) set_host(m);
X       else set_user(m);
X      }
X}
X
X
Xvoid
Xreset_mailbox(gw)
XWidget	gw;
X{
X MailwatchWidget w = (MailwatchWidget) gw;
X
X w->mailbox.flag_up = FALSE;
X redraw_mailbox(w);
X} /* reset_mailbox */
END_OF_FILE
if test 20783 -ne `wc -c <'Mailwatch.c'`; then
    echo shar: \"'Mailwatch.c'\" unpacked with wrong size!
fi
# end of 'Mailwatch.c'
fi
echo shar: End of archive 6 \(of 11\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 11 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 Heller
O'Reilly && Associates       Z-Code Software    Comp-sources-x:
Senior Writer                President          comp-sources-x at uunet.uu.net
argv at ora.com                 argv at zipcode.com



More information about the Comp.sources.x mailing list