home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume16
/
lumberjack
/
ljack.c
next >
Wrap
C/C++ Source or Header
|
1988-11-14
|
6KB
|
305 lines
#include <stdio.h>
#include <values.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/time.h>
#include <suntool/sunview.h>
#include <suntool/frame.h>
#include <suntool/textsw.h>
#include <sunwindow/notify.h>
/*
* SunView size definitions. I shouldn't have to define these, but
* there is no way to query SunView for them.
*/
#define LMARGIN 5 /* left frame margin */
#define RMARGIN 5 /* right frame margin */
#define BMARGIN 5 /* bottom frame margin */
#define SMARGIN 5 /* subwindow spacing */
Frame frame;
int files, updating = 0;
Textsw text[16]; /* text subwindows */
Menu menu[16]; /* menus for each subwindow */
char *file[16]; /* filenames */
off_t length[16]; /* file lengths */
char alert[16]; /* flags: blink icon on update? */
/*
* Construct the icons.
* None.icon is displayed when there are no new files; otherwise,
* new1.icon and new2.icon are toggled once a second.
*/
static short none_icon_i[] = {
#include "none.icon"
};
mpr_static(none_icon_p, 64, 64, 1, none_icon_i);
static short new1_icon_i[] = {
#include "new1.icon"
};
mpr_static(new1_icon_p, 64, 64, 1, new1_icon_i);
static short new2_icon_i[] = {
#include "new2.icon"
};
mpr_static(new2_icon_p, 64, 64, 1, new2_icon_i);
Icon ikes[3];
int inum = 1;
int newstuff;
main(argc, argv)
char **argv;
{
ikes[0] = icon_create(ICON_IMAGE, &none_icon_p, 0);
ikes[1] = icon_create(ICON_IMAGE, &new1_icon_p, 0);
ikes[2] = icon_create(ICON_IMAGE, &new2_icon_p, 0);
frame = window_create(NULL, FRAME,
FRAME_LABEL, "LUMBERJACK 1.0 by Steven Grimm (koreth@ssyx.ucsc.edu)",
FRAME_ARGC_PTR_ARGV, &argc, argv,
FRAME_SUBWINDOWS_ADJUSTABLE, FALSE,
FRAME_ICON, ikes[0],
WIN_ERROR_MSG, "Couldn't open window",
0);
parse_args(argc, argv);
create_subwindows();
set_window_sizes();
load_files();
newstuff = 0;
window_set(frame, FRAME_ICON, ikes[0], 0);
set_notifier();
window_main_loop(frame);
}
/*
* Create all the necessary subwindows.
*/
create_subwindows()
{
int i, domenu();
for (i=0; i<files; i++)
{
menu[i] = menu_create(MENU_TITLE_ITEM, file[i],
MENU_ACTION_ITEM, "Close", domenu,
0);
text[i] = window_create(frame, TEXTSW,
WIN_ERROR_MSG, "Couldn't create subwindow",
WIN_IGNORE_PICK_EVENT, WIN_RESIZE,
TEXTSW_DISABLE_CD, TRUE,
TEXTSW_DISABLE_LOAD, TRUE,
TEXTSW_INSERT_MAKES_VISIBLE, TEXTSW_ALWAYS,
TEXTSW_IGNORE_LIMIT, TEXTSW_INFINITY,
TEXTSW_MENU, menu[i],
0);
}
}
/*
* Set all the window sizes. This gets called whenever the base
* frame gets resized, and once at initialization.
*
* For now, all the subwindows are assumed to be of equal size.
*/
set_window_sizes()
{
int i, fr_height, fr_width, ts_height, ts_width;
fr_height = (int)window_get(frame, WIN_HEIGHT) -
(int)window_get(frame, WIN_TOP_MARGIN);
fr_width = (int)window_get(frame, WIN_WIDTH) -
LMARGIN - RMARGIN;
ts_height = fr_height/files - SMARGIN;
ts_width = fr_width;
for (i=0; i<files; i++)
{
window_set(text[i],
WIN_HEIGHT, ts_height,
WIN_WIDTH, ts_width,
0);
if (i)
window_set(text[i], WIN_BELOW, text[i-1], 0);
}
}
/*
* Parse command line arguments.
* For now, this is just a list of filenames.
*/
parse_args(c, v)
char **v;
{
int i, nflag = 0;
files = 0;
for (i=1; i<c; i++)
{
if (! strcmp(v[i], "-n"))
nflag = 1;
else if (access(v[i], R_OK) == 0)
{
file[files] = v[i];
length[files] = MAXINT;
alert[files] = !nflag;
nflag = 0;
if (++files == 16)
break;
}
else
perror(v[i]);
}
if (! files)
exit(1);
}
/*
* Load all the files into their windows, and place the cursors at the
* infinity position. This gets called once every second.
*/
load_files()
{
int i;
struct stat st;
for (i=0; i<files; i++)
{
if (stat(file[i], &st) < 0 || access(file[i], R_OK))
{
kill_file(i);
continue;
}
if (st.st_size == length[i])
continue;
if (st.st_size < length[i]) /* file has gotten smaller */
window_set(text[i], TEXTSW_FILE, file[i], 0);
else if (st.st_size > length[i])
{
char *buf;
int fd, bsiz;
buf = (char *)malloc(bsiz = (st.st_size - length[i]));
fd = open(file[i], O_RDONLY);
if (fd < 0)
{
filerror:
free(buf);
kill_file(i);
}
if (lseek(fd, length[i], L_SET) < 0)
goto filerror;
if (read(fd, buf, bsiz) < 0)
goto filerror;
window_set(text[i],
TEXTSW_INSERTION_POINT, TEXTSW_INFINITY,
0);
textsw_insert(text[i], buf, bsiz);
textsw_possibly_normalize(text[i], (Textsw_index)length[i]);
free(buf);
}
length[i] = st.st_size;
if (alert[i])
newstuff++;
}
if (newstuff)
if ((int)window_get(frame, FRAME_CLOSED))
{
inum ^= 3;
window_set(frame, FRAME_ICON, ikes[inum], 0);
}
else
{
newstuff = 0;
window_set(frame, FRAME_ICON, ikes[0], 0);
}
}
/*
* Handle events.
*/
Notify_value
event(window, event, arg, type)
Window window;
Event *event;
Notify_arg arg;
Notify_event_type type;
{
Notify_value value;
value = notify_next_event_func(window, event, arg, type);
if (event_id(event) == WIN_RESIZE)
set_window_sizes();
return(value);
}
/*
* Handle a menu selection.
*/
domenu(m, mi)
Menu m;
Menu_item mi;
{
int win;
for (win = 0; win < files; win++)
if (menu[win] == m)
break;
if (win == files)
return;
if ((int)menu_get(m, MENU_SELECTED) == 2)
kill_file(win);
}
/*
* Kill a file, either because we got an error reading it or because
* the user said so.
*/
kill_file(num)
int num;
{
int i;
menu_destroy(menu[num]);
window_destroy(text[num]);
if (num != files-1)
{
for (i = num+1; i < files; i++)
{
menu[i-1] = menu[i];
text[i-1] = text[i];
file[i-1] = file[i];
length[i-1] = length[i];
alert[i-1] = alert[i];
}
}
if (num == 0)
window_set(text[0], WIN_Y, 0, 0);
if (--files == 0)
exit(0);
set_window_sizes();
}
/*
* Set up a timer. It checks all the files once a second.
* Also, tell the notifier what to do about resizes and so forth.
*/
set_notifier()
{
static struct itimerval timer; /* this is our handle */
bzero(&timer, sizeof(timer));
timer.it_interval.tv_sec = 1;
timer.it_value.tv_sec = 1;
notify_set_itimer_func(&timer, load_files, ITIMER_REAL, &timer, NULL);
notify_interpose_event_func(frame, event, NOTIFY_SAFE);
}