[comp.sources.sun] v01i051: Lpqtool - a printer watcher for sunview

mcgrew@dartagnan.rutgers.edu (Charles Mcgrew) (07/21/89)

Submitted-by: chuck@trantor.harris-atd.com (Chuck Musciano)
Posting-number: Volume 1, Issue 51
Archive-name: lpqtool

     Lpqtool provides a convenient way to monitor the printer queue from
your desktop.  It will automatically track your jobs, and open and close
as the jobs enter and exit the queue.

Chuck Musciano			ARPA  : chuck@trantor.harris-atd.com
Harris Corporation 		Usenet: ...!uunet!x102a!trantor!chuck
PO Box 37, MS 3A/1912		AT&T  : (407) 727-6131
Melbourne, FL 32902		FAX   : (407) 727-{5118,5227,4004}

#! /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 shell archive."
# Contents:  Makefile lpqtool.c laserwriter.icon misc.c README
#   lpqtool.man
# Wrapped by chuck@melmac on Mon Oct 10 08:02:50 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(416 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# where you keep local executables
XBINDIR		= /usr/local/bin
X
X# man directory for local man pages (usually /usr/man/manl)
XMANDIR		= /usr/man/manl
XMANEXT		= l
X
XOFILES   = lpqtool.o misc.o
X
XWINDOW_LIB	= -lsuntool -lsunwindow -lpixrect
X
X.c.o:
X	cc -c $<
X
Xlpqtool: $(OFILES)
X	cc -o lpqtool $(OFILES) $(WINDOW_LIB)
X
Xinstall: lpqtool
X	cp lpqtool $(BINDIR)
X	cp lpqtool.man $(MANDIR)/lpqtool.$(MANEXT)
X
Xclean:
X	rm *.o core 
X
X
END_OF_FILE
if test 416 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'lpqtool.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'lpqtool.c'\"
else
echo shar: Extracting \"'lpqtool.c'\" \(13641 characters\)
sed "s/^X//" >'lpqtool.c' <<'END_OF_FILE'
X/************************************************************************/
X/*	Copyright 1988 by Chuck Musciano and Harris Corporation		*/
X/*									*/
X/*	Permission to use, copy, modify, and distribute this software	*/
X/*	and its documentation for any purpose and without fee is	*/
X/*	hereby granted, provided that the above copyright notice	*/
X/*	appear in all copies and that both that copyright notice and	*/
X/*	this permission notice appear in supporting documentation, and	*/
X/*	that the name of Chuck Musciano and Harris Corporation not be	*/
X/*	used in advertising or publicity pertaining to distribution	*/
X/*	of the software without specific, written prior permission.	*/
X/*	Chuck Musciano and Harris Corporation make no representations	*/
X/*	about the suitability of this software for any purpose.  It is	*/
X/*	provided "as is" without express or implied warranty.		*/
X/************************************************************************/
X
X
X#include	<suntool/sunview.h>
X#include	<suntool/panel.h>
X#include	<suntool/canvas.h>
X
X#include	<stdio.h>
X
X#define		LPQ			"/usr/ucb/lpq"
X
X#define		ICON_PATH		"laserwriter.icon"
X
X#define		NORMAL_FONT		"/usr/lib/fonts/fixedwidthfonts/screen.r.14"
X#define		BOLD_FONT		"/usr/lib/fonts/fixedwidthfonts/screen.b.14"
X
X#define		NO_STATE		0
X#define		IDLE_STATE		1
X#define		ACTIVE_STATE		2
X#define		CHECK_STATE		3
X
Xstatic	char	*lp_usage = "usage: lpqtool [-a <interval>] [-c] [-i <interval>] [-o] [-r <rows>] [-t <idle threshold>] [ <printer> ]\n";
X
Xstatic	short	lp_icon_image[] = {
X#include	ICON_PATH
X};
Xmpr_static(lp_icon_pixrect, 64, 30, 1, lp_icon_image);
X
Xstruct	itimerval	active	= {{10, 0}, {10, 0}};
Xstruct	itimerval	idle	= {{60, 0}, {60, 0}};
Xint	active_open		= FALSE;
Xint	idle_closed		= FALSE;
Xint	idle_threshold		= 6;
Xint	queue_rows		= 5;
Xint	idle_count, stay_idle;
Xint	state			= NO_STATE;
Xchar	user[30];
Xchar	*printer_name;
X
XIcon	icon;
XFrame	frame;
XCanvas	status, queue;
XPanel	panel;
XPixwin	*spw, *qpw;
Xstruct	pixfont	*normal_font, *bold_font;
XPanel_item	a_item, i_item, a_light, i_light, c_light, a_button, i_button, c_button;
X
X/************************************************************************/
Xstatic	char	*right_str(val, width)
X
Xint	val;
Xint	width;
X
X{	static	char	buf[20];
X
X	sprintf(buf, "%*d", width, val);
X	return(buf);
X}
X
X/************************************************************************/
Xstatic	set_status(st)
X
Xint	st;
X
X{
X	panel_set(a_light, PANEL_SHOW_ITEM, FALSE, 0);
X	panel_set(i_light, PANEL_SHOW_ITEM, FALSE, 0);
X	panel_set(c_light, PANEL_SHOW_ITEM, FALSE, 0);
X	if (st == IDLE_STATE)
X	   panel_set(i_light, PANEL_SHOW_ITEM, TRUE, 0);
X	else if (st == ACTIVE_STATE)
X	   panel_set(a_light, PANEL_SHOW_ITEM, TRUE, 0);
X	else if (st == CHECK_STATE)
X	   panel_set(c_light, PANEL_SHOW_ITEM, TRUE, 0);
X}
X/************************************************************************/
Xstatic	update_queue()
X
X{	FILE	*f;
X	char	buf[256];
X	int	line = 2, new_state = NO_STATE;
X
X	set_status(CHECK_STATE);
X	sprintf(buf, "%s%s%s", LPQ, *printer_name? " -P" : "", printer_name);
X	if ((f = popen(buf, "r")) == NULL) {
X	   pw_output(spw, 2, 5, TRUE, "Unable to obtain queue information");
X	   pw_rop(qpw, 0, 0, window_get(queue, WIN_WIDTH), window_get(queue, WIN_HEIGHT), PIX_SRC | PIX_COLOR(0), NULL, 0, 0);
X	   pclose(f);
X	   return;
X	   }
X	if (fgets(buf, 256, f) != NULL) {
X	   buf[strlen(buf) - 1] = '\0';
X	   pw_output(spw, 1, 1, TRUE, "Status:");
X	   pw_output(spw, 2, 5, TRUE, buf);
X	   pw_rop(qpw, 0, 0, window_get(queue, WIN_WIDTH), window_get(queue, WIN_HEIGHT), PIX_SRC | PIX_COLOR(0), NULL, 0, 0);
X	   if (strcmp(buf, "no entries") == 0)
X	      new_state = IDLE_STATE;
X	   else
X	      new_state = ACTIVE_STATE;
X	   }
X	while (fgets(buf, 256, f) != NULL) {
X	   buf[strlen(buf) - 1] = '\0';
X	   if (strncmp(buf, "Rank", 4) == 0) {
X	      if (new_state == IDLE_STATE)
X	         new_state = ACTIVE_STATE;
X	      continue;
X	      }
X	   else if (verify(buf, " \t\n\r"))
X	      continue;
X	   else {
X	      if (line == 2)
X	         pw_output(qpw, 1, 1, TRUE, "Rank   Owner      Job  Files                                 Total Size");
X	      pw_output(qpw, line++, 1, strindex(buf, user), buf);
X	      }
X	   }
X	pclose(f);
X	if (new_state == IDLE_STATE) {
X	   stay_idle = FALSE;
X	   if (state == ACTIVE_STATE && --idle_count <= 0)
X	      go_idle();
X	   }
X	else if (new_state == ACTIVE_STATE && !stay_idle)
X	   go_active();
X	set_status(state);
X}
X
X/************************************************************************/
Xstatic	Panel_setting	number_proc(item, event)
X
XPanel_item	item;
XEvent		*event;
X
X{	char	buf[80];
X	int	val;
X
X	strcpy(buf, panel_get_value(item));
X	val = atoi(buf);
X	if (event_id(event) >= '1' && event_id(event) <= '9') {
X	   val = val * 10 + event_id(event) - '0';
X	   panel_set(item, PANEL_VALUE, right_str(val, 5), 0);
X	   return(PANEL_NONE);
X	   }
X	else if (event_id(event) == '0')
X	   if (item == a_item && val == 0)
X	      return(PANEL_NONE);
X	   else {
X	      val = val * 10 + event_id(event) - '0';
X	      panel_set(item, PANEL_VALUE, right_str(val, 5), 0);
X	      return(PANEL_NONE);
X	      }
X	else if (event_id(event) == '\010') {
X	   val /= 10;
X	   panel_set(item, PANEL_VALUE, right_str(val, 5), 0);
X	   return(PANEL_NONE);
X	   }
X	else if (event_id(event) == '\177') {
X	   panel_set(item, PANEL_VALUE, "     ", 0);
X	   return(PANEL_NONE);
X	   }
X	else if (event_id(event) == '\n' || event_id(event) == '\r') {
X	   if (item == a_item) {
X	      active.it_value.tv_sec = active.it_interval.tv_sec = val;
X	      if (state == ACTIVE_STATE)
X	         notify_set_itimer_func(frame, update_queue, ITIMER_REAL, &active, NULL);
X	      }
X	   else {
X	      idle.it_value.tv_sec = idle.it_interval.tv_sec = val;
X	      if (state == IDLE_STATE)
X	         notify_set_itimer_func(frame, update_queue, ITIMER_REAL, &idle, NULL);
X	      }
X	   return(PANEL_NONE);
X	   }
X	else
X	   return(PANEL_NONE);
X}
X	
X/************************************************************************/
Xstatic	go_idle()
X
X{
X	if (state == IDLE_STATE)
X	   return;
X	state = IDLE_STATE;
X	if (idle_closed)
X	   window_set(frame, FRAME_CLOSED, TRUE, 0);
X	if (idle.it_value.tv_sec != 0)
X	   notify_set_itimer_func(frame, update_queue, ITIMER_REAL, &idle, NULL);
X	else
X	   notify_set_itimer_func(frame, update_queue, ITIMER_REAL, NULL, NULL);
X	set_status(IDLE_STATE);
X}
X
X/************************************************************************/
Xstatic	go_active()
X
X{
X	idle_count = idle_threshold;
X	if (state == ACTIVE_STATE)
X	   return;
X	state = ACTIVE_STATE;
X	if (active_open)
X	   window_set(frame, FRAME_CLOSED, FALSE, 0);
X	update_queue();
X	notify_set_itimer_func(frame, update_queue, ITIMER_REAL, &active, NULL);
X	set_status(ACTIVE_STATE);
X}
X
X/************************************************************************/
Xstatic	pw_output(pw, row, col, bold, str)
X
XPixwin	*pw;
Xint	row;
Xint	col;
Xint	bold;
Xchar	*str;
X
X{
X	row = (row - 1) * normal_font->pf_defaultsize.y;
X	col = (col - 1) * normal_font->pf_defaultsize.x + 4;
X	pw_text(pw, col, row - normal_font->pf_char['0'].pc_home.y, PIX_SRC, normal_font, str);
X	if (bold)
X	   pw_text(pw, col + 1, row - normal_font->pf_char['0'].pc_home.y, PIX_SRC | PIX_DST, normal_font, str);
X	col += strlen(str) * normal_font->pf_defaultsize.x;
X	pw_rop(pw, col, row, pw->pw_pixrect->pr_size.x - col, normal_font->pf_defaultsize.y, PIX_SRC | PIX_COLOR(0), NULL, 0, 0);
X}
X
X/************************************************************************/
Xstatic	Notify_value	close_proc(frame, event, arg, type)
X
XFrame	frame;
XEvent	*event;
XNotify_arg	arg;
XNotify_event_type	type;
X
X{	int	init_closed, curr_closed, is_resize;
X	Notify_value	value;
X	Rect	*temp;
X
X	init_closed = (int) window_get(frame, FRAME_CLOSED);
X	value = notify_next_event_func(frame, event, arg, type);
X	curr_closed = (int) window_get(frame, FRAME_CLOSED);
X	if (init_closed != curr_closed)
X	   if (curr_closed) {
X	      stay_idle = (state == ACTIVE_STATE);
X	      go_idle();
X	      }
X	   else
X	      go_active();
X	return(value);
X}
X
X/************************************************************************/
Xmain(argc, argv)
X
Xint	argc;
Xchar	**argv;
X
X{	char	c, *s, **saveargs();
X	int	i, interval = 10;
X	Rect	*r;
X
X	normal_font = pf_open(NORMAL_FONT);
X	bold_font = pf_open(BOLD_FONT);
X	icon = icon_create(ICON_IMAGE, &lp_icon_pixrect, 
X			   ICON_LABEL, NULL, 
X			   ICON_WIDTH, lp_icon_pixrect.pr_size.x, 
X			   ICON_HEIGHT, lp_icon_pixrect.pr_size.y,
X			   0);
X	frame = window_create(NULL, FRAME,
X				 FRAME_ICON, icon,
X				 FRAME_LABEL, "<< LaserWriter Queue Status >>",
X			         FRAME_ARGC_PTR_ARGV, &argc, argv,
X			      0);
X
X	argv = saveargs(argc, argv);
X	while ((c = getopt(&argc, argv, "a:ci:or:t:", &s)) != EOF)
X	   switch (c) {
X	      case 'a' : if (verify(s, "0123456789")) {
X	      		    active.it_value.tv_sec = active.it_interval.tv_sec = atoi(s);
X	      		    if (active.it_value.tv_sec <= 0)
X	      		       abend("invalid active interval: %s\n", s);
X	      		    }
X	      		 else
X	      		    abend("invalid active interval: %s\n", s);
X	      		 break;
X	      case 'c' : idle_closed = TRUE;
X	      		 break;
X	      case 'i' : if (verify(s, "0123456789")) {
X	      		    idle.it_value.tv_sec = idle.it_interval.tv_sec = atoi(s);
X	      		    if (idle.it_value.tv_sec < 0)
X	      		       abend("invalid idle interval: %s\n", s);
X	      		    }
X	      		 else
X	      		    abend("invalid idle interval: %s\n", s);
X	      		 break;
X	      case 'o' : active_open = TRUE;
X	      		 break;
X	      case 'r' : if (verify(s, "0123456789")) {
X	      		    queue_rows = atoi(s);
X	      		    if (queue_rows <= 0)
X	      		       abend("invalid number of queue lines: %s\n", s);
X	      		    }
X	      		 else
X	      		    abend("invalid number of queue lines: %s\n", s);
X	      		 break;
X	      case 't' : if (verify(s, "0123456789")) {
X	      		    idle_threshold = atoi(s);
X	      		    if (idle_threshold <= 0)
X	      		       abend("invalid idle thresold: %s\n", s);
X	      		    }
X	      		 else
X	      		    abend("invalid idle threshold: %s\n", s);
X	      		 break;
X	      case '?' : fprintf(stderr, lp_usage);
X	      		 break;
X	      default  : abend(lp_usage);
X	      		 break;
X	      }
X
X	panel = window_create(frame, PANEL,
X				 PANEL_FONT, normal_font,
X				 WIN_COLUMNS, 75,
X			      0);
X	a_item = panel_create_item(panel, PANEL_TEXT, 
X				      PANEL_LABEL_STRING, "Active Interval:",
X				      PANEL_LABEL_BOLD, TRUE,
X				      PANEL_ITEM_Y, ATTR_ROW(0) + 1,
X				      PANEL_VALUE_DISPLAY_LENGTH, 5,
X				      PANEL_VALUE, right_str(active.it_value.tv_sec, 5),
X				      PANEL_NOTIFY_PROC, number_proc,
X				      PANEL_NOTIFY_LEVEL, PANEL_ALL,
X				   0);
X	a_light = panel_create_item(panel, PANEL_MESSAGE,
X				       PANEL_LABEL_STRING, "Active",
X				       PANEL_LABEL_BOLD, TRUE,
X				    0);
X	i_light = panel_create_item(panel, PANEL_MESSAGE,
X				       PANEL_LABEL_STRING, "Idle",
X				       PANEL_LABEL_BOLD, TRUE,
X				    0);
X	c_light = panel_create_item(panel, PANEL_MESSAGE,
X				       PANEL_LABEL_STRING, "Checking",
X				       PANEL_LABEL_BOLD, TRUE,
X				    0);
X	i_item = panel_create_item(panel, PANEL_TEXT, 
X				      PANEL_LABEL_STRING, "Idle Interval:  ",
X				      PANEL_LABEL_BOLD, TRUE,
X				      PANEL_VALUE_DISPLAY_LENGTH, 5,
X				      PANEL_ITEM_X, ATTR_COL(0), 
X				      PANEL_ITEM_Y, ATTR_ROW(1) + 4,
X				      PANEL_VALUE, right_str(idle.it_value.tv_sec, 5),
X				      PANEL_NOTIFY_PROC, number_proc,
X				      PANEL_NOTIFY_LEVEL, PANEL_ALL,
X				   0);
X	a_button = panel_create_item(panel, PANEL_BUTTON,
X					PANEL_ITEM_Y, ATTR_ROW(1),
X					PANEL_ITEM_X, ATTR_COL(26),
X					PANEL_LABEL_IMAGE, better_button_image(panel, "Go Active", 12, 5, bold_font),
X					PANEL_NOTIFY_PROC, go_active,
X				     0);
X	i_button = panel_create_item(panel, PANEL_BUTTON,
X					PANEL_ITEM_Y, ATTR_ROW(1),
X					PANEL_LABEL_IMAGE, better_button_image(panel, "Go Idle", 12, 5, bold_font),
X					PANEL_NOTIFY_PROC, go_idle,
X				     0);
X	c_button = panel_create_item(panel, PANEL_BUTTON,
X					PANEL_ITEM_Y, ATTR_ROW(1),
X					PANEL_LABEL_IMAGE, better_button_image(panel, "Check Queue", 12, 5, bold_font),
X					PANEL_NOTIFY_PROC, update_queue,
X				     0);
X	r = (Rect *) panel_get(a_button, PANEL_ITEM_RECT);
X	i = r->r_left + r->r_width / 2;
X	r = (Rect *) panel_get(a_light, PANEL_ITEM_RECT);
X	panel_set(a_light, PANEL_ITEM_X, i - r->r_width / 2, 0);
X	r = (Rect *) panel_get(i_button, PANEL_ITEM_RECT);
X	i = r->r_left + r->r_width / 2;
X	r = (Rect *) panel_get(i_light, PANEL_ITEM_RECT);
X	panel_set(i_light, PANEL_ITEM_X, i - r->r_width / 2, 0);
X	r = (Rect *) panel_get(c_button, PANEL_ITEM_RECT);
X	i = r->r_left + r->r_width / 2;
X	r = (Rect *) panel_get(c_light, PANEL_ITEM_RECT);
X	panel_set(c_light, PANEL_ITEM_X, i - r->r_width / 2, 0);
X	window_fit_height(panel);
X
X	status = window_create(frame, CANVAS,
X				  WIN_HEIGHT, normal_font->pf_defaultsize.y * 2,
X				  WIN_WIDTH, normal_font->pf_defaultsize.x * 75,
X				  WIN_X, 0,
X				  WIN_BELOW, panel,
X			       0);
X	spw = canvas_pixwin(status);
X	queue = window_create(frame, CANVAS,
X				 WIN_HEIGHT, normal_font->pf_defaultsize.y * (queue_rows + 1),
X				 WIN_WIDTH, normal_font->pf_defaultsize.x * 75,
X				 WIN_X, 0,
X				 WIN_BELOW, status,
X			      0);
X	qpw = canvas_pixwin(queue);
X	window_set(panel, WIN_WIDTH, window_get(queue, WIN_WIDTH), 0);
X	window_fit(frame);
X
X	if (argc == 1)
X	   printer_name = "";
X	else if (argc == 2)
X	   printer_name = argv[1];
X	else
X	   abend(lp_usage);
X
X	strcpy(user, user_name());
X	set_status(NO_STATE);
X	if (window_get(frame, FRAME_CLOSED))
X	   go_idle();
X	else
X	   go_active();
X	notify_interpose_event_func(frame, close_proc, NOTIFY_SAFE);
X	window_main_loop(frame);
X	pf_close(normal_font);
X	pf_close(bold_font);
X}
END_OF_FILE
if test 13641 -ne `wc -c <'lpqtool.c'`; then
    echo shar: \"'lpqtool.c'\" unpacked with wrong size!
