[comp.sources.sun] v03i004: Catcher 1.0, Part03/05

mcgrew@aramis.rutgers.edu (Charles Mcgrew) (05/15/91)

Submitted-by: chuck@trantor.harris-atd.com (Chuck Musciano)
Posting-number: Volume 3, Issue 4
Archive-name: catcher/part03

#! /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 3 (of 5)."
# Contents:  catcher.c parse.y process.c
# Wrapped by chuck@melmac on Wed Jan 16 13:10:29 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'catcher.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'catcher.c'\"
else
echo shar: Extracting \"'catcher.c'\" \(8151 characters\)
sed "s/^X//" >'catcher.c' <<'END_OF_FILE'
X/************************************************************************/
X/*	Copyright 1987-1991 by Chuck Musciano and Harris Corporation 	*/
X/*									*/
X/*	Full ownership of this software, and all rights pertaining to 	*/
X/*	the for-profit distribution of this software, are retained by 	*/
X/*	Chuck Musciano and Harris Corporation.  You are permitted to 	*/
X/*	use this software without fee.  This software is provided "as 	*/
X/*	is" without express or implied warranty.  You may redistribute 	*/
X/*	this software, provided that this copyright notice is retained,	*/
X/*	and that the software is not distributed for profit.  If you 	*/
X/*	wish to use this software in a profit-making venture, you must 	*/
X/*	first license this code and its underlying technology from 	*/
X/*	Harris Corporation. 						*/
X/*									*/
X/*	Bottom line: you can have this software, you can use it, you 	*/
X/*	can give it away.  You just can't sell any or all parts of it 	*/
X/*	without prior permission from Harris Corporation. 		*/
X/************************************************************************/
X
X/************************************************************************/
X/*									*/
X/*	catcher.c	main control for catcher			*/
X/*									*/
X/************************************************************************/
X
X#include	<stdio.h>
X
X#include	<xview/xview.h>
X#include	<xview/panel.h>
X#include	<xview/icon.h>
X#include	<xview/svrimage.h>
X#include	<xview/seln.h>
X
X#include	<X11/Xlib.h>
X#include	<X11/Xutil.h>
X
X
X#include	"manifest.h"
X#include	"catcher.h"
X#include	"drag_drop.h"
X
XEXPORT	Frame	base;
X
XPUBLIC	shutdown_windows();
X
XPUBLIC	int	parse_errors_occured;
X
XPRIVATE	short	default_icon[] = {
X#include	"icons/catcher.icon"
X				 };
XPRIVATE	short	default_mask[] = {
X#include	"icons/catcher_mask.icon"
X				 };
X
XPRIVATE	char	*drag_buffer = NULL;
X
X/************************************************************************/
XPRIVATE	Seln_result	read_selection(response)
X
XSeln_request	*response;
X
X{	char	*reply;
X	long	total_size;
X	static	int	curr_size;
X
X	reply = response->data;
X	if (*(response->requester.context)) {
X	   reply += sizeof(SELN_REQ_BYTESIZE);
X	   total_size = *((long *) reply);
X	   reply += sizeof(long);
X	   if ((drag_buffer = (char *) malloc(total_size + 1)) == NULL)
X	      return(SELN_FAILED);
X	   reply += sizeof(SELN_REQ_CONTENTS_ASCII);
X	   *(response->requester.context) = FALSE;
X	   curr_size = 0;
X	   }
X	strcpy(drag_buffer + curr_size, reply);
X	curr_size += strlen(reply);
X	return(SELN_SUCCESS);
X}
X
X/************************************************************************/
XPRIVATE Notify_value	destroy(client, status)
X
XNotify_client	client;
XDestroy_status	status;
X
X{
X	if (status == DESTROY_CLEANUP) {
X	   shutdown_windows();
X	   return(notify_next_destroy_func(client, status));
X	   }
X	return(NOTIFY_DONE);
X}
X
X/************************************************************************/
XPRIVATE	Notify_value	catch_drop(win, event, arg, type)
X
XXv_Window	win;
XEvent		*event;
XNotify_arg	arg;
XNotify_event_type type;
X
X{	static	Xv_server	server = NULL;
X	XClientMessageEvent	*raw_message;
X	Drag_message		*message;
X	Atom			actual_type;
X	int			actual_format;
X	unsigned	long	nitems, bytes_after; 
X	Seln_holder		holder;
X	Seln_result		result;
X	char			*data, context = TRUE, *p, *q, *index();
X
X	if (server == NULL)
X	   server = (Xv_server) xv_get(xv_get(win, XV_SCREEN), SCREEN_SERVER);
X
X	switch (event_action(event)) {
X	   case ACTION_DRAG_LOAD : raw_message = (XClientMessageEvent *) event_xevent(event);
X	   			   message = (Drag_message *) &(raw_message->data);
X	   			   if (message->property != NULL)
X	   			      if (XGetWindowProperty(raw_message->display, message->window, message->property, 0L, 256, True, AnyPropertyType, &actual_type, &actual_format, &nitems, &bytes_after, &data) == Success) {
X	   			         drag_buffer = strsave(data);
X	   			         XFree(data);
X	   			         break;
X	   			         }
X	   case ACTION_DRAG_MOVE :
X	   case ACTION_DRAG_COPY : holder = selection_inquire(server, (event_action(event) == ACTION_PASTE)? SELN_SHELF : SELN_PRIMARY);
X				   result = selection_query(server, &holder, read_selection, &context, SELN_REQ_BYTESIZE, NULL, SELN_REQ_CONTENTS_ASCII, NULL, NULL);
X				   if (result == SELN_FAILED)
X				      error("could not get selection for drag or paste operation");
X				   else
X				      break;
X	   default               : return notify_next_event_func(win, event, arg, type);
X	   }
X
X	if (event_action(event) == ACTION_DRAG_MOVE)
X	   selection_ask(server, &holder, SELN_REQ_DELETE, NULL, NULL);
X	if (event_action(event) == ACTION_DRAG_LOAD) {
X	   for (p = drag_buffer; q = index(p, '\t'); p = q + 1) {
X	      *q = '\0';
X	      process_file(p);
X	      }
X	   process_file(p);
X	   }
X	else
X	   process_text(drag_buffer);
X	free(drag_buffer);
X	return(NOTIFY_DONE);
X}
X
X/************************************************************************/
Xmain(argc, argv)
X
Xint	argc;
Xchar	**argv;
X
X{	Icon	icon;
X	Server_image	image, mask = NULL;
X	Command	*cmd;
X	Option	*opt;
X	Choice	*c;
X	int	x, y, w, diff;
X	char	msg[256], *p, *rindex();
X	XClassHint	hints;
X
X	xv_init(XV_INIT_ARGC_PTR_ARGV, &argc, argv, NULL);
X
X	if (argc == 1)
X	   lex_init(NULL);
X	else if (argc == 2) {
X	   if (!lex_init(argv[1]))
X	      abend("could not read %s", argv[1]);
X	   }
X	else
X	   abend("usage: %s [<file>]", argv[0]);
X	yyparse();
X	if (parse_errors_occured)
X	   exit(1);
X
X	base = (Frame) xv_create(NULL, FRAME,
X				    FRAME_LABEL, config.label,
X				    FRAME_SHOW_RESIZE_CORNER, FALSE,
X				    FRAME_SHOW_FOOTER, config.message != NULL,
X				 NULL);
X
X	if (config.icon) {
X	   if ((image = (Server_image) load_icon(config.icon, msg)) == NULL)
X	      error("could not load icon from %s: %s", config.icon, msg);
X	   else if (config.icon_mask)
X	      if ((mask = (Server_image) load_icon(config.icon_mask, msg)) == NULL)
X	         error("could not load icon mask from %s: %s", config.icon, msg);
X	   }
X	else {
X	   image = (Server_image) xv_create(NULL, SERVER_IMAGE,
X	   				       SERVER_IMAGE_BITS, default_icon,
X	   				       XV_WIDTH, 64,
X	   				       XV_HEIGHT, 64,
X	   				    NULL);
X	   mask = (Server_image) xv_create(NULL, SERVER_IMAGE,
X	   				      SERVER_IMAGE_BITS, default_mask,
X	   				      XV_WIDTH, 64,
X	   				      XV_HEIGHT, 64,
X	   				   NULL);
X	   }
X	icon = (Icon) xv_create(base, ICON, ICON_IMAGE, image, NULL);
X	if (mask)
X	   xv_set(icon, ICON_MASK_IMAGE, mask, NULL);
X	xv_set(base, FRAME_ICON, icon, NULL);
X
X/* give the application a valid class and instance name */
X	hints.res_class = "Catcher";
X	hints.res_name = (p = rindex(argv[0], '/'))? p + 1 : argv[0];
X	XSetClassHint(xv_get(base, XV_DISPLAY), xv_get(xv_get(base, XV_ROOT), XV_XID), &hints);
X
X
X/* create the basic panels */
X	for (y = w = 0, cmd = config.command; cmd; cmd = cmd->next) {
X	   create_panel(base, cmd, y);
X	   notify_interpose_event_func(cmd->panel, catch_drop, NOTIFY_SAFE);
X	   y += (int) xv_get(cmd->panel, XV_HEIGHT) + PANEL_GAP;
X	   }
X
X/* align all the widget label right edges */
X	for (x = 0, cmd = config.command; cmd; cmd = cmd->next)
X	   for (opt = cmd->option; opt; opt = opt->next)
X	      if (x < (int) xv_get(opt->item, PANEL_VALUE_X))
X	         x = (int) xv_get(opt->item, PANEL_VALUE_X);
X	for (cmd = config.command; cmd; cmd = cmd->next)
X	   for (opt = cmd->option; opt; opt = opt->next) {
X	      diff = x - (int) xv_get(opt->item, PANEL_VALUE_X);
X	      xv_set(opt->item, XV_X, (int) xv_get(opt->item, XV_X) + diff, NULL);
X	      for (c = opt->choice; c; c = c->next)
X	         if (c->parameter)
X	            xv_set(c->item, XV_X, (int) xv_get(c->item, XV_X) + diff, NULL);
X	      }
X
X/* fix all the panel widths */
X	for (w = 0, cmd = config.command; cmd; cmd = cmd->next) {
X	   window_fit(cmd->panel);
X	   if (w < xv_get(cmd->panel, XV_WIDTH))
X	      w = (int) xv_get(cmd->panel, XV_WIDTH);
X	   }
X	for (cmd = config.command; cmd; cmd = cmd->next)
X	   xv_set(cmd->panel, XV_WIDTH, w, NULL);
X	window_fit(base);
X
X	notify_interpose_event_func(base, catch_drop, NOTIFY_SAFE);
X	notify_interpose_event_func(xv_get(base, FRAME_ICON), catch_drop, NOTIFY_SAFE);
X	notify_interpose_destroy_func(base, destroy);
X
X	xv_main_loop(base);
X}
END_OF_FILE
if test 8151 -ne `wc -c <'catcher.c'`; then
    echo shar: \"'catcher.c'\" unpacked with wrong size!
