534 lines
17 KiB
C
534 lines
17 KiB
C
#ifndef lint
|
|
static char sccsid[] = "@(#)metafile.c 1.1 94/10/31 Copyr 1985-9 Sun Micro";
|
|
#endif lint
|
|
|
|
/*
|
|
* Copyright (c) 1985, 1986, 1987, 1988, 1989 by Sun Microsystems, Inc.
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose and without fee is hereby granted, provided that the above
|
|
* copyright notice appear in all copies and that both that copyright
|
|
* notice and this permission notice are retained, and that the name
|
|
* of Sun Microsystems, Inc., not be used in advertising or publicity
|
|
* pertaining to this software without specific, written prior permission.
|
|
* Sun Microsystems, Inc., makes no representations about the suitability
|
|
* of this software or the interface defined in this software for any
|
|
* purpose. It is provided "as is" without express or implied warranty.
|
|
*/
|
|
/*
|
|
* CGI initialization & termination functions
|
|
*/
|
|
|
|
/*
|
|
open_cgi
|
|
_cgi_open_cgi
|
|
_cgi_initialize_internals
|
|
close_cgi
|
|
_cgi_alloc_output_att
|
|
_cgi_free_output_att
|
|
_cgi_hangup
|
|
_cgi_interrupt
|
|
set_up_sigwinch
|
|
_cgi_sigxcpu
|
|
*/
|
|
|
|
#include "cgipriv.h"
|
|
#include <sys/ioctl.h>
|
|
#include <sun/gpio.h>
|
|
#include <stdio.h>
|
|
#include <signal.h>
|
|
#include <sunwindow/notify.h>
|
|
|
|
Notify_value _cgi_winsig();
|
|
Notify_value _cgi_sigchild();
|
|
Notify_value _cgi_hangup();
|
|
Notify_value _cgi_interrupt();
|
|
Notify_value _cgi_ioint();
|
|
Notify_value _cgi_sigxcpu();
|
|
|
|
/* int malloc_debug (); */
|
|
|
|
View_surface *_cgi_view_surfaces[MAXVWS]; /* view surface information */
|
|
View_surface *_cgi_vws; /* current view surface */
|
|
int _cgi_vwsurf_count; /* number of view surfaces */
|
|
int _cgi_pix_mode; /* pixrect equivalent of drawing mode */
|
|
Ccombtype _cgi_drawing_mode;
|
|
int _cgi_ttext; /* text transparency flag */
|
|
int _cgi_pix_drawing_mode;
|
|
u_char *_cgi_disjoint_mvlist;
|
|
Ccombtype _cgi_bit_drawing_mode;
|
|
Cbmode _cgi_bit_vis_mode;
|
|
Cbitmaptype _cgi_bit_source;
|
|
Cbitmaptype _cgi_bit_dest;
|
|
Cacttype _cgi_clear_mode;
|
|
Cexttype _cgi_clear_extent;
|
|
int _cgi_input_devices; /* are input devices used */
|
|
int _cgi_num_events;/* event queue pointer */
|
|
Cqtype _cgi_que_status;/* event queue status */
|
|
Ceqflow _cgi_que_over_status; /* event queue status */
|
|
int _cgi_trigger[MAXTRIG][MAXASSOC + 1]; /* association list */
|
|
Outatt *_cgi_att; /* structure containing current attributes */
|
|
int _cgi_event_occurred; /* event flag */
|
|
struct locatstr *_cgi_locator[_CGI_LOCATORS];
|
|
struct keybstr *_cgi_keybord[_CGI_KEYBORDS];
|
|
struct strokstr *_cgi_stroker[_CGI_STROKES];
|
|
struct valstr *_cgi_valuatr[_CGI_VALUATRS];
|
|
struct choicestr *_cgi_button[_CGI_CHOICES];
|
|
struct pickstr *_cgi_pick[_CGI_PICKS];
|
|
Cint *_cgi_pattern_table[MAXNUMPATS]; /* pattern table */
|
|
caddr_t (*_cgi_win_get)(); /* -> "window_get" if canvas call */
|
|
|
|
Gstate _cgi_state =
|
|
{ /* CGI global state */
|
|
CGCL, /* state */
|
|
0, /* cgipw_mode */
|
|
(Notify_client) NULL, /* notifier_client_handle */
|
|
{
|
|
NO_FONT, (struct pixfont *) NULL
|
|
}, /* open_font */
|
|
0, /* gp1resetcnt */
|
|
1, 1, /* vdc_change_cnt, text_change_cnt */
|
|
(Outatt *) NULL, /* common_att */
|
|
};
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: open_cgi */
|
|
/* */
|
|
/* initializes cgi and selects viewsurface */
|
|
/****************************************************************************/
|
|
|
|
Cerror open_cgi()
|
|
{
|
|
int err;
|
|
|
|
err = _cgi_open_cgi(0, 0); /* cgipw_mode==0, use_pw_size==0 */
|
|
return (_cgi_errhand(err));
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: _cgi_open_cgi */
|
|
/* */
|
|
/* initializes cgi and selects viewsurface */
|
|
/****************************************************************************/
|
|
|
|
Cerror _cgi_open_cgi(cgipw_mode, use_pw_size)
|
|
int cgipw_mode; /* CGIPW mode: block certain accesses */
|
|
int use_pw_size; /* flag in Outatt structure for pixwin
|
|
* coordinates */
|
|
{
|
|
register u_char *mvP;
|
|
register Outatt *attP;
|
|
register int cnt;
|
|
Cerror err;
|
|
static VdcRect vdc_norm_rect = {0, 0, 32767, 32767};
|
|
static VdcRect vdc_pw_rect = {0, 0, 0, 0};
|
|
|
|
if (_cgi_state.state == CGCL)
|
|
err = NO_ERROR;
|
|
else
|
|
err = ENOTCGCL;
|
|
|
|
/*
|
|
* First, try allocating everything we'll be using. If any fail, free
|
|
* those already allocated, and return without changing anything more.
|
|
*/
|
|
_cgi_disjoint_mvlist = (u_char *) malloc(MAXPTS * sizeof(u_char));
|
|
if (_cgi_disjoint_mvlist == (u_char *) NULL)
|
|
err = EMEMSPAC;
|
|
else
|
|
{
|
|
_cgi_state.common_att = (Outatt *) calloc(1, sizeof(Outatt));
|
|
if (_cgi_state.common_att == (Outatt *) NULL)
|
|
{
|
|
err = EMEMSPAC;
|
|
free((char *) _cgi_disjoint_mvlist);
|
|
_cgi_disjoint_mvlist = NULL;
|
|
}
|
|
}
|
|
|
|
if (!err)
|
|
{
|
|
/*
|
|
* Construct a move list for a disjoint polyline. We can delete this
|
|
* code when pixrects supports POLY_DISJOINT.
|
|
*/
|
|
mvP = _cgi_disjoint_mvlist;
|
|
for (cnt = MAXPTS; cnt >= 2; cnt -= 2)
|
|
{
|
|
*mvP++ = 1;
|
|
*mvP++ = 0;
|
|
}
|
|
|
|
/*
|
|
* The first flag has a special meaning: close all sub-polygons. We
|
|
* need to clear it explicitly to prevent this.
|
|
*/
|
|
*_cgi_disjoint_mvlist = 0;
|
|
|
|
/* Initialize all data that is once-per-CGI */
|
|
_cgi_state.state = CGOP;
|
|
_cgi_state.cgipw_mode = cgipw_mode;
|
|
_cgi_state.notifier_client_handle = (Notify_client) & _cgi_state;
|
|
_cgi_state.open_font.num = NO_FONT;
|
|
_cgi_state.open_font.ptr = (struct pixfont *) NULL;
|
|
_cgi_state.gp1resetcnt = 0;
|
|
_cgi_state.vdc_change_cnt = 1;
|
|
_cgi_state.text_change_cnt = 1;
|
|
|
|
_cgi_att = attP = _cgi_state.common_att;
|
|
_cgi_vws = (View_surface *) NULL;
|
|
_cgi_vwsurf_count = 0;
|
|
attP->vdc.clip.indicator = CLIP;
|
|
attP->vdc.use_pw_size = use_pw_size;
|
|
if (use_pw_size)
|
|
{
|
|
attP->vdc.rect = vdc_pw_rect;
|
|
attP->vdc.clip.rect = vdc_pw_rect;
|
|
}
|
|
else
|
|
{
|
|
attP->vdc.rect = vdc_norm_rect;
|
|
attP->vdc.clip.rect = vdc_norm_rect;
|
|
}
|
|
_cgi_ttext = 1; /* text transparency flag = TRANSPARENT */
|
|
_cgi_pix_drawing_mode = _cgi_pix_mode = PIX_SRC;
|
|
_cgi_bit_drawing_mode = _cgi_drawing_mode = REPLACE;
|
|
_cgi_bit_vis_mode = OPAQUE;
|
|
_cgi_bit_source = BITTRUE;
|
|
_cgi_bit_dest = BITTRUE;
|
|
/* malloc_debug(2); */
|
|
_cgi_event_occurred = 0;/* event flag */
|
|
_cgi_win_get = (caddr_t (*)()) NULL; /* loaded by 'open_cgi_canvas' */
|
|
|
|
/* Install signal catchers */
|
|
notify_set_signal_func(_cgi_state.notifier_client_handle,
|
|
_cgi_hangup, SIGHUP, NOTIFY_ASYNC);
|
|
notify_set_signal_func(_cgi_state.notifier_client_handle,
|
|
_cgi_interrupt, SIGINT, NOTIFY_ASYNC);
|
|
notify_set_signal_func(_cgi_state.notifier_client_handle,
|
|
_cgi_winsig, SIGWINCH, NOTIFY_ASYNC);
|
|
notify_set_signal_func(_cgi_state.notifier_client_handle,
|
|
_cgi_ioint, SIGIO, NOTIFY_ASYNC);
|
|
notify_set_signal_func(_cgi_state.notifier_client_handle,
|
|
_cgi_sigxcpu, SIGXCPU, NOTIFY_ASYNC);
|
|
_cgi_initialize_internals();
|
|
}
|
|
return (err);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: _cgi_initialize_internals */
|
|
/* */
|
|
/* _cgi_initialize_internals startup variables. */
|
|
/****************************************************************************/
|
|
_cgi_initialize_internals()
|
|
{
|
|
int i;
|
|
|
|
_cgi_clear_mode = CLEAR;
|
|
_cgi_clear_extent = VIEWSURFACE;
|
|
_cgi_input_devices = -1; /* don't input devices unless they're used */
|
|
for (i = 0; i < _CGI_KEYBORDS; i++)
|
|
_cgi_keybord[i] = (struct keybstr *) NULL;
|
|
/*
|
|
for(i = 0; i < _CGI_LOCATORS; i++)
|
|
_cgi_locator[i].subloc.enable = L_FALSE;
|
|
for(i = 0; i < _CGI_STROKES; i++)
|
|
_cgi_stroker[i].substroke.enable = L_FALSE;
|
|
for(i = 0; i < _CGI_VALUATRS; i++)
|
|
_cgi_valuatr[i].subval.enable = L_FALSE;
|
|
for(i = 0; i < _CGI_CHOICES; i++)
|
|
_cgi_button[i].subchoice.enable = L_FALSE;
|
|
*/
|
|
for (i = 0; i < MAXTRIG; i++)
|
|
_cgi_trigger[i][0] = 0;
|
|
_cgi_num_events = 0; /* no pending events */
|
|
_cgi_que_status = EMPTY;
|
|
_cgi_que_over_status = NO_OFLO;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: close_cgi */
|
|
/* */
|
|
/* terminates cgi and deselects viewsurface */
|
|
/****************************************************************************/
|
|
Cerror close_cgi()
|
|
{
|
|
Cerror err;
|
|
|
|
if (_cgi_state.cgipw_mode)
|
|
err = ENOTCCPW;
|
|
else
|
|
err = _cgi_close_cgi();
|
|
return (_cgi_errhand(err));
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: _cgi_close_cgi */
|
|
/* */
|
|
/* terminates cgi and deselects viewsurface */
|
|
/****************************************************************************/
|
|
Cerror _cgi_close_cgi()
|
|
{
|
|
int i, err;
|
|
|
|
if (_cgi_state.state != CGCL)
|
|
err = NO_ERROR;
|
|
else
|
|
err = ENOTOPOP;
|
|
if (!err)
|
|
{
|
|
(void) flush_event_queue();
|
|
|
|
/* close all view surfaces */
|
|
for (i = 0; i < _cgi_vwsurf_count; i++)
|
|
{
|
|
if (_cgi_view_surfaces[i] != (View_surface *) NULL)
|
|
(void) close_vws(i);
|
|
}
|
|
|
|
/* free malloc'd globals */
|
|
if (_cgi_state.open_font.ptr != (struct pixfont *) NULL)
|
|
{
|
|
(void) pf_close(_cgi_state.open_font.ptr);
|
|
_cgi_state.open_font.ptr = (struct pixfont *) NULL;
|
|
_cgi_state.open_font.num = NO_FONT;
|
|
}
|
|
_cgi_free_output_att(_cgi_state.common_att);
|
|
_cgi_state.common_att = (Outatt *) NULL;
|
|
free((char *) _cgi_disjoint_mvlist);
|
|
_cgi_disjoint_mvlist = (u_char *) NULL;
|
|
|
|
/* free input devices */
|
|
for (i = 0; i < _CGI_LOCATORS; i++)
|
|
{
|
|
if (_cgi_locator[i])
|
|
{
|
|
free((char *) _cgi_locator[i]);
|
|
_cgi_locator[i] = (struct locatstr *) NULL;
|
|
}
|
|
}
|
|
for (i = 0; i < _CGI_KEYBORDS; i++)
|
|
{
|
|
if (_cgi_keybord[i])
|
|
{
|
|
free((char *) _cgi_keybord[i]->initstring);
|
|
free((char *) _cgi_keybord[i]->rinitstring);
|
|
free((char *) _cgi_keybord[i]);
|
|
_cgi_keybord[i] = (struct keybstr *) NULL;
|
|
}
|
|
}
|
|
for (i = 0; i < _CGI_STROKES; i++)
|
|
{
|
|
if (_cgi_stroker[i])
|
|
{
|
|
free((char *) _cgi_stroker[i]->sarray->ptlist);
|
|
free((char *) _cgi_stroker[i]->sarray);
|
|
free((char *) _cgi_stroker[i]->rsarray->ptlist);
|
|
free((char *) _cgi_stroker[i]->rsarray);
|
|
free((char *) _cgi_stroker[i]);
|
|
_cgi_stroker[i] = (struct strokstr *) NULL;
|
|
}
|
|
}
|
|
for (i = 0; i < _CGI_VALUATRS; i++)
|
|
{
|
|
if (_cgi_valuatr[i])
|
|
{
|
|
free((char *) _cgi_valuatr[i]);
|
|
_cgi_valuatr[i] = (struct valstr *) NULL;
|
|
}
|
|
}
|
|
for (i = 0; i < _CGI_CHOICES; i++)
|
|
{
|
|
if (_cgi_button[i])
|
|
{
|
|
free((char *) _cgi_button[i]);
|
|
_cgi_button[i] = (struct choicestr *) NULL;
|
|
}
|
|
}
|
|
for (i = 0; i < _CGI_PICKS; i++)
|
|
{
|
|
if (_cgi_pick[i])
|
|
{
|
|
free((char *) _cgi_pick[i]);
|
|
_cgi_pick[i] = (struct pickstr *) NULL;
|
|
}
|
|
}
|
|
|
|
/* free other malloc'd private data */
|
|
for (i = 0; i < MAXNUMPATS; i++)
|
|
{
|
|
if (_cgi_pattern_table[i])
|
|
{
|
|
free((char *) _cgi_pattern_table[i]);
|
|
_cgi_pattern_table[i] = (Cint *) NULL;
|
|
}
|
|
}
|
|
_cgi_free_text_cache();
|
|
|
|
_cgi_state.state = CGCL;
|
|
|
|
/* Clear notifier actions */
|
|
notify_set_signal_func(_cgi_state.notifier_client_handle,
|
|
(Notify_func) 0, SIGHUP, NOTIFY_ASYNC);
|
|
notify_set_signal_func(_cgi_state.notifier_client_handle,
|
|
(Notify_func) 0, SIGINT, NOTIFY_ASYNC);
|
|
notify_set_signal_func(_cgi_state.notifier_client_handle,
|
|
(Notify_func) 0, SIGWINCH, NOTIFY_ASYNC);
|
|
notify_set_signal_func(_cgi_state.notifier_client_handle,
|
|
(Notify_func) 0, SIGIO, NOTIFY_ASYNC);
|
|
notify_set_signal_func(_cgi_state.notifier_client_handle,
|
|
(Notify_func) 0, SIGXCPU, NOTIFY_ASYNC);
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: _cgi_alloc_output_att */
|
|
/* */
|
|
/* Allocate a new Outatt structure, possibly initialize it, */
|
|
/* and return a pointer to it. */
|
|
/****************************************************************************/
|
|
Outatt *_cgi_alloc_output_att(initial_value)
|
|
Outatt *initial_value;
|
|
{
|
|
int cnt;
|
|
Outatt *attP;
|
|
|
|
attP = (Outatt *) calloc(1, sizeof(Outatt));
|
|
if (attP != (Outatt *) NULL)
|
|
{
|
|
if (initial_value != (Outatt *) NULL)
|
|
{
|
|
*attP = *initial_value;
|
|
attP->text.astring = (char *) NULL;
|
|
for (cnt = 0; cnt < MAXAESSIZE; cnt++)
|
|
attP->aes_table[cnt] = (Cbunatt *) NULL;
|
|
}
|
|
}
|
|
return (attP);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: _cgi_free_output_att */
|
|
/* */
|
|
/* Frees a cgi output att structure. */
|
|
/* Caller should set his output att structure pointer to NULL. */
|
|
/****************************************************************************/
|
|
_cgi_free_output_att(att)
|
|
Outatt *att;
|
|
{
|
|
int i;
|
|
|
|
if (att != NULL)
|
|
{
|
|
for (i = 0; (i < MAXAESSIZE) && (att->aes_table[i]); i++)
|
|
{
|
|
free((char *) att->aes_table[i]);
|
|
att->aes_table[i] = (Cbunatt *) NULL; /* Don't free again */
|
|
}
|
|
if (att->text.astring != (char *) NULL)
|
|
{
|
|
free(att->text.astring);
|
|
att->text.astring = (char *) NULL;
|
|
}
|
|
/* free (att->pattern.point); Never, ever malloc'd! */
|
|
cfree(att);
|
|
}
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: _cgi_hangup */
|
|
/* */
|
|
/* terminates cgi in response to SIGHUP */
|
|
/****************************************************************************/
|
|
Notify_value _cgi_hangup()
|
|
{
|
|
if (_cgi_state.cgipw_mode)
|
|
(void) close_pw_cgi();
|
|
else
|
|
(void) close_cgi();
|
|
exit(0);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: _cgi_interrupt */
|
|
/* */
|
|
/* terminates cgi in response to SIGINT */
|
|
/****************************************************************************/
|
|
Notify_value _cgi_interrupt()
|
|
{
|
|
if (_cgi_state.cgipw_mode)
|
|
(void) close_pw_cgi();
|
|
else
|
|
(void) close_cgi();
|
|
exit(0);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: set_up_sigwinch */
|
|
/* */
|
|
/****************************************************************************/
|
|
Cerror set_up_sigwinch(name, sig_function)
|
|
int name;
|
|
int (*sig_function) (); /* signal handling function */
|
|
{
|
|
int err = _cgi_check_state_5();
|
|
|
|
if (!err && !(err = _cgi_legal_winname(name)) )
|
|
_cgi_view_surfaces[name]->sunview.sig_function = sig_function;
|
|
return (_cgi_errhand(err));
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* FUNCTION: _cgi_sigxcpu */
|
|
/* */
|
|
/* handle signal SIGXCPU (possibly from gp1) for CGI. */
|
|
/****************************************************************************/
|
|
Notify_value _cgi_sigxcpu()
|
|
{
|
|
register View_surface *vwsP;
|
|
static int ocnt, gpsentsignal;
|
|
int i;
|
|
|
|
gpsentsignal = 0;
|
|
/* Receive this signal whenever kernel resets GP */
|
|
/* Must assume that all GP state has been lost for this process */
|
|
for (i = 0; i <= MAXVWS; i++)
|
|
{
|
|
vwsP = _cgi_view_surfaces[i];
|
|
if (vwsP == NULL)
|
|
continue; /* NULL view surface pointer, try next one */
|
|
if (vwsP->sunview.gp_att != (Gp1_attr *) NULL)
|
|
{
|
|
ocnt = vwsP->sunview.gp_att->resetcnt;
|
|
(void) ioctl(gp1_d(vwsP->sunview.pw->pw_pixrect)->ioctl_fd,
|
|
GP1IO_GET_RESTART_COUNT, (char *) &_cgi_state.gp1resetcnt);
|
|
if (_cgi_state.gp1resetcnt != ocnt)
|
|
{
|
|
vwsP->sunview.gp_att->resetcnt = _cgi_state.gp1resetcnt;
|
|
gpsentsignal = 1;
|
|
}
|
|
}
|
|
}
|
|
/* if SIGXCPU was not sent by the GP pass it on */
|
|
if (!gpsentsignal)
|
|
{
|
|
(void) fprintf(stderr, "SIGXCPU signal received, not as a result of the Graphics Processor restarting ... exiting.\n");
|
|
exit(1);
|
|
}
|
|
|
|
return (NOTIFY_DONE);
|
|
}
|