/* Next available MSG number is  32 */

/*    

   SLD2PS.C

   Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994 by Autodesk, Inc.
 
   Permission to use, copy, modify, and distribute this software in 
   object code form for any purpose and without fee is hereby granted, 
   provided that the above copyright notice appears in all copies and 
   that both that copyright notice and the limited warranty and 
   restricted rights notice below appear in all supporting 
   documentation.
 
   AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.  
   AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF 
   MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC.
   DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE 
   UNINTERRUPTED OR ERROR FREE.
 
   Use, duplication, or disclosure by the U.S. Government is subject to 
   restrictions set forth in FAR 52.227-19 (Commercial Computer 
   Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) 
   (Rights in Technical Data and Computer Software), as applicable.
    
   .

      DESCRIPTION:


      SLD2PS.C - Converts AutoCAD Slide files to PostScript files
      Optionally outputs full color and Encapsulated PS files.

      Designed and implemented by Amar Hanspal, Autodesk Product Support

      Originally developed as a DOS stand-alone program - January 89
      Converted to Release 11 ADS application           - March 90

*/

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "adslib.h"

#define ushort unsigned short
#define uchar  unsigned char

/* Hardcopy parameters */

#define PSIZEX 8.50                   /* X Paper size in inches */
#define PSIZEY 11.00                  /* Y Paper size in inches */
#define HCLIP 0.125                   /* Printer's hardclip limits */

#define DPI 72.0                      /* PostScript's Units per inch */

#define PLOWX 0.5                     /* Half-inch border around plot */
#define PLOWY 0.5
#define PHIGHX (PSIZEX - 0.5)
#define PHIGHY (PSIZEY - 0.5)

#define LOWXDOT PLOWX*DPI             /* Convert to PostScript units */
#define LOWYDOT PLOWY*DPI
#define HIXDOT  PHIGHX*DPI
#define HIYDOT  PHIGHY*DPI
#define HCLIPADJ HCLIP*DPI

/* Define the record types present in a Slide file */

#define MINVEC          0x0000        /* Plain vector - minimum value */
#define MAXVEC          0x7F00        /* Plain vector - maximum value */
#define OFFSETVEC       0xFB00        /* Offset from last vector */
#define ENDOFSLD        0XFC00        /* End of Slide File marker */
#define SOLIDFILL       0xFD00        /* Solid Fill */
#define COMMONEND       0xFE00        /* Common endpoint with last vector */
#define NEWCOLOR        0xFF00        /* New color begins */

/* Declare global variables */

unsigned short lowx = 0, lowy = 0 ;   /* Drawing limits */
unsigned short highx= 0, highy = 0;   /* Ditto */
unsigned short plastx = 0, plasty = 0;/* PostScript's last X & Y point */
FILE *in = NULL, *out = NULL;         /* Input and output file pointers */
char *exfun = /*MSG0*/"C:SLD2PS";     /* AutoCAD Command name */

/* Declare global flags */

char lptok = 0;                       /* Last point OK flag */
char scrout = 0;                      /* = 1 if printing the screen */
char colorout = 0;                    /* = 1 if color */
char epsout = 0;                      /* = 1 if encapsulated */
char boxout = 0;                      /* = 1 if drawing a plotbox */
char rotate = 0;                      /* = 1 if landscape */
char oldformat = 0;                   /* = 1 if pre-R9 style slide file */
char backwards = 0;                   /* = 1 if file needs byte swapping */
char usrcanc = 0;                     /* = 0 if user cancels the function */
char intel = 0 ;                      /* = 1 if running on an Intel chip */

/* Forward Function declarations */

void main _((int argc, char **argv));         /* ADS link */
void clearopts _((void));             /* Clear old options */
int funcload _((void));               /* ADS function load routine */
int funcunload _((void));             /* ADS function unload routine */
int dofun _((void));                  /* ADS function dispatcher */
int sld2ps _((void));                 /* Main routine */
void endplot _((void));               /* Closes PostScript file */
void drawbox _((void));               /* Draws a border */

