v11i008: catcher -- drag and drop manager, Part03/05
Chuck Musciano
chuck at trantor.harris-atd.com
Tue Jan 29 19:17:17 AEST 1991
Submitted-by: chuck at trantor.harris-atd.com (Chuck Musciano)
Posting-number: Volume 11, Issue 8
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 at 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
--
dan
----------------------------------------------------
O'Reilly && Associates argv at sun.com / argv at ora.com
Opinions expressed reflect those of the author only.
More information about the Comp.sources.x
mailing list