Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3235 lines
76 KiB

  1. /*++
  2. Copyright (c) 1990-2003 Microsoft Corporation
  3. Module Name:
  4. plotgpc.c
  5. Abstract:
  6. This module contains the function to generate plotter gpc data for
  7. NT 1.0a
  8. This module contains the functions required to generate a plotter gpc
  9. data file.
  10. Development History:
  11. 15-Feb-1994 Tue 22:50:10 updated
  12. Add bitmap font caps
  13. 09-Nov-1993 Tue 09:23:48 created
  14. 18-Mar-1994 Fri 14:00:14 updated
  15. Adding PLOTF_RTL_NO_DPI_XY, PLOTF_RTLMONO_NO_CID and
  16. PLOTF_RTLMONO_FIXPAL flags
  17. [Environment:]
  18. GDI Device Driver - PLOTTER
  19. [Notes:]
  20. Revision History:
  21. --*/
  22. #if 0
  23. ;
  24. ; Plotter GPC data file format
  25. ;
  26. ; 1. All key value(s) for the keyword must be encloses by a {} brace pair.
  27. ; 2. Any Strings must be enclosed by quotes ("").
  28. ; 3. a ';' denotes a comment to the end of the current line.
  29. ; 4. Types
  30. ; a. FLAG - 1 or 0
  31. ; b. WORD - 16 bit number
  32. ; c. DWORD - 32 bit number
  33. ; d. STRING - ANSI character string, maximum size depends on keyword
  34. ; e. FORMSRC - 1. 31 byte string for the name of the form (paper source)
  35. ; 2. 2 DWORDs: size width/height (SIZEL) 1/1000mm
  36. ; ** if height is <= 25400 (1 inch) or it greater
  37. ; then DeviceSize CY then it is assumed that
  38. ; the form is variable length and the height
  39. ; will be reset to zero (0)
  40. ;
  41. ; 3. 4 DWORDs: Left/Top/Right/Bottom margins in 1/1000mm
  42. ;
  43. ; f. CONSTANT - Pick from a set of predefined strings in the header file
  44. ; g. COLORINFO - Windows 2000, Windows XP and Windows Server 2003 DDI COLORINFO data structure (30 DWORDs)
  45. ; h. PENDATA - 1. One word that specifies the location in the carousel
  46. ; of this pen (1=slot 1, 2=slot 2).
  47. ; 2. constant which specifies the predefined pen color
  48. ; PC_IDX_xxxx can be one of:
  49. ;
  50. ; Index R G B
  51. ; ------------------------------
  52. ; PC_IDX_WHITE 255 255 255
  53. ; PC_IDX_BLACK 0 0 0
  54. ; PC_IDX_RED 255 0 0
  55. ; PC_IDX_GREEN 0 255 0
  56. ; PC_IDX_YELLOW 255 255 0
  57. ; PC_IDX_BLUE 0 0 255
  58. ; PC_IDX_MAGENTA 255 0 255
  59. ; PC_IDX_CYAN 0 255 255
  60. ; PC_IDX_ORANGE 255 128 0
  61. ; PC_IDX_BROWN 255 192 0
  62. ; PC_IDX_VIOLET 128 0 255
  63. ;
  64. ; i. ROPLEVEL - One of following levels:
  65. ;
  66. ; ROP_LEVEL_0 - No Rop support
  67. ; ROP_LEVEL_1 - ROP1 support (SRC)
  68. ; ROP_LEVEL_2 - ROP2 support (SRC/DEST)
  69. ; ROP_LEVEL_3 - ROP3 support (SRC/DEST/PAT)
  70. ;
  71. ; *** if DeviceSize' height is <= 25400 (1 inch) then it is assumed that the
  72. ; device can handle variable length paper and the height will be reset to
  73. ; zero (0)
  74. ;
  75. ; *** RasterDPI must be defined for both raster and pen plotters. For raster
  76. ; plotters this should be the raster resolution of the device. For pen
  77. ; plotters it should be the ideal resolution for the device that GDI
  78. ; will report back to the calling windows application.
  79. ;
  80. ; Keyword Type Count Range/Size
  81. ; -------------------------------------------------------------------------
  82. ; DeviceName STRING 31 Device name as it appears in UI's
  83. ; DeviceSize DWORD 2 Device cx/cy in 1/1000mm
  84. ; DeviceMargin DWORD 4 Device L/T/R/B margin in 1/1000mm
  85. ; RasterCap Flag 1 0/1 (1=Raster Device, 2=Pen Device)
  86. ; ColorCap Flag 1 0/1 (1=Color Device, 2=Mono)
  87. ; BezierCap Flag 1 0/1 (1=Device supports HPGL2
  88. ; Beziers extension)
  89. ; RasterByteAlign Flag 1 0/1 (1=Device must receive all
  90. ; raster data on byte alligned
  91. ; x coordinates)
  92. ; PushPopPal Flag 1 0/1 (1=Driver must push/pop
  93. ; pallete when switching
  94. ; between RTL / HPGL2)
  95. ; TransparentCap Flag 1 0/1 (1=Device supports transp. cmd)
  96. ; WindingFillCap Flag 1 0/1 (1=Device can do winding fills)
  97. ; RollFeedCap Flag 1 0/1 (1=Device has roll paper src)
  98. ; PaperTrayCap Flag 1 0/1 has a main paper tray?
  99. ; NoBitmapFont Flag 1 0/1 Do not do bitmap font
  100. ; RTLMonoEncode5 Flag 1 0/1 RTL Mono Compress Mode 5?
  101. ; RTLNoDPIxy Flag 1 0/1 NO RTL DPI X,Y Move command
  102. ; RTLMonoNoCID Flag 1 0/1 RTL Mono No CID command
  103. ; RTLMonoFixPal Flag 1 0/1 RTL Mono PAL ONLY 0=W, 1=K
  104. ; PlotDPI DWORD 2 Plotter UNIT X/Y Dots per Inch
  105. ; RasterDPI WORD 2 Raster (RTL) X/Y Dots per Inch
  106. ; ROPLevel DWORD 1 0/1/2/3
  107. ; MaxScale WORD 1 0-10000 (100 times bigger)
  108. ; MaxPens WORD 1 Device max # of pens for pen plotter
  109. ; MaxCopies WORD 1 Device max # of copies of each
  110. ; page device can render by itself.
  111. ; MaxPolygonPts WORD 1 Device max # of points when defining
  112. ; a polygon to later be stroked or
  113. ; filled.
  114. ; MaxQuality WORD 1 Device maximum quality levels
  115. ; PaperTraySize DWORD 2 Paper Tray width/height in 1/1000mm
  116. ; COLORINFO DWORD 30 COLORINFO data structure
  117. ; DevicePelsDPI DWORD 1 Dots Per Inch
  118. ; HTPatternSize CONSTANT 1 HT_PATSIZE_xx
  119. ; InitString STRING 255 Standard string sent to device for
  120. ; initialization.
  121. ; PlotPenData PENDATA 32 (Max) Pen Plotter's carousel def.
  122. ; FormInfo FORMSRC 64 Device supported forms
  123. ;
  124. ; Following are example values for the PLOTTER characterization data:
  125. ;
  126. DeviceName { "HP DesignJet 650C (C2859B)" }; Device Name
  127. DeviceSize { 914400, 15240000 } ; Device Size (36" x 50')
  128. DeviceMargin { 25400, 25400, 5000, 36000 } ; Device Margin (in 1/1000mm)
  129. RasterCap { 1 } ; Pen/Raster plotter (0/1)
  130. ColorCap { 1 } ; Color plotter (0/1)
  131. BezierCap { 1 } ; Can do bezier curves (0/1)
  132. RasterByteAlign { 0 } ; need to byte aligned (0/1)
  133. PushPopPal { 1 } ; need to push/pop palette (0/1)
  134. TransparentCap { 0 } ; Has transparent mode (0/1)
  135. WindingFillCap { 0 } ; Can do winding fills (0/1)
  136. RollFeedCap { 1 } ; Can do RollPaper feed (0/1)
  137. PaperTrayCap { 0 } ; Has paper input tray (0/1)
  138. NoBitmapFont { 0 } ; Do not do bitmap font
  139. RTLMonoEncode5 { 1 } ; RTL Mono Adapt Compression
  140. RTLNoDPIxy { 0 } ; Has RTL DPI XY move comand
  141. RTLMonoNoCID { 0 } ; Has RTL MONO CID Command
  142. RTLMonoFixPal { 0 } ; Can change RTL Palette 0/1
  143. PlotDPI { 1016, 1016 } ; Pen Plotter X/Y DPI
  144. RasterDPI { 300, 300 } ; Raster Plotter X/Y DPI
  145. ROPLevel { ROP_LEVEL_2 } ; ROP levels (0/1/2/3)
  146. MaxScale { 1600 } ; Maximum allowed Scale %
  147. MaxPens { 256 } ; Maximum allowed pens
  148. MaxCopies { 1 } ; Maximum allowed copies
  149. MaxPolygonPts { 8192 } ; Maximum Polygon points
  150. MaxQuality { 3 } ; Maximum quality levels
  151. ;
  152. ; Only needed if PaperTrayCap = 1,
  153. ;
  154. PaperTraySize { 215900, 279400 } ; Letter size paper tray
  155. ;
  156. COLORINFO { 6810, 3050, 0, ; xr, yr, Yr
  157. 2260, 6550, 0, ; xg, yg, Yg
  158. 1810, 500, 0, ; xb, yb, Yb
  159. 2000, 2450, 0, ; xc, yc, Yc
  160. 5210, 2100, 0, ; xm, ym, Ym
  161. 4750, 5100, 0, ; xy, yy, Yy
  162. 3324, 3474, 10000, ; xw, yw, Yw
  163. 10000, 10000, 10000, ; RGB gamma
  164. 1422, 952, 787, ; Dye correction datas
  165. 495, 324, 248 }
  166. DevicePelsDPI { 0 } ; effective device DPI (default)
  167. HTPatternSize { HT_PATSIZE_6x6_M } ; GDI Halftone pattern size
  168. InitString { "\033E" }
  169. ;
  170. ; Only allowed if RasterCap = 0, and must define all pens (MaxPens)
  171. ;
  172. ; PlotPenData { 1, PC_WHITE }
  173. ; PlotPenData { 2, PC_BLACK }
  174. ; PlotPenData { 3, PC_RED }
  175. ; PlotPenData { 4, PC_GREEN }
  176. ; PlotPenData { 5, PC_YELLOW }
  177. ; PlotPenData { 6, PC_BLUE }
  178. ; PlotPenData { 7, PC_MAGENTA }
  179. ; PlotPenData { 8, PC_CYAN }
  180. ; PlotPenData { 9, PC_ORANGE }
  181. ; PlotPenData { 10, PC_BROWN }
  182. ; PlotPenData { 11, PC_VIOLET }
  183. ;
  184. FormInfo { "Roll Paper 24 in", 609600, 0, 0, 0, 0, 0 }
  185. FormInfo { "Roll Paper 36 in", 914400, 0, 0, 0, 0, 0 }
  186. FormInfo { "ANSI A 8.5 x 11 in", 215900, 279400, 0, 0, 0, 0 }
  187. FormInfo { "ANSI B 11 x 17 in", 279400, 431800, 0, 0, 0, 0 }
  188. FormInfo { "ANSI C 17 x 22 in", 431800, 558800, 0, 0, 0, 0 }
  189. FormInfo { "ANSI D 22 x 34 in", 558800, 863600, 0, 0, 0, 0 }
  190. FormInfo { "ANSI E 34 x 44 in", 863600, 1117600, 0, 0, 0, 0 }
  191. FormInfo { "ISO A4 210 x 297 mm", 210000, 297000, 0, 0, 0, 0 }
  192. FormInfo { "ISO A3 297 x 420 mm", 297000, 420000, 0, 0, 0, 0 }
  193. FormInfo { "ISO A2 420 x 594 mm", 420000, 594000, 0, 0, 0, 0 }
  194. FormInfo { "ISO A1 594 x 841 mm", 594000, 841000, 0, 0, 0, 0 }
  195. FormInfo { "ISO A0 841 x 1189 mm", 841000, 1189000, 0, 0, 0, 0 }
  196. FormInfo { "ISO OS A2 480 x 625 mm", 480000, 625000, 0, 0, 0, 0 }
  197. FormInfo { "ISO OS A1 625 x 900 mm", 625000, 900000, 0, 0, 0, 0 }
  198. FormInfo { "JIS B4 257 x 364 mm", 257000, 364000, 0, 0, 0, 0 }
  199. FormInfo { "JIS B3 364 x 515 mm", 364000, 515000, 0, 0, 0, 0 }
  200. FormInfo { "JIS B2 515 x 728 mm", 515000, 728000, 0, 0, 0, 0 }
  201. FormInfo { "JIS B1 728 x 1030 mm", 728000, 1030000, 0, 0, 0, 0 }
  202. FormInfo { "Arch A 9 x 12 in", 228600, 304800, 0, 0, 0, 0 }
  203. FormInfo { "Arch B 12 x 18 in", 304800, 457200, 0, 0, 0, 0 }
  204. FormInfo { "Arch C 18 x 24 in", 457200, 609600, 0, 0, 0, 0 }
  205. FormInfo { "Arch D 24 x 36 in", 609600, 914400, 0, 0, 0, 0 }
  206. FormInfo { "Arch E 36 x 48 in", 914400, 1219200, 0, 0, 0, 0 }
  207. FormInfo { "Arch E1 30 x 42 in", 762000, 1066800, 0, 0, 0, 0 }
  208. #endif
  209. #define DBG_PLOTFILENAME DbgPlotGPC
  210. #include <stddef.h>
  211. #include <windows.h>
  212. #include <winddi.h>
  213. #include <wingdi.h>
  214. #include <winspool.h>
  215. #include <stdio.h>
  216. #include <ctype.h>
  217. #include <stdlib.h>
  218. #include <strsafe.h>
  219. #include <plotlib.h>
  220. #define DBG_FORM 0x00000001
  221. #define DBG_PAPERTRAY 0x00000002
  222. #define DBG_FULLGPC 0x00000004
  223. DEFINE_DBGVAR(0);
  224. #if DBG
  225. TCHAR DebugDLLName[] = TEXT("PLOTGPC");
  226. #endif
  227. #define SIZE_ARRAY(a) (sizeof((a)) / sizeof((a)[0]))
  228. #define SIZE_COLORINFO (sizeof(COLORINFO) / sizeof(LDECI4))
  229. #define PK_FLAG 0
  230. #define PK_WORD 1
  231. #define PK_DWORD 2
  232. #define PK_STRING 3
  233. #define PK_FORMSRC 4
  234. #define PK_PENDATA 5
  235. #define PKF_DEFINED 0x8000
  236. #define PKF_REQ 0x0001
  237. #define PKF_MUL_OK 0x0002
  238. #define PKF_VARSIZE 0x0004
  239. #define PKF_FS_VARLEN 0x0008
  240. #define PKF_ALL 0x0010
  241. #define PKF_REQALL (PKF_REQ | PKF_ALL)
  242. #define PKF_ROLLPAPER (PKF_MUL_OK | PKF_VARSIZE | PKF_FS_VARLEN)
  243. #define PKF_FORMINFO (PKF_MUL_OK | \
  244. PKF_VARSIZE | \
  245. PKF_REQ | \
  246. PKF_FS_VARLEN)
  247. #define PKF_PENDATA (PKF_MUL_OK | PKF_VARSIZE)
  248. #define PLOTOFF(a) (DWORD)FIELD_OFFSET(PLOTGPC, a)
  249. #define GET_PLOTOFF(pPK) ((LPBYTE)&PlotGPC + pPK->Data)
  250. #define ADD_PLOTOFF(p, pPK) ((LPBYTE)(p) + pPK->Data)
  251. //
  252. // The plotval is used to provide a name constant selection.
  253. //
  254. typedef struct _PLOTVAL {
  255. LPSTR pValName;
  256. DWORD Val;
  257. } PLOTVAL, *PPLOTVAL;
  258. //
  259. // The keyword parser structure
  260. //
  261. typedef struct _PLOTKEY {
  262. LPSTR pKeyword; // Keyword name
  263. WORD KeywordLen; // Keyword length
  264. WORD Flags; // PKF_xxxx
  265. WORD Type; // PK_xxxx
  266. SHORT Count; // maximum size allowed, < 0 if non-Zero string
  267. DWORD Data; // data
  268. LPVOID pInfo; // extra set of pointer data
  269. } PLOTKEY, *PPLOTKEY;
  270. //
  271. // Local/Global variables
  272. //
  273. PLOTVAL PenColorVal[PC_IDX_TOTAL + 1] = {
  274. { "PC_WHITE", PC_IDX_WHITE },
  275. { "PC_BLACK", PC_IDX_BLACK },
  276. { "PC_RED", PC_IDX_RED },
  277. { "PC_GREEN", PC_IDX_GREEN },
  278. { "PC_YELLOW", PC_IDX_YELLOW },
  279. { "PC_BLUE", PC_IDX_BLUE },
  280. { "PC_MAGENTA", PC_IDX_MAGENTA },
  281. { "PC_CYAN", PC_IDX_CYAN },
  282. { "PC_ORANGE", PC_IDX_ORANGE },
  283. { "PC_BROWN", PC_IDX_BROWN },
  284. { "PC_VIOLET", PC_IDX_VIOLET },
  285. { NULL, 0xffffffff }
  286. };
  287. PLOTVAL ROPLevelVal[ROP_LEVEL_MAX + 2] = {
  288. { "ROP_LEVEL_0", ROP_LEVEL_0 },
  289. { "ROP_LEVEL_1", ROP_LEVEL_1 },
  290. { "ROP_LEVEL_2", ROP_LEVEL_2 },
  291. { "ROP_LEVEL_3", ROP_LEVEL_3 },
  292. { NULL, 0xffffffff }
  293. };
  294. PLOTVAL HTPatSizeVal[] = {
  295. { "HT_PATSIZE_2x2", HT_PATSIZE_2x2 },
  296. { "HT_PATSIZE_2x2_M", HT_PATSIZE_2x2_M },
  297. { "HT_PATSIZE_4x4", HT_PATSIZE_4x4 },
  298. { "HT_PATSIZE_4x4_M", HT_PATSIZE_4x4_M },
  299. { "HT_PATSIZE_6x6", HT_PATSIZE_6x6 },
  300. { "HT_PATSIZE_6x6_M", HT_PATSIZE_6x6_M },
  301. { "HT_PATSIZE_8x8", HT_PATSIZE_8x8 },
  302. { "HT_PATSIZE_8x8_M", HT_PATSIZE_8x8_M },
  303. { "HT_PATSIZE_10x10", HT_PATSIZE_10x10 },
  304. { "HT_PATSIZE_10x10_M", HT_PATSIZE_10x10_M },
  305. { "HT_PATSIZE_12x12", HT_PATSIZE_12x12 },
  306. { "HT_PATSIZE_12x12_M", HT_PATSIZE_12x12_M },
  307. { "HT_PATSIZE_14x14", HT_PATSIZE_14x14 },
  308. { "HT_PATSIZE_14x14_M", HT_PATSIZE_14x14_M },
  309. { "HT_PATSIZE_16x16", HT_PATSIZE_16x16 },
  310. { "HT_PATSIZE_16x16_M", HT_PATSIZE_16x16_M },
  311. { NULL, 0xffffffff }
  312. };
  313. BYTE InitString[512] = "";
  314. FORMSRC AvaiForms[64];
  315. PENDATA AvaiPenData[MAX_PENPLOTTER_PENS];
  316. UINT MaxKeywordLen = 0;
  317. UINT MaxPCValLen = 0;
  318. CHAR szFormInfo[] = "FormInfo";
  319. CHAR szPenData[] = "PlotPenData";
  320. CHAR szPaperTrayCap[] = "PaperTrayCap";
  321. CHAR szPaperTraySize[] = "PaperTraySize";
  322. CHAR szNoBmpFont[] = "NoBitmapFont";
  323. CHAR szRTLMonoEncode5[] = "RTLMonoEncode5";
  324. CHAR szRTLNoDPIxy[] = "RTLNoDPIxy";
  325. CHAR szRTLMonoNoCID[] = "RTLMonoNoCID";
  326. CHAR szRTLMonoFixPal[] = "RTLMonoFixPal";
  327. FILE *InFile;
  328. FILE *OutFile;
  329. UINT LineNo;
  330. CHAR InFileName[80];
  331. //
  332. // The keys to search / parse
  333. //
  334. PLOTKEY PlotKey[] = {
  335. { "DeviceName", 0,PKF_REQ, PK_STRING, (SHORT)CCHDEVICENAME, PLOTOFF(DeviceName), NULL },
  336. { "DeviceSize", 0,PKF_REQALL, PK_DWORD, 2, PLOTOFF(DeviceSize), NULL },
  337. { "DeviceMargin", 0,PKF_REQALL, PK_DWORD, 4, PLOTOFF(DeviceMargin), NULL },
  338. { "RasterCap", 0,PKF_REQ, PK_FLAG, 1, PLOTF_RASTER, NULL },
  339. { "ColorCap", 0,PKF_REQ, PK_FLAG, 1, PLOTF_COLOR, NULL },
  340. { "BezierCap", 0,PKF_REQ, PK_FLAG, 1, PLOTF_BEZIER, NULL },
  341. { "RasterByteAlign",0,PKF_REQ, PK_FLAG, 1, PLOTF_RASTERBYTEALIGN, NULL },
  342. { "PushPopPal", 0,PKF_REQ, PK_FLAG, 1, PLOTF_PUSHPOPPAL, NULL },
  343. { "TransparentCap", 0,PKF_REQ, PK_FLAG, 1, PLOTF_TRANSPARENT, NULL },
  344. { "WindingFillCap", 0,PKF_REQ, PK_FLAG, 1, PLOTF_WINDINGFILL, NULL },
  345. { "RollFeedCap", 0,PKF_REQ, PK_FLAG, 1, PLOTF_ROLLFEED, NULL },
  346. { szPaperTrayCap, 0,PKF_REQ, PK_FLAG, 1, PLOTF_PAPERTRAY, NULL },
  347. { szNoBmpFont, 0,0, PK_FLAG, 1, PLOTF_NO_BMP_FONT, NULL },
  348. { szRTLMonoEncode5, 0,0, PK_FLAG, 1, PLOTF_RTLMONOENCODE_5, NULL },
  349. { szRTLNoDPIxy, 0,0, PK_FLAG, 1, PLOTF_RTL_NO_DPI_XY, NULL },
  350. { szRTLMonoNoCID, 0,0, PK_FLAG, 1, PLOTF_RTLMONO_NO_CID, NULL },
  351. { szRTLMonoFixPal, 0,0, PK_FLAG, 1, PLOTF_RTLMONO_FIXPAL, NULL },
  352. { "PlotDPI", 0,PKF_REQALL, PK_DWORD, 2, PLOTOFF(PlotXDPI), NULL },
  353. { "RasterDPI", 0,PKF_REQALL, PK_WORD, 2, PLOTOFF(RasterXDPI), NULL },
  354. { "ROPLevel", 0,0, PK_WORD, 1, PLOTOFF(ROPLevel), ROPLevelVal },
  355. { "MaxScale", 0,0, PK_WORD, 1, PLOTOFF(MaxScale), NULL },
  356. { "MaxPens", 0,PKF_REQ, PK_WORD, 1, PLOTOFF(MaxPens), NULL },
  357. { "MaxCopies", 0,0, PK_WORD, 1, PLOTOFF(MaxCopies), NULL },
  358. { "MaxPolygonPts", 0,PKF_REQ, PK_WORD, 1, PLOTOFF(MaxPolygonPts), NULL },
  359. { "MaxQuality", 0,0, PK_WORD, 1, PLOTOFF(MaxQuality), NULL },
  360. { szPaperTraySize, 0,PKF_ALL, PK_DWORD, 2, PLOTOFF(PaperTraySize), NULL },
  361. { "COLORINFO", 0,0, PK_DWORD, (SHORT)SIZE_COLORINFO, PLOTOFF(ci), NULL },
  362. { "DevicePelsDPI", 0,0, PK_DWORD, 1, PLOTOFF(DevicePelsDPI), NULL },
  363. { "HTPatternSize", 0,0, PK_DWORD, 1, PLOTOFF(HTPatternSize), HTPatSizeVal },
  364. { "InitString", 0,PKF_VARSIZE, PK_STRING, -(SHORT)SIZE_ARRAY(InitString),PLOTOFF(InitString), InitString },
  365. { szPenData, 0,PKF_PENDATA, PK_PENDATA,(SHORT)SIZE_ARRAY(AvaiPenData),PLOTOFF(Pens), AvaiPenData },
  366. { szFormInfo, 0,PKF_FORMINFO, PK_FORMSRC,(SHORT)SIZE_ARRAY(AvaiForms), PLOTOFF(Forms), AvaiForms },
  367. { NULL, 0 }
  368. };
  369. //
  370. // Current default plotter's GPC
  371. //
  372. PLOTGPC PlotGPC = {
  373. PLOTGPC_ID, // ID
  374. PLOTGPC_VERSION, // Version
  375. sizeof(PLOTGPC), // cjThis
  376. 0, // SizeExtra
  377. "HPGL/2 Plotter", // DeviceName,
  378. { 215900, 279400 }, // DeviceSize
  379. { 5000, 5000, 5000, 36000 }, // DeviceMargin
  380. 0, // Flags
  381. 1016, // PlotXDPI
  382. 1016, // PlotYDPI
  383. 300, // RasterXDPI
  384. 300, // RasterYDPI
  385. ROP_LEVEL_0, // ROPLevel
  386. 100, // MaxScale
  387. 8, // MaxPens
  388. 1, // MaxCopies
  389. 128, // MaxPolygonPts
  390. 4, // MaxQuality 100 levels
  391. { -1, -1 }, // PaperTraySize = 0
  392. { // ci
  393. { 6810, 3050, 0 }, // xr, yr, Yr
  394. { 2260, 6550, 0 }, // xg, yg, Yg
  395. { 1810, 500, 0 }, // xb, yb, Yb
  396. { 2000, 2450, 0 }, // xc, yc, Yc
  397. { 5210, 2100, 0 }, // xm, ym, Ym
  398. { 4750, 5100, 0 }, // xy, yy, Yy
  399. { 3324, 3474, 10000 }, // xw, yw, Yw
  400. 10000, 10000, 10000, // RGBB gamma
  401. 1422, 952, // M/C, Y/C
  402. 787, 495, // C/M, Y/M
  403. 324, 248 // C/Y, M/Y
  404. },
  405. 0, // DevicePelsDPI
  406. 0xffffffff, // HTPatternSize
  407. { 0, 0, NULL }, // init string
  408. { 0, sizeof(FORMSRC), NULL }, // Forms
  409. { 0, sizeof(PENDATA), NULL } // Pens
  410. };
  411. VOID
  412. ShowUsage(
  413. VOID
  414. )
  415. {
  416. fprintf(stderr, "\nPlotGPC [-?] InputDataFile [OutputPlotGPC]\n");
  417. fprintf(stderr, "Build NT Plotter GPC data file\n\n");
  418. fprintf(stderr, " -?: display this message.\n");
  419. fprintf(stderr, " InputDataFile: input ASCII data file\n");
  420. fprintf(stderr, " OutputPlotGPC: output binary plotter gpc data file\n");
  421. }
  422. VOID
  423. cdecl
  424. DispError(
  425. INT Level,
  426. LPSTR pStr,
  427. ...
  428. )
  429. {
  430. va_list vaList;
  431. if (Level) {
  432. if (Level > 2) {
  433. fprintf(stderr, "%s\n", InFileName);
  434. } else {
  435. fprintf(stderr, "\n%s(%u): ", InFileName, LineNo);
  436. }
  437. if (Level < 0) {
  438. fprintf(stderr, "INTERNAL ERROR: ");
  439. } else if (Level == 1) {
  440. fprintf(stderr, "warning: ");
  441. } else if (Level >= 2) {
  442. fprintf(stderr, "error: ");
  443. }
  444. } else {
  445. fprintf(stderr, "\n!!! ");
  446. }
  447. va_start(vaList, pStr);
  448. vfprintf(stderr, pStr, vaList);
  449. va_end(vaList);
  450. }
  451. VOID
  452. ShowSpaces(
  453. UINT Spaces
  454. )
  455. {
  456. BYTE Buf[81];
  457. while (Spaces) {
  458. memset(Buf, ' ', sizeof(Buf));
  459. if (Spaces > (sizeof(Buf) - 1)) {
  460. Buf[sizeof(Buf) - 1] = '\0';
  461. Spaces -= (sizeof(Buf) - 1);
  462. } else {
  463. Buf[Spaces] = '\0';
  464. Spaces = 0;
  465. }
  466. fprintf(stdout, "%s", Buf);
  467. }
  468. }
  469. VOID
  470. ShowNumbers(
  471. LPBYTE pNum,
  472. PPLOTVAL pPV,
  473. WORD Type,
  474. UINT Count,
  475. UINT NumDigits,
  476. UINT NumPerLine
  477. )
  478. /*++
  479. Routine Description:
  480. This function shows numbers in the passed format.
  481. Arguments:
  482. pNum - Points to the number
  483. pPV - Point to the value constant key name to be displayed
  484. Type - PK_xxx type
  485. Count - Total numbers
  486. NumDigits - Total digits per number
  487. NumPerLine - Total number per line to display
  488. Return Value:
  489. VOID
  490. Development History:
  491. 09-Nov-1993 Tue 19:45:13 created
  492. Revision History:
  493. --*/
  494. {
  495. DWORD *pdw;
  496. WORD *pw;
  497. DWORD dw;
  498. UINT Wrap;
  499. static BYTE DigitFormat[] = "%4lu";
  500. if (NumDigits > 9) {
  501. NumDigits = 9;
  502. }
  503. DigitFormat[1] = (BYTE)(NumDigits + '0');
  504. pdw = NULL;
  505. pw = NULL;
  506. Wrap = 0;
  507. if (pPV) {
  508. Count = 1;
  509. }
  510. switch (Type) {
  511. case PK_DWORD:
  512. pdw = (DWORD *)pNum;
  513. break;
  514. case PK_WORD:
  515. pw = (WORD *)pNum;
  516. break;
  517. default:
  518. DispError(-1, "ShowNumbers only allowes PK_WORD, PK_DWORD");
  519. return;
  520. }
  521. while (Count--) {
  522. if (pdw) {
  523. dw = *pdw++;
  524. } else {
  525. dw = (DWORD)*pw++;
  526. }
  527. if (pPV) {
  528. pPV += dw;
  529. fprintf(stdout, "%s", pPV->pValName);
  530. } else {
  531. fprintf(stdout, DigitFormat, dw);
  532. }
  533. if (Count) {
  534. fprintf(stdout, ", ");
  535. if (++Wrap >= NumPerLine) {
  536. fprintf(stdout, "\n");
  537. ShowSpaces(MaxKeywordLen + 3);
  538. Wrap = 0;
  539. }
  540. }
  541. }
  542. }
  543. UINT
  544. ShowString(
  545. LPBYTE pBuf,
  546. UINT cBuf
  547. )
  548. /*++
  549. Routine Description:
  550. This function displays a formatted string
  551. Arguments:
  552. pBuf - points to the string buffer
  553. cBuf - Size of the string pointed to by pBuf
  554. Return Value:
  555. UINT - total characters displayed
  556. Development History:
  557. 14-Dec-1993 Tue 09:47:06 created
  558. Revision History:
  559. --*/
  560. {
  561. BYTE Ch;
  562. UINT i = 1;
  563. if (!cBuf) {
  564. cBuf = strlen(pBuf);
  565. }
  566. fprintf(stdout, "\"");
  567. while (cBuf--) {
  568. Ch = *pBuf++;
  569. i += 2;
  570. if ((Ch >= ' ') && (Ch <= 0x7f)) {
  571. if (Ch == '\\') {
  572. fprintf(stdout, "\\\\");
  573. } else if (Ch == '\"') {
  574. fprintf(stdout, "\\\"");
  575. } else {
  576. fprintf(stdout, "%c", Ch);
  577. --i;
  578. }
  579. } else {
  580. if (Ch == '\a') {
  581. fprintf(stdout, "\\a");
  582. } else if (Ch == '\b') {
  583. fprintf(stdout, "\\b");
  584. } else if (Ch == '\f') {
  585. fprintf(stdout, "\\f");
  586. } else if (Ch == '\n') {
  587. fprintf(stdout, "\\n");
  588. } else if (Ch == '\r') {
  589. fprintf(stdout, "\\r");
  590. } else if (Ch == '\t') {
  591. fprintf(stdout, "\\t");
  592. } else {
  593. fprintf(stdout, "\\x%02x", Ch);
  594. ++i;
  595. }
  596. }
  597. }
  598. fprintf(stdout, "\"");
  599. return(++i);
  600. }
  601. BOOL
  602. ShowOnePlotKey(
  603. PPLOTGPC pPlotGPC,
  604. PPLOTKEY pPK,
  605. UINT VarSizeIdx,
  606. UINT MaxLen
  607. )
  608. /*++
  609. Routine Description:
  610. This function takes a PLOTKEY structure and displays its content
  611. Arguments:
  612. pPlotGPC - Points to the current PLOTGPC data structure
  613. pPK - Points to the PLOTKEY data structure
  614. VarSizeIdx - a variable size index, must be less then pVS->Count
  615. MaxLen - The size to pack the output into
  616. Return Value:
  617. BOOL
  618. Development History:
  619. 14-Dec-1993 Tue 09:48:13 created
  620. Revision History:
  621. --*/
  622. {
  623. PGPCVARSIZE pVS = NULL;
  624. LPBYTE pData;
  625. PFORMSRC pFS;
  626. PPENDATA pPD;
  627. UINT i;
  628. DWORD dw;
  629. pData = ADD_PLOTOFF(pPlotGPC, pPK);
  630. if (pPK->Flags & PKF_VARSIZE) {
  631. pVS = (PGPCVARSIZE)pData;
  632. if (VarSizeIdx >= pVS->Count) {
  633. DispError(-1, "VarSizeIdx [%u] > GPCVarSize.Count [%u",
  634. VarSizeIdx, pVS->Count);
  635. return(FALSE);
  636. }
  637. pData = (LPBYTE)pPK->pInfo + (pVS->SizeEach * VarSizeIdx);
  638. }
  639. fprintf(stdout, "\n%s", pPK->pKeyword);
  640. ShowSpaces(MaxKeywordLen - pPK->KeywordLen + 1);
  641. fprintf(stdout, "{ ");
  642. switch (pPK->Type) {
  643. case PK_FLAG:
  644. fprintf(stdout, "%c", (pPlotGPC->Flags & pPK->Data) ? '1' : '0');
  645. break;
  646. case PK_WORD:
  647. case PK_DWORD:
  648. ShowNumbers(pData,
  649. (PPLOTVAL)pPK->pInfo,
  650. pPK->Type,
  651. (UINT)pPK->Count,
  652. (pPK->Data == PLOTOFF(ci)) ? 5 : 0,
  653. (pPK->Data == PLOTOFF(ci)) ? 3 : 6);
  654. break;
  655. case PK_STRING:
  656. if (pVS) {
  657. ShowString(pData, pVS->SizeEach);
  658. } else {
  659. ShowString(pData, 0);
  660. }
  661. break;
  662. case PK_FORMSRC:
  663. pFS = (PFORMSRC)pData;
  664. i = ShowString(pFS->Name, 0);
  665. fprintf(stdout, ",");
  666. ShowSpaces(MaxLen + 2 - i);
  667. fprintf(stdout, "%7lu,%8lu,%5lu,%5lu,%5lu,%5lu",
  668. pFS->Size.cx, pFS->Size.cy,
  669. pFS->Margin.left, pFS->Margin.top,
  670. pFS->Margin.right, pFS->Margin.bottom);
  671. break;
  672. case PK_PENDATA:
  673. pPD = (PPENDATA)pData;
  674. dw = VarSizeIdx + 1;
  675. ShowNumbers((LPBYTE)&dw, NULL, PK_DWORD, 1, 2, 1);
  676. fprintf(stdout, ", ");
  677. i = ShowString(PenColorVal[pPD->ColorIdx].pValName, 0);
  678. ShowSpaces(MaxLen + 2 - i);
  679. break;
  680. }
  681. fprintf(stdout, " }");
  682. return(TRUE);
  683. }
  684. VOID
  685. ShowPlotGPC(
  686. PPLOTGPC pPlotGPC
  687. )
  688. /*++
  689. Routine Description:
  690. This function show current settings of plotter GPC structure.
  691. Arguments:
  692. pPlotGPC - the GPC to be displayed
  693. Return Value:
  694. VOID
  695. Development History:
  696. 09-Nov-1993 Tue 19:07:05 created
  697. Revision History:
  698. --*/
  699. {
  700. PGPCVARSIZE pVS;
  701. PFORMSRC pFS;
  702. PPLOTKEY pPK;
  703. PLOTKEY PK;
  704. UINT i;
  705. UINT Size;
  706. UINT Count;
  707. UINT MaxLen = 0;
  708. fprintf(stdout, "\n\n;\n; '%s' plotter characterization data\n;\n",
  709. pPlotGPC->DeviceName);
  710. pPK = &PlotKey[0];
  711. while (pPK->pKeyword) {
  712. PK = *pPK++;
  713. if (PK.Flags & PKF_VARSIZE) {
  714. pVS = (PGPCVARSIZE)ADD_PLOTOFF(pPlotGPC, (&PK));
  715. Count = pVS->Count;
  716. PK.pInfo = pVS->pData;
  717. } else {
  718. Count = 1;
  719. }
  720. if (PK.Type == PK_FORMSRC) {
  721. if (PK.Flags & PKF_VARSIZE) {
  722. pFS = (PFORMSRC)PK.pInfo;
  723. } else {
  724. pFS = (PFORMSRC)ADD_PLOTOFF(pPlotGPC, pPK);
  725. }
  726. for (MaxLen = i = 0; i < Count; i++, pFS++) {
  727. if ((Size = strlen(pFS->Name)) > MaxLen) {
  728. MaxLen = Size;
  729. }
  730. }
  731. }
  732. if (PK.Type == PK_PENDATA) {
  733. MaxLen = MaxPCValLen;
  734. }
  735. if (Count > 1) {
  736. fprintf(stdout, "\n");
  737. }
  738. for (i = 0; i < Count; i++) {
  739. ShowOnePlotKey(pPlotGPC, &PK, i, MaxLen);
  740. }
  741. }
  742. fprintf(stdout, "\n\n");
  743. }
  744. #if 0
  745. VOID
  746. ShowUndefined(
  747. VOID
  748. )
  749. /*++
  750. Routine Description:
  751. This function displayes all undefined keywords
  752. Arguments:
  753. nono
  754. Return Value:
  755. VOID
  756. Development History:
  757. 12-Nov-1993 Fri 17:20:24 created
  758. Revision History:
  759. --*/
  760. {
  761. PPLOTKEY pPK;
  762. BOOL Ok = TRUE;
  763. pPK = (PPLOTKEY)&PlotKey[0];
  764. while (pPK->pKeyword) {
  765. if (!(pPK->Flags & PKF_DEFINED)) {
  766. DispError(1, "keyword '%s' not defined.", pPK->pKeyword);
  767. Ok = FALSE;
  768. }
  769. ++pPK;
  770. }
  771. if (!Ok) {
  772. fprintf(stdout, "\n\n");
  773. }
  774. }
  775. #endif
  776. LPBYTE
  777. GetOneLine(
  778. BOOL SkipFrontSpace
  779. )
  780. /*++
  781. Routine Description:
  782. This function return the next line in the input file string
  783. Arguments:
  784. SkipFrontSpace - skip the white space in the begining of the line
  785. Return Value:
  786. pointer to the string, NULL if Error/EOF
  787. Development History:
  788. 09-Nov-1993 Tue 10:39:31 created
  789. Revision History:
  790. --*/
  791. {
  792. LPBYTE pLine;
  793. static BYTE LineBuf[1024];
  794. while (fgets(LineBuf, sizeof(LineBuf) - 1, InFile)) {
  795. ++LineNo;
  796. //
  797. // Skip End white spaces
  798. //
  799. pLine = &LineBuf[strlen(LineBuf)];
  800. while ((pLine > LineBuf) && (isspace(*(pLine - 1)))) {
  801. --pLine;
  802. }
  803. *pLine = '\0';
  804. //
  805. // Skip Front white spaces
  806. //
  807. pLine = LineBuf;
  808. if (SkipFrontSpace) {
  809. while ((*pLine) && (isspace(*pLine))) {
  810. ++pLine;
  811. }
  812. }
  813. if (*pLine) {
  814. return(pLine);
  815. }
  816. }
  817. return (NULL);
  818. }
  819. LPBYTE
  820. ParseString(
  821. LPSTR pKeyword,
  822. LPBYTE *pLineLoc,
  823. LPBYTE pBuf,
  824. SHORT cBuf
  825. )
  826. /*++
  827. Routine Description:
  828. This function takes a pBuf and parses a series of characters into a string,
  829. it may contain escape format characters, the string may or may not be NULL
  830. terminated
  831. Arguments:
  832. pKeyword - Current keyword name
  833. pLineLoc - Pointer to pointer of buffer line location
  834. pBuf - Pointer to the buffer
  835. cBuf - size of output buffer, if negative then NULL is allowed in
  836. the string
  837. Return Value:
  838. LPBYTE points to the end of the string, NULL if failure.
  839. Development History:
  840. 14-Dec-1993 Tue 09:52:07 created
  841. Revision History:
  842. --*/
  843. {
  844. #define STR_STATE_ERROR -1
  845. #define STR_STATE_END 0
  846. #define STR_STATE_BYTE 1
  847. #define STR_STATE_BKSLASH 2
  848. #define STR_STATE_HEX1 3
  849. #define STR_STATE_HEX2 4
  850. #define STR_STATE_OCT2 5
  851. #define STR_STATE_OCT3 6
  852. LPBYTE pLine;
  853. LPBYTE pStrBuf;
  854. LPBYTE pEnd;
  855. INT State;
  856. INT Number;
  857. BOOL Error = FALSE;
  858. BOOL szStr;
  859. BYTE Ch;
  860. if (cBuf < 0) {
  861. cBuf = -cBuf;
  862. szStr = FALSE;
  863. } else {
  864. szStr = TRUE;
  865. }
  866. pLine = *pLineLoc;
  867. pStrBuf = pBuf;
  868. pEnd = pBuf + cBuf - 1;
  869. State = STR_STATE_BYTE;
  870. while ((State != STR_STATE_ERROR) &&
  871. (State != STR_STATE_END) &&
  872. (pBuf <= pEnd) &&
  873. (Ch = *pLine++)) {
  874. switch (State) {
  875. case STR_STATE_BYTE:
  876. if (Ch == '\\') {
  877. //
  878. // Check if end of the line, if so read the next line in
  879. // without stripping white space.
  880. //
  881. if (*pLine == '\0') {
  882. if (!(pLine = GetOneLine(FALSE))) {
  883. Ch = 0;
  884. State = STR_STATE_ERROR;
  885. } else {
  886. continue;
  887. }
  888. } else {
  889. State = STR_STATE_BKSLASH;
  890. }
  891. } else if (Ch == '\"') {
  892. State = STR_STATE_END;
  893. }
  894. break;
  895. case STR_STATE_BKSLASH:
  896. State = STR_STATE_BYTE;
  897. switch (Ch) {
  898. case '0': //
  899. case '1': // Maximum OCT number is 377
  900. case '2':
  901. case '3':
  902. Number = (INT)(Ch - '0');
  903. State = STR_STATE_OCT2;
  904. break;
  905. case 'x':
  906. Number = 0;
  907. State = STR_STATE_HEX1;
  908. break;
  909. case 'a':
  910. Ch = '\a';
  911. break;
  912. case 'b':
  913. Ch = '\b';
  914. break;
  915. case 'f':
  916. Ch = '\f';
  917. break;
  918. case 'n':
  919. Ch = '\n';
  920. break;
  921. case 'r':
  922. Ch = '\r';
  923. break;
  924. case 't':
  925. Ch = '\t';
  926. break;
  927. case '\\':
  928. case '\"':
  929. break;
  930. default:
  931. DispError(2, "Invalid escape character '%c' (%s)", Ch, pKeyword);
  932. State = STR_STATE_ERROR;
  933. }
  934. break;
  935. case STR_STATE_OCT2:
  936. case STR_STATE_OCT3:
  937. if ((Ch >= '0') && (Ch <= '7')) {
  938. Number = (INT)((Number * 8) + (Ch - '0'));
  939. if (State == STR_STATE_OCT2) {
  940. State = STR_STATE_OCT3;
  941. } else {
  942. State = STR_STATE_BYTE;
  943. Ch = (BYTE)Number;
  944. }
  945. } else {
  946. DispError(2, "invalid digits for octal number '%c'", Ch);
  947. State = STR_STATE_ERROR;
  948. }
  949. break;
  950. case STR_STATE_HEX1:
  951. case STR_STATE_HEX2:
  952. if ((Ch >= '0') && (Ch <= '9')) {
  953. Number = (INT)((Number << 4) | (Ch - '0'));
  954. } else if ((Ch >= 'a') && (Ch <= 'f')) {
  955. Number = (INT)((Number << 4) | (Ch - 'a' + 10));
  956. } else if ((Ch >= 'A') && (Ch <= 'F')) {
  957. Number = (INT)((Number << 4) | (Ch - 'A' + 10));
  958. } else if (State == STR_STATE_HEX1) {
  959. DispError(2, "string hex escape must have at least one hex digit");
  960. State = STR_STATE_ERROR;
  961. } else {
  962. --pLine; // re-process current one
  963. }
  964. if (State == STR_STATE_HEX1) {
  965. State = STR_STATE_HEX2;
  966. } else {
  967. Ch = (BYTE)Number;
  968. State = STR_STATE_BYTE;
  969. }
  970. }
  971. if (State == STR_STATE_BYTE) {
  972. if ((szStr) && (!Ch)) {
  973. //
  974. // Do not allowe zero in the string
  975. //
  976. DispError(2, "CANNOT have NULL char. in the middle of '%s' string",
  977. pKeyword);
  978. State = STR_STATE_ERROR;
  979. } else {
  980. *pBuf++ = Ch;
  981. }
  982. }
  983. }
  984. if (State != STR_STATE_END) {
  985. Error = TRUE;
  986. if (pBuf > pEnd) {
  987. DispError(2, "string too big: maximum length is %u for '%s'.",
  988. cBuf - 1, pKeyword);
  989. } else if (Ch == 0) {
  990. DispError(2, "string must end with a '\"'");
  991. }
  992. }
  993. *pLineLoc = pLine;
  994. if (Error) {
  995. return(NULL);
  996. } else {
  997. *pBuf = '\0';
  998. if (pStrBuf == pBuf) {
  999. DispError(1, "NULL string is defined for '%s'", pKeyword);
  1000. }
  1001. return(pBuf);
  1002. }
  1003. #undef STR_STATE_ERROR
  1004. #undef STR_STATE_END
  1005. #undef STR_STATE_BYTE
  1006. #undef STR_STATE_BKSLASH
  1007. #undef STR_STATE_HEX1
  1008. #undef STR_STATE_HEX2
  1009. #undef STR_STATE_OCT2
  1010. #undef STR_STATE_OCT3
  1011. }
  1012. LPBYTE
  1013. GetNextToken(
  1014. LPSTR pKeyword,
  1015. LPBYTE pBuf,
  1016. SHORT cBuf
  1017. )
  1018. /*++
  1019. Routine Description:
  1020. This function retrieves the next token from the input file
  1021. Arguments:
  1022. pKeyword - Current keyword name
  1023. pBuf - pointer to the string parsing output buffer, if not NULL
  1024. cBuf - size of pBuf
  1025. Return Value:
  1026. LPBYTE - a pointer to the output buffer or token string, NULL if failure
  1027. Development History:
  1028. 09-Nov-1993 Tue 11:21:11 created
  1029. Revision History:
  1030. --*/
  1031. {
  1032. static LPBYTE pLine = NULL;
  1033. static BYTE LastCh = '\0';
  1034. if (pLine == NULL) {
  1035. LineNo = 0;
  1036. pLine = GetOneLine(TRUE);
  1037. }
  1038. if (LastCh) {
  1039. *pLine = LastCh;
  1040. LastCh = '\0';
  1041. }
  1042. LastCh = 0;
  1043. if (pBuf) {
  1044. if (!cBuf) {
  1045. return(pBuf);
  1046. }
  1047. //
  1048. // reading a string section
  1049. //
  1050. while (pLine) {
  1051. while((*pLine) &&
  1052. ((isspace(*pLine)) ||
  1053. (*pLine == ','))) {
  1054. pLine++;
  1055. }
  1056. if ((*pLine) && (*pLine != ';')) {
  1057. if (*pLine++ != '"') {
  1058. DispError(2, "string must enclosed by \" (Quote)");
  1059. return(NULL);
  1060. }
  1061. return(ParseString(pKeyword, &pLine, pBuf, cBuf));
  1062. } else {
  1063. pLine = GetOneLine(TRUE);
  1064. }
  1065. }
  1066. } else {
  1067. while (pLine) {
  1068. while((*pLine) &&
  1069. ((isspace(*pLine)) ||
  1070. (*pLine == ','))) {
  1071. pLine++;
  1072. }
  1073. if ((*pLine) && (*pLine != ';')) {
  1074. LPBYTE pLineRet = pLine;
  1075. while((*pLine) &&
  1076. (!isspace(*pLine)) &&
  1077. (*pLine != ',') &&
  1078. (*pLine != '{') &&
  1079. (*pLine != '}')) {
  1080. ++pLine;
  1081. }
  1082. if ((*pLine == '{') ||
  1083. (*pLine == '}')) {
  1084. if (pLine == pLineRet) {
  1085. ++pLine;
  1086. }
  1087. LastCh = *pLine;
  1088. *pLine = '\0';
  1089. } else {
  1090. *pLine++ = '\0';
  1091. }
  1092. // fprintf(stderr, "\nTOKEN = '%s'", pLineRet);
  1093. return(pLineRet);
  1094. } else {
  1095. pLine = GetOneLine(TRUE);
  1096. }
  1097. }
  1098. }
  1099. return(NULL);
  1100. }
  1101. BOOL
  1102. CheckSingleToken(
  1103. BYTE Token
  1104. )
  1105. /*++
  1106. Routine Description:
  1107. Check if a single character 'Token' exists
  1108. Arguments:
  1109. Token - Token to be checked
  1110. Return Value:
  1111. TRUE if found, FALSE otherwise
  1112. Development History:
  1113. 09-Nov-1993 Tue 12:13:33 created
  1114. Revision History:
  1115. --*/
  1116. {
  1117. LPBYTE pToken;
  1118. if (!(pToken = GetNextToken(NULL, NULL, 0))) {
  1119. DispError(2, "Unexpected end of file.");
  1120. return(FALSE);
  1121. }
  1122. return(*pToken == Token);
  1123. }
  1124. BOOL
  1125. ConvertNumber(
  1126. LPSTR pBuf,
  1127. BOOL NegOk,
  1128. LONG *pRetVal
  1129. )
  1130. /*++
  1131. Routine Description:
  1132. Convert pBuf to a number based on the parameters passed
  1133. Arguments:
  1134. pBuf - Point to the string to be converted to a number
  1135. NegOk - TRUE if a negative number is allowed
  1136. pRetVal - Pointer to a LONG to return a converted number
  1137. Return Value:
  1138. TRUE if sucessful, FALSE if falied.
  1139. Development History:
  1140. 09-Nov-1993 Tue 18:47:43 created
  1141. Revision History:
  1142. --*/
  1143. {
  1144. if ((*pRetVal = atol(pBuf)) < 0) {
  1145. if (!NegOk) {
  1146. DispError(2, "expect a positive number. [%s]", pBuf);
  1147. return(FALSE);
  1148. }
  1149. } else if (*pRetVal == 0) {
  1150. if (*pBuf != '0') {
  1151. DispError(2, "expect a number. [%s]", pBuf);
  1152. return(FALSE);
  1153. }
  1154. }
  1155. return(TRUE);
  1156. }
  1157. INT
  1158. ReadNumbers(
  1159. LPSTR pKeyword,
  1160. LPVOID pNumbers,
  1161. PPLOTVAL pPlotVal,
  1162. UINT Total,
  1163. UINT Type,
  1164. UINT Flags
  1165. )
  1166. /*++
  1167. Routine Description:
  1168. This function reads the next token and returns a number, the number can be
  1169. 1. '0x' prefixed for a hex type
  1170. 2. normal for an integer type
  1171. Arguments:
  1172. pPK - Pointer to PLOTKEY
  1173. Return Value:
  1174. Expanded to DWORD, this function will only read positive numbers
  1175. Development History:
  1176. 09-Nov-1993 Tue 11:03:36 created
  1177. Revision History:
  1178. --*/
  1179. {
  1180. PPLOTVAL pPV;
  1181. LPBYTE pToken;
  1182. UINT Count;
  1183. DWORD SetBit;
  1184. DWORD *pdw;
  1185. WORD *pw;
  1186. pdw = NULL;
  1187. pw = NULL;
  1188. switch (Type) {
  1189. case PK_WORD:
  1190. pw = (WORD *)pNumbers;
  1191. break;
  1192. case PK_DWORD:
  1193. pdw = (DWORD *)pNumbers;
  1194. break;
  1195. case PK_FLAG:
  1196. if (Total != 1) {
  1197. DispError(-1, "PK_FLAG has more than one count");
  1198. Total = 1;
  1199. }
  1200. SetBit = *(DWORD *)pNumbers;
  1201. break;
  1202. default:
  1203. DispError(-1, "!!Unknow key type!!, internal error");
  1204. return(-1);
  1205. }
  1206. for (Count = 0; Count < Total; Count++) {
  1207. LONG RetVal;
  1208. BYTE Ch;
  1209. RetVal = 0;
  1210. if (pToken = GetNextToken(pKeyword, NULL, 0)) {
  1211. if (*pToken == '}') {
  1212. if (!Count) {
  1213. DispError(1, "%s none of %u numbers defined",
  1214. pKeyword, Total);
  1215. } else {
  1216. DispError(1, "%s defined only %u of %u numbers",
  1217. pKeyword, Count, Total);
  1218. }
  1219. if (Flags & PKF_ALL) {
  1220. DispError(2, "All %u numbers in keyword '%s' must defined",
  1221. Total, pKeyword);
  1222. return(-1);
  1223. } else {
  1224. return(0x01);
  1225. }
  1226. } else if (pPV = pPlotVal) {
  1227. while (pPV->pValName) {
  1228. if (!_stricmp(pToken, pPV->pValName)) {
  1229. break;
  1230. }
  1231. ++pPV;
  1232. }
  1233. if (pPV->pValName) {
  1234. RetVal = pPV->Val;
  1235. } else {
  1236. DispError(2, "unknown key value '%s' for keyword '%s'",
  1237. pToken, pKeyword);
  1238. return(-1);
  1239. }
  1240. } else if ((*pToken == '0') &&
  1241. ((*(pToken + 1) == 'x') || (*(pToken + 1) == 'X'))) {
  1242. //
  1243. // This is a Hex type format
  1244. //
  1245. pToken += 2;
  1246. while (Ch = *pToken++) {
  1247. if ((Ch >= '0') && (Ch <= '9')) {
  1248. Ch -= '0';
  1249. } else if ((Ch >= 'a') && (Ch <= 'f')) {
  1250. Ch = (Ch - 'a') + 10;
  1251. } else if ((Ch >= 'A') && (Ch <= 'F')) {
  1252. Ch = (Ch - 'A') + 10;
  1253. } else {
  1254. break;
  1255. }
  1256. RetVal = (LONG)(((DWORD)RetVal << 4) | (DWORD)Ch);
  1257. }
  1258. } else if (!ConvertNumber(pToken, Type == PK_FLAG, &RetVal)) {
  1259. DispError(2, "expect another %u numbers. [%s]",
  1260. Total - Count, pToken);
  1261. return(-1);
  1262. }
  1263. if (pdw) {
  1264. *pdw++ = (DWORD)RetVal;
  1265. } else if (pw) {
  1266. *pw++ = (WORD)RetVal;
  1267. } else {
  1268. if (RetVal) {
  1269. PlotGPC.Flags |= SetBit;
  1270. } else {
  1271. PlotGPC.Flags &= ~SetBit;
  1272. }
  1273. }
  1274. } else {
  1275. DispError(2, "'%s' expect another %u numbers. [End Of File]",
  1276. pKeyword, Total - Count);
  1277. return(-1);
  1278. }
  1279. }
  1280. return(0);
  1281. }
  1282. INT
  1283. ReadString(
  1284. PPLOTKEY pPK
  1285. )
  1286. /*++
  1287. Routine Description:
  1288. This function reads in the string for the PK (plotkey)
  1289. Arguments:
  1290. pPK - Points to the PLOTKEY data structure
  1291. Return Value:
  1292. size of the string that was read.
  1293. Development History:
  1294. 12-Nov-1993 Fri 12:25:50 created
  1295. Revision History:
  1296. --*/
  1297. {
  1298. LPBYTE pBuf;
  1299. LPBYTE pEnd;
  1300. pBuf = (LPBYTE)((pPK->Flags & PKF_VARSIZE) ? pPK->pInfo : GET_PLOTOFF(pPK));
  1301. if (!(pPK->Flags & PKF_VARSIZE)) {
  1302. if (pPK->Count < 0) {
  1303. DispError(-1, "'%s' is a non-variable size string, it CANNOT have NULL char",
  1304. pPK->pKeyword);
  1305. return(-1);
  1306. }
  1307. }
  1308. if (pEnd = GetNextToken(pPK->pKeyword, pBuf, pPK->Count)) {
  1309. UINT Size = (UINT)(pEnd - pBuf);
  1310. if (pPK->Flags & PKF_VARSIZE) {
  1311. PGPCVARSIZE pVS;
  1312. pVS = (PGPCVARSIZE)GET_PLOTOFF(pPK);
  1313. if (Size) {
  1314. pVS->Count = 1;
  1315. }
  1316. pVS->SizeEach = (WORD)Size;
  1317. pVS->pData = NULL;
  1318. }
  1319. return((pBuf[0] == '\0') ? 0x02 : 0x00);
  1320. }
  1321. return(-1);
  1322. }
  1323. BOOL
  1324. CheckFormSrc(
  1325. LPBYTE pKeyword,
  1326. WORD Flags,
  1327. SIZEL *pSize,
  1328. RECTL *pMargin,
  1329. LPSTR pFormName,
  1330. INT ErrNo
  1331. )
  1332. /*++
  1333. Routine Description:
  1334. Check if FORMSRC input is valid
  1335. Arguments:
  1336. pKeyword - Point to current keyword
  1337. Flags - PKF_xxxx
  1338. pSize - pointer to SIZEL for Form size
  1339. RECTL - Pointer to the RECTL for margins
  1340. pFormName - Name of the form
  1341. ErrNo - error number to send to DispError() if an error occurs
  1342. Return Value:
  1343. TRUE if OK, FALSE otherwise
  1344. Development History:
  1345. 18-Nov-1993 Thu 00:04:12 created
  1346. Revision History:
  1347. --*/
  1348. {
  1349. if (pSize->cx < MIN_PLOTGPC_FORM_CX) {
  1350. DispError(ErrNo, "minimum height for '%s' (%s) must >= %lu",
  1351. pFormName, pKeyword, MIN_PLOTGPC_FORM_CX);
  1352. return(FALSE);
  1353. }
  1354. if (pSize->cy < MIN_PLOTGPC_FORM_CY) {
  1355. if (Flags & PKF_FS_VARLEN) {
  1356. if (pSize->cy) {
  1357. pSize->cy = 0;
  1358. DispError(1, "ASSUME variable length (set to 0) for '%s' (%s)",
  1359. pFormName, pKeyword);
  1360. }
  1361. } else {
  1362. DispError(ErrNo, "minimum height for '%s' (%s) must >= %lu",
  1363. pFormName, pKeyword, MIN_PLOTGPC_FORM_CY);
  1364. return(FALSE);
  1365. }
  1366. }
  1367. if ((pSize->cx - pMargin->left - pMargin->right) < MIN_PLOTGPC_FORM_CX) {
  1368. DispError(ErrNo, "invalid left/right margins for '%s' (%s)",
  1369. pFormName, pKeyword);
  1370. return(FALSE);
  1371. }
  1372. if ((pSize->cy) &&
  1373. ((pSize->cx - pMargin->left - pMargin->right) < MIN_PLOTGPC_FORM_CY)) {
  1374. DispError(ErrNo, "invalid top/bottom margins for '%s' (%s)",
  1375. pFormName, pKeyword);
  1376. return(FALSE);
  1377. }
  1378. return(TRUE);
  1379. }
  1380. INT
  1381. ReadFormSrc(
  1382. PPLOTKEY pPK
  1383. )
  1384. /*++
  1385. Routine Description:
  1386. Input a FORMSRC line from the input file.
  1387. Arguments:
  1388. pPK - Pointer to the PLOTKEY data structure
  1389. Return Value:
  1390. INT - >= 0 if OK, -1 if failure, a 0 return means no '}' end bracket is read
  1391. a > 0 means '}' already read.
  1392. Development History:
  1393. 12-Nov-1993 Fri 13:34:50 created
  1394. Revision History:
  1395. --*/
  1396. {
  1397. PGPCVARSIZE pVS;
  1398. PFORMSRC pFS;
  1399. pVS = NULL;
  1400. pFS = (PFORMSRC)GET_PLOTOFF(pPK);
  1401. if (pPK->Flags & PKF_VARSIZE) {
  1402. pVS = (PGPCVARSIZE)pFS;
  1403. pFS = (PFORMSRC)pPK->pInfo;
  1404. if (pVS->Count >= pPK->Count) {
  1405. DispError(2, "too many '%s' defined, allowed only (%u)",
  1406. pPK->pKeyword, pPK->Count);
  1407. return(-1);
  1408. }
  1409. pFS += pVS->Count;
  1410. }
  1411. ZeroMemory(pFS, sizeof(FORMSRC));
  1412. if ((GetNextToken(pPK->pKeyword, pFS->Name, CCHFORMNAME)) &&
  1413. (pFS->Name[0]) &&
  1414. (ReadNumbers(pPK->pKeyword,
  1415. (LPVOID)&pFS->Size,
  1416. NULL,
  1417. 6,
  1418. PK_DWORD,
  1419. PKF_REQ) >= 0) &&
  1420. (CheckFormSrc(pPK->pKeyword,
  1421. pPK->Flags,
  1422. &(pFS->Size),
  1423. &(pFS->Margin),
  1424. &(pFS->Name[0]),
  1425. 2))) {
  1426. if (pVS) {
  1427. PFORMSRC pOrgFS = (PFORMSRC)pPK->pInfo;
  1428. UINT i = pVS->Count;
  1429. while (i--) {
  1430. if (_stricmp(pFS->Name, pOrgFS->Name) == 0) {
  1431. DispError(2, "'%s' already defined in keyword '%s'",
  1432. pOrgFS->Name, pPK->pKeyword);
  1433. return(-1);
  1434. }
  1435. pOrgFS++;
  1436. }
  1437. pVS->Count += 1;
  1438. pVS->SizeEach = sizeof(FORMSRC);
  1439. pVS->pData = NULL;
  1440. }
  1441. return(0);
  1442. }
  1443. return(-1);
  1444. }
  1445. INT
  1446. ReadPenData(
  1447. PPLOTKEY pPK
  1448. )
  1449. /*++
  1450. Routine Description:
  1451. Read a PENDATA structure
  1452. Arguments:
  1453. pPK - Pointer to the PLOTKEY data structure
  1454. Return Value:
  1455. INT - >= 0 if OK, -1 if failed, 0 if no '}' end bracket is
  1456. definined, > 0 means '}' already read.
  1457. Development History:
  1458. 12-Nov-1993 Fri 13:34:50 created
  1459. Revision History:
  1460. --*/
  1461. {
  1462. PGPCVARSIZE pVS;
  1463. PPENDATA pPD;
  1464. PENDATA PD;
  1465. WORD IdxPen;
  1466. INT Ret;
  1467. pVS = (PGPCVARSIZE)GET_PLOTOFF(pPK);
  1468. pPD = (PPENDATA)pPK->pInfo;
  1469. if ((ReadNumbers(pPK->pKeyword,
  1470. (LPVOID)&IdxPen,
  1471. NULL,
  1472. 1,
  1473. PK_WORD,
  1474. PKF_REQ) == 0) &&
  1475. ((Ret = ReadNumbers(pPK->pKeyword,
  1476. (LPVOID)&PD.ColorIdx,
  1477. PenColorVal,
  1478. 1,
  1479. PK_WORD,
  1480. PKF_REQ)) >= 0)) {
  1481. if (IdxPen <= 0) {
  1482. DispError(2, "first pen number started at one (1), not zero (0).");
  1483. return(-1);
  1484. }
  1485. if (IdxPen > MAX_PENPLOTTER_PENS) {
  1486. DispError(2, "maximum pen number is '%s'.", MAX_PENPLOTTER_PENS);
  1487. return(-1);
  1488. }
  1489. pPD += (IdxPen - 1);
  1490. if (pPD->ColorIdx != 0xffff) {
  1491. DispError(1, "redefined Pen #%d for '%s' keyword '%s'",
  1492. IdxPen, pPK->pKeyword);
  1493. } else {
  1494. ++pVS->Count;
  1495. }
  1496. *pPD = PD;
  1497. pVS->SizeEach = sizeof(PENDATA);
  1498. pVS->pData = NULL;
  1499. return(Ret);
  1500. }
  1501. return(-1);
  1502. }
  1503. PPLOTGPC
  1504. GetFullPlotGPC(
  1505. VOID
  1506. )
  1507. /*++
  1508. Routine Description:
  1509. This function converts the current contents of PlotGPC to allocated memory
  1510. so it has the entire PLOTGPC defined
  1511. Arguments:
  1512. VOID
  1513. Return Value:
  1514. PPLOTGPC, Pointer to the PLOTGPC packed and converted, NULL if failure
  1515. Development History:
  1516. 17-Nov-1993 Wed 17:08:53 created
  1517. Revision History:
  1518. --*/
  1519. {
  1520. PPLOTGPC pPlotGPC;
  1521. LPBYTE pData;
  1522. DWORD InitStrSize[2];
  1523. DWORD FormsSize[2];
  1524. DWORD PlotPensSize[2];
  1525. DWORD SizeExtra;
  1526. if ((PlotGPC.InitString.Count == 1) ||
  1527. (PlotGPC.InitString.SizeEach)) {
  1528. //
  1529. // Include the NULL terminated character
  1530. //
  1531. InitStrSize[0] = PlotGPC.InitString.SizeEach + 1;
  1532. } else {
  1533. InitStrSize[0] = 0;
  1534. ZeroMemory(&(PlotGPC.InitString), sizeof(GPCVARSIZE));
  1535. }
  1536. if ((PlotGPC.Forms.Count) &&
  1537. (PlotGPC.Forms.SizeEach == sizeof(FORMSRC))) {
  1538. FormsSize[0] = sizeof(FORMSRC) * PlotGPC.Forms.Count;
  1539. } else {
  1540. FormsSize[0] = 0;
  1541. ZeroMemory(&(PlotGPC.Forms), sizeof(GPCVARSIZE));
  1542. }
  1543. if ((PlotGPC.Pens.Count) &&
  1544. (PlotGPC.Pens.SizeEach == sizeof(PENDATA))) {
  1545. PlotPensSize[0] = sizeof(PENDATA) * PlotGPC.Pens.Count;
  1546. } else {
  1547. PlotPensSize[0] = 0;
  1548. ZeroMemory(&(PlotGPC.Pens), sizeof(GPCVARSIZE));
  1549. }
  1550. SizeExtra = (InitStrSize[1] = DWORD_ALIGNED(InitStrSize[0])) +
  1551. (FormsSize[1] = DWORD_ALIGNED(FormsSize[0])) +
  1552. (PlotPensSize[1] = DWORD_ALIGNED(PlotPensSize[0]));
  1553. PLOTDBG(DBG_FULLGPC, ("Size = PLOTGPC=%ld + SizeExtra=%ld = %ld",
  1554. sizeof(PLOTGPC), SizeExtra, sizeof(PLOTGPC) + SizeExtra));
  1555. if (pPlotGPC = (PPLOTGPC)LocalAlloc(LPTR, sizeof(PLOTGPC) + SizeExtra)) {
  1556. PlotGPC.SizeExtra = (WORD)SizeExtra;
  1557. CopyMemory(pData = (LPBYTE)pPlotGPC, &PlotGPC, sizeof(PLOTGPC));
  1558. pData += sizeof(PLOTGPC);
  1559. if (InitStrSize[0]) {
  1560. CopyMemory(pData, InitString, InitStrSize[0]);
  1561. pPlotGPC->InitString.pData = (LPVOID)pData;
  1562. pData += InitStrSize[1];
  1563. }
  1564. if (FormsSize[0]) {
  1565. CopyMemory(pData, AvaiForms, FormsSize[0]);
  1566. pPlotGPC->Forms.pData = (LPVOID)pData;
  1567. pData += FormsSize[1];
  1568. }
  1569. if (PlotPensSize[0]) {
  1570. CopyMemory(pData, AvaiPenData, PlotPensSize[0]);
  1571. pPlotGPC->Pens.pData = (LPVOID)pData;
  1572. pData += PlotPensSize[1];
  1573. }
  1574. }
  1575. return(pPlotGPC);
  1576. }
  1577. INT
  1578. ParsePlotGPC(
  1579. VOID
  1580. )
  1581. /*++
  1582. Routine Description:
  1583. This function parses a PlotGPC from a text file
  1584. Arguments:
  1585. VOID
  1586. Return Value:
  1587. INT, >= 0 means ok, -x if a failure occured.
  1588. Development History:
  1589. 09-Nov-1993 Tue 12:19:20 created
  1590. Revision History:
  1591. --*/
  1592. {
  1593. LPBYTE pToken;
  1594. PPLOTKEY pPK;
  1595. INT Result;
  1596. LONG cy;
  1597. INT i;
  1598. while (pToken = GetNextToken(NULL, NULL, 0)) {
  1599. pPK = (PPLOTKEY)&PlotKey[0];
  1600. while (pPK->pKeyword) {
  1601. if (!_stricmp(pToken, pPK->pKeyword)) {
  1602. break;
  1603. }
  1604. ++pPK;
  1605. }
  1606. if (pPK->pKeyword) {
  1607. // fprintf(stderr, "\nFound keyword '%s'", pToken);
  1608. if ((pPK->Flags & PKF_DEFINED) &&
  1609. (!(pPK->Flags & PKF_MUL_OK))) {
  1610. DispError(1, "keyword '%s' section redefined.", pToken);
  1611. }
  1612. if (!CheckSingleToken('{')) {
  1613. DispError(2, "expect '{' after keyword '%s. key values must enclosed in {}",
  1614. pPK->pKeyword);
  1615. return(-1);
  1616. }
  1617. switch (pPK->Type) {
  1618. case PK_FLAG:
  1619. Result = ReadNumbers(pPK->pKeyword,
  1620. (LPVOID)&(pPK->Data),
  1621. (PPLOTVAL)pPK->pInfo,
  1622. pPK->Count,
  1623. PK_FLAG,
  1624. pPK->Flags);
  1625. break;
  1626. case PK_WORD:
  1627. case PK_DWORD:
  1628. Result = ReadNumbers(pPK->pKeyword,
  1629. (LPVOID)GET_PLOTOFF(pPK),
  1630. (PPLOTVAL)pPK->pInfo,
  1631. pPK->Count,
  1632. pPK->Type,
  1633. pPK->Flags);
  1634. break;
  1635. case PK_STRING:
  1636. Result = ReadString(pPK);
  1637. break;
  1638. case PK_FORMSRC:
  1639. Result = ReadFormSrc(pPK);
  1640. break;
  1641. case PK_PENDATA:
  1642. Result = ReadPenData(pPK);
  1643. break;
  1644. default:
  1645. Result = -1;
  1646. break;
  1647. }
  1648. if (Result < 0) {
  1649. return(-1);
  1650. }
  1651. if (!(Result & 0x01)) {
  1652. if (!CheckSingleToken('}')) {
  1653. DispError(2, "unbalanced braces, missing '}' at end of keyword '%s'",
  1654. pPK->pKeyword);
  1655. return(-1);
  1656. }
  1657. }
  1658. if (!(Result & 0x02)) {
  1659. pPK->Flags |= PKF_DEFINED;
  1660. }
  1661. } else {
  1662. DispError(2, "Unknown keyword '%s'", pToken);
  1663. return(-1);
  1664. }
  1665. }
  1666. if (PlotGPC.Flags & PLOTF_RASTER) {
  1667. if (PlotGPC.Flags & PLOTF_COLOR) {
  1668. PlotGPC.Flags &= ~PLOTF_RTLMONO_NO_CID;
  1669. }
  1670. if ((pPK->pKeyword == szRTLMonoEncode5) &&
  1671. (!(pPK->Flags & PKF_DEFINED))) {
  1672. Result = -1;
  1673. DispError(2, "Flag keyword '%s' must defined for RASTER Plotter.", pPK->pKeyword);
  1674. }
  1675. } else {
  1676. PlotGPC.Flags |= (PLOTF_NO_BMP_FONT |
  1677. PLOTF_RTL_NO_DPI_XY |
  1678. PLOTF_RTLMONO_NO_CID |
  1679. PLOTF_RTLMONO_FIXPAL);
  1680. }
  1681. //
  1682. // Find out if a required keyword is missing
  1683. //
  1684. Result = 1;
  1685. pPK = (PPLOTKEY)&PlotKey[0];
  1686. while (pPK->pKeyword) {
  1687. if ((PlotGPC.Flags & PLOTF_RASTER) &&
  1688. (pPK->pKeyword == szRTLMonoEncode5) &&
  1689. (!(pPK->Flags & PKF_DEFINED))) {
  1690. Result = -1;
  1691. DispError(2, "Flag keyword '%s' must defined for RASTER Plotter.", pPK->pKeyword);
  1692. }
  1693. if ((pPK->Flags & PKF_REQ) &&
  1694. (!(pPK->Flags & PKF_DEFINED))) {
  1695. Result = -1;
  1696. DispError(2, "required keyword '%s' undefined", pPK->pKeyword);
  1697. }
  1698. ++pPK;
  1699. }
  1700. //
  1701. // Validate DeviceSize/DeviceMargins
  1702. //
  1703. if (PlotGPC.DeviceSize.cx < MIN_PLOTGPC_FORM_CX) {
  1704. DispError(2, "Invalid DeviceSize CX = %ld", PlotGPC.DeviceSize.cx);
  1705. Result = -1;
  1706. }
  1707. if (PlotGPC.DeviceSize.cy < MIN_PLOTGPC_FORM_CY) {
  1708. if (PlotGPC.Flags & PLOTF_ROLLFEED) {
  1709. PlotGPC.DeviceSize.cy = 15240000; // default to 50' of length
  1710. DispError(1, "Assume device length can handle up to 50 feet of paper");
  1711. } else {
  1712. PlotGPC.DeviceSize.cy = 279400; // default to 11" of length
  1713. DispError(1, "Assume device length can handle up to 11 inch of paper");
  1714. }
  1715. }
  1716. if (PlotGPC.DeviceSize.cx - (PlotGPC.DeviceMargin.left +
  1717. PlotGPC.DeviceMargin.right) < MIN_PLOTGPC_FORM_CX) {
  1718. DispError(3, "Invalid DeviceMargin left/right (%ld/%ld",
  1719. PlotGPC.DeviceMargin.left, PlotGPC.DeviceMargin.right);
  1720. Result = -1;
  1721. }
  1722. if (PlotGPC.DeviceSize.cy - (PlotGPC.DeviceMargin.top +
  1723. PlotGPC.DeviceMargin.bottom) < MIN_PLOTGPC_FORM_CY) {
  1724. DispError(3, "Invalid DeviceMargin top/bottom (%ld/%ld",
  1725. PlotGPC.DeviceMargin.top, PlotGPC.DeviceMargin.bottom);
  1726. Result = -1;
  1727. }
  1728. for (i = 0; i < (INT)PlotGPC.Forms.Count; i++) {
  1729. if ((!(PlotGPC.Flags & PLOTF_ROLLFEED)) &&
  1730. (AvaiForms[i].Size.cy == 0)) {
  1731. DispError(3, "%s '%s', the device CANNOT handle roll paper",
  1732. szFormInfo, AvaiForms[i].Name);
  1733. Result = -1;
  1734. }
  1735. if ((cy = AvaiForms[i].Size.cy) == 0) {
  1736. cy = PlotGPC.DeviceSize.cy;
  1737. }
  1738. if (((AvaiForms[i].Size.cx <= PlotGPC.DeviceSize.cx) &&
  1739. (cy <= PlotGPC.DeviceSize.cy)) ||
  1740. ((AvaiForms[i].Size.cx <= PlotGPC.DeviceSize.cy) &&
  1741. (cy <= PlotGPC.DeviceSize.cx))) {
  1742. NULL;
  1743. } else {
  1744. DispError(3, "%s '%s' size too big for device to handle",
  1745. szFormInfo, AvaiForms[i].Name);
  1746. Result = -1;
  1747. }
  1748. }
  1749. //
  1750. // Find out if pen data must be present
  1751. //
  1752. if (PlotGPC.Flags & PLOTF_RASTER) {
  1753. if (PlotGPC.Pens.Count) {
  1754. DispError(3, "CANNOT define Pen colors for a raster device");
  1755. Result = -1;
  1756. }
  1757. } else {
  1758. if (!(PlotGPC.Flags & PLOTF_NO_BMP_FONT)) {
  1759. DispError(3, "PEN plotter MUST SET '%s' to 1", szNoBmpFont);
  1760. Result = -1;
  1761. }
  1762. if (!(PlotGPC.Flags & PLOTF_COLOR)) {
  1763. DispError(3, "PEN plotter must specify COLOR. (ColorCap {1})");
  1764. Result = -1;
  1765. }
  1766. if (PlotGPC.MaxPens > MAX_PENPLOTTER_PENS) {
  1767. DispError(3, "maximum plotter Pens allowed are %ld, you defined %ld",
  1768. MAX_PENPLOTTER_PENS, PlotGPC.MaxPens);
  1769. PlotGPC.MaxPens = MAX_PENPLOTTER_PENS;
  1770. Result = -1;
  1771. }
  1772. if (PlotGPC.Pens.Count < PlotGPC.MaxPens) {
  1773. DispError(3, "only %ld pens out of %ld pens defined",
  1774. PlotGPC.Pens.Count, PlotGPC.MaxPens);
  1775. Result = -1;
  1776. }
  1777. if (PlotGPC.Pens.Count > PlotGPC.MaxPens) {
  1778. DispError(3, "too many pens (%ld) defined for '%s', Maximum is %ld",
  1779. PlotGPC.Pens.Count, szPenData, PlotGPC.MaxPens);
  1780. Result = -1;
  1781. }
  1782. for (i = 0; i < PlotGPC.MaxPens; i++) {
  1783. if (AvaiPenData[i].ColorIdx == 0xffff) {
  1784. DispError(3, "'%s' Pen #%ld undefined", szPenData, i + 1);
  1785. Result = -1;
  1786. }
  1787. }
  1788. }
  1789. if (PlotGPC.Flags & PLOTF_PAPERTRAY) {
  1790. if ((PlotGPC.PaperTraySize.cx < 0) ||
  1791. (PlotGPC.PaperTraySize.cy < 0)) {
  1792. DispError(3, "'%s' defined, but '%s' not defined",
  1793. szPaperTrayCap, szPaperTraySize);
  1794. Result = -1;
  1795. } else if ((PlotGPC.PaperTraySize.cx == 0) ||
  1796. (PlotGPC.PaperTraySize.cy == 0)) {
  1797. DispError(3, "'%s': Invalid Size (%ld x %ld), must have a size",
  1798. szPaperTraySize,
  1799. PlotGPC.PaperTraySize.cx,
  1800. PlotGPC.PaperTraySize.cy);
  1801. Result = -1;
  1802. } else if ((PlotGPC.PaperTraySize.cx != PlotGPC.DeviceSize.cx) &&
  1803. (PlotGPC.PaperTraySize.cy != PlotGPC.DeviceSize.cx)) {
  1804. DispError(3, "'%s': Invalid Size (%ld x %ld), one of width/height must eqaul device width (%ld)",
  1805. szPaperTraySize,
  1806. PlotGPC.PaperTraySize.cx,
  1807. PlotGPC.PaperTraySize.cy, PlotGPC.DeviceSize.cx);
  1808. Result = -1;
  1809. }
  1810. }
  1811. return(Result);
  1812. }
  1813. VOID
  1814. CopyPlotGPCToPCD(
  1815. PPLOTGPC_PCD pPlotGPC_PCD,
  1816. PPLOTGPC pPlotGPC
  1817. )
  1818. /*++
  1819. Routine Description:
  1820. This function copies a PLOTGPC structure into a PLOTGPC_GPC structure.
  1821. Arguments:
  1822. pPlotGPC_PCD - destination
  1823. pPlotGPC - source
  1824. Return Value:
  1825. None
  1826. Development History:
  1827. 1 Feb 2000
  1828. Revision History:
  1829. --*/
  1830. {
  1831. // All the datatypes upto InitString are the same in both the structures.
  1832. CopyMemory(pPlotGPC_PCD,
  1833. pPlotGPC,
  1834. (LPBYTE)&(pPlotGPC_PCD->InitString) - (LPBYTE)pPlotGPC_PCD);
  1835. // We need the size of PLOTGPC_PCD here, not the size of PLOTGPC
  1836. pPlotGPC_PCD->cjThis = sizeof(PLOTGPC_PCD);
  1837. pPlotGPC_PCD->InitString.Count = pPlotGPC->InitString.Count;
  1838. pPlotGPC_PCD->InitString.SizeEach = pPlotGPC->InitString.SizeEach;
  1839. if (pPlotGPC->InitString.pData) {
  1840. pPlotGPC_PCD->InitString.pData = (DWORD)(ULONG_PTR)(pPlotGPC->InitString.pData)
  1841. - (sizeof(PLOTGPC) - sizeof(PLOTGPC_PCD));
  1842. } else {
  1843. pPlotGPC_PCD->InitString.pData = 0;
  1844. }
  1845. pPlotGPC_PCD->Forms.Count = pPlotGPC->Forms.Count;
  1846. pPlotGPC_PCD->Forms.SizeEach = pPlotGPC->Forms.SizeEach;
  1847. if (pPlotGPC->Forms.pData) {
  1848. pPlotGPC_PCD->Forms.pData = (DWORD)(ULONG_PTR)(pPlotGPC->Forms.pData)
  1849. - (sizeof(PLOTGPC) - sizeof(PLOTGPC_PCD));
  1850. } else {
  1851. pPlotGPC_PCD->Forms.pData = 0;
  1852. }
  1853. pPlotGPC_PCD->Pens.Count = pPlotGPC->Pens.Count;
  1854. pPlotGPC_PCD->Pens.SizeEach = pPlotGPC->Pens.SizeEach;
  1855. if (pPlotGPC->Pens.pData) {
  1856. pPlotGPC_PCD->Pens.pData = (DWORD)(ULONG_PTR)(pPlotGPC->Pens.pData)
  1857. - (sizeof(PLOTGPC) - sizeof(PLOTGPC_PCD));
  1858. } else {
  1859. pPlotGPC_PCD->Pens.pData = 0;
  1860. }
  1861. }
  1862. VOID
  1863. WritePlotGPCToFile(
  1864. PPLOTGPC pPlotGPC
  1865. )
  1866. /*++
  1867. Routine Description:
  1868. This routine writes out pPlotGPC into a .pcd file. A FILE* pointer
  1869. to the file should be present in OutFile.
  1870. Arguments:
  1871. pPlotGPC - pointer to the PLOTGPC structure to be written. Some elements
  1872. maybe modified in *pPlotGPC in this function.
  1873. Return Value:
  1874. None
  1875. Development History:
  1876. 1 Feb 2000
  1877. Revision History:
  1878. --*/
  1879. {
  1880. PLOTGPC_PCD PlotGPC_PCD;
  1881. //
  1882. // make the references to offset
  1883. //
  1884. if (pPlotGPC->InitString.pData) {
  1885. (LPBYTE)pPlotGPC->InitString.pData -= (ULONG_PTR)pPlotGPC;
  1886. }
  1887. if (pPlotGPC->Forms.pData) {
  1888. (LPBYTE)pPlotGPC->Forms.pData -= (ULONG_PTR)pPlotGPC;
  1889. }
  1890. if (pPlotGPC->Pens.pData) {
  1891. (LPBYTE)pPlotGPC->Pens.pData -= (ULONG_PTR)pPlotGPC;
  1892. }
  1893. CopyPlotGPCToPCD(&PlotGPC_PCD, pPlotGPC);
  1894. if (OutFile) {
  1895. fwrite(&PlotGPC_PCD,
  1896. PlotGPC_PCD.cjThis,
  1897. 1,
  1898. OutFile);
  1899. fwrite((LPBYTE)pPlotGPC + pPlotGPC->cjThis,
  1900. PlotGPC.SizeExtra,
  1901. 1,
  1902. OutFile);
  1903. }
  1904. }
  1905. //
  1906. //***************************************************************************
  1907. // C main function entry point
  1908. //***************************************************************************
  1909. //
  1910. #define MAIN_SHOW_USAGE 0x0001
  1911. int __cdecl
  1912. main(
  1913. INT argc,
  1914. CHAR **argv
  1915. )
  1916. {
  1917. PPLOTGPC pPlotGPC = NULL;
  1918. INT RetVal = 1;
  1919. UINT Flags = 0;
  1920. UINT i;
  1921. LPSTR pOutFile = NULL;
  1922. PPLOTKEY pPK;
  1923. PPLOTVAL pPV;
  1924. memset(AvaiPenData, 0xff, sizeof(AvaiPenData));
  1925. pPV = PenColorVal;
  1926. MaxPCValLen = 0;
  1927. while (pPV->pValName) {
  1928. if ((i = (UINT)strlen(pPV->pValName)) > MaxPCValLen) {
  1929. MaxPCValLen = i;
  1930. }
  1931. ++pPV;
  1932. }
  1933. pPK = &PlotKey[0];
  1934. MaxKeywordLen = 0;
  1935. while (pPK->pKeyword) {
  1936. if ((pPK->KeywordLen = (WORD)strlen(pPK->pKeyword)) > MaxKeywordLen) {
  1937. MaxKeywordLen = pPK->KeywordLen;
  1938. }
  1939. ++pPK;
  1940. }
  1941. InFile = NULL;
  1942. OutFile = NULL;
  1943. if (argc > 1) {
  1944. for (--argc, ++argv; argc > 0; --argc, ++argv) {
  1945. if (**argv == '-' ) {
  1946. switch (*(*argv + 1)) {
  1947. case '?':
  1948. case 'h':
  1949. case 'H':
  1950. Flags |= MAIN_SHOW_USAGE;
  1951. RetVal = -1;
  1952. break;
  1953. }
  1954. } else if (InFile) {
  1955. if ((OutFile) && (OutFile != stdout)) {
  1956. DispError(0, "Unknown parameter '%s'", *argv);
  1957. Flags |= MAIN_SHOW_USAGE;
  1958. RetVal = 0;
  1959. } else if ((OutFile = fopen(pOutFile = *argv, "wb")) == NULL) {
  1960. DispError(0, "Cannot open output file '%s'\n", *argv);
  1961. RetVal = 0;
  1962. }
  1963. } else {
  1964. if (SUCCEEDED(StringCchCopyA(InFileName, CCHOF(InFileName), *argv)))
  1965. {
  1966. if ((InFile = fopen(*argv, "rt" )) == NULL) {
  1967. DispError(0, "Cannot open input file '%s'\n", *argv);
  1968. RetVal = -1;
  1969. }
  1970. }
  1971. else
  1972. {
  1973. DispError(0, "Wrong filename '%s'\n", *argv);
  1974. RetVal = -1;
  1975. }
  1976. }
  1977. }
  1978. } else {
  1979. Flags |= MAIN_SHOW_USAGE;
  1980. RetVal = -1;
  1981. }
  1982. if (Flags & MAIN_SHOW_USAGE) {
  1983. ShowUsage();
  1984. }
  1985. if ((RetVal >= 0) &&
  1986. (InFile)) {
  1987. RetVal = ParsePlotGPC();
  1988. }
  1989. if (RetVal >= 0) {
  1990. //
  1991. // if (InFile) {
  1992. //
  1993. // ShowUndefined();
  1994. // }
  1995. //
  1996. if (pPlotGPC = GetFullPlotGPC()) {
  1997. ValidatePlotGPC(pPlotGPC);
  1998. ShowPlotGPC(pPlotGPC);
  1999. WritePlotGPCToFile(pPlotGPC);
  2000. }
  2001. } else {
  2002. fprintf(stdout, "\n");
  2003. }
  2004. if (InFile) {
  2005. fclose(InFile);
  2006. }
  2007. if ((OutFile) && (OutFile != stdout)) {
  2008. fclose(OutFile);
  2009. }
  2010. #if (DBG && GPC_READ_TEST)
  2011. if (pOutFile) {
  2012. LPWSTR pwStr = NULL;
  2013. PPLOTGPC pReadPlotGPC;
  2014. UINT Idx = 0;
  2015. pwStr = str2MemWstr(pOutFile);
  2016. if (pReadPlotGPC = ReadPlotGPCFromFile(pwStr)) {
  2017. ShowPlotGPC(pReadPlotGPC);
  2018. //
  2019. // make the references to offset
  2020. //
  2021. if (pReadPlotGPC->InitString.pData) {
  2022. (LPBYTE)pReadPlotGPC->InitString.pData -= (DWORD)pReadPlotGPC;
  2023. }
  2024. if (pReadPlotGPC->Forms.pData) {
  2025. (LPBYTE)pReadPlotGPC->Forms.pData -= (DWORD)pReadPlotGPC;
  2026. }
  2027. if (pReadPlotGPC->Pens.pData) {
  2028. (LPBYTE)pReadPlotGPC->Pens.pData -= (DWORD)pReadPlotGPC;
  2029. }
  2030. if ((pPlotGPC->cjThis != pReadPlotGPC->cjThis) ||
  2031. (pPlotGPC->SizeExtra != pReadPlotGPC->SizeExtra)) {
  2032. DispError(-1, "Write / Read Size different");
  2033. } else {
  2034. UINT i;
  2035. LPBYTE pP1;
  2036. LPBYTE pP2;
  2037. pP1 = (LPBYTE)pPlotGPC;
  2038. pP2 = (LPBYTE)pReadPlotGPC;
  2039. Idx = pPlotGPC->cjThis + pPlotGPC->SizeExtra;
  2040. for (i = 0; i < Idx; i++) {
  2041. if (*pP1 != *pP2) {
  2042. fprintf(stdout, "\nOffset 0x%04x: Write = %02x, Read = %02x",
  2043. i, *pP1, *pP2);
  2044. }
  2045. ++pP1;
  2046. ++pP2;
  2047. }
  2048. }
  2049. LocalFree(pReadPlotGPC);
  2050. } else {
  2051. DispError(-1, "ReadPlotGPCFromFile(%s) failed", pOutFile);
  2052. }
  2053. if (pwStr) {
  2054. LocalFree(pwStr);
  2055. }
  2056. }
  2057. #endif
  2058. if (pPlotGPC) {
  2059. LocalFree((HLOCAL)pPlotGPC);
  2060. }
  2061. return(RetVal);
  2062. }