#ifdef __ZTC__
void initplot _((double pscfx, double pscfy));
void swap_pen _((int pen));
int drawvec _((int x1, int y1, int x2, int y2));
int contvec _((int x2, int y2));
void raisepen _((int curx, int cury));
int sfill _((int sx2, int sy2, int fillstat));
short fixchar _((int ch));
#else  /* __ZTC__ */
#if defined(__WATCOMC__) || defined(TURBOC) || defined(sun)
void initplot _((double pscfx, double pscfy));
#else
void initplot _((float pscfx, float pscfy));         /* Opens PostScript file */
#endif
void swap_pen _((short pen));         /* Handles color output */
int drawvec _((ushort x1, ushort y1, ushort x2, ushort y2));
int contvec _((ushort x2, ushort y2));
void raisepen _((ushort curx, ushort cury));
int sfill _((short sx2, short sy2, char fillstat));  /* Handles solid fill */
short fixchar _((unsigned char ch));  /* Simple read routine to help out */
#endif  /* __ZTC__ */

short fetch2bytes _((void));          /* Simple read routine to help out */
short fetchoffset _((void));          /* Ditto */
int formshort _((unsigned char *ptr));  /* The short of portability */
int formlong _((unsigned char *ptr));   /* The long of portability */
int testlong _((unsigned char *ptr));   /* Tests CPU storage of long integers */
int printscr _((void));               /* Creates a temporary slide file */
int getyorn _((char *question));       /* Asks questions, sets global flags */


void main(argc,argv)
  int argc;
  char *argv[];
{

    /* Local declarations */

    short scode = RSRSLT;             /* normal result code */
    int stat;
    char errmsg[80];

    /* Actual Code begins here */

    ads_init(argc, argv);

    for ( ;; ) {

        if ((stat = ads_link(scode)) < 0)  {
            sprintf(errmsg,
                    /*MSG1*/"SLD2PS: bad status from ads_link() = %d\n",
                    stat);
#ifdef Macintosh
            macalert(errmsg);
#else
            puts(errmsg);
            fflush(stdout);
#endif /* Macintosh */
            ads_exit(1);
        }

        scode = RSRSLT;               /* default return code */

        switch (stat)  {

        case RQXLOAD:
            scode = funcload() ? -RSRSLT : -RSERR;
            continue;

        case RQXUNLD:                 /* Unloading */
            scode = (funcunload() ? RSRSLT : RSERR);
            break;

        case RQSUBR:
            dofun();
            ads_retvoid();            /* Exit queitly */
            break;

        default:
            break;

        }                             /* End switch */

    }                                 /* End for */

}                                     /* End main */

/* FUNCLOAD - Load external functions  */

int funcload()
{
    if (ads_defun(exfun,0) != RTNORM)
        return 0;
    else
        return 1;
}

/* FUNCUNLOAD - Unload external functions */

int funcunload()
{
    ads_undef(exfun,0);

    return 1;
}

/* DOFUN - Process the RQSUBR call from AutoCAD */

int dofun()
{
    int val;

    if ( (val = ads_getfuncode()) < 0)
        return 0;
    else {
        switch (val) {

        case 0:
            return sld2ps();

        default:
            break;
        }

    }

    return 1;

}

/* SLD2PS - Reads and process the slide file */

