home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume36 / chiaro / part15 < prev    next >
Text File  |  1993-03-26  |  57KB  |  1,654 lines

  1. Newsgroups: comp.sources.misc
  2. From: jwbirdsa@picarefy.picarefy.com (James W. Birdsall)
  3. Subject: v36i085:  chiaro - Image Utilities, Part15/18
  4. Message-ID: <1993Mar26.202929.15020@sparky.imd.sterling.com>
  5. X-Md4-Signature: 1e704be0f2e7ae5456cb98e8bcc042a0
  6. Date: Fri, 26 Mar 1993 20:29:29 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: jwbirdsa@picarefy.picarefy.com (James W. Birdsall)
  10. Posting-number: Volume 36, Issue 85
  11. Archive-name: chiaro/part15
  12. Environment: UNIX, Sun, DECstation, 3B1
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then feed it
  16. # into a shell via "sh file" or similar.  To overwrite existing files,
  17. # type "sh file -c".
  18. # Contents:  src/gif.c.A src/mf.c
  19. # Wrapped by kent@sparky on Thu Mar 25 11:20:07 1993
  20. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  21. echo If this archive is complete, you will see the following message:
  22. echo '          "shar: End of archive 15 (of 18)."'
  23. if test -f 'src/gif.c.A' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'src/gif.c.A'\"
  25. else
  26.   echo shar: Extracting \"'src/gif.c.A'\" \(28663 characters\)
  27.   sed "s/^X//" >'src/gif.c.A' <<'END_OF_FILE'
  28. X/***************************************************************************
  29. X*   GIF.C                                                                  *
  30. X*   MODULE:  GIF                                                           *
  31. X*   OS:      UNIX                                                          *
  32. X*                                                                          *
  33. X*   Copyright (c) 1993 James W. Birdsall. All Rights Reserved.             *
  34. X*                                                                          *
  35. X*   The Graphics Interchange Format(c) is the Copyright property of        *
  36. X*   CompuServe Incorporated. GIF(sm) is a Service Mark property of         *
  37. X*   CompuServe Incorporated.                                               *
  38. X*                                                                          *
  39. X*   $Id: gif.c,v 1.7 1993/03/08 00:19:35 jwbirdsa Exp $
  40. X*                                                                          *
  41. X*   This module is for processing GIF format files. Functions are:         *
  42. X*                                                                          *
  43. X*      gif_verify                                                          *
  44. X*      gif_lsdget                                                          *
  45. X*      gif_searchlsd                                                       *
  46. X*      gif_gctget                                                          *
  47. X*      gif_findnext                                                        *
  48. X*      gif_imdget                                                          *
  49. X*      gif_lctget                                                          *
  50. X*      gif_skipsection                                                     *
  51. X*      gif_grafctrlext                                                     *
  52. X*      gif_commentext                                                      *
  53. X*      gif_plaintextext                                                    *
  54. X*      gif_applext                                                         *
  55. X*      gif_readblock                                                       *
  56. X*      gif_errstring                                                       *
  57. X*                                                                          *
  58. X***************************************************************************/
  59. X
  60. X#include "config.h"
  61. X
  62. X/*
  63. X** system includes <>
  64. X*/
  65. X
  66. X#include <stdio.h>
  67. X#ifndef NO_STDLIB
  68. X#include <stdlib.h>
  69. X#endif
  70. X#ifndef NO_STR_INC
  71. X#ifdef STRING_PLURAL
  72. X#include <strings.h>
  73. X#else
  74. X#include <string.h>
  75. X#endif
  76. X#endif
  77. X
  78. X
  79. X/*
  80. X** custom includes ""
  81. X*/
  82. X
  83. X#include "depend.h"
  84. X#include "fb.h"
  85. X#include "formats.h"
  86. X#include "gif.h"
  87. X
  88. X
  89. X/*
  90. X** local #defines
  91. X*/
  92. X
  93. X/* Define GIF_SIG_LEN_MAX as the longer of the two signature lengths. */
  94. X
  95. X#if GIF_SIGNATURE_LEN > SIG_VERS_SIG_LEN
  96. X#define GIF_SIG_LEN_MAX         GIF_SIGNATURE_LEN
  97. X#else
  98. X#define GIF_SIG_LEN_MAX         GIF_VERS_SIG_LEN
  99. X#endif
  100. X
  101. X
  102. X/*
  103. X** misc: copyright strings, version macros, etc.
  104. X*/
  105. X
  106. X/*
  107. X** typedefs
  108. X*/
  109. X
  110. X/*
  111. X** global variables
  112. X*/
  113. X
  114. Xchar CONST sig[] = GIF_SIGNATURE;
  115. X
  116. X
  117. X/*
  118. X** static globals
  119. X*/
  120. X
  121. Xstatic char CONST rcsid[] = "$Id: gif.c,v 1.7 1993/03/08 00:19:35 jwbirdsa Exp $";
  122. X
  123. X
  124. X/*
  125. X** function prototypes
  126. X*/
  127. X
  128. X#ifdef  __STDC__
  129. X# define P_(s) s
  130. X#else
  131. X# define P_(s) ()
  132. X#endif
  133. X
  134. Xstatic ULONG gif_vget P_((FILE *infile, ULONG *version));
  135. X
  136. X#ifndef NO_FB
  137. Xstatic ULONG gif_fgetvers P_((FB *infile, ULONG *version));
  138. X
  139. Xstatic ULONG gif_tblget P_((FB *infile, RGB_TRIPLET *colors, int size));
  140. Xstatic ULONG gif_gbytes P_((FB *infile, char **bytes, unsigned int *length));
  141. X#endif
  142. X
  143. X#undef P_
  144. X
  145. X#ifdef NO_STR_INC
  146. Xextern int strncmp();
  147. X#endif
  148. X
  149. X
  150. X/*
  151. X** functions
  152. X*/
  153. X
  154. X/***************************************************************************
  155. X*   FUNCTION: gif_verify                                                   *
  156. X*                                                                          *
  157. X*   DESCRIPTION:                                                           *
  158. X*                                                                          *
  159. X*      This function checks a file to determine if it is a GIF format      *
  160. X*      file or not.                                                        *
  161. X*                                                                          *
  162. X*                                                                          *
  163. X*   ENTRY:                                                                 *
  164. X*                                                                          *
  165. X*      filename - a pointer to a string which is the name of the file to   *
  166. X*                 be checked                                               *
  167. X*      version  - pointer to an unsigned long in which version information *
  168. X*                 is returned                                              *
  169. X*      exts     - optional list of file extensions                         *
  170. X*                                                                          *
  171. X*   EXIT:                                                                  *
  172. X*                                                                          *
  173. X*      Returns an error/status code.                                       *
  174. X*                                                                          *
  175. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  176. X*                                                                          *
  177. X***************************************************************************/
  178. XULONG
  179. X#ifdef __STDC__
  180. Xgif_verify(char *filename, ULONG *version, char **exts)
  181. X#else
  182. Xgif_verify(filename, version, exts)
  183. Xchar *filename;
  184. XULONG *version;
  185. Xchar **exts;
  186. X#endif
  187. X{
  188. X    FILE *infile;                /* file handle */
  189. X    ULONG status;                /* status code storage */
  190. X
  191. X    /* If a list of extensions was supplied, check against it. */
  192. X
  193. X    if (((char **) NULL) != exts)
  194. X    {
  195. X        /* Search for '.' marking extension. */
  196. X
  197. X        int loop;
  198. X        char *extptr = (char *) strrchr(filename, '.');
  199. X
  200. X        if (NULL == extptr)
  201. X        {
  202. X            /* No extension, cannot classify. */
  203. X
  204. X            *version = GIF_NOT;
  205. X            return 0;
  206. X        }
  207. X        extptr++;
  208. X
  209. X        /* Now we have the extension, check against list. */
  210. X
  211. X        for (loop = 0; exts[loop] != NULL; loop++)
  212. X        {
  213. X            /* Case-sensitive string compare. */
  214. X
  215. X            if (strcmp(extptr, exts[loop]) == 0)
  216. X            {
  217. X                /* Match, so break out of loop. */
  218. X
  219. X                break;
  220. X            }
  221. X        }
  222. X
  223. X        /* Check exit from loop. */
  224. X
  225. X        if (NULL == exts[loop])
  226. X        {
  227. X            /* No match, return. */
  228. X
  229. X            *version = GIF_NOT;
  230. X            return 0;
  231. X        }
  232. X
  233. X        /* Extension is valid for type GIF, so process accordingly. */
  234. X    }
  235. X
  236. X    /* Open file. */
  237. X
  238. X    if ((infile = fopen(filename, FOPEN_READ_BINARY)) == (FILE *) NULL)
  239. X    {
  240. X        return GIF_NOFILE_E;
  241. X    }
  242. X
  243. X    /* Get version. */
  244. X
  245. X    status = gif_vget(infile, version);
  246. X
  247. X    if (fclose(infile))
  248. X    {
  249. X        return GIF_FILEERR_E;
  250. X    }
  251. X
  252. X    return status;
  253. X} /* end of gif_verify() */
  254. X
  255. X
  256. X/***************************************************************************
  257. X*   FUNCTION: gif_lsdget                                                   *
  258. X*                                                                          *
  259. X*   DESCRIPTION:                                                           *
  260. X*                                                                          *
  261. X*      This function obtains and parses the GIF logical screen descriptor  *
  262. X*      (LSD), then returns the results.                                    *
  263. X*                                                                          *
  264. X*   ENTRY:                                                                 *
  265. X*                                                                          *
  266. X*      infile - handle of file (must be open in BINARY mode)               *
  267. X*      lsd    - pointer to GIF_LSD structure in which results  returned.   *
  268. X*                                                                          *
  269. X*   EXIT:                                                                  *
  270. X*                                                                          *
  271. X*      Returns an error/status code.                                       *
  272. X*                                                                          *
  273. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  274. X*                                                                          *
  275. X*      Leaves file pointer pointing to byte after logical screen           *
  276. X*      descriptor.                                                         *
  277. X*                                                                          *
  278. X***************************************************************************/
  279. XULONG
  280. X#ifdef __STDC__
  281. Xgif_lsdget(FILE *infile, GIF_LSD *results)
  282. X#else
  283. Xgif_lsdget(infile, results)
  284. XFILE *infile;
  285. XGIF_LSD *results;
  286. X#endif
  287. X{
  288. X    ULONG status;                    /* status code storage */
  289. X    UCHAR lsd_buffer[GIF_LSD_LEN];   /* buffer for raw lsd */
  290. X
  291. X    /* First, check that it is a GIF file and get version. */
  292. X
  293. X    /* Seek to correct place in file. */
  294. X
  295. X    if (fseek(infile, 0L, SEEK_SET))
  296. X    {
  297. X        return GIF_FILEERR_E;
  298. X    }
  299. X    if ((status = gif_vget(infile, &(results->version))) != 0)
  300. X    {
  301. X        return status;
  302. X    }
  303. X
  304. X    /* Check version. */
  305. X
  306. X    if (results->version == GIF_NOT)
  307. X    {
  308. X        return GIF_NOTGIF_E;
  309. X    }
  310. X
  311. X    /*
  312. X    ** Calling gif_vget() has forwarded us over signature, so next
  313. X    ** bytes should be the LSD.
  314. X    */
  315. X
  316. X    if (fread(lsd_buffer, 1, GIF_LSD_LEN, infile) != GIF_LSD_LEN)
  317. X    {
  318. X        return GIF_UNEOF_E;
  319. X    }
  320. X
  321. X    /* Got the lsd, so let's take it apart. */
  322. X
  323. X    results->scr_wid = CONSTRUCT_I_UINT(lsd_buffer + GIF_LSD_SCRWID_OFF);
  324. X    results->scr_hi = CONSTRUCT_I_UINT(lsd_buffer + GIF_LSD_SCRHI_OFF);
  325. X    results->background = (int) (*(lsd_buffer + GIF_LSD_BACKGROUND_OFF));
  326. X    results->aspect = (int) (*(lsd_buffer + GIF_LSD_ASPECT_OFF));
  327. X
  328. X    results->raw_packed = (*(lsd_buffer + GIF_LSD_PACKED_OFF));
  329. X    results->gct_flag = (results->raw_packed & GIF_LSD_GCTFLAG_MASK) ? 1 : 0;
  330. X    results->clr_res = (((unsigned int)(results->raw_packed &
  331. X                                        GIF_LSD_CLRRES_MASK)) >> 
  332. X                        GIF_LSD_CLRRES_SHIFT);
  333. X    results->clr_res++;
  334. X    results->sort_flag = (results->raw_packed & GIF_LSD_SORTFLAG_MASK) ? 1 : 0;
  335. X    results->gct_size = (((unsigned int)(results->raw_packed &
  336. X                                         GIF_LSD_GCTSIZE_MASK)) + 1);
  337. X
  338. X    /* All done. */
  339. X
  340. X    return 0;
  341. X} /* end of gif_lsdget() */
  342. X
  343. X
  344. X/***************************************************************************
  345. X*   FUNCTION: gif_searchlsd                                                *
  346. X*                                                                          *
  347. X*   DESCRIPTION:                                                           *
  348. X*                                                                          *
  349. X*      This function obtains and parses the GIF logical screen descriptor  *
  350. X*      (LSD), then returns the results. It scans forward over leading      *
  351. X*      junk, starting from the beginning of the file.                      *
  352. X*                                                                          *
  353. X*   ENTRY:                                                                 *
  354. X*                                                                          *
  355. X*      infile  - FB handle of file                                         *
  356. X*      lsd     - pointer to GIF_LSD structure in which results returned.   *
  357. X*      skipped - pointer to unsigned long in which count of junk           *
  358. X*                character skipped is returned.                            *
  359. X*                                                                          *
  360. X*   EXIT:                                                                  *
  361. X*                                                                          *
  362. X*      Returns an error/status code.                                       *
  363. X*                                                                          *
  364. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  365. X*                                                                          *
  366. X*      Leaves file pointer pointing to byte after logical screen           *
  367. X*      descriptor.                                                         *
  368. X*                                                                          *
  369. X***************************************************************************/
  370. XULONG
  371. X#ifdef __STDC__
  372. Xgif_searchlsd(FB *infile, GIF_LSD *results, ULONG *skipped)
  373. X#else
  374. Xgif_searchlsd(infile, results, skipped)
  375. XFB *infile;
  376. XGIF_LSD *results;
  377. XULONG *skipped;
  378. X#endif
  379. X{
  380. X#ifndef NO_FB
  381. X    ULONG status;                    /* status code storage */
  382. X    UCHAR lsd_buffer[GIF_LSD_LEN];   /* buffer for raw lsd */
  383. X    int c;
  384. X    long place;
  385. X
  386. X    /* Seek to correct place in file. */
  387. X
  388. X    if (fb_seek(infile, 0L))
  389. X    {
  390. X        return fb_error;
  391. X    }
  392. X
  393. X    /* Search for GIF signature. */
  394. X
  395. X    *skipped = 0L;
  396. X    while ((c = fb_getc(infile)) != -1)
  397. X    {
  398. X        if (c == sig[0])
  399. X        {
  400. X            /* Found first char of signature. Seek back one and check. */
  401. X
  402. X            place = fb_tell(infile);
  403. X            if (fb_error != 0)
  404. X            {
  405. X                return fb_error;
  406. X            }
  407. X            if (fb_seek(infile, (place - 1)))
  408. X            {
  409. X                return fb_error;
  410. X            }
  411. X
  412. X            /* Check for signature. */
  413. X
  414. X            if ((status = gif_fgetvers(infile, &(results->version))) != 0)
  415. X            {
  416. X                if (status != GIF_NOTGIF_E)
  417. X                {
  418. X                    /* Real error. */
  419. X
  420. X                    return status;
  421. X                }
  422. X                /* If status was GIF_NOTGIF_E, keep looking. */
  423. X            }
  424. X            else
  425. X            {
  426. X                /*
  427. X                ** If got half a signature, gif_fgetvers() returns OK
  428. X                ** but with bad version number. Check for this.
  429. X                */
  430. X
  431. X                if (results->version != GIF_NOT)
  432. X                {
  433. X                    /* Really got a signature, exit while loop. */
  434. X
  435. X                    break;
  436. X                }
  437. X                /* Only got half a signature, so keep looking. */
  438. X            }
  439. X        }
  440. X        (*skipped)++;
  441. X    }
  442. X
  443. X    /* If c is EOF, file isn't a GIF; otherwise got signature OK. */
  444. X
  445. X    if (c == -1)
  446. X    {
  447. X        /* If FB says EOF, is OK; otherwise real error occurred. */
  448. X
  449. X        return ((FB_EOF_W == fb_error) ? GIF_NOTGIF_E : fb_error);
  450. X    }
  451. X
  452. X    /* Check version, just to be sure. */
  453. X
  454. X    if (results->version == GIF_NOT)
  455. X    {
  456. X        return GIF_NOTGIF_E;
  457. X    }
  458. X
  459. X    /*
  460. X    ** Calling gif_fgetvers() has forwarded us over signature, so next
  461. X    ** bytes should be the LSD.
  462. X    */
  463. X
  464. X    if (fb_read(infile, lsd_buffer, GIF_LSD_LEN) != GIF_LSD_LEN)
  465. X    {
  466. X        return GIF_UNEOF_E;
  467. X    }
  468. X
  469. X    /* Got the lsd, so let's take it apart. */
  470. X
  471. X    results->scr_wid = CONSTRUCT_I_UINT(lsd_buffer + GIF_LSD_SCRWID_OFF);
  472. X    results->scr_hi = CONSTRUCT_I_UINT(lsd_buffer + GIF_LSD_SCRHI_OFF);
  473. X    results->background = (int) (*(lsd_buffer + GIF_LSD_BACKGROUND_OFF));
  474. X    results->aspect = (int) (*(lsd_buffer + GIF_LSD_ASPECT_OFF));
  475. X
  476. X    results->raw_packed = (*(lsd_buffer + GIF_LSD_PACKED_OFF));
  477. X    results->gct_flag = (results->raw_packed & GIF_LSD_GCTFLAG_MASK) ? 1 : 0;
  478. X    results->clr_res = (((unsigned int)(results->raw_packed &
  479. X                                        GIF_LSD_CLRRES_MASK)) >> 
  480. X                        GIF_LSD_CLRRES_SHIFT);
  481. X    results->clr_res++;
  482. X    results->sort_flag = (results->raw_packed & GIF_LSD_SORTFLAG_MASK) ? 1 : 0;
  483. X    results->gct_size = (((unsigned int)(results->raw_packed &
  484. X                                         GIF_LSD_GCTSIZE_MASK)) + 1);
  485. X
  486. X    /* All done. */
  487. X
  488. X    return 0;
  489. X
  490. X#else
  491. X
  492. X   return GIF_UNSUPRT_F;
  493. X
  494. X#endif /* NO_FB */
  495. X} /* end of gif_searchlsd() */
  496. X
  497. X
  498. X/***************************************************************************
  499. X*   FUNCTION: gif_gctget                                                   *
  500. X*                                                                          *
  501. X*   DESCRIPTION:                                                           *
  502. X*                                                                          *
  503. X*      This function reads and returns the GIF global color table.         *
  504. X*                                                                          *
  505. X*   ENTRY:                                                                 *
  506. X*                                                                          *
  507. X*      infile - FB handle of file                                          *
  508. X*      gct    - pointer to pointer to array of RGB_TRIPLETs in which color *
  509. X*               table is returned. This array is malloc()ed and must be    *
  510. X*               free()ed when no longer needed.                            *
  511. X*      colors - number of entries in table                                 *
  512. X*                                                                          *
  513. X*   EXIT:                                                                  *
  514. X*                                                                          *
  515. X*      Returns an error/status code.                                       *
  516. X*                                                                          *
  517. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  518. X*                                                                          *
  519. X*      Assumes file positioned correctly.                                  *
  520. X*                                                                          *
  521. X*      Leaves file pointer pointing to byte after end of global color      *
  522. X*      table.                                                              *
  523. X*                                                                          *
  524. X***************************************************************************/
  525. XULONG
  526. X#ifdef __STDC__
  527. Xgif_gctget(FB *infile, RGB_TRIPLET **gct, int colors)
  528. X#else
  529. Xgif_gctget(infile, gct, colors)
  530. XFB *infile;
  531. XRGB_TRIPLET **gct;
  532. Xint colors;
  533. X#endif
  534. X{
  535. X#ifndef NO_FB
  536. X
  537. X    ULONG status;                 /* status code storage */
  538. X
  539. X    /* Allocate memory. */
  540. X
  541. X    *gct = (RGB_TRIPLET *) malloc(colors * sizeof(RGB_TRIPLET));
  542. X    if (*gct == (RGB_TRIPLET *) NULL)
  543. X    {
  544. X        return GIF_NOMEM_E;
  545. X    }
  546. X
  547. X    /* Read table. */
  548. X
  549. X    if ((status = gif_tblget(infile, *gct, colors)) != 0)
  550. X    {
  551. X        return status;
  552. X    }
  553. X
  554. X    /* Return OK. */
  555. X
  556. X    return 0;
  557. X
  558. X#else
  559. X
  560. X    return GIF_UNSUPRT_F;
  561. X
  562. X#endif /* NO_FB */
  563. X} /* end of gif_gctget() */
  564. X
  565. X
  566. X/***************************************************************************
  567. X*   FUNCTION: gif_findnext                                                 *
  568. X*                                                                          *
  569. X*   DESCRIPTION:                                                           *
  570. X*                                                                          *
  571. X*      Searches forward through the GIF file for the next recognized       *
  572. X*      section of data.                                                    *
  573. X*                                                                          *
  574. X*   ENTRY:                                                                 *
  575. X*                                                                          *
  576. X*      infile   - FB handle of file                                        *
  577. X*      datatype - pointer to int in which type of section is returned      *
  578. X*      skip     - pointer to unsigned long in which number of bytes        *
  579. X*                 skipped before section intro was found is returned       *
  580. X*      extype   - pointer to int in which type of extension block is       *
  581. X*                 returned when an extension block is found. Also set      *
  582. X*                 when terminator found; 0 if no extra characters, 1 if    *
  583. X*                 extras.                                                  *
  584. X*                                                                          *
  585. X*   EXIT:                                                                  *
  586. X*                                                                          *
  587. X*      Returns an error/status code.                                       *
  588. X*                                                                          *
  589. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  590. X*                                                                          *
  591. X*      Assumes file is positioned correctly. Leaves file pointer pointing  *
  592. X*      to first byte of image descriptor, first byte of extension block    *
  593. X*      data, or to EOF (roughly) for terminator.                           *
  594. X*                                                                          *
  595. X***************************************************************************/
  596. XULONG
  597. X#ifdef __STDC__
  598. Xgif_findnext(FB *infile, int *datatype, ULONG *skip, int *extype)
  599. X#else
  600. Xgif_findnext(infile, datatype, skip, extype)
  601. XFB *infile;
  602. Xint *datatype;
  603. XULONG *skip;
  604. Xint *extype;
  605. X#endif
  606. X{
  607. X#ifndef NO_FB
  608. X    int c;
  609. X
  610. X    /* Preinit returns. */
  611. X
  612. X    *skip = MKLONG(0);
  613. X    *extype = 0;
  614. X
  615. X    /* Search forward. */
  616. X
  617. X    while ((c = fb_getc(infile)) != -1)
  618. X    {
  619. X        if ((c == GIF_EXTBLOCK) || (c == GIF_IMAGE) || (c == GIF_TERMINATOR))
  620. X        {
  621. X            /* If a known block is found, break out of loop. */
  622. X
  623. X            break;
  624. X        }
  625. X
  626. X        /* Otherwise increment count and keep going. */
  627. X
  628. X        (*skip)++;
  629. X    }
  630. X
  631. X    /* Check for error. */
  632. X
  633. X    if (c == -1)
  634. X    {
  635. X        /*
  636. X        ** If not end of file, just pass error code along; otherwise
  637. X        ** is an unexpected EOF.
  638. X        */
  639. X
  640. X        return ((fb_error != FB_EOF_W) ? fb_error : GIF_UNEOF_E);
  641. X    }
  642. X
  643. X    /* Set data type. */
  644. X
  645. X    *datatype = c;
  646. X
  647. X    /* Further processing. */
  648. X
  649. X    if (c == GIF_EXTBLOCK)
  650. X    {
  651. X        /* If extension block, get type. */
  652. X
  653. X        if ((*extype = fb_getc(infile)) == -1)
  654. X        {
  655. X            /*
  656. X            ** If not end of file, just pass error code along; otherwise
  657. X            ** is an unexpected EOF.
  658. X            */
  659. X
  660. X            return ((fb_error != FB_EOF_W) ? fb_error : GIF_UNEOF_E);
  661. X        }
  662. X    }
  663. X    else if (c == GIF_TERMINATOR)
  664. X    {
  665. X        /* Check for additional characters. */
  666. X
  667. X        if ((c = fb_getc(infile)) != -1)
  668. X        {
  669. X            *extype = 1;
  670. X        }
  671. X        else
  672. X        {
  673. X            /* If not end of file, just pass error code along. */
  674. X
  675. X            if (fb_error != FB_EOF_W)
  676. X            {
  677. X                return fb_error;
  678. X            }
  679. X
  680. X            /* Got the EOF we wanted. */
  681. X
  682. X            *extype = 0;
  683. X        }
  684. X    }
  685. X
  686. X    /* Return OK. */
  687. X
  688. X    return 0;
  689. X
  690. X#else
  691. X
  692. X    return GIF_UNSUPRT_F;
  693. X
  694. X#endif /* NO_FB */
  695. X} /* end of gif_findnext() */
  696. X
  697. X
  698. X/***************************************************************************
  699. X*   FUNCTION: gif_imdget                                                   *
  700. X*                                                                          *
  701. X*   DESCRIPTION:                                                           *
  702. X*                                                                          *
  703. X*      Reads and parses the GIF image descriptor, and returns the results. *
  704. X*                                                                          *
  705. X*   ENTRY:                                                                 *
  706. X*                                                                          *
  707. X*      infile - FB handle of file                                          *
  708. X*      imd    - pointer to GIF_IMD structure in which to return results    *
  709. X*                                                                          *
  710. X*   EXIT:                                                                  *
  711. X*                                                                          *
  712. X*      Returns an error/status code.                                       *
  713. X*                                                                          *
  714. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  715. X*                                                                          *
  716. X*      Assumes the file is positioned correctly. Leaves file pointer       *
  717. X*      pointing to first byte after image descriptor.                      *
  718. X*                                                                          *
  719. X***************************************************************************/
  720. XULONG
  721. X#ifdef __STDC__
  722. Xgif_imdget(FB *infile, GIF_IMD *imd)
  723. X#else
  724. Xgif_imdget(infile, imd)
  725. XFB *infile;
  726. XGIF_IMD *imd;
  727. X#endif
  728. X{
  729. X#ifndef NO_FB
  730. X    UCHAR rawimd[GIF_IMD_LEN];
  731. X
  732. X    /* Read the raw image descriptor. */
  733. X
  734. X    if (fb_read(infile, rawimd, GIF_IMD_LEN) != GIF_IMD_LEN)
  735. X    {
  736. X        /*
  737. X        ** If not end of file, just pass error code along; otherwise
  738. X        ** is an unexpected EOF.
  739. X        */
  740. X
  741. X        return ((fb_error != FB_EOF_W) ? fb_error : GIF_UNEOF_E);
  742. X    }
  743. X
  744. X    /* Parse image descriptor. */
  745. X
  746. X    imd->im_left = CONSTRUCT_I_UINT(rawimd + GIF_IMD_IMLEFT_OFF);
  747. X    imd->im_top = CONSTRUCT_I_UINT(rawimd + GIF_IMD_IMTOP_OFF);
  748. X    imd->im_wid = CONSTRUCT_I_UINT(rawimd + GIF_IMD_IMWID_OFF);
  749. X    imd->im_hi = CONSTRUCT_I_UINT(rawimd + GIF_IMD_IMHI_OFF);
  750. X
  751. X    /* Unpack packed fields. */
  752. X
  753. X    imd->raw_packed = (*(rawimd + GIF_IMD_PACKED_OFF));
  754. X    imd->lct_flag = ((imd->raw_packed & GIF_IMD_LCTFLAG_MASK) ? 1 : 0);
  755. X    imd->interlace_flag = ((imd->raw_packed &
  756. X                            GIF_IMD_INTRLACEFLAG_MASK) ? 1 : 0);
  757. X    imd->sort_flag = ((imd->raw_packed & GIF_IMD_SORTFLAG_MASK) ? 1 : 0);
  758. X    imd->lct_size = ((int) (imd->raw_packed & GIF_IMD_LCTSIZE_MASK)) + 1;
  759. X
  760. X    /* Return OK. */
  761. X
  762. X    return 0;
  763. X
  764. X#else
  765. X
  766. X    return GIF_UNSUPRT_F;
  767. X
  768. X#endif /* NO_FB */
  769. X} /* end of gif_imdget() */
  770. X
  771. X
  772. X/***************************************************************************
  773. X*   FUNCTION: gif_lctget                                                   *
  774. X*                                                                          *
  775. X*   DESCRIPTION:                                                           *
  776. X*                                                                          *
  777. X*      This function reads and returns a GIF local color table.            *
  778. X*                                                                          *
  779. X*   ENTRY:                                                                 *
  780. X*                                                                          *
  781. X*      infile - FB handle of file                                          *
  782. X*      lct    - pointer to pointer to array of RGB_TRIPLETs in which color *
  783. X*               table is returned. This array is malloc()ed and must be    *
  784. X*               free()ed when no longer needed.                            *
  785. X*      colors - number of entries in table                                 *
  786. X*                                                                          *
  787. X*   EXIT:                                                                  *
  788. X*                                                                          *
  789. X*      Returns an error/status code.                                       *
  790. X*                                                                          *
  791. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  792. X*                                                                          *
  793. X*      Assumes the file is positioned correctly.                           *
  794. X*      Leaves file pointer pointing to byte after end of local color       *
  795. X*      table.                                                              *
  796. X*                                                                          *
  797. X***************************************************************************/
  798. XULONG
  799. X#ifdef __STDC__
  800. Xgif_lctget(FB *infile, RGB_TRIPLET **lct, int colors)
  801. X#else
  802. Xgif_lctget(infile, lct, colors)
  803. XFB *infile;
  804. XRGB_TRIPLET **lct;
  805. Xint colors;
  806. X#endif
  807. X{
  808. X#ifndef NO_FB
  809. X
  810. X    ULONG status;                 /* status code storage */
  811. X
  812. X    /* Allocate memory. */
  813. X
  814. X    *lct = (RGB_TRIPLET *) malloc(colors * sizeof(RGB_TRIPLET));
  815. X    if (*lct == (RGB_TRIPLET *) NULL)
  816. X    {
  817. X        return GIF_NOMEM_E;
  818. X    }
  819. X
  820. X    /* Read table. */
  821. X
  822. X    if ((status = gif_tblget(infile, *lct, colors)) != 0)
  823. X    {
  824. X        return status;
  825. X    }
  826. X
  827. X    /* Return OK. */
  828. X    return 0;
  829. X
  830. X#else
  831. X
  832. X    return GIF_UNSUPRT_F;
  833. X
  834. X#endif /* NO_FB */
  835. X} /* end of gif_lctget() */
  836. X
  837. END_OF_FILE
  838.   if test 28663 -ne `wc -c <'src/gif.c.A'`; then
  839.     echo shar: \"'src/gif.c.A'\" unpacked with wrong size!
  840.   elif test -f 'src/gif.c.B'; then
  841.     echo shar: Combining  \"'src/gif.c'\" \(63060 characters\)
  842.     cat 'src/gif.c.A' 'src/gif.c.B' > 'src/gif.c'
  843.     if test 63060 -ne `wc -c <'src/gif.c'`; then
  844.       echo shar: \"'src/gif.c'\" combined with wrong size!
  845.     else 
  846.       rm src/gif.c.A src/gif.c.B 
  847.     fi 
  848.   fi 
  849.   # end of 'src/gif.c.A'
  850. fi
  851. if test -f 'src/mf.c' -a "${1}" != "-c" ; then 
  852.   echo shar: Will not clobber existing file \"'src/mf.c'\"
  853. else
  854.   echo shar: Extracting \"'src/mf.c'\" \(24264 characters\)
  855.   sed "s/^X//" >'src/mf.c' <<'END_OF_FILE'
  856. X/***************************************************************************
  857. X*   MF.C                                                                   *
  858. X*   MODULE:  MF                                                            *
  859. X*   OS:      UNIX                                                          *
  860. X*                                                                          *
  861. X*   Copyright (c) 1993 James W. Birdsall. All Rights Reserved.             *
  862. X*                                                                          *
  863. X*   $Id: mf.c,v 1.8 1993/03/02 01:01:50 jwbirdsa Exp $
  864. X*                                                                          *
  865. X*   This file contains functions which can write to memory or disk.        *
  866. X*                                                                          *
  867. X*   This module assumes that the FB module has been initialized with       *
  868. X*   appropriate values before any MF functions are called.                 *
  869. X*                                                                          *
  870. X*   Functions in this file are:                                            *
  871. X*                                                                          *
  872. X*     mf_open  - open the "file", determine size, allocate memory & disk   *
  873. X*     mf_write - write to the "file"                                       *
  874. X*     mf_reset - prepare "file" for readback                               *
  875. X*     mf_read  - read from "file"                                          *
  876. X*     mf_close - close the "file", free memory and disk                    *
  877. X*                                                                          *
  878. X*     mf_errstring - convert an error/status code into a string            *
  879. X*                                                                          *
  880. X***************************************************************************/
  881. X
  882. X#include "config.h"
  883. X
  884. X/*
  885. X** system includes <>
  886. X*/
  887. X
  888. X#include <stdio.h>
  889. X#include <ctype.h>
  890. X#include <sys/types.h>
  891. X#ifndef NO_MALLOCHDR
  892. X#include <malloc.h>
  893. X#endif
  894. X#ifndef NO_STR_INC
  895. X#ifdef STRING_PLURAL
  896. X#include <strings.h>
  897. X#else
  898. X#include <string.h>
  899. X#endif
  900. X#endif
  901. X
  902. X
  903. X/*
  904. X** custom includes ""
  905. X*/
  906. X
  907. X#include "depend.h"
  908. X#include "mf.h"
  909. X#include "fb.h"
  910. X
  911. X
  912. X/*
  913. X** local #defines
  914. X*/
  915. X
  916. X#define STATE_CLOSED     0
  917. X#define STATE_WOPEN      1
  918. X#define STATE_ROPEN      2
  919. X
  920. X
  921. X/*
  922. X** misc: copyright strings, version macros, etc.
  923. X*/
  924. X
  925. Xstatic char CONST rcsid[] = "$Id: mf.c,v 1.8 1993/03/02 01:01:50 jwbirdsa Exp $";
  926. X
  927. X
  928. X/*
  929. X** typedefs
  930. X*/
  931. X
  932. X/*
  933. X** global variables
  934. X*/
  935. X
  936. Xint mf_locked = 0;
  937. X
  938. X
  939. X/*
  940. X** static globals
  941. X*/
  942. X
  943. Xstatic int openflag = STATE_CLOSED;
  944. X
  945. Xstatic ULONG conmem;
  946. Xstatic UCHAR *conmemhandle;
  947. Xstatic ULONG dskmem;
  948. Xstatic FB *dskmemhandle;
  949. Xstatic char dskmemname[MAXPATH];
  950. X
  951. Xstatic ULONG conmemptr;
  952. Xstatic ULONG dskmemptr;
  953. X
  954. X
  955. X/*
  956. X** function prototypes
  957. X*/
  958. X
  959. X#ifdef  __STDC__
  960. X# define P_(s) s
  961. X#else
  962. X# define P_(s) ()
  963. X#endif
  964. X
  965. Xstatic ULONG cleanup();
  966. X
  967. X#undef P_
  968. X
  969. X#ifdef NO_STR_INC
  970. Xextern char *strcpy();
  971. X#endif
  972. X
  973. X
  974. X/*
  975. X** functions
  976. X*/
  977. X
  978. X/***************************************************************************
  979. X*   FUNCTION:    mf_open                                                   *
  980. X*                                                                          *
  981. X*   DESCRIPTION:                                                           *
  982. X*                                                                          *
  983. X*      This function allocates memory and/or disk space and prepares the   *
  984. X*      module to accept data. It cannot be called when a "file" is already *
  985. X*      open.                                                               *
  986. X*                                                                          *
  987. X*   ENTRY:                                                                 *
  988. X*                                                                          *
  989. X*      flags   - memory/disk usage flags                                   *
  990. X*      maxsize - maximum size that will be required                        *
  991. X*      tpath   - path on which to put temporary file, if any               *
  992. X*                                                                          *
  993. X*   EXIT:                                                                  *
  994. X*                                                                          *
  995. X*      Returns an error/status code.                                       *
  996. X*                                                                          *
  997. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  998. X*                                                                          *
  999. X***************************************************************************/
  1000. XULONG
  1001. X#ifdef __STDC__
  1002. Xmf_open(unsigned int flags, ULONG maxsize, char *tpath)
  1003. X#else
  1004. Xmf_open(flags, maxsize, tpath)
  1005. Xunsigned int flags;
  1006. XULONG maxsize;
  1007. Xchar *tpath;
  1008. X#endif
  1009. X{
  1010. X    ULONG temp;
  1011. X    char *tempn;
  1012. X    char scratch[MAXPATH];
  1013. X    char tempend, separator;
  1014. X
  1015. X    /* Check for already open. */
  1016. X
  1017. X    if (openflag != STATE_CLOSED)
  1018. X    {
  1019. X        return MF_REOPEN_E;
  1020. X    }
  1021. X
  1022. X    /* Set up. */
  1023. X
  1024. X    conmem = 0;
  1025. X    dskmem = 0;
  1026. X    conmemptr = 0;
  1027. X    dskmemptr = 0;
  1028. X
  1029. X    /* Use memory first. */
  1030. X
  1031. X    if (flags & USE_CONMEM)
  1032. X    {
  1033. X        /* Determine size of block to allocate. */
  1034. X
  1035. X        for (conmem = maxsize; (conmem > 1023) && (coreleft((long)conmem) == 0);
  1036. X             conmem /= 2) ;
  1037. X        if (conmem > 1023)
  1038. X        {
  1039. X            /* Allocate block. */
  1040. X
  1041. X            conmemhandle = (UCHAR *) malloc(conmem);
  1042. X            if (((UCHAR *) NULL) == conmemhandle)
  1043. X            {
  1044. X                conmem = 0;
  1045. X                cleanup();
  1046. X                return MF_BUG_F;
  1047. X            }
  1048. X    
  1049. X            /* Decrease maxsize. */
  1050. X
  1051. X            maxsize -= conmem;
  1052. X        }
  1053. X        else
  1054. X        {
  1055. X            conmem = 0;
  1056. X            conmemhandle = (UCHAR *) NULL;
  1057. X        }
  1058. X    }
  1059. X
  1060. X    if (0 == maxsize)
  1061. X    {
  1062. X        /* All done, return OK. */
  1063. X        openflag = STATE_WOPEN;
  1064. X        return ST_SUCCESS;
  1065. X    }
  1066. X
  1067. X    /* When out of memory, use disk. */
  1068. X
  1069. X    if (flags & USE_DISKMEM)
  1070. X    {
  1071. X        /* Get free space on disk. Is it enough? */
  1072. X
  1073. X        if ((dskmem = dfree(tpath)) == -1)
  1074. X        {
  1075. X            dskmem = 0;
  1076. X            cleanup();
  1077. X            return MF_DISKERROR_E;
  1078. X        }
  1079. X        if (maxsize > dskmem)
  1080. X        {
  1081. X            dskmem = 0;
  1082. X            cleanup();
  1083. X            return MF_NOSPACE_E;
  1084. X        }
  1085. X
  1086. X        /* Create a temporary filename. */
  1087. X
  1088. X        tempn = tempname(tpath, NULL);
  1089. X        if (NULL == tempn)
  1090. X        {
  1091. X            dskmem = 0;
  1092. X            cleanup();
  1093. X            return MF_DISKERROR_E;
  1094. X        }
  1095. X        strcpy(dskmemname, tempn);
  1096. X        free(tempn);
  1097. X        /* Open temporary file. */
  1098. X
  1099. X        if ((dskmemhandle = fb_open(dskmemname, 'w', (long *) &temp)) ==
  1100. X            (FB *) NULL)
  1101. X        {
  1102. X            dskmem = 0;
  1103. X            cleanup();
  1104. X            return fb_error;
  1105. X        }
  1106. X
  1107. X        /* All done, return OK. */
  1108. X
  1109. X        dskmem = maxsize;
  1110. X        openflag = STATE_WOPEN;
  1111. X
  1112. X        return ST_SUCCESS;
  1113. X    }
  1114. X
  1115. X    /* No space, so clean up and abort. */
  1116. X
  1117. X    cleanup();
  1118. X
  1119. X    return MF_NOSPACE_E;
  1120. X} /* end of mf_open() */
  1121. X
  1122. X
  1123. X/***************************************************************************
  1124. X*   FUNCTION:    mf_write                                                  *
  1125. X*                                                                          *
  1126. X*   DESCRIPTION:                                                           *
  1127. X*                                                                          *
  1128. X*      This function writes data from the buffer to the "file." Writes up  *
  1129. X*      to 65535 bytes (max unsigned int on 16-bit machines) are allowed.   *
  1130. X*                                                                          *
  1131. X*   ENTRY:                                                                 *
  1132. X*                                                                          *
  1133. X*      buffer - pointer to data buffer                                     *
  1134. X*      length - length of "write"                                          *
  1135. X*                                                                          *
  1136. X*   EXIT:                                                                  *
  1137. X*                                                                          *
  1138. X*      Returns an error/status code.                                       *
  1139. X*                                                                          *
  1140. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1141. X*                                                                          *
  1142. X*      Must call mf_open() before calling this function.                   *
  1143. X*                                                                          *
  1144. X***************************************************************************/
  1145. XULONG
  1146. X#ifdef __STDC__
  1147. Xmf_write(UCHAR *buffer, unsigned int length)
  1148. X#else
  1149. Xmf_write(buffer, length)
  1150. XUCHAR *buffer;
  1151. Xunsigned int length;
  1152. X#endif
  1153. X{
  1154. X    ULONG copylen;
  1155. X    UCHAR *source;
  1156. X    UCHAR *dest;
  1157. X#ifdef INT16
  1158. X    ULONG tempoff;
  1159. X    ULONG remlen;
  1160. X#endif
  1161. X
  1162. X    /* Check that we're open. */
  1163. X
  1164. X    if (openflag != STATE_WOPEN)
  1165. X    {
  1166. X        return MF_NOTOPEN_E;
  1167. X    }
  1168. X
  1169. X    /* First check memory. */
  1170. X
  1171. X    if (conmemptr != conmem)
  1172. X    {
  1173. X        /* 
  1174. X        ** Some free space left in memory, so copy there. Determine amount
  1175. X        ** to copy.
  1176. X        */
  1177. X
  1178. X        copylen = conmem - conmemptr;
  1179. X        copylen = ((copylen > length) ? length : copylen);
  1180. X
  1181. X        /* Do copy. */
  1182. X
  1183. X        dest = (conmemhandle + conmemptr);
  1184. X        memcpy(dest, buffer, (unsigned int) copylen);
  1185. X
  1186. X        /* Decrease length, update buffer. */
  1187. X
  1188. X        length -= (unsigned int) copylen;
  1189. X        buffer += copylen;
  1190. X
  1191. X        /* Update conmemptr. */
  1192. X
  1193. X        conmemptr += copylen;
  1194. X    }
  1195. X
  1196. X    if (0 == length)
  1197. X    {
  1198. X        /* All done, return OK. */
  1199. X
  1200. X        return ST_SUCCESS;
  1201. X    }
  1202. X
  1203. X    /* Write rest to disk. */
  1204. X
  1205. X    if (dskmemptr != dskmem)
  1206. X    {
  1207. X        /* 
  1208. X        ** Some free space left on disk, so copy there. Determine amount
  1209. X        ** to copy.
  1210. X        */
  1211. X
  1212. X        copylen = dskmem - dskmemptr;
  1213. X        copylen = ((copylen > length) ? length : copylen);
  1214. X
  1215. X#ifdef INT16
  1216. X        /* 
  1217. X        ** On a 16-bit machine, if copylen is more than 32767 (max positive 
  1218. X        ** signed int), break up write into as many parts as necessary.
  1219. X        */
  1220. X
  1221. X        for (tempoff = 0, remlen = copylen; remlen > 32767; 
  1222. X             tempoff += 32767, remlen -= 32767)
  1223. X        {
  1224. X            if (fb_write(dskmemhandle, (buffer + tempoff), 32767) != 0)
  1225. X            {
  1226. X                return fb_error;
  1227. X            }
  1228. X        }
  1229. X        if (remlen != 0)
  1230. X        {
  1231. X            if (fb_write(dskmemhandle, (buffer + tempoff), (int) remlen) !=
  1232. X                ST_SUCCESS)
  1233. X            {
  1234. X                return fb_error;
  1235. X            }
  1236. X        }
  1237. X#else
  1238. X        /* On 32-bit machine, simply do copy. */
  1239. X
  1240. X        if (fb_write(dskmemhandle, buffer, (int) copylen) != ST_SUCCESS)
  1241. X        {
  1242. X            return fb_error;
  1243. X        }
  1244. X#endif
  1245. X
  1246. X        /* Decrease length, update buffer. */
  1247. X
  1248. X        length -= (unsigned int) copylen;
  1249. X        buffer += copylen;
  1250. X
  1251. X        /* Update dskmemptr. */
  1252. X
  1253. X        dskmemptr += copylen;
  1254. X    }
  1255. X
  1256. X    /* If length is 0, all done, return OK; otherwise overflow error */
  1257. X
  1258. X    return ((0 == length) ? ST_SUCCESS : MF_OVERFLOW_F);
  1259. X} /* end of mf_write() */
  1260. X
  1261. X
  1262. X/***************************************************************************
  1263. X*   FUNCTION:    mf_reset                                                  *
  1264. X*                                                                          *
  1265. X*   DESCRIPTION:                                                           *
  1266. X*                                                                          *
  1267. X*      This function resets all pointers and otherwise prepares "file"     *
  1268. X*      for readback after writing.                                         *
  1269. X*                                                                          *
  1270. X*   ENTRY:                                                                 *
  1271. X*                                                                          *
  1272. X*      None.                                                               *
  1273. X*                                                                          *
  1274. X*   EXIT:                                                                  *
  1275. X*                                                                          *
  1276. X*      Returns an error/status code.                                       *
  1277. X*                                                                          *
  1278. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1279. X*                                                                          *
  1280. X***************************************************************************/
  1281. XULONG
  1282. Xmf_reset()
  1283. X{
  1284. X    long junk;
  1285. X
  1286. X    /* Check for open. */
  1287. X
  1288. X    if (openflag != STATE_WOPEN)
  1289. X    {
  1290. X        return MF_NOTOPEN_E;
  1291. X    }
  1292. X
  1293. X    conmemptr = 0;
  1294. X    dskmemptr = 0;
  1295. X
  1296. X    if (dskmem != 0)
  1297. X    {
  1298. X        /* If using disk, close file and reopen for reading. */
  1299. X
  1300. X        if (fb_close(dskmemhandle) != ST_SUCCESS)
  1301. X        {
  1302. X            return fb_error;
  1303. X        }
  1304. X        if ((dskmemhandle = fb_open(dskmemname, 'r', &junk)) == (FB *) NULL)
  1305. X        {
  1306. X            return fb_error;
  1307. X        }
  1308. X    }
  1309. X
  1310. X    /* Reset open status. */
  1311. X
  1312. X    openflag = STATE_ROPEN;
  1313. X
  1314. X    /* Return OK. */
  1315. X
  1316. X    return ST_SUCCESS;
  1317. X} /* end of mf_reset() */
  1318. X
  1319. X
  1320. X/***************************************************************************
  1321. X*   FUNCTION:    mf_read                                                   *
  1322. X*                                                                          *
  1323. X*   DESCRIPTION:                                                           *
  1324. X*                                                                          *
  1325. X*      This function reads  data from the buffer to the "file." Reads up   *
  1326. X*      to 65535 bytes (max unsigned int on a 16-bit machine) are allowed.  *
  1327. X*                                                                          *
  1328. X*   ENTRY:                                                                 *
  1329. X*                                                                          *
  1330. X*      buffer - pointer to data buffer                                     *
  1331. X*      length - length of "read"                                           *
  1332. X*      lread  - pointer to unsigned in which to return bytes actually read *
  1333. X*                                                                          *
  1334. X*   EXIT:                                                                  *
  1335. X*                                                                          *
  1336. X*      Returns an error/status code.                                       *
  1337. X*                                                                          *
  1338. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1339. X*                                                                          *
  1340. X*      Must call mf_open() and mf_reset() before this function.            *
  1341. X*                                                                          *
  1342. X***************************************************************************/
  1343. XULONG
  1344. X#ifdef ___STDC__
  1345. Xmf_read(UCHAR *buffer, unsigned int length, unsigned int *lread)
  1346. X#else
  1347. Xmf_read(buffer, length, lread)
  1348. XUCHAR *buffer;
  1349. Xunsigned int length;
  1350. Xunsigned int *lread;
  1351. X#endif
  1352. X{
  1353. X    ULONG copylen;
  1354. X    UCHAR *source;
  1355. X    UCHAR *dest;
  1356. X#ifdef INT16
  1357. X    ULONG tempoff;
  1358. X    ULONG remlen;
  1359. X#endif
  1360. X
  1361. X    /* Check that we're open. */
  1362. X
  1363. X    if (openflag != STATE_ROPEN)
  1364. X    {
  1365. X        return MF_NOTOPEN_E;
  1366. X    }
  1367. X
  1368. X    *lread = 0;
  1369. X
  1370. X    /* First check memory. */
  1371. X
  1372. X    if (conmemptr != conmem)
  1373. X    {
  1374. X        /* 
  1375. X        ** Still down in memory, so copy out of there. Determine amount
  1376. X        ** to copy.
  1377. X        */
  1378. X
  1379. X        copylen = conmem - conmemptr;
  1380. X        copylen = ((copylen > length) ? length : copylen);
  1381. X
  1382. X        /* Do copy. */
  1383. X
  1384. X        source = (conmemhandle + conmemptr);
  1385. X        dest = buffer;
  1386. X        memcpy(dest, source, (unsigned int) copylen);
  1387. X
  1388. X        /* Decrease length, update buffer. */
  1389. X
  1390. X        length -= (unsigned int) copylen;
  1391. X        buffer += copylen;
  1392. X        *lread += (unsigned int) copylen;
  1393. X
  1394. X        /* Update conmemptr. */
  1395. X        conmemptr += copylen;
  1396. X    }
  1397. X
  1398. X    if (0 == length)
  1399. X    {
  1400. X        /* All done, return OK. */
  1401. X
  1402. X        return ST_SUCCESS;
  1403. X    }
  1404. X
  1405. X    /* Read rest from disk. */
  1406. X
  1407. X    if (dskmemptr != dskmem)
  1408. X    {
  1409. X        /* Determine amount to copy. */
  1410. X
  1411. X        copylen = dskmem - dskmemptr;
  1412. X        copylen = ((copylen > length) ? length : copylen);
  1413. X
  1414. X#ifdef INT16
  1415. X        /*
  1416. X        ** On a 16-bit machine, if copylen is more than 32767 (max positive
  1417. X        ** signed int), break up read into as many parts as necessary.
  1418. X        */
  1419. X
  1420. X        for (tempoff = 0, remlen = copylen; remlen > 32767; 
  1421. X             tempoff += 32767, remlen -= 32767)
  1422. X        {
  1423. X            if (fb_read(dskmemhandle, (buffer + tempoff), 32767) != 32767)
  1424. X            {
  1425. X                return fb_error;
  1426. X            }
  1427. X        }
  1428. X        if (remlen != 0)
  1429. X        {
  1430. X            if (fb_read(dskmemhandle, (buffer + tempoff), (int) remlen) !=
  1431. X                (int) remlen)
  1432. X            {
  1433. X                return fb_error;
  1434. X            }
  1435. X        }
  1436. X#else
  1437. X        /* On 32-bit machine, simply do copy. */
  1438. X
  1439. X        if (fb_read(dskmemhandle, buffer, (int) copylen) != (int) copylen)
  1440. X        {
  1441. X            return fb_error;
  1442. X        }
  1443. X#endif
  1444. X
  1445. X        /* Decrease length, update buffer. */
  1446. X
  1447. X        length -= (unsigned int) copylen;
  1448. X        buffer += copylen;
  1449. X        *lread += (unsigned int) copylen;
  1450. X
  1451. X        /* Update dskmemptr. */
  1452. X
  1453. X        dskmemptr += copylen;
  1454. X    }
  1455. X
  1456. X    /* If length is 0, all done, return OK; otherwise hit EOF */
  1457. X
  1458. X    return ((0 == length) ? ST_SUCCESS : MF_EOF_W);
  1459. X} /* end of mf_read() */
  1460. X
  1461. X
  1462. X/***************************************************************************
  1463. X*   FUNCTION:    mf_close                                                  *
  1464. X*                                                                          *
  1465. X*   DESCRIPTION:                                                           *
  1466. X*                                                                          *
  1467. X*      Closes a "file". Must be called before mf_open() is called again.   *
  1468. X*                                                                          *
  1469. X*   ENTRY:                                                                 *
  1470. X*                                                                          *
  1471. X*      None.                                                               *
  1472. X*                                                                          *
  1473. X*   EXIT:                                                                  *
  1474. X*                                                                          *
  1475. X*      Returns an error/status code.                                       *
  1476. X*                                                                          *
  1477. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1478. X*                                                                          *
  1479. X***************************************************************************/
  1480. XULONG 
  1481. Xmf_close()
  1482. X{
  1483. X    ULONG status;
  1484. X
  1485. X    /* Check for open. */
  1486. X
  1487. X    if (STATE_CLOSED == openflag)
  1488. X    {
  1489. X        return MF_NOTOPEN_E;
  1490. X    }
  1491. X
  1492. X    /* Do cleanup. */
  1493. X
  1494. X    status = cleanup();
  1495. X
  1496. X    /* Reset status. */
  1497. X
  1498. X    openflag = STATE_CLOSED;
  1499. X
  1500. X    return status;
  1501. X} /* end of mf_close() */
  1502. X
  1503. X
  1504. X/***************************************************************************
  1505. X*   FUNCTION: mf_errstring                                                 *
  1506. X*                                                                          *
  1507. X*   DESCRIPTION:                                                           *
  1508. X*                                                                          *
  1509. X*       Returns a string corresponding to the given error.                 *
  1510. X*                                                                          *
  1511. X*   ENTRY:                                                                 *
  1512. X*                                                                          *
  1513. X*       errcode - error code to be translated                              *
  1514. X*                                                                          *
  1515. X*   EXIT:                                                                  *
  1516. X*                                                                          *
  1517. X*       Returns a pointer to the appropriate string, or NULL if there is   *
  1518. X*       no appropriate string.                                             *
  1519. X*                                                                          *
  1520. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1521. X*                                                                          *
  1522. X***************************************************************************/
  1523. Xchar *
  1524. X#ifdef __STDC__
  1525. Xmf_errstring(ULONG errcode)
  1526. X#else
  1527. Xmf_errstring(errcode)
  1528. XULONG errcode;
  1529. X#endif
  1530. X{
  1531. X    char *temp;
  1532. X    static char msg[80];
  1533. X
  1534. X    /* If not an MF module error code, return NULL. */
  1535. X
  1536. X    if (MODULE(errcode) != MODULE(MF_MODULE))
  1537. X    {
  1538. X        return NULL;
  1539. X    }
  1540. X
  1541. X    /* Process by code. */
  1542. X    switch (ERRSEV(errcode))
  1543. X    {
  1544. X        case ERRSEV(MF_EOF_W):
  1545. X            temp = "End of file.";
  1546. X            break;
  1547. X
  1548. X        case ERRSEV(MF_REOPEN_E):
  1549. X            temp = "Attempting to open memory file while already open.";
  1550. X            break;
  1551. X        case ERRSEV(MF_DISKERROR_E):
  1552. X            temp = "Critical error in disk management routines.";
  1553. X            break;
  1554. X        case ERRSEV(MF_NOSPACE_E):
  1555. X            temp = "Not enough space for temporary storage.";
  1556. X            break;
  1557. X        case ERRSEV(MF_NOTOPEN_E):
  1558. X            temp = "Memory file has not been opened.";
  1559. X            break;
  1560. X        case ERRSEV(MF_MALLOC_E):
  1561. X            temp = "Unable to allocate control structures.";
  1562. X            break;
  1563. X
  1564. X        case ERRSEV(MF_BUG_F):
  1565. X            temp = "This shouldn't happen.";
  1566. X            break;
  1567. X        case ERRSEV(MF_OVERFLOW_F):
  1568. X            temp =
  1569. X               "Attempt to access beyond end of allocated space.";
  1570. X            break;
  1571. X
  1572. X        default:
  1573. X            temp = NULL;
  1574. X    }
  1575. X
  1576. X    return temp;
  1577. X} /* end of mf_errstring() */
  1578. X
  1579. X
  1580. X/***************************************************************************
  1581. X*   FUNCTION:    cleanup  STATIC                                           *
  1582. X*                                                                          *
  1583. X*   DESCRIPTION:                                                           *
  1584. X*                                                                          *
  1585. X*      This function frees memory and deletes temporary files.             *
  1586. X*                                                                          *
  1587. X*   ENTRY:                                                                 *
  1588. X*                                                                          *
  1589. X*      type - indicates whether to clean up disk or not                    *
  1590. X*                                                                          *
  1591. X*   EXIT:                                                                  *
  1592. X*                                                                          *
  1593. X*      Returns an error/status code.                                       *
  1594. X*                                                                          *
  1595. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1596. X*                                                                          *
  1597. X***************************************************************************/
  1598. Xstatic ULONG
  1599. Xcleanup()
  1600. X{
  1601. X    ULONG status = 0;
  1602. X
  1603. X    /* If any memory allocated, free it. */
  1604. X
  1605. X    if (conmem != 0)
  1606. X    {
  1607. X        free(conmemhandle);
  1608. X    }
  1609. X
  1610. X    /*
  1611. X    ** If a temporary file is in use, close it. Also delete it unless it 
  1612. X    ** is locked.
  1613. X    */
  1614. X
  1615. X    if (dskmem != 0)
  1616. X    {
  1617. X        status = fb_close(dskmemhandle);
  1618. X        if (0 == mf_locked)
  1619. X        {
  1620. X            if (unlink(dskmemname) == -1)
  1621. X            {
  1622. X                status = MF_DISKERROR_E;
  1623. X            }
  1624. X        }
  1625. X    }
  1626. X
  1627. X    return status;
  1628. X} /* end of static cleanup() */
  1629. X
  1630. END_OF_FILE
  1631.   if test 24264 -ne `wc -c <'src/mf.c'`; then
  1632.     echo shar: \"'src/mf.c'\" unpacked with wrong size!
  1633.   fi
  1634.   # end of 'src/mf.c'
  1635. fi
  1636. echo shar: End of archive 15 \(of 18\).
  1637. cp /dev/null ark15isdone
  1638. MISSING=""
  1639. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
  1640.     if test ! -f ark${I}isdone ; then
  1641.     MISSING="${MISSING} ${I}"
  1642.     fi
  1643. done
  1644. if test "${MISSING}" = "" ; then
  1645.     echo You have unpacked all 18 archives.
  1646.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1647. else
  1648.     echo You still must unpack the following archives:
  1649.     echo "        " ${MISSING}
  1650. fi
  1651. exit 0
  1652. exit 0 # Just in case...
  1653.