home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
x
/
volume14
/
xmalarm
/
part02
< prev
next >
Wrap
Text File
|
1991-10-08
|
58KB
|
2,573 lines
Path: uunet!sun-barr!cronkite.Central.Sun.COM!newstop!exodus!mips.com
From: peebles@mips.com (Andrew Peebles)
Newsgroups: comp.sources.x
Subject: v14i081: Motif Alarm program, Part02/02
Message-ID: <21242@exodus.Eng.Sun.COM>
Date: 9 Oct 91 01:27:45 GMT
References: <csx-14i080-xmalarm@uunet.UU.NET>
Sender: news@exodus.Eng.Sun.COM
Lines: 2561
Approved: argv@sun.com
Submitted-by: peebles@mips.com (Andrew Peebles)
Posting-number: Volume 14, Issue 81
Archive-name: xmalarm/part02
Xalarm is a Motif-based personal reminder and clock program.
#---------------------------------- cut here ----------------------------------
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by peebles@wildcat on Fri Aug 23 14:21:30 PDT 1991
#
# This archive contains:
# SetArg.c
# arm.c
# at.c
# help.c
# image.c
# view.c
# xalarm.c
# xalarm_d.c
#
LANG=""; export LANG
echo x - SetArg.c
cat > SetArg.c << '@EOF'
#include "copyright.h"
#ident "$Header: SetArg.c,v 4.3 90/12/27 13:17:18 mar Exp $"
#include <stdio.h>
#include <ctype.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xos.h>
#include <sys/stat.h>
#include <varargs.h>
/*
* Function SetArgs
*
* SetArgs fills an ArgList (an array of Args) with a given list of values.
* The list of values is NULL terminated.
*
* SetArgs returns the number of arguments that were set.
*
* EXAMPLE USAGE:
*
* int n;
* Arg args[10];
*
* n = SetArgs (args,
* XmNwidth, 10,
* XmNheight, 20,
* NULL);
* XtSetValues (w, args, n);
*/
SetArgs(va_alist)
va_dcl
{
va_list a;
/* The first argument is the array to fill. */
register ArgList this_arg;
/* Others are name and value pairs. */
String name;
/* How many Args have we set? */
int count = 0;
va_start(a);
this_arg = va_arg(a, ArgList);
while ((name = va_arg(a, String)) != NULL)
{
XtSetArg(this_arg[count], name, va_arg(a, XtArgVal));
++count;
}
va_end(a);
return count;
}
/*
* New shared function between xalarm and xalarm_display. This function
* reads xalarm message files and attempts to handle both the new and old
* text formats, biased towards the new. If it encounters an old format
* file, it will automatically convert it to new.
*/
char *
ReadMessageText (fname)
char *fname;
{
char *text;
int size, fsize;
int fd;
struct stat buf;
if ((fd = open (fname, O_RDONLY, 0644)) == -1) {
return(NULL);
}
if (fstat(fd, &buf) == -1) {
fclose(fd);
return(NULL);
}
size = buf.st_size;
text = (char *) XtMalloc (size+2);
read (fd, text, size);
close (fd);
/*
* Does the first character look printable? If not its probably the
* old format and we got to read it that way.
*/
if (!isprint(text[0])) {
if ((fd = open (fname, O_RDONLY, 0644)) == -1) {
return(NULL);
}
read (fd, &size, sizeof(int));
text = (char *) XtMalloc (size+2);
read (fd, text, size);
close (fd);
/*
* And write it back out again. If the write fails, just ignore it!
*/
if ((fd = open (fname, O_WRONLY)) != -1) {
write (fd, text, size);
close (fd);
}
}
/*
* text now contains the message text
*/
text[size] = '\0';
return (text);
}
@EOF
echo x - arm.c
cat > arm.c << '@EOF'
#include "copyright.h"
#ident "$Header: arm.c,v 4.2 90/12/27 13:18:02 mar Exp $"
/***************************************************************************
*
* FILE NAME : arm.c
*
* AUTHOR : Andrew Peebles
*
* DESCRIPTION : The routines for auto-repeat feature on forward
* and reverse keys on the main xalarm display
*
* VERSIONS : @(#)arm.c 1.1
*
***************************************************************************/
/*
* standard includes
*/
#include <stdio.h>
#include <Xm/Xm.h>
void RepeatTimeOut();
XtIntervalId repeatId = 0;
extern Widget top;
extern int RepeatDelay;
extern int InitialDelay;
void
arm (w, client, call)
Widget w;
void (*client)(); /* fwd or rev callback function pointer */
caddr_t call;
{
/*
* client (w, NULL, NULL)
* tid = addTimeOut (initialDelay)
*/
client (w, NULL, NULL);
XSync (XtDisplay (top), False);
repeatId = XtAppAddTimeOut (XtWidgetToApplicationContext(top),
InitialDelay,
RepeatTimeOut,
client);
}
void
disarm (w, client, call)
Widget w;
caddr_t client, call;
{
/*
* if (tid)
* removeTimeOut (tid)
*/
if (repeatId != 0)
XtRemoveTimeOut (repeatId);
repeatId = 0;
}
void
RepeatTimeOut (func, id)
void (*func)();
XtIntervalId id;
{
func (0, NULL, NULL);
XSync (XtDisplay (top), False);
repeatId = XtAppAddTimeOut (XtWidgetToApplicationContext(top),
RepeatDelay,
RepeatTimeOut,
func);
}
@EOF
echo x - at.c
cat > at.c << '@EOF'
#include "copyright.h"
/*
* standard includes
*/
#include <stdio.h>
#include <X11/Xos.h>
#include <pwd.h>
#include "at.h"
#ifdef USE_SYSV_AT
#define ATSYS "sysv"
#else
#define ATSYS "bsd"
#endif
static char *user = NULL;
int
at_command (hour, minute, month, day, file, idfile, id, cmd)
int hour, minute;
char *month;
int day;
char *file, *idfile;
char *id;
int cmd;
{
char com[1024];
int status;
if (!user) {
struct passwd *p = (struct passwd *) getpwuid(getuid());
user = p->pw_name;
}
switch (cmd) {
case AT_SUBMIT:
sprintf (com, "xat %s %s submit xxx %02d%02d %s %d %s > %s 2> %s",
ATSYS, user,
hour, minute,
month, day,
file, idfile, idfile);
status = system(com);
break;
case AT_LIST:
sprintf (com, "xat %s %s list xxx xxx xxx xxx xxx",
ATSYS, user);
status = system(com);
break;
case AT_REMOVE:
sprintf (com, "xat %s %s remove %s xxx xxx xxx xxx",
ATSYS, user, id);
status = system(com);
break;
}
return (status);
}
@EOF
echo x - help.c
cat > help.c << '@EOF'
#include "copyright.h"
#ident "$Header: help.c,v 4.2 90/12/27 13:20:50 mar Exp $"
/***************************************************************************
*
* FILE NAME : help.c
*
* AUTHOR : Andrew Peebles
*
* DESCRIPTION : Contains the initial help screen code
*
* VERSIONS : @(#)help.c 1.5
*
***************************************************************************/
/*
* standard includes
*/
#include <stdio.h>
#include <Xm/Text.h>
#include <Xm/PushB.h>
#include <Xm/Form.h>
#include <X11/Xos.h>
#include <sys/stat.h>
Widget dialog, text, quit;
Widget REF;
/*
* Function:
*/
Help (ref, help_file)
Widget ref;
char *help_file;
/*
* Creates and brings up the tutorial screen when xalarm is invoked for
* the first time.
*/
{
Arg args[20];
int n;
void QuitCB();
int status;
REF = ref;
dialog = XmCreateFormDialog (ref,
"help",
NULL,0);
XtManageChild (dialog);
n = SetArgs (args,
XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
NULL);
quit = XmCreatePushButton (dialog,
"quit",
args, n);
XtManageChild (quit);
n = SetArgs (args,
XmNeditMode, XmMULTI_LINE_EDIT,
XmNcolumns, 85,
XmNrows, 24,
XmNwordWrap, True,
XmNscrollHorizontal, False,
XmNautoShowCursorPosition, True,
XmNcursorPositionVisible, True,
XmNblinkRate, 0,
XmNeditable, False,
NULL);
text = XmCreateScrolledText (dialog,
"text",
args,n);
status = GetHelpInfo (text, help_file);
XtManageChild (text);
n = SetArgs (args,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, quit,
XmNleftAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
XmNeditMode, XmMULTI_LINE_EDIT,
XmNcolumns, 85,
XmNrows, 24,
NULL);
XtSetValues (XtParent(text), args, n);
XtAddCallback (quit, XmNactivateCallback, QuitCB, NULL);
XtManageChild (dialog);
return (status);
}
/*
* Function:
*/
void
QuitCB(w, client, call)
Widget w;
caddr_t client, call;
/*
* Callback attached to the quit button on the help window
*/
{
Widget box = XtParent(w);
Widget shell = XtParent (box);
XtUnmanageChild (box);
XtDestroyWidget (shell);
}
/*
* Function:
*/
GetHelpInfo (w, fname)
Widget w;
char *fname;
/*
* Read in the tutorial file and put it in the text edit widgwet.
*/
{
Arg args[5];
char *buffer;
int fp;
struct stat stats;
if ((fp = open (fname, O_RDONLY, 0644)) == -1) {
Warning (REF,"Can't open help file");
return(False);
}
fstat (fp, &stats);
buffer = (char *) XtMalloc (stats.st_size);
read (fp, buffer, stats.st_size);
XtSetArg (args[0], XmNvalue, buffer);
XtSetValues (w, args, 1);
close (fp);
return (True);
}
@EOF
echo x - image.c
cat > image.c << '@EOF'
#include "copyright.h"
#ident "$Header: image.c,v 4.2 90/12/27 13:21:12 mar Exp $"
/***************************************************************************
*
* FILE NAME : image.c
*
* AUTHOR : Andrew Peebles
*
* DESCRIPTION : Contains Xm routines for pixmap handling
*
* VERSIONS : @(#)image.c 1.4
*
***************************************************************************/
/*
* standard includes
*/
#include <stdio.h>
#include <X11/Intrinsic.h>
#include <X11/IntrinsicP.h>
#include <Xm/Xm.h>
#include "image.h"
/*
* Function:
*/
Boolean
CreateAndInstallPixmap (bits, width, height, name)
char *bits;
int width, height;
char *name;
/*
* Take parameters from a bitmap(1) include file, create an XImage and
* install it in the Motif PIXMAP cache where it can be referenced by
* name.
*/
{
XImage *image;
image = (XImage *) XtMalloc (sizeof (XImage));
image->width = width;
image->height = height;
image->data = bits;
image->depth = 1;
image->xoffset = 0;
image->format = XYBitmap;
image->byte_order = LSBFirst;
image->bitmap_unit = 8;
image->bitmap_bit_order = LSBFirst;
image->bitmap_pad = 8;
image->bytes_per_line = (width+7)/8;
return (XmInstallImage (image, name));
}
/*
* Function:
*/
Pixmap
GetPixmap (w, name)
Widget w;
char *name;
/*
* Return a PIXMAP that is stored in the Motif PIXMAP cache by name
*/
{
Pixmap p;
Arg args[5];
Pixel f,b;
XtSetArg (args[0], XmNforeground, &f);
XtSetArg (args[1], XmNbackground, &b);
XtGetValues (w, args, 2);
p = XmGetPixmap (w->core.screen,
name,
f, b);
return (p);
}
/*
* Function:
*/
void
InstallDefaultPixmaps ()
/*
* Install the standard dialog pixmaps in the PIXMAP cache. I stole
* these from the dialog widgets provided by Motif. They are nice lookin
* bitmap images.
*/
{
XImage *image;
CreateAndInstallPixmap (errorBits,
errorWidth,
errorHeight,
"xm_error");
CreateAndInstallPixmap (infoBits,
infoWidth,
infoHeight,
"xm_info");
CreateAndInstallPixmap (questionBits,
questionWidth,
questionHeight,
"xm_question");
CreateAndInstallPixmap (warningBits,
warningWidth,
warningHeight,
"xm_warning");
CreateAndInstallPixmap (workingBits,
workingWidth,
workingHeight,
"xm_working");
}
@EOF
echo x - view.c
cat > view.c << '@EOF'
#include "copyright.h"
#ident "$Header: view.c,v 4.4 90/12/27 13:22:16 mar Exp $"
/***************************************************************************
*
* FILE NAME : view.c
*
* AUTHOR : Andrew Peebles
*
* DESCRIPTION : routines to view pending alarms
*
* VERSIONS : @(#)view.c 1.5
*
***************************************************************************/
/*
* standard includes
*/
#include <stdio.h>
#include <ctype.h>
#include <X11/Xos.h>
#ifdef BSD43
#include <sys/dir.h>
#else
#include <dirent.h>
#endif
#include <sys/stat.h>
#include <Xm/SelectioB.h>
#include "at.h"
extern Widget top;
extern char *display_name;
Widget REF_WIDGET_SELECT;
extern char *ReadMessageText();
extern int at_command();
/*
* This stucture is used as an entry in an array and contains the
* information pertaining to an alarm. The alarm file directory is
* scaned, and for each pending alarm a structure is created and filled
* out and added to the array of pending alarms.
*/
typedef struct _message_item {
char *atID; /* the ID returned by at */
char *date; /* time this alarm will go off */
char *first_10_chars; /* first 10 chars of alarm message */
char *filename; /* basename of the alarm files */
} message_item;
/*
* this array contains the pending alarms. note that there can be a MAX
* of 1K pending at any given time.
*/
message_item *messages[1024];
int num_messages = 0;
/*
* Function:
*/
MakeList (dir)
char *dir;
/*
* Scan the alarm file directory and fill out the messages[] array
*/
{
DIR *dirp;
#ifdef BSD43
struct direct *item;
#else
struct dirent *item;
#endif
char message[120];
char *ext();
char *CopyString();
if ((dirp = opendir (dir)) == NULL) {
sprintf (message,"Can't open %s to read pending alarms",dir);
Warning (top,message);
return(0);
}
num_messages = 0;
for (item = readdir(dirp); item != NULL; item = readdir(dirp)) {
if (strcmp(ext(item->d_name),".aid") == 0) {
messages[num_messages++] = (message_item *) XtMalloc (sizeof(message_item));
messages[num_messages -1]->filename = CopyString (item->d_name);
GetMessageInfo (messages [num_messages -1], dir, item->d_name);
}
}
closedir(dirp);
}
/*
* Function:
*/
char *
ext (str)
char *str;
/*
* return the file name extension for the passed in file
*/
{
char *p = str;
while ((*p != '.') && (*p != '\0')) ++p;
if (*p == '\0') return ("..");
else return (p);
}
/*
* Function:
*/
char *
CopyString (str)
char *str;
/*
* return a copy of the passed in string
*/
{
char *p;
p = (char *) XtMalloc (strlen(str));
strcpy(p,str);
return(p);
}
/*
* Function:
*/
GetMessageInfo (item, dir, fname)
message_item *item;
char *dir;
char *fname;
/*
* Fill in the message_item with the alarm info.
*/
{
char *basename();
char *base = basename (fname);
char text_file[512];
char aid_file[512];
FILE *fp, *fopen();
char *tok, *strtok();
char warning[120];
int size;
struct stat buf;
sprintf (text_file,"%s/%s.txt",dir,fname);
sprintf (aid_file, "%s/%s.aid",dir,fname);
if ((fp = fopen (aid_file, "r")) == NULL) {
sprintf (warning,"Can't open %s to read alarm info",aid_file);
Warning (top,warning);
return(0);
}
item->first_10_chars = ReadMessageText (text_file);
if (!item->first_10_chars) {
sprintf (warning,"Can't open %s to read alarm text",text_file);
Warning (top,warning);
fclose(fp);
return(0);
}
if (strlen(item->first_10_chars) > 10)
item->first_10_chars[9] = '\0';
StripCR (item->first_10_chars);
fgets (warning, 120, fp);
fgets (warning, 120, fp);
tok = strtok (warning," ");
item->atID = CopyString (strtok(NULL," "));
tok = strtok (NULL," ");
item->date = CopyString (strtok(NULL,"\n"));
fclose(fp);
}
/*
* Function:
*/
char *
basename (str)
char *str;
/*
* chop off the file name extension of the passed in file
*/
{
char *p = str;
while (*p != '.') ++p;
*p = '\0';
return(str);
}
/*
* Function:
*/
DumpList()
/*
* Debug routine that dumps the contents of the messages[] array
*/
{
int i;
for (i=0; i<num_messages; i++) {
printf ("at id : %s\n",messages[i]->atID);
printf ("date : %s\n",messages[i]->date);
printf ("message : %s\n",messages[i]->first_10_chars);
printf ("filename: %s\n\n",messages[i]->filename);
}
}
/*
* Function:
*/
DisplayList()
/*
* Display the contents of the messages[] array in a selectionBox widget
* where the user can view an alarm message or remove an alarm from the
* system.
*/
{
Widget select;
Widget button;
char line[80];
XmString *xmstrings;
Arg args[10];
int n,i;
void ViewAlarm(), RemoveAlarm(), HideViewer();
/*
* Create an XmStringList containing lines for each pendind alarm.
* Each line will have the time the alarm will go off and the first
* 10 charaters of the alarm message. This list will go into the
* list portion of the selectionBox widget.
*/
xmstrings = (XmString *) XtMalloc (sizeof(XmString) * num_messages);
for (i=0; i<num_messages; i++) {
sprintf (line,"%d: %s - %s",i,messages[i]->date,messages[i]->first_10_chars);
xmstrings[i] = XmStringCreateLtoR (line, XmSTRING_DEFAULT_CHARSET);
}
if (num_messages == 0)
xmstrings = NULL;
n = SetArgs (args,
XmNlistItems, xmstrings,
XmNlistItemCount, num_messages,
XmNlistLabelString, XmStringCreateLtoR("Pending Alarms",XmSTRING_DEFAULT_CHARSET),
XmNeditable, False,
XmNokLabelString, XmStringCreateLtoR("view",XmSTRING_DEFAULT_CHARSET),
XmNcancelLabelString, XmStringCreateLtoR("remove",XmSTRING_DEFAULT_CHARSET),
XmNhelpLabelString, XmStringCreateLtoR("done",XmSTRING_DEFAULT_CHARSET),
XmNmustMatch, True,
NULL);
select = XmCreateSelectionDialog (top,
"ViewMessages",
args,n);
button = XmSelectionBoxGetChild (select,
XmDIALOG_APPLY_BUTTON);
XtUnmanageChild(button);
button = XmSelectionBoxGetChild (select,
XmDIALOG_OK_BUTTON);
XtRemoveAllCallbacks (button, XmNactivateCallback);
XtAddCallback (button, XmNactivateCallback, ViewAlarm, NULL);
button = XmSelectionBoxGetChild (select,
XmDIALOG_CANCEL_BUTTON);
XtRemoveAllCallbacks (button, XmNactivateCallback);
XtAddCallback (button, XmNactivateCallback, RemoveAlarm, NULL);
XtAddCallback (select, XmNhelpCallback, HideViewer, select);
REF_WIDGET_SELECT = select;
XtManageChild (select);
}
void
HideViewer(w, shell, unused)
Widget w, shell;
caddr_t unused;
{
XtUnmanageChild (shell);
XtDestroyWidget (shell);
}
/*
* Function:
*/
void
ViewAlarm(w, client, call)
Widget w;
caddr_t client, call;
/*
* View a pending alarm message. The "displayProgram" will be used via
* a system(3c) call to display the message.
*/
{
char *item;
XmString text_string;
Arg args[5];
int n;
Widget select = XtParent(w);
Widget shell = XtParent(select);
char *tok;
int index;
char com[120];
extern char *InfoFilePath;
extern char *DisplayProgram;
char text_file[512];
n = SetArgs (args,
XmNtextString, &text_string,
NULL);
XtGetValues (REF_WIDGET_SELECT, args, n);
XmStringGetLtoR (text_string,
XmSTRING_DEFAULT_CHARSET,
&item);
if (!item) return;
if (item[0] == '\0') return;
/*
* The item in the selection buffer has its index in the messages[]
* array as its first characters. Scan this index out so we can index
* the pending alarm in the messages[] array so we can get file names.
*/
tok = strtok (item,":");
sscanf (tok,"%d",&index);
basename(messages[index]->filename);
sprintf (text_file,"%s/%s.txt",InfoFilePath,messages[index]->filename);
sprintf (com,"%s -display %s %s &",
DisplayProgram,display_name,text_file);
system(com);
}
/*
* Function:
*/
void
RemoveAlarm(w, client, call)
Widget w;
caddr_t client, call;
/*
* Remove the selected alarm from the system. We will use a call to
* "at -l" via a system(3c) call.
*/
{
char *item;
XmString text_string;
Arg args[5];
int n;
Widget select = XtParent(w);
Widget shell = XtParent(select);
char *tok;
int index;
char com[120];
extern char *InfoFilePath;
char fname[512];
n = SetArgs (args,
XmNtextString, &text_string,
NULL);
XtGetValues (REF_WIDGET_SELECT, args, n);
XmStringGetLtoR (text_string,
XmSTRING_DEFAULT_CHARSET,
&item);
if (!item) return;
if (item[0] == '\0') return;
/*
* The item in the selection buffer has its index in the messages[]
* array as its first characters. Scan this index out so we can index
* the pending alarm in the messages[] array so we can get file names.
*/
tok = strtok (item,":");
sscanf (tok,"%d",&index);
#if 0
sprintf (com,"/usr/bin/at -r %s",messages[index]->atID);
system(com);
#endif
at_command (0,0,"xx",0,"xx","xx",messages[index]->atID,AT_REMOVE);
basename (messages[index]->filename);
/*
* and remove the alarm files
*/
sprintf (fname,"rm -f %s/%s.*",InfoFilePath,messages[index]->filename);
system(fname);
/*
* And now remove it from the list
*/
XmListDeleteItem (XmSelectionBoxGetChild(REF_WIDGET_SELECT,
XmDIALOG_LIST), text_string);
/*
* and clear out the select window
*/
XmTextSetString (XmSelectionBoxGetChild(REF_WIDGET_SELECT,
XmDIALOG_TEXT), NULL);
}
/*
* Function:
*/
StripCR (str)
char *str;
/*
* convert <cr>s in string to ' ' so selection buffer don't get
* messed up
*/
{
char *p = str;
while (*p != '\0') {
if (*p == '\n') *p = ' ';
++p;
}
}
@EOF
echo x - xalarm.c
cat > xalarm.c << '@EOF'
/*
* xalarm - a Motif based personal reminder and clock program
*
* Copyright (c) 1990 MIPS Computer Systems, Inc.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted, provided
* that the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Mips Computer Systems, Inc. not
* be used in advertising or publicity pertaining to distribution of
* the software without specific, written prior permission. Mips Computer
* Systems, Inc. makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* MIPS COMPUTER SYSTEMS, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO
* THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL MIPS COMPUTER SYSTEMS,INC. BE LIABLE FOR
* ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
* CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Author: Andrew Peebles
* peebles@mips.com
*/
#ident "$Header: xalarm.c,v 4.3 90/12/27 13:22:27 mar Exp $"
static char version[] = "@(#)xalarm.c 1.7";
/***************************************************************************
*
* FILE NAME : xalarm.c
*
* AUTHOR : Andrew Peebles
*
* DESCRIPTION :
*
* Xalarm is a Motif application that displays an alarm clock on the
* screen that shows the current time in a segmented display and the
* current day of the week and date. The user can program alarms
* and enter messages that will be displayed when those alarms go off.
* Pending alarms can be viewed and purged from the system.
*
* Xalarm uses the Unix system 5 "at" command to schedule these alarms.
* Another X window program, called xalarm_display is used to display
* an alarm when it goes off. When an alarm is programmed by the
* user, three files are created. The three files use the current
* clock time as returned by time(3c) for a base. A message file,
* called <time>.txt, contains the message for that alarm. A command
* file, called <time>.com, is the file executed by at when the alarm
* will go off. The third file, called <time>.aid contains the at
* ID of the at command origianlly fired for this alarm. When an
* alarm is created by the user, this is what happens:
*
* 1. Two files are created, with the following contents:
* nnnn.com
* xalarm_display nnnn.txt
* rm nnnn.txt nnnn.aid
* exec rm nnnn.com
*
* nnnn.txt
* <size in bytes of message>
* Message Text ...
*
* 2. Then the unix at command is fired via a system(3c) call:
* at 11:00 am < nnnn.com 2> nnnn.aid
*
* The <time>.aid file is used by the Pending Alarm screen to remove
* pending alarms from the system via an "at -r <at_id>" command.
*
* VERSIONS : @(#)xalarm.c 1.7
*
***************************************************************************/
/*
* standard includes
*/
#include <stdio.h>
#include <X11/Xos.h>
#include <Xm/Xm.h>
#include <Xm/Form.h>
#include <Xm/DrawingA.h>
#include <Xm/Frame.h>
#include <Xm/PushB.h>
#include <Xm/ToggleB.h>
#include <Xm/RowColumn.h>
#include <Xm/Label.h>
#include "patchlevel.h"
/*
* digits for the segmented display
*/
#include "b0.h"
#include "b1.h"
#include "b2.h"
#include "b3.h"
#include "b4.h"
#include "b5.h"
#include "b6.h"
#include "b7.h"
#include "b8.h"
#include "b9.h"
/*
* blank bitmaps for place holders
*/
#include "blank.h"
#include "blankdots.h"
/*
* the dots between hours and minutes in the
* segmented display
*/
#include "dots.h"
/*
* button face bitmaps for the main xalarm keys
*/
#include "set.h"
#include "ffwd.h"
#include "revd.h"
#include "pwr.h"
/*
* The bitmaps above are converted to XImages for
* writing the screen. The digits are kept in the
* Digits array for ease of access, the dots are
* kept seperate.
*/
XImage *Digits[11];
XImage *DOTS;
XImage *BlankDots;
/*
* This gc is used for drawing the digits
*/
GC gc;
/*
* The main xalarm display widgets
*/
Widget top, /* top level application widget */
bb, /* a Form, holds every one together */
frame, /* frame surrounding segmented display */
rc, /* rowColumn for the toggles */
draw, /* drawingArea for the segmented display */
label, /* Label for the date */
pm_ind; /* Label for the AM/PM indicator */
/*
* These are the programming keys, ToggleButtons in the rowColumn
*/
Widget day_btn,
hour_btn,
min_btn;
/*
* These are the other buttons on the main display
*/
Widget set,
fwd,
rev,
pwr; /* the name is historical, this is the pending view button */
/*
* These two arrays are kept for ease of getting the string for a day from a
* number obtained from ctime(). The abrevs. here must be compatible with
* the Unix "at" command, as they are used to fire alarms.
*/
char *Days[] = {
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"
};
char *Months[] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
};
/*
* The Non-Widget Resources
*/
typedef struct _resoure_data {
char *FilePath; /* path to alarm files */
Boolean TickTock; /* do the dots between hour and minute blink*/
char *DisplayProgram; /* path to alarm display program */
char *HelpFile; /* path to tutorial file */
int InitialDelay; /* for begin auto repeat */
int RepeatDelay; /* for repeating auto repeat */
} resource_data, *resource_data_ptr;
static XtResource resources[] = {
{"filePath",
"FilePath",
XmRString,
sizeof (char *),
XtOffset(resource_data_ptr, FilePath),
XmRString,
NULL}, /* default will be $HOME */
{"displayProgram",
"DisplayProgram",
XmRString,
sizeof (char *),
XtOffset(resource_data_ptr, DisplayProgram),
XmRString,
NULL}, /* no default, MUST BE SPECIFIED BY USER */
{"helpFile",
"HelpFile",
XmRString,
sizeof (char *),
XtOffset(resource_data_ptr, HelpFile),
XmRString,
"/usr/lib/X11/app-defaults/xalarm/help.txt"},
{"tickTock",
"TickTock",
XmRBoolean,
sizeof (int),
XtOffset (resource_data_ptr, TickTock),
XmRString,
"True"},
{"initialDelay",
"InitialDelay",
XmRInt,
sizeof (int),
XtOffset (resource_data_ptr, InitialDelay),
XmRString,
"250"},
{"repeatDelay",
"RepeatDelay",
XmRInt,
sizeof (int),
XtOffset (resource_data_ptr, RepeatDelay),
XmRString,
"50"}
};
/****************************************************************************
* These are the different alarm types, passed as timeout IDs to the
* timeout handler.
****************************************************************************/
#define SYS_TIME 0 /* update the time */
#define SYS_TICK 1 /* toggle the blinking dots */
/*
* and a couple of commonly used time values
*/
#define MS 1000 /* 100 ms / sec */
#define E_60_SECONDS 60*MS
#define E_1_SECOND 1*MS
/*
* Am I in Programming Mode ? I need to know this when I want to
* potencially update the time. If i'm in programming mode, I don't
* wnat to change the display on the user! This variable is set
* in the cb.c file routines that control programming of alarms.
*/
extern Boolean PROGRAMMING;
/*
* this will contain the path to the information files created for
* each alarm and is set in the resource files, obtained with
* a call to GetApplicationResources
*/
char *InfoFilePath;
/*
* the name of the program to use to display alarm messages on
* the screen, set in the resource files, obtained with a call to
* GetApplicationResources.
*/
char *DisplayProgram;
char *display_name;
/*
* These are times for the timeout events used for the auto repeat
* functions of the << and >> buttons.
*/
int RepeatDelay;
int InitialDelay;
/**************************************************************************
* M A I N
**************************************************************************/
main (argc, argv)
int argc;
char **argv;
{
/* various callback function declarations */
void display_expose_event();
void TimeOutEvent();
void OffEvent();
void PlusEvent();
void MinusEvent();
void DayEvent();
void HourEvent();
void MinEvent();
void SetEvent();
void arm();
void disarm();
Display *dpy;
resource_data res_data; /* for GetApplicationResources call */
Arg args[10]; /* for setting XmArg values */
int n;
/*
* by default, the users HOME will contain the alarm information
* files. This will be reset if specified in the resource files
*/
InfoFilePath = (char *) getenv ("HOME");
top = XtInitialize ("main",
"XAlarm", /* APPLICATION CLASS NAME */
NULL,NULL,
&argc,argv);
dpy = XtDisplay(top);
display_name = dpy->display_name;
/*
* we're gonna use fancy PIXMAP buttons. Install them
* in the PIXMAP cache.
*/
CreateAndInstallPixmap (ffwd_bits, ffwd_width, ffwd_height, "fwd_face");
CreateAndInstallPixmap (revd_bits, revd_width, revd_height, "rev_face");
CreateAndInstallPixmap (set_bits, set_width, set_height, "set_face");
CreateAndInstallPixmap (pwr_bits, pwr_width, pwr_height, "pwr_face");
/*
* Create the widgets for this application
*/
CreateApplicationWidgets();
/*
* Get the non-widget resources
*/
XtGetApplicationResources (top,
&res_data,
resources,
XtNumber(resources),
NULL,0);
/*
* set the auto repeat delays
*/
InitialDelay = res_data.InitialDelay;
RepeatDelay = res_data.RepeatDelay;
/*
* Reset InfoFilePath if specified
*/
if (res_data.FilePath)
InfoFilePath = res_data.FilePath;
/*
* If display program is not set, bail.
*/
if (res_data.DisplayProgram)
DisplayProgram = res_data.DisplayProgram;
else {
fprintf (stderr,"You must specify the `displayProgram' resource\n");
fprintf (stderr,"in your resource file. Xalarm will not function\n");
fprintf (stderr,"properly without it.\n");
exit(1);
}
/*
* The first time xalarm is invoked, a brief tutorial will be displayed
* in a read-only text edit widget. See the function definition for
* how this is done.
*/
NeedsHelp (InfoFilePath,res_data.HelpFile);
/*
* add an expose routine for the segmented display
*/
XtAddCallback (draw,
XmNexposeCallback,
display_expose_event,
NULL);
/*
* Add the push button call backs
*/
XtAddCallback (pwr, XmNactivateCallback, OffEvent);
XtAddCallback (rev, XmNarmCallback, arm, PlusEvent);
XtAddCallback (fwd, XmNarmCallback, arm, MinusEvent);
XtAddCallback (rev, XmNdisarmCallback, disarm);
XtAddCallback (fwd, XmNdisarmCallback, disarm);
XtAddCallback (set, XmNactivateCallback, SetEvent);
XtAddCallback (day_btn, XmNarmCallback, DayEvent);
XtAddCallback (hour_btn, XmNarmCallback, HourEvent);
XtAddCallback (min_btn, XmNarmCallback, MinEvent);
/*
* and go for it
*/
XtRealizeWidget (top);
SetupDisplay (draw); /* create all of the seg. display digits */
ComputeDisplaySize (); /* bogus additional sizing for seg. display */
/*
* install the periodic time update and ticker update
* timeout events
*/
XtAppAddTimeOut (XtWidgetToApplicationContext(top),
E_60_SECONDS,
TimeOutEvent,
(caddr_t) SYS_TIME);
if (res_data.TickTock)
XtAppAddTimeOut (XtWidgetToApplicationContext(top),
E_1_SECOND,
TimeOutEvent,
(caddr_t) SYS_TICK);
XtMainLoop();
}
/****************************************************************************
* M A I N
****************************************************************************/
/*
* Function:
*/
void
display_expose_event (w, closure, call)
Widget w;
caddr_t closure, call;
/*
* This callback is attached to the DrawingArea widget to redraw the
* segmented display containing the time.
*/
{
long clock, time();
struct tm *theTime, *localtime();
clock = time ((long *) 0);
theTime = localtime (&clock);
UpdateTime (theTime->tm_hour,
theTime->tm_min,
theTime->tm_wday,
theTime->tm_mon,
theTime->tm_mday,
True);
}
/*
* Function:
*/
void
GetTime (hour, min, wday, mon, mday)
int *hour, *min, *wday, *mon, *mday;
/*
* Used by various other routines for obtaining the current time in
* the pointers passed in.
*/
{
long clock, time();
struct tm *theTime, *localtime();
clock = time ((long *) 0);
theTime = localtime (&clock);
*hour = theTime->tm_hour;
*min = theTime->tm_min;
*wday = theTime->tm_wday;
*mon = theTime->tm_mon;
*mday = theTime->tm_mday;
}
/*
* Function:
*/
XmString
GetDate(wday,mon,mday)
int wday, mon, mday;
/*
* Returns an XmString containg the current day of the week and date
*/
{
XmString date;
char dateStr[15];
sprintf (dateStr,"%s, %s. %d",Days[wday],Months[mon],mday);
date = XmStringCreateLtoR (dateStr,XmSTRING_DEFAULT_CHARSET);
return (date);
}
/*
* Function:
*/
XmString
GetAMPM(h,m)
int h, m;
/*
* Returns an XmString containing "AM" or "PM" based in the hour and
* minute passed in.
*/
{
XmString date;
char dateStr[5];
Boolean PM;
if (h > 12) {
PM = True;
}
else if ((h == 12) && (m > 0)) {
PM = True;
}
else {
PM = False;
}
date = XmStringCreateLtoR (((PM == True) ? "PM" : "AM"),
XmSTRING_DEFAULT_CHARSET);
return (date);
}
/*
* Function:
*/
UpdateTime (hour, minute, wday, month, mday, SetDate)
int hour, minute, wday, month, mday;
Boolean SetDate;
/*
* This function is used to draw the time and date in the main xalarm
* display. The time and date is passed in as integers (obtained by
* calls to ctime(3c) functions). The boolean "SetDate" tells if we
* should update the date string as well as the time. This boolean
* is used to make drawing the display less "jumpy" when only the time
* is being updated.
*/
{
int PM = False;
int XOFFSET = 0;
int YOFFSET = 0;
Window win;
Display *display;
int i;
Arg args[5];
int n;
win = XtWindow (draw);
display = XtDisplay (draw);
n=0;
XtSetArg (args[n], XmNlabelString, GetAMPM(hour,minute)); n++;
XtSetValues (pm_ind, args, n);
if (hour == 0)
hour = 24;
if (hour > 12) {
PM = True;
hour -= 12;
}
else if ((hour == 12) && (minute > 0)) {
PM = True;
}
else {
PM = False;
}
XClearWindow (display, win);
/*
* place the digits into the segmented display
*/
if ((hour/10) != 0) {
XPutImage (display,win,gc,Digits[ (hour / 10) ],0,0,
XOFFSET+0,YOFFSET+0,
16,26);
}
else {
XPutImage (display,win,gc,Digits[ 10 ],0,0,
XOFFSET+0,YOFFSET+0,
16,26);
}
XPutImage (display,win,gc,Digits[ (hour % 10) ],0,0,
XOFFSET+16,YOFFSET+0,
16,26);
XPutImage (display,win,gc,DOTS,0,0,
XOFFSET+32,YOFFSET+0,
5,26);
XPutImage (display,win,gc,Digits[ (minute / 10) ],0,0,
XOFFSET+37,YOFFSET+0,
16,26);
XPutImage (display,win,gc,Digits[ (minute % 10) ],0,0,
XOFFSET+53,YOFFSET+0,
16,26);
if (SetDate) {
n=0;
XtSetArg (args[n], XmNlabelString, GetDate(wday,month,mday)); n++;
XtSetValues (label, args, n);
}
XFlush (display); /* should do this whenever you're drawing your own */
/* graphics do the server is synced up */
}
/*
* Function:
*/
static Boolean TickOn = True;
Tick()
/*
* This function call will toggle the dots in the segmented display
* on and off. It is a nice and simple effect when scheduled every
* second, makes xalarm look like a "real" machine. It is called from
* the time out event handler.
*/
{
Window win = XtWindow (draw);
Display *display = XtDisplay (draw);
int XOFFSET = 0;
int YOFFSET = 0;
if (TickOn) {
TickOn = False;
XPutImage (display,win,gc,BlankDots,0,0,
XOFFSET+32,YOFFSET+0,
5,26);
}
else {
TickOn = True;
XPutImage (display,win,gc,DOTS,0,0,
XOFFSET+32,YOFFSET+0,
5,26);
}
XFlush (XtDisplay(top));
}
/*
* Function:
*/
SetupDisplay (w)
Widget w;
/*
* This function sets up the digit XImage structures for the
* segmented display.
*/
{
Pixmap fore;
Pixmap back;
Arg args[5];
XImage *MakeImage();
XGCValues values;
int screen;
XtSetArg (args[0], XmNforeground, &fore);
XtSetArg (args[1], XmNbackground, &back);
XtGetValues (w, args, 2);
screen = DefaultScreen (XtDisplay(w));
values.foreground = fore;
values.background = back;
gc = XCreateGC (XtDisplay(w),
XtWindow(w),
(GCForeground | GCBackground),
&values);
Digits[0] = MakeImage (b0_width,
b0_height,
b0_bits);
Digits[1] = MakeImage (b1_width,
b1_height,
b1_bits);
Digits[2] = MakeImage (b2_width,
b2_height,
b2_bits);
Digits[3] = MakeImage (b3_width,
b3_height,
b3_bits);
Digits[4] = MakeImage (b4_width,
b4_height,
b4_bits);
Digits[5] = MakeImage (b5_width,
b5_height,
b5_bits);
Digits[6] = MakeImage (b6_width,
b6_height,
b6_bits);
Digits[7] = MakeImage (b7_width,
b7_height,
b7_bits);
Digits[8] = MakeImage (b8_width,
b8_height,
b8_bits);
Digits[9] = MakeImage (b9_width,
b9_height,
b9_bits);
Digits[10] = MakeImage (blank_width,
blank_height,
blank_bits);
DOTS = MakeImage (dots_width,
dots_height,
dots_bits);
BlankDots = MakeImage (blankdots_width,
blankdots_height,
blankdots_bits);
}
/*
* Function:
*/
XImage *
MakeImage (width, height, data)
int width, height;
char *data;
/*
* Return an XImage structure created with the passed in
* parameters. The input parameters are bitmap(1) generated and
* are in the include file for a bitmap image.
*/
{
XImage *image;
image = (XImage *) XtMalloc (sizeof (XImage));
image->width = width;
image->height = height;
image->data = data;
image->depth = 1;
image->xoffset = 0;
image->format = XYBitmap;
image->byte_order = LSBFirst;
image->bitmap_unit = 8;
image->bitmap_bit_order = LSBFirst;
image->bitmap_pad = 8;
image->bytes_per_line = (width+7)/8;
return (image);
}
/*
* Function:
*/
ComputeDisplaySize ()
/*
* After the digits are read in, the drawingArea widget is sized to
* to surround them.
*/
{
Arg args[5];
int sw,sh;
sw = (2 * b0_width) + dots_width + (2 * b0_width);
sh = b0_height;
XtSetArg (args[0], XmNwidth, sw);
XtSetArg (args[1], XmNheight, sh);
XtSetValues (draw, args, 2);
}
/*
* Function:
*/
GetWidgetSize (w, width, height)
Widget w;
int *width, *height;
/*
* Return the current size of a passed in widget
*/
{
Arg args[5];
XtSetArg (args[0], XmNwidth, width);
XtSetArg (args[1], XmNheight, height);
XtGetValues (w, args, 2);
}
/*
* Function:
*/
SetGlobalSize ()
/*
* This function sends the window manager the size hints for xalarm.
* I don't want xalarm to be resized, and I want it to come up a
* particular size no matter what the user wants. Is this bad? I
* don't think so for an application of this type. Xalarm looks bad
* at any other size.
*
* The hard-coded size is based on and depends on the use of the
* "9x15" font.
*
* ----------------------------------------------------------------------
* In this version, the R4/Motif 1.1, the XmForm functions a lot better,
* and this function is no longer called. There is no font dependent
* behavior and the application can be resized.
*/
{
XSizeHints hints;
Arg args[5];
int w,h;
int x,y;
XtSetArg (args[0],XmNwidth,&w);
XtSetArg (args[1],XmNheight,&h);
XtSetArg (args[2],XmNx, &x);
XtSetArg (args[3],XmNy, &y);
XtGetValues (top,args,4);
hints.width = hints.max_width = hints.min_width = 200;
hints.height = hints.max_height = hints.min_height = 105;
hints.x = x;
hints.y = y;
hints.flags = (USSize | PSize | PMinSize | PMaxSize | USPosition);
XSetNormalHints (XtDisplay(top),XtWindow(top), &hints);
}
/*
* Function:
*/
CreateApplicationWidgets()
/*
* This function created the main xalarm dispay widgets
*/
{
Arg args[10];
int n;
XmString GetDate();
/*
* the form contains all children
*/
n=0;
XtSetArg (args[n], XmNhorizontalSpacing, 3); n++;
XtSetArg (args[n], XmNverticalSpacing, 3); n++;
XtSetArg (args[n], XmNallowOverlap, False); n++;
XtSetArg (args[n], XmNrubberPositioning, True); n++;
bb = XmCreateForm (top,
"bb",
args,n);
XtManageChild (bb);
/*
* The day, hour, and minute programming selections
* are radio buttons, to provide a one of many selection
* model.
*/
n=0;
XtSetArg (args[n],XmNtopAttachment, XmATTACH_FORM); n++;
XtSetArg (args[n],XmNrightAttachment,XmATTACH_FORM); n++;
XtSetArg (args[n],XmNentryClass,xmToggleButtonWidgetClass); n++;
rc = XmCreateRadioBox (bb,
"sets",
args,n);
XtManageChild (rc);
XmAddTabGroup (rc);
/*
* and now the toggles
*/
n=0;
XtSetArg (args[n], XmNmarginHeight, 0); n++;
day_btn = XmCreateToggleButton (rc,
"day",
args,n);
XtManageChild (day_btn);
hour_btn = XmCreateToggleButton (rc,
"hour",
args,n);
XtManageChild (hour_btn);
min_btn = XmCreateToggleButton (rc,
"min",
args,n);
XtManageChild (min_btn);
/*
* There is a set button to finish the programming
* sequence.
*/
n=0;
XtSetArg (args[n],XmNtopAttachment,XmATTACH_WIDGET); n++;
XtSetArg (args[n],XmNtopWidget,rc); n++;
XtSetArg (args[n],XmNrightAttachment,XmATTACH_FORM); n++;
XtSetArg (args[n],XmNbottomAttachment,XmATTACH_FORM); n++;
set = XmCreatePushButton (bb,
"set",
args,n);
XtManageChild (set);
XmAddTabGroup (set);
n=0;
XtSetArg (args[n],XmNlabelType,XmPIXMAP); n++;
XtSetArg (args[n],XmNlabelPixmap,GetPixmap(set,"set_face")); n++;
XtSetValues (set,args,n);
/*
* there are two buttons for programming the alarm,
* a backward and a forward button. Both will have
* pixmaps for button faces.
*/
n=0;
XtSetArg (args[n],XmNrightAttachment,XmATTACH_WIDGET); n++;
XtSetArg (args[n],XmNrightWidget,rc); n++;
XtSetArg (args[n],XmNtopAttachment,XmATTACH_FORM); n++;
rev = XmCreatePushButton (bb,
"fwd",
args,n);
XtManageChild (rev);
n=0;
XtSetArg (args[n],XmNlabelType,XmPIXMAP); n++;
XtSetArg (args[n],XmNlabelPixmap,GetPixmap(rev,"rev_face")); n++;
XtSetValues (rev,args,n);
n=0;
XtSetArg (args[n],XmNrightAttachment,XmATTACH_WIDGET); n++;
XtSetArg (args[n],XmNrightWidget,rev); n++;
XtSetArg (args[n],XmNtopAttachment,XmATTACH_FORM); n++;
fwd = XmCreatePushButton (bb,
"rev",
args,n);
XtManageChild (fwd);
n=0;
XtSetArg (args[n],XmNlabelType,XmPIXMAP); n++;
XtSetArg (args[n],XmNlabelPixmap,GetPixmap(fwd,"fwd_face")); n++;
XtSetValues (fwd,args,n);
/*
* The segmented display is a frame around a drawing area
*/
n=0;
XtSetArg (args[n],XmNmarginWidth, 5); n++;
XtSetArg (args[n],XmNmarginHeight, 5); n++;
XtSetArg (args[n],XmNrightAttachment,XmATTACH_WIDGET); n++;
XtSetArg (args[n],XmNrightWidget,rc); n++;
XtSetArg (args[n],XmNtopAttachment,XmATTACH_WIDGET); n++;
XtSetArg (args[n],XmNtopWidget, fwd); n++;
XtSetArg (args[n],XmNrightOffset,7); n++;
frame = XmCreateFrame (bb,
"frame",
args,n);
XtManageChild (frame);
n=0;
XtSetArg (args[n],XmNwidth,75); n++;
XtSetArg (args[n],XmNheight,25); n++;
draw = XmCreateDrawingArea (frame,
"display",
args,n);
XtManageChild (draw);
/*
* and under the segmented display is a date label
*/
n=0;
XtSetArg (args[n],XmNleftAttachment,XmATTACH_FORM); n++;
XtSetArg (args[n],XmNrightAttachment,XmATTACH_WIDGET); n++;
XtSetArg (args[n],XmNrightWidget,set); n++;
XtSetArg (args[n],XmNtopAttachment,XmATTACH_WIDGET); n++;
XtSetArg (args[n],XmNtopWidget,frame); n++;
XtSetArg (args[n],XmNlabelString,GetDate(6,6,6)); n++;
label = XmCreateLabel (bb,
"date",
args,n);
XtManageChild (label);
/*
* over the label is the power button
*/
n=0;
XtSetArg (args[n],XmNbottomAttachment,XmATTACH_WIDGET); n++;
XtSetArg (args[n],XmNbottomWidget,label); n++;
XtSetArg (args[n],XmNleftAttachment,XmATTACH_FORM); n++;
XtSetArg (args[n],XmNrightAttachment,XmATTACH_WIDGET); n++;
XtSetArg (args[n],XmNrightOffset, 15); n++;
XtSetArg (args[n],XmNrightWidget,frame); n++;
pwr = XmCreatePushButton (bb,
"pwr",
args,n);
XtManageChild(pwr);
XmAddTabGroup(pwr);
n=0;
XtSetArg (args[n],XmNlabelType, XmPIXMAP); n++;
XtSetArg (args[n],XmNlabelPixmap, GetPixmap(pwr,"pwr_face")); n++;
XtSetValues (pwr, args, n);
/*
* and a am/pm indicator
*/
n=0;
XtSetArg (args[n],XmNlabelString,GetAMPM(5,5)); n++;
XtSetArg (args[n],XmNrightAttachment,XmATTACH_WIDGET); n++;
XtSetArg (args[n],XmNrightWidget,frame); n++;
XtSetArg (args[n],XmNrightOffset, 15); n++;
XtSetArg (args[n],XmNbottomAttachment,XmATTACH_WIDGET); n++;
XtSetArg (args[n],XmNbottomWidget,pwr); n++;
pm_ind = XmCreateLabel (bb,
"pm",
args,n);
XtManageChild(pm_ind);
}
/*
* Function:
*/
void
TimeOutEvent (type, id)
int type;
XtIntervalId *id;
/*
* This function is the timeout event procedure, called when a time
* out event occurs. There are two possible timeout events, one that
* is scheduled every 60 seconds to update the time, and one that is
* scheduled every second that makes the dots blink. The two are distinguished
* by the "type" parameter.
*/
{
int hour,min,wday,mon,mday;
switch (type) {
case SYS_TIME:
if (!PROGRAMMING) {
GetTime (&hour, &min, &wday, &mon, &mday);
UpdateTime (hour, min, wday, mon, mday, True);
}
/* reschedule it */
XtAppAddTimeOut (XtWidgetToApplicationContext(top),
E_60_SECONDS,
TimeOutEvent,
(caddr_t) SYS_TIME);
break;
case SYS_TICK:
if (!PROGRAMMING) {
Tick();
}
/* reschedule it */
XtAppAddTimeOut (XtWidgetToApplicationContext(top),
E_1_SECOND,
TimeOutEvent,
(caddr_t) SYS_TICK);
break;
default:
fprintf (stderr, "xalarm: Unknown alarm type, %d\n",type);
break;
}
}
/*
* Function:
*/
NeedsHelp (fpath, helpfile)
char *fpath;
char *helpfile;
/*
* This function checks the existence of a file called ".needshelp"
* in the directory where the alarm message files exist. If its
* not there, the help window is poped up and the file is created.
* Future invokations of xalarm will see this file and the tutorial
* will not come up.
*/
{
char com[120];
char *fname;
FILE *fp, *fopen();
fname = (char *) XtMalloc (strlen(fpath) + strlen("/.needshelp") + 5);
sprintf (fname, "%s/.needshelp", fpath);
if ((fp = fopen (fname, "r")) != NULL) {
fclose(fp);
return (0);
}
if (!Help (top, helpfile)) {
return(0);
}
if ((fp = fopen(fname,"w")) == NULL) {
Warning (top,"Can't open help lock file.");
return (0);
}
fprintf (fp,"\n");
}
/*
* The End
*/
@EOF
echo x - xalarm_d.c
cat > xalarm_d.c << '@EOF'
#include "copyright.h"
#ident "$Header: xalarm_d.c,v 4.5 90/12/27 13:22:49 mar Exp $"
static char version[] = "@(#)xalarm_d.c 1.7";
/***************************************************************************
*
* FILE NAME : xalarm_display.c
*
* AUTHOR : Andrew Peebles
*
* DESCRIPTION :
*
* This program is used to display an alarm message on the screen.
* It is invoked when an alarm goes off (via a Unix SYSTEMV at call)
* and when a user views a pending alarm. Because of the displayProgram
* resource for xalarm, any similar program could be written to display
* alarm messages. Note that by adopting this "two program" appraoch,
* xalarm itself does not have to be running to recieve alarm messages.
*
* VERSIONS : @(#)xalarm_d.c 1.7
*
***************************************************************************/
/*
* standard includes
*/
#include <stdio.h>
#include <Xm/Xm.h>
#include <Xm/Text.h>
#include <Xm/PushB.h>
#include <Xm/Form.h>
#include <X11/Shell.h>
#include <X11/StringDefs.h>
#include <X11/Xos.h>
#include <sys/stat.h>
Widget top, form, ok, snooze, text;
extern char *ReadMessageText();
/*
* Non-widget resource structurs. These are used so a call to
* GetApplicationResources can retrieve this resource from a
* number of places.
*/
typedef struct _res_data {
int snooze_time; /* number of seconds to snooze */
Boolean beep_on; /* turn on beeper */
int beep_freq; /* frequency of beep */
int beep_volume; /* beep volume (-100 to 100) */
} res_data, *res_data_ptr;
res_data myresources; /* global resource table */
static XtResource resources[] = {
{"snoozeTime",
"SnoozeTime",
XmRInt,
sizeof(int),
XtOffset (res_data_ptr, snooze_time),
XmRString,
"30"}, /* default is 30 seconds */
{"beepOn",
"BeepOn",
XmRBoolean,
sizeof (Boolean),
XtOffset (res_data_ptr, beep_on),
XmRString,
"True"}, /* default is on */
{"beepPeriod",
"BeepPeriod",
XmRInt,
sizeof(int),
XtOffset (res_data_ptr, beep_freq),
XmRString,
"1"}, /* every second */
{"beepVolume",
"BeepVolume",
XmRInt,
sizeof(int),
XtOffset (res_data_ptr, beep_volume),
XmRString,
"99"} /* 99; valid range is -100 to 100 */
};
#define MS 1000
int SysSnoozeTime = 30*MS; /* 30 second snooze time default */
/*
* Used to keep track of beep timeout
*/
XtIntervalId BeepId = 0;
/*
* Now restrict beeper to beep 5 times, then do not beep again unless
* snooze is selected.
*/
int BEEPTIMES = 5;
/***************************************************************************
* M A I N
***************************************************************************/
main (argc, argv)
int argc;
char **argv;
{
Arg args[10];
int n;
Display *display;
Screen *scrn;
char **saved_argv;
int saved_argc = argc;
int i;
void TimeOutEvent();
void OKCallback(), SnoozeCallback(), TimeOut();
XtAppContext context;
/*
* We'll go through the long hand method of initializing this application
* so if the display is not accessable, the message is instead mailed to
* the user.
*/
XtToolkitInitialize();
saved_argv = (char **) XtCalloc(
(unsigned) ((argc) + 1) , (unsigned)sizeof(*saved_argv));
for (i = 0 ; i < argc ; i++) saved_argv[i] = argv[i];
saved_argv[i] = NULL;
context = XtCreateApplicationContext();
if ((display = XtOpenDisplay(context,
NULL,
NULL,
"XAlarm_display",
NULL,0,
&argc,argv)) == NULL) {
Recover (argc,argv);
exit(1);
}
scrn = DefaultScreenOfDisplay(display);
n = SetArgs (args,
XtNscreen, scrn,
XtNargc, saved_argc,
XtNargv, saved_argv,
NULL);
top = XtAppCreateShell (NULL,
"XAlarm_display",
applicationShellWidgetClass,
display,
args,n);
/*
* Create the main display widgets
*/
CreateApplicationWidgets();
/*
* Get the non-widget resources
*/
XtGetApplicationResources (top,
&myresources,
resources,
XtNumber(resources),
NULL,0);
SysSnoozeTime = MS*myresources.snooze_time;
/*
* Add the callbacks to the buttons
*/
XtAddCallback (ok, XmNactivateCallback, OKCallback, NULL);
XtAddCallback (snooze, XmNactivateCallback, SnoozeCallback, NULL);
/*
* get the alarm message and put it in text widget
*/
GetAlarmMessage (argv[1]);
XtRealizeWidget (top);
/*
* if beep on then set up beep timeout
*/
if (myresources.beep_on) {
XBell (XtDisplay(top), myresources.beep_volume);
BeepId = XtAppAddTimeOut (context,
myresources.beep_freq*MS,
TimeOutEvent,
NULL);
}
XtAppMainLoop(context);
}
/*
* Function:
*/
CreateApplicationWidgets()
/*
* Create the main display widgets
*/
{
Arg args[10];
int n;
form = XmCreateForm (top,
"form",
NULL,0);
XtManageChild (form);
n = SetArgs (args,
XmNtopAttachment, XmATTACH_FORM,
XmNleftAttachment, XmATTACH_FORM,
NULL);
ok = XmCreatePushButton (form,
"OK",
args,n);
XtManageChild (ok);
n = SetArgs (args,
XmNtopAttachment, XmATTACH_FORM,
XmNrightAttachment, XmATTACH_FORM,
NULL);
snooze = XmCreatePushButton (form,
"Snooze",
args,n);
XtManageChild (snooze);
n = SetArgs (args,
XmNeditMode, XmMULTI_LINE_EDIT,
XmNcolumns, 40,
XmNrows, 12,
XmNwordWrap, True,
XmNscrollHorizontal, False,
XmNautoShowCursorPosition, True,
XmNcursorPositionVisible, True,
XmNblinkRate, 0,
XmNeditable, False,
NULL);
text = XmCreateScrolledText (form,
"text",
args,n);
XtManageChild (text);
n = SetArgs (args,
XmNtopAttachment, XmATTACH_WIDGET,
XmNtopWidget, ok,
XmNleftAttachment, XmATTACH_FORM,
XmNeditMode, XmMULTI_LINE_EDIT,
NULL);
XtSetValues (XtParent(text), args, n);
}
/*
* Function:
*/
GetAlarmMessage (fname)
char *fname;
/*
* The the alarm message text and put it in the text widget
*/
{
char *buffer;
Arg args[2];
if ((buffer = ReadMessageText(fname)) == NULL) {
fprintf (stderr,"Can't open %s.\n",fname);
exit(1);
}
XtSetArg (args[0], XmNvalue, buffer);
XtSetValues (text, args, 1);
}
/*
* Function:
*/
void
OKCallback (w, client, call)
Widget w;
caddr_t client, call;
/*
* Callback attached to the "OK" button. Just exit the application.
*/
{
exit(0);
}
/*
* Function:
*/
void
SnoozeCallback (w, client, call)
Widget w;
caddr_t client, call;
/*
* Callback attached to the "Snooze" button. Set up a timeout event
* to occur in the number of seconds the user specified for the snooze
* time and then unmap the application (so it disappears). The timeout
* event will remap the application.
*/
{
void TimeOut();
XtAppAddTimeOut (XtWidgetToApplicationContext(top),
SysSnoozeTime,
TimeOut,
NULL);
XtUnmapWidget (top);
/*
* Remove the beeper timeout if present
*/
if (BeepId != 0)
XtRemoveTimeOut (BeepId);
}
/*
* Function:
*/
void
TimeOut (w, client, call)
Widget w;
caddr_t client, call;
/*
* remap the application after the snooze time has expired
*/
{
XtMapWidget (top);
/*
* re-establish beep timeout if specified
*/
if (myresources.beep_on) {
XBell (XtDisplay(top), myresources.beep_volume);
BEEPTIMES = 5;
BeepId = XtAppAddTimeOut (XtWidgetToApplicationContext(top),
myresources.beep_freq*MS,
TimeOutEvent,
NULL);
}
}
/*
* These arrays are kept to display nice text for the alarm time
*/
char *Days[] = {
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"
};
char *Months[] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
};
/*
* Function:
*/
Recover (num_args, args)
int num_args;
char **args;
/*
* Can't open the display. We'll just write the message to stdout and
* at will mail it to the user.
*/
{
char *fname = args[num_args-1];
int fp;
struct tm *theTime, *localtime();
long clock;
char line[120];
char *buffer;
int buf_size;
clock = time ((long *)0);
theTime = localtime(&clock);
printf ("xalarm message sent at %d:%02d on %s, %s %d :\n", theTime->tm_hour,
theTime->tm_min,
Days[theTime->tm_wday],
Months[theTime->tm_mon],
theTime->tm_mday);
if ((fp = open (fname, O_RDONLY, 0644)) == -1) {
printf ("Can't open %s to display.\n",fname);
exit(1);
}
read (fp, &buf_size, sizeof(int));
buffer = (char *) XtMalloc (buf_size+5);
read (fp, buffer, buf_size);
buffer[buf_size] = '\0';
printf ("%s\n",buffer);
close(fp);
return(0);
}
void
TimeOutEvent (client, id)
caddr_t client;
XtIntervalId id;
/*
* when beep timeout occurs
*/
{
XBell (XtDisplay(top), myresources.beep_volume);
if ( (--BEEPTIMES) ) {
BeepId = XtAppAddTimeOut (XtWidgetToApplicationContext(top),
myresources.beep_freq*MS,
TimeOutEvent,
NULL);
}
else {
BeepId = 0;
}
}
@EOF
exit 0
--
Dan Heller
Z-Code Software O'Reilly && Associates Comp-sources-x:
President Senior Writer comp-sources-x@uunet.uu.net
argv@z-code.com argv@ora.com [^^^ this address only!]