int sld2ps()
{

    /* Slide file header fields */

    char id[17];                      /* Slide file banner */
    char typeind, levlind;            /* Header information */
    short hfill, testno;              /* Hardware fill & test number */
    long aspect;                      /* Aspect Ratio encoded as long */

    /* Alternate fields for OLD format slide files */

    double oldasp;                    /* Old format aspect ratio */
    short oldhfill;                   /* Old hardware fill */
    char fillbyte;                    /* Padding around old format file */

    /* Local variables */

    static char sldfile[132], plotfile[132];  /* Filename strings */

    float gscf;                       /* PostScript Scale Factor */
    float xscf, yscf, scly;           /* X, Y & Scaled Y Scale factors */

    unsigned short fromx, fromy, tox, toy;    /* Vector co-ordinates */
    unsigned short lastx = 0, lasty = 0;      /* Last point saved */
    short sfx, sfy  = 0;              /* Running Solid fill co-ords */

    unsigned short rtype = 0x00;      /* Slide file record type flag */
    short color = 0x07;               /* Initialize color to white or black */
    short offset;                     /* +/- 127 Offset buffer */

    char fillon = 0;                  /* Fill in progress ? */
    char firstpass = 0;               /* First time through ? */

    char lobyte;                      /* Low byte value */
    unsigned short cword;             /* 2 byte integer from "    */

    register unsigned short j = 0;    /* Processing vector counter */

    /* Begin */

    clearopts ();                     /* Clear previous flags */

    scrout = getyorn(/*MSG2*/"\nWould you like to plot the display ? <No>: ");

    if (usrcanc)                      /* We're aborting */
        return 0 ;

    if (scrout) {
        if (!printscr()) {
            ads_fail(/*MSG3*/"Error creating temporary slide file.");
            return 0;
        }
        strcpy(sldfile,/*MSG0*/"sld2ps");
    }
    else {
        ads_getstring (0,/*MSG4*/"\nEnter the name of Slide File to process: ",
                       sldfile);
    }

    if (sldfile[0] == 0) {
        ads_fail (/*MSG5*/"Slide file name must be specified.\n");
        return 0;
    }

    strcpy (plotfile, sldfile);
    strcat (sldfile,/*MSG0*/".sld");

    if ((in = fopen (sldfile,/*MSG0*/"rb")) == NULL)  {
        ads_fail (/*MSG6*/"Error opening slide file.\n");
        return 0;
    }

    /* Get answers to some major questions about life */

    colorout = getyorn
               (/*MSG7*/"\nDo you want Color PostScript Output ? <No>: ");
    if (usrcanc) return 0 ;

    epsout = getyorn
             (/*MSG8*/"\nDo you want Encapsulated PostScript Output ? <No>: ");
    if (usrcanc) return 0 ;

    rotate = getyorn
             (/*MSG9*/"\nDo you want to rotate the output ? <No>: ");
    if (usrcanc) return 0 ;

    boxout = getyorn
             (/*MSG10*/"\nDo you want a border around the plot ? <No>: ");
    if (usrcanc) return 0;

    if (epsout == 1)
        strcat (plotfile,/*MSG0*/".eps");
    else
        strcat (plotfile,/*MSG0*/".ps" );

    ads_printf (/*MSG11*/"\nInput slide file %s, Output PostScript file %s.\n",
                sldfile, plotfile);

    if (colorout == 1)
        ads_printf (/*MSG12*/"\nFull Color: RGB triples will be output.");
    else
        ads_printf (/*MSG13*/"\nMonochrome output assumed.");

    if (epsout == 1)
        ads_printf (/*MSG14*/"\nGenerating Encapsulated PostScript file.");

    if (rotate == 1)
        ads_printf (/*MSG15*/"\nRotating plots to landscape orientation. ");

    if ((out = fopen(plotfile,/*MSG0*/"wb")) == NULL) {
        ads_fail (/*MSG16*/"Error opening plot file.\n");
        return 0;
    }

    /* Read in from slide file: Assume Release 9 Slide file format */

    fread (id,17,1,in);
    fread (&typeind,sizeof(typeind),1,in);
    fread (&levlind,sizeof(levlind),1,in);
    fread (&highx,sizeof(highx),1,in);
    fread (&highy,sizeof(highy),1,in);

    if (levlind == 1)
        oldformat = 1;

    if (!oldformat) {
        fread (&aspect,sizeof(aspect),1,in);
        fread (&hfill,sizeof(hfill),1,in);
        fread (&testno,sizeof(testno),1,in);
    }
    else {
        fread (&oldasp,sizeof(oldasp),1,in);
        fread (&oldhfill,sizeof(oldhfill),1,in);
        fread (&fillbyte,sizeof(fillbyte),1,in);
    }

    if ( (strncmp(id,/*MSG0*/"AutoCAD Slide", 13)) != 0) {
        ads_fail (/*MSG17*/"Invalid slide file header! Aborting.\n");
        return 0;
    }

    if (testno != 0x1234)
        backwards = 1;                /* File written in reverse byte order */

    if (!oldformat) {
        formshort ((unsigned char *)&highx);
        formshort ((unsigned char *)&highy);
        formshort ((unsigned char *)&hfill);
        formlong  ((unsigned char *)&aspect);
    }


    if (oldformat) {
        ads_printf (/*MSG18*/"\n\nSlide file was written in old format.");
        ads_printf (/*MSG19*/"\nNo byte-ordering check possible.");
    }
    else {
        ads_printf (/*MSG20*/"\n\nSlide file was written in Release 9 format.");

        if (backwards)
            ads_printf (/*MSG21*/"\nSwapping bytes while reading file.");
        else
            ads_printf (/*MSG22*/"\nNo byte-swapping neccessary.");
    }

    ads_printf (/*MSG23*/"\nSlide file resolution is %u x %u pixels.",
                highx + 1, highy + 1);

    ads_printf ("\n\n");

    /* Calculate X & Y scale factors as: Paper size/Highest X or Y pixel */
    /* If plots are rotated, the X & Y PAPER directions are reversed */

    if (rotate == 1)  {
        xscf =  (HIYDOT - LOWYDOT - 2*HCLIPADJ)/(float)highx;
        yscf =  (HIXDOT - LOWXDOT - 2*HCLIPADJ)/(float)highy;
    }
    else {
        xscf =  (HIXDOT - LOWXDOT - 2*HCLIPADJ)/(float)highx;
        yscf =  (HIYDOT - LOWYDOT - 2*HCLIPADJ)/(float)highy;
    }

    gscf =  (xscf < yscf) ? xscf : yscf;  /* Global scale is higher of 2 */

    if (!oldformat)
        scly =  aspect/1e7*(float)highy;     /* Scale Y using aspect ratio */
    else
        scly = oldasp*(float)highy;

    yscf =  gscf*(float)highx/scly;          /* Scale the Y factor by global factor */

    /* Start plot */

    initplot (xscf, yscf);

    if (boxout == 1)
        drawbox();

    /* Start parsing data */

    while ( (cword = (ushort)fetch2bytes() ) != ENDOFSLD) {

        lobyte = (cword & 0x00FF);
        rtype = (cword & 0xFF00);     /* High order byte marks record type */

        switch (rtype) {

        case OFFSETVEC:

            offset = fixchar((uchar)lobyte);
            fromx = lastx + offset;

            offset = fetchoffset();
            fromy = lasty + offset;

            offset = fetchoffset();
            tox = lastx + offset;

            offset = fetchoffset();
            toy = lasty + offset;

            /* Output vector */

            drawvec (fromx, fromy, tox, toy);

            /* Save last point */

            lastx = fromx;
            lasty = fromy;

            break;

        case ENDOFSLD:
            /* Nothing to do */
            break;

        case SOLIDFILL:

            sfx = fetch2bytes();
            sfy = fetch2bytes();

            /* Toggle fill on/off if negative Y value */

            if (sfy < 0)
                fillon = (fillon == 0) ? 1 : 0;

            /* Output point to fill routine */

            sfill (sfx, sfy, fillon);

            /* Last point is no longer OK ! */

            lptok = 1;

            break;

        case COMMONEND:

            fromx = lastx;
            fromy = lasty;

            offset = fixchar(lobyte);
            tox = lastx + offset;

            offset = fetchoffset();
            toy = lasty + offset;

            /* Output vector */

            drawvec (fromx, fromy, tox, toy);

            /* Save point */

            lastx = tox;
            lasty = toy;

            break;

        case NEWCOLOR:

            color = lobyte;

            if (colorout == 1) {
                if (firstpass != 0)
                    raisepen (lastx,lasty);
                swap_pen(color);
                firstpass = 1;
            }

            break;

        default:
            /* Should be vector def; else oops ! */

            if (rtype <= MAXVEC)  {

                fromx = cword;
                fromy = fetch2bytes();
                tox   = fetch2bytes();
                toy   = fetch2bytes();

                drawvec (fromx, fromy, tox, toy);

                lastx = fromx;
                lasty = fromy;
            }
            else
                ads_printf(/*MSG24*/"\nUnknown code %x in slide file! ", rtype);

            break;


        }                             /* End switch */

        j++;


        if (j % 32 == 0)  {
            ads_printf(/*MSG25*/"\rProcessing vector %u", j );
            if ( ads_usrbrk() ) {
                ads_fail(/*MSG30*/"Function cancelled. ") ;
                endplot () ;
                return 0 ;
            }
        }

        if (j % 150 == 0 && fillon == 0 )
            raisepen (lastx, lasty);


    }                                 /* End while */

    endplot ();
    ads_printf (/*MSG26*/"\n\nDone ! Output file %s created!\n", plotfile);

    return 1;
}