fi
# end of 'lpqtool.c'
fi
if test -f 'laserwriter.icon' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'laserwriter.icon'\"
else
echo shar: Extracting \"'laserwriter.icon'\" \(947 characters\)
sed "s/^X//" >'laserwriter.icon' <<'END_OF_FILE'
X/* Format_version=1, Width=64, Height=30, Depth=1, Valid_bits_per_item=16
X */
X	0x888F,0xFFFF,0xFFFF,0xFFFC,0x2228,0x0000,0x0000,0x0006,
X	0x2228,0x0000,0x0000,0x0006,0x8888,0x0000,0x0000,0x0004,
X	0x8888,0x0000,0x0000,0x0004,0x222F,0xFFFF,0xFFFF,0xFFFE,
X	0x2229,0x0100,0x0000,0x0806,0x8889,0x0100,0x0000,0x0804,
X	0x8889,0x0100,0x0000,0x0804,0x2229,0x3D00,0x0000,0x0806,
X	0x2229,0x2500,0x0F00,0x0806,0x8889,0x3D00,0x0900,0x0804,
X	0x8889,0x3D00,0x0F00,0x0804,0x2229,0x3D00,0x0000,0x0806,
X	0x2229,0x0100,0x0000,0x0806,0x8889,0x0100,0x0000,0x0804,
X	0x8889,0x0100,0x0000,0x0808,0xE22F,0xFFFF,0xFFFF,0xF812,
X	0xFE2F,0x8000,0x0000,0x07E2,0x9FFF,0x8000,0x0000,0x0028,
X	0x8BFF,0x80FF,0xFFFF,0xF028,0x2222,0x8000,0x0000,0x0022,
X	0x2222,0x80FF,0xFFFF,0xF022,0x8888,0x8000,0x0000,0x0028,
X	0x8888,0x80FF,0xFFFF,0xF028,0x2222,0x8000,0x0000,0x0022,
X	0x2222,0x80FF,0xFFFF,0xF022,0x8888,0x8000,0x0000,0x0028,
X	0x8888,0xFFFF,0xFFFF,0xFFE8,0x2222,0x2FA2,0x2222,0x3E22
END_OF_FILE
if test 947 -ne `wc -c <'laserwriter.icon'`; then
    echo shar: \"'laserwriter.icon'\" unpacked with wrong size!
