/* utils.c 28 April 1999 */ /* copyright 1987, 1988, 1989 Phil Andrews, Pittsburgh Supercomputing Center */ /* all rights reserved */ /* utility functions */ # include # include # include # include # include # include "defs.h" /* some include files vary in location */ #ifdef VAXC #include time static tbuffer_t time_b; #else #include #include #ifdef CRAY1 #include #endif #ifdef CRAY1 #include #endif static struct tms time_b; #endif /* Some systems don't define HZ */ #ifndef HZ #define HZ 60 #endif /* memory allocation */ void *malloc(), *realloc(); /* more globals for time info*/ static int elaps_time; /* elapsed time in seconds */ static float proc_used; /* the process time used so far in seconds */ static long etime; /* need this for VMS */ #define toint(inchar) ((int) inchar - (int) '0') #define float_size (sizeof(float)) /* more globals */ static struct one_opt *new_opt = NULL; /* put command line options here */ /* PROCEDURE DECLARATIONS */ int get_angle ( int *ptr, float *deg, double *theta ); /* and now the actual utility routines */ /* starts the clock running */ initialise_time() { (void) times(&time_b); /* void for compatibility */ #ifdef VAXC proc_used = time_b.proc_user_time * 0.01; #else proc_used = (float) (time_b.tms_utime + time_b.tms_stime) / HZ; #endif etime = time(NULL); return(1); } /* says how much we used */ write_time(pages_done) int pages_done; { char buffer[80]; times(&time_b); #ifdef VAXC proc_used = time_b.proc_user_time * 0.01 - proc_used; #else proc_used = ((float) (time_b.tms_utime + time_b.tms_stime) / HZ) - proc_used; #endif elaps_time = time(NULL) - etime; fprintf(stderr, "\nCPU time: %.2f sec., elapsed time: %d sec.", proc_used, elaps_time); #ifndef VAXC fprintf(stderr, "\n"); #endif /* and put it in the log file (if it exists) */ sprintf(buffer, "%.2f %d %d", proc_used, elaps_time, pages_done); log_line(buffer, 0, NULL, 1, 0, 3); return(1); } /* take care of necessary memory, note must clear by hand for compatibility */ unsigned char *allocate_mem(size, clear) int size, clear; { unsigned char *mem_ptr; int i; if ( !(mem_ptr = (unsigned char *) malloc(size)) ) { fprintf(stderr, "\ncouldn't allocate (%d bytes) memory !\n", size); return(NULL); } else if (clear) for (i=0; i0) && !((argv[i][0] == '-') && (argv[i][1]==flag));--i);\ if (i) { opt[(int) name_val].set = 1; switch(opt[(int) name_val].tag)\ {\ case onoff: opt[(int) name_val].val.i = 1; break;\ case integer: sscanf(&argv[i][2], "%d", &opt[(int) name_val].val.i); break;\ case real: sscanf(&argv[i][2], "%f", &opt[(int) name_val].val.r); break;\ case str: case lst:\ strncpy(opt[(int) name_val].val.str, &argv[i][2], max_str); break;}}} #define init_check(name_val, name_str, in_char, type, init) \ init_opt(name_val, name_str, in_char, type, init) check_opt(name_val, in_char) #endif static int called_before = 0; /* has this routine been called before ? */ /* VMS specifics */ #ifdef VMS /* first setup the parsing */ int GPT_COMMANDS( ); /* THE COMMAND TABLE */ int CLI$DCL_PARSE( ); /* parse the command */ int LIB$GET_INPUT( ); /* get input from the tty */ static $DESCRIPTOR(prompt, "GPT> "); /* our prompt */ int status; char option_str[max_str], *my_string(); struct dsc$descriptor_s str_desc; extern void init_defs(); /* in cgm.c */ extern int ask_device(); /* cgm.c */ option_str[0] = '\0'; str_desc.dsc$w_length = strlen(cmd_str); str_desc.dsc$a_pointer = cmd_str; str_desc.dsc$b_class = DSC$K_CLASS_S; str_desc.dsc$b_dtype = DSC$K_DTYPE_T; status = CLI$DCL_PARSE(&str_desc, &GPT_COMMANDS, &LIB$GET_INPUT, &LIB$GET_INPUT, &prompt); /* get the command */ #else int endc; if (argc <= 0) { fprintf(stderr, "usage gplot/gtex [options] input_name output_name\n"); return(0); } /* figure out if we have any file names (i.e. non - options) */ *cmd_str = '\0'; for (i=0; i0) && (argv[i][0] != '-'); --i); /* are we using stdin for input ? */ if ((argv[i][0] == '-') && (argv[i][1] == '\0')) { --i; strcpy(opt[(int) in_name].val.str, "-"); /* make it explicit */ opt[(int) in_name].set = 1; } endc = i; #endif /* actually do it, format is (enum_name, vms_name, unix_char, type, default) */ if (!called_before) { /* first time */ init_check(device, "device", 'd', str, "nodev"); init_check(diaquest, "diaquest", 'v', str, "CSA0:"); #ifdef vms init_check(lvr,"lvr",'V',str,"TTA0:"); #else init_check(lvr,"lvr",'V',str,"/dev/tty0"); #endif init_check(eject, "eject", 'E', onoff, "0"); init_check(copies, "copies", 'c', integer, "1"); init_check(debug, "debug", 'D', onoff, "0"); init_check(list, "list", 'l', onoff, "0"); init_check(pxl_in, "pxl_in", 'P', real, "0.0"); init_check(ypxl_in, "ypxl_in", 'Q', real, "0.0"); init_check(screen, "screen", 's', str, "nodev"); init_check(start, "start", 'b', integer, "0"); init_check(tty, "tty", 't', onoff, "0"); init_check(out_name, "out_name", '2', str, "foobar"); init_check(user, "username", 'u', str, "unknown"); } /* now the stuff that can be reset */ init_check(x_offset, "x_offset", 'x', real, "0.0"); init_check(y_offset, "y_offset", 'y', real, "0.0"); init_check(x_size, "x_size", 'X', real, "0.0"); init_check(y_size, "y_size", 'Y', real, "0.0"); init_check(included, "included", 'i', onoff, "0"); init_check(index_file, "index_file", 'I', onoff, "0"); init_check(degrees, "degrees", 'r', real, "0.0"); init_check(pages, "pages", 'p', lst, "*"); init_check(title_string, "title_string", 'T', str, "none"); init_check(clear_text, "clear_text", 'C', onoff, "0"); init_check(in_name, "in_name", '1', str, "foo"); init_check(text_mag, "text_mag", 'm', real, "1.0"); init_check(font_type, "font_type", 'f', integer, "0"); init_check(scale_output, "scale_output", 'S', integer, "0"); init_check(nindex, "nindex", 'N', onoff, "0"); ++called_before; /* if we're debugging, tell what options are set */ if (opt[(int) debug].set) for (i=0; i <= (int) out_name; ++i) { if (opt[i].set) { fprintf(stderr, "%s: ", opt[i].flag_str); switch (opt[i].tag) { case onoff: fprintf(stderr, "%s\n", (opt[i].val.i) ? "on" : "off"); break; case integer: fprintf(stderr, "value = %d\n", opt[i].val.i);break; case real: fprintf(stderr, "value = %f\n", opt[i].val.r);break; case str: fprintf(stderr, "value = %s\n", opt[i].val.str);break; case lst: fprintf(stderr, "value = %s\n", opt[i].val.str);break; } } } /* set the other arguments */ *to_screen = opt[(int) screen].set; *do_list = opt[(int) list].set; /* now send off info to the logging line routine */ log_line(cmd_str, argc, argv, 0, 1, 1); return(1); } /* device characteristics may be overridden by the command line */ consult_device(opt, out_info) struct info_struct *out_info; struct one_opt *opt; /* put command line options here */ /* #define may_override(name) if (opt[(int) name].set) switch (opt[(int) name].tag) { \ case integer: out_info->name = opt[(int) name].val.i; break; \ case real: out_info->name = opt[(int) name].val.r; break; \ case lst: case str: strcpy(out_info->name, opt[(int) name].val.str); break;} */ { /* and now overide the device if the command line wants us to */ /* may_override(pxl_in); may_override(ypxl_in); may_override(x_offset); may_override(y_offset); may_override(x_size); may_override(y_size); */ #ifdef VMS if (opt[(int) screen].set) { strcpy(opt[(int) out_name].val.str, "SYS$OUTPUT:"); opt[(int) out_name].set = 1; } #endif /* store pointer to option */ new_opt = opt; return(1); } /* function to set cgm status structures to their startup default values */ /* note that we do not do this at compile time because of the possibility of processing multiple cgm files. */ void s_defaults(c1, c2, c3, c5, g5, pxlvdc_in) struct mf_d_struct *c1; /* the class 1 elements */ struct pic_d_struct *c2; /* the class 2 elements */ struct control_struct *c3; /* the class 3 elements */ struct attrib_struct *c5, *g5; /* the class 5 elements */ double pxlvdc_in; /* the pxl_vdc value */ { int i, nsteps; /* and set up the initial colour table values */ #define init_csize 13 /* how many entries */ static float init_ctab[3 * init_csize] /* global memory */ = { /* my defaults */ 1.0, 1.0, 1.0, /* white */ 0.0, 0.0, 0.0, /* black */ 1.0, 0.0, 0.0, /* red */ 0.0, 1.0, 0.0, /* green */ 0.0, 0.0, 1.0, /* blue */ 1.0, 1.0, 0.0, /* yellow */ 1.0, 0.0, 1.0, /* magenta */ 0.0, 1.0, 1.0, /* cyan */ 1.0, 0.5, 0.0, /* orange */ 1.0, 0.0, 0.5, /* purple-red */ 0.5, 0.0, 1.0, /* blue-purple */ 0.5, 1.0, 0.0, /* yellow-green */ 0.0, 1.0, 0.5 /* bluish-green */ }; /* first the class1, metafile descriptor elements */ c1->vdc_type = vdc_int; c1->int_prec = 16; c1->real_prec.fixed = 1; c1->real_prec.exp = 16; c1->real_prec.fract = 16; c1->ind_prec = 16; c1->col_prec = 8; c1->col_i_prec = 8; c1->max_c_index = 63; for (i=0; i<3; ++i) { c1->c_v_extent.min[i] = 0; c1->c_v_extent.max[i] = 255; } c1->char_c_an = 0; /* now class2, the picture descriptor elements */ c2->scale_mode.s_mode = 0; c2->scale_mode.m_scaling= 0.0; c2->c_s_mode = i_c_mode; c2->l_w_s_mode = scaled; c2->m_s_s_mode = scaled; c2->e_w_s_mode = scaled; for (i=0; i<2; ++i) { c2->vdc_extent.i[i] = 0; c2->vdc_extent.r[i] = 0.0; c2->vdc_extent.i[i + 2] = 32767; c2->vdc_extent.r[i + 2] = 1.0; } c2->back_col.red = 1.0; c2->back_col.green = 1.0; c2->back_col.blue = 1.0; /* now the control elements, class 3 */ /* note that everything except vdc_extent is kept in pixel units */ c3->vdc_i_prec = 16; c3->vdc_r_prec.fixed = 1; c3->vdc_r_prec.exp = 16; c3->vdc_r_prec.fract = 16; c3->aux_col.red = 1.0; c3->aux_col.green = 1.0; c3->aux_col.blue = 1.0; c3->aux_col.ind = 0; c3->transparency = on; for (i=0; i<4; ++i) { c3->clip_rect.i[i] = pxlvdc_in * c2->vdc_extent.i[i]; c3->clip_rect.r[i] = pxlvdc_in * c2->vdc_extent.r[i]; } c3->clip_ind = on; /* class 5, the attribute elements */ c5->l_b_index = 1; c5->line_type = solid_l; c5->line_width.i = pxlvdc_in * 33; c5->line_width.r = 1.0; c5->line_colour.red = 0.0; c5->line_colour.green = 0.0; c5->line_colour.blue = 0.0; c5->line_colour.ind = 1; c5->mk_b_index = 1; c5->mk_type = 1; c5->mk_size.i = pxlvdc_in * 328;/* standard has error */ c5->mk_size.r = 1.0; c5->mk_colour.red = 0.0; c5->mk_colour.green = 0.0; c5->mk_colour.blue = 0.0; c5->mk_colour.ind = 1; c5->t_b_index = 1; c5->t_f_index = 1; c5->t_prec = string; c5->c_exp_fac = 1.0; c5->c_space = 0.0; c5->text_colour.red = 0.0; c5->text_colour.green = 0.0; c5->text_colour.blue = 0.0; c5->text_colour.ind = 1; c5->c_height = pxlvdc_in * 328; if (new_opt && (new_opt[(int) text_mag].set)) c5->c_height *= new_opt[(int) text_mag].val.r; c5->c_orient.x_up = 0; c5->c_orient.y_up = 1; c5->c_orient.x_base = 1; c5->c_orient.y_base = 0; c5->text_path = right; c5->text_align.hor = normal_h; c5->text_align.ver = normal_v; c5->text_align.cont_hor = 0.0; c5->text_align.cont_ver = 0.0; c5->c_set_index = 1; c5->a_c_set_index = 1; c5->f_b_index = 1; c5->int_style = hollow; c5->fill_colour.red = 0.0; c5->fill_colour.green = 0.0; c5->fill_colour.blue = 0.0; c5->fill_colour.ind = 1; c5->hatch_index = 1; c5->pat_index = 1; c5->e_b_index = 1; c5->edge_type = solid_l; c5->edge_width.i = pxlvdc_in * 33; c5->edge_width.r = 1.0; c5->edge_colour.red = 0.0; c5->edge_colour.green = 0.0; c5->edge_colour.blue = 0.0; c5->edge_colour.ind = 1; c5->edge_vis = off; for (i=0; i<2; ++i) { c5->fill_ref.i[i] = 0; c5->fill_ref.r[i] = 0.0; } for (i=0; i<4; ++i) { c5->pat_size.i[i] = pxlvdc_in * c2->vdc_extent.i[i]; c5->pat_size.r[i] = pxlvdc_in * c2->vdc_extent.r[i]; } /* now allocate both colour tables */ c5->ctab = (float *) allocate_mem((c1->max_c_index + 1) * 3 * float_size, 1); g5->ctab = (float *) allocate_mem((c1->max_c_index + 1) * 3 * float_size, 1); /* and fill them in with the defaults */ for (i = 0; (i< (3 * init_csize)) && (i< 3*(c1->max_c_index + 1)); ++i) *(g5->ctab + i) = *(c5->ctab + i) = init_ctab[i]; nsteps = (c1->max_c_index + 1 - init_csize) / 3; if (nsteps <= 0) { (void) fprintf(stderr, "illegal nsteps %d\n", nsteps); return; } for (i = 3 * init_csize; i < 3 * (init_csize + nsteps); i+=3) { *(g5->ctab + i) = *(c5->ctab + i) = (float) (i - 3 * init_csize)/ (3 * nsteps); *(g5->ctab + i + 1) = *(c5->ctab + i + 1) = 0.0; *(g5->ctab + i + 2) = *(c5->ctab + i + 2) = 0.0; } for (i = 3 * (init_csize + nsteps); i < 3 * (init_csize + 2 * nsteps); i+=3) { *(g5->ctab + i) = *(c5->ctab + i) = 0.0; *(g5->ctab + i + 1) = *(c5->ctab + i + 1) = (float) (i - 3 * (init_csize + nsteps))/ (3 * nsteps); *(g5->ctab + i + 2) = *(c5->ctab + i + 2) = 0.0; } for (i = 3 * (init_csize + 2 * nsteps); i <= 3 * c1->max_c_index; i+=3) { *(g5->ctab + i) = *(c5->ctab + i) = 0.0; *(g5->ctab + i + 1) = *(c5->ctab + i + 1) = 0.0; *(g5->ctab + i + 2) = *(c5->ctab + i + 2) = (float) (i - 3 * (init_csize + 2 * nsteps)) / (3 * (c1->max_c_index - (init_csize + 2 * nsteps))); } /* pattern, bundle tables later */ } /* function to reset cgm status structures to the correct default values (preumably at the beginning of a new page). The cn variables are the ones to be set, the dn are defaults that may have been changed by a metafile defaults replacement element. */ void rs_defaults(c1, c2, c3, c5, d2, d3, d5, pxlvdc_in) struct mf_d_struct *c1; /* the class 1 elements */ struct pic_d_struct *c2, *d2; /* the class 2 elements */ struct control_struct *c3, *d3; /* the class 3 elements */ struct attrib_struct *c5, *d5; /* the class 5 elements */ double pxlvdc_in; /* the pxl_vdc value */ { int i; double vdc_long, vdc_try; /* first class2, the picture descriptor elements */ c2->scale_mode.s_mode = d2->scale_mode.s_mode; c2->scale_mode.m_scaling= d2->scale_mode.m_scaling; c2->c_s_mode = d2->c_s_mode; c2->l_w_s_mode = d2->l_w_s_mode; c2->m_s_s_mode = d2->m_s_s_mode; c2->e_w_s_mode = d2->e_w_s_mode; for (i=0; i<2; ++i) { c2->vdc_extent.i[i] = d2->vdc_extent.i[i]; c2->vdc_extent.r[i] = d2->vdc_extent.r[i]; c2->vdc_extent.i[i + 2] = d2->vdc_extent.i[i + 2]; c2->vdc_extent.r[i + 2] = d2->vdc_extent.r[i + 2]; } c2->back_col.red = d2->back_col.red; c2->back_col.green = d2->back_col.green; c2->back_col.blue = d2->back_col.blue; /* now the control elements, class 3 */ c3->vdc_i_prec = d3->vdc_i_prec; c3->vdc_r_prec.fixed = d3->vdc_r_prec.fixed; c3->vdc_r_prec.exp = d3->vdc_r_prec.exp; c3->vdc_r_prec.fract = d3->vdc_r_prec.fract; c3->aux_col.red = d3->aux_col.red; c3->aux_col.green = d3->aux_col.green; c3->aux_col.blue = d3->aux_col.blue; c3->aux_col.ind = d3->aux_col.ind; c3->transparency = d3->transparency; for (i=0; i<4; ++i) { c3->clip_rect.i[i] = d3->clip_rect.i[i]; c3->clip_rect.r[i] = d3->clip_rect.r[i]; } c3->clip_ind = d3->clip_ind; /* class 5, the attribute elements */ /* these include some that depend on earlier defaults, so first: */ switch (c1->vdc_type) { case vdc_int: vdc_long = abs(d2->vdc_extent.i[2] - d2->vdc_extent.i[0]); vdc_try = abs(d2->vdc_extent.i[3] - d2->vdc_extent.i[1]); break; case vdc_real: vdc_long = fabs(d2->vdc_extent.r[2] - d2->vdc_extent.r[0]); vdc_try = fabs(d2->vdc_extent.r[3] - d2->vdc_extent.r[1]); break; } vdc_long = (vdc_long >= vdc_try) ? vdc_long : vdc_try; /* longest side */ /* now make the setting */ c5->l_b_index = d5->l_b_index; c5->line_type = d5->line_type; c5->line_width.i = pxlvdc_in * vdc_long / 1000 + 0.5; c5->line_width.r = d5->line_width.r; c5->line_colour.red = d5->line_colour.red; c5->line_colour.green = d5->line_colour.green; c5->line_colour.blue = d5->line_colour.blue; c5->line_colour.ind = d5->line_colour.ind; c5->mk_b_index = d5->mk_b_index; c5->mk_type = d5->mk_type; c5->mk_size.i = pxlvdc_in * vdc_long / 100 + 0.5; c5->mk_size.r = d5->mk_size.r; c5->mk_colour.red = d5->mk_colour.red; c5->mk_colour.green = d5->mk_colour.green; c5->mk_colour.blue = d5->mk_colour.blue; c5->mk_colour.ind = d5->mk_colour.ind; c5->t_b_index = d5->t_b_index; c5->t_f_index = d5->t_f_index; c5->t_prec = d5->t_prec; c5->c_exp_fac = d5->c_exp_fac; c5->c_space = d5->c_space; c5->text_colour.red = d5->text_colour.red; c5->text_colour.green = d5->text_colour.green; c5->text_colour.blue = d5->text_colour.blue; c5->text_colour.ind = d5->text_colour.ind; c5->c_height = pxlvdc_in * vdc_long / 100 + 0.5; if (new_opt && (new_opt[(int) text_mag].set)) c5->c_height *= new_opt[(int) text_mag].val.r; c5->c_orient.x_up = d5->c_orient.x_up; c5->c_orient.y_up = d5->c_orient.y_up; c5->c_orient.x_base = d5->c_orient.x_base; c5->c_orient.y_base = d5->c_orient.y_base; c5->text_path = d5->text_path; c5->text_align.hor = d5->text_align.hor; c5->text_align.ver = d5->text_align.ver; c5->text_align.cont_hor = d5->text_align.cont_hor; c5->text_align.cont_ver = d5->text_align.cont_ver; c5->c_set_index = d5->c_set_index; c5->a_c_set_index = d5->a_c_set_index; c5->f_b_index = d5->f_b_index; c5->int_style = d5->int_style; c5->fill_colour.red = d5->fill_colour.red; c5->fill_colour.green = d5->fill_colour.green; c5->fill_colour.blue = d5->fill_colour.blue; c5->fill_colour.ind = d5->fill_colour.ind; c5->hatch_index = d5->hatch_index; c5->pat_index = d5->pat_index; c5->e_b_index = d5->e_b_index; c5->edge_type = d5->edge_type; c5->edge_width.i = pxlvdc_in * vdc_long / 1000 + 0.5; c5->edge_width.r = d5->edge_width.r; c5->edge_colour.red = d5->edge_colour.red; c5->edge_colour.green = d5->edge_colour.green; c5->edge_colour.blue = d5->edge_colour.blue; c5->edge_colour.ind = d5->edge_colour.ind; c5->edge_vis = d5->edge_vis; for (i=0; i<2; ++i) { c5->fill_ref.i[i] = d5->fill_ref.i[i]; c5->fill_ref.r[i] = d5->fill_ref.r[i]; } for (i=0; i<4; ++i) { c5->pat_size.i[i] = d5->pat_size.i[i]; c5->pat_size.r[i] = d5->pat_size.r[i]; } for (i = 0; i< 3 * (c1->max_c_index + 1); ++i) *(c5->ctab + i) = *(d5->ctab + i); /* tables later */ } /* begin VMS only stuff here, this could all be removed under UNIX */ /* use a VAXC flag since may use these on VMS but with VMS undefined */ #ifdef VAXC #include rms #include ssdef /* systems services commands */ #include climsgdef /* CLI interface */ /* this from the old trn.h file */ #define LNM$_STRING 2 #define LNM$M_CASE_BLIND 33554432 static int lnm_attr = LNM$M_CASE_BLIND; /* this is from the old jbc.h file */ #define SJC$_ADD_FILE 2 #define SJC$_CLOSE_JOB 9 #define SJC$_CREATE_JOB 10 #define SJC$_DELETE_FILE 24 #define SJC$_FILE_SPECIFICATION 42 #define SJC$_JOB_NAME 79 #define SJC$_JOB_STATUS_OUTPUT 88 #define SJC$_NOTIFY 108 #define SJC$_QUEUE 134 /* more globals */ static char global_string[max_str]; #define max_no_items 5 #define first_flag 1 #define second_flag 14 struct one_item { unsigned short buffer_length; unsigned short item_code; char *buffer_address; int *return_length_address; }; struct my_struct { unsigned short s_length; /* ASCIID */ char flag2; char flag1; char *s_ptr; }; static struct one_item item_array[max_no_items]; static struct my_struct t_name, l_name; /* checks to see if the argument is present on the command line */ my_present(in_string) char *in_string; { int ret = 0; /* in VMS use the CLI interface provided */ int CLI$PRESENT( ), LIB$SIG_TO_RET(); struct dsc$descriptor_s name_desc; name_desc.dsc$w_length = strlen(in_string); name_desc.dsc$a_pointer = in_string; name_desc.dsc$b_class = DSC$K_CLASS_S; name_desc.dsc$b_dtype = DSC$K_DTYPE_T; /* don't bother with error trapping, presume right .cld file linked */ ret = CLI$PRESENT(&name_desc); return(ret); } char *my_string(in_string) char *in_string; { #define c_length 128 int CLI$GET_VALUE( ); char out_string[c_length]; struct dsc$descriptor_s name_desc, out_desc; short str_l; int ret, ret_value, i; for (i=0; i= max_str){ fprintf(stderr, "\nlogical string too long, %d > %d", n_chars, max_str); n_chars = max_str - 1; } trans_name[n_chars] = '\0'; if (result != SS$_NORMAL) return(0); else return(result); } /* utility to create a VMS logical */ make_lnm(log_name, tab_name, trans_name) char *log_name, /* the logical to be translated */ *tab_name, /* the logical name table to use */ *trans_name; /* what name to translate to */ { int result, item_no = 0, n_chars = 0, acmode = 0, attr = 0; l_name.s_length = strlen(log_name); l_name.flag2 = second_flag; l_name.flag1 = first_flag; l_name.s_ptr = log_name; t_name.s_length = strlen(tab_name); t_name.flag2 = second_flag; t_name.flag1 = first_flag; t_name.s_ptr = tab_name; item_array[item_no].buffer_length = strlen(trans_name); item_array[item_no].item_code = LNM$_STRING; item_array[item_no].buffer_address = trans_name; item_array[item_no].return_length_address = &n_chars; ++item_no; item_array[item_no].item_code = 0; item_array[item_no].buffer_length = 0; result = sys$crelnm(&attr,&t_name, &l_name, 0,item_array); if (result != SS$_NORMAL) { if (new_opt && (new_opt[(int) debug].set)) LIB$SIGNAL(result); else return(0); } else return(result); } /* create a job in the specified VMS queue */ static int delete_files; create_job(queue_name, job_name, notify, do_delete) char *queue_name, *job_name; int notify, do_delete; { int item_no = 0, result; delete_files = do_delete; item_array[item_no].item_code = SJC$_QUEUE; item_array[item_no].buffer_length = strlen(queue_name); item_array[item_no].buffer_address = queue_name; item_array[item_no].return_length_address = 0; ++item_no; item_array[item_no].item_code = SJC$_JOB_NAME; item_array[item_no].buffer_length = strlen(job_name); item_array[item_no].buffer_address = job_name; item_array[item_no].return_length_address = 0; if (notify) { ++item_no; item_array[item_no].item_code = SJC$_NOTIFY; item_array[item_no].buffer_length = 0; item_array[item_no].buffer_address = 0; item_array[item_no].return_length_address = 0; } ++item_no; item_array[item_no].item_code = 0; result = sys$sndjbc(0,SJC$_CREATE_JOB,0,item_array,0,0,0); if (result != SS$_NORMAL) { fprintf(stderr, "\nproblem with create_job for queue %s,SNDJBC = %d", queue_name, result); LIB$SIGNAL(result); } return(result); } /* adds a file to the VMS queue */ add_file(file_name, deletable) char *file_name; int deletable; { int item_no = 0, result; item_array[item_no].item_code = SJC$_FILE_SPECIFICATION; item_array[item_no].buffer_length = strlen(file_name); item_array[item_no].buffer_address = file_name; item_array[item_no].return_length_address = 0; if ( (delete_files) && (deletable) ) { ++item_no; item_array[item_no].item_code = SJC$_DELETE_FILE; item_array[item_no].buffer_length = 0; item_array[item_no].buffer_address = 0; item_array[item_no].return_length_address = 0; } ++item_no; item_array[item_no].item_code = 0; result = sys$sndjbc(0,SJC$_ADD_FILE,0,item_array,0,0,0); if (result != SS$_NORMAL) fprintf(stderr, "\nproblem with adding %s, SNDJBC = %d",file_name, result); return(result); } /* closes a VMS queue job */ /* NOTE!!! we are asking for a status return to be written into job_msg this can be very DANGEROUS!!! there appears to be a time lag between return from the sndjbc call and the actual writing, if job_msg was a local variable it might not get written into until the subroutine had returned, with highly unpredictable and dangerous results. Thus we must make it a global variable, wait for a while and check for success. Note that I wait for a maximum of 5 seconds, rather than calling $SYNCH, which might wait for ever, or might not work, just as sys$sndjbcw doesn't work */ close_job(queue_name, job_msg, msg_length, n_chars, out_name) char *queue_name, *job_msg, out_name; int msg_length, *n_chars; { int result, item_no = 0, i; *n_chars = 0; item_array[item_no].buffer_length = msg_length; item_array[item_no].item_code = SJC$_JOB_STATUS_OUTPUT; item_array[item_no].buffer_address = job_msg; item_array[item_no].return_length_address = n_chars; ++item_no; item_array[item_no].item_code = 0; result = sys$sndjbc(0,SJC$_CLOSE_JOB,0,item_array,0,0,0); if (result != SS$_NORMAL) LIB$SIGNAL(result); for (i=0; (i<5) && (*n_chars==0); ++i) sleep(1); if ( (*n_chars > 0) && (*n_chars <= msg_length) ) { job_msg[*n_chars] = '\0'; fprintf(stderr, "\n%s", job_msg); } else fprintf(stderr, "\ncouldn't communicate with %s, output in %s", queue_name, out_name); return(result); } /* look for a default name for GTEX to start up with */ try_def_name(file_name) char *file_name; { char input_name[max_str]; if (translate("TEX$OUTPUT", "LNM$FILE_DEV", input_name) & 1) strcpy(file_name, input_name); return(1); } make_name(new_bits, def_bits, resultant, size, out_file) char *new_bits, *def_bits, *resultant; int size, out_file; /* if out_file, the file to be opened is an output one, don't want old area */ { struct FAB mfb; struct NAM mnb; #define b_size 128 char str_buffer[b_size + 1]; int rms_status; extern int SYS$PARSE(); mfb = cc$rms_fab; mnb = cc$rms_nam; mfb.fab$l_dna = def_bits; mfb.fab$b_dns = strlen(def_bits); mfb.fab$l_fna = new_bits; mfb.fab$b_fns = strlen(new_bits); mfb.fab$l_nam = &mnb; /* name block */ mnb.nam$b_nop = NAM$M_SYNCHK; mnb.nam$l_esa = str_buffer; mnb.nam$b_ess = b_size; rms_status = SYS$PARSE(&mfb); if (out_file) { strncpy(resultant, mnb.nam$l_name, (int) mnb.nam$b_name + (int) mnb.nam$b_type); resultant[mnb.nam$b_name + mnb.nam$b_type] = '\0'; } else { strncpy(resultant, str_buffer, (int) mnb.nam$b_esl); resultant[mnb.nam$b_esl] = '\0'; } return(rms_status); } #endif /* this should come at the very end of the file */ /* utility routine to see if a file exists */ find_file(fname) char *fname; { #ifdef VAXC int LIB$FIND_FILE(), LIB$FIND_FILE_END(), i, ret, user_flags, context, stv_addr, LIB$SIGNAL(), j, rb; struct dsc$descriptor_s out_desc, rel_desc, name_desc; char out_name[max_str], rel_name[max_str]; name_desc.dsc$a_pointer = fname; name_desc.dsc$w_length = strlen(fname); name_desc.dsc$b_class = DSC$K_CLASS_S; name_desc.dsc$b_dtype = DSC$K_DTYPE_T; out_desc.dsc$a_pointer = out_name; out_desc.dsc$w_length = (sizeof out_name) - 1; out_desc.dsc$b_class = DSC$K_CLASS_S; out_desc.dsc$b_dtype = DSC$K_DTYPE_T; rel_desc.dsc$a_pointer = rel_name; rel_desc.dsc$w_length = 0; rel_desc.dsc$b_class = DSC$K_CLASS_S; rel_desc.dsc$b_dtype = DSC$K_DTYPE_T; user_flags = 0; /* allow wild cards and memory */ context = 0; ret = LIB$FIND_FILE(&name_desc, &out_desc, &context, 0, &rel_desc, &stv_addr, &user_flags); if ( (ret == RMS$_NMF) && (ret == RMS$_NORMAL) ) LIB$FIND_FILE_END(&context); /* recover memory */ return(ret == RMS$_NORMAL); #endif return (1); } /* utility routine to find all possible magnifications for pk files */ find_mags(poss_mags, max_mags, exp_str, fname) int *poss_mags, max_mags; char *exp_str, *fname; { int no_mags, i; char dir_str[max_str]; #ifdef VAXC int LIB$FIND_FILE(), LIB$FIND_FILE_END(), ret, user_flags, context, stv_addr, LIB$SIGNAL(), j, rb; struct dsc$descriptor_s out_desc, rel_desc, name_desc; char out_name[max_str], rel_name[max_str]; /* create the name we want to look for */ sprintf(dir_str, "%s*]%s.pk;", exp_str, fname); name_desc.dsc$a_pointer = dir_str; name_desc.dsc$w_length = strlen(dir_str); name_desc.dsc$b_class = DSC$K_CLASS_S; name_desc.dsc$b_dtype = DSC$K_DTYPE_T; out_desc.dsc$a_pointer = out_name; out_desc.dsc$w_length = (sizeof out_name) - 1; out_desc.dsc$b_class = DSC$K_CLASS_S; out_desc.dsc$b_dtype = DSC$K_DTYPE_T; rel_desc.dsc$a_pointer = rel_name; rel_desc.dsc$w_length = 0; rel_desc.dsc$b_class = DSC$K_CLASS_S; rel_desc.dsc$b_dtype = DSC$K_DTYPE_T; user_flags = 0; /* allow wild cards and memory */ context = 0; no_mags = 0; while ((RMS$_NORMAL == ( ret = LIB$FIND_FILE(&name_desc, &out_desc, &context, 0, &rel_desc, &stv_addr, &user_flags))) && (no_mags0) && (out_name[j]!=']'); --j); rb = j = j - 1; for (;(j>0) && (out_name[j] >= '0') && (out_name[j] <= '9'); --j); if ((j > 0) && (j < rb)) { sscanf(out_name + j + 1, "%d", poss_mags + no_mags); ++no_mags; } } if ( (ret != RMS$_NMF) && (ret != RMS$_NORMAL) ) { return(0); } LIB$FIND_FILE_END(&context); /* recover memory */ /* now take care of the UNIX stuff */ #else #define b_size 256 FILE *popen(), *p_ptr; char c, in_buffer[b_size + 1], *b_ptr; /* create the name we want to look for */ sprintf(dir_str, "ls %s/*/%s.pk", exp_str, fname); p_ptr = popen(dir_str, "r"); /* now look for possible files */ no_mags = 0; if (p_ptr) { while (fgets(in_buffer, b_size, p_ptr) && (no_mags= in_buffer) && (*b_ptr != '/')) --b_ptr; /* now another */ --b_ptr; while ((b_ptr >= in_buffer) && (*b_ptr != '/')) --b_ptr; ++b_ptr; /* forward one char */ if (sscanf(b_ptr, "%d", poss_mags + no_mags)) ++no_mags; else fprintf(stderr, "couldn't parse %s\n", in_buffer); } pclose(p_ptr); } else { /* try this */ *poss_mags = 1000; no_mags = 1; } #undef b_size #endif poss_mags[no_mags] = 0; if (new_opt && (new_opt[(int) debug].set)) { fprintf(stderr, "%s poss mags", fname); for (i=0; (i < no_mags) && poss_mags[i]; ++i) fprintf(stderr, ", %d", poss_mags[i]); fputc('\n', stderr); } return(no_mags); } /* function to return index of closest match to argument in array */ /* assume 0 is not a possibility */ find_best(want, have, no_have) int want, no_have, have[]; { int i, mag_dif, best_so_far; mag_dif = 0; for (i=0; i=0) { *deg = *theta = 0.0; } else { *deg = 180.0; *theta = pi; } return(2); } dx = (double) ptr[0]; dy = (double) ptr[1]; *theta = atan2(dy, dx); *deg = 180.0 * (*theta / pi); return(1); } /* function to return cos and sin corr. to x and y components */ angle_str(ctheta, stheta, y_comp, x_comp) double *ctheta, *stheta; int y_comp, x_comp; { double hypotenuse, sqrt(); if (!(y_comp || x_comp)) return(0); /* unknown */ if (!x_comp) { *ctheta = 0.0; if (y_comp > 0) *stheta = 1.0; else *stheta = -1.0; return(1); } if (!y_comp) { *stheta = 0.0; if (x_comp > 0) *ctheta = 1.0; else *ctheta = -1.0; return(1); } hypotenuse = y_comp * y_comp + x_comp * x_comp; hypotenuse = sqrt(hypotenuse); *ctheta = x_comp / hypotenuse; *stheta = y_comp / hypotenuse; return(1); } /* function to fill out the correct offsets */ get_offsets(dx, dy, ctheta1, stheta1, ctheta2, stheta2, text_align, ht, wd, path) int *dx, *dy, ht, wd; double ctheta1, stheta1, ctheta2, stheta2; struct align_struct *text_align; enum path_enum path; { int x_sz, y_sz; switch (text_align->ver) { case normal_v: switch (path) { case right: *dy = 0; break; case left: *dy = 0; break; case up: *dy = 0; break; case down: *dy = 0; break; } break; case top_v: *dy = -1.1 * ht * stheta2; break; case cap_v: *dy = ht; break; case half_v: *dy = -0.5 * ht * stheta2; break; case base_v: *dy = 0; break; case bottom_v: *dy = 0.1 * ht * stheta2; break; case cont_v: *dy = 0; break; } /* now add on x component */ /* *dy -= wd * stheta1; */ switch (text_align->hor) { case normal_h: switch (path) { case right: *dx = 0; break; case left: *dx = 0; break; case up: case down: *dx = -wd * 0.5 * ctheta1; break; } break; case left_h: *dx = 0; break; case center_h: *dx = -0.5 * wd * ctheta1; break; case right_h: *dx = -wd * ctheta1; break; case cont_h: *dx = 0; break; } return(1); } /* function to do any smart type things necessary to get the device ready */ void get_smart(started, gsptr1, gsptr2, opt, dev_info, cosr, sinr, pxl_vdc, xoffset, yoffset, xp0, yp0, xsize, ysize, font_check, font_text, sx, sy) int started; struct mf_d_struct *gsptr1; /* the class 1 element pointer */ struct pic_d_struct *gsptr2; /* the class 2 element pointer */ struct one_opt *opt; /* the command line options, in only */ struct info_struct *dev_info; /* device info to fill out, out only */ double *cosr, *sinr, *pxl_vdc, *sx, *sy; int *xoffset, *yoffset, *xsize, *ysize; float *xp0, *yp0; int (**font_check)(), (**font_text)(); { float vdc_y, vdc_x; double fabs(), cos(), sin(); float vdc_w, vdc_h, x_scale, y_scale, pi; double theta; float dev_ht, dev_wd; /* the device parameters */ double in_vdc; /* conversion from VDC units to inches */ extern int ca_check(), ca_text(), hl_check(), hl_text(); /* font routines */ float bl_x, bl_y; /* bottom left x and y co-ords */ char *namptr = NULL; int to_cgm = 0; /* get the device and VDC sizes */ dev_wd = dev_info->x_size; dev_ht = dev_info->y_size; /* now sort out the vdc dimensions */ switch (gsptr1->vdc_type) { case vdc_int: if (gsptr2->vdc_extent.i[2] > gsptr2->vdc_extent.i[0]) { vdc_x = gsptr2->vdc_extent.i[2] - gsptr2->vdc_extent.i[0]; bl_x = gsptr2->vdc_extent.i[0]; *sx = 1.0; } else { vdc_x = gsptr2->vdc_extent.i[0] - gsptr2->vdc_extent.i[2]; bl_x = gsptr2->vdc_extent.i[2]; *sx = -1.0; } if (gsptr2->vdc_extent.i[3] > gsptr2->vdc_extent.i[1]) { vdc_y = gsptr2->vdc_extent.i[3] - gsptr2->vdc_extent.i[1]; bl_y = gsptr2->vdc_extent.i[1]; *sy = 1.0; } else { vdc_y = gsptr2->vdc_extent.i[1] - gsptr2->vdc_extent.i[3]; bl_y = gsptr2->vdc_extent.i[1]; *sy = -1.0; } break; case vdc_real: if (gsptr2->vdc_extent.r[2] > gsptr2->vdc_extent.r[0]) { vdc_x = gsptr2->vdc_extent.r[2] - gsptr2->vdc_extent.r[0]; bl_x = gsptr2->vdc_extent.r[0]; *sx = 1.0; } else { vdc_x = gsptr2->vdc_extent.r[0] - gsptr2->vdc_extent.r[2]; bl_x = gsptr2->vdc_extent.r[2]; *sx = -1.0; } if (gsptr2->vdc_extent.r[3] > gsptr2->vdc_extent.r[1]) { vdc_y = gsptr2->vdc_extent.r[3] - gsptr2->vdc_extent.r[1]; bl_y = gsptr2->vdc_extent.r[1]; *sy = 1.0; } else { vdc_y = gsptr2->vdc_extent.r[1] - gsptr2->vdc_extent.r[3]; bl_y = gsptr2->vdc_extent.r[1]; *sy = -1.0; } break; default: (void) fprintf(stderr, "illegal vdc_type = %d\n",gsptr1->vdc_type); } /* now take care of centering, etc */ if ( (!opt[(int) degrees].set) /* didn't specify a rotation */ && (dev_info->capability & port_land)/* can rotate page */ && (!opt[(int) screen].set) /* not on a screen */ && (!opt[(int) included].set) /* not included */ && ( ( (vdc_x > vdc_y) /* wide image */ && (dev_wd < dev_ht)) /* narrow page */ || ( (vdc_x < vdc_y) /* narrow image */ && (dev_wd > dev_ht)) /* wide page */ ) ) { opt[(int) degrees].val.r = 90.0; /* rotate it for the user */ opt[(int) degrees].set = 1; } if (opt[(int) degrees].set) { /* specified/given a rotation */ pi = 4. * atan(1.0); theta = pi * opt[(int) degrees].val.r / 180.0 ; *cosr = cos(theta); *sinr = sin(theta); } else { /* standard */ *cosr = 1.0; *sinr = 0.0; } /* these are the real height and width of the vdc image */ vdc_w = fabs(vdc_x * (*cosr)) + fabs(vdc_y * (*sinr)); vdc_h = fabs(vdc_x * (*sinr)) + fabs(vdc_y * (*cosr)); /* now figure out the scaling */ if ((gsptr2->scale_mode.s_mode == 1) && /* metric scaling */ !opt[(int) scale_output].set) { /* not overridden */ in_vdc = gsptr2->scale_mode.m_scaling / 25.4; x_scale = y_scale = in_vdc; *pxl_vdc = dev_info->pxl_in * in_vdc; *xsize = ((dev_wd * dev_info->pxl_in) < (*pxl_vdc * vdc_w)) ? dev_wd * dev_info->pxl_in : *pxl_vdc * vdc_w; *ysize = ((dev_ht * dev_info->ypxl_in) < (*pxl_vdc * vdc_h)) ? dev_ht * dev_info->ypxl_in : *pxl_vdc * vdc_h; } else { x_scale = dev_wd / vdc_w; y_scale = dev_ht / vdc_h; /* which is the smallest ? */ if (x_scale < y_scale) { *xsize = dev_wd * dev_info->pxl_in; *ysize = dev_ht * (x_scale / y_scale) * dev_info->ypxl_in; in_vdc = y_scale = x_scale; } else { *xsize = dev_wd * (y_scale / x_scale) * dev_info->pxl_in; *ysize = dev_ht * dev_info->ypxl_in; in_vdc = x_scale = y_scale; } *pxl_vdc = dev_info->pxl_in * in_vdc; } if (!started) return; /* get the origin to the right place */ if ((*cosr >= 0.0) && (*sinr >= 0.0)) { *xoffset = dev_info->pxl_in * in_vdc * vdc_y * (*sinr); *yoffset = 0.0; } else if ((*cosr < 0.0) && (*sinr >= 0.0)) { *xoffset = dev_info->pxl_in * in_vdc * (vdc_y * (*sinr) - vdc_x * (*cosr)); *yoffset = - dev_info->ypxl_in * in_vdc * vdc_x * (*cosr); } else if ((*cosr < 0.0) && (*sinr < 0.0)) { *xoffset = - dev_info->pxl_in * in_vdc * vdc_x * (*cosr); *yoffset = - dev_info->ypxl_in * in_vdc * (vdc_x * (*sinr) + vdc_y * (*cosr)); } else if ((*cosr >= 0.0) && (*sinr < 0.0)) { *xoffset = 0.0; *yoffset = - dev_info->ypxl_in * in_vdc * vdc_x * (*sinr); } if (!gsptr2->scale_mode.s_mode && !opt[(int) degrees].set) { *xoffset = (dev_wd - vdc_x * in_vdc) * dev_info->pxl_in / 2; } /* fix later PLA */ /* and add any externally required offsets */ *xoffset += dev_info->pxl_in * dev_info->x_offset; *yoffset += dev_info->ypxl_in * dev_info->y_offset; /* may be able to do some stuff at device level */ /* if we're going to another cgm file, no internal offsets */ if (opt[(int) device].set) namptr = opt[(int) device].val.str; else if (opt[(int) screen].set) namptr = opt[(int) screen].val.str; to_cgm = namptr && ((*namptr == 'C') || (*namptr == 'c')) && ((namptr[1] == 'G') || (namptr[1] == 'g')) && ((namptr[2] == 'M') || (namptr[2] == 'm')); if (to_cgm) { /* pass everything thru */ *xp0 = 0; *yp0 = 0; *sx = 1.0; *sy = 1.0; *pxl_vdc = (gsptr1->vdc_type == vdc_int) ? 1.0 : 32767.0 / dev_wd; } else if (dev_info->capability & arb_trans) { /* device can do it */ *xp0 = - *pxl_vdc * bl_x; *yp0 = - *pxl_vdc * bl_y; } else { *xp0 = *xoffset - *pxl_vdc * bl_x; *yp0 = *yoffset - *pxl_vdc * bl_y; } if (dev_info->capability & arb_rot){ /* device can do any rotn */ *cosr = 1.0; *sinr = 0.0; } else if ((dev_info->capability & port_land) && (opt[(int) degrees].val.r < 91.0) && (opt[(int) degrees].val.r > 89.0)) { /* this only */ *cosr = 1.0; *sinr = 0.0; *xp0 = - *pxl_vdc * bl_y + dev_info->pxl_in * dev_info->x_offset; *yp0 = - *pxl_vdc * bl_x + dev_info->ypxl_in * dev_info->y_offset; } /* now take care of the font functions */ #ifdef incpkras /* linked with pk fonts */ if (opt[(int) font_type].set && (opt[(int) font_type].val.i == 2)) { *font_check = ca_check; *font_text = ca_text; } #endif #ifdef inchershey /* linked with hershey fonts */ if ((opt[(int) font_type].set && (opt[(int) font_type].val.i == 1)) || (new_opt && !new_opt[(int) font_type].set)) { *font_check = hl_check; *font_text = hl_text; } #endif return; } /* handle clipping (very simpleminded) */ int uclip(xin, yin, clip_rect) int *xin, *yin, *clip_rect; { if ((*xin - clip_rect[0]) * (*xin - clip_rect[2]) > 0) { /* needs clipping */ *xin = ((*xin - clip_rect[0]) * (*xin - clip_rect[0]) < (*xin - clip_rect[2]) * (*xin - clip_rect[2])) ? clip_rect[0] : clip_rect[2]; } if ((*yin - clip_rect[1]) * (*yin - clip_rect[3]) > 0) { /* needs clipping */ *yin = ((*yin - clip_rect[1]) * (*yin - clip_rect[1]) < (*yin - clip_rect[3]) * (*yin - clip_rect[3])) ? clip_rect[1] : clip_rect[3]; } return 1; }