fi
# end of 'catcher.c'
fi
if test -f 'parse.y' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'parse.y'\"
else
echo shar: Extracting \"'parse.y'\" \(9186 characters\)
sed "s/^X//" >'parse.y' <<'END_OF_FILE'
X/************************************************************************/
X/*	Copyright 1987-1991 by Chuck Musciano and Harris Corporation 	*/
X/*									*/
X/*	Full ownership of this software, and all rights pertaining to 	*/
X/*	the for-profit distribution of this software, are retained by 	*/
X/*	Chuck Musciano and Harris Corporation.  You are permitted to 	*/
X/*	use this software without fee.  This software is provided "as 	*/
X/*	is" without express or implied warranty.  You may redistribute 	*/
X/*	this software, provided that this copyright notice is retained,	*/
X/*	and that the software is not distributed for profit.  If you 	*/
X/*	wish to use this software in a profit-making venture, you must 	*/
X/*	first license this code and its underlying technology from 	*/
X/*	Harris Corporation. 						*/
X/*									*/
X/*	Bottom line: you can have this software, you can use it, you 	*/
X/*	can give it away.  You just can't sell any or all parts of it 	*/
X/*	without prior permission from Harris Corporation. 		*/
X/************************************************************************/
X
X%{
X
X#include	<stdio.h>
X#include	<ctype.h>
X
X#include	<xview/xview.h>
X#include	<xview/panel.h>
X
X#include	"manifest.h"
X#include	"catcher.h"
X
XEXPORT	int	parse_errors_occured;
X
XEXPORT	Catch	config = {NULL, NULL, "Catcher", NULL, '$', '{', '}', NULL, NULL};
X
XPRIVATE	char	*get_last_token();
X
XPRIVATE	char	*curr_file;
XPRIVATE	int	line_count = 1;
XPRIVATE	char	ungetc = -1;
X
XPRIVATE	Command	*curr_cmd;
XPRIVATE	Option	*curr_opt;
XPRIVATE	Choice	*curr_cho;
XPRIVATE	Text	text;
X
X%}
X
X%start	configuration
X
X%union	{Choice		*chval;
X	 char		*cpval;
X	 Command	*cval;
X	 int		ival;
X	 Option		*oval;
X	}
X
X%token	<cpval>	STRING ID
X%token	<ival>	INTEGER
X
X%token		LBRACE RBRACE
X
X%token		BY CHOICE COMMAND DEFAULT DELIMITER EXCLUSIVE FINISH HORIZONTAL ICON_ ICON_MASK INIT LABEL
X%token		MESSAGE NONEXCLUSIVE NUMERIC OPTIONAL OUTPUT PARAMETER START SUFFIX TEXT TO VALUE WINDOW_
X
X%type	<chval>	anon_choice choice
X%type	<cpval>	command_name delimiter icon icon_mask label message suffix text_init value
X%type	<cval>	command
X%type	<ival>	int_init
X%type	<oval>	exclusive nonexclusive option text
X
X%%
X
Xconfiguration	:	prologue command_list
X		;
X
Xprologue	:	prologue prologue_item
X		|	empty
X		;
X
Xprologue_item	:	delimiter
X						{ if (strlen($1) != 3)
X						     yyerror("delimiter must contain three characters");
X						  config.escape = $1[0];
X						  config.ldelim = $1[1];
X						  config.rdelim = $1[2];
X						}
X		|	icon
X						{ config.icon = strsave($1); }
X		|	icon_mask
X						{ config.icon_mask = strsave($1); }
X		|	label
X						{ config.label = strsave($1); }
X		|	message
X						{ config.message = strsave($1); }
X		|	output
X		|	suffix
X						{ config.suffix = strsave($1); }
X		;
X
Xcommand_list	:	command
X						{ config.command = $1; }
X		|	command_list command
X						{ Command *c;
X						
X						  for (c = config.command; c->next; c = c->next)
X						     ;
X						  c->next = $2;
X						}
X		;
X
Xcommand		:	COMMAND
X						{ curr_cmd = (Command *) malloc(sizeof(Command));
X						  curr_cmd->command = NULL;
X						  curr_cmd->label = NULL;
X						  curr_cmd->optional = FALSE;
X						  curr_cmd->option = NULL;
X						  curr_cmd->next = NULL;
X						}
X			LBRACE command_info options RBRACE
X						{ if (is_empty(curr_cmd->command))
X						     yyerror("no command specified");
X						  $$ = curr_cmd;
X						}
X		;
X
Xcommand_info	:	command_info cmd_info_item
X		|	empty
X		;
X
Xcmd_info_item	:	command_name
X						{ curr_cmd->command = strsave($1); }
X		|	label
X						{ curr_cmd->label = strsave($1); }
X		|	optional
X						{ curr_cmd->optional = TRUE; }
X		;
X
Xoptions		:	options option
X						{ Option *o;
X						
X						  if (curr_cmd->option == NULL)
X						     curr_cmd->option = $2;
X						  else {
X						     for (o = curr_cmd->option; o->next; o = o->next)
X						        ;
X						     o->next = $2;
X						     }
X						}
X		|	empty
X		;
X
Xoption		:	exclusive
X		|	nonexclusive
X		|	text
X		;
X
Xexclusive	:	EXCLUSIVE ID
X						{ curr_opt = (Option *) malloc(sizeof(Option));
X						  curr_opt->id = strsave($2);
X						  curr_opt->label = NULL;
X						  curr_opt->type = OPT_EXCLUSIVE;
X						  curr_opt->horizontal = FALSE;
X						  curr_opt->choice = NULL;
X						  curr_opt->next = NULL;
X						}
X			LBRACE option_info anon_choices RBRACE
X						{ if (curr_opt->choice == NULL)
X						     yyerror("no choices specified for exclusive option %s", curr_opt->id);
X						  $$ = curr_opt;
X						}
X		;
X
Xnonexclusive	:	NONEXCLUSIVE
X						{ curr_opt = (Option *) malloc(sizeof(Option));
X						  curr_opt->id = NULL;
X						  curr_opt->label = NULL;
X						  curr_opt->type = OPT_NONEXCLUSIVE;
X						  curr_opt->horizontal = FALSE;
X						  curr_opt->choice = NULL;
X						  curr_opt->next = NULL;
X						}
X			LBRACE option_info choices RBRACE
X						{ if (curr_opt->choice == NULL)
X						     yyerror("no choices specified for nonexclusive option %s", curr_opt->id);
X						  $$ = curr_opt;
X						}
X		;
X
Xtext		:	TEXT ID
X						{ curr_opt = (Option *) malloc(sizeof(Option));
X						  curr_opt->id = strsave($2);
X						  curr_opt->label = NULL;
X						  curr_opt->type = OPT_TEXT;
X						  curr_opt->choice = NULL;
X						  curr_opt->next = NULL;
X						}
X			LBRACE option_info parm RBRACE
X						{ curr_opt->text = text;
X						  $$ = curr_opt;
X						}
X		;
X
Xoption_info	:	option_info opt_info_item
X		|	empty
X		;
X
Xopt_info_item	:	label
X						{ curr_opt->label = strsave($1); }
X		|
X			horizontal
X						{ curr_opt->horizontal = TRUE; }
X		;
X
Xchoices		:	choices choice
X						{ Choice *c;
X						
X						  if (curr_opt->choice == NULL)
X						     curr_opt->choice = $2;
X						  else {
X						     for (c = curr_opt->choice; c->next; c = c->next)
X						        ;
X						     c->next = $2;
X						     }
X						}
X		|	empty
X		;
X
Xchoice		:	CHOICE ID
X						{ curr_cho = (Choice *) malloc(sizeof(Choice));
X						  curr_cho->id = strsave($2);
X						  curr_cho->value = NULL;
X						  curr_cho->label = NULL;
X						  curr_cho->parameter = FALSE;
X						  curr_cho->is_default = FALSE;
X						  curr_cho->item = NULL;
X						  curr_cho->next = NULL;
X						}
X			LBRACE choice_info RBRACE
X						{ if (curr_cho->value == NULL)
X						     yyerror("no value specified for choice");
X						  $$ = curr_cho;
X						}
X		;
X
Xanon_choices	:	anon_choices anon_choice
X						{ Choice *c;
X						
X						  if (curr_opt->choice == NULL)
X						     curr_opt->choice = $2;
X						  else {
X						     for (c = curr_opt->choice; c->next; c = c->next)
X						        ;
X						     c->next = $2;
X						     }
X						}
X		|	empty
X		;
X
Xanon_choice	:	CHOICE
X						{ curr_cho = (Choice *) malloc(sizeof(Choice));
X						  curr_cho->id = NULL;
X						  curr_cho->value = NULL;
X						  curr_cho->label = NULL;
X						  curr_cho->parameter = FALSE;
X						  curr_cho->is_default = FALSE;
X						  curr_cho->item = NULL;
X						  curr_cho->next = NULL;
X						}
X			LBRACE choice_info RBRACE
X						{ if (curr_cho->value == NULL)
X						     yyerror("no value specified for choice");
X						  $$ = curr_cho;
X						}
X		;
X
Xchoice_info	:	choice_info cho_info_item
X		|	empty
X		;
X
Xcho_info_item	:	label
X						{ curr_cho->label = strsave($1); }
X		|	default
X						{ curr_cho->is_default = TRUE; }
X		|	parameter
X						{ curr_cho->parameter = TRUE;
X						  curr_cho->text = text;
X						  curr_opt->horizontal = FALSE;
X						}
X		|	value
X						{ curr_cho->value = strsave($1); }
X		;
X
Xparameter	:	PARAMETER parm
X		;
X
Xparm		:	TEXT INTEGER text_init
X						{ text.type = PARM_TEXT;
X						  text.length = $2;
X						  text.text_init = strsave($3);
X						}
X		|	NUMERIC INTEGER INTEGER TO INTEGER
X						{ text.type = PARM_NUMERIC;
X						  text.length = $2;
X						  text.low = $3;
X						  text.high = $5;
X						  if (text.low > text.high)
X						     yyerror("numeric text field range is incorrect");
X						  }
X			int_init
X						{ text.int_init = $7;
X						  if (text.int_init < text.low || text.int_init > text.high)
X						     yyerror("numeric text field initial value is out of range");
X						}
X		;
X
Xtext_init	:	INIT STRING
X						{ $$ = $2; }
X		|	empty
X						{ $$ = NULL; }
X		;
X
Xint_init	:	INIT INTEGER
X						{ $$ = $2; }
X		|	empty
X						{ $$ = text.low; }
X		;
X
Xcommand_name	:	COMMAND STRING
X						{ $$ = $2; }
X		;
X
Xdefault		:	DEFAULT
X		;
X
Xdelimiter	:	DELIMITER STRING
X						{ $$ = $2; }
X		;
X
Xicon		:	ICON_ STRING
X						{ $$ = $2; }
X		;
X
Xicon_mask	:	ICON_MASK STRING
X						{ $$ = $2; }
X		;
X
Xhorizontal	:	HORIZONTAL
X		;
X
Xlabel		:	LABEL STRING
X						{ $$ = $2; }
X		;
X
Xmessage		:	MESSAGE STRING
X						{ $$ = $2; }
X		;
X
Xoptional	:	OPTIONAL
X		;
X
Xoutput		:	OUTPUT INTEGER BY INTEGER
X						{ output_height = $2;
X						  output_width = $4;
X						}
X		;
X
Xsuffix		:	SUFFIX STRING
X						{ $$ = $2; }
X		;
X
Xvalue		:	VALUE STRING
X						{ $$ = $2; }
X		;
X
Xempty		: ;
X
X%%
X
X/************************************************************************/
XPRIVATE	yyerror(s1, s2, s3, s4, s5, s6, s7)
X
Xchar	*s1, *s2, *s3, *s4, *s5, *s6, *s7;
X
X{	char	buf1[1024], buf2[1024];
X
X	sprintf(buf1, "%s: line %d: ", curr_file, line_count - ((ungetc == '\n')? 1 : 0));
X	sprintf(buf2, s1, s2, s3, s4, s5, s6, s7);
X	strcat(buf1, buf2);
X	if (strcmp(s1, "syntax error") == 0) {
X	   strcat(buf1, " at or near ");
X	   strcat(buf1, get_last_token());
X	   }
X	error(buf1);
X	yyclearin;
X	parse_errors_occured++;
X}
X
X#include "lex.c"
END_OF_FILE
if test 9186 -ne `wc -c <'parse.y'`; then
    echo shar: \"'parse.y'\" unpacked with wrong size!