/* INITPLOT - Opens and constructs the Header of the PostScript file */

void initplot(pscfx, pscfy)
  float pscfx;
  float pscfy;
{
    if (epsout == 1) {                /* Special header for Encapsulated file */
        fprintf (out,/*MSG0*/"%%!PS-Adobe-2.0 EPSF-1.2\n");
        fprintf (out,/*MSG0*/"%%%%Bounding Box: %u %u %u %u\n",
                 lowx, lowy, highx, highy) ;
        fprintf (out,/*MSG0*/"%%%%Creator: File from SLD2PS\n");
        fprintf (out,/*MSG0*/"%%%%EndComments\n");
    }
    else {
        fprintf (out,/*MSG0*/"%%!PS-Adobe-1.0\n");
        fprintf (out,/*MSG0*/"%%%%Creator: File from SLD2PS\n");
        fprintf (out,/*MSG0*/"%%%%EndComments\n");
    }

    fprintf (out,/*MSG0*/"/m {moveto} def\n");
    fprintf (out,/*MSG0*/"/l {lineto} def\n");
    fprintf (out,/*MSG0*/"/s {stroke} def\n");
    fprintf (out,/*MSG0*/"/f {fill} def\n");
    fprintf (out,/*MSG0*/"/n {newpath} def\n");
    fprintf (out,/*MSG0*/"1 setlinejoin\n");
    fprintf (out,/*MSG0*/"0.5 setlinewidth\n");
    fprintf (out,/*MSG0*/"1 setlinecap\n");

    if (rotate == 1)  {               /* Reset origin & re-align co-ords */
        fprintf (out,/*MSG0*/"90 rotate\n");
        fprintf (out,/*MSG0*/"0 %f translate\n", -1.0*DPI*PSIZEX);
        fprintf (out,/*MSG0*/"%f %f translate\n", LOWXDOT, LOWYDOT);
    }
    else
        fprintf (out,/*MSG0*/"%f %f translate\n", LOWXDOT, LOWYDOT);

    fprintf (out,/*MSG0*/"%5.3f %5.3f scale\n", pscfx, pscfy);
    fprintf (out,/*MSG0*/"n\n");

    return;
}

