gp_macio.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. /* Copyright (C) 1989 - 1995, 1997 Aladdin Enterprises. All rights reserved.
  2. This file is part of Aladdin Ghostscript.
  3. Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author
  4. or distributor accepts any responsibility for the consequences of using it,
  5. or for whether it serves any particular purpose or works at all, unless he
  6. or she says so in writing. Refer to the Aladdin Ghostscript Free Public
  7. License (the "License") for full details.
  8. Every copy of Aladdin Ghostscript must include a copy of the License,
  9. normally in a plain ASCII text file named PUBLIC. The License grants you
  10. the right to copy, modify and redistribute Aladdin Ghostscript, but only
  11. under certain conditions described in the License. Among other things, the
  12. License requires that the copyright notice and this notice be preserved on
  13. all copies.
  14. */
  15. /* $Id: gp_macio.c,v 1.2.4.1 2002/01/25 06:33:09 rayjj Exp $ */
  16. //#include "MacHeaders"
  17. #include <Palettes.h>
  18. #include <Aliases.h>
  19. #include <Quickdraw.h>
  20. #include <QDOffscreen.h>
  21. #include <AppleEvents.h>
  22. #include <Fonts.h>
  23. #include <Controls.h>
  24. #include <Script.h>
  25. #include <Timer.h>
  26. #include <Folders.h>
  27. #include <Resources.h>
  28. #include <Sound.h>
  29. #include <ToolUtils.h>
  30. #include <Menus.h>
  31. #include <LowMem.h>
  32. #include <Devices.h>
  33. #include <Scrap.h>
  34. #include <StringCompare.h>
  35. #include <Gestalt.h>
  36. #include <Folders.h>
  37. #include <Fonts.h>
  38. #include <FixMath.h>
  39. #include <Resources.h>
  40. #include "math_.h"
  41. #include <string.h>
  42. #include <stdlib.h>
  43. //#include <stdio.h>
  44. //#include <cstdio.h>
  45. #include "sys/stat.h"
  46. #include "stdio_.h"
  47. #include <stdlib.h>
  48. #include "gx.h"
  49. #include "gp.h"
  50. #include "gxdevice.h"
  51. #include <stdarg.h>
  52. #include <console.h>
  53. #include "gp_mac.h"
  54. #include "stream.h"
  55. #include "gxiodev.h" /* must come after stream.h */
  56. //#include "gp_macAE.h"
  57. #include "gsdll.h"
  58. //HWND hwndtext;
  59. extern void
  60. convertSpecToPath(FSSpec * s, char * p, int pLen)
  61. {
  62. OSStatus err = noErr;
  63. DirInfo block;
  64. Str255 dirName;
  65. int totLen = 0, dirLen = 0;
  66. memcpy(p, s->name + 1, s->name[0]);
  67. totLen += s->name[0];
  68. block.ioNamePtr = dirName;
  69. block.ioVRefNum = s->vRefNum;
  70. block.ioDrParID = s->parID;
  71. block.ioFDirIndex = -1;
  72. do {
  73. block.ioDrDirID = block.ioDrParID;
  74. err = PBGetCatInfoSync((CInfoPBPtr)&block);
  75. if ((err != noErr) || (totLen + dirName[0] + 2 > pLen)) {
  76. p[0] = 0;
  77. return;
  78. }
  79. dirName[++dirName[0]] = ':';
  80. memmove(p + dirName[0], p, totLen);
  81. memcpy(p, dirName + 1, dirName[0]);
  82. totLen += dirName[0];
  83. } while (block.ioDrParID != fsRtParID);
  84. p[totLen] = 0;
  85. return;
  86. }
  87. /* ------ File name syntax ------ */
  88. /* Define the character used for separating file names in a list. */
  89. const char gp_file_name_list_separator = ',';
  90. /* Define the default scratch file name prefix. */
  91. const char gp_scratch_file_name_prefix[] = "tempgs_";
  92. /* Define the name of the null output file. */
  93. const char gp_null_file_name[] = "????";
  94. /* Define the name that designates the current directory. */
  95. extern const char gp_current_directory_name[] = ":";
  96. int fake_stdin = 0;
  97. /* Do platform-dependent initialization */
  98. void
  99. setenv(const char * env, char *p) {
  100. // if ( strcmp(env,"outfile") == 0) {
  101. // sprintf((char *)&g_fcout[0],"%s",p);
  102. // }
  103. }
  104. char *
  105. getenv(const char * env) {
  106. char *p;
  107. FSSpec pFile;
  108. OSErr err = 0;
  109. char fpath[256]="";
  110. if ( strcmp(env,"GS_LIB") == 0) {
  111. pFile.name[0] = 0;
  112. err = FindFolder(kOnSystemDisk, kApplicationSupportFolderType, kDontCreateFolder,
  113. &pFile.vRefNum, &pFile.parID);
  114. if (err != noErr) goto failed;
  115. // FSMakeFSSpec(pFile.vRefNum, pFile.parID,thepfname, &pfile);
  116. convertSpecToPath(&pFile, fpath, 256);
  117. // sprintf(fpath,"%s",fpath);
  118. p = (char*)gs_malloc(1, (size_t) ( 4*strlen(fpath) + 40), "getenv");
  119. sprintf(p,"%s,%sGhostscript:lib,%sGhostscript:fonts",
  120. (char *)&fpath[0],(char *)&fpath[0],
  121. (char *)&fpath[0] );
  122. return p;
  123. failed:
  124. return NULL;
  125. } else
  126. return NULL;
  127. }
  128. /* ====== Substitute for stdio ====== */
  129. /* Forward references */
  130. private void mac_std_init(void);
  131. private stream_proc_process(mac_stdin_read_process);
  132. private stream_proc_process(mac_stdout_write_process);
  133. private stream_proc_process(mac_stderr_write_process);
  134. private stream_proc_available(mac_std_available);
  135. /* Use a pseudo IODevice to get mac_stdio_init called at the right time. */
  136. /* This is bad architecture; we'll fix it later. */
  137. private iodev_proc_init(mac_stdio_init);
  138. const gx_io_device gs_iodev_macstdio =
  139. {
  140. "macstdio", "Special",
  141. {mac_stdio_init, iodev_no_open_device,
  142. iodev_no_open_file, iodev_no_fopen, iodev_no_fclose,
  143. iodev_no_delete_file, iodev_no_rename_file,
  144. iodev_no_file_status, iodev_no_enumerate_files
  145. }
  146. };
  147. /* Do one-time initialization */
  148. private int
  149. mac_stdio_init(gx_io_device * iodev, gs_memory_t * mem)
  150. {
  151. mac_std_init(); /* redefine stdin/out/err to our window routines */
  152. return 0;
  153. }
  154. /* Define alternate 'open' routines for our stdin/out/err streams. */
  155. extern const gx_io_device gs_iodev_stdin;
  156. private int
  157. mac_stdin_open(gx_io_device * iodev, const char *access, stream ** ps,
  158. gs_memory_t * mem)
  159. {
  160. int code = gs_iodev_stdin.procs.open_device(iodev, access, ps, mem);
  161. stream *s = *ps;
  162. if (code != 1)
  163. return code;
  164. s->procs.process = mac_stdin_read_process;
  165. s->procs.available = mac_std_available;
  166. s->file = NULL;
  167. return 0;
  168. }
  169. extern const gx_io_device gs_iodev_stdout;
  170. private int
  171. mac_stdout_open(gx_io_device * iodev, const char *access, stream ** ps,
  172. gs_memory_t * mem)
  173. {
  174. int code = gs_iodev_stdout.procs.open_device(iodev, access, ps, mem);
  175. stream *s = *ps;
  176. if (code != 1)
  177. return code;
  178. s->procs.process = mac_stdout_write_process;
  179. s->procs.available = mac_std_available;
  180. s->file = NULL;
  181. return 0;
  182. }
  183. extern const gx_io_device gs_iodev_stderr;
  184. private int
  185. mac_stderr_open(gx_io_device * iodev, const char *access, stream ** ps,
  186. gs_memory_t * mem)
  187. {
  188. int code = gs_iodev_stderr.procs.open_device(iodev, access, ps, mem);
  189. stream *s = *ps;
  190. if (code != 1)
  191. return code;
  192. s->procs.process = mac_stderr_write_process;
  193. s->procs.available = mac_std_available;
  194. s->file = NULL;
  195. return 0;
  196. }
  197. /* Patch stdin/out/err to use our windows. */
  198. private void
  199. mac_std_init(void)
  200. {
  201. /* If stdxxx is the console, replace the 'open' routines, */
  202. /* which haven't gotten called yet. */
  203. // if (gp_file_is_console(gs_stdin))
  204. gs_findiodevice((const byte *)"%stdin", 6)->procs.open_device =
  205. mac_stdin_open;
  206. // if (gp_file_is_console(gs_stdout))
  207. gs_findiodevice((const byte *)"%stdout", 7)->procs.open_device =
  208. mac_stdout_open;
  209. // if (gp_file_is_console(gs_stderr))
  210. gs_findiodevice((const byte *)"%stderr", 7)->procs.open_device =
  211. mac_stderr_open;
  212. }
  213. private int
  214. mac_stdin_read_process(stream_state *st, stream_cursor_read *ignore_pr,
  215. stream_cursor_write *pw, bool last)
  216. {
  217. uint count;
  218. /* callback to get more input */
  219. count = (*pgsdll_callback) (GSDLL_STDIN, (char*)pw->ptr + 1, count);
  220. pw->ptr += count;
  221. return 1;
  222. }
  223. private int
  224. mac_stdout_write_process(stream_state *st, stream_cursor_read *pr,
  225. stream_cursor_write *ignore_pw, bool last)
  226. { uint count = pr->limit - pr->ptr;
  227. (*pgsdll_callback) (GSDLL_STDOUT, (char *)(pr->ptr + 1), count);
  228. pr->ptr = pr->limit;
  229. return 0;
  230. }
  231. private int
  232. mac_stderr_write_process(stream_state *st, stream_cursor_read *pr,
  233. stream_cursor_write *ignore_pw, bool last)
  234. { uint count = pr->limit - pr->ptr;
  235. (*pgsdll_callback) (GSDLL_STDOUT, (char *)(pr->ptr + 1), count);
  236. pr->ptr = pr->limit;
  237. return 0;
  238. }
  239. private int
  240. mac_std_available(register stream * s, long *pl)
  241. {
  242. *pl = -1; // EOF, since we can't do it
  243. return 0; // OK
  244. }
  245. /* ====== Substitute for stdio ====== */
  246. /* These are used instead of the stdio version. */
  247. /* The declarations must be identical to that in <stdio.h>. */
  248. int
  249. fprintf(FILE *file, const char *fmt, ...)
  250. {
  251. int count;
  252. va_list args;
  253. char buf[1024];
  254. int i;
  255. va_start(args,fmt);
  256. if (file != stdout && file != stderr) {
  257. count = vfprintf(file, fmt, args);
  258. }
  259. else {
  260. count = vsprintf(buf, fmt, args);
  261. return fwrite(buf, strlen(buf), 1, file);
  262. }
  263. va_end(args);
  264. return count;
  265. }
  266. int
  267. fputs(const char *string, FILE *file)
  268. {
  269. int i,count;
  270. char buf[1024];
  271. if (file != stdout && file != stderr) {
  272. return fwrite(string, strlen(string), 1, file);
  273. }
  274. else {
  275. return fwrite(string, strlen(string), 1, file);
  276. }
  277. }
  278. /* ------ Printer accessing ------ */
  279. /* These should NEVER be called. */
  280. /* Open a connection to a printer. A null file name means use the */
  281. /* standard printer connected to the machine, if any. */
  282. /* "|command" opens an output pipe. */
  283. /* Return NULL if the connection could not be opened. */
  284. FILE *
  285. gp_open_printer (char *fname, int binary_mode)
  286. {
  287. if (strlen(fname) == 1 && fname[0] == '-')
  288. return stdout;
  289. else if (strlen(fname) == 0)
  290. return gp_open_scratch_file(gp_scratch_file_name_prefix, fname, binary_mode ? "wb" : "w");
  291. else
  292. return gp_fopen(fname, binary_mode ? "wb" : "b");
  293. }
  294. /* Close the connection to the printer. */
  295. void
  296. gp_close_printer (FILE *pfile, const char *fname)
  297. {
  298. fclose(pfile);
  299. }
  300. /* Define whether case is insignificant in file names. */
  301. /* OBSOLETE
  302. const int gp_file_names_ignore_case = 1;
  303. */
  304. /* Define the string to be concatenated with the file mode */
  305. /* for opening files without end-of-line conversion. */
  306. const char gp_fmode_binary_suffix[] = "b";
  307. /* Define the file modes for binary reading or writing. */
  308. const char gp_fmode_rb[] = "rb";
  309. const char gp_fmode_wb[] = "wb";
  310. /* Set a file into binary or text mode. */
  311. int
  312. gp_setmode_binary(FILE *pfile, bool binary)
  313. { return 0; /* Noop under VMS */
  314. }
  315. /* Create and open a scratch file with a given name prefix. */
  316. /* Write the actual file name at fname. */
  317. FILE *
  318. gp_open_scratch_file (const char *prefix, char *fname, const char *mode)
  319. {
  320. char thefname[256];
  321. Str255 thepfname;
  322. OSErr myErr;
  323. short foundVRefNum;
  324. long foundDirID;
  325. FSSpec fSpec;
  326. strcpy (fname, (char *) prefix);
  327. {
  328. char newName[50];
  329. tmpnam (newName);
  330. strcat (fname, newName);
  331. }
  332. if ( strrchr(fname,':') == NULL ) {
  333. memcpy((char*)&thepfname[1],(char *)&fname[0],strlen(fname));
  334. thepfname[0]=strlen(fname);
  335. myErr = FindFolder(kOnSystemDisk,kTemporaryFolderType,kCreateFolder,
  336. &foundVRefNum, &foundDirID);
  337. if ( myErr != noErr ) {
  338. fprintf(stderr,"Can't find temp folder.\n");
  339. return;
  340. }
  341. FSMakeFSSpec(foundVRefNum, foundDirID,thepfname, &fSpec);
  342. convertSpecToPath(&fSpec, thefname, sizeof(thefname) - 1);
  343. sprintf(fname,"%s",thefname);
  344. } else {
  345. sprintf((char*)&thefname[0],"%s\0",fname);
  346. memcpy((char*)&thepfname[1],(char *)&thefname[0],strlen(thefname));
  347. thepfname[0]=strlen(thefname);
  348. }
  349. return gp_fopen (thefname, mode);
  350. }
  351. /*
  352. {
  353. char thefname[256];
  354. strcpy (fname, (char *) prefix);
  355. {
  356. char newName[50];
  357. tmpnam (newName);
  358. strcat (fname, newName);
  359. }
  360. if ( strrchr(fname,':') == NULL )
  361. // sprintf((char *)&thefname[0],"%s%s\0",g_homeDir,fname);
  362. sprintf((char *)&thefname[0],"%s%s\0","",fname);
  363. else
  364. sprintf((char*)&thefname[0],"%s\0",fname);
  365. return gp_fopen (thefname, mode);
  366. }
  367. */
  368. /* Answer whether a file name contains a directory/device specification, */
  369. /* i.e. is absolute (not directory- or device-relative). */
  370. int
  371. gp_file_name_is_absolute (const char *fname, register uint len)
  372. {
  373. if (len /* > 0 */)
  374. {
  375. if (*fname == ':')
  376. {
  377. return 0;
  378. }
  379. else
  380. {
  381. register char *p;
  382. register char lastWasColon;
  383. register char sawColon;
  384. for (len, p = (char *) fname, lastWasColon = 0, sawColon = 0;
  385. len /* > 0 */;
  386. len--, p++)
  387. {
  388. if (*p == ':')
  389. {
  390. sawColon = 1;
  391. if (lastWasColon /* != 0 */)
  392. {
  393. return 0;
  394. }
  395. else
  396. {
  397. lastWasColon = 1;
  398. }
  399. }
  400. else
  401. {
  402. lastWasColon = 0;
  403. }
  404. }
  405. return sawColon;
  406. }
  407. }
  408. else
  409. {
  410. return 0;
  411. }
  412. }
  413. /* Answer whether the file_name references the directory */
  414. /* containing the specified path (parent). */
  415. bool
  416. gp_file_name_references_parent(const char *fname, unsigned len)
  417. {
  418. int i = 0, last_sep_pos = -1;
  419. /* A file name references its parent directory if it starts */
  420. /* with ..: or :: or if one of these strings follows : */
  421. while (i < len) {
  422. if (fname[i] == ':') {
  423. if (last_sep_pos == i - 1)
  424. return true; /* also returns true is starts with ':' */
  425. last_sep_pos = i++;
  426. continue;
  427. }
  428. if (fname[i++] != '.')
  429. continue;
  430. if (i > last_sep_pos + 2 || (i < len && fname[i] != '.'))
  431. continue;
  432. i++;
  433. /* have separator followed by .. */
  434. if (i < len && (fname[i] == ':'))
  435. return true;
  436. }
  437. return false;
  438. }
  439. /* Answer the string to be used for combining a directory/device prefix */
  440. /* with a base file name. The prefix directory/device is examined to */
  441. /* determine if a separator is needed and may return an empty string */
  442. const char *
  443. gp_file_name_concat_string (const char *prefix, uint plen)
  444. {
  445. if ( plen > 0 && prefix[plen - 1] == ':' )
  446. return "";
  447. return ":";
  448. }
  449. /* ------ File enumeration ------ */
  450. /****** THIS IS NOT SUPPORTED ON MACINTOSH SYSTEMS. ******/
  451. struct file_enum_s {
  452. char *pattern;
  453. int first_time;
  454. gs_memory_t *memory;
  455. };
  456. /* Initialize an enumeration. NEEDS WORK ON HANDLING * ? \. */
  457. file_enum *
  458. gp_enumerate_files_init (const char *pat, uint patlen, gs_memory_t *memory)
  459. { file_enum *pfen =
  460. (file_enum *)gs_alloc_bytes(memory, sizeof(file_enum), "gp_enumerate_files");
  461. char *pattern;
  462. if ( pfen == 0 ) return 0;
  463. pattern =
  464. (char *)gs_alloc_bytes(memory, patlen + 1, "gp_enumerate_files(pattern)");
  465. if ( pattern == 0 ) return 0;
  466. memcpy(pattern, pat, patlen);
  467. pattern[patlen] = 0;
  468. pfen->pattern = pattern;
  469. pfen->memory = memory;
  470. pfen->first_time = 1;
  471. return pfen;
  472. }
  473. /* Enumerate the next file. */
  474. uint
  475. gp_enumerate_files_next (file_enum *pfen, char *ptr, uint maxlen)
  476. { if ( pfen->first_time )
  477. { pfen->first_time = 0;
  478. }
  479. return -1;
  480. }
  481. /* Clean up the file enumeration. */
  482. void
  483. gp_enumerate_files_close (file_enum *pfen)
  484. {
  485. gs_free_object(pfen->memory, pfen->pattern, "gp_enumerate_files_close(pattern)");
  486. gs_free_object(pfen->memory, (char *)pfen, "gp_enumerate_files_close");
  487. }
  488. FILE *
  489. gp_fopen (const char * fname, const char * mode ) {
  490. char thefname[256];
  491. FILE *fid;
  492. int ans;
  493. //sprintf((char*)&thefname[0],"\n%s\n",fname);
  494. //(*pgsdll_callback) (GSDLL_STDOUT, thefname, strlen(fname));
  495. if ( strrchr(fname,':') == NULL )
  496. // sprintf((char *)&thefname[0],"%s%s\0",g_homeDir,fname);
  497. sprintf((char *)&thefname[0],"%s%s\0","",fname);
  498. else
  499. sprintf((char*)&thefname[0],"%s\0",fname);
  500. fid = fopen(thefname,mode);
  501. return fid;
  502. }
  503. FILE *
  504. popen (const char * fname, const char * mode ) {
  505. return gp_fopen (fname, mode );
  506. }
  507. int
  508. pclose (FILE * pipe ) {
  509. return fclose (pipe );
  510. }