fi
# end of 'laserwriter.icon'
fi
if test -f 'misc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'misc.c'\"
else
echo shar: Extracting \"'misc.c'\" \(4418 characters\)
sed "s/^X//" >'misc.c' <<'END_OF_FILE'
X/************************************************************************/
X/*	Copyright 1988 by Chuck Musciano and Harris Corporation		*/
X/*									*/
X/*	Permission to use, copy, modify, and distribute this software	*/
X/*	and its documentation for any purpose and without fee is	*/
X/*	hereby granted, provided that the above copyright notice	*/
X/*	appear in all copies and that both that copyright notice and	*/
X/*	this permission notice appear in supporting documentation, and	*/
X/*	that the name of Chuck Musciano and Harris Corporation not be	*/
X/*	used in advertising or publicity pertaining to distribution	*/
X/*	of the software without specific, written prior permission.	*/
X/*	Chuck Musciano and Harris Corporation make no representations	*/
X/*	about the suitability of this software for any purpose.  It is	*/
X/*	provided "as is" without express or implied warranty.		*/
X/************************************************************************/
X
X
X/************************************************************************/
X/*	Some miscellaneous support routines				*/
X/************************************************************************/
X
X#include	<stdio.h>
X#include	<pwd.h>
X
X#include	<suntool/sunview.h>
X#include	<suntool/panel.h>
X
Xstatic	short	cross_bits[] = {0x4000, 0xe000, 0x4000};
Xmpr_static(better_button_cross, 3, 3, 1, cross_bits);
X
Xextern	char	*strcpy();
X
Xtext_width(text, font)
X
Xchar	*text;
Xstruct	pixfont	*font;
X
X{	int	width;
X
X	for (width = 0; *text; text++)
X	   width += font->pf_char[*text].pc_adv.x;
X	return(width);
X}
X
Xstruct	pixrect	*better_button_image(panel, text, chars, pixels, font)
X
XPanel	panel;
Xchar	*text;
Xint	chars;
Xint	pixels;
Xstruct	pixfont	*font;
X
X{	struct	pixrect	*pr;
X	struct	pr_prpos	pos;
X	int	width, true_width, height;
X
X	if (font == NULL)
X	   font = (struct pixfont *) window_get(panel, WIN_FONT);
X	width = chars * font->pf_char['0'].pc_adv.x + pixels;
X	true_width = text_width(text, font);
X	if (width < true_width)
X	   width = true_width;
X	pr = mem_create(width + 8, height = font->pf_defaultsize.y + 6, 1);
X	pr_rop(pr, 3, 0, width + 2, 2, PIX_SRC | PIX_COLOR(1), NULL, 0, 0);
X	pr_rop(pr, 3, height - 2, width + 2, 2, PIX_SRC | PIX_COLOR(1), NULL, 0, 0);
X	pr_rop(pr, 0, 3, 2, height - 6, PIX_SRC | PIX_COLOR(1), NULL, 0, 0);
X	pr_rop(pr, width + 6, 3, 2, height - 6, PIX_SRC | PIX_COLOR(1), NULL, 0, 0);
X	pr_rop(pr, 1, 1, 3, 3, PIX_SRC | PIX_DST, &better_button_cross, 0, 0);
X	pr_rop(pr, width + 4, 1, 3, 3, PIX_SRC | PIX_DST, &better_button_cross, 0, 0);
X	pr_rop(pr, width + 4, height - 4, 3, 3, PIX_SRC | PIX_DST, &better_button_cross, 0, 0);
X	pr_rop(pr, 1, height - 4, 3, 3, PIX_SRC | PIX_DST, &better_button_cross, 0, 0);
X	pos.pr = pr;
X	pos.pos.x = 4 + (width - true_width) / 2;
X	pos.pos.y = 4 - font->pf_char['T'].pc_home.y;
X	pf_ttext(pos, PIX_SRC | PIX_COLOR(1), font, text);
X	return(pr);
X}
X
Xchar	*user_name()
X
X{	struct passwd *pp;
X
X	pp = getpwuid(getuid());
X	return(pp? pp->pw_name : NULL);
X}
X
Xabend(s1, s2, s3, s4, s5, s6, s7, s8)
X
Xchar	*s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8;
X
X{
X	fprintf(stderr, s1, s2, s3, s4, s5, s6, s7, s8);
X	exit(1);
X}
X
Xchar	*strindex(source, target)
X
Xchar	*source;
Xchar	*target;
X
X{	register	int	len;
X
X	len = strlen(target);
X	for (; *source; source++)
X	   if (strncmp(source, target, len) == 0)
X	      return(source);
X	return(0);
X}
X
Xverify(source, valid)
X
Xchar	*source;
Xchar	*valid;
X
X{	register	char	*s;
X
X	for ( ; *source; source++) {
X	   for (s = valid; *s && *s != *source; s++)
X	      ;
X	   if (*s == '\0')
X	      return(0);
X	   }
X	return(1);
X}
X
Xchar	**saveargs(argc, argv)
X
Xint	argc;
Xchar	**argv;
X
X{	int	i;
X	char	**copy;
X
X	copy = (char **) malloc((argc + 1) * sizeof(char *));
X	for (i = 0; i < argc; i++)
X	   strcpy(copy[i] = (char *) malloc(strlen(argv[i]) + 1), argv[i]);
X	copy[i] = (char *) 0;
X	return(copy);
X}
X
Xstatic	delarg(argc, argv)
X
Xint	*argc;
Xchar	**argv;
X
X{	char	*p;
X
X	while (*argv = *(argv+1))
X	   argv++;
X	(*argc)--;
X}
X
Xchar	getopt(argc, argv, opts, parm)
X
Xint	*argc;
Xchar	**argv;
Xchar	*opts;
Xchar	**parm;
X
X{	char	c, *p, *index();
X	int	killed;
X
X	*parm = NULL;
X	while (*argv && ((**argv != '-') || (*(*argv+1) == '\0')))
X	   argv++;
X	if (*argv == NULL)
X	   return(EOF);
X	c = *(*argv+1);
X	*++(*argv) = '-';
X	if (killed = (*(*argv+1) == '\0'))
X	   delarg(argc, argv);
X	if ((p = index(opts, c)) == NULL)
X	   c = '\0';
X	else if (*(p+1) == ':') {
X	   *parm = killed ? *argv : *argv+1;
X	   delarg(argc, argv);
X	   }
X	return(c);
X}
END_OF_FILE
if test 4418 -ne `wc -c <'misc.c'`; then
    echo shar: \"'misc.c'\" unpacked with wrong size!