/* ENDPLOT - Completes PostScript file */

void endplot()
{
    fprintf (out,/*MSG0*/"s\n");

    if (epsout != 1)
        fprintf (out,/*MSG0*/"%%%%Bounding Box %u %u %u %u\n",
                 lowx, lowy, highx, highy);

    fprintf (out,/*MSG0*/"showpage\n");

    fclose (in) ;
    fclose (out) ;

    return;
}

/* DRAWBOX - Draws a nice rectangular border around plot */

void drawbox()
{
    fprintf (out,/*MSG0*/"%u %u m\n", lowx, lowy);
    fprintf (out,/*MSG0*/"%u %u l\n", highx, lowy);
    fprintf (out,/*MSG0*/"%u %u l\n", highx, highy);
    fprintf (out,/*MSG0*/"%u %u l\n", lowx, highy);
    fprintf (out,/*MSG0*/"%u %u l\n", lowx, lowy);
    fprintf (out,/*MSG0*/"s\n");
    return;
}

/* SWAP_PEN - Outputs PostScript RGB triple from AutoCAD HSV color */
/* Adapted from Foley and Van Dam and some ADI documentation */

#ifdef __STDC__
void swap_pen(short pen)
#else
void swap_pen(pen)
  short pen;
#endif
{
    unsigned char acadclr;                      /* AutoCAD color number */
    float red = 0.0, green = 0.0, blue = 0.0;   /* RGB triplet values */
    float hue, sat, val;                        /* HSV components */
    static float bright[5] = {
            1.0, 0.65, 0.5, 0.3, 0.15       };
    int i, vs;
    float f;
    float p,q,t;
    int visible = 0;                  /* Force white visibility is off */


    /* Begin */

    acadclr = pen ;

    if (acadclr >= 250 && acadclr <= 255)  {
        red = 1;
        green = 0.5;                  /* These RGB choices are arbitrary */
        blue = 0.35;
        visible = 1;                  /* Make sure it comes out ; force black */
    }
    else {

        switch (acadclr) {

        case 1 :                      /* Red */
            red = 1;
            blue = 0;
            green = 0;
            break;

        case 2 :                      /* Yellow */
            red = 1;
            green = 1;
            blue = 0;
            break;

        case 3 :                      /* Green */
            red = 0;
            green = 1;
            blue = 0;
            break;

        case 4 :                      /* Cyan */
            red = 0;
            green = 1;
            blue = 1;
            break;

        case 5:                       /* Blue */
            red = 0;
            green = 0;
            blue = 1;
            break;

        case 6:                       /* Magenta */
            red = 1;
            green = 0;
            blue = 1;
            break;

        case 0 :                      /* Just in case someone screws up */

        case 7 :                      /* White */
        case 8 :
        case 9 :
            red = 1;
            green = 1;
            blue = 1;
            visible = 1;              /* Force black output on paper */
            break;

        default :                     /* For colors between 10 & 250 */

            hue =  ((float)acadclr - 10) / 10.0; /* 240 maps to 0 - 6 */

            if (hue >= 24)
                hue -= 24;
            hue = hue / 4.0;

            vs =   acadclr % 10;      /* Encoded Saturation and Value */

            val =  bright[vs >> 1];   /* this should be 0,2,4,6,8 */
            sat =  vs & 1 ? 0.5 : 1.0;    /* if odd, set it to 0.5, else 1 */

            i = (int)hue;
            f = hue - i;              /* Fractional part of Hue */

            p = val*(1 - sat);
            q = val*(1 - (sat*f));
            t = val*(1 - (sat*(1 - f)));

            switch (i)        {

            case 0 :
                red = val;
                green = t;
                blue = p;
                break;

            case 1 :
                red = q;
                green = val;
                blue = p;
                break;

            case 2 :
                red = p;
                green = val;
                blue = t;
                break;

            case 3 :
                red = p;
                green = q;
                blue = val;
                break;

            case 4 :
                red = t;
                green = p;
                blue = val;
                break;

            case 5 :
                red = val;
                green = p;
                blue = q;
                break;

            default :
                ads_printf (/*MSG27*/"Unknown color code : %d %f %f %f %f\n",
                            acadclr, hue,sat, val);

            }                         /* Switch (i) */

        }                             /* Switch (acadclr) */

    }                                 /* Else (acadclr < 250) */

    if (visible == 1)
        fprintf (out,/*MSG0*/"0 0 0 setrgbcolor\n");    /* Pure black ! */
    else
        fprintf (out,/*MSG0*/"%f %f %f setrgbcolor\n", red, green, blue);

    return;
}

