Article View: net.micro.atari16
Article #531ST Calendar Desk Accessory (SOURCE)
From: Jim Tittsler
Date: Thu, 24 Apr 1986 19:19
Date: Thu, 24 Apr 1986 19:19
547 lines
13886 bytes
13886 bytes
Here is a shar file containing the source for a simple "sort of
perpetual" calendar desk accessory.
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# cal.c string.c
echo x cal.c
sed 's/^X//' > cal.c << 'xEOF'
X/*
X * cal.c -- simple TOS desktop calendar accessory
X *
X * provides a "perpetual" (well, really 1980-2009) calendar page display
X * uses vertical scroll bar: arrows move by month, shaded area by year
X *
X * link68 cal.68k=accstart,cal,string,osbind,vdibind,aesbind
X * relmod cal
X * ren cal.prg cal.acc (must be DESKN.ACC in early TOS)
X *
X * - a further experiment into the realm of writing a desk accessory
X * This was a personal experiment to learn more about desk accessories.
X * It may be freely distributed, on an "as-is" basis. Comments and
X * suggestions are welcome. This is NOT an official, supported,
X * Atari product.
X * Jim Tittsler, Atari Corp.
X *
X * 15Oct85 jwt v0.01 hacked from WATCH accessory
X * 17Jan86 jwt v0.02 set first displayed page at OPEN time,
X * not init time
X * added Day of Week string
X * 21Jan86 jwt v0.03 use reverse video to highlight current date
X * 30Jan86 jwt v0.04 reduce height & width of highlight in high res
X * 18Apr86 jwt v0.05 "reopen" at same place as last close
X * 24Apr86 jwt v1.00 distribute
X */
X
Xstatic char id[] = "@(#)CAL.ACC V1.00 jwt@atari";
X
X/* #define DEBUG 1 */
X/* #define DDEVICE 2 */
X#define REVHIGHLIGHT 1
X
X#include "obdefs.h"
X#include "define.h"
X#include "gemdefs.h"
X#include "osbind.h"
X
X#define WI_KIND (MOVER|CLOSER|NAME|UPARROW|DNARROW|VSLIDE)
X
X#define NO_WINDOW (-1)
X
X#define AR_UPPG 0
X#define AR_DNPG 1
X#define AR_UPLN 2
X#define AR_DNLN 3
X
X#define STRINGWIDTH 22
X#define BLANKSTRING " "
X#define CALLINES 8
X#define DAYOFWEEKSTRING " Sn M Tu W Th F Sa "
X#define LENDOWS STRINGWIDTH
X
X#define YEAROFFSET 1980
X#define BASEYEAR 1980
X#define CALLEN 30
X#define LASTYEAR (BASEYEAR+CALLEN-1)
X
X#define MIN_WIDTH (STRINGWIDTH*gl_wchar)
X#define MIN_HEIGHT (CALLINES*gl_hchar+1)
X
X#define INIT_X 100
X#define INIT_Y 50
X#define INIT_WIDTH MIN_WIDTH
X#define INIT_HEIGHT MIN_HEIGHT
X
Xextern int gl_apid;
X
Xint year,month,day;
Xint curyr,curmo,curday;
X
Xint initx = INIT_X;
Xint inity = INIT_Y;
X
Xint lastdate = -1; /* last DOS date */
Xint washighlighted;
Xint hires; /* 1 if in high resolution */
Xchar dtoabuf[10];
Xchar calstring[CALLINES][(STRINGWIDTH+1)];
Xchar *months[]= {"January", "February", "March", "April",
X "May", "June", "July", "August",
X "September", "October", "November", "December"};
Xint daypermon[]= {31, 28, 31, 30,
X 31, 30, 31, 31,
X 30, 31, 30, 31};
X
Xint gl_hchar;
Xint gl_wchar;
Xint gl_wbox;
Xint gl_hbox; /* system sizes */
X
Xint menu_id ; /* our menu id */
X
Xint phys_handle; /* physical workstation handle */
Xint handle; /* virtual workstation handle */
Xint wi_handle; /* window handle */
Xint top_window; /* handle of topped window */
X
Xint xwork,ywork,hwork,wwork; /* work area */
X
Xint msgbuff[8]; /* event message buffer */
Xint keycode; /* keycode returned by event-keyboard */
Xint mx,my; /* mouse x and y pos. */
Xint ret; /* dummy return variable */
X
Xint hidden; /* current state of cursor */
X
Xint contrl[12];
Xint intin[128];
Xint ptsin[128];
Xint intout[128];
Xint ptsout[128]; /* storage wasted for idiotic bindings */
X
Xint work_in[11]; /* Input to GSX parameter array */
Xint work_out[57]; /* Output from GSX parameter array */
Xint pxyarray[10]; /* input point array */
X
X/*page*/
Xchar *dtoa( i, fwidth ) register int i,fwidth; {
Xregister char *ptr,*lptr;
Xregister int cnt;
Xchar tbuf[6];
X
X ptr = dtoabuf;
X
X if (i < 0) {
X *ptr++ = '-';
X --fwidth;
X i = -i;
X }
X
X lptr = tbuf;
X cnt = 0;
X
X do {
X *lptr++ = (i % 10)+0x30;
X ++cnt;
X } while ( (i /= 10) && (cnt<fwidth) );
X
X if (i) /* did we exceed the field width? */
X for(cnt=0; cnt<fwidth; ++cnt) *ptr++ = '*';
X else {
X for(i=0; i<(fwidth-cnt); ++i) *ptr++ = ' ';
X while(cnt--) *ptr++ = *--lptr;
X }
X
X *ptr='\0'; /* null terminate the string */
X
X return dtoabuf;
X}
X
X/*page*/
Xhide_mouse()
X{
X if(! hidden){
X graf_mouse(M_OFF,0x0L);
X hidden=TRUE;
X }
X}
X
Xshow_mouse()
X{
X if(hidden){
X graf_mouse(M_ON,0x0L);
X hidden=FALSE;
X }
X}
X
Xopen_vwork() {
Xint i;
X for(i=0;i<10;work_in[i++]=1);
X work_in[10]=2; /* use device coordinates */
X handle=phys_handle;
X v_opnvwk(work_in,&handle,work_out);
X}
X
Xset_clip(x,y,w,h) int x,y,w,h; {
Xint clip[4];
X clip[0]=x;
X clip[1]=y;
X clip[2]=x+w-1;
X clip[3]=y+h-1;
X vs_clip(handle,1,clip);
X}
X
Xopen_window() {
Xint xbord,ybord,wbord,hbord;
X
X wind_calc(WC_BORDER,WI_KIND, /* WC_BORDER */
X initx,inity,INIT_WIDTH,INIT_HEIGHT,
X &xbord, &ybord, &wbord, &hbord);
X wi_handle=wind_create(WI_KIND,xbord,ybord,
X wbord,hbord);
X wind_set(wi_handle, WF_NAME," CALENDAR ",0,0);
X wind_set(wi_handle, WF_VSLSIZE, -1, 0, 0, 0);
X wind_set(wi_handle, WF_VSLIDE,
X (int)((1000L*((year-BASEYEAR)*12L+month))/(CALLEN*12)),0,0,0);
X graf_growbox(0,0,gl_wbox,gl_hbox,
X xbord,ybord,wbord,hbord);
X wind_open(wi_handle,xbord,ybord,
X wbord,hbord);
X wind_get(wi_handle,WF_WORKXYWH,&xwork,&ywork,&wwork,&hwork);
X}
X
Xdo_redraw(complete,xc,yc,wc,hc)
Xint complete;
Xint xc,yc,wc,hc;
X{
XGRECT t1,t2;
X
X hide_mouse();
X wind_update(TRUE);
X t2.g_x=xc;
X t2.g_y=yc;
X t2.g_w=wc;
X t2.g_h=hc;
X wind_get(wi_handle,WF_FIRSTXYWH,&t1.g_x,&t1.g_y,&t1.g_w,&t1.g_h);
X while (t1.g_w && t1.g_h) {
X if (rc_intersect(&t2,&t1)) {
X set_clip(t1.g_x,t1.g_y,t1.g_w,t1.g_h);
X draw_calendar(complete);
X }
X wind_get(wi_handle,WF_NEXTXYWH,&t1.g_x,&t1.g_y,&t1.g_w,&t1.g_h);
X }
X wind_update(FALSE);
X show_mouse();
X}
X
X/*page*/
Xmain() {
Xlong ikbdtime;
X
X appl_init();
X phys_handle=graf_handle(&gl_wchar,&gl_hchar,&gl_wbox,&gl_hbox);
X gl_hchar++;
X menu_id=menu_register(gl_apid," Calendar");
X
X /* use the ikbd's version of time if it looks valid */
X /* i.e., month is nonzero */
X if((ikbdtime = Gettime()) &0x01E00000L) {
X Tsetdate((int)(ikbdtime>>16));
X Tsettime((int)(ikbdtime&0xFFFFL));
X }
X wi_handle=NO_WINDOW;
X hidden=FALSE;
X
X hires = (Getrez() == 2); /* hires = 1 if in high res */
X multi();
X}
X
X/*page*/
Xmulti()
X{
Xint event;
X#ifdef DEBUG
Xint idebug;
X#endif
X
X while (TRUE) {
X event = evnt_multi(MU_MESAG | MU_KEYBD | MU_TIMER,
X 1,1,0,
X 0,0,0,0,0,
X 0,0,0,0,0,
X msgbuff,10000,0,&mx,&my,&ret,&ret,&keycode,&ret);
X
X if((lastdate != Tgetdate()) && (wi_handle != NO_WINDOW)){
X lastdate = Tgetdate();
X curday = lastdate & 0x1F;
X curmo = (lastdate >> 5) & 0xF;
X curyr = (lastdate >> 9)+YEAROFFSET;
X if(((year==curyr)&&(month==curmo)) || washighlighted)
X do_redraw(FALSE,xwork,ywork,wwork,hwork);
X }
X
X wind_update(TRUE);
X wind_get(wi_handle,WF_TOP,&top_window,&ret,&ret,&ret);
X
X if (event & MU_MESAG) {
X#ifdef DEBUG
X putsaux("Message: ");
X for (idebug=0; idebug<8; ++idebug) {
X putdaux(msgbuff[idebug]);
X putcaux(' ');
X }
X putcaux(0x0D); putcaux(0x0A);
X#endif
X
X switch (msgbuff[0]) {
X
X case WM_REDRAW:
X if (msgbuff[3] == wi_handle)
X do_redraw(TRUE,msgbuff[4],msgbuff[5],msgbuff[6],msgbuff[7]);
X break;
X
X case WM_NEWTOP:
X case WM_TOPPED:
X if (msgbuff[3] == wi_handle){
X wind_set(wi_handle,WF_TOP,0,0,0,0);}
X break;
X
X case AC_CLOSE:
X if((msgbuff[3] == menu_id)&&(wi_handle != NO_WINDOW)){
X v_clsvwk(handle);
X wi_handle = NO_WINDOW;
X }
X break;
X
X case WM_CLOSED:
X if(msgbuff[3] == wi_handle){
X wind_close(wi_handle);
X graf_shrinkbox(0,0,gl_wbox,gl_hbox,xwork,ywork,wwork,hwork);
X wind_delete(wi_handle);
X v_clsvwk(handle);
X wi_handle = NO_WINDOW;
X }
X break;
X
X case WM_MOVED:
X if(msgbuff[3] == wi_handle){
X wind_set(wi_handle,WF_CURRXYWH,
X msgbuff[4],msgbuff[5],msgbuff[6],msgbuff[7]);
X wind_get(wi_handle,WF_WORKXYWH,&xwork,&ywork,&wwork,&hwork);
X initx = xwork; inity = ywork;
X }
X break;
X
X case AC_OPEN:
X if (msgbuff[4] == menu_id){
X if(wi_handle == NO_WINDOW){
X
X if (lastdate != Tgetdate()){
X lastdate = Tgetdate();
X curday = day = lastdate & 0x1F;
X curmo = month = (lastdate >> 5) & 0xF;
X curyr = year = (lastdate >> 9)+YEAROFFSET;
X makecalpage(year, month, day);
X }
X open_vwork();
X open_window();
X }
X else /* if already opened, for user convenience */
X wind_set(wi_handle,WF_TOP,0,0,0,0);
X }
X break;
X
X case WM_ARROWED:
X switch(msgbuff[4]){
X case AR_UPLN: if(--month) break;
X month=12;
X if(--year<BASEYEAR) {
X year = BASEYEAR;
X month = 1;
X }
X break;
X case AR_UPPG: if(--year<BASEYEAR) year = BASEYEAR; break;
X case AR_DNLN: if(++month<13) break;
X month=1;
X if(++year>LASTYEAR) {
X year = LASTYEAR;
X month = 12;
X }
X break;
X case AR_DNPG: if(++year>LASTYEAR) year = LASTYEAR; break;
X } /* switch(msgbuff[4]) */
X makecalpage(year,month,-1);
X do_redraw(FALSE,xwork,ywork,wwork,hwork);
X wind_set(wi_handle, WF_VSLIDE,
X (int)((1000L*((year-BASEYEAR)*12L+month))/(CALLEN*12)),0,0,0);
X break;
X
X case WM_VSLID:
X wind_set(wi_handle, WF_VSLIDE, msgbuff[4], 0, 0, 0);
X month = (int)(((long)msgbuff[4]*(CALLEN*12-1))/1000L);
X year = (month/12)+BASEYEAR;
X month = (month % 12)+1;
X makecalpage(year,month,-1);
X do_redraw(FALSE,xwork,ywork,wwork,hwork);
X break;
X
X } /* switch (msgbuff[0]) */
X }
X
X wind_update(FALSE);
X
X } /* while (TRUE) */
X
X}
X
Xdraw_calendar(complete) int complete; {
Xint temp[4];
Xint i;
X
X if (complete || washighlighted){
X vsf_interior(handle,1); /* solid */
X vsf_color(handle,0);
X temp[0]=xwork;
X temp[1]=ywork;
X temp[2]=xwork+wwork-1;
X temp[3]=ywork+hwork-1;
X v_bar(handle,temp); /* blank the interior */
X }
X
X vst_color(handle, 1);
X
X for(i=0; i<CALLINES; ++i)
X v_gtext(handle, xwork, ywork+(i+1)*gl_hchar-1,
X calstring[i]);
X
X if((year==curyr)&&(month==curmo)){
X i = dow(curyr,curmo,1)+curday-1;
X#ifdef REVHIGHLIGHT
X vsf_color(handle,1);
X temp[0]=xwork+((i%7)*3+1)*gl_wchar-2;
X temp[1]=ywork+((i/7)+2)*gl_hchar+1+hires;
X temp[2]=temp[0]+2*gl_wchar+3-hires;
X temp[3]=temp[1]+gl_hchar-1-hires;
X v_bar(handle,temp);
X vst_color(handle, 0);
X vswr_mode(handle, 2);
X#else /* not REVHIGHLIGHT */
X vst_color(handle, 3);
X#endif /* REVHIGHLIGHT */
X v_gtext(handle,xwork+((i%7)*3+1)*gl_wchar,
X ywork+((i/7)+3)*gl_hchar-1,
X dtoa(curday,2));
X#ifdef REVHIGHLIGHT
X vswr_mode(handle, 1);
X#endif /* REVHIGHLIGHT */
X washighlighted = 1;
X } else washighlighted = 0;
X}
X
X/*page*/
X/*
X * dow -- find the day of the week
X * for a given yr,mon,day between Mar1900 and Dec2099
X */
Xint dow(yr, mon, day) int yr, mon, day; {
X register int d,i;
X
X /* find day of week of jan1 of the year of interest */
X d = (yr+((yr+3)/4)+5) % 7;
X
X /* find day of week for first of month */
X for(i=1; i<mon; ++i) d += daypermon[i-1];
X
X /* and for the given day */
X d += day-1;
X
X return d % 7;
X}
X
Xmakecalpage(yr, mon, day) int yr, mon, day; {
X register int i,monlen,xpos;
X
X daypermon[1] = (yr%4) ? 28 : 29;
X
X --mon; /* create index into months array */
X
X for(i=0; i<CALLINES; ++i)
X strcpy(calstring[i], BLANKSTRING);
X
X monlen = strlen(months[mon]);
X
X xpos = (STRINGWIDTH/2) - (monlen+5)/2;
X
X strncpy(&calstring[0][xpos],months[mon],monlen);
X strncpy(&calstring[0][xpos+monlen+1],dtoa(year,4),4);
X
X strncpy(calstring[1], DAYOFWEEKSTRING, LENDOWS);
X
X xpos = dow(yr, mon+1, 1);
X for(i=1; i<=daypermon[mon]; ++i,++xpos)
X strncpy(&calstring[xpos/7+2][3*(xpos%7)+1],
X dtoa(i,2),2);
X}
X
X/*page*/
X#ifdef DEBUG
Xputsaux( s ) char *s; {
Xchar c;
X
X while(c = *s++) putcaux(c);
X}
X
Xputdaux( i ) int i; {
X int pot, leading, d;
X
X if (i < 0) {
X putcaux('-');
X i = -i;
X }
X
X leading = 0;
X for(pot = 10000; pot >= 1; pot /= 10) {
X d = i/pot; i -= d*pot;
X if (d || leading || (pot == 1)) {
X putcaux(d+0x30);
X leading = 1;
X } else putcaux(' ');
X }
X}
X
Xputcaux( c ) char c; {
X Bconout(DDEVICE, c);
X}
X#endif
xEOF
echo x string.c
sed 's/^X//' > string.c << 'xEOF'
Xstrcpy(s1,s2) register char *s1,*s2; {
X
X while (*s1++ = *s2++);
X
X}
X
Xstrncpy(s1, s2, n) register char *s1,*s2; register int n; {
X register char c;
X
X while((c = *s2++) && n--) *s1++ = c;
X
X while(n--) *s1++ = '\0'; /* NULL fill */
X}
X
Xint strlen(s1) register char *s1; {
X register int length;
X
X length = 0;
X
X while(*s1++) ++length;
X
X return length;
X}
xEOF
----
Jim Tittsler, Atari Corp lll-crg!vecpyr!atari!jwt
Technical Details
Message-ID:
<210@atari.UUcp>Path:
arc1-ca.pugleaf.net!utzoo!watmath!clyde!burl!ulysses!allegra!princeton!orsvax1!pyrnj!caip!topaz!lll-crg!lll-lcc!vecpyr!atari!jwtShow Full Headers
Complete Article Headers
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: arc1-ca.pugleaf.net!utzoo!watmath!clyde!burl!ulysses!allegra!princeton!orsvax1!pyrnj!caip!topaz!lll-crg!lll-lcc!vecpyr!atari!jwt From: jwt@atari.UUcp (Jim Tittsler) Newsgroups: net.micro.atari16 Subject: ST Calendar Desk Accessory (SOURCE) Message-ID: <210@atari.UUcp> Date: Thu, 24-Apr-86 15:19:24 EDT Article-I.D.: atari.210 Posted: Thu Apr 24 15:19:24 1986 Date-Received: Sun, 27-Apr-86 06:32:48 EDT Organization: Atari Corp., Sunnyvale, CA Lines: 547 Keywords: ST Accessory