[comp.sources.misc] v17i096: calentool - day/week/month/year-at-a-glance SunView tool, Part15/23

billr@saab.CNA.TEK.COM (Bill Randle) (04/06/91)

Submitted-by: Bill Randle <billr@saab.CNA.TEK.COM>
Posting-number: Volume 17, Issue 96
Archive-name: calentool/part15

#! /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 15 (of 23)."
# Contents:  dates/gdead devent.c event.h mpaint.c
# Wrapped by billr@saab on Thu Mar 28 08:38:26 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'dates/gdead' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dates/gdead'\"
else
echo shar: Extracting \"'dates/gdead'\" \(9832 characters\)
sed "s/^X//" >'dates/gdead' <<'END_OF_FILE'
X# CalenTool V2.2 - nflag=1 range=1,12 - DO NOT REMOVE THIS LINE
X# $Header: gdead,v 1.2 91/03/07 16:21:08 billr Exp $
X#
X# Dead Dates from the 1982 Dead Calendar
X#     courtesy of Tom Uffner <tom@cis.udel.edu>
X#
X** 01 02 99 99 00 Psychedelic Shop opens, Haight St. SF (1966)
X** 01 08 99 99 00 Acid Test Fillmore Aud. SF (1966)
X** 01 09 99 99 00 Bill Graham born (1931)
X** 01 13 99 99 00 "Stop Nuclear Power" benefit, Arlington Theatre, Santa Barbara (1978)
X** 01 13 99 99 00 Cambodian Boat People's benefit, Oakland Col. w/ Joan Baez (1980)
X** 01 14 99 99 00 Human Be-In, Golden Gate Park, SF, Dead, Airplane, Quicksilver (1967)
X** 01 19 99 99 00 Janis Joplin born (1943)
X** 01 21 99 99 00 Longshoreman's Hall Trips Festival, SF (thru 1-23-66)
X** 01 22 99 99 00 Honolulu Civic Aud. (first show in Hawaii) (1970)
X** 01 24 99 99 00 BAM's award, SF, Phil Lesh "best bassist" (1978)
X** 01 30 99 99 00 BAM's award, SF, Mickey Hart "best drummer", Dead "best group" (1979)
X** 01 31 99 99 00 Dead busted, New Orleans (1970)
X** 02 04 99 99 00 Neal Cassady dies (1968)
X** 02 08 99 99 00 Neal Cassady born (1926)
X** 02 11 99 99 00 Watts Acid Test, Compton, CA (1966)
X** 02 11 99 99 00 Fillmore East, NYC (w/ Duane and Gregg Allman, Peter Green) (1970)
X** 02 13 99 99 00 'Bears Choice' recorded at Fillmore East, NYC (also 2-14-70) (1970)
X** 02 13 99 99 00 "New Music for the 80's", Rhythm Devils debut, Marin, CA (1980)
X** 02 14 99 99 00 Dead/Airplane open Carousel Ballroom, SF (1968)
X** 02 17 99 99 00 "Rock for Life" benefit, Keith and Donna G.'s last show, Oakland (1979)
X** 02 19 99 99 00 ESP Experiment show, Capital Theatre, Portchester, NY (1971)
X** 02 23 99 99 00 Jefferson Airplane headline benefit for Dead's N.Orl. bust, Fill. W. (1970)
X** 03 03 99 99 00 Haight Street, SF, free concert (1968)
X** 03 05 99 99 00 Black Panther benefit, Oakland Aud. (1st show there), CA (1971)
X** 03 05 99 99 00 Rolling Thunder benefit, Winterland, SF (1972)
X** 03 08 99 99 00 Fillmore East opens, NYC (1968)
X** 03 08 99 99 00 Pigpen found dead (1973)
X** 03 12 99 99 00 Jack Kerouac born (1922)
X** 03 15 99 99 00 Phil Lesh born (1940)
X** 03 15 99 99 00 Benefit for SF Symphony ('Black and White Ball') Hilton Hotel, SF (1969)
X** 03 20 99 99 00 Rainbow Theatre, London (also 3-21 thru 3-24) (1981)
X** 03 23 99 99 00 Cow Palace debut of new sound system (25 tons, 641 spkrs, 48 amps) (1974)
X** 03 23 99 99 00 S.N.A.C.K. benefit w/ Merl Saunders, Ned Lagin, Kezer Stad. SF (1975)
X** 03 25 99 99 00 Academy of Music, NYC Donna's first show w/ Bo Diddley (1972)
X** 03 25 99 99 00 BAM's award, SF, Jerry Garcia "Musician of the year" (1980)
X** 03 28 99 99 00 Gruga Hall, Essen, Germany, w/ The Who, Flying Karamazov Bros. (1981)
X** 04 01 99 99 00 "April Fools Show" Capital Theatre, Passaic, NJ (1980)
X** 04 05 99 99 00 'Saturday Night Live' second appearance  (1980)
X** 04 07 99 99 00 Europe '72 Tour begins, Empire Pool, Wembley, England (1972)
X** 04 15 99 99 00 BAM's award, SF, Phil Lesh "best bassist" (1981)
X** 04 20 99 99 00 People's Park planted, Berkeley (1969)
X** 04 22 99 99 00 Brent Mydland's first show, Spartan Stadium, San Jose, CA (1979)
X** 04 26 99 99 00 Fillmore East, NYC w/ Duane Allman (1971)
X** 04 27 99 99 00 Fillmore East, NYC w/ Beach Boys (1971)
X** 04 28 99 99 00 Fillmore Eest, NYC w/ Tom Constanten (1971)
X** 04 29 99 99 00 Fillmore East, NYC last show (1971)
X** 04 30 99 99 00 Casey Jones killed (1900)
X** 05 06 99 99 00 MIT, Cambridge, MA free concert (1970)
X** 05 07 99 99 00 Bill Kreutzmann born (1946)
X** 05 07 99 99 00 'Tomorrow Show' interview and music (1981)
X** 05 13 99 99 00 Lille Fairgrounds, France (free concert) (1972)
X** 05 16 99 99 00 Diga Rhythm Band's first public appearance, Winterland w/ Starship  (1975)
X** 05 24 99 99 00 Hollywood Festival Newcastle, England (first European show) (1970)
X** 05 26 99 99 00 Europe '72 tour ends, Lyceum, London (1970)
X** 05 26 99 99 00 Day on the Green #1, Kezer Stadim, SF w/ Dead, NRPS (1973)
X** 05 27 99 99 00 First Avalon Ballroom show, SF (1966)
X** 06 01 99 99 00 Haight Ashbury Free Clinic opens, SF (1967)
X** 06 01 99 99 00 Dead Movie opens, Ziegfield Theatre, NYC (1977)
X** 06 03 99 99 00 'The Vacation Ends', Dead begin touring again, Portland, OR  (1976)
X** 06 06 99 99 00 'Seastones' debut at Dominican College, San Rafael, CA (1975)
X** 06 07 99 99 00 15-year anniversary shows, Folsom Field, Univ. of CO, Boulder (1980)
X** 06 08 99 99 00 Day on the Green w/ Beach Boys, Oakland (1974)
X** 06 09 99 99 00 RFK Stadium, Wash. DC, w/ Allman Bros. (1973)
X** 06 12 99 99 00 'Fire on the Mountain', Dead and Mt. St. Helens hit Portland (1980)
X** 06 14 99 99 00 First Fillmore East show (1968)
X** 06 15 99 99 00 Dead play at Straight Theatre christening party, SF (1967)
X** 06 17 99 99 00 Pigpen's last show, Hollywood Bowl, CA (1972)
X** 06 17 99 99 00 Bob Fried Memorial Boogie, Winterland, SF (1975)
X** 06 18 99 99 00 Dead at Monterey Pop Festival (1967)
X** 06 19 99 99 00 Summer Solstice shows, West High Aud., Anchorage, AK (thru 6-21) (1980)
X** 06 21 99 99 00 Chateau de Herouville, France, free concert (1971)
X** 06 22 99 99 00 Central Park, NYC free concert (1969)
X** 06 23 99 99 00 Robert Hunter born (1941)
X** 06 27 99 99 00 Fillmore East, NYC closes (1971)
X** 06 29 99 99 00 Red Dog Saloon opens, Virginia City, NV (1965)
X** 06 29 99 99 00 Canadian Train Tour begins, Toronto, ends 7-3 (1970)
X** 07 02 99 99 00 Last Fillmore West show, SF (1971)
X** 07 04 99 99 00 William Hitchcock's mansion, Millbrook, NY (1967)
X** 07 04 99 99 00 Fillmore West closes, SF (1971)
X** 07 08 99 99 00 Mississippi River Festival, Edwardsville, IL (1970)
X** 07 12 99 99 00 Orpheum Theatre shows begin, ends 7-18 (1976)
X** 07 19 99 99 00 Keith Godchaux born (1948)
X** 07 23 99 99 00 Keith Godchaux dies (1980)
X** 07 28 99 99 00 Watkins Glen, NY w/ Allman Bros., Band. 600,000 people (1973)
X** 08 01 99 99 00 Jerry Garcia born (1942)
X** 08 04 99 99 00 Newport Rock Festival, Costa Mesa, CA (1968)
X** 08 07 99 99 00 Merry Pranksters "Welcome Hell's Angels' Party", La Honda, CA (1965)
X** 08 13 99 99 00 Great American Music Hall, SF (1975)
X** 08 15 99 99 00 Woodstock Music and Arts Festival, NY (Dead 8-16), thru 8-17 (1969)
X** 08 20 99 99 00 First Fillmore West show, SF (1968)
X** 08 22 99 99 00 Donna Jean Godchaux born (1947)
X** 08 28 99 99 00 Springfield Creamery benefit, Lane County Fairgrounds, OR (1972)
X** 08 31 99 99 00 Dead at New Orleans Pop Festival (1969)
X** 09 03 99 99 00 Dead at Sky River Rock Festival, Washington (1968)
X** 09 08 99 99 00 Ron "Pigpen" McKernan born (1945)
X** 09 09 99 99 00 Alexandra Palace, London (start of '74 European Tour' (1974)
X** 09 10 99 99 00 Rolling Thunder (1916)
X** 09 11 99 99 00 Mickey Hart born (1943)
X** 09 11 99 99 00 Ken Kesey born (1935)
X** 09 14 99 99 00 Sound and Light Theatre, Gizah, Egypt, w/ Hamza El-Din, thru 9-16 (1978)
X** 09 16 99 99 00 Albert Hoffman's first LSD experience (1943)
X** 09 23 99 99 00 Jefferson Airplane/Muddy Waters headline first Winterland dance, SF (1966)
X** 09 25 99 99 00 Warfield shows begin, SF (return of accoustic sets) (1980)
X** 09 26 99 99 00 Record Factory auction of Dead artwork and memorabilia, San Rafael, SF (1976)
X** 09 28 99 99 00 Last free Dead show in Golden Gate Park, SF w/ Starship (1975)
X** 09 28 99 99 00 Cabrillo discovers California (1542 )
X** 09 29 99 99 00 Mickey Hart's first show, Straight Theatre, SF (1967)
X** 10 01 99 99 00 SF State College Acid Test (1966)
X** 10 02 99 99 00 710 Ashbury Street bust (1967)
X** 10 04 99 99 00 Janis Joplin dies (1970)
X** 10 06 99 99 00 LSD declared illegal (1966)
X** 10 06 99 99 00 'Death of Hippie' ceremony, SF (1967)
X** 10 07 99 99 00 First Winterland show as "The Grateful Dead", SF (1966)
X** 10 08 99 99 00 First 'Mickey and the Harbeats' show, The Matrix, SF (1968)
X** 10 09 99 99 00 Roadie benefit, Winterland, SF (1972)
X** 10 09 99 99 00 Who/Dead Day on the Green, Oakland, CA  (thru 10-10) (1976)
X** 10 14 99 99 00 Warfield shows end, SF (1980)
X** 10 15 99 99 00 Peace Festival, Mt. Tamalpais, CA (1966)
X** 10 16 99 99 00 Bob Wier born (1947)
X** 10 16 99 99 00 Dead 'retire' (five shows at Winterland), SF (1974)
X** 10 19 99 99 00 Keith Godchaux's first show, Northrup Aud., Minn., MN (1971)
X** 10 20 99 99 00 Mickey Hart rejoins band at Winterland (retirement shows end), SF (1974)
X** 10 21 99 99 00 Brent Mydland born (1952)
X** 10 21 99 99 00 Jack Kerouac dies (1969)
X** 10 23 99 99 00 Radio City Music Hall shows begin, NYC (thru 10-31) (1980)
X** 10 26 99 99 00 Dead play at North Face Ski Shop opening, SF (1966)
X** 10 27 99 99 00 KSAN's live tape weekend (vintage Fillmore, Avalon tapes played), SF (1972)
X** 11 06 99 99 00 Jefferson Airplane headline first Bill Graham show, SF (1965)
X** 11 09 99 99 00 First issue of Rolling Stone published, SF (1967)
X** 11 11 99 99 00 'Saturday Night Live' first appearance  (1978)
X** 11 15 99 99 00 Moratorium Day, Lanai Theatre, Crockett, CA (1969)
X** 11 15 99 99 00 Fillmore East, NYC w/ Winwood, Wood, Capaldi, Ramblin' Jack Elliot (1970)
X** 11 17 99 99 00 Acoustic benefit for Hunger Week, Chicago's Loyola College (1978)
X** 11 24 99 99 00 Capital Theatre, Passaic, NJ, nationwide broadcast (1978)
X** 12 04 99 99 00 San Jose Acid Test (1965)
X** 12 06 99 99 00 Mill Valley Recreation Center (free concert), CA (1980)
X** 12 10 99 99 00 First Fillmore Auditorium show (2nd Mime Troupe benefit), SF (1965)
X** 12 17 99 99 00 'Death and Rebirth of the Haight A. and Death of Money' parade, SF (1966)
X** 12 18 99 99 00 Big Beat Club Acid Test, Palo Alto, CA (1965)
X** 12 26 99 99 00 St. Stephens' Day
X** 12 27 99 99 00 First Dead Head arrives for Winterland closing, SF  (1978)
X** 12 31 99 99 00 First New Year's show Fillmore Auditorium, SR (1966)
X** 12 31 99 99 00 New Year's Eve at The Ark, Boston, MA (1969)
X** 12 31 99 99 00 Dead close Winterland, SF w/ Blues Bros., NRPS (1978)
X
END_OF_FILE
if test 9832 -ne `wc -c <'dates/gdead'`; then
    echo shar: \"'dates/gdead'\" unpacked with wrong size!
fi
# end of 'dates/gdead'
fi
if test -f 'devent.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'devent.c'\"
else
echo shar: Extracting \"'devent.c'\" \(30220 characters\)
sed "s/^X//" >'devent.c' <<'END_OF_FILE'
X/*
X * $Header: devent.c,v 2.8 91/03/27 16:45:23 billr Exp $
X */
X/*
X * devent.c
X *
X * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com>
X *
X * Original source Copyright (C) 1987, Sun Microsystems, Inc.
X *	All Rights Reserved
X * Permission is hereby granted to use and modify this program in source
X * or binary form as long as it is not sold for profit and this copyright
X * notice remains intact.
X *
X *
X * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM>
X *
X * Changes and additions Copyright (C) 1988, 1989, 1991 Tektronix, Inc.
X *	All Rights Reserved
X * Permission is hereby granted to use and modify the modifications in source
X * or binary form as long as they are not sold for profit and this copyright
X * notice remains intact.
X */
X/********************************************************
X *							*
X *      Day event routines for main subwindow.		*
X *							*
X ********************************************************/
X
X
X#include <stdio.h>
X#include <suntool/sunview.h>
X#include <suntool/canvas.h>
X#include <suntool/panel.h>
X#include <suntool/menu.h>
X#include <suntool/seln.h>
X#include <sys/time.h>
X#include <fcntl.h>
X#include "ct.h"
X#include "event.h"
X
Xextern Menu day_sel_menu;
Xextern Frame attr_frame;
Xextern Panel_item everyx_pi, repeat_pi, remind_pi;
Xextern Panel_item whichwk_pi, marked_pi, advw_pi;
Xextern Panel_item del_choice_pi;
Xextern Panel_item runl_pi;
Xextern Frame del_frame;
Xextern Panel del_panel;
Xextern Pixrect tri_right_pr, tri_up_pr;
Xextern Pixrect *leftarrow, *rightarrow, *morebutton;
Xextern int n_tslots, n_slots, start_hour;
Xextern Seln_client s_client;
Xint attr_bi;
Xstruct appt_entry shelf_appt = {0};
Xint old_slot = -1;	/* for text cursor location */
Xint box_index, found_flag;
Xchar sel_text[MAX_STRLEN];
Xstatic char *get_shelf();
Xextern int chk_deleted();
X
Xday_inputevent(canvas, event)
XCanvas canvas;
XEvent *event;
X{
X	Menu_item an_item;
X	int x, y;
X	int i, j, active_above, strl;
X	struct appt_entry *aptr;
X	static int start_arrow_box = -1, prev_box = 0;
X	static int expecting = 0;
X	char *paste_str;
X
X        found_flag = 0;                	/* See if cursor is in a box. */
X	/* translate coordinates back to pixwin space */
X	event = canvas_window_event(canvas, event);
X        x = event_x(event);
X        y = event_y(event);
X	if (event_id(event) == LOC_RGNEXIT && old_slot >= 0) {
X		/* erase text cursor */
X		text_cursor(old_slot);
X		old_slot = -1;
X	}
X
X        for (box_index=0; box_index<n_slots; box_index++) {
X		/* is cursor inside a slot ? */
X                if (x>=slots[box_index].slot_pos.left && x<=slots[box_index].slot_pos.right &&
X                    y>=slots[box_index].slot_pos.top && y<=slots[box_index].slot_pos.bottom) {
X                        found_flag = FOUND_SLOT;
X                        break;
X                }
X		/* is cursor inside a "more" button ? */
X                if (x>=slots[box_index].moreb_pos.left && x<=slots[box_index].moreb_pos.right &&
X                    y>=slots[box_index].moreb_pos.top && y<=slots[box_index].moreb_pos.bottom) {
X			if (slots[box_index].active > 1) {
X				/* "more" button is active */
X				found_flag = FOUND_MORE;
X				break;
X			}
X		}
X		/* is cursor inside a "leftarrow" button ? */
X                if (x>=slots[box_index].larrow_pos.left && x<=slots[box_index].larrow_pos.right &&
X                    y>=slots[box_index].larrow_pos.top && y<=slots[box_index].larrow_pos.bottom) {
X			found_flag = FOUND_LARROW;
X			break;
X		}
X		/* is cursor inside a "rightarrow" button ? */
X                if (x>=slots[box_index].rarrow_pos.left && x<=slots[box_index].rarrow_pos.right &&
X                    y>=slots[box_index].rarrow_pos.top && y<=slots[box_index].rarrow_pos.bottom) {
X			found_flag = FOUND_RARROW;
X			break;
X		}
X	}
X	if (old_slot >= 0) {
X		/* erase text cursor at old location */
X		text_cursor(old_slot);
X		old_slot = -1;
X	}
X
X        if (!found_flag && !expecting)
X                return(0);		/* Not in a box => ignore. */
X
X	if (event_id(event) == LOC_STILL || (event_is_button(event) && event_is_up(event))) {
X		if (found_flag == FOUND_SLOT && box_index != old_slot)
X			/* in a different slot than we were before */
X			if (slots[box_index].active)
X				/* display cursor at new location */
X			  text_cursor(box_index);
X	      }
X        if (found_flag == FOUND_SLOT && event_id(event) == KEY_LEFT(8)
X	    && event_is_up(event)) {
X		/*
X		 * Process a "Paste" ("Get") event by pasting the text
X		 * from the SHELF. Note that this is different from
X		 * pasting an appointment.
X		 */
X		if (!slots[box_index].active)
X			return(0);
X		new_entry = 1;	/* flag for file updating */
X		strl = strlen(slots[box_index].cur_appt->str);
X		paste_str = get_shelf();
X		if (paste_str == NULL) {
X			text_cursor(box_index);
X			return(0);
X		}
X		strncpy(slots[box_index].cur_appt->str + strl, paste_str,
X		    min(strlen(paste_str),MAX_STRLEN - strl ));
X		slots[box_index].cur_appt->str[min(strlen(paste_str) + strl, MAX_STRLEN)] = '\0';
X		rewrite_string(box_index, JUSTIFY_LEFT);
X		/* display cursor at new location */
X		text_cursor(box_index);
X	} else if (event_id(event) == KEY_LEFT(6) && event_is_up(event)) {
X		/* put string for current appt on the shelf */
X		if (found_flag == FOUND_SLOT && slots[box_index].active)
X			/* we're in an active slot */
X			strcpy(sel_text, slots[box_index].cur_appt->str);
X		else
X			sel_text[0] = '\0';
X	} else if (found_flag == FOUND_SLOT && event_id(event) <= ASCII_LAST) {
X		/* Process a kbd event. */
X                if (!slots[box_index].active)
X                        return(0);
X		if (event_id(event) == CTRL_R) {
X                        rewrite_string(box_index, JUSTIFY_LEFT);
X                        return(0);
X		}
X		if (slots[box_index].cur_appt->flags & READONLY)
X			return(0);
X		new_entry = 1;	/* flag for file updating */
X		strl = strlen(slots[box_index].cur_appt->str);
X                if (event_id(event) == CTRL_U) {
X                        slots[box_index].cur_appt->str[0] = '\0';
X                        rewrite_string(box_index, JUSTIFY_LEFT);
X                } else if (event_id(event) == CTRL_W) {
X                        while (strl > 0 && slots[box_index].cur_appt->str[strl-1] != ' ') {
X                                slots[box_index].cur_appt->str[strl-1] = '\0';
X				strl--;
X                        }
X			rewrite_string(box_index, JUSTIFY_RIGHT);
X                } else if (event_id(event) == DEL || event_id(event) == BACKSPACE) {
X			if (strl > 0) {
X                                slots[box_index].cur_appt->str[strl-1] = '\0';
X                                rewrite_string(box_index, JUSTIFY_RIGHT);
X                        }
X                } else if (event_id(event) >= (int)' ' && strl < MAX_STRLEN-2) {
X                        slots[box_index].cur_appt->str[strl] = (char)event_id(event);
X			slots[box_index].cur_appt->str[strl+1] = '\0';
X                        rewrite_string(box_index, JUSTIFY_RIGHT);
X                }
X		/* display cursor at new location */
X		text_cursor(box_index);
X	} else if (event_id(event) == MS_LEFT && event_is_down(event)) {
X		/* LB down event */
X		switch (found_flag) {
X			case FOUND_SLOT:
X				break;
X			case FOUND_MORE:
X				/* reverse video "more" button */
X				pw_rop(main_pixwin, slots[box_index].moreb_pos.left, slots[box_index].moreb_pos.top,
X					morebutton->pr_width, morebutton->pr_height, PIX_NOT(PIX_DST),
X					morebutton, 0, 0);
X				expecting = box_index + (FOUND_MORE<<8);
X				break;
X			case FOUND_LARROW:
X				do_left_arrow(canvas, box_index);
X				break;
X			case FOUND_RARROW:
X				do_right_arrow(canvas, box_index);
X				break;
X		}
X	} else if (event_id(event) == MS_LEFT && event_is_up(event)) {
X		/* Process an LB up click. */
X		i = expecting>>8;
X		if (expecting && found_flag != i) {
X			/* return button to normal video */
X			if (i == FOUND_MORE) {
X				/* "more" button */
X				i = expecting & 0xff;
X				pw_rop(main_pixwin, slots[i].moreb_pos.left, slots[i].moreb_pos.top,
X					morebutton->pr_width, morebutton->pr_height, PIX_SRC,
X					morebutton, 0, 0);
X			}
X		} else {
X			switch (found_flag) {
X				case FOUND_SLOT:
X					if (!read_only) {
X						make_box_active(box_index);
X						new_entry = 1;
X					}
X					break;
X				case FOUND_MORE:
X					next_appt(box_index, TRUE);
X					/* normal video "more" button */
X					pw_rop(main_pixwin, slots[box_index].moreb_pos.left, slots[box_index].moreb_pos.top,
X						morebutton->pr_width, morebutton->pr_height, PIX_SRC,
X						morebutton, 0, 0);
X					break;
X				case FOUND_LARROW:
X					break;
X				case FOUND_RARROW:
X					break;
X			}
X		}
X		expecting = 0;
X	} else if (found_flag == FOUND_SLOT && event_id(event) == MS_MIDDLE) {
X		/* Process a MB click. */
X		if (event_is_down(event)) {
X			/* try to start dragging from here */
X			if (!slots[box_index].active || box_index >= n_tslots) {
X				/* not allowed in notes slots, either */
X				start_arrow_box = -1;
X				return(0);
X			}
X			if ((slots[box_index].cur_appt->flags & READONLY) || read_only) {
X				start_arrow_box = -1;
X				return(0);
X			}
X			if (slots[box_index].cur_appt->arrows > 0) {
X				/* remove old arrows and adjust counts */
X				deactivate_lower_arrows(box_index, TRUE);
X				j = slots[box_index].cur_appt->arrows;
X				while (j > 0)
X					slots[box_index+(j--)].count--;
X				slots[box_index].cur_appt->arrows = 0;
X			}
X			prev_box = start_arrow_box = box_index;
X		} else {
X			if (box_index >= n_tslots) {
X				/* mouse currently in notes section */
X				if (start_arrow_box == -1)
X					/* started in notes section, too */
X					return(0);
X				else
X					/* truncate at start of notes section */
X					box_index = n_tslots - 1;
X			}
X			/* end of dragging => end of arrow */
X			if (box_index > start_arrow_box && start_arrow_box != -1) {
X				int left = (dayslot_width-2)/2 - 8;
X
X				i = start_arrow_box;
X				slots[i].cur_appt->arrows = box_index - start_arrow_box;
X				while (++i < box_index) {
X					slots[i].count++;
X					/*
X					 * erase arrow shaft on boxes - it will be
X					 * replaced by a real arrowshaft during redraw
X					 */
X					pw_rop(main_pixwin, slots[i].slot_pos.left+left,
X						slots[i].slot_pos.top+1,
X						16, dayslot_height-2,
X						PIX_SRC^PIX_DST, arrowshaft_pr,
X						0, 0);
X				}
X				slots[i].count++;
X				/*
X				 * erase arrow shaft on last box - it will be
X				 * replaced by an arrowhead during redraw
X				 */
X				pw_rop(main_pixwin, slots[i].slot_pos.left+left,
X					slots[i].slot_pos.top+1,
X					16, dayslot_height-2,
X					PIX_SRC^PIX_DST, arrowshaft_pr,
X					0, 0);
X			}
X			start_arrow_box = -1;
X			new_entry = 1;
X			draw_day_appts();
X		}
X	} else if (found_flag == FOUND_SLOT && event_id(event) == LOC_DRAG) {
X		/* mouse dragging - is it the middle button ? */
X		if ((int)window_get(canvas, WIN_EVENT_STATE, MS_MIDDLE) && start_arrow_box >= 0) {
X			int left = (dayslot_width-2)/2 - 8;
X
X			if (box_index >= n_tslots)
X				/* don't flow into notes section */
X				box_index = n_tslots - 1;
X			/*
X			 * xor arrow shaft thru current slot so
X			 * we can see where we're dragging
X			 */
X			if (box_index > prev_box) {
X				while (++prev_box <= box_index) {
X					pw_rop(main_pixwin, slots[prev_box].slot_pos.left+left,
X						slots[prev_box].slot_pos.top+1,
X						16, dayslot_height-2,
X						PIX_SRC^PIX_DST, arrowshaft_pr,
X						0, 0);
X				}
X				prev_box = box_index;
X			} else if (box_index < prev_box && box_index >= start_arrow_box) {
X				/* going backwards - cleanup as we go */
X				while (prev_box > box_index) {
X					pw_rop(main_pixwin, slots[prev_box].slot_pos.left+left,
X						slots[prev_box].slot_pos.top+1,
X						16, dayslot_height-2,
X						PIX_SRC^PIX_DST, arrowshaft_pr,
X						0, 0);
X					--prev_box;
X				}
X			}
X		}
X	} else if (found_flag == FOUND_SLOT && event_id(event) == MS_RIGHT && event_is_down(event)) {
X		/* Process a RB click. */
X		/*
X		 * display popup menu of choices, but first disable
X		 * certain entries if this is a readonly appointment
X		 * or an empty slot.
X		 */
X		/* undelete - almost always inactive */
X		an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MUNDELETE);
X		menu_set(an_item, MENU_INACTIVE, TRUE, 0);
X		if (!slots[box_index].first) {
X			/* empty slot. only paste active */
X			paste_only();
X		} else if (slots[box_index].cur_appt->flags & READONLY) {
X			/* readonly => paste and copy only */
X			paste_only();
X			/* copy */
X			an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MCOPY);
X			menu_set(an_item, MENU_INACTIVE, FALSE, 0);
X		} else {
X			/* delete */
X			an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MDELETE);
X			menu_set(an_item, MENU_INACTIVE, FALSE, 0);
X			/* cut */
X			an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MCUT);
X			menu_set(an_item, MENU_INACTIVE, FALSE, 0);
X			/* copy */
X			an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MCOPY);
X			menu_set(an_item, MENU_INACTIVE, FALSE, 0);
X			/* modify */
X			an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MMODIFY);
X			menu_set(an_item, MENU_INACTIVE, FALSE, 0);
X			for (aptr=slots[box_index].first; aptr; aptr=aptr->next)
X				if (aptr->flags & DELETED) {
X					if (!slots[box_index].active)
X						/* only paste and undelete */
X						paste_only();
X					/* undelete */
X					an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MUNDELETE);
X					menu_set(an_item, MENU_INACTIVE, FALSE, 0);
X					break;
X				}
X		}
X		i = (int) menu_show(day_sel_menu, canvas, event, 0);
X		if (i > 0) {
X			switch (i) {
X				case MDELETE:
X					delete_appt(box_index, canvas);
X					break;
X				case MCUT:
X					cut_appt(box_index, canvas);
X					break;
X				case MCOPY:
X					copy_appt(box_index);
X					break;
X				case MPASTE:
X					paste_appt(box_index);
X					break;
X				case MMODIFY:
X					modify_appt(box_index, canvas);
X					break;
X				case MUNDELETE:
X					undelete_appt(box_index);
X					break;
X			}
X			if (new_entry) {
X				close_day();
X				draw_day();	/* redraw display */
X			}
X		}
X	} else
X		window_default_event_proc(canvas, event, 0);
X	return(1);
X}
X
X
X/* make "paste" the only active menu entry */
Xpaste_only()
X{
X	Menu_item an_item;
X
X	/* delete */
X	an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MDELETE);
X	menu_set(an_item, MENU_INACTIVE, TRUE, 0);
X	/* cut */
X	an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MCUT);
X	menu_set(an_item, MENU_INACTIVE, TRUE, 0);
X	/* copy */
X	an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MCOPY);
X	menu_set(an_item, MENU_INACTIVE, TRUE, 0);
X	/* modify */
X	an_item = menu_get(day_sel_menu, MENU_NTH_ITEM, MMODIFY);
X	menu_set(an_item, MENU_INACTIVE, TRUE, 0);
X}
X
X/* draw (or erase) text cursor in a day slot */
Xtext_cursor(slotno)
Xint slotno;
X{
X	int	strl, x;
X
X	strl = strlen(&slots[slotno].cur_appt->str[slots[slotno].cur_appt->sindex]);
X	if (strl <= (day_message_size-1)) {
X		x = slots[slotno].slot_pos.left + strl * font->pf_defaultsize.x;
X		pw_write(main_pixwin, x, slots[slotno].slot_pos.bottom-4,
X		  16, 16, PIX_SRC^PIX_DST, &tri_up_pr, 0, 0);
X	}
X	old_slot = slotno;
X}
X
X/* make slot active */
Xmake_box_active(bi)
Xint bi;
X{
X	add_to_slot(bi, NULL, TRUE);
X	fill_appt(bi);
X	rewrite_string(bi, JUSTIFY_LEFT);
X	text_cursor(bi);
X}
X
X/* activate a hidden appt and make it visible */
Xint
Xactivate_slot(bi, dpyflag)
Xint bi;
Xint dpyflag;
X{
X	if (slots[bi].active <= 0)
X		/* nothing to activate */
X		return(0);
X
X	if (dpyflag)
X		draw_day_appts();	/* redraw display */
X
X	return(1);
X}
X
X/* clears a day slot */
Xdeactivate_slot(bi, dpyflag)
Xint bi, dpyflag;
X{
X	if (!dpyflag)
X		return;
X	/* erase text cursor at old location */
X	if (old_slot >= 0) {
X		text_cursor(old_slot);
X		old_slot = -1;
X	}
X	/* erase displayed slot */
X	if (!ymd_compare(current, today))
X		pw_write(main_pixwin, slots[bi].slot_pos.left, slots[bi].slot_pos.top,
X		  dayslot_width, dayslot_height, PIX_SRC, timeslot_td_pr, 0, 0);
X	else
X		pw_write(main_pixwin, slots[bi].slot_pos.left+1, slots[bi].slot_pos.top+1,
X		  dayslot_width-2, dayslot_height-2, PIX_CLR, NULL, 0, 0);
X	if (slots[bi].cur_appt->arrows > 0)
X		deactivate_lower_arrows(bi, dpyflag);
X}
X
X/* clear any displayed arrowshafts and arrowheads */
Xdeactivate_lower_arrows(bi, dpyflag)
Xint bi, dpyflag;
X{
X	int narrows, offset;
X
X	if (!dpyflag)
X		return;
X	narrows = slots[bi].cur_appt->arrows;
X	offset = (slots[bi].count - slots[bi].active + 1) * 40;
X	while (narrows-- > 0) {
X		bi++;
X		if (slots[bi].active)
X			continue;
X		/* erase displayed arrowshaft or arrowhead */
X		if (!ymd_compare(current, today))
X			pw_write(main_pixwin, slots[bi].slot_pos.left+1+offset,
X			  slots[bi].slot_pos.top+1, 16,
X			  dayslot_height-2, PIX_SRC, timeslot_td_pr, 0, 0);
X		else
X			pw_write(main_pixwin, slots[bi].slot_pos.left+1+offset,
X			  slots[bi].slot_pos.top+1, 16,
X			  dayslot_height-2, PIX_CLR, NULL, 0, 0);
X	}
X}
X
X/* fill in appt struct with current info */
Xfill_appt(bi)
Xint bi;
X{
X	int s_hour, s_minute, n_arrows;
X
X	slots[bi].cur_appt->year = current.tm_year;
X	slots[bi].cur_appt->month = current.tm_mon;
X	slots[bi].cur_appt->day = current.tm_mday;
X	slots[bi].cur_appt->arrows = 0;
X	slots[bi].cur_appt->flags = slots[bi].cur_appt->repeat = 0;
X	slots[bi].cur_appt->lookahead = slots[bi].cur_appt->sindex = 0;
X	slots[bi].cur_appt->runlength = 0;
X	slots[bi].cur_appt->warn = 10;
X	if (bi >= n_tslots) {
X		/* notes section */
X		slots[bi].cur_appt->hour = 99;
X		slots[bi].cur_appt->minute = 0;
X		slots[bi].cur_appt->flags = A_NOTE;
X	} else {
X		/* regular appt */
X		slots[bi].cur_appt->hour = bi/2 + start_hour;
X		slots[bi].cur_appt->minute = (bi % 2) * 30;
X	}
X	slots[bi].cur_appt->str[0] = '\0';
X}
X
X/*
X * Display delete popup window to let user choose delete mode for
X * recurring appts (delete this one only or delete all), otherwise,
X * just wipe it out with no options.
X */
Xdelete_appt(bi, canvas)
Xint bi;
XCanvas canvas;
X{
X	Rect *canvas_r;
X	int top, left, width, height;
X
X	if (slots[bi].cur_appt->flags & READONLY) {
X		err_rpt("Can't delete a read-only appt", NON_FATAL);
X		return;
X	}
X	if (Repeating(slots[bi].cur_appt->flags)) {
X		attr_bi = bi;	/* set global index for notify func */
X
X		/* get x,y position of canvas window on the screen so we
X		 * can center popup window in it.
X		 */
X		canvas_r = (Rect *) window_get(canvas, WIN_RECT);
X		panel_set(del_choice_pi, PANEL_CHOICE_STRINGS,
X			"Delete this occurrance only",
X			"Delete all occurrances", 0,
X			PANEL_CLIENT_DATA, 0,
X			0);
X		window_fit(del_panel);
X		window_fit(del_frame);
X		width = (int) window_get(del_frame, WIN_WIDTH);
X		height = (int) window_get(del_frame, WIN_HEIGHT);
X		left =  canvas_r->r_left + (canvas_r->r_width - width) / 2;
X		top =  canvas_r->r_top + (canvas_r->r_height - height) / 2;
X		window_set(del_frame, WIN_X, left, WIN_Y, top, 0);
X		panel_set_value(del_choice_pi, 0);
X
X		window_loop(del_frame);	/* let user select things */
X	} else {
X		cut_delete(bi);
X		new_entry = 1;
X	}
X}
X
Xcut_appt(bi, canvas)
Xint bi;
XCanvas canvas;
X{
X	Rect *canvas_r;
X	int top, left, width, height;
X	int i;
X
X	/* cut (delete) current entry, saving the info on the "shelf" */
X	if (slots[bi].cur_appt->flags & READONLY) {
X		err_rpt("Can't cut a read-only appt", NON_FATAL);
X		return;
X	}
X	shelf_appt = *slots[bi].cur_appt;
X	if (Repeating(slots[bi].cur_appt->flags)) {
X		attr_bi = bi;	/* set global index for notify func */
X
X		/* get x,y position of canvas window on the screen so we
X		 * can center popup window in it.
X		 */
X		canvas_r = (Rect *) window_get(canvas, WIN_RECT);
X		panel_set(del_choice_pi, PANEL_CHOICE_STRINGS,
X			"Move this occurrance only",
X			"Move all occurrances", 0,
X			PANEL_CLIENT_DATA, 1,
X			0);
X		window_fit(del_panel);
X		window_fit(del_frame);
X		width = (int) window_get(del_frame, WIN_WIDTH);
X		height = (int) window_get(del_frame, WIN_HEIGHT);
X		left =  canvas_r->r_left + (canvas_r->r_width - width) / 2;
X		top =  canvas_r->r_top + (canvas_r->r_height - height) / 2;
X		window_set(del_frame, WIN_X, left, WIN_Y, top, 0);
X		panel_set_value(del_choice_pi, 0);
X
X		window_loop(del_frame);	/* let user select things */
X	} else {
X		cut_delete(bi);
X		new_entry = 1;
X	}
X}
X
Xcut_delete(bi)
Xint bi;
X{
X	int j;
X	struct appt_entry *aptr, *cptr, *optr;
X
X	cptr = slots[bi].cur_appt;
X	slots[bi].count--;
X	slots[bi].active--;
X	deactivate_slot(bi, TRUE);
X	if ( (j = cptr->arrows) > 0) {
X		/* adjust counts */
X		while (j > 0)
X			slots[bi+(j--)].count--;
X	}
X	if (slots[bi].cur_appt == slots[bi].first) {
X		/* displaying first entry in list */
X		/* see if there's any more */
X		if (slots[bi].first->next)
X			slots[bi].first = slots[bi].first->next;
X		else {
X			/* last one */
X			slots[bi].first = NULL;
X			slots[bi].active = 0;
X		}
X		slots[bi].cur_appt = slots[bi].first;
X	} else {
X		/* not first, so find previous one to this */
X		for (aptr=slots[bi].first; slots[bi].cur_appt!=aptr; optr=aptr,aptr=aptr->next)
X			;
X		slots[bi].cur_appt = optr->next = aptr->next;
X		if (!optr->next)
X			slots[bi].cur_appt = slots[bi].first;
X	}
X	free(cptr);
X	(void)activate_slot(bi, TRUE);	/* show any hidden appts */
X}
X
Xcopy_appt(bi)
Xint bi;
X{
X	/* copy current entry, saving the info on the "shelf" */
X	shelf_appt = *slots[bi].cur_appt;
X}
X
Xpaste_appt(bi)
Xint bi;
X{
X	int j;
X
X	/* insert the saved entry (if any) */
X	if (shelf_appt.str[0] == '\0') {
X		err_rpt("nothing to paste", NON_FATAL);
X		return;
X	}
X	shelf_appt.year = current.tm_year;
X	shelf_appt.month = current.tm_mon;
X	shelf_appt.day = current.tm_mday;
X	if (shelf_appt.flags & EVERY_SOMEDAY) {
X		/* change repeating appt to this day */
X		shelf_appt.flags &= ~EVERY_SOMEDAY;
X		shelf_appt.flags |= Setday(current.tm_wday);
X	}
X	if (bi >= n_tslots) {
X		/* notes section */
X		shelf_appt.hour = 99;
X		shelf_appt.minute = 0;
X		/* just in case converting from time to note */
X		shelf_appt.flags |= A_NOTE;
X	} else {
X		/* regular appt */
X		shelf_appt.hour = bi/2 + start_hour;
X		shelf_appt.minute = (bi % 2) * 30;
X		/* just in case converting from note to time */
X		shelf_appt.flags &= ~MARKED_NOTE;
X	}
X	add_to_slot(bi, &shelf_appt, TRUE);
X	new_entry = 1;
X}
X
X/*
X * Display attributes popup window to let user modify
X * various appointment options (such as repeat interval,
X * etc.)
X */
Xmodify_appt(bi, canvas)
Xint bi;
XCanvas canvas;
X{
X	Rect *canvas_r;
X	int top, left, width, height;
X
X	if (slots[bi].cur_appt->flags & READONLY) {
X		err_rpt("Can't modify a read-only appt", NON_FATAL);
X		return;
X	}
X	attr_bi = bi;	/* set global index for notify func */
X	set_attr();	/* set panel item current values */
X
X	/* get x,y position of canvas window on the screen so we
X	 * can center this one in it.
X	 */
X	canvas_r = (Rect *) window_get(canvas, WIN_RECT);
X	width = (int) window_get(attr_frame, WIN_WIDTH);
X	height = (int) window_get(attr_frame, WIN_HEIGHT);
X	left =  canvas_r->r_left + (canvas_r->r_width - width) / 2;
X	top =  canvas_r->r_top + (canvas_r->r_height - height) / 2;
X	window_set(attr_frame, WIN_X, left, WIN_Y, top, 0);
X
X	window_loop(attr_frame);	/* let user select things */
X	window_set(attr_frame, WIN_SHOW, FALSE, 0);
X}
X
X/* undelete a recurring appointment for this day */
X/* we only get here if a deleted appt exists */
Xundelete_appt(bi)
Xint bi;
X{
X	struct appt_entry *aptr, *optr;
X
X	/* search list to find deleted entry */
X	for (optr=aptr=slots[bi].first; aptr; optr=aptr,aptr=aptr->next)
X		if (aptr->flags & DELETED)
X			break;
X	if (aptr == slots[bi].first)
X		slots[bi].first = aptr->next;
X	else
X		optr->next = aptr->next;
X	slots[bi].count++;
X	slots[bi].active++;
X	if (slots[bi].active == 1) {
X		slots[bi].cur_appt = slots[bi].first;
X		(void)activate_slot(bi, TRUE);
X	}
X	free(aptr);
X	new_entry = 1;
X}
X
Xset_attr()
X{
X	int everyx_val = 0, whichwk_val = 0;
X	char str[5];
X	struct appt_entry *apt = slots[attr_bi].cur_appt;
X
X	panel_set_value(repeat_pi, "");	/* set default */
X	panel_set_value(remind_pi, "");	/* set default */
X	panel_set_value(runl_pi, "");	/* set default */
X	if (apt->flags & EVERY_MON_FRI)
X		everyx_val |= 0x1;
X	else if (apt->flags & ALL_DAYS)
X		everyx_val |= 0x2;
X	if (apt->flags & ALL_MONTHS)
X		everyx_val |= 0x8;
X	if (apt->flags & ALL_YEARS)
X		everyx_val |= 0x10;
X	if (apt->flags & EVERY_SOMEDAY) {
X		everyx_val |= 0x4;
X		if (apt->repeat == ALL_WEEKS)
X			whichwk_val = 0x40;
X		else
X			whichwk_val = apt->repeat;
X		panel_set(repeat_pi, PANEL_SHOW_ITEM, FALSE, 0);
X		panel_set(whichwk_pi, PANEL_SHOW_ITEM, TRUE, 0);
X	} else {
X		if (apt->repeat) {
X			sprintf(str, "%d", apt->repeat);
X			panel_set_value(repeat_pi, str);
X		}
X		panel_set(whichwk_pi, PANEL_SHOW_ITEM, FALSE, 0);
X		panel_set(repeat_pi, PANEL_SHOW_ITEM, TRUE, 0);
X	}
X	panel_set_value(everyx_pi, everyx_val);
X	panel_set_value(whichwk_pi, whichwk_val);
X	if (apt->flags & LOOKAHEAD) {
X		sprintf(str, "%d", apt->lookahead);
X		panel_set_value(remind_pi, str);
X	}
X	if (apt->flags & RUN) {
X		sprintf(str, "%d", apt->runlength);
X		panel_set_value(runl_pi, str);
X	}
X	panel_set_value(marked_pi, (apt->flags & MARKED ? 1 : 0));
X	sprintf(str, "%d", apt->warn);
X	panel_set_value(advw_pi, str);
X	if (apt->flags & A_NOTE)
X		panel_set(marked_pi, PANEL_SHOW_ITEM, TRUE, 0);
X	else
X		panel_set(marked_pi, PANEL_SHOW_ITEM, FALSE, 0);
X}
X
X/* "more" button selected. Display next appt in rotation. */
Xnext_appt(bi, dpyflag)
Xint bi;
Xint dpyflag;
X{
X	static int loopcnt = 0;
X
X	if (slots[bi].active)
X		deactivate_slot(bi, dpyflag);
X
X	if (slots[bi].cur_appt->next == NULL) {
X		/* end of the chain */
X		slots[bi].cur_appt = slots[bi].first;
X		if (loopcnt) {
X			/* infinite loop detected */
X			loopcnt = 0;
X			return;
X		} else
X			++loopcnt;
X	} else
X		/* activate next in chain */
X		slots[bi].cur_appt = slots[bi].cur_appt->next;
X	/* make sure it is not a deleted one */
X	if (chk_deleted(&slots[bi], slots[bi].cur_appt))
X		next_appt(bi, dpyflag); /* try next in chain */
X	else if (!activate_slot(bi, dpyflag))
X		next_appt(bi, dpyflag); /* try next in chain */
X	loopcnt = 0;
X}
X
X/* left scroll arrow selected */
Xdo_left_arrow(canvas, bi)
XCanvas canvas;
Xint bi;
X{
X	struct timeval timeout;
X	Event event;
X	int fd, ertn, flags;
X
X	if (!slots[bi].active || strlen(slots[bi].cur_appt->str) < day_message_size)
X		return;
X	timeout.tv_sec = 0L;
X	timeout.tv_usec = 100000L;	/* 1/10 sec */
X	fd = (int)window_get(canvas, WIN_FD);
X	flags = fcntl(fd, F_GETFL, 0);
X	(void)fcntl(fd, F_SETFL, flags|FNDELAY);
X	/* reverse video the arrow */
X	pw_rop(main_pixwin, slots[bi].larrow_pos.left, slots[bi].larrow_pos.top,
X		19, 14, PIX_NOT(PIX_DST), leftarrow, 0, 0);
X	while (TRUE) {
X		if (slots[bi].cur_appt->sindex < strlen(slots[bi].cur_appt->str)) {
X			++slots[bi].cur_appt->sindex;
X			rewrite_string(bi, JUSTIFY_INDEX);
X			/* reverse video the arrow (rewrite changed it) */
X			pw_rop(main_pixwin, slots[bi].larrow_pos.left, slots[bi].larrow_pos.top,
X				19, 14, PIX_NOT(PIX_DST), leftarrow, 0, 0);
X		}
X		/* do this garbage to handle a repeat function */
X		(void)select(0, NULL, NULL, NULL, &timeout);
X		ertn = window_read_event(canvas, &event);
X		if (ertn != -1 && event_is_up(&event))
X			break;
X	}
X	/* put arrow back to normal */
X	pw_rop(main_pixwin, slots[bi].larrow_pos.left, slots[bi].larrow_pos.top,
X		19, 14, PIX_SRC, leftarrow, 0, 0);
X	(void)fcntl(fd, F_SETFL, flags & ~FNDELAY);
X}
X
X/* right scroll arrow selected */
Xdo_right_arrow(canvas, bi)
XCanvas canvas;
Xint bi;
X{
X	struct timeval timeout;
X	Event event;
X	int fd, ertn, flags;
X
X	if (!slots[bi].active || strlen(slots[bi].cur_appt->str) < day_message_size)
X		return;
X	timeout.tv_sec = 0L;
X	timeout.tv_usec = 100000L;	/* 1/10 sec */
X	fd = (int)window_get(canvas, WIN_FD);
X	flags = fcntl(fd, F_GETFL, 0);
X	(void)fcntl(fd, F_SETFL, flags|FNDELAY);
X	/* reverse video the arrow */
X	pw_rop(main_pixwin, slots[bi].rarrow_pos.left, slots[bi].rarrow_pos.top,
X		19, 14, PIX_NOT(PIX_DST), rightarrow, 0, 0);
X	while (TRUE) {
X		if (slots[bi].cur_appt->sindex > 0) {
X			--slots[bi].cur_appt->sindex;
X			rewrite_string(bi, JUSTIFY_INDEX);
X			/* reverse video the arrow (rewrite changed it) */
X			pw_rop(main_pixwin, slots[bi].rarrow_pos.left, slots[bi].rarrow_pos.top,
X				19, 14, PIX_NOT(PIX_DST), rightarrow, 0, 0);
X		}
X		/* do this garbage to handle a repeat function */
X		(void)select(0, NULL, NULL, NULL, &timeout);
X		ertn = window_read_event(canvas, &event);
X		if (ertn != -1 && event_is_up(&event))
X			break;
X	}
X	pw_rop(main_pixwin, slots[bi].rarrow_pos.left, slots[bi].rarrow_pos.top,
X		19, 14, PIX_SRC, rightarrow, 0, 0);
X	(void)fcntl(fd, F_SETFL, flags & ~FNDELAY);
X}
X
X/*
X * get_shelf - get text from selection service shelf for copy
X * operation. From Mark Feblowitz <mdf0%shemesh@gte.COM>.
X */
Xstatic
Xchar *
Xget_shelf()
X{
X	Seln_holder	holder;
X	Seln_request	*buffer;
X
X	holder = seln_inquire(SELN_SHELF);
X	/* do we have the shelf? */
X	if (!seln_holder_same_process(&holder)) {
X		buffer = seln_ask(&holder, SELN_REQ_CONTENTS_ASCII, 0, 0);
X		(void) strncpy(sel_text, buffer->data + sizeof(Seln_attribute),
X			MAX_STRLEN-1);
X		sel_text[MAX_STRLEN-1] = '\0';
X		if (strlen(sel_text) == 0)
X			/* empty string is no sel. */
X			return(NULL);
X		sel_text[MAX_STRLEN-1] = '\0';
X	}
X	return(sel_text);
X}
X
X/*
X * respond to function keys the selection service thinks
X * are important
X */
Xvoid
Xsel_func_key_proc(client_data, args)
Xchar *client_data;
XSeln_function_buffer *args;
X{
X	Seln_holder *holder;
X	Seln_response resp;
X
X	if ((resp = seln_figure_response(args, &holder)) == SELN_SHELVE) {
X		/* put string for current appt on the shelf */
X		if (found_flag == FOUND_SLOT && slots[box_index].active)
X			/* we're in an active slot */
X			strcpy(sel_text, slots[box_index].cur_appt->str);
X		else
X			sel_text[0] = '\0';
X	}
X}
X
X/*
X * called by selection svc library when someone requests our shelf
X * text. Abridged from the seln_demo() in the SunView manual.
X */
XSeln_result
Xsel_reply_proc(item, context, length)
XSeln_attribute item;
XSeln_replier_data *context;
Xint length;
X{
X	char *destp, *seln = NULL;
X	int size;
X
X	if (context->rank == SELN_SHELF)
X		seln = sel_text;
X	
X	switch (item) {
X		case SELN_REQ_CONTENTS_ASCII:
X			/* send the contents of the selection buffer */
X			if (seln == NULL)
X				return(SELN_DIDNT_HAVE);
X			context->context = seln;
X			size = strlen(seln);
X			destp = (char *)context->response_pointer;
X			/* allow for padding */
X			(void) strncpy(destp, seln, length-8);
X			destp += size;
X			/* pad to long word */
X			while ((int)destp % 4 != 0)
X				*destp++ = '\0';
X			context->response_pointer = (char **)destp;
X			*context->response_pointer++ = 0;
X			break;
X		
X		case SELN_REQ_YIELD:
X			*context->response_pointer++ = (char *)SELN_SUCCESS;
X			break;
X		
X		case SELN_REQ_BYTESIZE:
X			if (seln == NULL)
X				return(SELN_DIDNT_HAVE);
X			*context->response_pointer++ = (char *)strlen(seln);
X			break;
X			
X		case SELN_REQ_END_REQUEST:
X			break;
X		
X		default:
X			return(SELN_UNRECOGNIZED);
X	}
X
X	return(SELN_SUCCESS);
X}
END_OF_FILE
if test 30220 -ne `wc -c <'devent.c'`; then
    echo shar: \"'devent.c'\" unpacked with wrong size!