/* DRAWVEC - Outputs PostScript vector to file */

#ifdef __STDC__
int drawvec(unsigned short x1,
            unsigned short y1,
            unsigned short x2,
            unsigned short y2)
#else
int drawvec(x1, y1, x2, y2)
  unsigned short x1, y1, x2, y2;
#endif
{

    /*   See if from point is the same as the last saved point
         If so, continue the vector, rather than output a full one
         Note that PostScript's "last point" is the exact opposite of
         the slide file's last point. PostScript uses the "to" point
         Also avoid continuing a vector if lastpoint is invalid following
         a fill.
    */

    if (x1 == plastx && y1 == plasty && lptok == 0)
        contvec (x2, y2);
    else {
        fprintf (out,/*MSG0*/"%u %u m\n", x1, y1);
        fprintf (out,/*MSG0*/"%u %u l\n", x2, y2);
    }

    plastx = x2;
    plasty = y2;

    lptok = 0;

    return 1;
}

/* CONTVEC - Continues last vector */
#ifdef __STDC__
int contvec(unsigned short x2,
            unsigned short y2)
#else
int contvec(x2, y2)
  unsigned short x2, y2;
#endif
{
    fprintf (out,/*MSG0*/"%u %u l\n", x2, y2);

    return 1;
}

/* RAISEPEN - Strokes current path when PostScript path has reached max points */
#ifdef __STDC__
void raisepen(unsigned short curx,
              unsigned short cury)
#else
void raisepen(curx, cury)
  unsigned short curx, cury;
#endif
{
    fprintf (out,/*MSG0*/"s\n");
    fprintf (out,/*MSG0*/"%u %u m\n", curx, cury);

    lptok = 1;                        /* Warn vector drawing function */

    return;
}

/* SFILL - Generates Solid Fill Polygon */
#ifdef __STDC__
int sfill(short sx2, short sy2, char fillstat)
#else
int sfill(sx2, sy2, fillstat)
  short sx2, sy2;                     /* Fill polygon co-ordinates */
  char fillstat;                      /* Is fill beginning or ending ? */
