1 /* pstotxtd.c */
2 /* OS/2 and Win32 Command line interface to pstotxt[23].dll */
3 /* 8086 MS-DOS command line EXE. */
4 /* Russell Lang */
5
6 /* derived from main.c */
7 /* Copyright (C) 1995, Digital Equipment Corporation. */
8 /* All rights reserved. */
9 /* See the file pstotext.txt for a full description. */
10 /* Last modified on Fri Jan 9 21:11:00 AEST 2004 by rjl */
11 /* modified on Sat Mar 11 09:16:00 AEST 2000 by rjl */
12 /* modified on Fri Oct 16 16:30:54 PDT 1998 by mcjones */
13 /* modified on Thu Nov 16 13:33:13 PST 1995 by deutsch */
14
15 /* Modifications by rjl
16 * Fixed compiler warnings.
17 */
18
19 #ifndef MSDOS
20 #ifdef _Windows
21 #include <windows.h>
22 #include <io.h>
23 #ifndef __BORLANDC__
24 #define mktemp(t) _mktemp(t)
25 #endif
26 #else
27 #define INCL_DOS
28 #include <os2.h>
29 #endif
30 #endif
31
32 #include <signal.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36
37 #ifdef MSDOS
38 #include <io.h>
39 #include <ctype.h>
40 #include "bundle.h"
41 #include "ocr.h"
42 #include "rot270.h"
43 #include "rot90.h"
44 typedef int HMODULE;
45 #endif
46
47 #include "ptotdll.h"
48
49
50 #define BOOLEAN int
51 #define FALSE 0
52 #define TRUE 1
53
54 #define LINELEN 2000 /* longest allowable line from gs ocr.ps output */
55
56 /* resource IDs for pstotxt3.dll */
57 #define OCR_PROLOG 1
58 #define ROT270_PROLOG 2
59 #define ROT90_PROLOG 3
60
61 static int cleanup(void);
62 static void do_it(char *path);
63 #define strcasecmp stricmp
64 #define MAXPATHLEN 256
65 static int debug = FALSE;
66 static int cork = FALSE;
67 #ifdef MSDOS
68 static char *gscommand = "gs386.exe";
69 #else
70 #ifdef _Windows
71 static char *gscommand = "gswin32c.exe";
72 #else
73 static char *gscommand = "gsos2.exe";
74 #endif
75 #endif
76 static char *outfile = "";
77
78 static char *cmd; /* = argv[0] */
79
80 static enum {
81 portrait,
82 landscape,
83 landscapeOther} orientation = portrait;
84
85 static int bboxes = FALSE;
86
87 static int explicitFiles = 0; /* count of explicit file arguments */
88
usage(void)89 void usage(void) {
90 fprintf(stderr, "pstotext 1.8i of 2003-01-08\n");
91 fprintf(stderr, "Copyright (C) 1995-1998, Digital Equipment Corporation.\n");
92 fprintf(stderr, "Modified by Ghostgum Software Pty Ltd for Ghostscript 6.0.\n");
93 fprintf(stderr, "Comments to {mcjones,birrell}@pa.dec.com.\n\n");
94 fprintf(stderr, "Usage: %s [option|file]...\n", cmd);
95 fprintf(stderr, "Options:\n");
96 fprintf(stderr, " -cork Assume Cork encoding for dvips output\n");
97 fprintf(stderr, " -landscape rotate 270 degrees\n");
98 fprintf(stderr, " -landscapeOther rotate 90 degrees\n");
99 fprintf(stderr, " -portrait don't rotate (default)\n");
100 fprintf(stderr, " -bboxes output one word per line with bounding box\n");
101 fprintf(stderr, " -debug show Ghostscript output and error messages\n");
102 fprintf(stderr, " -gs \042command\042 Ghostscript command\n");
103 fprintf(stderr, " -output file output results to \042file\042 (default is stdout)\n");
104 fprintf(stderr, " - read from stdin (default if no files specified)\n");
105 }
106
107 #ifndef _Windows
108 #define WINAPI /* nothing for OS/2 or MSDOS */
109 #endif
110
111 typedef int (WINAPI *PFN_pstotextInit)(void **instance);
112 typedef int (WINAPI *PFN_pstotextFilter)(void *instance, char *instr,
113 char **pre, char **word, char **post,
114 int *llx, int *lly, int *urx, int *ury);
115 typedef int (WINAPI *PFN_pstotextExit)(void *instance);
116 typedef int (WINAPI *PFN_pstotextSetCork)(void *instance, int value);
117 HMODULE pstotextModule;
118 void *pstotextInstance;
119 PFN_pstotextInit dllfn_pstotextInit;
120 PFN_pstotextFilter dllfn_pstotextFilter;
121 PFN_pstotextExit dllfn_pstotextExit;
122 PFN_pstotextSetCork dllfn_pstotextSetCork;
123
124 #ifdef _Windows
125 int
load_pstotext(void)126 load_pstotext(void)
127 {
128 char dllname[256];
129 char *p;
130 /* get path to EXE */
131 GetModuleFileName(0, dllname, sizeof(dllname));
132 if ((p = strrchr(dllname,'\\')) != (char *)NULL)
133 p++;
134 else
135 p = dllname;
136 *p = '\0';
137 #ifdef __WIN32__
138 #ifdef DECALPHA
139 strcat(dllname, "pstotxta.dll");
140 #else
141 strcat(dllname, "pstotxt3.dll");
142 #endif
143 #else
144 strcat(dllname, "pstotxt1.dll");
145 #endif
146 if (debug) {
147 fputs(dllname, stdout);
148 fputc('\n', stdout);
149 }
150
151
152 /* load pstotext DLL */
153 pstotextModule = LoadLibrary(dllname);
154 if (pstotextModule < (HINSTANCE)HINSTANCE_ERROR) {
155 fprintf(stderr, "Can't load %s\n", dllname);
156 return 1;
157 }
158 dllfn_pstotextInit = (PFN_pstotextInit) GetProcAddress(pstotextModule, "pstotextInit");
159 if (dllfn_pstotextInit == (PFN_pstotextInit)NULL) {
160 fprintf(stderr, "Can't find pstotextInit() in %s\n", dllname);
161 FreeLibrary(pstotextModule);
162 return 1;
163 }
164 dllfn_pstotextFilter = (PFN_pstotextFilter) GetProcAddress(pstotextModule, "pstotextFilter");
165 if (dllfn_pstotextFilter == (PFN_pstotextFilter)NULL) {
166 fprintf(stderr, "Can't find pstotextFilter() in %s\n", dllname);
167 FreeLibrary(pstotextModule);
168 return 1;
169 }
170 dllfn_pstotextExit = (PFN_pstotextExit) GetProcAddress(pstotextModule, "pstotextExit");
171 if (dllfn_pstotextExit == (PFN_pstotextExit)NULL) {
172 fprintf(stderr, "Can't find pstotextExit() in %s\n", dllname);
173 FreeLibrary(pstotextModule);
174 return 1;
175 }
176 dllfn_pstotextSetCork = (PFN_pstotextSetCork) GetProcAddress(pstotextModule, "pstotextSetCork");
177 if (dllfn_pstotextSetCork == (PFN_pstotextSetCork)NULL) {
178 fprintf(stderr, "Can't find pstotextSetCork() in %s\n", dllname);
179 FreeLibrary(pstotextModule);
180 return 1;
181 }
182
183 dllfn_pstotextInit(&pstotextInstance);
184
185 return 0;
186 }
187
188 int
unload_pstotext(void)189 unload_pstotext(void)
190 {
191 if (pstotextInstance)
192 dllfn_pstotextExit(pstotextInstance);
193 pstotextInstance = NULL;
194 FreeLibrary(pstotextModule);
195 pstotextModule = NULL;
196 return 0;
197 }
198
199 void
send_prolog(FILE * f,int resource)200 send_prolog(FILE *f, int resource)
201 {
202 HGLOBAL hglobal;
203 LPSTR prolog;
204 hglobal = LoadResource(pstotextModule,
205 FindResource(pstotextModule, (LPSTR)resource, RT_RCDATA));
206 if ( (prolog = (LPSTR)LockResource(hglobal)) != (LPSTR)NULL) {
207 fputs(prolog, f);
208 FreeResource(hglobal);
209 }
210 }
211
212 #else /* !_Windows */
213 #ifdef MSDOS
214 int
load_pstotext(void)215 load_pstotext(void)
216 {
217 dllfn_pstotextInit = pstotextInit;
218 dllfn_pstotextFilter = pstotextFilter;
219 dllfn_pstotextExit = pstotextExit;
220 dllfn_pstotextSetCork = pstotextSetCork;
221 dllfn_pstotextInit(&pstotextInstance);
222 return 0;
223 }
224
225 int
unload_pstotext(void)226 unload_pstotext(void)
227 {
228 return 0;
229 }
230
231 void
send_prolog(FILE * f,int resource)232 send_prolog(FILE *f, int resource)
233 {
234 switch (resource) {
235 case OCR_PROLOG:
236 putbundle(ocr, f);
237 break;
238 case ROT270_PROLOG:
239 putbundle(rot270, f);
240 break;
241 case ROT90_PROLOG:
242 putbundle(rot90, f);
243 break;
244 }
245 }
246
247 #else /* !_Windows && !MSDOS */
248 /* OS/2 */
249 int
load_pstotext(void)250 load_pstotext(void)
251 {
252 char dllname[256];
253 char buf[256];
254 char *p;
255 APIRET rc;
256 PTIB pptib;
257 PPIB pppib;
258
259 if ( (rc = DosGetInfoBlocks(&pptib, &pppib)) != 0 ) {
260 fprintf(stderr,"Couldn't get pid, rc = \n", rc);
261 return rc;
262 }
263
264 /* get path to EXE */
265 if ( (rc = DosQueryModuleName(pppib->pib_hmte, sizeof(dllname), dllname)) != 0 ) {
266 fprintf(stderr,"Couldn't get module name, rc = %d\n", rc);
267 return rc;
268 }
269 if ((p = strrchr(dllname,'\\')) != (PCHAR)NULL) {
270 p++;
271 *p = '\0';
272 }
273 strcat(dllname, "pstotxt2.dll");
274 if (debug) {
275 fputs(dllname, stdout);
276 fputc('\n', stdout);
277 }
278
279 /* load pstotext DLL */
280 if (DosLoadModule(buf, sizeof(buf), dllname, &pstotextModule)) {
281 fprintf(stderr, "Can't load %s\n", dllname);
282 return 1;
283 }
284 if ((rc = DosQueryProcAddr(pstotextModule, 0, "pstotextInit", (PFN *)(&dllfn_pstotextInit))) !=0) {
285 fprintf(stderr, "Can't find pstotextInit() in %s\n", dllname);
286 DosFreeModule(pstotextModule);
287 pstotextModule = (HMODULE)NULL;
288 return 1;
289 }
290 if ((rc = DosQueryProcAddr(pstotextModule, 0, "pstotextFilter", (PFN *)(&dllfn_pstotextFilter))) !=0) {
291 fprintf(stderr, "Can't find pstotextFilter() in %s\n", dllname);
292 DosFreeModule(pstotextModule);
293 pstotextModule = (HMODULE)NULL;
294 return 1;
295 }
296 if ((rc = DosQueryProcAddr(pstotextModule, 0, "pstotextExit", (PFN *)(&dllfn_pstotextExit))) !=0) {
297 fprintf(stderr, "Can't find pstotextExit() in %s\n", dllname);
298 DosFreeModule(pstotextModule);
299 pstotextModule = (HMODULE)NULL;
300 return 1;
301 }
302 if ((rc = DosQueryProcAddr(pstotextModule, 0, "pstotextSetCork", (PFN *)(&dllfn_pstotextSetCork))) !=0) {
303 fprintf(stderr, "Can't find pstotextSetCork() in %s\n", dllname);
304 DosFreeModule(pstotextModule);
305 pstotextModule = (HMODULE)NULL;
306 return 1;
307 }
308
309 dllfn_pstotextInit(&pstotextInstance);
310
311 return 0;
312 }
313
314 int
unload_pstotext(void)315 unload_pstotext(void)
316 {
317 if (pstotextInstance)
318 dllfn_pstotextExit(pstotextInstance);
319 pstotextInstance = NULL;
320 if (pstotextModule)
321 DosFreeModule(pstotextModule);
322 pstotextModule = (HMODULE)NULL;
323 return 0;
324 }
325
326
327 int
send_prolog(FILE * f,int resource)328 send_prolog(FILE *f, int resource)
329 {
330 char *prolog, *p;
331 APIRET rc;
332 int code = -1;
333 rc = DosGetResource(pstotextModule, RT_RCDATA, resource, (PPVOID)&prolog);
334 if (!rc && (prolog != (char *)NULL) ) {
335 code = 0;
336 p = prolog;
337 while (*p) {
338 if (!code)
339 fputs(p, f);
340 p += strlen(p)+1;
341 }
342 DosFreeResource(prolog);
343 }
344 else {
345 fprintf(stderr, "Failed to load pstotext resource %d\n", resource);
346 }
347 return code;
348 }
349 #endif /* OS/2 (!MSDOS) */
350 #endif /* (!_Windows) */
351
352 /* create an empty temporary file and return its name */
scratch_file(void)353 static char *scratch_file(void) {
354 FILE *f;
355 char *temp;
356 char *path = malloc(256);
357 if (path == NULL)
358 return NULL;
359 if ( (temp = getenv("TEMP")) != NULL )
360 strcpy(path, temp);
361 else if ( (temp = getenv("TMP")) != NULL )
362 strcpy(path, temp);
363 else
364 strcpy(path, "c:\\");
365
366 /* Prevent X's in path from being converted by mktemp. */
367 for ( temp = path; *temp; temp++ ) {
368 *temp = (char)tolower(*temp);
369 if (*temp == '/')
370 *temp = '\\';
371 }
372 if ( strlen(path) && (path[strlen(path)-1] != '\\') )
373 strcat(path, "\\");
374
375 strcat(path, "ptXXXXXX");
376 mktemp(path);
377 f = fopen(path, "w");
378 if (f==NULL) {perror(cmd); exit(1);}
379 fclose(f);
380 return path;
381 }
382
make_temp(int resource)383 static char *make_temp(int resource) {
384 /* Return pathname of temporary file containing prolog from resources. Caller
385 should unlink file (and, technically, free pathname). */
386 FILE *f;
387 char *path = scratch_file();
388 if (path == NULL) {perror(cmd); cleanup(); exit(1);}
389
390 f = fopen(path, "w");
391 if (f==NULL) {perror(cmd); cleanup(); exit(1);}
392
393 send_prolog(f, resource);
394 fclose(f);
395 return path;
396 }
397
398
399 static char *ocr_path = NULL, *rotate_path = NULL;
400 static FILE *gs = NULL;
401 char *gstemp = NULL;
402 static void *instance; /* pstotext state */
403
cleanup(void)404 static int cleanup(void) {
405 int status = 0;
406 unload_pstotext();
407 if (gs!=NULL) {
408 #if defined(_Windows) || defined(MSDOS)
409 fclose(gs);
410 #else
411 pclose(gs);
412 #endif
413 }
414 if (gstemp!=NULL && !debug)
415 unlink(gstemp);
416 if (rotate_path!=NULL && strcmp(rotate_path, "")!=0 && !debug)
417 unlink(rotate_path);
418 if (ocr_path!=NULL && !debug)
419 unlink(ocr_path);
420 return status;
421 }
422
handler(int code)423 static void handler(int code) {
424 int status = code; /* suppress unreference 'code' warning */
425 status = cleanup();
426 if (status!=0)
427 exit(status);
428 exit(2);
429 }
430
do_it(char * path)431 static void do_it(char *path) {
432 /* If "path" is NULL, then "stdin" should be processed. */
433 char gs_cmd[2*MAXPATHLEN];
434 char input[MAXPATHLEN];
435 int status;
436 FILE *fileout;
437 #ifdef MSDOS
438 char *gsargtemp;
439 FILE *gsargfile;
440 #endif
441
442 fileout = stdout;
443 if (strlen(outfile) != 0) {
444 fileout = fopen(outfile, "w");
445 if (fileout == NULL) {perror(cmd); exit(1);}
446 }
447
448 signal(SIGINT, handler);
449 signal(SIGTERM, handler);
450
451 status = load_pstotext();
452 if (status!=0) {
453 fprintf(stderr, "%s: internal error %d\n", cmd, status);
454 exit(5);
455 }
456
457 if (cork) {
458 status = dllfn_pstotextSetCork(pstotextInstance, TRUE);
459 if (status!=0) {
460 fprintf(stderr, "%s: internal error %d\n", cmd, status);
461 exit(5);
462 }
463 }
464
465 ocr_path = make_temp(OCR_PROLOG);
466
467 switch (orientation) {
468 case portrait: rotate_path = ""; break;
469 case landscape: rotate_path = make_temp(ROT270_PROLOG); break;
470 case landscapeOther: rotate_path = make_temp(ROT90_PROLOG); break;
471 }
472
473 if (path==NULL) strcpy(input, "-");
474 else {strcpy(input, "-- "); strcat(input, path);}
475
476 #if defined(_Windows) || defined(MSDOS)
477 /* don't support pipes, so write gs output to a temporary file */
478 if ( (gstemp = scratch_file()) == NULL) {
479 cleanup();
480 exit(1);
481 }
482 #endif
483
484 #ifdef MSDOS
485 /* MSDOS has command line length problems */
486 if ( (gsargtemp = scratch_file()) == NULL) {
487 cleanup();
488 exit(1);
489 }
490 if ( (gsargfile = fopen(gsargtemp, "w")) == (FILE *)NULL) {
491 cleanup();
492 exit(1);
493 }
494 fprintf(gsargfile, "-r72 -dNODISPLAY -dFIXEDMEDIA -dDELAYBIND -dWRITESYSTEMDICT %s -dNOPAUSE\n",
495 (debug ? "" : "-q"));
496 fputs(rotate_path, gsargfile);
497 fputs("\n", gsargfile);
498 fputs(ocr_path, gsargfile);
499 fputs("\n", gsargfile);
500 fputs(input, gsargfile);
501 fputs("\n", gsargfile);
502 fclose(gsargfile);
503
504 sprintf(gs_cmd, "%s @%s %s %s", gscommand, gsargtemp,
505 #if defined(_Windows) || defined(MSDOS)
506 "> ", gstemp
507 #else
508 "", ""
509 #endif
510 );
511
512 #else /* !MSDOS */
513 sprintf(gs_cmd, "%s -r72 -dNODISPLAY -dFIXEDMEDIA -dDELAYBIND -dWRITESYSTEMDICT %s -dNOPAUSE %s %s %s %s %s",
514 gscommand,
515 (debug ? "" : "-q"),
516 ocr_path,
517 rotate_path,
518 input,
519 #if defined(_Windows) || defined(MSDOS)
520 "> ", gstemp
521 #else
522 "", ""
523 #endif
524 );
525 #endif
526
527 if (debug) {
528 fputs(gs_cmd, stdout);
529 fputc('\n', stdout);
530 }
531
532 #if defined(_Windows) || defined(MSDOS)
533 if (system(gs_cmd)) {
534 fprintf(stderr,"\nCan't run (errno=%d):\n %s\n", errno, gs_cmd);
535 cleanup();
536 exit(1);
537 }
538
539 gs = fopen(gstemp, "r");
540 #else
541 gs = popen(gs_cmd, "r");
542 #endif
543
544 #ifdef MSDOS
545 if (!debug)
546 unlink(gsargtemp);
547 free(gsargtemp);
548 #endif
549
550 if( gs==NULL ) {perror(cmd); cleanup(); exit(1);}
551
552 while (gs != NULL) { /* while TRUE */
553 char line[LINELEN];
554 char *pre, *word, *post;
555 int llx, lly, urx, ury;
556 if (fgets(line, LINELEN, gs)==NULL) break;
557 if (debug)
558 fputs(line, stdout);
559 status = dllfn_pstotextFilter(
560 pstotextInstance, line, &pre, &word, &post, &llx, &lly, &urx, &ury);
561 if (status!=0) {
562 fprintf(stderr, "%s: internal error %d\n", cmd, status);
563 cleanup();
564 exit(5);
565 }
566 if (word!=NULL)
567 if (!bboxes) {
568 fputs(pre, fileout); fputs(word, fileout); fputs(post, fileout);
569 if (debug)
570 fputc('\n', stdout);
571 }
572 else {
573 if (pre) {
574 if (*pre == ' ')
575 pre++;
576 fputs(pre, fileout);
577 }
578 fprintf(fileout, "%6d\t%6d\t%6d\t%6d\t%s\n", llx, lly, urx, ury, word);
579 if (post)
580 fputs(post, fileout);
581 }
582 }
583 if (fileout != stdout) fclose(fileout);
584 status = cleanup();
585 if (status!=0) exit(status);
586 }
587
main(int argc,char * argv[])588 int main(int argc, char *argv[]) {
589 int i;
590 char *arg;
591 cmd = argv[0];
592 for (i = 1; i<argc; i++) {
593 arg = argv[i];
594 if (strcasecmp(arg, "-landscape")==0) orientation = landscape;
595 else if (strcasecmp(arg, "-cork")==0) cork = TRUE;
596 else if (strcasecmp(arg, "-landscapeOther")==0) orientation = landscapeOther;
597 else if (strcasecmp(arg, "-portrait")==0) orientation = portrait;
598 else if (strcasecmp(arg, "-bboxes")==0) bboxes = TRUE;
599 else if (strcasecmp(arg, "-debug")==0) debug = TRUE;
600 else if (strcasecmp(arg, "-gs")==0) {
601 i++;
602 if (i<argc)
603 gscommand = argv[i];
604 }
605 else if (strcasecmp(arg, "-output") == 0) {
606 i++;
607 if (i>=argc) {usage(); exit(1);}
608 outfile = argv[i];
609 }
610 else if (strcmp(arg, "-")==0) do_it(NULL);
611 else if (arg[0] == '-') {usage(); exit(1);}
612 else /* file */ {
613 explicitFiles++;
614 do_it(arg);
615 }
616 }
617 if (explicitFiles==0) do_it(NULL);
618 return 0;
619 }
620