fi
# end of 'misc.c'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(3612 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X/************************************************************************/
X/*	Copyright 1988 by Chuck Musciano and Harris Corporation		*/
X/*									*/
X/*	Permission to use, copy, modify, and distribute this software	*/
X/*	and its documentation for any purpose and without fee is	*/
X/*	hereby granted, provided that the above copyright notice	*/
X/*	appear in all copies and that both that copyright notice and	*/
X/*	this permission notice appear in supporting documentation, and	*/
X/*	that the name of Chuck Musciano and Harris Corporation not be	*/
X/*	used in advertising or publicity pertaining to distribution	*/
X/*	of the software without specific, written prior permission.	*/
X/*	Chuck Musciano and Harris Corporation make no representations	*/
X/*	about the suitability of this software for any purpose.  It is	*/
X/*	provided "as is" without express or implied warranty.		*/
X/************************************************************************/
X
X
X     Lpqtool is a windowed version of lpq.  It will periodically poll the
Xprint queue (using lpq) and display the results in a little window.  You can
Xadjust the polling rate to suit yourself.  Lpqtool has two rates: one for an 
Xactive queue (with jobs in it) and another for an idle (empty) queue.  
XNormally, it polls an active queue more rapidly than an idle queue, to deliver 
Xup to the minute information about the state of the queue.  Lpqtool can also
Xbe configured (via command line options) to close when the queue is idle,
Xand pop open when it becomes active.  This is handy, because you can pop it
Xopen when you submit a job, and it will watch the queue until it becomes
Xempty, and then it will go away.  See the man page for all the details.
X
X     Installing lpqtool is easy.  You'll need to check the Makefile and
Xlpqtool.c to make sure some pathnames and such are correct.  These items
Xare:
X
X	In Makefile:
X		BINDIR		Where the executable will go, normally
X				/usr/local/bin
X		MANDIR		Where the man page will go, normally
X				/usr/man/manl
X		MANEXT		The man page extension, usually 'l',
X				for local man pages.  You may want to
X				make MANDIR /usr/man/man1, in which case
X				MANEXT should be '1'.
X
X	In lpqtool.c
X		LPQ		The full pathname of the lpq command on
X				your system.  Normally, this is
X				/usr/ucb/lpq.  You may have it in a 
X				different place, or might use a different
X				queue display command.  Be warned: lpqtool
X				depends on the format of the output of lpq,
X				so other commands may not work right.
X		ICON_PATH	Where the laserwriter icon can be found.
X				Normally, it is in the directory that you
X				created lpqtool in, but you might want to move
X				it to a more global place.  We keep all our
X				icons in /usr/local/images, for example.
X				Fix this path to match where you put the icon.
X		NORMAL_FONT
X		BOLD_FONT	Point to the fonts used by lpqtool, which should
X				be in the standard Sun font place,
X				/usr/lib/fonts/fixedwidthfonts.  If you have moved
X				them, fix up these paths.  You should always use
X				screen.r.14 and screen.b.14, since lpqtool depends
X				on the font widths to make its windows look good.
X
XEverything else is system independent.  Just type "make lpqtool" or "make install"
Xand give it a whirl!
X
X     Comments, bugs, to me, please.  I would be very interested in your impressions
Xof lpqtool and any suggestions you might have to make it better.  By the way,
Xthere are a few convenient untility routines in misc.c you might find useful in
Xother programs you are writing.
X
XChuck Musciano
XAdvanced Technology Department
XHarris Corporation
X(407) 727-6131
XARPA: chuck@trantor.harris-atd.com
END_OF_FILE
if test 3612 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'lpqtool.man' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'lpqtool.man'\"
else
echo shar: Extracting \"'lpqtool.man'\" \(3225 characters\)
sed "s/^X//" >'lpqtool.man' <<'END_OF_FILE'
X.TH LPQTOOL 1 "29 April 1987"
X.SH NAME
Xlpqtool \- monitor the LaserWriter queue
X.SH SYNOPSIS
X\fBlpqtool\fP [ \fIoptions\fP ] [ \fIprinter\fP ]
X.SH DESCRIPTION
X.LP
X\fILpqtool\fP is a window-based tool that allows the user to monitor a
Xprint queue.  The tool periodically uses the \fIlpq\fP(1)
Xcommand to inspect the state of the queue, and displays that information
Xin a window.  Jobs associated with the invoking user are shown in boldface.
XIf a \fIprinter\fP is specified, \fIlpqtool\fP will monitor that printer.
XOtherwise, the default printer, as determined by \fIlpq\fP, is used.
X.LP
X\fILpqtool\fP switches between the \fIactive\fP and the \fIidle\fP modes
Xwhile watching the queue.  In active mode, the queue is inspected more
Xfrequently, as determined by the \fB-a\fP option, below.  During idle mode,
Xthe queue is inspected less frequently, as determined by the \fB-i\fP
Xoption, below.  If the queue is found to be empty a certain number of
Xsuccessive times while in active mode (see \fB-t\fP), \fIlpqtool\fP
Xswitches into idle mode.  Conversely, if the queue is found to be not empty while in 
Xidle mode, \fIlpqtool\fP switches to active mode.
X.LP
XIn addition to this, \fIlpqtool\fP can be made to automatically open itself
Xwhen the queue becomes active, and to automatically close itself when the
Xqueue is empty.  Finally, the user can control the size of the displayed 
Xqueue.
X.LP
X\fILpqtool\fP provides three buttons when it is open, which allow the user 
Xto force it into either mode, and to force an inspection of the queue. 
XThere are also type-in areas where the user can change the active and idle
Xpolling intervals.
X.SH OPTIONS
X\fILpqtool\fP runs only under SunWindows, and honors all of the window
Xcommand line options.  The various options that control \fIlpqtool\fP are:
X.IP "\fB\-a\fP \fIinterval\fP" 14
XThis option determines the time, in seconds, between inspections of the
Xqueue while in active mode.  The default value is 10 seconds.
X.IP "\fB\-c\fP" 14
XThis option causes \fIlpqtool\fP to automatically close when in idle mode.
X.IP "\fB\-i\fP \fIinterval\fP" 14
XThis option determines the time, in seconds, between inspections of the
Xqueue while in idle mode.  The default value is 60 seconds.  If this value is
Xset to 0, no polling occurs during idle mode, and the only way to enter
Xactive mode is to either open the tool, or to click the \*(lqGo Active\*(rq
Xbutton.
X.IP "\fB\-o\fP" 14
XThis option causes \fIlpqtool\fP to automatically open when in active mode.
X.IP "\fB\-r\fP \fIrows\fP" 14
XThis option determines the number of rows in the queue display.
XThe default value is 5 rows.
X.IP "\fB\-t\fP \fIthreshold\fP" 14 
XThis option determines the number of consecutive times an empty queue must
Xbe encountered before switching from active mode to idle mode.  The default is 6.
X.SH SEE ALSO
Xlpq(1), lpr(1), suntools(1)
X.SH AUTHOR
X.LP
XChuck Musciano
X.br
XAdvanced Technology Department
X.br
XHarris Corporation
X.br
X(407) 727-6131
X.br
XARPA: chuck@trantor.harris-atd.com
X.SH BUGS
X.LP
X\fILpqtool\fP was really designed to watch the LaserWriter, although it
Xallows other printers to be specified.  Thus, references to the LaserWriter,
Xand the \fIlpqtool\fP icon, may not be correct for the desired printer.
END_OF_FILE
if test 3225 -ne `wc -c <'lpqtool.man'`; then
    echo shar: \"'lpqtool.man'\" unpacked with wrong size!
fi
# end of 'lpqtool.man'
fi
echo shar: End of shell archive.
exit 0

Chuck Musciano			ARPA  : chuck@trantor.harris-atd.com
Harris Corporation 		Usenet: ...!uunet!x102a!trantor!chuck
PO Box 37, MS 3A/1912		AT&T  : (407) 727-6131
Melbourne, FL 32902		FAX   : (407) 727-{5118,5227,4004}