/* Copyright 1991,1992,1993,1994,1995,1996,1997,1998,1999 Y&Y, Inc. Copyright 2007 TeX Users Group 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef _WINDOWS #define _WINDOWS #endif #define NOCOMM #define NOSOUND #define NODRIVERS #define STRICT #include "windows.h" #include "windowsx.h" #include #include #include #include #include "dviwindo.h" #include "winextra.h" #include "winhead.h" #include "winbased.h" #pragma hdrstop /* stdlib.h not really needed - just for hdrstop */ #include #include #include /* for sine and cosine */ #include "winspeci.h" #pragma warning(disable:4100) // unreferenced formal parameters #define USEMEMCPY #define DEBUGDIB /* #define DEBUGTIFF */ /* #define DEBUGBMP */ /* #define DEBUGHYPER */ /* #define DEBUGMETAFILE */ /* #define DEBUGEPSPATH */ /* debugging only */ /* #define DEBUGREADDVIPS */ /* #define DEBUGCOLORSTACK */ /********************************************************************** * * DVI \special function implementation * * Copyright (C) 1991, 1992 Y&Y. All Rights Reserved. * * DO NOT COPY OR DISTRIBUTE! * * This implements text and rule colors and figure insertion * **********************************************************************/ #define MAXIMAGEDIMEN 65536 /* maximum rows & columns permitted */ #define MAXIMAGESIZE 67108864 /* maximum BytesPerRow x rows */ /* #define MAXIMAGEDIMEN 4096 */ /* #define MAXIMAGESIZE 4194304 */ /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ #define PALVERSION 0x300 /* Windows 3.0 palette version */ #define MAXPALETTE 256 /* max. # supported palette entries */ int allowclip = 1; /* read BBox from EPS file and allow clipping */ int tweakdash=1; /* adjust dashes in TPIC */ int tweakdot=1; /* adjust dots in TPIC */ COLORREF OldTextColor, SavedTextColor, SavedBkColor; COLORREF FigureColor, BackColor, OldFigureColor, OldBackColor; COLORREF RuleColor; /* 94/July/5 used in winanal.c */ int captionindex=-1; /* index into Caption Fonts table */ int captionttf=0; /* is Caption font TrueType ? */ /* Use instead FakeFonts[] in dviwindo.c with offset to step over serifed */ int CaptionFontSize=8 * 20; /* BOOL bBoxFigure=0; */ /* draw box around figure */ HGLOBAL hImage; /* handle to memory for image bytes */ LPSTR lpImageBytes; /* FAR pointer to start of Image Data */ char buttonlabel[MAXMARKS+1]=""; /* label of last button hit */ char line[MAXLINE]; /* buffer for reading lines from EPS file */ char moreline[MAXLINE]; /* buffer for reading more stuff from EPS file */ int lookup[256]; /* remapping table for color stretch */ long nspecialsav; /* saved byte count of special */ long specstart; /* saved start of \special for error message */ /* Is this assuming standard dvi_num and dvi_den ??? */ double scaledpoint = (65536.0 * 72.27) / 72.0; int prewidth=0, preheight=0, prebits=0, prelines=0; /* 92/Jan/2 */ int rule_r, rule_g, rule_b; /* rule color saved for TPIC */ /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ POINT FAR *lpTPIC; /* FAR pointer to TPIC path table */ /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ /* Procedure specific to TIFF file format: */ /* Procedure specific to WMF file format: */ /* 95/Oct/1 */ #ifdef LONGNAMES int readtifffile(HDC, HFILE, int, int, int, int, int, int); int readwmffile(HDC, HFILE, int, int, int, int); int readbmpfile(HDC, HFILE, int, int, int, int, int); #else int readtifffile(HDC, FILE *, int, int, int, int, int, int); int readwmffile(HDC, FILE *, int, int, int, int); int readbmpfile(HDC, FILE *, int, int, int, int, int); #endif /* procedure specific to MetaFile format: */ void showmetafile(HDC, char *, double, double, int); /* 96/Apr/4 */ /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ /* Procedure specific to EPSI file format: */ #ifdef LONGNAMES int readepsipreview(HDC, HFILE, int, int, int, int, int); int renderimage(HDC, HFILE, int, int, int, int); int getline(HFILE, char *); #else int readepsipreview(HDC, FILE *, int, int, int, int, int); int renderimage(HDC, FILE *, int, int, int, int); int getline(FILE *, char *); #endif /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ static char *modname = "WINSPECI"; /* static char *modname = __FILE__; */ static void winerror(char *message) { HWND hFocus; if ((hFocus = GetFocus()) == NULL) hFocus = hwnd; (void) MessageBox(hFocus, message, modname, MB_ICONSTOP | MB_OK); } /* using this while repainting can lead to looping and `BusyRepaint' */ /* try and use winbadimage or winbadspecial instead */ static int wincancel (char *message) { HWND hFocus; int flag; if ((hFocus = GetFocus()) == NULL) hFocus = hwnd; flag = MessageBox(hFocus, message, modname, MB_ICONSTOP | MB_OKCANCEL); if (flag == IDCANCEL) { bShowFlag = 0; /* turn off displaying */ finish = -1; /* set early termination */ bUserAbort = 1; /* stop printing */ return -1; } return 0; } void winbadimage (char *message) { /* 95/April/6 */ if (bBadFileComplained++ == 0) { wincancel (message); /* bBadFileComplained++; */ } else { /* 96/Feb/4 */ bShowFlag = 0; /* turn off displaying */ finish = -1; /* set early termination */ bUserAbort = 1; /* stop printing */ } } void winbadspecial (char *message) { /* 95/Feb/4 */ if (bBadSpecialComplained++ == 0) { wincancel (message); /* bBadSpecialComplained++; */ } else { /* 96/Feb/4 */ bShowFlag = 0; /* turn off displaying */ finish = -1; /* set early termination */ bUserAbort = 1; /* stop printing */ } } /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ /* Attempt to speed up EPSI preview reading */ /* modified 95/Dec/1 */ #define EPSISPEED 1 #ifdef EPSISPEED #define EPSIBUFFERLEN 256 /* stuff for speeding up reading of EPSI preview - not worth it ? */ /* static char buffer[BUFFERLEN]; */ /* buffer for low level routines */ static char *lpspcBuffer=NULL; /* buffer for low level routines */ static char *spcbufptr; /* pointer to next byte to take out of buffer */ static int spcbuflen; /* bytes still left in str buffer */ /* static int ungotten=-1; */ /* result of unwingetc - or -1 */ /* assumes only one file open at a time */ /* attempt to speed up readepsi */ /* versions of getc and ungetc using low-level C input/output */ /* static void unwingetc(int c, int input) { if (ungotten >= 0) { wincancel("Repeated unwingetc"); errcount(); } else filepos--; ungotten = c; } */ #ifdef LONGNAMES static int replenish(HFILE input, int bufferlen) { spcbuflen = _lread(input, lpspcBuffer, (unsigned int) bufferlen); #else static int replenish(FILE *input, int bufferlen) { spcbuflen = fread(lpspcBuffer, 1, (unsigned int) bufferlen, input); #endif if (spcbuflen < 0) { wincancel ("Read error in wingetc "); finish = -1; } if (spcbuflen <= 0) return EOF; /* end of file or read error */ spcbufptr = lpspcBuffer; return spcbuflen; } #ifdef LONGNAMES static int wingetc(HFILE input) { #else static int wingetc(FILE *input) { #endif /* int c; */ /* if (ungotten >= 0) { c = ungotten; ungotten = -1; filepos++; return c; } else */ if (spcbuflen == 0) { /* if (replenish(input, BUFFERLEN) < 0) return EOF; */ if (replenish(input, EPSIBUFFERLEN) < 0) return EOF; } spcbuflen--; return (unsigned char) *spcbufptr++; } #ifdef LONGNAMES static int wininit(HFILE input) { /* ignores `input' */ #else static int wininit(FILE *input) { /* ignores `input' */ #endif /* filepos = 0; */ /* beginning of file */ /* ungotten = -1; */ if (lpspcBuffer != NULL) winerror("Buffer Error"); else lpspcBuffer = (char *) LocalAlloc(LMEM_FIXED, EPSIBUFFERLEN); spcbuflen = 0; /* nothing buffered yet */ if (lpspcBuffer == NULL) { /* 1996/May/12 */ /* sprintf(str, "EPSI buffer alloc error (%d bytes)", EPSIBUFFERLEN); winbadimage(str); */ return -1; /* indicate failure to caller */ } spcbufptr = lpspcBuffer; /* redundant ? */ return 0; } static void winendit (void) { if (lpspcBuffer == NULL) winerror("Buffer Error"); LocalFree ((HLOCAL) lpspcBuffer); lpspcBuffer = NULL; } #endif /* EPSISPEED */ /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ /* Remove path name off fully qualified file name */ /* return pointer to file name - minus path */ /* the string is not copied */ char *removepath (char *pathname) { char *s; if ((s=strrchr(pathname, '\\')) != NULL) s++; else if ((s=strrchr(pathname, '/')) != NULL) s++; else if ((s=strrchr(pathname, ':')) != NULL) s++; else s = pathname; return s; } /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ void extension (char *fname, char *ext) { /* supply extension if none */ char *s, *t; /* if ((s = strrchr(fname, '.')) == NULL || ((t = strrchr(fname, '\\')) != NULL && s < t)) { strcat(fname, "."); strcat(fname, ext); } */ /* rewritten 94/Apr/22 */ if ((s = strrchr(fname, '.')) != NULL) { if ((t = strrchr(fname, '\\')) == NULL) t = strrchr(fname, '/'); if (t == NULL || s > t) return; /* already has extension */ } strcat(fname, "."); strcat(fname, ext); } void forceexten (char *fname, char *ext) { /* change extension if present */ char *s, *t; /* if ((s = strrchr(fname, '.')) == NULL || ((t = strrchr(fname, '\\')) != NULL && s < t)) { strcat(fname, "."); strcat(fname, ext); } else strcpy(s+1, ext); *//* rewritten 94/Apr/22 */ if ((s = strrchr(fname, '.')) != NULL) { if ((t = strrchr(fname, '\\')) == NULL) t = strrchr(fname, '/'); if (t == NULL || s > t) strcpy(s+1, ext); /* replace */ } strcat(fname, "."); strcat(fname, ext); } /* remove file name - keep only path - inserts '\0' to terminate - not used */ void stripname (char *pathname) { char *s; if ((s=strrchr(pathname, '\\')) != NULL) ; else if ((s=strrchr(pathname, '/')) != NULL) ; else if ((s=strrchr(pathname, ':')) != NULL) s++; else s = pathname; *s = '\0'; } /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ /* file handle of \special file being read kept globally here */ /* should we reset this to BAD_ERROR when starting ? */ #ifdef LONGNAMES HFILE special=HFILE_ERROR; #else FILE *special=NULL; #endif /* checks whether given filename has more than 8 characters 97/Nov/28 */ /* do similar hack for extension longer than 3 characters ? */ int islongname (char *name) { char *s, *t; if ((t = strrchr(name, '.')) == NULL) t = name + strlen(name); s = t; while (s > name && *s != '\\' && *s != '/' && *s != ':') s--; if (s > name) s++; if ((t - s) > 8) { strcpy(s+8, t); /* truncate it */ /* winerror(s); */ /* debugging */ return 1; } else return 0; } /* constructed name of special file */ /* Use szHyperFile instead ??? */ /* Inserted EPS file is searched for as follows: */ /* If fully qualified, full filename is tried first */ /* If an EPSPath is given, directory part of the file name is stripped off */ /* - then each pathname in the search path is tried in turn */ /* If file is not found, it is next looked for in the dvi file's directory */ /* Finally, an attempt is made to find it in the current directory */ /* shouldn't it look in DVI file directory first ? if unqualified ? */ /* Drops constructed name in global var `filename' */ /* Returns BAD_FILE (NULL or HFILE_ERROR) if failed completely */ /* FINDEPSFILE: Try to open the file to be included (or overlayed) */ #ifdef LONGNAMES HFILE findepsfile(char *name, int warnflag, char *ext) { #else FILE *findepsfile(char *name, int warnflag, char *ext) { #endif /* FILE *findepsfile(char *name, int warnflag, char *ext, char *epsfilename) {*/ char *s; char *epsname; /* points to file name (minus path) */ int foundfile = 0; char epsfilename[MAXFILENAME]; /* 95/Apr/26 move in caller or global ? */ #ifndef SUBDIRSEARCH char *searchpath; #endif /* #ifndef LONGNAMES */ int nFile, nFileSpecial; /* debugging tests on number of handles */ /* #endif */ #ifdef DEBUGEPSPATH if (bDebug > 1) { sprintf(debugstr, "FindEpsFile: %s %s", name, ext); OutputDebugString(debugstr); } #endif /* if (special != NULL) */ /* 92/Feb/13 */ if (special != BAD_FILE) { /* 92/Feb/13 */ sprintf(debugstr, "Attempt to reopen special (%d)", special); winerror(debugstr); rewind(special); return special; } tryagain: /* 97/Nov/28 */ strcpy(epsfilename, name); /* file name as given */ /* expand ..\foo.dvi notation and .\foo.dvi notation 1996/Jan/30 */ /* Note that . here refers to directory of DVI file! 1996/Jan/30 */ if (*name == '.' || *name == '\\' || *name == '/') expanddots(epsfilename); extension(epsfilename, ext); /* add extension */ epsname = removepath(epsfilename); /* strip path from eps file name */ /* printf("epsfilename %s epsname = %s\n", epsfilename, epsname); */ /* maybe consider only fully qualified if it contains `:' ??? */ /* if fully qualified name, try that first */ if (strchr(epsfilename, '\\') != NULL || strchr(epsfilename, '/') != NULL || strchr(epsfilename, ':') != NULL) { /* fully qualified name */ strcpy(FileName, epsfilename); #ifdef DEBUGEPSPATH if (bDebug > 1) { sprintf(debugstr, "%s (fully qualified)", FileName); OutputDebugString(debugstr); } /* 93/Dec/2 debugging */ #endif /* if ((special = fopen(filename, "rb")) != NULL) */ special = fopen(FileName, "rb"); if (special != BAD_FILE) foundfile = 1; } else { /* not fully qualified try anyway 99/July/3 */ strcpy(FileName, epsfilename); special = fopen(FileName, "rb"); if (special != BAD_FILE) foundfile = 1; } /* If not successful, try each path in szEPSPath in turn */ /* The bug introduced 94/Aug/18 was fixed 4PM 94/Sep/3 ... */ if (foundfile == 0 && /* strcmp(szEPSPath, "") != 0) */ /* was epspath */ szEPSPath != NULL) { #ifdef SUBDIRSEARCH /* if ((special = findandopen(epsname, szEPSPath, "rb", 0)) != NULL) */ special = findandopen(epsname, szEPSPath, FileName, "rb", 0); if (special != BAD_FILE) foundfile = 1; #else searchpath = szEPSPath; for(;;) { if ((searchpath = nextpathname(filename, searchpath)) == NULL) { foundfile = 0; break; } /* printf("NEXTPATH %s %d", filename, strlen(filename)); */ s = filename + strlen(filename) - 1; /*93/Dec/21 */ if (*s != '\\' && *s != '/') strcat(filename, "\\"); strcat(filename, epsname); /* extension(epsfilename, ext); */ #ifdef DEBUGEPSPATH if (bDebug > 1) { sprintf(debugstr, "%s (on search path)", filename); OutputDebugString(debugstr); } /* 93/Dec/2 debugging */ #endif special = fopen(filename, "rb"); /* "r" ? */ /* if (special != NULL) */ if (special != BAD_FILE) { foundfile = 1; break; } } #endif } /* if not found on search path */ if (foundfile == 0 && strchr(epsfilename, ':') == NULL) { strcpy(FileName, DefPath); /* try full name in dir of dvi file */ if (*FileName != '\0') { s = FileName + strlen(FileName) - 1; /*93/Dec/21 */ if (*s != '\\' && *s != '/') strcat(FileName, "\\"); } strcat(FileName, epsfilename); /* 92/May/05 */ #ifdef DEBUGEPSPATH if (bDebug > 1) { sprintf(debugstr, "%s (in DVI file directory)", FileName); OutputDebugString(debugstr); } /* 93/Dec/2 debugging */ #endif special = fopen(FileName, "rb"); /* if (special != NULL) foundfile = 1; */ if (special != BAD_FILE) foundfile = 1; } if (foundfile == 0 && strcmp(epsfilename, epsname) != 0) { strcpy(FileName, DefPath);/* try file name in directory of dvi file */ if (*FileName != '\0') { s = FileName + strlen(FileName) - 1; /*93/Dec/21 */ if (*s != '\\' && *s != '/') strcat(FileName, "\\"); } strcat(FileName, epsname); /* try file name (no path) */ #ifdef DEBUGEPSPATH if (bDebug > 1) { sprintf(debugstr, "%s (in DVI file directory)", FileName); OutputDebugString(debugstr); } #endif special = fopen(FileName, "rb"); /* if (special != NULL) foundfile = 1; */ if (special != BAD_FILE) foundfile = 1; } if (foundfile == 0 && strchr(epsfilename, ':') == NULL) { strcpy(FileName, epsfilename); /* try full name (current directory) */ #ifdef DEBUGEPSPATH if (bDebug > 1) { sprintf(debugstr, "%s (current directory)", FileName); OutputDebugString(debugstr); } /* 93/Dec/2 debugging */ #endif /* if ((special = fopen(FileName, "rb")) != NULL) foundfile = 1;*/ special = fopen(FileName, "rb"); if (special != BAD_FILE) foundfile = 1; } if (foundfile == 0 && strcmp(epsfilename, epsname) != 0) { strcpy(FileName, epsname); /* try in current directory */ #ifdef DEBUGEPSPATH if (bDebug > 1) { sprintf(debugstr, "%s (current directory)", FileName); OutputDebugString(debugstr); } /* 93/Dec/2 debugging */ #endif /* if ((special = fopen(FileName, "rb")) != NULL) foundfile = 1;*/ special = fopen(FileName, "rb"); if (special != BAD_FILE) foundfile = 1; } if (foundfile == 0) { /* try with shortened name - 97/Nov/28 */ if (islongname(name) != 0) goto tryagain; } if (foundfile == 0) { /* if (warnflag != 0) */ /* if (warnflag != 0 && bComplainFiles != 0) */ if (warnflag != 0 && bComplainFiles != 0 && /* 93/Mar/30 */ (bShowPreview != 0 || bPrintFlag != 0 || bCopyFlag != 0)) { sprintf(debugstr, "Can't find `%s'", epsname); /* sprintf(str, "Can't find %s %d %d", epsname, warnflag, bComplainFiles); */ /* file to be inserted */ /* perror(epsname); */ winbadimage(debugstr); /* errcount(); */ } /* return NULL; */ /* failed ! */ return BAD_FILE; /* 95/Dec/10 */ } /* #ifndef LONGNAMES */ /* winerror(FileName); */ /* debugging hack to check whether files are opened and not closed ! */ /* if (bDebug && special != NULL) */ /* why is this suddenly not 6 & 7 */ /* if (special != NULL) */ /* why is this suddenly not 6 & 7 */ if (special != BAD_FILE) { /* why is this suddenly not 6 & 7 */ #ifdef LONGNAMES nFileSpecial = special; #else nFileSpecial = _fileno(special); #endif #ifdef DEBUGEPSPATH if (bDebug > 1) { sprintf(debugstr, "File %d Open", nFileSpecial); OutputDebugString(debugstr); } #endif if (nFileSpecial > nFileMax) { nFileMax = nFileSpecial; nFile = 6; if (bPrintFlag != 0) nFile++; /* if ((UINT) hTIFFLibrary >= MAXDOSERROR) nFile++; */ if (hTIFFLibrary >= HINSTANCE_ERROR) nFile++; /* if (fileno(special) != nfile) { */ /* if (fileno(special) > nfile + 3) { */ #ifdef IGNORED if (bDebug > 1 && nFileSpecial > nFile + 3) { sprintf(debugstr, "File Handle %d", nFileSpecial); OutputDebugString(debugstr); } #endif } } /* #endif */ /* 95/Dec/1 */ return special; } /* Above deals with names starting with ..\ and .\ only relative */ /* to DVI file directory. Might also want to have it relative */ /* to each directory on the search path ??? */ /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ int scanspecial(int, char *, int); #define TPIC #ifdef TPIC /* char *tpiccommand[] = { "pa", "fp", "ip", "da", "dt", "sp", "pn", "ar", "ia", "sh", "wh", "bk", "tx", ""}; */ char *tpiccommands = "pa fp ip da dt sp pn ar ia sh wh bk tx cl"; /* Is this assuming standard dvi_num and dvi_den ??? */ /* * 0.001 => in */ /* * 72.27 => points */ /* * 65536 => scaled points */ long convscal (long z) { /* convert to scaled point from 0.001 inch */ /* return (long) ((double) z * 0.001 * 72.27 * 65536); */ /* return (long) ((double) z * 4736.28672); */ return z * 4736; /* avoid round-off error accumulation & floating */ } long convscaldouble (double z) { /* as above, but for double */ if (z < 0.0) return - (long) (-z * 4736.0 + 0.5); return (long) (z * 4736.0 + 0.5); } /* #define CONVDEG(x) ((x) * 180 / 3.141592653) */ /* long xold=0, yold=0; */ /* last point placed in path */ int tpicxll, tpicyll, tpicxur, tpicyur; /* bounding box of path */ /* double tpicgrey=0.5; */ /* selected gray level for fill */ int tpic_r=0, tpic_b=0, tpic_g=0; /* fill color for TPIC specials */ int fillflag=0; /* non-zero if shading requested */ #define MAXTPIC 1000 /* maximum path in TPIC special */ /* long FAR *xpath; */ /* FAR pointer to TPIC path table */ /* long FAR *ypath; */ /* FAR pointer to TPIC path table */ int tpicinx=0; /* index into path */ int penwidth=10; /* pen width from `pn' command */ #define MINMILLI 1.0 /* smallest measure in milli-inches */ void resetpath(void) { /* do after stroking/filling path */ if (lpTPIC != NULL) { ReleaseTPIC(); lpTPIC = NULL; } /* xold = 0; yold = 0; */ /* reset previous point */ tpicxll = TWIPLIM; tpicyll = TWIPLIM; tpicxur = -TWIPLIM; tpicyur = -TWIPLIM; tpicinx = 0; /* reset path pointer */ fillflag = 0; /* reset fill/shading if any */ tpic_r = tpic_g = tpic_b = 0; /* default fill color is black */ /* greyspecified = 1; */ /* claim it is given 96/Mar/31 */ } /* following used to convert bit pattern to grey shade */ char bits[16]="0112122312232334"; /* "0123456789ABCDEF" */ /* flag = 0 for `stroke', 1 for `fill' */ /* style is pen style */ /* should get here only for PS_SOLID style (or bElCheapo is set) */ void showpathsub (HDC hDC, int flag, int style) { HPEN hTPICPen=NULL, hOldPen; HBRUSH hTPICBrush=NULL; HBRUSH hOldBrush=NULL; /* 98/Mar/23 uninit ??? */ int pen; if (tpicinx < 1) return; /* nothing to show */ if (lpTPIC == NULL) return; /* rather serious error ! */ if (flag == 0) { /* fp draw polygonal line */ if (style == PS_SOLID) pen = penwidth; else pen = 1; /* limitation on dotted and dashed lines */ /* if (pen == 0) pen = 1; */ hTPICPen = CreatePen(style, pen, RGB(rule_r, rule_g, rule_b)); } else { /* ip do filling only */ hTPICPen = GetStockObject(NULL_PEN); /* hTPICPen = CreatePen(PS_SOLID, 1, RGB(tpic_r, tpic_g, tpic_b)); */ } hOldPen = SelectObject(hDC, hTPICPen); if (flag != 0 || fillflag != 0) { /* fill polygonal region */ hTPICBrush = CreateSolidBrush(RGB(tpic_r, tpic_g, tpic_b)); hOldBrush = SelectObject(hDC, hTPICBrush); } if (flag == 0 && fillflag == 0) Polyline(hDC, lpTPIC, tpicinx); else Polygon(hDC, lpTPIC, tpicinx); (void) SelectObject(hDC, hOldPen); if (flag == 0) (void) DeleteObject (hTPICPen); /* (void) DeleteObject (hTPICPen); */ /* hOldBrush may be uninitialized */ if (flag != 0 || fillflag != 0) { (void) SelectObject(hDC, hOldBrush); (void) DeleteObject (hTPICBrush); } } /* draw part of poylgonal line --- style PS_SOLID, PS_DASH, or PD_DOT */ void DrawLine(HDC hDC, int xold, int yold, int xnew, int ynew, int style, int inter) { int dx, dy, delx, dely, dotx, doty, xo, yo, len, n, k; /* sprintf(str, "OLD %d %d NEW %d %d STYLE %d inter %d PEN %d", xold, yold, xnew, ynew, style, inter, penwidth); winerror(str); */ /* if style is PS_SOLID, or if inter is zero, or if line length is zero */ if (style == PS_SOLID || inter == 0 || (xnew == xold && ynew == yold)) { MoveToEx(hDC, xold, yold, NULL); LineTo(hDC, xnew, ynew); return; } /* assert(inter != 0); */ /* should not have zero interval here */ if (inter == 0) { winerror("interval == 0"); /* debugging */ return; /* paranoia 94/Nov/19 */ } dx = xnew - xold; dy = ynew - yold; if (dx == 0) len = abs(dy); else if (dy == 0) len = abs(dx); else len = (int) sqrt ((double) dx * dx + (double) dy * dy); /* assert(len != 0); */ if (len == 0) { winerror("length == 0"); /* debugging */ return; /* paranoia 94/Nov/19 */ } n = (len + inter/2) / inter; if (n == 0) n = 1; /* assert(n != 0); */ xo = xold; yo = yold; if (style == PS_DASH) { n = ((n - 1) / 2) * 2 + 1; /* make an odd number */ delx = dx / n; dely = dy / n; /* the following shortens the dashes a bit a la TPIC specs */ if (tweakdash != 0) { dotx = (int) ((double) penwidth * dx / len); doty = (int) ((double) penwidth * dy / len); } else { dotx = 0; doty = 0; } MoveToEx(hDC, xold, yold, NULL); for (k = 1; k <= n/2; k++) { LineTo(hDC, xo+delx-dotx/4, yo+dely-doty/4); xo = xo + delx + delx; yo = yo + dely + dely; MoveToEx(hDC, xo+dotx/4, yo+doty/4, NULL); } LineTo(hDC, xnew, ynew); } else if (style == PS_DOT) { delx = dx / n; dely = dy / n; /* the following elongates the dots a bit a la TPIC specs */ if (tweakdot != 0) { dotx = (int) ((double) penwidth * dx / len); doty = (int) ((double) penwidth * dy / len); } else { dotx = 0; doty = 0; } MoveToEx(hDC, xold, yold, NULL); for (k = 1; k <= n; k++) { LineTo(hDC, xo+dotx/4, yo+doty/4); xo = xo + delx; yo = yo + dely; MoveToEx(hDC, xo-dotx/4, yo-doty/4, NULL); } LineTo(hDC, xnew, ynew); } else winerror("Unrecognized style"); } /* The above has no snapto device grid so at small sizes dots come and go...*/ /* Following used for dashed and dotted polylines */ /* Assume for now these will not be shaded/filled */ void showpathslow (HDC hDC, int flag, int style, int inter) { HPEN hTPICPen=NULL, hOldPen; HBRUSH hTPICBrush=NULL; HBRUSH hOldBrush=NULL; /* 98/Mar/23 ??? uninit */ int xold, yold, xnew, ynew; int k; if (tpicinx < 1) return; /* nothing to show */ if (lpTPIC == NULL) return; /* rather serious error ! */ /* if (penwidth < MinWidth) penwidth = (3 * penwidth + MinWidth)/4; */ if (flag == 0) /* draw polygonal line */ hTPICPen = CreatePen(PS_SOLID, penwidth, RGB(rule_r, rule_g, rule_b)); else { hTPICPen = GetStockObject(NULL_PEN); /* do filling only */ /* hTPICPen = CreatePen(PS_SOLID, 1, RGB(tpic_r, tpic_g, tpic_b)); */ } hOldPen = SelectObject(hDC, hTPICPen); if (flag != 0 || fillflag != 0) { /* fill polygonal region */ hTPICBrush = CreateSolidBrush(RGB(tpic_r, tpic_g, tpic_b)); hOldBrush = SelectObject(hDC, hTPICBrush); } /* if (bDebug > 1) { sprintf(debugstr, "flag %d fillflag %d style %d tpicinx %d penwidth %d\n", flag, fillflag, style, tpicinx, penwidth); OutputDebugString(debugstr); } */ xold = lpTPIC[0].x; yold = lpTPIC[0].y; /* MoveToEx(hDC, xold, yold, NULL); */ for (k = 1; k < tpicinx; k++) { xnew = lpTPIC[k].x; ynew = lpTPIC[k].y; /* LineTo(hDC, xnew, ynew); */ DrawLine(hDC, xold, yold, xnew, ynew, style, inter); xold = xnew; yold = ynew; } MoveToEx(hDC, mapx(dvi_h), mapy(dvi_v), NULL); /* current point */ (void) SelectObject(hDC, hOldPen); if (flag == 0) (void) DeleteObject (hTPICPen); /* (void) DeleteObject (hTPICPen); */ if (flag != 0 || fillflag != 0) { (void) SelectObject(hDC, hOldBrush); (void) DeleteObject (hTPICBrush); } } /* See whether TPIC path is visible */ /* We won't worry here about Windows 95 bug in RectVisible */ /* But maybe we should! See below */ int pathvisible(HDC hDC) { RECT FigureRect; /* There ought to be a better way ... Just what is the smallest visible ? */ if (bFixZeroWidth) { /* if ((tpicxur - tpicxll) < (tpicyur - tpicyll)) tpicxur = tpicxll + (tpicyur - tpicyll); if ((tpicyur - tpicyll) < (tpicxur - tpicxll)) tpicyur = tpicyll + (tpicxur - tpicxll); */ if ((tpicxur - tpicxll) < MinWidth) tpicxur = tpicxll + MinWidth; if ((tpicyur - tpicyll) < MinWidth) tpicyur = tpicyll + MinWidth; } /* fix 95/Sep/3 */ FigureRect.left = tpicxll; FigureRect.right = tpicxur; FigureRect.bottom = tpicyll; FigureRect.top = tpicyur; /* Avoid RectVisible() in MetaFile - use InterSectRect instead */ if ((bCopyFlag == 0 && RectVisible(hDC, &FigureRect) != 0) || (bCopyFlag != 0 && InterSectRect(&CopyClipRect, &FigureRect) != 0)) { return 1; /* it is visible */ } else return 0; /* it is not visible */ } void showpath (HDC hDC, int flag) { /* flag = 0 for fp, 1 for ip */ if (pathvisible(hDC) == 0) return; showpathsub(hDC, flag, PS_SOLID); } /* PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT */ /* flag = 0 for da (dash), 1 for dt (dot) */ void dashdot (HDC hDC, int inter, int flag) { int style; if (pathvisible(hDC) == 0) return; if (flag == 0) style = PS_DASH; else style = PS_DOT; /* El Cheapo implementation first ... */ if (bElCheapo != 0 && bPrintFlag == 0 && bCopyFlag == 0) showpathsub(hDC, 0, style); else showpathslow(hDC, 0, style, inter); } /* ************************* SPLINE STUFF ****************************** */ int flatten = 20; /* flattenpath parameter in TWIPS */ /* is device and magnifciation dependent */ int splinestyle; /* style of spline */ int markingflag; /* non-zero while on dash, zero in between */ int arclength; /* arc length accumulated from previous flip */ int dashlength; /* length of dash or dot-interval */ int xdash, ydash; /* last MoveTo or LineTo in dashing spline */ void DashMoveTo(HDC hDC, int x, int y) { MoveToEx (hDC, x, y, NULL); markingflag = 1; arclength = 0; xdash = x; ydash = y; } void DashLineTo(HDC hDC, int x, int y) { int len, delx, dely, dx, dy, dlen; if (x == xdash && y == ydash) return; /* zero length */ delx = x - xdash; dely = y - ydash; /* if (delx == 0) len = abs(dely); */ /* else if (dely == 0) len = abs(delx); else */ len = (int) sqrt ((double) delx * delx + (double) dely * dely); /* else if (abs (delx) > abs(dely)) len = abs(delx); */ /* else len = abs(dely); */ /* assert (len != 0); */ if (len == 0) { winerror("length == 0"); /* debugging */ return; /* paranoia 94/Nov/14 */ } if (arclength + len < dashlength) { /* no flip in line */ arclength += len; xdash = x; ydash = y; if (markingflag != 0) LineTo (hDC, x, y); else MoveToEx (hDC, x, y, NULL); /* needed ? */ return; } /* need at least one flip */ dlen = dashlength - arclength; /* first partial */ dx = (int) ((long) delx * dlen / len); dy = (int) ((long) dely * dlen / len); xdash += dx; ydash += dy; if (markingflag != 0) LineTo (hDC, xdash, ydash); else MoveToEx (hDC, xdash, ydash, NULL); markingflag = 1 - markingflag; /* flip state* */ arclength = 0; /* reset phase */ dx = (int) ((long) delx * dashlength / len); /* ready full dash */ dy = (int) ((long) dely * dashlength / len); len -= dlen; /* reduce length */ while (len > dashlength) { /* full dashes of need */ xdash += dx; ydash += dy; if (markingflag != 0) LineTo (hDC, xdash, ydash); else MoveToEx (hDC, xdash, ydash, NULL); markingflag = 1 - markingflag; len -= dashlength; } /* arclength = 0; */ dx = x - xdash; dy = y - ydash; /* if (dx == 0) dlen = abs(dy); */ /* else if (dy == 0) dlen = abs(dx); else */ dlen = (int) sqrt ((double) dx * dx + (double) dy * dy); /* else if (abs (dx) > abs(dy)) dlen = abs(dx); */ /* else dlen = abs(dy); */ if (markingflag != 0) LineTo(hDC, x, y); else MoveToEx(hDC, x, y, NULL); /* needed ? */ xdash = x; ydash = y; arclength += dlen; /* len -= dlen; */ } void DotMoveTo(HDC hDC, int x, int y) { MoveToEx (hDC, x, y, NULL); LineTo (hDC, x, y); /* try and make a spot */ arclength = 0; xdash = x; ydash = y; } void DotLineTo(HDC hDC, int x, int y) { int len, delx, dely, dx, dy, dlen; /* take care of initial spot */ /* if (arclength == 0) { MoveTo (hDC, x, y); LineTo (hDC, x, y); } */ if (x == xdash && y == ydash) return; /* zero length */ delx = x - xdash; dely = y - ydash; /* if (delx == 0) len = abs(dely); */ /* else if (dely == 0) len = abs(delx); else */ len = (int) sqrt ((double) delx * delx + (double) dely * dely); /* else if (abs (delx) > abs(dely)) len = abs(delx); */ /* else len = abs(dely); */ if (len == 0) { winerror("length == 0"); /* debugging */ return; /* paranoia 94/Nov/14 */ } if (arclength + len < dashlength) { /* no dot on this line */ arclength += len; xdash = x; ydash = y; MoveToEx (hDC, x, y, NULL); /* needed ? */ /* winerror("no dot"); */ return; } /* need at least one dot */ dlen = dashlength - arclength; /* first partial */ dx = (int) ((long) delx * dlen / len); dy = (int) ((long) dely * dlen / len); xdash += dx; ydash += dy; MoveToEx (hDC, xdash, ydash, NULL); LineTo (hDC, xdash, ydash); /* try and make a dot */ /* sprintf(str, "%d %d", xdash, ydash); winerror(str); */ /* debugging */ arclength = 0; /* reset phase */ dx = (int) ((long) delx * dashlength / len); /* ready full dash */ dy = (int) ((long) dely * dashlength / len); len -= dlen; /* reduce length */ while (len > dashlength) { /* full dots if need */ xdash += dx; ydash += dy; MoveToEx (hDC, xdash, ydash, NULL); LineTo (hDC, xdash, ydash); /* try and make a dot */ /* sprintf(str, "%d %d", xdash, ydash); winerror(str); */ /* debugging */ len -= dashlength; } /* arclength = 0; */ dx = x - xdash; dy = y - ydash; /* if (dx == 0) dlen = abs(dy); */ /* else if (dy == 0) dlen = abs(dx); else */ dlen = (int) sqrt ((double) dx * dx + (double) dy * dy); /* else if (abs (dx) > abs(dy)) dlen = abs(dx); */ /* else dlen = abs(dy); */ MoveToEx(hDC, x, y, NULL); /* needed ? */ xdash = x; ydash = y; arclength += dlen; /* len -= dlen; */ } /* draw quadratic spline from (xa, ya) to (xc, yc), using (xb, yb) control */ void Quadratic(HDC hDC, int xa, int ya, int xb, int yb, int xc, int yc){ int xn, yn, xm, ym, len; long cross; if ((xa == xb && ya == yb) || (xb == xc && yb == yc)) { /* only ONE line, not two */ if (splinestyle == PS_SOLID) LineTo(hDC, xc, yc); else if (splinestyle == PS_DASH) DashLineTo(hDC, xc, yc); else DotLineTo(hDC, xc, yc); return; } cross = (long) (xb - xa) * (yc - ya) - (long) (xc - xa) * (yb - ya); if (cross < 0) cross = - cross; if (abs(xc - xa) > abs(yc - ya)) len = abs(xc - xa); else len = abs(yc - ya); if (cross < (long) len * flatten) { /* terminating case */ /* MoveToEx(hDC, xa, ya, NULL); */ if (splinestyle == PS_SOLID) LineTo(hDC, xb, yb); else if (splinestyle == PS_DASH) DashLineTo(hDC, xb, yb); else DotLineTo(hDC, xb, yb); if (splinestyle == PS_SOLID) LineTo(hDC, xc, yc); else if (splinestyle == PS_DASH) DashLineTo(hDC, xc, yc); else DotLineTo(hDC, xc, yc); return; } else { /* split and recurse */ /* xm = (xa/2 + xc/2)/2 + xb/2; */ xm = (int) (((long) xa + xb + xb + xc)/4); /* ym = (ya/2 + yc/2)/2 + yb/2; */ ym = (int) (((long) ya + yb + yb + yc)/4); /* xn = xa/2 + xb/2; */ xn = (int) (((long) xa + xb)/2); /* yn = ya/2 + yb/2; */ yn = (int) (((long) ya + yb)/2); Quadratic (hDC, xa, ya, xn, yn, xm, ym); /* xn = xc/2 + xb/2; */ xn = (int) (((long) xc + xb)/2); /* yn = yc/2 + yb/2; */ yn = (int) (((long) yc + yb)/2); Quadratic (hDC, xm, ym, xn, yn, xc, yc); } } /* following used for showing splines */ /* so far only set up for SOLID splines */ /* interval = 0 => SOLID, interval > 0 => DASHED, interval < 0 => DOTTED */ /* flag = 0 for `stroke', 1 for `fill' */ /* style is pen style */ void showspline (HDC hDC, int flag, int style, int inter) { HPEN hTPICPen=NULL, hOldPen; HBRUSH hTPICBrush=NULL; HBRUSH hOldBrush=NULL; /* 98/Mar/23 ??? uninit */ int xanc, yanc, xold, yold, xnew, ynew, xmid, ymid, xmud, ymud; int xstar, ystar; int closedflag=0; /* non-zero if spline is closed */ int k; if (pathvisible(hDC) == 0) return; if (tpicinx < 2) return; /* nothing to show */ if (lpTPIC == NULL) return; /* rather serious error ! */ markingflag = 1; /* start with dash */ /* redundant */ arclength = 0; /* draw full dash first */ /* redundant */ dashlength = inter; /* remember dash interval */ splinestyle = style; /* remember style of spline */ /* if (splinestyle != PS_SOLID) winerror("NOT SOLID"); */ if (flag == 0) /* draw spline */ hTPICPen = CreatePen(PS_SOLID, penwidth, RGB(rule_r, rule_g, rule_b)); else { hTPICPen = GetStockObject(NULL_PEN); /* do filling only */ /* hTPICPen = CreatePen(PS_SOLID, 1, RGB(tpic_r, tpic_g, tpic_b)); */ } hOldPen = SelectObject(hDC, hTPICPen); if (flag != 0 || fillflag != 0) { /* fill polygonal region */ hTPICBrush = CreateSolidBrush(RGB(tpic_r, tpic_g, tpic_b)); hOldBrush = SelectObject(hDC, hTPICBrush); } /* Make dependent on magnification ? */ flatten = 20; /* 1 pt = 1/72 in */ /* flatten = flatten - wantedzoom; */ /* NO, coords ARE screen coordinates */ /* Use coarse resolution on screen - finer when printing */ /* Should determine pixel size here ? */ if (bPrintFlag != 0 || bCopyFlag != 0) flatten = flatten / 8; if (flatten <= 0) flatten = 1; xanc = lpTPIC[0].x; yanc = lpTPIC[0].y; xold = lpTPIC[1].x; yold = lpTPIC[1].y; xmid = xanc/2 + xold/2; ymid = yanc/2 + yold/2; xstar = xmid; ystar = ymid; if (xanc == lpTPIC[tpicinx-1].x && yanc == lpTPIC[tpicinx-1].y) closedflag = 1; else closedflag = 0; if (bAllowClosed == 0) closedflag = 0; /* only if permitted */ /* markingflag = 1; */ /* arclength = 0; */ if (closedflag == 0) { if (splinestyle == PS_SOLID) MoveToEx(hDC, xanc, yanc, NULL); else if (splinestyle == PS_DASH) DashMoveTo(hDC, xanc, yanc); else DotMoveTo(hDC, xanc, yanc); if (splinestyle == PS_SOLID) LineTo(hDC, xmid, ymid); else if (splinestyle == PS_DASH) DashLineTo(hDC, xmid, ymid); else DotLineTo(hDC, xmid, ymid); } else { if (splinestyle == PS_SOLID) MoveToEx(hDC, xmid, ymid, NULL); else if (splinestyle == PS_DASH) DashMoveTo(hDC, xmid, ymid); else DotMoveTo(hDC, xmid, ymid); } for (k = 2; k < tpicinx; k++) { xnew = lpTPIC[k].x; ynew = lpTPIC[k].y; xmud = xold/2 + xnew/2; ymud = yold/2 + ynew/2; Quadratic(hDC, xmid, ymid, xold, yold, xmud, ymud); xanc = xold; yanc = yold; xmid = xmud; ymid = ymud; xold = xnew; yold = ynew; } xnew = lpTPIC[tpicinx-1].x; ynew = lpTPIC[tpicinx-1].y; if (closedflag == 0) { if (splinestyle == PS_SOLID) LineTo(hDC, xnew, ynew); else if (splinestyle == PS_DASH) DashLineTo(hDC, xnew, ynew); else DotLineTo(hDC, xnew, ynew); } else Quadratic(hDC, xmid, ymid, xold, yold, xstar, ystar); MoveToEx(hDC, mapx(dvi_h), mapy(dvi_v), NULL); /* current point */ (void) SelectObject(hDC, hOldPen); if (flag == 0) (void) DeleteObject (hTPICPen); /* (void) DeleteObject (hTPICPen); */ if (flag != 0 || fillflag != 0) { (void) SelectObject(hDC, hOldBrush); (void) DeleteObject (hTPICBrush); } } /* interval = 0 => SOLID, interval > 0 => DASHED, interval < 0 => DOTTED */ void spline (HDC hDC, int inter) { int style; if (inter == 0) style = PS_SOLID; else if (inter > 0) style = PS_DASH; else style = PS_DOT; if (inter < 0) inter = - inter; /* absolute value */ /* el cheapo implementation first ... */ if (bElCheapo != 0 && bPrintFlag == 0 && bCopyFlag == 0) showpathsub (hDC, 0, style); /* else if (style == PS_SOLID) showspline (hDC, 0, style, inter); */ else showspline (hDC, 0, style, inter); /* else showpathsub (hDC, 0, style); */ /* until we fix it up */ } void ellipse (HDC hDC, long x, long y, long xr, long yr, double sa, double ea, int flag) { /* flag = 0 for ar, 1 for ia */ int xll, yll, xur, yur, xs, ys, xe, ye; double da; RECT FigureRect; HPEN hTPICPen=NULL, hOldPen; HBRUSH hTPICBrush=NULL; HBRUSH hOldBrush=NULL; /* 98/Mar/23 ??? uninit */ if (flag == 0) /* draw elliptical arc */ hTPICPen = CreatePen(PS_SOLID, penwidth, RGB(rule_r, rule_g, rule_b)); else { hTPICPen = GetStockObject(NULL_PEN); /* do filling only */ /* hTPICPen = CreatePen(PS_SOLID, 0, RGB(tpic_r, tpic_g, tpic_b)); */ } hOldPen = SelectObject(hDC, hTPICPen); if (flag != 0 || fillflag != 0) { /* fill elliptical arc */ hTPICBrush = CreateSolidBrush(RGB(tpic_r, tpic_g, tpic_b)); hOldBrush = SelectObject(hDC, hTPICBrush); } /* Compute bounding box of ellipse */ xll = mapx(dvi_h + x-xr); yll = mapy(dvi_v + y-yr); xur = mapx(dvi_h + x+xr); yur = mapy(dvi_v + y+yr); /* sprintf(str, "LL %d %d UR %d %d PEN %d", xll, yll, xur, yur, penwidth); winerror(str); */ /* make sure tiny ellipse does not disappear ... */ /* ellipse can't be smaller than this -- or maybe draw as point ??? */ /* if (xur < xll + 2 && xur > xll - 2) xur = xll + 2; */ /* if (yur > yll - 2 && yur < yll + 2) yur = yll - 2; */ FigureRect.left = xll; FigureRect.right = xur; FigureRect.bottom = yll; FigureRect.top = yur; /* First check whether ellipse is visible */ /* We won't worry here about Windows 95 bug */ /* why ??? */ /* Avoid RectVisible() in MetaFile - use InterSectRect instead */ if ((bCopyFlag == 0 && RectVisible(hDC, &FigureRect) != 0) || (bCopyFlag != 0 && InterSectRect(&CopyClipRect, &FigureRect) != 0)) { /* interchange start and end, because GUI counterclockwise, TPIC clockwise */ xs = mapx(dvi_h + x + (long) (xr * cos(ea))); ys = mapy(dvi_v + y + (long) (yr * sin(ea))); xe = mapx(dvi_h + x + (long) (xr * cos(sa))); ye = mapy(dvi_v + y + (long) (yr * sin(sa))); da = ea - sa; /* if (fabs(da - 6.283185307) < 0.001) { xe = xs; ye = ys+1; } */ if (flag != 0 || fillflag != 0) { if (fabs(da - 6.283185307) < 0.002) Ellipse(hDC, xll, yll, xur, yur); else Pie(hDC, xll, yll, xur, yur, xs, ys, xe, ye); /* else Chord(hDC, xll, yll, xur, yur, xs, ys, xe, ye); */ } else Arc(hDC, xll, yll, xur, yur, xs, ys, xe, ye); } /* end of clipping rectangle check */ (void) SelectObject(hDC, hOldPen); if (flag == 0) (void) DeleteObject (hTPICPen); /* (void) DeleteObject (hTPICPen); */ if (flag != 0 || fillflag != 0) { (void) SelectObject(hDC, hOldBrush); (void) DeleteObject (hTPICBrush); } } int readtpic (HDC hDC, int input) { long x, y; double z=0.0; long xr=0, yr=0; double sa=0.0, ea=0.0; double r, g, b, grey=0.5; int bitsone, bitstot; int c, k; int xnew, ynew; char *s; int flag; /* long interval; */ int interval; /* char temp[3]; */ /* char bits[16]="0112122312232334"; */ if (strlen(line) != 2) return 0; /* quick exit */ if (strstr(tpiccommands, line) == NULL) return 0; /* quick exit */ if (hTPIC == NULL) { /* if path array storage does not yet exist */ AllocTPIC(MAXTPIC); lpTPIC = NULL; } if (strcmp(line, "pn") == 0) { /* pn n - set pen width */ /* (void) scanspecial(input, line, MAXLINE); */ (void) scanspecial(input, line, sizeof(line)); (void) sscanf(line, "%lg", &z); /* complain if < 1 ? */ if (z > - MINMILLI && z < MINMILLI) /* should be in miniinches */ z = z * 1000.0; /* argument was in inches ? */ /* warn if pen-width is zero ? */ /* tpicpenwidth = convscaldouble(z); */ /* remember pen width */ penwidth = mapd(convscaldouble(z)); /* remember pen width */ /* A hack to try and prevent thin dotted lines from dropping out */ if (penwidth > 0 && penwidth < MinWidth) penwidth = (3 * penwidth + MinWidth) >> 2; /* 95/Sep/3 */ if (penwidth <= 0) penwidth = 1; /* fprintf(output, "%ld pn ", convscaldouble(z)); */ } else if (strcmp(line, "pa") == 0) { /* pa x y - add point to path */ /* (void) scanspecial(input, line, MAXLINE); */ (void) scanspecial(input, line, sizeof(line)); /* x = xold; y = yold; */ /* just in case */ (void) sscanf (line, "%ld %ld", &x, &y); /* complain if < 2 ? */ if (lpTPIC == NULL) { GrabTPIC(); /* xpath = lpTPIC; ypath = lpTPIC + MAXTPIC; */ tpicinx = 0; } /* lpTPIC[tpicinx] = convscal(x - xold); */ /* xpath[tpicinx] = convscal(x - xold); */ /* xpath[tpicinx] = convscal(x); */ xnew = mapx(dvi_h + convscal(x)); lpTPIC[tpicinx].x = xnew; /* lpTPIC[MAXTPIC + tpicinx] = convscal(y - yold); */ /* ypath[tpicinx] = convscal(y - yold); */ /* ypath[tpicinx] = convscal(y); */ ynew = mapy(dvi_v + convscal(y)); lpTPIC[tpicinx].y = ynew; tpicinx++; if (tpicinx >= MAXTPIC) { /* overflowed buffer */ tpicinx--; } /* fprintf(output, "%ld %ld pa", convscal(x - xold), convscal(y - yold));*/ /* xold = x; yold = y; */ /* buil dup bounding box for path */ if (xnew > tpicxur) tpicxur = xnew; if (xnew < tpicxll) tpicxll = xnew; if (ynew > tpicyur) tpicyur = ynew; if (ynew < tpicyll) tpicyll = ynew; } else if (strcmp(line, "da") == 0 || strcmp(line, "dt") == 0) { /* da/dt l - stroke dashed/dotted */ if (strcmp(line, "dt") == 0) flag = 1; else flag = 0; /* (void) scanspecial(input, line, MAXLINE); */ /* complain if < 1 ? */ (void) scanspecial(input, line, sizeof(line)); /* complain if < 1 ? */ z = 0; (void) sscanf (line, "%lg", &z); if (z > - MINMILLI && z < MINMILLI) /* should be in inches */ z = z * 1000.0; /* argument was in inches */ /* warn if dot/dash length is zero ? */ /* interval = convscaldouble(z); */ interval = mapd(convscaldouble(z)); /* if (bDebug > 1) { sprintf(debugstr, "z %lg intderval %d scaled %ld\n", z, interval, convscaldouble(z)); OutputDebugString(debugstr); } */ /* 95/Sep/3 */ dashdot (hDC, interval, flag); resetpath(); } /* end of da/dt case */ else if (strcmp(line, "sp") == 0) { /* sp [l] - stroke quadratic spline */ /* (void) scanspecial(input, line, MAXLINE); */ (void) scanspecial(input, line, sizeof(line)); interval = 0; /* solid spline case */ if (sscanf (line, "%lg", &z) > 0) { if (z > - MINMILLI && z < MINMILLI) z = z * 1000.0; /* argument was in inches */ /* warn if dot/dash length is zero ? */ /* interval = convscaldouble(z); */ interval = mapd(convscaldouble(z)); /* sprintf(str, "z %lg convscal %ld interval %d", z, convscaldouble(z), interval); winerror (str); */ /* debugging */ } spline (hDC, interval); resetpath(); } /* end of sp/sp case */ else if (strcmp(line, "ar") == 0 || strcmp(line, "ia") == 0) { /* ar/ia x y xr yr sa ea */ if (strcmp(line, "ia") == 0) flag = 1; else flag = 0; /* following added 94/June/20 */ if (fillflag == 0) flag = 0; /* if sh not used then ia => ar */ /* (void) scanspecial(input, line, MAXLINE); */ (void) scanspecial(input, line, sizeof(line)); (void) sscanf(line, "%ld %ld %ld %ld %lg %lg", &x, &y, &xr, &yr, &sa, &ea); /* ah hoc attempt to compensate for apparent GUI radius error */ if (xr > 0) xr += 3; if (yr > 0) yr += 3; /* allow for dotted/dashed ellipses ? */ ellipse(hDC, convscal(x), convscal(y), convscal(xr), convscal(yr), sa, ea, flag); /* fillflag = 0; */ /* reset fill/shading if any */ /* tpic_r = tpic_g = tpic_b = 0; */ /* default fill color is black */ resetpath(); } /* end of ar/ia case */ else if (strcmp(line, "sh") == 0 || strcmp(line, "cl") == 0) { /* sh [s] */ /* (void) scanspecial(input, line, MAXLINE); */ (void) scanspecial(input, line, sizeof(line)); grey = 0.5; /* default grey value */ /* greyspecified = 1; */ /* whether grey/color given */ if (sscanf(line, "%lg %lg %lg", &r, &g, &b) < 3) { (void) sscanf (line, "%lg", &grey); /* if "sh" or "cl" given without args, use 0.5 ... */ /* if (sscanf (line, "%lg", &grey) < 1) greyspecified = 0; */ /* 96/Mar/31 */ r = g = b = grey; } if (r > 1.0 || g > 1.0 || b > 1.0) { tpic_r = (int) r; tpic_g = (int) g; tpic_b = (int) b; } else { tpic_r = (int) ((1.0 - r) * 255.0 + 0.5); tpic_g = (int) ((1.0 - g) * 255.0 + 0.5); tpic_b = (int) ((1.0 - b) * 255.0 + 0.5); } fillflag++; } /* end of sh/cl case */ else if (strcmp(line, "fp") == 0 || strcmp(line, "ip") == 0) { /* fp/ip */ if (strcmp(line, "ip") == 0) flag = 1; else flag = 0; /* following added 94/June/20 */ if (fillflag == 0) flag = 0; /* if sh not used then ip => fp */ showpath(hDC, flag); resetpath(); } /* end of fp/ip case */ else if (strcmp(line, "wh") == 0 || strcmp(line, "bk") == 0) { /* wh/bk */ if (strcmp(line, "bk") == 0) { tpic_r = tpic_g = tpic_b = 0; /* black */ } else { tpic_r = tpic_g = tpic_b = 255; /* white */ } /* greyspecified = 1; */ /* 96/Mar/31 */ fillflag++; } /* end of bk/wh case */ else if (strcmp(line, "tx") == 0) { /* tx */ /* (void) scanspecial(input, line, MAXLINE); */ (void) scanspecial(input, line, sizeof(line)); /* need to count bits in hexadecimal mask pattern here */ bitsone=0; bitstot=0; s = line; while ((c = *s++) != 0) { if (c >= '0' && c <= '9') k = c - '0'; else if (c >= 'A' && c <= 'Z') k = c + 10 - 'A'; else if (c >= 'a' && c <= 'z') k = c + 10 - 'a'; else k = 0; bitsone += bits[k] - '0'; bitstot += 4; } if (bitstot == 0) bitstot = 1; /* paranoia */ grey = (double) bitsone / bitstot; tpic_r = tpic_g = tpic_b = (int) ((1.0 - grey) * 255.0 + 0.5); /* greyspecified = 1; */ /* 96/Mar/31 */ fillflag++; } /* end of tx case */ /* else return 0; */ /* impossible ! not a TPIC special */ /* if (lpTPIC != NULL) { ReleaseTPIC(); lpTPIC = NULL; } */ /* somewhat inefficient */ flushspecial(input); /* clean out the rest */ return -1; } #else int readtpic (HDC hDC, int input) { /* fail if not implemented */ return 0; } #endif /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ /* stuff moved from winanal - move back for efficiency ? */ /* read the whole special into a buffer */ // void readspecial(int input, char *buff, int nmax) void readspecial (int input, char *buff, unsigned int nmax) { int c; // if (nspecial <= 0) return; if (nspecial == 0) return; if (nspecial >= nmax) { /* protect ourselves from insanity 99/Feb/21 */ if (bDebug > 1) { sprintf(debugstr, "special too long %d >= %d", nspecial, nmax); OutputDebugString(debugstr); } flushspecial(input); *buff = '\0'; return; } c = an_wingetc(input); nspecial--; while (nspecial > 0 && c != EOF) { *buff++ = (char) c; c = an_wingetc(input); nspecial--; } if (c != EOF) *buff++ = (char) c; *buff = '\0'; } void flushspecial (int input) { int c; if (nspecial <= 0) return; c = an_wingetc(input); nspecial--; while (nspecial > 0 && c != EOF) { c = an_wingetc(input); nspecial--; } } /* error message output of beginning of long item */ void showbeginning(char *s) { sprintf(debugstr, "Token too long: "); strncpy(debugstr + 16, s, 32); strcat(debugstr, " ..."); /* wincancel(debugstr); */ winbadspecial(debugstr); /* 96/Feb/4 */ } /* read next alphanumeric token from special - stop when not alphanumeric */ /* returns terminator */ /* here need to use ANSI character operations ? what about file names ? */ /* need to use AnsiToOem on filenames ? */ /* or use _lopen ? */ int getalphatoken(int input, char *token, int nmax) { int c, k = 0; char *s = token; *token = '\0'; /* in case pop out early 96/Aug/29 */ if (nspecial <= 0) return 0; if (nmax <= 0) { /* 95/Aug/30 */ flushspecial(input); return 0; /* error overflow */ } c = an_wingetc(input); --nspecial; if (c == 0) { flushspecial(input); return 0; /* first byte is null 96/Aug/29 */ } while(c <= ' ' && nspecial > 0) { /* over initial white space */ c = an_wingetc(input); --nspecial; } if (nspecial <= 0) return 0; /* while(((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'))) */ while(IsCharAlphaNumeric((char) c)) { *s++ = (char) c; if(k++ >= nmax) { /* too long */ showbeginning(token); /* errcount(); */ c = an_wingetc(input); --nspecial; /* while(((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) && nspecial > 0) { */ while (IsCharAlphaNumeric((char) c)) { c = an_wingetc(input); --nspecial; } break; } if (nspecial <= 0) { c = ' '; break; /* pretend there is a space at the end */ } c = an_wingetc(input); --nspecial; } *s++ = '\0'; /* printf("token: %s (length %d)\n", line, s - line); */ return c; /* return terminator */ } /* read token from special *//* ignore leading white space */ /* - either up to white space - or - double quote delimited */ /* NEW */ /* returns terminating character */ int gettoken (int input, char *buff, int nmax) { int c, k=0, marker=' '; // end of token marker char *s=buff; *s = '\0'; // in case pop out right away if (nspecial <= 0) return 0; /* nothing more in \special */ if (nmax <= 0) { /* 95/Aug/30 */ flushspecial(input); return 0; /* error overflow */ } c = an_wingetc(input); --nspecial; while(c <= ' ' && nspecial > 0) { /* ignore initial white space */ c = an_wingetc(input); --nspecial; } if (c <= ' ') return 0; /* nothing more 1993/Sep/7 */ // if (nspecial <= 0) return 0; /* nothing more */ if (c == '\"') { /* deal with quoted string */ marker = '\"'; if (nspecial <= 0) return 0; /* nothing more */ /* 93/Sep/7 */ c = an_wingetc(input); --nspecial; } // if (nspecial <= 0) return 0; /* nothing more */ /* while (c > ' ' && nspecial >= 0) { */ while (c != marker && c >= ' ') { /* *s++ = (char) c; */ if(k++ >= nmax) { /* fprintf(stderr, " Token in special too long (> %d)\n", nmax); */ showbeginning(buff); /* errcount(); */ // c = an_wingetc(input); // --nspecial; // while(c > ' ' && nspecial > 0) { // c = an_wingetc(input); // --nspecial; // } flushspecial(input); break; } *s++ = (char) c; /* moved down 95/Aug/30 */ if (nspecial <= 0) { /* hit end of special ? */ if (marker != ' ') { /* complain if marker is not ` ' ...*/ sprintf(debugstr, " Missing `%c' in special\n", marker); winerror(debugstr); } /* above added 1993/Sep/7 */ /* c = ' '; */ /* pretend finished with space */ c = marker; /* pretend hit desired marker */ break; } c = an_wingetc(input); --nspecial; } *s = '\0'; return c; /* return terminator */ } void analspecial(HDC, int, int); /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ int readimagefile (HDC, char *, int, int, int, int, int, int); void DrawFigureBox(HDC hDC, int xll, int yll, int xur, int yur) { HPEN hOldPen=NULL; POINT Box[5]; /* 93/Jan/22 */ /* if (bCopyFlag != 0) return; */ /* 95/April/15 OK */ hOldPen = SelectObject(hDC, hFigurePen); /* ??? */ Box[0].x = xll; Box[0].y = yll; Box[1].x = xur; Box[1].y = yll; Box[2].x = xur; Box[2].y = yur; Box[3].x = xll; Box[3].y = yur; Box[4].x = xll; Box[4].y = yll; Polyline(hDC, Box, 5); /* 93/Jan/22 */ if ((UINT) hOldPen > 1) /* avoid Windows 3.0 MetaFile problem */ (void) SelectObject(hDC, hOldPen); } int ShowNameFile(HDC hDC, int xll, int yll, int xur, int yur, char *filename) { long atsize; int nHeight; HFONT hFont=NULL, hOldFont=NULL; SIZE TextSize; int xmd, ymd, dx, dy; COLORREF SavedTextColor, SavedBackColor; int k; int flag=0; /* return non-zero if text was too large */ /* can't use GetTextExtent in MetaFile DC, so why bother with file name */ /* can't retrieve old text or background color in MetaFile DC */ if (bCopyFlag != 0) return 0; /* 95/April/15 */ if (*filename == '\0') return 0; atsize = (((long) CaptionFontSize) * 16384) / 5; nHeight = mapd(atsize); if (captionindex < 0) { /* don't know yet what to use ? 93/Aug/26 */ /* for (k = 0; k < 16; k++) */ /* Reuse FakeFonts in dviwindo.c instead */ for (k = 4; k < 16; k++) { /* if (strcmp(CaptionFonts[k], "") == 0) break; */ if (strcmp(FakeFonts[k], "") == 0) break; /* hFont = createatmfont(CaptionFonts[k], nHeight, 0, 0, 0, 0); */ hFont = createatmfont(FakeFonts[k], nHeight, 0, 0, 0, 0); if (hFont != NULL) { captionindex=k; #ifdef DEBUGGING if (bDebug > 1) { sprintf(debugstr, "Using %s (%d) for caption font", /* CaptionFonts[k], captionttf ? " (TT)" : "", k);*/ FakeFonts[k], k); OutputDebugString(debugstr); } #endif break; } } /* if (captionindex < 0) { if (bDebug > 1) OutputDebugString("Can't find caption font!\n"); } */ /* debugging */ } /* we found a suitable caption font on a previous visit ... */ /* else hFont = createatmfont(CaptionFonts[captionindex], nHeight, 0, 0, 0, 0);*/ else hFont = createatmfont(FakeFonts[captionindex], nHeight, 0, 0, 0, 0); /* if (bCopyFlag != 0) return 0; */ /* 95/April/15 */ /* we hope ATM is not in some weird reencoded state at this point ... */ if (hFont != NULL) hOldFont = SelectObject(hDC, hFont); if (bCopyFlag) { dx = 0; dy = 0; } else { /* use GetTextExtentPoint32 in WIN32 ? */ /* this is just for showing file name - no need to reencode */ (void) GetTextExtentPoint32(hDC, filename, (int) strlen(filename), &TextSize); /* (void) GetTextExtentPoint(hDC, filename, (int) strlen(filename), &TextSize); */ dx = TextSize.cx; dy = TextSize.cy; } /* we don't get here if bCopyFlag != 0 */ /* otherwise return from SetTextColor & SetBkColor would be useless ... */ /* SavedTextColor = SetTextColor(hDC, RGB(128, 0, 128));*/ /* frame color */ SavedTextColor = SetTextColor(hDC, FrameColor); /* frame color 94/Sep/20 */ SavedBackColor = SetBkColor(hDC, BkColor); /* 92/June/25 */ /* only show the darn name it fits in the box */ if (dx < (xur - xll) && dy < (yur - yll)) { xmd = (xll + xur - dx) / 2; ymd = (yll + yur - dy) / 2; MoveToEx(hDC, xmd, ymd, NULL); /* this is just for showing file name - no need to reencode */ (void) TextOut(hDC, 0, 0, filename, (int) strlen(filename)); } else flag = 1; /* indicate failure */ /* if ((UINT) SavedTextColor > 1) */ (void) SetTextColor(hDC, SavedTextColor); /* if ((UINT) SavedBackColor > 1) */ (void) SetBkColor(hDC, SavedBackColor); /* 92/June/25 */ if (hFont != NULL) { if ((UINT) hOldFont > 1) /* avoid Windows 3.0 MetaFile problem */ (void) SelectObject(hDC, hOldFont); if ((UINT) hFont > 1) (void) DeleteObject(hFont); } cp_valid = 0; /* ??? */ return flag; } /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ long ImageWidth, ImageLength; /* width and height of image */ long BitsPerSample, ExtraSamples; long SamplesPerPixel, SamplesPerPixelX; long compression, Orientation; long PlanarConfiguration, Predictor; long colormap; int colormaptype, colormaplength; int nColors; long BitsPerPixel; /* BitsPerSample * SamplePerPixel */ long BitsPerPixelX; /* BitsPerSample * (SamplePerPixel-ExtraSamples) */ long MinSampleValue, MaxSampleValue; int ResolutionUnit=2; /* 93/Oct/20 */ /* long xresnum, xresden; */ /* 93/Oct/20 */ /* long yresnum, yresden; */ /* 93/Oct/20 */ unsigned long xresnum, xresden; /* 95/Oct/10 */ unsigned long yresnum, yresden; /* 95/Oct/10 */ int hptagflag=0; /* non-zero if call from HPTAG */ /* may need something more elaborate hleft / hright and vhigh / vlow */ long PhotometricInterpretation; /* 0 for reversed binary images */ int bCMYK=0; /* non-zero if CMYK rather than RGB 2000 May 27 */ int mingrey, maxgrey, flip; long StripOffset, StripByteCount; long StripOffsetsPtr; int StripOffsetsType; int StripOffsetsLength; long StripByteCountsPtr; int StripByteCountsType; int StripByteCountsLength; long RowsPerStrip, StripsPerImage; long InRowLength; /* number of source bytes from file */ long InRowLengthX; /* after removing ExtraSamples */ long OutRowLength; /* number of processed bytes for output */ long BytesPerRow; /* number of destination bytes in bitmap */ /* int checksum; */ /* x * (numer / denom) 1995/Oct/12 */ long MulRatio (long x, unsigned long numer, unsigned long denom) { if (denom == 0 || numer == 0) return 0; else return(MulDiv(x, numer, denom)); /* 97/Sep/25 */ } /* long MulRatio(long x, unsigned long numer, unsigned long denom) { long result; if (denom == 0 || numer == 0) return 0; if ((numer % denom) == 0) { numer = numer / denom; denom = 1; } if ((denom % numer) == 0) { denom = denom / numer; numer = 1; } while (denom > 65536 || numer > 65536) { denom = denom >> 1; numer = numer >> 1; } result = x / denom * numer; return result; } */ int wmfflag=0; /* set in readimagefile */ int bmpflag=0; /* set in readimagefile */ /* actually insert the TIFF (or WMF? or BMP?) figure here */ /* negative nifd indicates figure missing - draw box and filename only */ /* if dheight == 0 => calculate dheight from dwidth based on aspect ratio */ /* added scaling (xscale, yscale) possibility 99/July/2 */ void showtiffhere (HDC hDC, char *filename, long dwidth, long dheight, double xscale, double yscale, int nifd) { int xll=0, yll=0, xur=0, yur=0; RECT FigureRect; #ifdef DEBUGTIFF char *stype; #endif #ifdef DEBUGTIFF /* can't use wmfflag and bmpflag yet - since not set */ if (strstr(filename, ".wmf") != NULL) stype = "WMF"; else if (strstr(filename, ".tif") != NULL) stype = "TIFF"; else if (strstr(filename, ".bmp") != NULL) stype = "BMP"; else if (strstr(filename, ".eps") != NULL) stype = "EPS"; else stype=""; #endif #ifdef DEBUGTIFF if (bDebug > 1) { /* sprintf(debugstr, "ShowTIFFHere: %s dwidth %ld dheight %ld", */ sprintf(debugstr, "Show%sHere: %s dwidth %ld dheight %ld", stype, filename, dwidth, dheight); OutputDebugString(debugstr); } /* debugging 95/April/13 */ #endif if (bShowFlag != 0 && bTextOutFlag != 0) { /* if (dheight == 0) */ if (dheight == 0 || dwidth == 0) { /* do a pre-scan to extract fields */ /* (void) readimagefile(hDC, filename, xll, yll, xur, yur, nifd, 0) */ if (readimagefile(hDC, filename, xll, yll, xur, yur, nifd, 0) != 0) return; /* 94/Nov/19 */ /* check again after prescan */ #ifdef DEBUGTIFF if (bDebug > 1) { sprintf(debugstr, "dwidth %ld dheight %ld AFTER PRESCAN", dwidth, dheight); OutputDebugString(debugstr); } /* debugging 95/April/13 */ #endif if (dwidth == 0 && dheight == 0) { /* 95/April/13 ? */ /* dwidth = (ImageWidth * xresden / xresnum) << 16; */ /* dheight = (ImageLength * yresden / yresnum) << 16; */ if (xresnum == 0 || yresnum == 0) { /* 94/Nov/19 */ if (bDebug > 1) { sprintf(debugstr, "xres %lu / %lu yres %lu / %lu unit %d", xresnum, xresden, yresnum, yresden, ResolutionUnit); OutputDebugString(debugstr); } /* xresnum = yresnum = 72; */ /* 96/Apr/3 */ xresnum = yresnum = nDefaultTIFFDPI; /* return; */ /* 1996/Apr/4 */ } /* dwidth = ((long) ImageWidth << 16) / xresnum * xresden; */ dwidth = MulRatio ((long) ImageWidth << 16, xresden, xresnum); /* dheight = ((long) ImageLength << 16) / yresnum * yresden; */ dheight = MulRatio ((long) ImageLength << 16, yresden, yresnum); if (ResolutionUnit == 1) { /* what to do ? */ if (bDebug > 1) OutputDebugString("ResolutionUnit == 1"); } else if (ResolutionUnit == 2) { /* 72.27 pt per in */ dwidth = dwidth / 100 * 7227; dheight = dheight / 100 * 7227; } else if (ResolutionUnit == 3) { /* 28.45 pt per cm */ dwidth = dwidth / 100 * 2845; dheight = dheight / 100 * 2845; } } /* if dwidth == 0 && dheight == 0 *after* prescan */ /* changed order of multiplication and division to avoid overflow 94/Dec/16 */ else if (dheight == 0) { if (ImageWidth != 0) /* dheight = (ImageLength * dwidth) / ImageWidth; */ /* dheight = (dwidth / ImageWidth) * ImageLength; */ dheight = MulRatio(dwidth, ImageLength, ImageWidth); } else if (dwidth == 0) { if (ImageLength != 0) /* dwidth = (ImageWidth * dheight) / ImageLength; */ /* dwidth = (dheight / ImageLength) * ImageWidth; */ dwidth = MulRatio(dheight, ImageWidth, ImageLength); } /* added 99/July/2 */ if (xscale != 0.0) dwidth = (long) ((double) dwidth * xscale); if (yscale != 0.0) dheight = (long) ((double) dheight * yscale); } /* if dwidth == 0 || dheight == 0 when we come into readtiffimage */ #ifdef DEBUGTIFF if (bDebug > 1) { sprintf(debugstr, "Show%sHere: dwidth %ld dheight %ld", stype, dwidth, dheight); OutputDebugString(debugstr); } /* 94/Dec/16 */ #endif xll = mapx(dvi_h); xur = mapx(dvi_h + dwidth); if (hptagflag) { /* 95/Oct/12 */ yll = mapy(dvi_v + dheight); yur = mapy(dvi_v); } else { /* current point is at bottom left corner */ yll = mapy(dvi_v); yur = mapy(dvi_v - dheight); } #ifdef DEBUGTIFF if (bDebug > 1) { sprintf(debugstr, "Show%sHere: xll %d yll %d xur %d yur %d", stype, xll, yll, xur, yur); OutputDebugString(debugstr); /* experiment */ } /* debugging 95/April/13 */ #endif FigureRect.left = xll; FigureRect.right = xur; FigureRect.bottom = yll; FigureRect.top = yur; /* First check whether the TIFF image is even visible */ /* We won't worry here about Windows 95 bug in RectVisible *//* why ??? */ /* Avoid RectVisible() in MetaFile - use InterSectRect instead */ if ((bCopyFlag == 0 && RectVisible(hDC, &FigureRect) != 0) || (bCopyFlag != 0 && InterSectRect(&CopyClipRect, &FigureRect) != 0)) { /* if (bBoxFigure != 0) DrawFigureBox(hDC, xll, yll, xur, yur); if (bShowFileName != 0) ShowNameFile(hDC, xll, yll, xur, yur, filename); */ if (bShowImage != 0) { if(nifd < 0 || bShowPreview == 0 || /* 93/April/9 */ readimagefile(hDC, filename, xll, yll, xur, yur, nifd, -1) < 0) { if (bShowFileName != 0) { DrawFigureBox(hDC, xll, yll, xur, yur); ShowNameFile(hDC, xll, yll, xur, yur, filename); } } } } #ifdef DEBUGTIFF else if (bDebug > 1) { sprintf(debugstr, "Not visible xll %d yll %d xur %d yur %d", xll, yll, xur, yur); OutputDebugString (str); } #endif } } /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ /* This attempts to do Textures style color calls */ /* Does not do anything about rule color, only text color */ /* Does not do anything about BackgroundColor only TextColor */ /* Does not do anything fancy about CMYK instead of RGB */ /* Does not do anything about page boundaries - should it ? */ /* 1 - .30 * C - .59 * M - .11 * Y - K => setgray on B/W devices */ /* .30 * R + .59 * G + .11 * B => setgray on B/W devices ? */ /* Arguments r, g, b here are from 0 - 255 */ void SetupRuleColor (HDC hDC, int r, int g, int b) { /* split out 95/Mar/8 */ HPEN hOldPen; /* use color also for TPIC outline pen operations */ rule_r = r; rule_g = g; rule_b = b; /* save for TPIC \specials */ /* use color also for TPIC fill operations 96/Mar/31 */ tpic_r = r; tpic_g = g; tpic_b = b; /* save for TPIC \specials */ /* need RulePen whether filling rules or not */ if (r == 0 && g == 0 && b == 0) hRulePen = hBlackPen; /* else hRulePen = CreatePen(PS_SOLID, 10, RGB(r, g, b)); */ else hRulePen = CreatePen(PS_SOLID, 0, RGB(r, g, b)); hOldPen = SelectObject(hDC, hRulePen); /* if (hOldPen != hBlackPen) */ if (hOldPen != hRulePenDefault) { if ((UINT) hOldPen > 1) (void) DeleteObject(hOldPen); } /* need RuleBrush only when filling rules */ /* then it exists, but not selected into device context */ if (bRuleFillFlag != 0) { if (hRuleBrush != NULL && hRuleBrush != hRuleBrushDefault) { if ((UINT) hRuleBrush > 1) (void) DeleteObject(hRuleBrush); } if (r == 0 && g == 0 && b == 0) hRuleBrush = hBlackBrush; else hRuleBrush = CreateSolidBrush(RGB(r, g, b)); } /* OldRuleColor = RuleColor; */ RuleColor = RGB(r, g, b); /* 94/July/6 */ } /* clean up color stack and reset screen state */ /* called from winanal.c at do_eop */ void CheckColorStack(HDC hDC) { /* 96/Nov/3 ??? */ int r, g, b; if (colorindex == 0) return; /* nothing left on stack */ if (bCarryColor == 0) colorindex = 0; if (colorindex == 0) { /* 98/Feb/14 ??? */ CurrentTextColor = ColorStack[colorindex]; (void) SetTextColor(hDC, CurrentTextColor); r = GetRValue (CurrentTextColor); g = GetGValue (CurrentTextColor); b = GetBValue (CurrentTextColor); SetupRuleColor(hDC, r, g, b); } } /* Ugh: Presumably GetTextColor won't work in Copying to clipboard ??? */ void doColorPush (HDC hDC) { /* if (bCopyFlag == 0) ColorStack[colorindex] = GetTextColor (hDC); else ColorStack[colorindex] = CurrentTextColor; */ ColorStack[colorindex] = CurrentTextColor; /* 98/Feb/21 */ #ifdef DEBUGCOLORSTACK if (bDebug > 1) { int r, g, b; r = GetRValue (CurrentTextColor); g = GetGValue (CurrentTextColor); b = GetBValue (CurrentTextColor); sprintf(debugstr, "doColorPUSH colorindex %d RGB %d %d %d", colorindex, r, g, b); OutputDebugString(debugstr); } #endif colorindex++; if (colorindex >= MAXCOLORSTACK) /* quietly overflow */ colorindex = MAXCOLORSTACK-1; } /* hDC unreferenced */ void doColorPop (HDC hDC) { int r, g, b; /* colorindex--; */ /* if (colorindex < 0) colorindex = 0; */ /* quietly ignore stack underflow */ /* happens on first page */ if (colorindex <= 0) colorindex = 1; CurrentTextColor = ColorStack[--colorindex]; /* pop */ /* if ((UINT) CurrentTextColor > 1) */ /* verify its OK */ (void) SetTextColor(hDC, CurrentTextColor); /* set */ /* OldColor = ColorStack[colorindex]; */ /* rule color ? */ r = GetRValue (CurrentTextColor); g = GetGValue (CurrentTextColor); b = GetBValue (CurrentTextColor); SetupRuleColor(hDC, r, g, b); #ifdef DEBUGCOLORSTACK if (bDebug > 1) { sprintf(debugstr, "doColorPOP colorindex %d RGB %d %d %d", colorindex, r, g, b); OutputDebugString(debugstr); } #endif } /* Do DVIPS / Textures style color calls */ /* \special{color cmyk } */ /* \special{color rgb } */ /* \special{color gray } */ /* \special{color push} and \special{color pop} */ /* also allow combinations such as: \special{color push rgb } */ /* also called from winpslog.c in checkspecial in scanlogfile c == 0*/ /* to maintain current color and stack for end of page */ /* c == 0 during prescan */ void DoColor (HDC hDC, int input, int c) { /* 95/Feb/26 */ char *s; int r, g, b, n, setcolor=0; double fr, fg, fb; double fc, fy, fm, fk; s = line + strlen(line); if (c > 0) *s++ = (char) c; /* stick in terminator */ *s = '\0'; /* just in case */ if (nspecial > 0) /* read rest of line */ readspecial (input, s, sizeof(line) - strlen(line)); if (c > 0) { /* 98/Feb/15 */ if (bColorFont != 0 || markfont >= 0) return; /* 96/Nov/3 */ } else { /* prescan situation 98/Feb/15 */ s = line; while (*s != ' ' && *s != '\0') s++; /* step up to white space */ } /* if (bDebug > 1) OutputDebugString(line); */ /* 99/Feb/21 test */ for(;;) { /* allow multiple commands */ while (*s <= ' ' && *s != '\0') s++; /* step over white space */ if (*s == '\0') break; /* processed all of them */ if (strncmp(s, "pop", 3) == 0) { doColorPop(hDC); s += 3; } else if (strncmp(s, "popall", 6) == 0) { /* 96/Nov/3 */ colorindex = 0; CurrentTextColor = ColorStack[colorindex]; /* if ((UINT) CurrentTextColor > 1) */ /* verify its OK */ (void) SetTextColor(hDC, CurrentTextColor); /* OldColor = ColorStack[colorindex]; */ /* rule color ? */ r = GetRValue (CurrentTextColor); g = GetGValue (CurrentTextColor); b = GetBValue (CurrentTextColor); SetupRuleColor(hDC, r, g, b); s += 6; } else if (strncmp(s, "push", 4) == 0) { doColorPush(hDC); s += 4; } else if (strncmp(s, "rgb", 3) == 0) { s += 3; if (sscanf(s, "%lg %lg %lg%n", &fr, &fg, &fb, &n) == 3) { setcolor=1; s += n; } else if (bComplainSpecial != 0) { winbadspecial(line); /* 96/Feb/4 */ break; } } else if (strncmp(s, "cmyk", 4) == 0) { s += 4; if (sscanf(s, "%lg %lg %lg %lg%n", &fc, &fm, &fy, &fk, &n) == 4) { setcolor=1; fr = 1.0 - fc - fk; fg = 1.0 - fm - fk; fb = 1.0 - fy - fk; if (fr < 0.0) fr = 0.0; if (fg < 0.0) fg = 0.0; if (fb < 0.0) fb = 0.0; s += n; } else if (bComplainSpecial != 0) { winbadspecial(line); /* 96/Nov/3 */ break; } } else if (strncmp(s, "gray", 4) == 0) { s += 4; if (sscanf(s, "%lg%n", &fk, &n) == 1) { setcolor=1; fr = fg = fb = fk; s += n; } else if (bComplainSpecial != 0) { winbadspecial(line); /* 96/Feb/4 */ break; } } else if (_strnicmp(s, "black", 5) == 0) { /* 96/Feb/4 */ s += 5; setcolor=1; fr = fg = fb = 0.0; } else if (_strnicmp(s, "white", 5) == 0) { /* 96/Feb/4 */ s += 5; setcolor=1; fr = fg = fb = 1.0; } else if (bComplainSpecial != 0) { /* 95/April/30 */ winbadspecial(line); /* 96/Feb/4 */ break; } if (setcolor) { /* if "rgb" or "cmyk" or "gray" seen */ r = (int) (fr * 255.9999); g = (int) (fg * 255.9999); b = (int) (fb * 255.9999); if (OldFore >= 0 || OldBack >= 0) { r = 255 - r; g = 255 - g; b = 255 - b; } CurrentTextColor = RGB(r, g, b); if (c > 0) { OldTextColor = SetTextColor(hDC, CurrentTextColor); SetupRuleColor (hDC, r, g, b); /* 95/Mar/8 */ } } /* if (setcolor) */ } /* for ( ; ; ) */ } /* Attempt at \special{background rgb 0 0 1} support 98 June 4 */ /* so far incomplete - effect is to just ignore background \special */ /* c == 0 during prescan (and this should not be called otherwise) */ void DoBackGround (HDC hDC, int input, int c) { /* 95/Feb/26 */ char *s; int r, g, b, n, setcolor=0; double fr, fg, fb; double fc, fy, fm, fk; s = line + strlen(line); if (c > 0) *s++ = (char) c; /* stick in terminator */ *s = '\0'; /* just in case */ if (nspecial > 0) /* read rest of line */ readspecial (input, s, sizeof(line) - strlen(line)); /* if (bDebug > 1) OutputDebugString(line); */ /* 99/Feb/21 test */ if (c > 0) return; /* only do in prescan ! */ if (c > 0) { /* 98/Feb/15 */ if (bColorFont != 0 || markfont >= 0) return; /* 96/Nov/3 */ } s = line; while (*s != ' ' && *s != '\0') s++; /* step up to white space */ while (*s <= ' ' && *s != '\0') s++; /* step over white space */ if (*s == '\0') return; if (strncmp(s, "rgb", 3) == 0) { s += 3; if (sscanf(s, "%lg %lg %lg%n", &fr, &fg, &fb, &n) == 3) { setcolor=1; s += n; } else if (bComplainSpecial != 0) { winbadspecial(line); /* 96/Feb/4 */ return; } } else if (strncmp(s, "cmyk", 4) == 0) { s += 4; if (sscanf(s, "%lg %lg %lg %lg%n", &fc, &fm, &fy, &fk, &n) == 4) { setcolor=1; fr = 1.0 - fc - fk; fg = 1.0 - fm - fk; fb = 1.0 - fy - fk; if (fr < 0.0) fr = 0.0; if (fg < 0.0) fg = 0.0; if (fb < 0.0) fb = 0.0; s += n; } else if (bComplainSpecial != 0) { winbadspecial(line); /* 96/Nov/3 */ return; } } else if (strncmp(s, "gray", 4) == 0) { s += 4; if (sscanf(s, "%lg%n", &fk, &n) == 1) { setcolor=1; fr = fg = fb = fk; s += n; } else if (bComplainSpecial != 0) { winbadspecial(line); /* 96/Feb/4 */ return; } } else if (_strnicmp(s, "black", 5) == 0) { /* 96/Feb/4 */ s += 5; setcolor=1; fr = fg = fb = 0.0; } else if (_strnicmp(s, "white", 5) == 0) { /* 96/Feb/4 */ s += 5; setcolor=1; fr = fg = fb = 1.0; } else if (bComplainSpecial != 0) { /* 95/April/30 */ winbadspecial(line); /* 96/Feb/4 */ return; } if (setcolor) { /* if "rgb" or "cmyk" or "gray" seen */ r = (int) (fr * 255.9999); g = (int) (fg * 255.9999); b = (int) (fb * 255.9999); if (OldFore >= 0 || OldBack >= 0) { r = 255 - r; g = 255 - g; b = 255 - b; } GrabBack(); /* lpBack[dvipage] = RGB(r, g, b); */ lpBack[pageno] = RGB(r, g, b); /* ReleaseBack(); */ if (bDebug > 1) { sprintf(debugstr, "page %d back clr %X (rgb %d %d %d)", pageno, lpBack[dvipage], r, g, b); OutputDebugString(debugstr); } ReleaseBack(); /* actually, ignore while doing page ? *//* called from winpslog.c */ /* if (c > 0) { OldBackColor = SetBkColor(hDC, CurrentBackColor); } */ } } /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ /* Look at \special string, extract string and strip leading white space */ /* Remove enclosing "..." if present */ /* White space or comma or end of special is delimiter */ /* Also returns pointer to buttoname in original string */ char *getbuttonname (char buttonname[], char *s) { int m; char *t; /* while (*s <= ' ') s++; */ /* search for non-space */ while (*s <= ' ' && *s > 0) s++; /* search for non-space */ if (*s == '\"') { /* deal with "..." case */ s++; t = s; /* while (*t != '\"' && t < s + MAXMARKS) t++; */ while (*t != '\"' && *t > 0 && t < s + MAXMARKS) t++; } else { t = s; /* while (*t > ' ' && t < s + MAXMARKS) t++; */ /* 95/Dec/20 */ while (*t > ' ' && *t != ',' && t < s + MAXMARKS) t++; } /* *t = '\0'; */ if (t != s) { m = t - s; if (m > MAXMARKS) m = MAXMARKS; /* 94/Dec/13 */ strncpy(buttonname, s, m); buttonname[m] = '\0'; } return s; } /* returns pointer into special string where button name starts */ /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ /* new to allow quoted file names with spaces 98/Jul/9 */ char *scaninsert(char *line, char *filename) { char *s = line; char *t = filename; *filename = '\0'; while (*s <= ' ' && *s != '\0') s++; /* step over white space */ if (*s == '\0') return 0; if (*s == '\"') { /* is it quoted file name ? */ s++; /* step over initial " */ while (*s != '\"' && *s != '\0') *t++ = *s++; if (*s != '\0') s++; /* step over final " */ } else { /* normal file name */ while (*s > ' ' && *s != '\0') *t++ = *s++; } *t = '\0'; if (*s <= ' ' && *s != '\0') s++; /* step over white space after name */ /* special hack to convert ## to # */ if ((t = strstr(filename, "##")) != NULL) strcpy(t, t+1); if (bDebug > 1) { sprintf(debugstr, "line: %s filename: %s", line, filename); OutputDebugString(debugstr); } return s; } /* int rule_r, rule_g, rule_b; */ /* main entry point coming from winanal.c */ void dospecial(HDC hDC, int input, unsigned long n) { HPEN hOldPen; int nifd; char filename[MAXFILENAME]; long dwidth, dheight; double xscale, yscale; long dx, dy; long xll, yll, xur, yur; /* long offadj; */ int dxll, dyll, dxur, dyur; /* int tmp; */ int c, m; int button; char *s, *samp, *t; /* char *t; */ char buttonname[MAXMARKS+1]=""; /* label of button */ int r=0, g=0, b=0, rback=255, gback=255, bback=255; double fr=0.0, fg=0.0, fb=0.0; /* experiment 94/Mar/3 */ double frback=0.0, fgback=0.0, fbback=0.0; /* experiment 94/Mar/3 */ /* RECT RuleRect; */ nspecialsav = nspecial; /* save length for error message output */ specstart = an_wintell(input); /* save start in case of error (?) */ if (bIgnoreSpecial != 0) { flushspecial(input); return; } c = an_wingetc(input); --nspecial; while (c == ' ') { /* flush leading spaces - 1999/Apr/23 */ c = an_wingetc(input); --nspecial; } if (c == 0 && bFirstNull) { /* 96/Aug/29 */ flushspecial(input); return; } /* NO support for `literal graphics' kludge in dvips - start with " */ if (c == '\"') { flushspecial(input); /* basically for now */ /* copystring(input); */ /* PS passthrough ? */ return; } /* NO support for `literal macros' kludge in dvips - start with ! */ if (c == '!') { /* 1997 Nov 26 */ flushspecial(input); /* basically for now */ /* copystring(input); */ /* should be done in prepass */ return; } an_unwingetc(c, input); nspecial++; if ((c = getalphatoken(input, line, sizeof(line))) == 0) { if (bComplainSpecial != 0) winbadspecial("Blank \\special"); return; } if (strncmp(line, "if", 2) == 0) { /* new conditional option 99/July/2 */ if (strcmp(line+2, "view") != 0) { /* ignore all but ifview */ flushspecial(input); /* not for DVIWindo */ return; } else if ((c = getalphatoken(input, line, sizeof(line))) == 0) { /* recurse */ if (bComplainSpecial != 0) winbadspecial("Blank \\special"); return; /* found nothing ! */ } } /* drop through here normally */ /* see whether this is one of the new ones recognized here in DVIWindo */ if ((strcmp(line, "textcolor") == 0 || strcmp(line, "rulecolor") == 0 || strcmp(line, "figurecolor") == 0 || strcmp(line, "reversevideo") == 0 || strcmp(line, "button") == 0 || strcmp(line, "mark") == 0 || strcmp(line, "viewrule") == 0 || /* 95/Mar/27 */ strcmp(line, "viewtext") == 0 || /* 95/Mar/27 */ strcmp(line, "insertimage") == 0 || strcmp(line, "insertmf") == 0) /* 94/Sep/27 */ && n < BUFLEN) { /* don't look at it if is extremely long */ /* odd sort of test, since char line[MAXLINE], char str[BUFLEN] */ s = line + strlen(line); *s++ = (char) c; /* stick in terminator */ readspecial(input, s, sizeof(line) - strlen(line)); } else { /* not one of the DVIWindo specials */ analspecial(hDC, input, c); flushspecial(input); /* can't hurt ... */ return; } /* Deal with the known DVIWindo \specials now */ if (strncmp(line, "textcolor:", 10) == 0) { if (bColorFont == 0 && markfont < 0) { if (strstr(line, "revert") != NULL) { (void) SetTextColor(hDC, TextColor); /* 92/May/07 */ CurrentTextColor = TextColor; /* 95/April/30 */ /* (void) SetTextColor(hDC, OldTextColor); */ } /* else if(sscanf(line, "textcolor: %d %d %d", &r, &g, &b) == 3) */ else { if ((s = strchr(line, '.')) == NULL || *(s+1) < '0') { if (sscanf(line, "textcolor: %d %d %d", &r, &g, &b) == 3); else if (bComplainSpecial != 0) { /* wincancel(line); */ winbadspecial(line); /* 96/Feb/4 */ } } else { if (sscanf(line, "textcolor: %lg %lg %lg", &fr, &fg, &fb) == 3) { r = (int) (fr * 255.9999); g = (int) (fg * 255.9999); b = (int) (fb * 255.9999); } else if (bComplainSpecial != 0) { /* wincancel(line); */ winbadspecial(line); /* 96/Feb/4 */ } } if (OldFore >= 0 || OldBack >= 0) { r = 255 - r; g = 255 - g; b = 255 - b; } /* text_r = r; text_g = g; text_b = b; */ CurrentTextColor = RGB(r, g, b); /* OldTextColor = SetTextColor(hDC, RGB(r, g, b)); */ OldTextColor = SetTextColor(hDC, CurrentTextColor); } /* else if (bComplainSpecial != 0) wincancel(line); */ /* wincancel("Don't understand `textcolor' special"); */ } } else if (strncmp(line, "rulecolor:", 10) == 0) { if (strstr(line, "revert") != NULL) { /* new 92/May/07 */ hRulePen = hRulePenDefault; hOldPen = SelectObject(hDC, hRulePen); if (hOldPen != hRulePenDefault) { if ((UINT) hOldPen > 1) (void) DeleteObject(hOldPen); } if (bRuleFillFlag != 0) { if (hRuleBrush != hRuleBrushDefault) { if ((UINT) hRuleBrush > 1) (void) DeleteObject(hRuleBrush); } hRuleBrush = hRuleBrushDefault; } /* RuleColor = RGB(0,0,0); */ RuleColor = TextColor; } /* else if (sscanf(line, "rulecolor: %d %d %d", &r, &g, &b) == 3) */ else { if ((s = strchr(line, '.')) == NULL || *(s+1) < '0') { if (sscanf(line, "rulecolor: %d %d %d", &r, &g, &b) == 3) ; else if (bComplainSpecial != 0) { /* wincancel(line); */ winbadspecial(line); /* 96/Feb/4 */ } } else { if (sscanf(line, "rulecolor: %lg %lg %lg", &fr, &fg, &fb) ==3) { r = (int) (fr * 255.9999); g = (int) (fg * 255.9999); b = (int) (fb * 255.9999); } else if (bComplainSpecial != 0) { /* wincancel(line); */ winbadspecial(line); /* 96/Feb/4 */ } } SetupRuleColor(hDC, r, g, b); /* spliced out 95/Mar/8 */ #ifdef IGNORED rule_r = r; rule_g = g; rule_b = b; /* 92/May/09 */ /* need RulePen whether filling rules or not */ /* if (bRuleFillFlag == 0) */ if (r == 0 && g == 0 && b == 0) hRulePen = hBlackPen; /* else hRulePen = CreatePen(PS_SOLID, 10, RGB(r, g, b)); */ else hRulePen = CreatePen(PS_SOLID, 0, RGB(r, g, b)); hOldPen = SelectObject(hDC, hRulePen); /* if (hOldPen != hBlackPen) */ if (hOldPen != hRulePenDefault) { if ((UINT) hOldPen > 1) (void) DeleteObject(hOldPen); } /* } */ /* need RuleBrush only when filling rules */ if (bRuleFillFlag != 0) { /* else */ if (hRuleBrush != NULL && hRuleBrush != hRuleBrushDefault) { if ((UINT) hRuleBrush > 1) (void) DeleteObject(hRuleBrush); } if (r == 0 && g == 0 && b == 0) hRuleBrush = hBlackBrush; else hRuleBrush = CreateSolidBrush(RGB(r, g, b)); } /* OldRuleColor = RuleColor; */ /* 95/Mar/8 */ RuleColor = RGB(r, g, b); /* 94/July/6 */ #endif } /* bColorFont == 0 && markfont < 0 */ } /* end of rulecolor */ else if (strncmp(line, "figurecolor:", 12) == 0) { if (strstr(line, "revert") != NULL) { /* FigureColor = OldFigureColor; */ FigureColor = TextColor; /* 92/May/07 */ /* BackColor = OldBackColor; */ BackColor = BkColor; /* 92/May/07 */ } else { if ((s = strchr(line, '.')) == NULL || *(s+1) < '0') { if (sscanf(line, "figurecolor: %d %d %d %d %d %d", &r, &g, &b, &rback, &gback, &bback) >= 3) ; else if (bComplainSpecial != 0) { /* wincancel(line); */ winbadspecial(line); /* 96/Feb/4 */ } } else { if (sscanf(line, "figurecolor: %lg %lg %lg %lg %lg %lg", &fr, &fg, &fb, &frback, &fgback, &fbback) >= 3) { r = (int) (fr * 255.9999); g = (int) (fg * 255.9999); b = (int) (fb * 255.9999); rback = (int) (frback * 255.9999); gback = (int) (fgback * 255.9999); bback = (int) (fbback * 255.9999); } else if (bComplainSpecial != 0) { /* wincancel(line); */ winbadspecial(line); /* 96/Feb/4 */ } } OldFigureColor = FigureColor; FigureColor = RGB(r, g, b); OldBackColor = BackColor; BackColor = RGB(rback, gback, bback); } } else if (strncmp(line, "reversevideo:", 13) == 0) { if (strstr(line, "on") != NULL) bReverseVideo = 1; else if (strstr(line, "off") != NULL) bReverseVideo = 0; else if (strstr(line, "toggle") != NULL) bReverseVideo = 1 - bReverseVideo; else if (bComplainSpecial != 0) { /* wincancel("Don't understand `reversevideo' special"); */ /* wincancel(line); */ winbadspecial(line); /* 96/Feb/4 */ } if (markfont < 0) colorandreverse(); } else if (strncmp(line, "insertimage:", 12) == 0) { dwidth = dheight = 0; /* NEW - use for isotropic scaling */ xscale = yscale = 0.0; /* 99/July/2 */ nifd = 1; /* n-th (sub-)image in TIFF file */ /* if (sscanf(line, "insertimage: %s %ld %ld %d", filename, &dwidth, &dheight, &nifd) */ s = scaninsert(line+12, filename); if ((t = strstr(s, "scaled")) == NULL) { sscanf(s, "%ld %ld %d", &dwidth, &dheight, &nifd); /* normal */ } else { /* new case 99/July/2 */ sscanf(t+7, "%lg %lg", &xscale, &yscale); if (xscale > 33.33) xscale = xscale / 1000.0; if (yscale > 33.33) yscale = yscale / 1000.0; if (xscale != 0.0 && yscale == 0.0) yscale = xscale; if (xscale == 0.0) xscale = 1.0; if (yscale == 0.0) yscale = 1.0; } if (*filename != '\0') { /* need at least file name */ hptagflag = 0; if (bShowTIFF) /* allow suppression of 97/Jan/5 */ showtiffhere(hDC, filename, dwidth, dheight, xscale, yscale, nifd); } else if (bComplainSpecial != 0) { winbadspecial(line); /* 96/Feb/4 */ } } else if (strncmp(line, "insertmf:", 9) == 0) { /* 94/Sep/27 */ /* dwidth = 0; dheight = 0; */ xscale = yscale = 0.0; xll = yll = xur = yur = 0; /* 96/Apr/4 */ /* NEW FORM of insertmf: 0 0 96/Apr/4 */ /* if (sscanf(line, "insertmf: %s %ld %ld %ld %ld", filename, &xll, &yll, &xur, &yur) > 3 ) */ s = scaninsert(line+9 , filename); if (sscanf(s, "%ld %ld %ld %ld", &xll, &yll, &xur, &yur) > 2 ) { /* showmetafile(hDC, filename, (double) (xur - xll), (double) (yur - yll), 1); */ if (bShowWMF) /* allow suppression 97/Jan/7 */ showmetafile(hDC, filename, (double) (xur - xll), (double) (yll - yur), 1); /* vertical direction reversed ? 1996/July/16 */ #ifdef DEBUGMETAFILE if (bDebug > 1) OutputDebugString("After showmetafile"); #endif } /* OLD FORM of insertmf: */ /* NEW FORM of insertmf: scaled */ /* else if (sscanf(line, "insertmf: %s %lg %lg", filename, &xscale, &yscale) > 0) */ else if (*filename != '\0') { if ((t = strstr(s, "scaled")) != NULL) { sscanf(t+7, "%lg %lg", &xscale, &yscale); /* new 99/July/2 */ } else sscanf(s, "%lg %lg", &xscale, &yscale); if (xscale > 33.33) xscale = xscale / 1000.0; if (yscale > 33.33) yscale = yscale / 1000.0; if (xscale != 0.0 && yscale == 0.0) yscale = xscale; if (xscale == 0.0) xscale = 1.0; if (yscale == 0.0) yscale = 1.0; /* showmetafile(hDC, filename, xscale, yscale); */ if (bShowWMF) /* allow suppression 97/Jan/7 */ showmetafile(hDC, filename, xscale, yscale, 0); #ifdef DEBUGMETAFILE if (bDebug > 1) OutputDebugString("After showmetafile"); #endif } else if (bComplainSpecial != 0) { /* wincancel(line); */ winbadspecial(line); /* 96/Feb/4 */ } } else if (strncmp(line, "mark:", 5) == 0) { /* nothing to do */ /* bHyperUsed = 1;*/ /* indicate this file uses hypertext 94/Oct/5 */ } else if (strncmp(line, "button:", 7) == 0) { /* if (sscanf(line, "button: %d %ld %ld %ld %ld", &button, &xll, &yll, &xur, &yur) == 5) */ button = 0; if (bHyperText) /* set, but only if HyperText implemented */ bHyperUsed = 1; /* indicate file uses hypertext 94/Oct/5 */ /* optional third numeric arg is button number - no longer used ? */ if (sscanf(line, "button: %ld %ld%n %d", &dx, &dy, &m, &button) >= 2) { xll = dvi_h; yll = dvi_v; xur = xll + dx; yur = yll - dy; dxll = mapx(xll); dyll = mapy(yll); dxur = mapx(xur); dyur = mapy(yur); if (bShowButtons != 0) DrawFigureBox(hDC, dxll, dyll, dxur, dyur); /* now get the button label */ /* button name --- if any --- goes into buttonlabel[] - else empty string */ /* command string --- if any --- goes into str[] - else empty string */ buttonname[0] = '\0'; /* reset, in case not filled 95/Aug/12 */ s = line + m; s = getbuttonname (buttonname, s); /* flush supposed button name if its a command instead 95/Aug/12 */ /* if there is no mark name and we go straight into actions ... */ /* if (strchr(buttonname, ':') != NULL) */ /* fixed 95/Oct/3 */ if (strncmp(s, "file:", 5) == 0 || strncmp(s, "execute:", 8) == 0 || strncmp(s, "launch:", 7) == 0 || strncmp(s, "page:", 5) == 0) buttonname[0] = '\0'; /* allow for , launch: <...> , file: <...> 95/Aug/12 */ /* allow for page: <..> 96/May/18 */ /* comma is delimiter between hyper-text commands */ else if ((samp = strchr(s, ',')) != NULL) { s = samp+1; while (*s <= ' ' && *s > 0) s++; } /* if we grabbed launch / execute / file then keep on going */ if (strncmp(s, "file:", 5) == 0 || strncmp(s, "execute:", 8) == 0 || strncmp(s, "launch:", 7) == 0 || strncmp(s, "page:", 5) == 0) { /* maybe avoid the following to allow combined action 95/Aug/12 */ /* (void) getbuttonname (buttonname, strchr(s, ':')+1); */ /* overwrite `buttonname', but don't mess with s 95/April/30 */ } /* if comes after (but not before) launch: & or file: & ??? */ else if (*buttonname == '\0') (void) getbuttonname (buttonname, s); if (bShowButtons != 0) { #ifdef DEBUGBUTTON if (bDebug > 1) OutputDebugString(buttonname); #endif CaptionFontSize = CaptionFontSize / 2; ShowNameFile(hDC, dxll, dyll, dxur, dyur, buttonname); CaptionFontSize = CaptionFontSize * 2; } if (bMarkFlag != 0 && tagx >= dxll && tagx <= dxur && tagy >= dyll && tagy <= dyur) { /* What to do if we have a hit: */ buttonlabel[0] = '\0'; /* 95/Aug/12 */ str[0] = '\0'; /* 95/Aug/12 */ marknumber = button; if (strncmp(s, "file:", 5) == 0 || strncmp(s, "execute:", 8) == 0 || strncmp(s, "launch:", 7) == 0 || strncmp(s, "page:", 5) == 0) { /* 95/Feb/8 */ strcpy(str, s); #ifdef DEBUGHYPER if (bDebug > 1) OutputDebugString(debugstr); #endif /* buttonlabel[0] = '\0'; *//* indicate no button name */ } /* hyper execute added 94/Dec/13 */ else { strcpy(buttonlabel, buttonname); /* str[0] = '\0'; */ /* indicate ordinary button push */ } if (*buttonname != '\0') strcpy(buttonlabel, buttonname); buttonpos = an_wintell(input); /* lastsearch = an_wintell(input); */ buttondvipage = dvipage; /* EXPERIMENT 95/Mar/10 */ /* finish = -1; */ /* NO !!! Unless ShowFlag == 0 */ } } else if (bComplainSpecial != 0) { /* wincancel("Don't understand `button' special"); */ /* wincancel(line); */ sprintf(debugstr, "Bad hyper-text \\special: %s", line); winbadimage(debugstr); } } else if (strncmp(line, "viewrule:", 9) == 0) { /* 95/Mar/27 */ if (bPrintFlag == 0 && bCopyFlag == 0 && bViewExtras) { if (sscanf(line, "viewrule: %ld %ld%n", &dx, &dy, &m) >= 2) { /* xll = dvi_h; yll = dvi_v; xur = xll + dx; yur = yll - dy; */ /* dxll = mapx(xll); dyll = mapy(yll); */ /* dxur = mapx(xur); dyur = mapy(yur); */ DrawRule(dy, dx); /* DrawFigureBox(hDC, dxll, dyll, dxur, dyur); */ /* better rule ? */ /* if (bDebug > 1) { sprintf(debugstr, "viewrule: %d %d %d %d\n", dxll, dyll, dxur, dyur); OutputDebugString(debugstr); } */ } } } else if (strncmp(line, "viewtext:", 9) == 0) { /* 95/Mar/27 */ if (bShowFlag != 0 && bTextOutFlag != 0) { if (bPrintFlag == 0 && bCopyFlag == 0 && bViewExtras) { s = line + 9; while (*s <= ' ' && *s > 0) s++; dvi_hh = mapx(dvi_h); dvi_vv = mapy(dvi_v); /* ??? */ if (cp_valid == 0) /* moveto current pt */ (void) MoveToEx(hDC, dvi_hh, dvi_vv, NULL); (void) ExtTextOut(hDC, 0, 0, 0, NULL, s, strlen(s), NULL); cp_valid = 0; /* ??? */ /* if (bDebug > 1) { sprintf(debugstr, "viewtext: %s\n", s); OutputDebugString(debugstr); } */ } } } } /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ /* \special{tiff:/mount/mktpub_d1/users/temp_jobs/59625100nl/procroms.tif lib=control.glb xmag=1 ymag=1 hleft vhigh bclip=0.000000 lclip=0.000000 rclip=0.000000 tclip=0.000000 nostrip */ /* New stuff for HPTAG */ /* 95/Oct/12 */ /* int dohptag(HDC hDC, FILE *input) */ int dohptag(HDC hDC, int input) { /* double bclip=0, lclip=0, rclip=0, tclip=0; */ /* double xmag=1, ymag=1; */ /* int hleft=1, hright=0, vhigh=1, vlow=0; */ /* int nostrip=1; */ char *s, *t; char filename[MAXFILENAME]; /* (void) scanspecial(input, line, MAXLINE); */ (void) scanspecial(input, line, sizeof(line)); if ((s = strchr(line, ' ')) != NULL) *s = '\0'; if ((t = strrchr(line, '/')) != NULL) strcpy(filename, t+1); else if (strlen(line) < sizeof(filename)) strcpy(filename, line); else return 0; /* failure */ /* now analyze the rest of the line starting at s+1 */ /* showtiffhere(output, filename, dwidth, dheight, 0, 0, nifd); */ hptagflag = 1; if (bShowTIFF) /* allow suppression of 97/Jan/5 */ showtiffhere(hDC, filename, 0, 0, 0, 0, 1); return 1; /* success */ } /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ /* Stuff for reading simple uncompressed TIFF files (& PackBits compressed) */ unsigned int tiffversion; /* TIFF version number */ unsigned int leastfirst=1; /* least significant first */ unsigned int ifdcount; /* number of items image file directory */ unsigned long ifdposition; /* position of image file directory */ /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ /* following moved to end to try and avoid compiler error */ #ifdef LONGNAMES static unsigned int ureadtwo (HFILE); static unsigned long ureadfour(HFILE); #else static unsigned int ureadtwo (FILE *); static unsigned long ureadfour(FILE *); #endif /* char *typename[6] = {"", "BYTE ", "ASCII", "SHORT", "LONG ", "RATIO"}; */ int typesize[6] = {0, 1, 1, 2, 4, 8}; /* units of length/count */ /* struct tagname { unsigned int tag; char *name; }; */ /* header information from EPSF file */ long psoffset, pslength; long metaoffset, metalength; long tiffoffset, tifflength; /* we are ignoring the possibility here that length > 1 and such ... */ #ifdef LONGNAMES long indirectvalue(unsigned int type, long length, long offset, HFILE input) { #else long indirectvalue(unsigned int type, long length, long offset, FILE *input) { #endif long present, val=0; present = ftell(input); /* remember where we are */ if (fseek(input, (long) (offset + tiffoffset), SEEK_SET) != 0) { /* wincancel("Error in seek to indirect value"); */ winbadimage("Error in seek to indirect value"); return -1; } if (type == TYPE_LONG) val = (long) ureadfour(input); else if (type == TYPE_SHORT) val = ureadtwo(input); else if (type == TYPE_BYTE) val = getc(input); else { /* wincancel("Invalid Indirect Value"); */ winbadimage("Invalid Indirect Value"); } fseek(input, present, SEEK_SET); /* return to where we were */ return val; } /* length unreferenced */ /* get value of a tag field in TIFF file */ /* if value fits in 4 bytes or less, use offset itself */ #ifdef LONGNAMES long extractvalue (unsigned int type, unsigned long length, long offset, HFILE input) { #else long extractvalue (unsigned int type, unsigned long length, long offset, FILE *input) { #endif if (length == 0) return 0; switch(type) { case TYPE_BYTE: if (length <= 4) return offset; else return indirectvalue(type, (long) length, (long) offset, input); case TYPE_SHORT: if (length <= 2) return offset; else return indirectvalue(type, (long) length, (long) offset, input); case TYPE_LONG: if (length == 1) return offset; else return indirectvalue(type, (long) length, (long) offset, input); default: return -1; } } #ifdef LONGNAMES int skipthisimage (HFILE input, unsigned long ifdpos) { #else int skipthisimage (FILE *input, unsigned long ifdpos) { #endif int k, j; if (fseek(input, (long) ifdpos + tiffoffset, SEEK_SET) != 0) { sprintf(debugstr, "Error in seek to %ld", (long) ifdpos + tiffoffset); /* wincancel(str); */ winbadimage(debugstr); return -1; } ifdcount = ureadtwo(input); /* How many tags in this IFD */ for (k = 0; k < (int) ifdcount; k++) { /* read to end of IFD */ for (j = 0; j < 12; j++) (void) getc(input); } ifdposition = ureadfour(input); /* get next IFD offset in file */ if (ifdposition == 0) { return -1; /* no more IFDs !!! */ } return 0; } /* read the tag fields in the TIFF file, ignore ones we don't care about */ #ifdef LONGNAMES int readtifffields (HFILE input, unsigned long ifdpos) { #else int readtifffields (FILE *input, unsigned long ifdpos) { #endif unsigned int k, tag, type; unsigned long length, offset; int c; /* char *s; */ if (fseek(input, (long) ifdpos + tiffoffset, SEEK_SET) != 0) { sprintf(debugstr, "Error in seek to %ld", (long) ifdpos + tiffoffset); /* wincancel(str); */ winbadimage(debugstr); return -1; } ifdcount = ureadtwo(input); /* How many tags in this IFD */ ImageWidth = ImageLength = -1; SamplesPerPixel = BitsPerSample = 1; ExtraSamples = 0; /* default TIFF 6.0 99/May/10 */ compression = 0; Orientation = 1; StripOffset = -1; StripByteCount = -1; /* RowsPerStrip = 0; */ PhotometricInterpretation = 1; /* default */ PlanarConfiguration = 1; Predictor = 1; colormap = 0; /* pointer to map in case of Palette Color Images */ mingrey = -1; maxgrey = -1; /* xresnum = yresnum = 72; */ xresnum = yresnum = nDefaultTIFFDPI; /* 96/Apr/3 */ xresden = yresden = 1; /* 93/Oct/20 */ ResolutionUnit = 2; /* default dpi */ /* 93/Oct/20 */ for (k = 0; k < ifdcount; k++) { tag = ureadtwo(input); /* tag - key */ type = ureadtwo(input); /* value type */ if (tag == 0 && type == 0) { /* invalid */ c = getc(input); ungetc(c, input); sprintf(debugstr, "Tag: %u Type: %u (k %d c %d)\n", tag, type, k, c); winbadimage(debugstr); break; } if (type > 5) { if (bDebug > 1) { c = getc(input); ungetc(c, input); sprintf(debugstr, "Tag: %u Type: %u (k %d c %d)\n", tag, type, k, c); OutputDebugString(debugstr); } /* removed on screen warning 98/Sep/22 */ /* break; */ /* ignore 98/Sep/22 */ } length = ureadfour(input); /* count - length */ if (length == 1) { if (type == TYPE_LONG) offset = ureadfour(input); else if (type == TYPE_SHORT) { offset = ureadtwo(input); (void) ureadtwo(input); /* should be zero */ } else if (type == TYPE_BYTE) { offset = getc(input); (void) getc(input);(void) getc(input);(void) getc(input); } else offset = ureadfour(input); /* for ratio e.g. */ } else offset = ureadfour(input); /* value */ switch (tag) { case IMAGEWIDTH: ImageWidth = extractvalue(type, length, (long) offset, input); break; case IMAGELENGTH: ImageLength = extractvalue(type, length, (long) offset, input); break; case BITSPERSAMPLE: BitsPerSample = (int) extractvalue(type, length, (long) offset, input); break; case COMPRESSION: compression = (unsigned int) extractvalue(type, length, (long) offset, input); break; case SAMPLESPERPIXEL: SamplesPerPixel = extractvalue(type, length, (long) offset, input); break; case STRIPOFFSETS: StripOffset = extractvalue(type, length, (long) offset, input); StripOffsetsPtr = offset; StripOffsetsType = type; StripOffsetsLength = length; break; case STRIPBYTECOUNTS: StripByteCount = extractvalue(type, length, (long) offset, input); StripByteCountsPtr = offset; StripByteCountsType = type; StripByteCountsLength = length; break; case ROWSPERSTRIP: RowsPerStrip = extractvalue(type, length, (long) offset, input); break; case ORIENTATION: Orientation = extractvalue(type, length, (long) offset, input); break; case PLANARCONFIG: PlanarConfiguration = extractvalue(type, length, (long) offset, input); break; case PREDICTOR: Predictor = extractvalue(type, length, (long) offset, input); break; case EXTRASAMPLES: /* 1999/May/10 */ ExtraSamples = (int) extractvalue(type, length, (long) offset, input); break; case MINSAMPLEVALUE: MinSampleValue = extractvalue(type, length, (long) offset, input); mingrey = (int) MinSampleValue; break; case MAXSAMPLEVALUE: MaxSampleValue = extractvalue(type, length, (long) offset, input); maxgrey = (int) MaxSampleValue; break; case XRESOLUTION: /* 93/Oct/20 */ xresnum = indirectvalue(TYPE_LONG, 1, offset, input); xresden = indirectvalue(TYPE_LONG, 1, offset+4, input); break; case YRESOLUTION: /* 93/Oct/20 */ yresnum = indirectvalue(TYPE_LONG, 1, offset, input); yresden = indirectvalue(TYPE_LONG, 1, offset+4, input); break; case RESOLUTIONUNIT: ResolutionUnit = (int) extractvalue(type, length, (long) offset, input); break; case PHOTOMETRICINTERPRETATION: PhotometricInterpretation = extractvalue(type, length, (long) offset, input); break; case COLORMAP: colormap = offset; colormaptype = type; /* remember type */ colormaplength = (int) length; /* remember length */ /* extractvalue(type, length, (long) offset, input); */ break; default: /* ignore unknown tags */ break; } } return 0; } /**************************************************************************** * * * The EPSF header has the following structure: * * * * 0-3 the first four bytes are the letters EPSF with the meta-bit on - * * that is, hex C5D0D3C6. * * 4-7 the next four are the byte position of start of the PS section * * 8-11 The next four are the length of the PostScript part of file; * * 12-15 The next four are the byte position of start of MetaFile version; * * 16-19 The next four are the length of the MetaFile version; * * 20-23 The next four are the byte position of start of TIFF version; * * 24-27 The next four are the length of the TIFF version; * * 28-29 The next two bytes are the header checksum or hex FFFF * * that is, two bytes that are all ones (meta-control-? = 255) * * * * IN EACH CASE THE LOW ORDER BYTE IS GIVEN FIRST * * * * Either the MetaFile length or the TIFF length or both are zero * * * * If there is no MetaFile or Tiff version, the PS code starts at 30 * * * * The file produced as plain PS by Designer, instead starts and ends * * on control-D. The first control-D is followed by %, * * which is non-standard, to say the least. * * * ****************************************************************************/ /* Try and see whether EPSF file and read header info if so: */ /* fills in tiffoffset and psoffset and metaoffset and lengths */ /* returns zero if not an EPSF file */ /* file position is end of EPSF head */ /* called from checkpcform and showtiffhere */ #ifdef LONGNAMES int readepsfhead(HFILE special) { #else int readepsfhead(FILE *special) { #endif int c, d, e, f; psoffset = 0; /* redundant */ metaoffset = 0; /* redundant */ tiffoffset = 0; /* redundant */ c = getc(special); d = getc(special); e = getc(special); f = getc(special); if (c == 'E' + 128 && d == 'P' + 128 && e == 'S' + 128 && f == 'F' + 128) { leastfirst = 1; psoffset = (long) ureadfour(special); /* read PS start offset */ pslength = (long) ureadfour(special); /* read PS length */ metaoffset = (long) ureadfour(special); /* read MF start offset */ metalength = (long) ureadfour(special); /* read MF length */ tiffoffset = (long) ureadfour(special); /* read TIFF start offset */ tifflength = (long) ureadfour(special); /* read TIFF length */ (void) ureadtwo(special); /* should be 255, 255 */ return -1; } else return 0; /* not an EPSF file */ } /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ HPALETTE CreateBIPalette(LPBITMAPINFOHEADER); /* macros to break C "far" pointers into their segment and offset components*/ /* from dos.h */ /* #define FP_SEG(fp) (*((unsigned _far *)&(fp)+1)) */ /* #define FP_OFF(fp) (*((unsigned _far *)&(fp))) */ /* if (FP_SEG(s) == FP_SEG(s + InRowLength)) copy using far pointer else copy using huge pointer */ /* try this ? */ /* combine r, g, b into palette index - divide row length by 3 */ /* NOTE: RGBQUAD and RGBTRIPLE have byte order: Blue, Green, Red */ /* void compresscolor(char *buffer, unsigned int InRowLength, int lookup[]) */ void compresscolor (unsigned char far *buffer, unsigned int InRowLength, int lookup[]) { int r, g, b; unsigned int k, OutRowLength; /* char *s=buffer, *t=buffer; */ unsigned char far *s=buffer; unsigned char far *t=buffer; if (buffer == NULL) { /* winerror("NULL buffer in compresscolor"); */ /* debugging */ return; } OutRowLength = InRowLength / 3; for (k = 0; k < OutRowLength; k++) { r = *s++ & 255; g = *s++ & 255; b = *s++ & 255; if (bStretchColor) { r = lookup[r]; g = lookup[g]; b = lookup[b]; } /* Note: 224 = E0 (use top 3 bits) 192 = C0 (use top 2 bits) */ /* The 8 bit palette index is built as |rrr|ggg|bb| */ if (bBGRflag == 0) /* reversed 92/Feb/21 */ *t++ = (char) ((r & 224) | ((g & 224) >> 3) | ((b & 192) >> 6)); else *t++ = (char) ((b & 224) | ((g & 224) >> 3) | ((r & 192) >> 6)); } /* modified above 92/01/26 */ } /* Will this work correctly in both Standard and Enhanced Mode ? YES */ /* In standard mode segments are high part of real address */ /* In enhanced mode segments are index into table instead */ /* But this code does no arithmetic on segment part of address */ /* copy bytes from NEAR buffer to HUGE image array */ /* attempt to be efficient about it */ /* split up copy operation if crosses segment boundary */ /* IN FACT in WINVER >=0x03a, WE CAN USE _hread TO READ THE WHOLE THING */ /* should be easier - no need for breaking up into chunck then ? */ #ifndef USEMEMCPY void copynearimage (unsigned char *to, unsigned char *from, unsigned long count) { /* strncpy(to, from, count); */ #ifdef USEMEMCPY memcpy(to, from, count); #else while (count-- > 0) *to++ = *from++; #endif } #endif /* copy bytes from FAR buffer to HUGE image array */ /* attempt to be efficient about it */ /* split up copy operation if crosses segment boundary */ /* IN FACT in WINVER >=0x03a, WE CAN USE _hread TO READ THE WHOLE THING */ /* should be easier - no need for breaking up into chunck then */ #ifndef USEMEMCPY void copyfarimage(unsigned char *to, unsigned char *from, unsigned long count) { /* strncpy(to, from, count); */ #ifdef USEMEMCPY memcpy(to, from, count); #else while (count-- > 0) *to++ = *from++; #endif } #endif /* This opens the file and makes sure it is closed before exiting */ /* should perhaps have helper function that does not fclose ... */ /* called from `showtiffhere' */ /* readflag if only scanning for w * h */ int readimagefile (HDC hDC, char *filename, int xll, int yll, int xur, int yur, int nifd, int readflag) { char infilename[MAXFILENAME]; /* char epsfilename[MAXFILENAME]; */ /* 95/Apr/ 26 */ /* FILE *input=NULL; */ /* changed to => special */ long present; int c, d; char *s; wmfflag=0; bmpflag=0; strcpy(infilename, filename); /* extension(infilename, "tif"); */ /* use `tif' if no extension given */ /* if ((special = findepsfile(infilename, -1, "tif")) == NULL) { */ special = findepsfile(infilename, -1, "tif"); if (special == BAD_FILE) { /*if ((special = findepsfile(infilename, -1, "tif", epsfilename)) == NULL) {*/ /* sprintf(str, "Image file %s not found", t); wincancel(str); */ /* already complained about */ return -1; /* failed */ } tiffoffset = 0; /* normally beginning of file */ psoffset = 0; metaoffset = 0; /* First see whether this perhaps is an EPSF file with (TIFF) preview */ c = getc(special); (void) ungetc(c, special); if (c > 128) { /* see whether perhaps EPSF file */ if (readepsfhead(special) != 0) { /* is it EPSF file ? */ /* If valid EPSF header with pointer to TIFF we get here */ if (tiffoffset != 0 && tifflength != 0) { /* 95/Oct/1 */ if (fseek(special, tiffoffset, SEEK_SET) != 0) { if (bDebug > 1) { sprintf(debugstr, "Error in seek to %ld in %s", tiffoffset, filename); OutputDebugString(debugstr); /* 94/Oct/14 */ } fclose(special); /* special = NULL; */ special = BAD_FILE; return -1; } } /* If valid EPSF header with pointer to WMF we get here */ else if (metaoffset != 0 && metalength != 0) { /* 95/Oct/1 */ if (fseek(special, metaoffset, SEEK_SET) != 0) { if (bDebug > 1) { sprintf(debugstr, "Error in seek to %ld in %s", metaoffset, filename); OutputDebugString(debugstr); /* 94/Oct/14 */ } fclose(special); /* special = NULL; */ special = BAD_FILE; return -1; } } else { /* 95/Oct/1 */ if (bDebug > 1) { sprintf(debugstr, "Zero TIFF or WMF offset or length in %s", filename); OutputDebugString(debugstr); /* 94/Oct/14 */ } fclose(special); /* special = NULL; */ special = BAD_FILE; return -1; } /* if seek to TIFF or WMF preview *succeeds* we drop through here */ } /* end of readepsfhead (special) != 0 */ else { /* sprintf(str, "`%s' not a valid EPSF or TIFF file", filename); */ strcpy(debugstr, "Not a valid "); strcat(debugstr, "EPSF or TIFF file: "); strcat(debugstr, filename); winbadimage(debugstr); fclose(special); /* special = NULL; */ special = BAD_FILE; return -1; } } /* end of c > 128 (EPSF file) */ /* Next, try and deal with PostScript ASCII stuff EPSI preview maybe ? */ /* Or may meet TIFF / WMF preamble */ c = getc(special); /* Ignore white space at the start of the file 98/Jul/29 */ while (c <= ' ' && c > 1) c = getc(special); d = getc(special); /* if (c == '%' && d == '!') { */ /* ordinary PS file ? */ if (c == '%') { /* less strict 96/Sep/15 */ /* see whether file has EPSI preview ... */ /* 92/Jan/2 */ (void) getline(special, line); /* skip over first line */ (void) getline(special, line); /* grap next comment line */ /* winerror("Checking whether EPSI"); */ /* debugging */ /* search %% DSC comments at head of file for %%Preview */ while (*line == '%' && *(line+1) == '%') { /* was 94/May/19 */ if (strncmp(line+2, "BeginPreview:", 13) == 0) { /* winerror("Yes it's EPSI"); */ /* debugging */ if (sscanf(line+2+13, "%d %d %d %d", &prewidth, &preheight, &prebits, &prelines) >= 3) { /* OK, we have an EPSI preview here */ /* do something with it ! */ /* sprintf(str, "w %d h %d b %d l %d", prewidth, preheight, prebits, prelines); wincancel(str); */ /* debugging */ /* winerror("Going to read EPSI"); */ /* debugging */ /* shouldn't really every get here if bShowPreview is zero - so flush ? */ if (bShowPreview != 0 || bPrintFlag != 0 || bCopyFlag != 0) { /* 93/Mar/30 */ (void) readepsipreview(hDC, special, xll, yll, xur, yur, readflag); fclose(special); /* special = NULL; */ special = BAD_FILE; return 0; /* done with EPS preview */ } else break; /* 93/Mar/30 what ??? */ } } if (getline(special, line) == 0) break; /* added following to skip blank line in Mathematica EPSI */ while (*line == '\n' || *line == '\r') /* 94/May/19 */ if (getline(special, line) == 0) break; } fclose(special); /* special = NULL; */ special = BAD_FILE; /* It was a PS file, but without a preview in TIFF or EPSI form */ /* return -1; */ if (!bForceTIFF) return -1; /* just give up */ /* Forced search for TIFF file with same name 95/Sep/7 */ strcpy(infilename, filename); /* If extension was `eps' strip it and replace with `tif' and re-search */ if ((s = strrchr(infilename, '.')) != NULL && _stricmp(s+1, "eps") == 0) { *s = '\0'; /* if ((special = findepsfile(infilename, -1, "tif")) == NULL) */ /* if ((special = findepsfile(infilename, 0, "tif")) == NULL) */ special = findepsfile(infilename, 0, "tif"); if (special == BAD_FILE) return -1; /* failed */ c = getc(special); d = getc(special); /* drop through if we have opened what appears to be TIFF file */ } else return -1; /* it was a PS file, but without a preview */ } /* else if (c == 'I' && d == 'I') leastfirst = 1; */ /* 1995/Sep/7 */ /* Now check whether TIFF file (in Intel or Motorola format) */ if (c == 'I' && d == 'I') leastfirst = 1; /* PC style TIFF file */ else if (c == 'M' && d == 'M') leastfirst = 0; /* Mac style TIFF file */ else if (c == 1 && d == 0) wmfflag = 1; /* wmf, not placeable */ else if (c == 'B' && d == 'M') bmpflag = 1; /* BMP 98/May/28 */ else { fclose(special); /* special = NULL; */ special = BAD_FILE; /* sprintf(str, "`%s' not a valid EPSF or TIFF file", filename); */ /* sprintf(str, "`%s' not a valid EPSF, TIFF, or WMF file", filename); */ strcpy(debugstr, "Not a valid "); strcat(debugstr, "EPSF, TIFF, BMP or WMF file: "); strcat(debugstr, filename); s = debugstr + strlen(debugstr); /* add debugging info 95/Dec/1 */ sprintf(s, " %c%c (%d %d) ", c, d, c, d); /* sprintf(debugstr, "TIFF file %s should start with `II' or `MM' not `%c%c'", filename, c, d); */ winerror(debugstr); present = ftell(special); /* sprintf(debugstr, "at byte %ld with tiffoffset %ld", present, tiffoffset); */ sprintf(debugstr, "at byte %ld, tiffoffset %ld, metaoffset %ld", present, tiffoffset, metaoffset); winbadimage(debugstr); return -1; /* not a TIFF or WMF subfile !!! */ } /* Now have decided that this is a TIFF file (or TIFF or WMF preview) */ if (bShowPreview != 0 || bPrintFlag != 0 || bCopyFlag != 0) { if (wmfflag) readwmffile(hDC, special, xll, yll, xur, yur); else if (bmpflag) readbmpfile(hDC, special, xll, yll, xur, yur, readflag); else readtifffile(hDC, special, xll, yll, xur, yur, nifd, readflag); } fclose(special); /* 92/Feb/13 */ /* moved here rather than scattered */ /* special = NULL; */ special = BAD_FILE; return 0; } /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ /* stuff for extracting hex-bytes in EPSI preview */ /* speed up using lookup table ? */ #ifdef LONGNAMES int readhexbyte (HFILE input) { #else int readhexbyte (FILE *input) { #endif int c, d; #ifdef EPSISPEED while((c = wingetc(input)) < '0') if (c == EOF) return -1; #else while((c = getc(input)) < '0') if (c == EOF) return -1; #endif if (c <= '9' && c >= '0') c = c - '0'; else if (c <= 'F' && c >= 'A') c = c - 'A' + 10; else if (c <= 'f' && c >= 'a') c = c - 'a' + 10; /* else if (c == EOF) return -1; */ else { /* not a hexadecimal character */ /* wincancel("Bad EPSI preview"); return -1; */ } #ifdef EPSISPEED while((d = wingetc(input)) < '0') if (c == EOF) return -1; #else while((d = getc(input)) < '0') if (c == EOF) return -1; #endif if (d <= '9' && d >= '0') d = d - '0'; else if (d <= 'F' && d >= 'A') d = d - 'A' + 10; else if (d <= 'f' && d >= 'a') d = d - 'a' + 10; /* else if (d == EOF) return -1; */ else { /* not a hexadecimal character */ /* wincancel("Bad EPSI preview"); return -1; */ } return (c << 4) | d; } #ifdef LONGNAMES int readepsipreview (HDC hDC, HFILE input, int xll, int yll, int xur, int yur, int readflag) { #else int readepsipreview (HDC hDC, FILE *input, int xll, int yll, int xur, int yur, int readflag) { #endif int n; int i, j, flag; unsigned char huge *s; /* HUGE to access global image array */ char far *t; /* FAR to access global image array */ unsigned char *u; /* source for transfer to global image */ /* HANDLE hBuffer=NULL; */ /* Flushed 95/July/27 */ unsigned char *lpBuffer=NULL; /* Buffer for a row, locally allocated */ unsigned long imagesize; /* shouldn't get here if bShowPreview == 0 */ if (special == BAD_FILE) return -1; /* sanity check */ ImageWidth = prewidth; ImageLength = preheight; SamplesPerPixel = 1; BitsPerSample = prebits, ExtraSamples = 0; /* 99/May/10 */ compression = 0; Orientation = 1; colormap = 0; if (BitsPerSample == 1) PhotometricInterpretation = 0; /* NOT default - flipped for EPSI */ else PhotometricInterpretation = 1; /* default */ if (ExtraSamples > 0) SamplesPerPixelX = SamplesPerPixel-ExtraSamples; else SamplesPerPixelX = SamplesPerPixel; BitsPerPixel = BitsPerSample * SamplesPerPixel; if (ExtraSamples > 0) BitsPerPixelX = BitsPerSample * SamplesPerPixelX; else BitsPerPixelX = BitsPerPixel; if (RowsPerStrip > 0) /* 1996/Sep/7 */ StripsPerImage = (int) ((ImageLength + RowsPerStrip - 1) / RowsPerStrip); else StripsPerImage = 1; if (readflag == 0) { /* if only scanning for width & height */ /* fclose(input); */ /* done after call anyway */ return -1; } mingrey = 0; maxgrey = (1 << (int) BitsPerSample) - 1; /* NOTE: (Bitmap) monochrome bitmap rows are int aligned (page 7-6) */ /* NOTE: (DIB) color bitmap rows are long aligned (page 7-9, 7-11) */ InRowLength = (ImageWidth * BitsPerPixel + 7) / 8; /* row length in file */ if (ExtraSamples > 0)InRowLengthX = (ImageWidth * BitsPerPixelX + 7) / 8; else InRowLengthX = InRowLength; /* OutRowLength = InRowLength; */ OutRowLength = InRowLengthX; /* possibly less */ /* if (BitsPerPixel == 1) BytesPerRow = 4 * ((ImageWidth * BitsPerPixel + 31) / 32); else BytesPerRow = 4 * ((ImageWidth * BitsPerPixel + 31) / 32); */ /* BytesPerRow is *after* any removeal of ExtraSamples */ BytesPerRow = 4 * ((ImageWidth * BitsPerPixelX + 31) / 32); /* row length in BitMap data */ /* if (ExtraSamples > 0) { BytesPerRow = 4 * ((ImageWidth * BitsPerSample * (SamplesPerPixel-ExtraSamples) + 31) / 32); } */ /* if (BitsPerPixel == 24 && bCompressColor != 0) { OutRowLength = OutRowLength / 3; BytesPerRow = BytesPerRow / 3; } */ /* sprintf(str, "inrow %ld outrow %ld BytesPerRow %ld", InRowLength, OutRowLength, BytesPerRow); winerror(str); */ /* debugging */ imagesize = (unsigned long) BytesPerRow * ImageLength; if (ImageWidth > MAXIMAGEDIMEN || ImageLength > MAXIMAGEDIMEN || /* too large - bad data */ imagesize > MAXIMAGESIZE) { /* arbitrary limits (to catch bad files) */ sprintf(debugstr, "TIFF file too large\n(%ld x %ld (%ld) => %ld bytes)", ImageWidth, ImageLength, BitsPerPixel, imagesize); winbadimage(debugstr); /* fclose(input); */ return -1; } /* allocate global array to store image in */ /* sprintf(str, "imagesize %lu", imagesize); winerror(str); */ /* debug */ if (imagesize == 0) { /* wincancel("Zero image size"); */ sprintf(debugstr, "ERROR: Zero image size %ld x %ld (%s)", BytesPerRow, ImageLength, "readepsipreview"); winbadimage(debugstr); /* fclose(input); */ return -1; } hImage = GlobalAlloc(GMEM_MOVEABLE, imagesize); lpImageBytes = (LPSTR) GlobalLock(hImage); /* With fixed memory should be able to use LocalAlloc result directly! */ /* if ((hBuffer = LocalAlloc(LMEM_FIXED, (WORD) InRowLength)) == NULL || (lpBuffer = LocalLock(hBuffer)) == NULL) { sprintf(str, "Image memory alloc error (%ld bytes)", InRowLength); wincancel(str); return -1; } */ lpBuffer = (unsigned char *) LocalAlloc(LMEM_FIXED, (UINT) InRowLength); if (lpBuffer == NULL) { sprintf(debugstr, "Image memory alloc error (%ld bytes)", InRowLength); /* wincancel(str); */ winbadimage(debugstr); return -1; } /* winerror("Allocated Memory"); */ #ifdef EPSISPEED /* wininit(input); */ /* set up buffering stuff */ if (wininit(input) != 0) { /* 1996/May/12 */ /* failed to allocate EPSIBUFFERLEN bytes */ winbadimage("EPSI buffer alloc error"); return -1; } #endif flip = 1; /* DIB Bitmaps are reversed */ /* monochrome (CreateBitMap) - is reversed from color (CreateDIBitmap) */ /* if (BitsPerPixel == 1) flip = 1 - flip; */ /* use CreateDIBitmap now */ /* else if (Orientation == 4) flip = 1 - flip; */ /* not for pmjean ... */ /* need to flip when printing to PostScript printer driver */ /* printer output is reversed from screen output */ /* if (bPrintFlag != 0) { if (IsItPSCRPT(hDC) != 0) flip = 1 - flip; } */ flag = 0; /* flag gets set if EOF hit */ for (i = 0; i < (int) ImageLength; i++) { /* read image lines */ if (flip == 0) s = (unsigned char huge *) lpImageBytes + (BytesPerRow * i); else s = (unsigned char huge *) lpImageBytes + (BytesPerRow * ((ImageLength-1) - i)); t = (char far *) s; /* speed up later using buffered reads */ if (imagesize < 65536L) { for (j = 0; j < (int) InRowLength; j++) { if ((n = readhexbyte(input)) < 0) { flag = -1; /* hit EOF */ break; } /* *u++ = (char) ((c << 4) | d); */ /* NOT INITIALIZED ! */ else *t++ = (char) n; /* speed up later */ } } else { u = lpBuffer; for (j = 0; j < (int) InRowLength; j++) { if ((n = readhexbyte(input)) < 0) { flag = -1; /* hit EOF */ break; } else *u++ = (char) n; /* else *s++ = (char) n; */ /* speed up later */ } #ifdef USEMEMCPY memcpy(s, lpBuffer, InRowLength); #else copynearimage(s, lpBuffer, InRowLength); /* NEW */ #endif } /* Remove ExtraSamples in the above, if any ??? */ if (bEnableTermination != 0 && checkuser() != 0) { #ifdef DEBUGTIFF if (bDebug > 1) OutputDebugString("checkuser abort\n"); #endif bShowFlag = 0; /* turn off displaying */ finish = -1; /* redundant ??? */ bUserAbort = 1; flag = 1; break; } } /* if (hBuffer != NULL) { (void) LocalUnlock(hBuffer); hBuffer = LocalFree (hBuffer); } */ /* 95/July/27 */ if (lpBuffer != NULL) lpBuffer = (unsigned char *) LocalFree ((HLOCAL) lpBuffer); if (colormap == 0) { /* fclose(input); */ /* input = NULL; */ } /* winerror("Finished reading image"); */ /* debugging */ /* if (flag != 0) { fclose(input); input = NULL; return -1; NO ! } */ if (bUserAbort == 0) { #ifdef DEBUGTIFF if (bDebug > 1) { sprintf(debugstr, "ReadEPSIPreview: xll %d yll %d xur %d yur %d", xll, yll, xur, yur); OutputDebugString(debugstr); } /* debugging 95/April/13 */ #endif (void) renderimage(hDC, input, xll, yll, xur, yur); } else { if (bDebug > 1) OutputDebugString("renderimage abort\n"); } /* if (colormap != 0 && input != NULL) */ if (colormap != 0 && input != BAD_FILE) { /* fclose(input); */ /* input = BAD_FILE; */ } if (hImage != NULL) { if (GlobalUnlock(hImage) > 0) { sprintf(debugstr, "Lock count Not Zero %s", "Image"); wincancel(debugstr); PostQuitMessage(0); /* pretty serious ! */ } hImage = GlobalFree(hImage); /* hImage = NULL; */ /* for debugging */ } #ifdef EPSISPEED winendit(); /* clear up buffering stuff activated 95/Dec/4 */ #endif return 0; } /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ void flipRB (unsigned char *lpLineBuff, unsigned int n) { // separated 2000 May 27 unsigned char *u, *v; int unsigned i; int r, g, b; u = lpLineBuff; v = lpLineBuff; for (i = 0; i < n / 3; i++) { r = *u++; g = *u++; b = *u++; *v++ = (char) b; *v++ = (char) g; *v++ = (char) r; } } // Approximate transformation from CMYK to RGB // Note heuristic adjustement to K component subtracted out ... void CMYKtoRGB (unsigned char *lpLineBuff, unsigned int n) { // 2000 May 27 unsigned char *u, *v; int unsigned i; int c, y, m, k, r, g, b; u = lpLineBuff; v = lpLineBuff; for (i = 0; i < n / 4; i++) { c = *u++; m = *u++; y = *u++; k = *u++; // r = 255 - c - k; r = 255 - c - k/2; // g = 255 - m - k; g = 255 - m - k/2; // b = 255 - y - k; b = 255 - y - k/2; if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0; *v++ = (char) b; *v++ = (char) g; *v++ = (char) r; *v++ = (char) 0; } } int nFirstTime=0; /* get here if asked to display TIFF image and it is found to be compressed */ /* first close file again ! */ /* nImage contains nfid (or nfid - 1 ?) */ /* lpszFileName contains TIFF file name */ /* Can use explicit Link-Time Import page 20-33 */ /* Line callback function for loading up TIFF image */ /* assumes global access to flip, InRowLength, lpImageBytes, BytesPerRow */ /* parameters passed are: */ /* pointer to line buffer, line number (zero based), parameter from caller */ /* int CALLBACK CopyLineFun(LPSTR lpLineBuff, int nLine, LONG lParam) */ int CALLBACK _export CopyLineFun (unsigned char *lpLineBuff, int nLine, LONG lParam) { unsigned char huge *s; /* HUGE to access global image array */ // unsigned char *u, *v; // int k, r, g, b; /* UNUSED (lParam); */ // if (nFirstTime++ == 0) { // sprintf(debugstr, "BitsPerPixelX %d bCMYK %d bCompressColor %d InRowLengthX %d", // BitsPerPixelX, bCMYK, bCompressColor, InRowLengthX); // wincancel(debugstr); // debugging only // } if (BitsPerPixelX == 32 && bCMYK) { CMYKtoRGB(lpLineBuff, (unsigned int) InRowLengthX); } if (BitsPerPixelX == 24 && bCompressColor) { compresscolor(lpLineBuff, (unsigned int) InRowLengthX, lookup); } /* Following added 96/Sep/15 to support bCompressColor == 0 */ if (BitsPerPixelX == 24 && bCompressColor == 0 && bBGRflag == 0) { flipRB(lpLineBuff, InRowLength); } /* copy the image line across */ if (flip == 0) s = (unsigned char huge *) lpImageBytes + (BytesPerRow * nLine); else s = (unsigned char huge *) lpImageBytes + (BytesPerRow * ((ImageLength-1) - nLine)); /* maybe do directly far => far instead if image is small ? */ #ifdef USEMEMCPY memcpy(s, lpLineBuff, OutRowLength); /* 99/June/25 */ #else copyfarimage(s, lpLineBuff, OutRowLength); /* 92/May/12 */ #endif return 0; /* or error status */ } /* lParam unreferenced */ /* above must be exported in EXPORTS section of .DEF file */ /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ /* Call format modelled somewhat on DecodeTiffImage in Black Ice */ int DecompressTiff(HFILE, int, WORD, WORD, LONG, FARPROC); /* This call CopyLineFun with data for each line */ /* int CALLBACK _export CopyLineFun(LPSTR lpLineBuff, int nLine, LONG lParam); */ /* Assumes global access to flip, InRowLength, lpImageBytes, BytesPerRow */ /* returns -1 if error, returns 0 if success */ int UseOurTIFF (int nImage) { /* do our own 1996/Sep/2 */ HFILE hFile; WORD wFirstStrip, wNumLines; LONG LineFunParam; int flag=0; #ifdef DEBUGTIFF OutputDebugString("UseOurTIFF"); #endif hFile = _lopen(FileName, READ); if (hFile == HFILE_ERROR) { #ifdef DEBUGTIFF if (bDebug > 1) { sprintf(debugstr, "Unable to open %s", FileName); OutputDebugString(debugstr); } #endif return -1; /* failed */ } /* read TIFF TAGS for ImageWidth, ImageLength, BitsPerSample, SamplesPerPixel */ /* let's assume this has been done already */ wFirstStrip = 0; /* start at first strip */ wNumLines = 0; /* decode all lines */ LineFunParam = 0; /* or whatever is to be passed */ #ifdef DEBUGTIFF if (bDebug > 1) { sprintf(debugstr, "ImageWidth %ld ImageLength %ld BitsPerSample %ld SamplesPerPixel %ld", ImageWidth, ImageLength, BitsPerSample, SamplesPerPixel); OutputDebugString(debugstr); } #endif flag = 0; /* call into wintiff.c */ if (DecompressTiff(hFile, nImage, wFirstStrip, wNumLines, LineFunParam, (FARPROC) CopyLineFun) == 0) { #ifdef DEBUGTIFF if (bDebug > 1) OutputDebugString("DecompressTiff failed"); #endif flag = -1; /* failure */ } _lclose(hFile); return flag; } /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */ /* Throw out ExtraSamples in SamplesPerPixel */ /* IMPORTANT NOTE: assume for the moment samples are one byte */ int RemoveExtraSamples (unsigned char *lpBuffer, int InRowLength) { unsigned char *s = lpBuffer; unsigned char *t = lpBuffer; int i, k, n = InRowLength / SamplesPerPixel; if (ExtraSamples == 0) return InRowLength; /* check that BitsPerSample == 8 ??? */ for (k = 0;