fi
# end of 'parse.y'
fi
if test -f 'process.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'process.c'\"
else
echo shar: Extracting \"'process.c'\" \(9815 characters\)
sed "s/^X//" >'process.c' <<'END_OF_FILE'
X/************************************************************************/
X/*	Copyright 1987-1991 by Chuck Musciano and Harris Corporation 	*/
X/*									*/
X/*	Full ownership of this software, and all rights pertaining to 	*/
X/*	the for-profit distribution of this software, are retained by 	*/
X/*	Chuck Musciano and Harris Corporation.  You are permitted to 	*/
X/*	use this software without fee.  This software is provided "as 	*/
X/*	is" without express or implied warranty.  You may redistribute 	*/
X/*	this software, provided that this copyright notice is retained,	*/
X/*	and that the software is not distributed for profit.  If you 	*/
X/*	wish to use this software in a profit-making venture, you must 	*/
X/*	first license this code and its underlying technology from 	*/
X/*	Harris Corporation. 						*/
X/*									*/
X/*	Bottom line: you can have this software, you can use it, you 	*/
X/*	can give it away.  You just can't sell any or all parts of it 	*/
X/*	without prior permission from Harris Corporation. 		*/
X/************************************************************************/
X
X/************************************************************************/
X/*									*/
X/*	process.c	process files dropped on the catcher		*/
X/*									*/
X/************************************************************************/
X
X#include	<stdio.h>
X#include	<ctype.h>
X
X#include	<xview/xview.h>
X#include	<xview/panel.h>
X
X#include	"manifest.h"
X#include	"catcher.h"
X
XPUBLIC	char	*getenv();
X
XPUBLIC	Frame	base;
X
X/************************************************************************/
XPRIVATE	get_text_value(value, text, item)
X
Xchar	*value;
XText	*text;
XPanel_item	item;
X
X{	int	val;
X
X	if (text->type == PARM_TEXT)
X	   strcpy(value, xv_get(item, PANEL_VALUE));
X	else {
X	   val = (int) xv_get(item, PANEL_VALUE);
X	   if (val < text->low)
X	      val = text->low;
X	   if (val > text->high)
X	      val = text->high;
X	   sprintf(value, "%d", val);
X	   }
X}
X
X/************************************************************************/
XPRIVATE	int	get_choice_value(value, choice, field, oname)
X
Xchar	*value;
XChoice	*choice;
Xchar	*field;
Xchar	*oname;
X
X{	
X	if (field)
X	   if (strcmp(field, "value") == 0)
X	      if (choice->parameter)
X	         get_text_value(value, &(choice->text), choice->item);
X	      else if (choice->id == NULL)
X	         *value = '\0';
X	      else{
X	         error("choice \"%s\" in option \"%s\" has no parameter defined", choice->id, oname);
X	         return(FALSE);
X	         }
X	   else {
X	      error("unknown field: \"%s\"", field);
X	      return(FALSE);
X	      }
X	else
X	   strcpy(value, choice->value);
X	return(TRUE);
X}
X
X/************************************************************************/
XPRIVATE	int	find_name(name, field, value, file, options)
X
Xchar	*name;
Xchar	*field;
Xchar	*value;
Xchar	*file;
XOption	*options;
X
X{	Option	*o;
X	Choice	*c;
X	int	i, val;
X	char	*p;
X
X	if (strcmp(name, "file") == 0) {
X	   if (field) {
X	      error("no fields are allowed with the \"file\" variable");
X	      return(FALSE);
X	      }
X	   strcpy(value, file);
X	   }
X	else {
X	   for (o = options; o; o = o->next)
X	      if (o->type == OPT_NONEXCLUSIVE) {
X	         for (i = 0, c = o->choice; c; c = c->next, i++)
X	            if (strcmp(name, c->id) == 0) {
X	               val = (int) xv_get(o->item, PANEL_VALUE);
X	               if (val & (1 << i))
X	                  return(get_choice_value(value, c, field, o->id));
X	               else
X	                  *value = '\0';
X	               break;
X	               }
X	         if (c)
X	            break;
X	         }
X	      else if (strcmp(name, o->id) == 0) {
X	         if (o->type == OPT_TEXT)
X	            if (field) {
X	               error("no fields are allowed with text variables");
X	               return(FALSE);
X	               }
X	            else {
X	               get_text_value(value, &(o->text), o->item);
X	               break;
X	               }
X	         else {
X	            val = (int) xv_get(o->item, PANEL_VALUE);
X	            for (i = 0, c = o->choice; i < val; c = c->next, i++)
X	               ;
X	            return(get_choice_value(value, c, field, o->id));
X	            }
X	         }
X	   if (o == NULL)
X	      if ((p = getenv(name)) == NULL) {
X	         error("undefined variable: \"%s\"", name);
X	         return(FALSE);
X	         }
X	      else if (field) {
X	         error("no fields are allowed with environment variables");
X	         return(FALSE);
X	         }
X	      else
X	         strcpy(value, p);
X	   }
X	return(TRUE);
X}
X
X/************************************************************************/
XPRIVATE	int	apply_mods(value, mods)
X
Xchar	*value;
Xchar	*mods;
X
X{	char	*p, *q, *rindex;
X
X	while (*mods) {
X	   switch (*mods) {
X	      case 'h' : for (p = value + strlen(value) - 1; p >= value; p--)
X	         	    if (*p == '/') {
X	         	       *p = '\0';
X	         	       break;
X	         	       }
X	         	 if (*value == '\0')
X	         	    strcpy(value, "/");
X	         	 break;
X	      case 'r' : for (p = value + strlen(value) - 1; p >= value; p--)
X	         	    if (*p == '.') {
X	         	       *p = '\0';
X	         	       break;
X	         	       }
X	         	    else if (*p == '/')
X	         	       break;
X	         	 break;
X	      case 's' : for (p = value + strlen(value) - 1; p >= value; p--)
X	         	    if (*p == '.') {
X	         	       strcpy(value, p + 1);
X	         	       break;
X	         	       }
X	         	    else if (*p == '/')
X	         	       break;
X	         	 if (p < value || *p == '/')
X	         	    *value = '\0';
X	         	 break;
X	      case 't' : for (p = value + strlen(value) - 1; p >= value; p--)
X	         	    if (*p == '/') {
X	         	       strcpy(value, p + 1);
X	         	       break;
X	         	       }
X	         	 break;
X	      default  : error("invalid modifier: '%c'", *mods);
X	         	 return(FALSE);
X	      }
X	   if (*++mods == ':')
X	      ++mods;
X	   }
X	return(TRUE);
X}
X
X/************************************************************************/
XPRIVATE	char	*substitute(pattern, file, options)
X
Xchar	*pattern;
Xchar	*file;
XOption	*options;
X
X{	char	*name, *field, *mods, *p;
X	static	char	value[2048];
X
X	for (p = name = pattern; *p && *p != '.' && *p != ':'; p++)
X	   ;
X	if (*p == '.') {
X	   *p++ = '\0';
X	   for (field = p; *p && *p != ':'; p++)
X	      ;
X	   if (*p)
X	      *p++ = '\0';
X	   }
X	else {
X	   if (*p == ':')
X	      *p++ = '\0';
X	   field = NULL;
X	   }
X	mods = p;
X	if (!find_name(name, field, value, file, options))
X	   return(NULL);
X	if (!apply_mods(value, mods))
X	   return(NULL);
X	return(value);
X}
X
X/************************************************************************/
XPRIVATE	int	build_command(result, command, option, file)
X
Xchar	*result;
Xchar	*command;
XOption	*option;
Xchar	*file;
X
X{	char	*template = NULL, buf[2048], *t, *r, *p, *q, c;
X	int	changed, depth;
X
X	do {
X	   changed = FALSE;
X	   if (template == NULL)
X	      template = strsave(command);
X	   else {
X	      free(template);
X	      template = strsave(result);
X	      }
X	   for (t = template, r = result; *t; )
X	      if (*t == config.escape) {
X	         changed = TRUE;
X	         if (*++t == config.ldelim) {
X	            for (p = t + 1, depth = 1; *p && depth > 0; p++)
X	               if (*p == config.ldelim)
X	                  depth++;
X	               else if (*p == config.rdelim)
X	                  depth--;
X	            if (depth > 0) {
X	               error("erroneous substitution pattern: %s", t);
X	               return(FALSE);
X	               }
X	            *--p = '\0';
X	            if (!build_command(buf, t + 1, option, file))
X	               return(FALSE);
X	            if ((q = substitute(buf, file, option)) == NULL)
X	               return(FALSE);
X	            strcpy(r, q);
X	            r += strlen(q);
X	            t = p + 1;
X	            }
X	         else {
X	            for (p = t; *p && (isalnum(*p) || *p == '_'); p++)
X	               ;
X	            c = *p;
X	            *p = '\0';
X	            if ((q = substitute(t, file, option)) != NULL) {
X	               strcpy(r, q);
X	               r += strlen(q);
X	               *p = c;
X	               t = p;
X	               }
X	            else {
X	               error("undefined variable: %s", t);
X	               return(FALSE);
X	               }
X	            }
X	         }
X	      else
X	         *r++ = *t++;
X	   *r = '\0';
X	   } while (changed);
X	return(TRUE);
X}
X
X/************************************************************************/
XEXPORT	process_file(path)
X
Xchar	*path;
X
X{	char	*command = NULL, buf[2048];
X	Command	*cmd;
X
X	for (cmd = config.command; cmd; cmd = cmd->next) {
X	   if (cmd->optional && (int) xv_get(cmd->toggle, PANEL_VALUE) == 0)
X	      continue;
X	   if (!build_command(buf, cmd->command, cmd->option, path))
X	      return;
X	   if (command == NULL)
X	      command = strsave(buf);
X	   else {
X	      command = (char *) realloc(command, strlen(command) + strlen(buf) + 5);
X	      strcat(command, " | ");
X	      strcat(command, buf);
X	      }
X	   }
X	if (!is_empty(command)) {
X	   if (config.message) {
X	      if (build_command(buf, config.message, NULL, path))
X	         xv_set(base, FRAME_LEFT_FOOTER, buf, NULL);
X	      }
X	   execute(command, path);
X	   free(command);
X	   }
X}
X
X/************************************************************************/
XEXPORT	process_text(data)
X
Xchar	*data;
X
X{	char	*path;
X	FILE	*f;
X
X	path = (char *) malloc(strlen(config.suffix) + 22);
X	strcpy(path, "/tmp/catcher.XXXXXX");
X	mktemp(path);
X	strcat(path, ".");
X	strcat(path, config.suffix);
X	if ((f = fopen(path, "w")) == NULL)
X	   error("cannot open %s for writing: %s", path, sys_errlist[errno]);
X	else if (fwrite(data, 1, strlen(data), f) != strlen(data)) {
X	   fclose(f);
X	   error("error while writing to %s: %s", path, sys_errlist[errno]);
X	   }
X	else {
X	   fclose(f);
X	   process_file(path);
X	   }
X	free(path);
X}
END_OF_FILE
if test 9815 -ne `wc -c <'process.c'`; then
    echo shar: \"'process.c'\" unpacked with wrong size!
fi
# end of 'process.c'
fi
echo shar: End of archive 3 \(of 5\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0