#endif
{
    static int call;

    if (sy2 < 0 && fillstat == 1)
        call = 1;                     /* Start of fill, nothing to do */
    else
    if (sy2 > 0) {
        if (call == 1) {              /* First fill point. End current path
                                         and move to start point */
            fprintf (out,/*MSG0*/"s\n");
            fprintf (out,/*MSG0*/"%d %d m\n", sx2, sy2);
            call++;
        }                             /* Output fill polygon point */
        else
            fprintf (out,/*MSG0*/"%d %d l\n", sx2, sy2);
    }

    if (sy2 < 0 && fillstat == 0) {   /* End of fill */
        call = 0;
        fprintf (out,/*MSG0*/"f\n");
    }

    return 1;

}

/* FETCH2BYTES - Read a 2 byte integer in a portable fashion */

short fetch2bytes()
{
    short wd = 0 ;

    fread (&wd, sizeof(wd), 1, in) ;

    if (!oldformat) {
        if (backwards)
            wd = ((wd >> 8) & 0xFF) | (wd << 8) ;
    }

    return wd ;
}

/* FETCHOFFSET - Fetches a 1 byte short */

short fetchoffset()
{
    unsigned char ch = 0;

    fread (&ch, sizeof(ch) , 1, in);

    return fixchar(ch);
}

/* FIXCHAR - Converts a char to a short, hammers in sign bit */

#ifdef __STDC__
short fixchar(unsigned char ch)
#else
short fixchar(ch)
  unsigned char ch;
#endif
{
    return ( (short) ((ch & 0x80) ? ch | ~0xFF : ch));
}

/* FORMSHORT - Swaps bytes of a short depending on machine type */

int formshort(ptr)
  unsigned char *ptr;                 /* Pointer to data array */
{
    register unsigned char swap;

    if (backwards) {
        swap   = ptr[0];
        ptr[0] = ptr[1];
        ptr[1] = swap;                /* Swap those bytes ! */
    }

    return 1;
}

/* FORMLONG - Form a 4 byte long integer */

int formlong(ptr)
  unsigned char *ptr;                 /* Pointer to data array */
{
    unsigned long testval = 1L;       /* Test value */
    register unsigned char swap;

    testlong ((unsigned char *)&testval);      /* Test to check CPU type */

    if (!intel) {
        swap   = ptr[0];
        ptr[0] = ptr[3];
        ptr[3] = swap;
        swap   = ptr[1];
        ptr[1] = ptr[2];
        ptr[2] = swap;
    }                                 /* AutoCAD always writes longs with LSB */
                                      /* first, so Intel CPUs don't need help */

    return 1;
}

/* TESTLONG - Checks to see if the CPU stores longs with LSB first or HSB first */

int testlong(ptr)
  unsigned char *ptr;
{
    char lsb = 0;

    lsb = ptr[0];                     /* Get first byte */

    if (lsb == 1)
        intel = 1;                    /* Intel style CPUs store LSB first */

    return 1 ;

}

/* PRINTSCR - Creates a temporary slide file of the current display */

int printscr()
{
    ads_printf (/*MSG28*/"\nCreating temporary slide file SLD2PS.SLD\n");

    if ( (ads_command (RTSTR,/*MSG29*/"_.MSLIDE", RTSTR,/*MSG0*/"sld2ps",
                       RTNONE) ) < 0)
        return 0;
    else
        return 1;
}

/* GETOPT - Gets a simple yes or no from the user, to set a global flag */

int getyorn(question)
  char *question;
{
    static char opt, optstr[132];

    opt = /*MSG0*/'n';                /* Set default option */

    if ( (ads_getstring (0,question,optstr)) == RTCAN)  {
        usrcanc = 1 ;
        ads_fail (/*MSG31*/"Function cancelled.") ;
        return 0 ;
    }

    opt = optstr[0];

    if (toupper(opt) == /*MSG0*/'Y')
        return 1;
    else
        return 0;
}

/* CLEAROPTS - Clears previously set flags and options from last RQSUBR */
/* The application is loaded and initialized only once, but could be executed */
/* several times.  Flags not cleared would be affect the next execution */

void clearopts()
{
    backwards = lptok = scrout = colorout = 0;
    epsout = boxout = rotate = oldformat = 0;
    usrcanc = 0 ;

    return;
}
