/* @(#)aglinit.c 17.1.1.1 (ES0-DMD) 01/25/02 17:33:35 */ /*=========================================================================== Copyright (C) 1995 European Southern Observatory (ESO) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, MA 02139, USA. Corresponding concerning ESO-MIDAS should be addressed as follows: Internet e-mail: midas@eso.org Postal address: European Southern Observatory Data Management Division Karl-Schwarzschild-Strasse 2 D 85748 Garching bei Muenchen GERMANY ===========================================================================*/ /* @(#)aglinit.c 17.1.1.1 (OAA-ASTRONET) 01/25/02 17:33:35 */ /* * HEADER : aglinit.c - Vers 3.6.004 - Sep 1994 - L. Fini, OAA * - Vers 3.6.003 - Aug 1994 - L. Fini, OAA * - Vers 3.6.002 - Feb 1994 - L. Fini, OAA * - Vers 3.6.001 - Sep 1993 - L. Fini, OAA * - Vers 3.6.000 - Oct 1991 - L. Fini, OAA */ /* AGL INITIALIZATIONS ROUTINES */ /* PLUS SOME TIME CRITICAL FUNCTIONS */ #include #include /* AGL STATUS DEFINITION */ int AGL_wasinit=0x00; /* AGL initialization status */ struct AGL_STATUS AGL_status; FILE *AGL_err=NULL; /* Error output file (or stderr) */ /**************************************/ /* MISCELLANEOUS VARIABLES */ int AGL_DEBUG = FALSE; /* Debugging flag */ #ifndef NO_METAFILE_SUPPORT char *AGL_mfhead = MFHEAD; #endif static char *err_stack[ERRSTACKLNG]; /* Routine names stack */ static int stack_pointer; /* Stack pointer */ static int scan_pointer; void AGL_push(name) /* Push a routine name into stack */ /* N.B.: Only the pointer is pushed, */ /* So the string name must be static */ char *name; { if(stack_pointer0) stack_pointer--; scan_pointer=stack_pointer; } char *AGL_top() /* Returns topmost name from stack */ /* Stack is not modified */ { scan_pointer=stack_pointer; if(stack_pointer>0) return err_stack[stack_pointer-1]; else return NULL; } char *AGL_scan() /* returns names from stack in */ /* reverse order, one for each call */ /* The routine is reset with a call */ /* to any stack manipulation routine */ { if(scan_pointer>0) return err_stack[--scan_pointer]; else { scan_pointer=stack_pointer; return NULL; } } /****************************************************************************/ /* setdev (Internal AGL use) */ /* set up the driver entry point table for a single device */ static void setdev(dvnam,curs,eras,escp,init,send,term,poly) char *dvnam; /* Driver name */ int (*curs)(),(*eras)(),(*escp)(); /* Driver entry points */ int (*init)(),(*send)(); int (*term)(),(*poly)(); { if (AGL_status.ndevs < NDRIVERS) { strcpy(AGL_status.drvname[AGL_status.ndevs],dvnam); AGL_status.drvtab[AGL_status.ndevs][0] = curs; AGL_status.drvtab[AGL_status.ndevs][1] = eras; AGL_status.drvtab[AGL_status.ndevs][2] = escp; AGL_status.drvtab[AGL_status.ndevs][3] = init; AGL_status.drvtab[AGL_status.ndevs][4] = send; AGL_status.drvtab[AGL_status.ndevs][5] = term; AGL_status.drvtab[AGL_status.ndevs][6] = poly; AGL_status.ndevs++; AGL_status.errstat=AGLNOERR; } else AGL_status.errstat= DEVOVFSEV; } #define DEF(e1) extern void e1() #include "aglddef.c" /*****************************************************************************/ /* AGL_term (AGL internal use) */ /* Reset AGL status */ void AGL_term() { int i; void AGL_fvwp(); AGL_vflsh(); /* Empty viewport buffer */ for(i = 0;imetafile!=NULL)/* Close metafile */ fclose((AGL_status.vwpts[i])->metafile); #endif AGL_fvwp(i); /* Free viewport dynamic block */ } for(i = 0; i 0) AGL_dstop(i); /* stop device */ if ( AGL_err != stderr ) fclose(AGL_err); /* Close error stream */ } /*****************************************************************************/ /* AGL_stop (AGL internal use) */ /* Reset AGL status and terminate process */ void AGL_stop() { AGL_term(); /* Reset status */ exit(0); /* Terminate process */ } /*****************************************************************************/ /* AGL_init (Internal AGL use) */ /* This routine is called the first time a viewport is defined in order to */ /* initialize static global parameters of the library */ void AGL_init() { int i; AGL_status.errstat=AGLNOERR; if(!(AGL_wasinit&AGL_INIT)) { AGL_status.curvwp = VWPEMPTY; AGL_status.vwpoint = NULL; stack_pointer=0; scan_pointer=0; for(i=0;i= (unsigned int) DEVCMDLNG ) { AGL_status.errstat = CMDBOVFWNG; return; } pos = strchr(src,prc); if(pos != NULL) { while(srcINTB[1]; NPLANS(device) = combuf->INTB[2]; DEFFOREGR(device) = combuf->INTB[8]; AGLBLACK(device) = combuf->INTB[9]; AGLRED(device) = combuf->INTB[10]; AGLGREEN(device) = combuf->INTB[11]; AGLBLUE(device) = combuf->INTB[12]; AGLYELLOW(device) = combuf->INTB[13]; AGLMAGENTA(device) = combuf->INTB[14]; AGLCYAN(device) = combuf->INTB[15]; AGLWHITE(device) = combuf->INTB[16]; if(AGL_wasinit&AGL_BKGPRESET) DEFBACKGR(device) = combuf->INTB[8+AGL_status.DefBkgr]; else DEFBACKGR(device) = combuf->INTB[7]; MAXLWIDTH(device)= combuf->INTB[6]; /* FLOAT parameters */ XLENG(device) = combuf->FLTB[6]; YLENG(device) = combuf->FLTB[7]; XMAXL(device) = combuf->FLTB[8]; YMAXL(device) = combuf->FLTB[9]; XCURL(device) = combuf->FLTB[0]; YCURL(device) = combuf->FLTB[1]; /* Compute some more parameters */ XPIXELS(device) = combuf->INTB[3]; YPIXELS(device) = combuf->INTB[4]; RSLX(device) = 1./(XPIXELS(device)-1); RSLY(device) = 1./(YPIXELS(device)-1); RATYX(device) = combuf->FLTB[1]/combuf->FLTB[0] ; RATXY(device) = combuf->FLTB[0]/combuf->FLTB[1] ; DOTLEN(device) = (XLENG(device)/XCURL(device))*0.002; CHARMULT(device)=combuf->FLTB[2]; if(combuf->INTB[5] != CURRDRV_VERS) /* Check version of driver */ return ILLDRVSEV; else return AGLNOERR; } /*****************************************************************************/ /* AGL_sdrv (Internal AGL Use) */ /* Initializes driver entry points */ /* This routine must be called every time a viewport is (re)activated */ void AGL_sdrv() { int (*(*drvpnt))(); /* Device driver table pointer */ drvpnt = DRVADDR(DY(devidx)); AGL_status.CURS_POINTER = *(drvpnt++); AGL_status.ERAS_POINTER = *(drvpnt++); AGL_status.ESCP_POINTER = *(drvpnt++); AGL_status.INIT_POINTER = *(drvpnt++); AGL_status.SEND_POINTER = *(drvpnt++); AGL_status.TERM_POINTER = *(drvpnt++); AGL_status.POLY_POINTER = *(drvpnt++); AGL_status.CUsrTransf = DY(UsrTransf); } /****************************************************************************/ /* rdevfil (Internal AGL use) */ /* read specified file for device info */ static int rdevfil(fil,dvnam,maxlng,driv, /* return -1: no file, */ sysaux,node,dcmd) /* 0: no device */ /* 1: found */ char *fil; /* Configuration file name */ char *dvnam; /* device name */ int maxlng; /* Max output string length */ char *driv; /* Output device type (or driver name) */ char *sysaux; /* Auxiliary system info */ char *node; /* Network node name */ char *dcmd; /* Device close command string */ { FILE *wrk; char line[100], cbuf[PHNAMLNG]; char *ist, *pntr; int is =(-1); int i; for(i=0;i<4;i=(i<<1)|0x1) { /* Search standard directory hierarchy */ wrk = AG_STDO(fil,"",i); /* search configuration file */ if ( wrk!=NULL ) { is=0; for(;;) { ist=AG_GETS(line,100,wrk); /* get a line le */ if(ist==NULL) break; pntr = AG_SCAN(ist,':',32,cbuf); if(AGL_scmp(cbuf,dvnam)) { AG_DMSG("From file:",line); pntr = AG_SCAN(pntr,':',maxlng,cbuf); pntr = AG_SCAN(pntr,':',maxlng,node); pntr = AG_SCAN(pntr,'\0',DEVCMDLNG,dcmd); pntr = AG_SCAN(cbuf,'.',maxlng,driv); pntr = AG_SCAN(pntr,':',maxlng,sysaux); if(*dcmd == '=') strcpy(dcmd,(dcmd+1)); is=1; break; } } fclose(wrk); if(is==1) break; } else break; } return is; } /****************************************************************************/ /* getdvty (Internal AGL use) */ /* Get device type */ /* The routine gets from the AGLDEVS.DAT files the information about the */ /* device. */ static void getdvty(dvnam,maxlng,driv,sysaux,node,dcmd) char *dvnam; /* device identification (System dep) */ int maxlng; /* Max output string length */ char *driv; /* Output device type (or driver name) */ char *sysaux; /* Auxiliary system info */ char *node; /* Network node name */ char *dcmd; /* Device close command string */ { static char *cnfile = "agldevs.dat"; int is; char cbuf[PHNAMLNG]; char *pntr; extern char *AG_SCAN(); extern void AG_DMSG(); AGL_status.errstat=AGLNOERR; *driv='\0'; *sysaux='\0'; *node='\0'; *dcmd='\0'; is = rdevfil(cnfile,dvnam,maxlng,driv,sysaux,node,dcmd); if(is<=0) { /* Device not found */ *dcmd='\0'; AGL_trns(DEVGLOBAL,maxlng,cbuf); AG_DMSG("AGLDEV=",cbuf); if(cbuf[0]=='\0') { /* Device not in configuration */ AGL_status.errstat=ILLDEVERR; return; } pntr=AG_SCAN(cbuf,'.',maxlng,driv); pntr=AG_SCAN(pntr,':',maxlng,sysaux); } AG_DMSG("Driver:",driv); AG_DMSG("SYSAUX:",sysaux); AG_DMSG("Nodenm:",node); AG_DMSG("Commnd:",dcmd); } /*****************************************************************************/ /* AGL_gdev (Internal AGL use) */ /* Attach the viewport to a device */ /* The device name is firstly checked against the active device table. If it */ /* is not in use the device is opened (through the interf. rout. AGLINxxx) */ /* and assigned the channel. If it is already in use the related channel is */ /* passed back */ void AGL_gdev(device,xlng,ylng) char *device; /* device name */ double xlng,ylng; /* Dimension requests */ { char dnam[PHNAMLNG]; char driv[DRVNAMLNG]; char sysaux[PHNAMLNG]; char nodnam[PHNAMLNG]; char dcmd[DEVCMDLNG]; char *pt; int err,is; int clearflg,slot,id; DEFINE_AGLDVCOM; extern void AG_DMSG(); extern char *AG_SCAN(); AGL_status.errstat = AGLNOERR; clearflg=TRUE; pt=AG_SCAN(device,'.',PHNAMLNG,dnam); AG_DMSG("Dev.select: ",device); AG_DMSG("Name:",dnam); if(strcmp(dnam,"tt") != 0 ) AGL_trns(dnam,PHNAMLNG,dnam); /* Translate environment variables */ AG_DMSG("Translated:",dnam); AG_DMSG("USRAUX:",pt); strcpy(CHARBUF,dnam); /* put phys. name into buffer */ is = FALSE; for(slot=0;slot=ERRTRSH) return; /* Error return */ GRCHAN(slot)=CHANNEL; *(DEVCOMMND(slot)) = '\0'; *(FILNAM(slot)) = '\0'; if(AGL_status.errstat<=INFOTRSH) makecmd(slot,dcmd,CHARBUF); } strcpy(DEVNAM(slot),dnam); /* Put name into active table */ DY(curchan)=GRCHAN(slot); ACTREQST(slot)++; err=AGL_status.errstat; /* Remember error status */ IBUFFR(0)=1; CHANNEL=DY(curchan); IBUFFR(5)=0; /* Due to compatibility with older */ /* drivers */ *(CHARBUF) = '\0'; INITFUNCT(AGLDVCOM); /* get device characteristics */ AGL_status.errstat = ERRCODE; if(AGL_status.errstat>=ERRTRSH) return; /* Error return */ AGL_status.errstat=setdevpar(AGLDVCOM); /* put params into strucure */ if(AGL_status.errstat != AGLNOERR) return; /* Error return */ if(clearflg&&AGL_status.ersonst&&(FLAGS(slot)&ERASEIT)) { CHANNEL=DY(curchan); /* Erase screen */ IBUFFR(0)=DEFBACKGR(AGL_status.devid); RBUFFR(0) = 0.0; RBUFFR(1) = 1.0; RBUFFR(2) = 0.0; RBUFFR(3) = 1.0; ERASFUNCT(AGLDVCOM); } AGL_status.errstat=MAX(err,ERRCODE); /* Remember worst error */ } /*****************************************************************************/ /* Clipping routines (Internal AGL use) */ /* Two entry points are defined: */ /* aglclpi: for segments whose starting point is inside the clipping */ /* area */ /* aglclpo: for segments whose starting point is outside the clipping */ /* area */ /* Starting coordinates are held in global variables: x00,y00 */ /* Starting status code is held in global variable: stat0 */ /* Both functions return next intersection point with the clipping area */ /* in the global variables: x01,y01 */ /* The function return value is the cursor status of the point to reach */ /* Note: status codes define the position of a point with respect to the */ /* clipping area as showed in the following picture: */ /* xlow xup */ /* | | */ /* stat = 9 | stat = 8 | stat = 10 */ /* yup ----------+----------+---------- */ /* stat = 1 | stat = 0 | stat = 2 */ /* ylow----------+----------+---------- */ /* stat = 5 | stat = 4 | stat = 6 */ /* | | */ #define STATP(x,y) ((xxup)?2:0))|((yyup)?8:0)) static double x00,y00; static double auxdx,auxdy; static double xlow,ylow,xup,yup; static int stat0,stat1; static int intrsht(xc,yc) /* Intersection with horizontal top side */ float *xc,*yc; { if(auxdy!=0.0) { *xc = x00+(yup-y00)*auxdx/auxdy; *yc = yup; return (STATP(*xc,*yc)==0); } return(FALSE); } static int intrshb(xc,yc) /* Intersection with horizontal bottom side */ float *xc,*yc; { if(auxdy!=0.0) { *xc = x00+(ylow-y00)*auxdx/auxdy; *yc = ylow; return (STATP(*xc,*yc)==0); } return(FALSE); } static int intrsvr(xc,yc) /* Intersection with vertical right side */ float *xc,*yc; { if(auxdx!=0.0) { *xc = xup; *yc = y00+(xup-x00)*auxdy/auxdx; return (STATP(*xc,*yc)==0); } return(FALSE); } static int intrsvl(xc,yc) /* Intersection with vertical left side */ float *xc,*yc; { if(auxdx!=0.0) { *xc = xlow; *yc = y00+(xlow-x00)*auxdy/auxdx; return (STATP(*xc,*yc)==0); } return(FALSE); } int aglclip(xv,yv,stat1,xc,yc) /* returns TRUE if intersection */ /* Start coordinates and status are */ /* in global variables x00,y00,stat0 */ double xv,yv; /* End coordinates */ int stat1; /* End point status */ float *xc,*yc; /* Output clipped coordinates */ { int stat; auxdx=xv-x00; auxdy=yv-y00; if(stat0!=0) stat=stat0; else stat=stat1; switch(stat) { case 9: if(intrsht(xc,yc)) return TRUE; case 1: return(intrsvl(xc,yc)); case 6: if(intrshb(xc,yc)) return TRUE; case 2: return(intrsvr(xc,yc)); case 5: if(intrsvl(xc,yc)) return TRUE; case 4: return(intrshb(xc,yc)); case 10: if(intrsvr(xc,yc)) return TRUE; case 8: return(intrsht(xc,yc)); } return(0); } /*****************************************************************************/ /* AGL_padj (Internal AGL Use) */ /* Divides the input polyline into smaller pieces fitting into an output */ /* polyline. Also transforms coordinates into normalized mode (if required) */ /* and clip the resulting polylines against either the viewport or the clip- */ /* ping area depending on the polyline mode. */ /* The input polyline structure (but not coordinate data therein) is modifi- */ /* ed after the call (pointers and counters will point to the first point */ /* not fitting into output polyline). */ static float Xpolybuf[AUXPOLYBUFLNG]; static float Ypolybuf[AUXPOLYBUFLNG]; static struct polyline A0poly = { AUXPOLYBUFLNG, 0, (-1), Xpolybuf,Ypolybuf, NORMAL, NORMAL, FALSE, NULL }; struct polyline *AGL_padj(inpoly) /* Return either pointer to output */ /* polyline or NULL */ struct polyline *inpoly; { int ni = inpoly->nvects; int no =0; int maxo = A0poly.maxvects-1; double xpn,ypn; float *XI, *YI; float *XO, *YO; int convert=inpoly->grmode!=NORMAL; if(ni<2) return NULL; XI = inpoly->XV; YI = inpoly->YV; XO = A0poly.XV; YO = A0poly.YV; if(inpoly->clipmode!=NORMAL) { xlow = XCLOW; xup = XCLUP; ylow = YCLOW; yup = YCLUP; } else { xlow = XVWLOW; xup = XVWUP; ylow = YVWLOW; yup = YVWUP; } xpn = *XI++; ypn = *YI++; ni--; if(convert) { CNVRT_BEGIN CNVRT_LOGX(stat0,xpn,ypn) CNVRT_LOGY(stat0,xpn,ypn) CNVRT_USRT0(stat0,xpn,ypn) CNVRT_USRT1(stat0,xpn,ypn) CNVRT_USER0(stat0,xpn,ypn) CNVRT_USER1(stat0,xpn,ypn) } else stat0 = STATP(xpn,ypn); if(stat0==0) { /* Starting point is VISIBLE */ *XO++ = xpn; *YO++ = ypn; no++; } x00=xpn; y00=ypn; for(;;) { xpn = *XI++; ypn = *YI++; if(convert) { CNVRT_BEGIN CNVRT_LOGX(stat1,xpn,ypn) CNVRT_LOGY(stat1,xpn,ypn) CNVRT_USRT0(stat1,xpn,ypn) CNVRT_USRT1(stat1,xpn,ypn) CNVRT_USER0(stat1,xpn,ypn) CNVRT_USER1(stat1,xpn,ypn) } else stat1 = STATP(xpn,ypn); if(stat0==0) { /* last point was VISIBLE */ if(stat1!=0) /* current point not visible */ aglclip(xpn,ypn,stat1,XO,YO); /* Do clipping */ else { *XO=xpn; *YO=ypn; /* Put coordinate */ } no++; XO++; YO++; } else if (stat0==(-1)) { /* last point undefined */ if(stat1==0) { /* Current point VISIBLE */ *XO=xpn; *YO=ypn; /* Put it as first of piece */ no++; XO++; YO++; } } else { /* last point was NOT VISIBLE*/ if((stat1&stat0)==0) { /* Clipping must be tested */ if(aglclip(xpn,ypn,stat1,XO,YO)) { x00 = *XO++; y00 = *YO++; no++; stat0=0; if(stat1==0) { *XO=xpn; *YO=ypn; } else aglclip(xpn,ypn,stat1,XO,YO); no++; XO++; YO++; } } } x00=xpn; y00=ypn; stat0=stat1; ni--; if(ni<=0) break; if((no>=maxo)||((no>0)&&(stat0!=0))) { if(ni>=0) XI--; YI--; ni++; break; } } inpoly->nvects=ni; inpoly->XV = XI; inpoly->YV = YI; if((A0poly.nvects=no)>0) return &A0poly; else return NULL; }