fi
# end of 'devent.c'
fi
if test -f 'event.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'event.h'\"
else
echo shar: Extracting \"'event.h'\" \(1467 characters\)
sed "s/^X//" >'event.h' <<'END_OF_FILE'
X/*
X * $Header: event.h,v 2.2 91/02/01 12:19:43 billr Exp $
X */
X/*
X * event.h
X *
X * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com>
X *
X * Original source Copyright (C) 1987, Sun Microsystems, Inc.
X *	All Rights Reserved
X * Permission is hereby granted to use and modify this program in source
X * or binary form as long as it is not sold for profit and this copyright
X * notice remains intact.
X *
X *
X * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM>
X *
X * Changes and additions Copyright (C) 1988, 1989, 1991 Tektronix, Inc.
X *	All Rights Reserved
X * Permission is hereby granted to use and modify the modifications in source
X * or binary form as long as they are not sold for profit and this copyright
X * notice remains intact.
X */
X
Xextern struct dayslot *slots;
Xextern int mainsw_state, day_is_open;
Xextern struct rect_limits boxlims[];
Xextern struct rect_limits mboxlims[];
Xextern int selected_type, read_only, new_entry;
Xextern int dayslot_width, nr_weekdays, day_message_size;
Xextern int dayslot_height, weekslot_height, weekslot_width;
Xextern int ybox_height, ybox_width;
Xextern struct weekrect week_boxes[];
Xextern Pixwin *main_pixwin;
Xextern Pixfont *font;
Xextern Cursor month_cursor, week_cursor, day_cursor;
Xextern Pixrect *smallarrow_pr, *arrowhead_pr, *arrowshaft_pr;
Xextern struct week_arrow week_arrows[];
Xextern struct tm current;
Xextern struct tm today;
Xextern Pixrect *timeslot_td_pr, *morebutton;
X
END_OF_FILE
if test 1467 -ne `wc -c <'event.h'`; then
    echo shar: \"'event.h'\" unpacked with wrong size!
fi
# end of 'event.h'
fi
if test -f 'mpaint.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mpaint.c'\"
else
echo shar: Extracting \"'mpaint.c'\" \(9590 characters\)
sed "s/^X//" >'mpaint.c' <<'END_OF_FILE'
X/*
X * $Header: mpaint.c,v 2.5 91/03/27 16:45:56 billr Exp $
X */
X/*
X * mpaint.c
X *
X * Author: Philip Heller, Sun Microsystems. Inc. <terrapin!heller@sun.com>
X *
X * Original source Copyright (C) 1987, Sun Microsystems, Inc.
X *	All Rights Reserved
X * Permission is hereby granted to use and modify this program in source
X * or binary form as long as it is not sold for profit and this copyright
X * notice remains intact.
X *
X *
X * Changes/additions by: Bill Randle, Tektronix, Inc. <billr@saab.CNA.TEK.COM>
X *
X * Changes and additions Copyright (C) 1988, 1989, 1991 Tektronix, Inc.
X *	All Rights Reserved
X * Permission is hereby granted to use and modify the modifications in source
X * or binary form as long as they are not sold for profit and this copyright
X * notice remains intact.
X */
X/***************************************************
X *						   *
X *	Artistic routines that draw in the main    *
X * subwindow for the month display.		   *
X *						   *
X ***************************************************/
X
X#include <suntool/sunview.h>
X#include <suntool/canvas.h>
X#include <ctype.h>
X#include <stdio.h>
X#include "ct.h"
X#include "paint.h"
X#ifndef NO_HOLIDAYS
Xextern struct appt_entry a_appts[], c_appts[];
Xextern struct appt_entry i_appts[], j_appts[];
Xextern struct appt_entry s_appts[];
X#endif
X
X/*
X * Routine to draw month calendar.
X */
X
Xdraw_month()
X{
X	int start_dow, i, j, k, x, y, n_days;
X	int days_in_week;
X	int arrow_index, last_top, index;
X	char c[4], title[20], *cp;
X	int left_border, right_border, top_border, bottom_border;
X	Rect *rect;
X	int busy_today[31];
X	FILE *apts;
X	int read_stat;
X	struct tm Save;
X	struct appt_entry appt;
X	int runl;
X
X	lock_cursors();
X	/* destory future appts popup, if it exists */
X	if (fframe) {
X		window_destroy(fframe);
X		fframe = 0;
X	}
X	fix_current_day();
X	Save = current;
X	current.tm_mday = 1;
X	fix_current_day();
X	working(TRUE);
X	start_dow = current.tm_wday;
X	n_days = monthlength(current.tm_mon);
X	
X	pw_batch_on(main_pixwin);
X        rect = (Rect *) window_get(canvas, WIN_RECT);
X	/* Erase the window */
X        pw_writebackground(main_pixwin,0,0,rect->r_width,rect->r_height,PIX_CLR);
X        left_border = (rect->r_width - 7*64)/2 + 32;
X        top_border = (rect->r_height - 5*64) / 2;
X        right_border = left_border + 7*64;
X         
X	sprintf(title, "%s, %d",
X		monthnames[current.tm_mon], 1900 + current.tm_year);
X        pw_text(main_pixwin, (rect->r_width - bigfont->pf_defaultsize.x*strlen(title))/2 + 32, top_border/2 +  7,
X          PIX_SRC, bigfont, title);
X	sun_moon_buttons(FALSE);
X	print_button(TRUE);
X
X	for (i=0; i<31; i++)		/* Which days have appointments? */
X		busy_today[i] = 0;
X	if ((apts = fopen(apts_pathname, "r")) == NULL)
X		err_rpt("can't open appointments file", FATAL);
X	First = current;
X	current.tm_mday = monthlength(current.tm_mon);
X	fix_current_day();
X	Last = current;
X	working(FALSE);
X	while ((read_stat = get_aentry(apts, &appt, FALSE, 1, First.tm_mon+1)) != EOF) {
X		if (read_stat)
X			continue;	/* read error (ignore) */
X		if (appt.flags & A_COMMENT)
X			continue;
X		if ((appt.flags & MARKED_NOTE) == MARKED_NOTE)
X			continue;
X		current.tm_year = appt.year;
X		current.tm_mon = appt.month;
X		current.tm_mday = appt.day;
X		if (appt.flags & ALL_YEARS)
X			current.tm_year = First.tm_year;
X		if (appt.flags & ALL_MONTHS)
X			current.tm_mon = First.tm_mon;
X		if (appt.flags & EVERY_SOMEDAY) {
X			if ((current.tm_mon == First.tm_mon) && (current.tm_year == First.tm_year)) {
X				/* find first occurance of this day this month */
X				current.tm_mday = First.tm_mday;
X				find_date(&appt);
X				if (appt.flags & RUN)
X					runl = appt.runlength;
X				else
X					runl = 1;
X			} else if (appt.flags & RUN) {
X				runl = appt.runlength;
X				find_date(&appt);
X				while (ymd_compare(current, First) < 0 && --runl) {
X					current.tm_mday += 7;
X					find_date(&appt);
X				}
X				if (ymd_compare(current, First) < 0) {
X					/* ran out of runlength */
X					continue;
X				}
X			} else
X				continue;
X			while (ymd_compare(current, Last) <= 0 && runl) {
X				if (chk_week(appt.repeat, current.tm_mday)) {
X					if (runl)
X						busy_today[current.tm_mday-1]++;
X					if (appt.flags & RUN)
X						--runl;
X				}
X				current.tm_mday += 7;
X				fix_current_day();
X			}
X		} else if ((appt.flags & REPEAT) && !(appt.flags & ALL_DAYS)
X		    && !(appt.flags & EVERY_MON_FRI)) {
X			if (appt.flags & EVERY_SOMEDAY)
X				continue;
X			if (appt.flags & RUN)
X				runl = appt.runlength;
X			else
X				runl = 1;
X			while (ymd_compare(current, First) < 0 && runl) {
X				if (appt.flags & RUN)
X					--runl;
X				if (runl) {
X					current.tm_mday += appt.repeat;
X					fix_current_day();
X				}
X			}
X			while (ymd_compare(current, Last) <= 0 && runl) {
X				if (runl) {
X					busy_today[current.tm_mday-1]++;
X					current.tm_mday += appt.repeat;
X					fix_current_day();
X					if (appt.flags & RUN)
X						--runl;
X				}
X			}
X		} else if (current.tm_year == First.tm_year 
X			&& current.tm_mon == First.tm_mon) {
X			if (appt.flags & ALL_DAYS)
X				for (i=0; i<monthlength(First.tm_mon); i++)
X					busy_today[i]++;
X			else if (appt.flags & EVERY_MON_FRI)
X				for (i=0,j=First.tm_wday; i<monthlength(First.tm_mon); i++,j++) {
X					if (j > SAT)
X						j = SUN;
X					else if (j >= MON && j <= FRI)
X						busy_today[i]++;
X				}
X			else if (appt.flags & DELETED)
X				busy_today[appt.day-1]--;
X			else
X				busy_today[appt.day-1]++;
X		}
X				
X	}
X	fclose(apts);
X	current = First;
X	fix_current_day();
X#ifndef NO_HOLIDAYS
X	/*
X	 * now that we've gone thru the appointments file,
X	 * check to see if the user has selected any holiday
X	 * options and add them in.
X	 */
X	for (i=0; i<monthlength(First.tm_mon); i++) {
X		working(TRUE);
X		if (holiday_a == 1) {
X			j = a_dates(holiday_a);
X			for (k=0; k<j; k++)
X				if (ymd2_compare(&current, &a_appts[k]) == 0)
X					busy_today[i]++;
X		}
X		if (holiday_c == 1) {
X			j = c_dates(holiday_c);
X			for (k=0; k<j; k++)
X				if (ymd2_compare(&current, &c_appts[k]) == 0)
X					busy_today[i]++;
X		}
X		working(FALSE);
X		if (holiday_i == 1) {
X			j = i_dates(holiday_i);
X			for (k=0; k<j; k++)
X				if (ymd2_compare(&current, &i_appts[k]) == 0)
X					busy_today[i]++;
X		}
X		working(TRUE);
X		if (holiday_j == 1) {
X			j = j_dates(holiday_j);
X			for (k=0; k<j; k++)
X				if (ymd2_compare(&current, &j_appts[k]) == 0)
X					busy_today[i]++;
X		}
X		if (holiday_s == 1) {
X			j = s_dates(holiday_s);
X			for (k=0; k<j; k++)
X				if (ymd2_compare(&current, &s_appts[k]) == 0)
X					busy_today[i]++;
X		}
X		current.tm_mday++;
X		working(FALSE);
X	}
X	current = First;
X	fix_current_day();
X#endif
X
X	y = top_border;				/* Draw all day boxes. */
X	if (monday_first) {
X		if (start_dow == SUN) {
X			x = 64*6 + left_border;
X			days_in_week = 6;
X		} else {
X			x = 64*(start_dow - 1) + left_border;
X			days_in_week = start_dow -1 ;
X		}
X	} else {
X		x = 64*start_dow + left_border;
X		days_in_week = start_dow;
X	}
X        c[0] = ' ';
X        c[1] = '1';
X        c[2] = ' ';
X        c[3] = '\0';
X        for (i=0; i<n_days; i++){
X		if (ymd_compare(today, current) == 0)
X			/* gray box */
X			pw_write(main_pixwin,x,y,64,64,PIX_SRC,daybox_td_pr,0,0);
X		else
X			pw_write(main_pixwin,x,y,64,64,PIX_SRC,daybox_pr,0,0);
X		if (busy_today[i] > 0)
X			pw_write(main_pixwin, x+46, y+2, 16, 16,
X			  PIX_SRC|PIX_DST, triangle_pr, 0, 0);
X                boxlims[i].lowx = x;
X                boxlims[i].lowy = y;
X                boxlims[i].highx = x + 63;
X                boxlims[i].highy = y + 63;
X		pw_text(main_pixwin,x+6,y+21,PIX_SRC|PIX_DST,bigfont,c);
X                days_in_week++;
X		current.tm_mday++;
X                if (days_in_week == 7){
X                        days_in_week = 0;
X                        x = left_border;
X                        y += 64;
X                }
X		else
X                        x += 64;
X                if (c[1] != '9')
X                        c[1]++;
X                else {
X                        c[1] = '0';
X                        if (c[0] == ' ')
X                                c[0] = '1';
X                        else
X                                c[0]++;
X                }
X        }
X        x = left_border + 27;
X        y = top_border - 16;
X	if (monday_first) {
X		for (i=1; i<7; i++) {		/* Mon ... Sat Sun */
X			pw_char(main_pixwin,x,y,PIX_SRC,bigfont,daynames[i][0]);
X			x += 64;
X		}
X		pw_char(main_pixwin,x,y,PIX_SRC,bigfont,daynames[0][0]);
X	} else {
X		for (i=0; i<7; i++) {		/* Sun Mon ... Sat */
X			pw_char(main_pixwin,x,y,PIX_SRC,bigfont,daynames[i][0]);
X			x += 64;
X		}
X        }
X
X	bottom_border = boxlims[n_days-1].highy;
X
X        /* Draw the "week arrows" */
X        arrow_index = 0;
X        last_top = -1;
X
X	current = First;
X        for (i=0; i<n_days; i++)
X                if (boxlims[i].lowy > last_top) {
X                        last_top = boxlims[i].lowy;
X                        week_arrows[arrow_index].active = 1;
X                        week_arrows[arrow_index].left = left_border - 64;
X                        week_arrows[arrow_index].top = last_top + 12;
X                        week_arrows[arrow_index].right =
X                          week_arrows[arrow_index].left + 43;
X                        week_arrows[arrow_index].bottom =
X                          week_arrows[arrow_index].top + 28;
X                        pw_write(main_pixwin, left_border-64, last_top + 12,
X                          43, 29, PIX_SRC, weekarrow_pr, 0, 0);
X
X			/*  Week numbers  */
X			sprintf(c, "%2d", week_number());
X			pw_text(main_pixwin, left_border-54, last_top+32, 
X				PIX_SRC, font, c);
X			current.tm_mday += 7;
X			fix_current_day();
X
X                        arrow_index++;
X                }
X	pw_batch_off(main_pixwin);
X	current = Save;
X	unlock_cursors();
X}
END_OF_FILE
if test 9590 -ne `wc -c <'mpaint.c'`; then
    echo shar: \"'mpaint.c'\" unpacked with wrong size!
fi
# end of 'mpaint.c'
fi
echo shar: End of archive 15 \(of 23\).
cp /dev/null ark15isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 23 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

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.