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

  1. Newsgroups: comp.sources.misc
  2. From: jwbirdsa@picarefy.picarefy.com (James W. Birdsall)
  3. Subject: v36i076:  chiaro - Image Utilities, Part06/18
  4. Message-ID: <1993Mar25.181105.20262@sparky.imd.sterling.com>
  5. X-Md4-Signature: 7381dd77afba41ed385c9cf7145d4b09
  6. Date: Thu, 25 Mar 1993 18:11:05 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 76
  11. Archive-name: chiaro/part06
  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/gld.c src/tga.c
  19. # Wrapped by kent@sparky on Thu Mar 25 11:20:03 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 6 (of 18)."'
  23. if test -f 'src/gld.c' -a "${1}" != "-c" ; then 
  24.   echo shar: Will not clobber existing file \"'src/gld.c'\"
  25. else
  26.   echo shar: Extracting \"'src/gld.c'\" \(40825 characters\)
  27.   sed "s/^X//" >'src/gld.c' <<'END_OF_FILE'
  28. X/***************************************************************************
  29. X*   GLD.C                                                                  *
  30. X*   MODULE:  GIF/LZW decode                                                *
  31. X*   OS:      UNIX                                                          *
  32. X*                                                                          *
  33. X*   Copyright (c) 1992 James W. Birdsall. All Rights Reserved.             *
  34. X*                                                                          *
  35. X*   GIF copyright CompuServe etc.                                          *
  36. X*                                                                          *
  37. X*   $Id: gld.c,v 1.5 1993/03/02 00:54:20 jwbirdsa Exp $
  38. X*                                                                          *
  39. X*   This is the LZW decompressor for GIF images.                           *
  40. X*                                                                          *
  41. X*       gld_init      - initializes the decompressor for a new image       *
  42. X*       gld_process   - processes a block of data bytes                    *
  43. X*       gld_errstring - converts GLD module error code to message string   *
  44. X*                                                                          *
  45. X***************************************************************************/
  46. X
  47. X#include "config.h"
  48. X
  49. X/*
  50. X** system includes <>
  51. X*/
  52. X
  53. X#include <stdio.h>
  54. X#ifndef NO_STDLIB
  55. X#include <stdlib.h>
  56. X#endif
  57. X#ifndef NO_MEMOP
  58. X#include <memory.h>
  59. X#endif
  60. X
  61. X
  62. X/*
  63. X** custom includes ""
  64. X*/
  65. X
  66. X#include "depend.h"
  67. X
  68. X#include "gld.h"
  69. X
  70. X
  71. X/*
  72. X** local #defines
  73. X*/
  74. X
  75. X/* Indicators for special codes. */
  76. X
  77. X#define CLEARCODE          -1
  78. X#define EOICODE            -2
  79. X#define BADCODE            -3
  80. X
  81. X/* Convert a bit offset to a byte offset. */
  82. X
  83. X#define BIT2IND(x)         ((x) >> 3)
  84. X
  85. X/* Round bit offset down to nearest byte boundary. */
  86. X
  87. X#define CHROUND(x)         ((x) & 0xFFF8)
  88. X
  89. X/* Size of the internal handoff buffer. */
  90. X
  91. X#define HANDBUFSIZ         640
  92. X
  93. X/* Default number of hops to allow before expanding into holding buffer. */
  94. X
  95. X#define DEFAULT_HOPS       4
  96. X
  97. X
  98. X/*
  99. X** misc: copyright strings, version macros, etc.
  100. X*/
  101. X
  102. X/*
  103. X** typedefs
  104. X*/
  105. X
  106. X/*
  107. X** global variables
  108. X*/
  109. X
  110. X/* Controls how many hops to allow before expanding into holding buffer. */
  111. X
  112. Xunsigned int gld_hopsmax = DEFAULT_HOPS;
  113. X
  114. X/* Statistics on decompression process. */
  115. X
  116. Xunsigned int gld_holdmax;
  117. XULONG gld_codes;
  118. XUCHAR gld_indused[256];
  119. Xunsigned int gld_colors;
  120. Xunsigned int gld_clears;
  121. XULONG gld_pixout;
  122. X
  123. X
  124. X/*
  125. X** static globals
  126. X*/
  127. X
  128. X/* Initial and current code size, in bits. */
  129. X
  130. Xstatic int init_codesize;
  131. Xstatic int cur_codesize;
  132. X
  133. X/* Index in code table for next new code. */
  134. X
  135. Xstatic int newcodeindex;
  136. X
  137. X/* Flag to stop adding to code table. */
  138. X
  139. Xstatic int stop_adding = 0;
  140. X
  141. X/* The code table itself. */
  142. X
  143. Xstatic codeinfo *codetable;
  144. X
  145. X/* Store bits from previous data block in codebuf; valid when bufvalid != 0. */
  146. X
  147. Xstatic int bufvalid = 0;
  148. Xstatic unsigned int codebuf;
  149. X
  150. X/* Previous code. */
  151. X
  152. Xstatic unsigned int oldcode;
  153. X
  154. X/* The highest code table entry which is a root entry. */
  155. X
  156. Xstatic unsigned int maxroot;
  157. X
  158. X/* Final output buffer pointer, length, and position in buffer. */
  159. X
  160. Xstatic UCHAR *finbuf;
  161. Xstatic long finbuflen;
  162. Xstatic long finalpos;
  163. X
  164. X/* Callback function for when final buffer is full, EOI, end of block, etc. */
  165. X
  166. X#ifdef __STDC__
  167. Xstatic VOID (*finalcall)(long, UCHAR **, long *, long *);
  168. X#else
  169. Xstatic VOID (*finalcall)();
  170. X#endif
  171. X
  172. X#ifndef MINIMAL
  173. X/* Internal handoff buffer to increase performance. */
  174. X
  175. Xstatic UCHAR hndbuf[HANDBUFSIZ];
  176. Xstatic int hndbufind = 0;
  177. X#endif
  178. X
  179. X/* Holding buffer pointer, length, and next free position in buffer. */
  180. X
  181. Xstatic UCHAR *hldbuf;
  182. Xstatic unsigned int hldbuflen;
  183. Xstatic unsigned int hldbufhi = 0;
  184. X
  185. X
  186. Xstatic char CONST rcsid[] = "$Id: gld.c,v 1.5 1993/03/02 00:54:20 jwbirdsa Exp $";
  187. X
  188. X
  189. X/*
  190. X** function prototypes
  191. X*/
  192. X
  193. X#ifdef __STDC__
  194. X# define P_(s) s
  195. X#else
  196. X# define P_(s) ()
  197. X#endif
  198. X
  199. Xstatic ULONG proc_code P_((unsigned int code));
  200. X
  201. X#ifndef MINIMAL
  202. Xstatic ULONG extract P_((unsigned int code, UCHAR *firstout));
  203. X
  204. Xstatic VOID handchar P_((UCHAR c));
  205. Xstatic VOID flushhand();
  206. Xstatic VOID handoff P_((UCHAR *input, unsigned int inlen));
  207. Xstatic VOID dohand P_((UCHAR *input, unsigned int inlen));
  208. X#endif
  209. X
  210. Xstatic ULONG reinit();
  211. X
  212. X#undef P_
  213. X
  214. X
  215. X/*
  216. X** functions
  217. X*/
  218. X
  219. X
  220. X/***************************************************************************
  221. X*   FUNCTION: GLD_INIT                                                     *
  222. X*                                                                          *
  223. X*   DESCRIPTION:                                                           *
  224. X*                                                                          *
  225. X*       Initializes decompressor for next image. Must be called between    *
  226. X*       images.                                                            *
  227. X*                                                                          *
  228. X*   ENTRY:                                                                 *
  229. X*                                                                          *
  230. X*       min_codesize - the starting code size                              *
  231. X*       truebits     - the actual number of bits/pixel (needed to          *
  232. X*                      distinguish between 2 colors and 4, both of which   *
  233. X*                      have codesize of 2)                                 *
  234. X*       table        - pointer to code table                               *
  235. X*       savebuf      - pointer to holding buffer                           *
  236. X*       savebufsiz   - size of holding buffer attached to code table       *
  237. X*                                                                          *
  238. X*   EXIT:                                                                  *
  239. X*                                                                          *
  240. X*       Returns an error/status code.                                      *
  241. X*                                                                          *
  242. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  243. X*                                                                          *
  244. X***************************************************************************/
  245. XULONG
  246. X#ifdef __STDC__
  247. Xgld_init(int min_codesize, int truebits, codeinfo *table, UCHAR *savebuf,
  248. X         unsigned int savebufsiz)
  249. X#else
  250. Xgld_init(min_codesize, truebits, table, savebuf, savebufsiz)
  251. Xint min_codesize;
  252. Xint truebits;
  253. Xcodeinfo *table;
  254. XUCHAR *savebuf;
  255. Xunsigned int savebufsiz;
  256. X#endif
  257. X{
  258. X    int loop;
  259. X
  260. X    /* Store codesize. */
  261. X
  262. X    init_codesize = min_codesize + 1;
  263. X
  264. X    /* Store table pointer. */
  265. X
  266. X    codetable = table;
  267. X
  268. X    /* Initialize decode table. */
  269. X
  270. X    for (loop = 0; loop < (0x1 << min_codesize); loop++)
  271. X    {
  272. X        codetable[loop].stringlen = 1;
  273. X        codetable[loop].firstchar = (UCHAR) loop;
  274. X        codetable[loop].lastchar = (UCHAR) loop;
  275. X    }
  276. X    codetable[loop].stringlen = CLEARCODE;
  277. X    codetable[(loop + 1)].stringlen = EOICODE;
  278. X
  279. X    /* If truebits == 1, then codes 2 and 3 are bad. */
  280. X
  281. X    if (truebits == 1)
  282. X    {
  283. X        codetable[2].stringlen = BADCODE;
  284. X        codetable[3].stringlen = BADCODE;
  285. X    }
  286. X
  287. X    /* Set max root size. */
  288. X
  289. X    maxroot = (0x1 << truebits) - 1;
  290. X
  291. X    /* Reset global variables. */
  292. X
  293. X    hldbuflen = savebufsiz;
  294. X    hldbuf = savebuf;
  295. X    bufvalid = 0;
  296. X    gld_holdmax = 0;
  297. X    gld_codes = 0;
  298. X    for (loop = 0; loop < 256; loop++)
  299. X    {
  300. X        gld_indused[loop] = 0;
  301. X    }
  302. X    gld_colors = 0;
  303. X    gld_clears = 0;
  304. X    gld_pixout = 0;
  305. X
  306. X    /* Initialize position in final output buffer. */
  307. X
  308. X    finalpos = 0;
  309. X
  310. X    /* Finish initialization and return. */
  311. X
  312. X    return (reinit());
  313. X} /* end of gld_init() */
  314. X
  315. X
  316. X/***************************************************************************
  317. X*   FUNCTION: GLD_PROCESS                                                  *
  318. X*                                                                          *
  319. X*   DESCRIPTION:                                                           *
  320. X*                                                                          *
  321. X*       Processes a block of packed codes.                                 *
  322. X*                                                                          *
  323. X*   ENTRY:                                                                 *
  324. X*                                                                          *
  325. X*       length   - length in bytes of code block                           *
  326. X*       codes    - pointer to code block                                   *
  327. X*       buffer   - pointer to final output buffer                          *
  328. X*       buflen   - length of final output buffer                           *
  329. X*       callback - pointer to callback function                            *
  330. X*                                                                          *
  331. X*   EXIT:                                                                  *
  332. X*                                                                          *
  333. X*       Returns an error/status code.                                      *
  334. X*                                                                          *
  335. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  336. X*                                                                          *
  337. X***************************************************************************/
  338. XULONG
  339. X#ifdef __STDC__
  340. Xgld_process(int length, UCHAR *codes, UCHAR *buffer, long buflen,
  341. X            VOID (*callback)(long, UCHAR **, long *, long *))
  342. X#else
  343. Xgld_process(length, codes, buffer, buflen, callback)
  344. Xint length;
  345. XUCHAR *codes;
  346. XUCHAR *buffer;
  347. Xlong buflen;
  348. XVOID (*callback)();
  349. X#endif
  350. X{
  351. X    unsigned int curcode;
  352. X    unsigned int mask;
  353. X    unsigned int temp;
  354. X    int bitindex;
  355. X    int bitoffset;
  356. X    int bitsgot;
  357. X    ULONG status;
  358. X
  359. X    /* Set up. */
  360. X
  361. X    bitindex = 0;
  362. X    finbuf = buffer;
  363. X    finbuflen = buflen;
  364. X    finalcall = callback;
  365. X
  366. X    /* If leftover bits, use them first. */
  367. X
  368. X    if (bufvalid != 0)
  369. X    {
  370. X        /* Get bits into curcode. */
  371. X
  372. X        curcode = codebuf;
  373. X        bitsgot = bufvalid;
  374. X
  375. X        /* Extract more bits from codes array. */
  376. X
  377. X        if ((cur_codesize - bitsgot) >= 8)
  378. X        {
  379. X            temp = (unsigned int) codes[0];
  380. X            temp <<= bitsgot;
  381. X            curcode |= temp;
  382. X            bitsgot += 8;
  383. X            bitindex = 8;
  384. X        }
  385. X        if (bitsgot != cur_codesize)
  386. X        {
  387. X            bitoffset = cur_codesize - bitsgot;
  388. X            mask = (0x1 << bitoffset) - 1;
  389. X            temp = mask & ((unsigned int) codes[BIT2IND(bitindex)]);
  390. X            temp <<= bitsgot;
  391. X            curcode |= temp;
  392. X            bitindex += bitoffset;
  393. X        }
  394. X
  395. X        /* Process the code. */
  396. X
  397. X        if (SUCCESS(status = proc_code(curcode)) != ST_SUCCESS)
  398. X        {
  399. X            return status;
  400. X        }
  401. X
  402. X        /* Check for end of info. */
  403. X
  404. X        if (status == GLD_EOI_S)
  405. X        {
  406. X#ifndef MINIMAL
  407. X            /* Force a callback. */
  408. X
  409. X            flushhand();
  410. X#endif
  411. X
  412. X            /* All done with this image. */
  413. X
  414. X            return GLD_EOI_S;
  415. X        }
  416. X
  417. X        /* Reset bufvalid. */
  418. X
  419. X        bufvalid = 0;
  420. X    }
  421. X
  422. X    /* Now process rest of codes array. */
  423. X
  424. X    while (1)
  425. X    {
  426. X        /* Check for overflow. */
  427. X
  428. X        if ((bitindex + cur_codesize - 1) >= (length * 8))
  429. X        {
  430. X            /* Get number of leftover bits. */
  431. X
  432. X            temp = (length * 8) - bitindex;
  433. X            if (temp == 0)
  434. X            {
  435. X                /* If no leftovers, break out of loop now. */
  436. X
  437. X                codebuf = 0;
  438. X                bufvalid = 0;
  439. X                break;
  440. X            }
  441. X
  442. X            /* Store whatever bits are left over in codebuf. */
  443. X
  444. X            bitoffset = bitindex - CHROUND(bitindex);
  445. X            codebuf = ((unsigned int) codes[BIT2IND(bitindex)]) >> bitoffset;
  446. X            bufvalid = 8 - bitoffset;
  447. X            temp -= bufvalid;
  448. X            if (temp != 0)
  449. X            {
  450. X                temp = (unsigned int) codes[BIT2IND(bitindex) + 1];
  451. X                temp <<= bufvalid;
  452. X                codebuf |= temp;
  453. X                bufvalid += 8;
  454. X            }
  455. X
  456. X            /* Break out of loop. */
  457. X
  458. X            break;
  459. X        }
  460. X
  461. X        /* Extract next code. */
  462. X
  463. X        bitoffset = bitindex - CHROUND(bitindex);
  464. X        curcode = ((unsigned int) codes[BIT2IND(bitindex)]) >> bitoffset;
  465. X        bitsgot = 8 - bitoffset;
  466. X        if (bitsgot > cur_codesize)
  467. X        {
  468. X            mask = (0x1 << cur_codesize) - 1;
  469. X            curcode &= mask;
  470. X            bitsgot = cur_codesize;
  471. X        }
  472. X        bitindex += bitsgot;
  473. X
  474. X        if ((cur_codesize - bitsgot) >= 8)
  475. X        {
  476. X            temp = (unsigned int) codes[BIT2IND(bitindex)];
  477. X            temp <<= bitsgot;
  478. X            curcode |= temp;
  479. X            bitsgot += 8;
  480. X            bitindex += 8;
  481. X        }
  482. X
  483. X        if (bitsgot != cur_codesize)
  484. X        {
  485. X            bitoffset = cur_codesize - bitsgot;
  486. X            mask = (0x1 << bitoffset) - 1;
  487. X            temp = ((unsigned int) codes[BIT2IND(bitindex)]) & mask;
  488. X            temp <<= bitsgot;
  489. X            curcode |= temp;
  490. X            bitsgot = cur_codesize;
  491. X            bitindex += bitoffset;
  492. X        }
  493. X
  494. X        /* Process the code. */
  495. X
  496. X        if (SUCCESS(status = proc_code(curcode)) != ST_SUCCESS)
  497. X        {
  498. X            return status;
  499. X        }
  500. X
  501. X        /* Check for end of info. */
  502. X
  503. X        if (status == GLD_EOI_S)
  504. X        {
  505. X#ifndef MINIMAL
  506. X            /* Force a callback. */
  507. X
  508. X            flushhand();
  509. X#endif
  510. X
  511. X            /* All done with this image. */
  512. X
  513. X            return GLD_EOI_S;
  514. X        }
  515. X
  516. X        /* Otherwise do it all again. */
  517. X    }
  518. X
  519. X    /* If we got this far, must be OK. */
  520. X
  521. X#ifndef MINIMAL
  522. X    /* Force a callback. */
  523. X
  524. X    flushhand();
  525. X#endif
  526. X
  527. X    return ST_SUCCESS;
  528. X} /* end of gld_process() */
  529. X
  530. X
  531. X/***************************************************************************
  532. X*   FUNCTION: gld_errstring                                                *
  533. X*                                                                          *
  534. X*   DESCRIPTION:                                                           *
  535. X*                                                                          *
  536. X*      Returns a string corresponding to an error code.                    *
  537. X*                                                                          *
  538. X*   ENTRY:                                                                 *
  539. X*                                                                          *
  540. X*      errcode - error code to be translated                               *
  541. X*                                                                          *
  542. X*   EXIT:                                                                  *
  543. X*                                                                          *
  544. X*      Returns a pointer to the appropriate string, or NULL if there is    *
  545. X*      no appropriate string.                                              *
  546. X*                                                                          *
  547. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  548. X*                                                                          *
  549. X***************************************************************************/
  550. Xchar *
  551. X#ifdef __STDC__
  552. Xgld_errstring(ULONG errcode)
  553. X#else
  554. Xgld_errstring(errcode)
  555. XULONG errcode;
  556. X#endif
  557. X{
  558. X    char *temp;
  559. X
  560. X    /* If error code not from this module, return NULL. */
  561. X
  562. X    if (MODULE(errcode) != MODULE(GLD_MODULE))
  563. X    {
  564. X        return NULL;
  565. X    }
  566. X
  567. X    /* Process by code. */
  568. X
  569. X    switch (ERRSEV(errcode))
  570. X    {
  571. X        case ERRSEV(GLD_EOI_S):
  572. X            temp = "End of Information code found.";
  573. X            break;
  574. X        case ERRSEV(GLD_CLEARED_S):
  575. X            temp = "Code table cleared.";
  576. X            break;
  577. X
  578. X        case ERRSEV(GLD_NOMEM_E):
  579. X            temp = "Could not allocate memory in GLD module.";
  580. X            break;
  581. X        case ERRSEV(GLD_BADHOLDSIZE_E):
  582. X            temp = "Size of code table + holding buffer exceeds 64K.";
  583. X            break;
  584. X
  585. X        case ERRSEV(GLD_BADCODE_F):
  586. X            temp = "Bad code found in codestream.";
  587. X            break;
  588. X        case ERRSEV(GLD_BUG_F):
  589. X            temp = "Internal error. Should never happen.";
  590. X            break;
  591. X        case ERRSEV(GLD_LENOVERFLOW_F):
  592. X            temp = "The string expansion of a code is > 32767 bytes.";
  593. X            break;
  594. X
  595. X        default:
  596. X            temp = NULL;
  597. X            break;
  598. X    }
  599. X
  600. X    return temp;
  601. X} /* end of gld_errstring() */
  602. X
  603. X
  604. X/***************************************************************************
  605. X*   FUNCTION: PROC_CODE  (STATIC)                                          *
  606. X*                                                                          *
  607. X*   DESCRIPTION:                                                           *
  608. X*                                                                          *
  609. X*       Processes a single code.                                           *
  610. X*                                                                          *
  611. X*   ENTRY:                                                                 *
  612. X*                                                                          *
  613. X*       code - code to be processed                                        *
  614. X*                                                                          *
  615. X*   EXIT:                                                                  *
  616. X*                                                                          *
  617. X*       Returns an error/status code.                                      *
  618. X*                                                                          *
  619. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  620. X*                                                                          *
  621. X***************************************************************************/
  622. Xstatic ULONG 
  623. X#ifdef __STDC__
  624. Xproc_code(unsigned int code)
  625. X#else
  626. Xproc_code(code)
  627. Xunsigned int code;
  628. X#endif
  629. X{
  630. X    codeinfo *entry;
  631. X    codeinfo *tracer;
  632. X#ifndef MINIMAL
  633. X    ULONG status;
  634. X    UCHAR firstout;
  635. X#endif
  636. X
  637. X
  638. X#ifdef CODE_CHECK
  639. X    printf("%u\n", code);
  640. X#endif
  641. X
  642. X    /* Increment counter. */
  643. X
  644. X    gld_codes++;
  645. X
  646. X    /*
  647. X    ** CHECK CODE
  648. X    ** While it is possible to get codes that are not in the string
  649. X    ** table, such codes will never be more than (maximum_valid_code + 1).
  650. X    ** Since newcodeindex is (maximum_valid_code + 1), if code is <=
  651. X    ** newcodeindex, we're OK; otherwise, error.
  652. X    */
  653. X
  654. X    if (code > newcodeindex)
  655. X    {
  656. X        /* Bad code! */
  657. X
  658. X        return GLD_BADCODE_F;
  659. X    }
  660. X
  661. X    /* Extract entry from codetable. */
  662. X
  663. X    entry = (codetable + code);
  664. X
  665. X    /* Check for other special-function codes. */
  666. X
  667. X    if (entry->stringlen == CLEARCODE)
  668. X    {
  669. X        /* Clear code table. */
  670. X
  671. X        gld_clears++;
  672. X        reinit();
  673. X        return GLD_CLEARED_S;
  674. X    }
  675. X    if (entry->stringlen == EOICODE)
  676. X    {
  677. X        return GLD_EOI_S;
  678. X    }
  679. X
  680. X    /* Check code again. */
  681. X
  682. X    if (entry->stringlen == BADCODE)
  683. X    {
  684. X        return GLD_BADCODE_F;
  685. X    }
  686. X    if (entry->stringlen < 0)
  687. X    {
  688. X        return GLD_LENOVERFLOW_F;
  689. X    }
  690. X
  691. X#ifndef MINIMAL
  692. X    /* OK, is code in string table? */
  693. X
  694. X    if (code < newcodeindex)
  695. X    {
  696. X        /* It is, call extract() on it. */
  697. X
  698. X        if (SUCCESS(status = extract(code, &firstout)) != ST_SUCCESS)
  699. X        {
  700. X            return status;
  701. X        }
  702. X    }
  703. X    else
  704. X    {
  705. X        /* Not in table, output string for oldcode. */
  706. X
  707. X        if (SUCCESS(status = extract(oldcode, &firstout)) != ST_SUCCESS)
  708. X        {
  709. X            return status;
  710. X        }
  711. X
  712. X        /* Then re-output first character */
  713. X
  714. X        handchar(firstout);
  715. X    }
  716. X#endif
  717. X
  718. X    /* Mark use tables. */
  719. X
  720. X    if (code <= maxroot)
  721. X    {
  722. X        if (gld_indused[code] == 0)
  723. X        {
  724. X            gld_colors++;
  725. X            gld_indused[code] = 1;
  726. X        }
  727. X    }
  728. X
  729. X    /* Add to the string table, maybe. */
  730. X
  731. X    if ((oldcode != (unsigned int) BADCODE) &&
  732. X        (oldcode != (unsigned int) EOICODE) &&
  733. X        (oldcode != (unsigned int) CLEARCODE) &&
  734. X        (stop_adding == 0))
  735. X    {
  736. X        entry = (codetable + newcodeindex++);
  737. X        tracer = (codetable + oldcode);
  738. X
  739. X        /* Update codesize. */
  740. X
  741. X        if (newcodeindex == (0x1 << cur_codesize))
  742. X        {
  743. X            if (cur_codesize == MAXCODEBITS)
  744. X            {
  745. X                stop_adding = 1;
  746. X            }
  747. X            else
  748. X            {
  749. X                cur_codesize++;
  750. X                stop_adding = 0;
  751. X            }
  752. X        }
  753. X        entry->stringlen = tracer->stringlen + 1;
  754. X        if (entry->stringlen < 0)
  755. X        {
  756. X            return GLD_LENOVERFLOW_F;
  757. X        }
  758. X#ifndef MINIMAL
  759. X        entry->firstchar = tracer->firstchar;
  760. X        entry->lastchar = firstout;
  761. X
  762. X        switch (entry->stringlen)
  763. X        {
  764. X            case 3:
  765. X                entry->pb.buf[0] = tracer->lastchar;
  766. X                break;
  767. X
  768. X            case 4:
  769. X                entry->pb.buf[0] = tracer->pb.buf[0];
  770. X                entry->pb.buf[1] = tracer->lastchar;
  771. X                break;
  772. X
  773. X            default:
  774. X                entry->pb.prevind = oldcode;
  775. X                break;
  776. X        }
  777. X#endif
  778. X    }
  779. X
  780. X    /* Add length of this string to total output length. */
  781. X
  782. X    entry = (codetable + code);
  783. X    gld_pixout += entry->stringlen;
  784. X
  785. X    /* Update oldcode. */
  786. X
  787. X    oldcode = code;
  788. X
  789. X    /* Return OK. */
  790. X
  791. X    return ST_SUCCESS;
  792. X} /* end of static proc_code() */
  793. X
  794. X
  795. X#ifndef MINIMAL
  796. X
  797. X/***************************************************************************
  798. X*   FUNCTION: EXTRACT  (STATIC)                                            *
  799. X*                                                                          *
  800. X*   DESCRIPTION:                                                           *
  801. X*                                                                          *
  802. X*       Actually decompresses the code by extracting the expansion from    *
  803. X*       the code table.                                                    *
  804. X*                                                                          *
  805. X*   ENTRY:                                                                 *
  806. X*                                                                          *
  807. X*       code     - code to be processed                                    *
  808. X*       firstout - pointer to unsigned char in which the first character   *
  809. X*                  of the code extracted is returned                       *
  810. X*                                                                          *
  811. X*   EXIT:                                                                  *
  812. X*                                                                          *
  813. X*       Returns an error/status code.                                      *
  814. X*                                                                          *
  815. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  816. X*                                                                          *
  817. X***************************************************************************/
  818. Xstatic ULONG
  819. X#ifdef __STDC__
  820. Xextract(unsigned int code, UCHAR *firstout)
  821. X#else
  822. Xextract(code, firstout)
  823. Xunsigned int code;
  824. XUCHAR *firstout;
  825. X#endif
  826. X{
  827. X    codeinfo *entry;
  828. X    codeinfo *tracer;
  829. X    unsigned int index;
  830. X    UCHAR *temp;
  831. X    unsigned int localhops;
  832. X    UCHAR *trans;
  833. X    UCHAR *trans2;
  834. X    UCHAR tempbuf[4];
  835. X
  836. X    /* Set entry. */
  837. X
  838. X    entry = codetable + code;
  839. X
  840. X    /* Extract string. */
  841. X
  842. X    switch (entry->stringlen)
  843. X    {
  844. X        case 0:
  845. X            /* ERROR! */
  846. X            return GLD_BUG_F;
  847. X
  848. X        case 1:
  849. X            /* String is lastchar. */
  850. X            handchar(entry->lastchar);
  851. X            *firstout = entry->lastchar;
  852. X            break;
  853. X
  854. X        case 2:
  855. X            /* String is firstchar, lastchar. */
  856. X            handchar(entry->firstchar);
  857. X            *firstout = entry->firstchar;
  858. X            handchar(entry->lastchar);
  859. X            break;
  860. X
  861. X        case 3:
  862. X            /* String is firstchar, pb.buf[0], lastchar. */
  863. X            *firstout = tempbuf[0] = entry->firstchar;
  864. X            tempbuf[1] = entry->pb.buf[0];
  865. X            tempbuf[2] = entry->lastchar;
  866. X            handoff(tempbuf, 3);
  867. X            break;
  868. X
  869. X        case 4:
  870. X            /* String is firstchar, pb.buf[0], pb.buf[1], lastchar. */
  871. X            *firstout = tempbuf[0] = entry->firstchar;
  872. X            tempbuf[1] = entry->pb.buf[0];
  873. X            tempbuf[2] = entry->pb.buf[1];
  874. X            tempbuf[3] = entry->lastchar;
  875. X            handoff(tempbuf, 4);
  876. X            break;
  877. X
  878. X        default:
  879. X            /* Long string, have to get it the hard way. */
  880. X
  881. X            if (entry->pb.prevind > CODES)
  882. X            {
  883. X                /* Grab it out of memory, preassembled. */
  884. X
  885. X                handoff((hldbuf + (entry->pb.prevind - CODES - 1)),
  886. X                        entry->stringlen);
  887. X                *firstout = hldbuf[entry->pb.prevind - CODES - 1];
  888. X            }
  889. X            else
  890. X            {
  891. X                localhops = 0;
  892. X                tracer = entry;
  893. X                temp = (UCHAR *) malloc(entry->stringlen - 4);
  894. X                if (temp == (UCHAR *) NULL)
  895. X                {
  896. X                    return GLD_NOMEM_E;
  897. X                }
  898. X                for (index = entry->stringlen; index > 4; index--)
  899. X                {
  900. X                    /* Check for bad length. */
  901. X
  902. X                    if (tracer->stringlen != index)
  903. X                    {
  904. X                        /* Chain is corrupt! */
  905. X
  906. X                        return GLD_BUG_F;
  907. X                    }
  908. X
  909. X                    /* Get character. */
  910. X
  911. X                    temp[(index - 5)] = tracer->lastchar;
  912. X
  913. X                    /* Check for bad index. */
  914. X
  915. X                    if (tracer->pb.prevind >= newcodeindex)
  916. X                    {
  917. X                        if (tracer->pb.prevind > CODES)
  918. X                        {
  919. X                            /*
  920. X                            ** Chained back to another long one. First, hand
  921. X                            ** off stuff that is here.
  922. X                            */
  923. X
  924. X                            handoff((hldbuf + (tracer->pb.prevind - CODES - 1)),
  925. X                                    tracer->stringlen);
  926. X
  927. X                            /* 
  928. X                            ** Now hand off what's in temp. Use (index-4)
  929. X                            ** instead of (index-5) because the character
  930. X                            ** just transferred into temp[index-5] above
  931. X                            ** is also on the end of the buffer handed off
  932. X                            ** immediately above; hence we don't want to hand
  933. X                            ** it off again, so skip it by using (index-4).
  934. X                            */
  935. X
  936. X                            handoff((temp + (index - 4)),
  937. X                                    (entry->stringlen - index));
  938. X
  939. X                            /* Set firstout. */
  940. X
  941. X                            *firstout = hldbuf[tracer->pb.prevind - CODES - 1];
  942. X
  943. X                            /* Break out of loop. */
  944. X
  945. X                            break;
  946. X                        }
  947. X                        else
  948. X                        {
  949. X                            /* Chains to code not in table! */
  950. X
  951. X                            return GLD_BUG_F;
  952. X                        }
  953. X                    }
  954. X
  955. X                    /* Trace to previous entry. */
  956. X
  957. X                    tracer = (codetable + tracer->pb.prevind);
  958. X                    localhops++;
  959. X                }
  960. X
  961. X                /* If length is 4, need to extract from firstchar etc. */
  962. X
  963. X                if (tracer->stringlen == 4)
  964. X                {
  965. X                    /* Get the first four characters. */
  966. X
  967. X                    *firstout = tempbuf[0] = entry->firstchar;
  968. X                    tempbuf[1] = tracer->pb.buf[0];
  969. X                    tempbuf[2] = tracer->pb.buf[1];
  970. X                    tempbuf[3] = tracer->lastchar;
  971. X                    handoff(tempbuf, 4);
  972. X                    handoff(temp, (entry->stringlen - 4));
  973. X                }
  974. X
  975. X                /* Check number of hops required. */
  976. X
  977. X                if (localhops > gld_hopsmax)
  978. X                {
  979. X                    /* If too many, try to allocate holding space. */
  980. X
  981. X                    if ((hldbuflen - hldbufhi) >= entry->stringlen)
  982. X                    {
  983. X                        /*
  984. X                        ** Enough room, so allocate it and stick its offset
  985. X                        ** into entry->pb.prevind. Note that we can and do
  986. X                        ** use entry->pb.prevind directly, below, because
  987. X                        ** CODES+1 hasn't been added to it yet.
  988. X                        */
  989. X
  990. X                        entry->pb.prevind = hldbufhi;
  991. X                        hldbufhi += entry->stringlen;
  992. X                        gld_holdmax = max(gld_holdmax, hldbufhi);
  993. X
  994. X                        if (tracer->stringlen == 4)
  995. X                        {
  996. X                            /*
  997. X                            ** We ended at a short one, so copy stuff from
  998. X                            ** its various fields first, then memcpy() from
  999. X                            ** temp.
  1000. X                            */
  1001. X
  1002. X                            hldbuf[entry->pb.prevind] = tracer->firstchar;
  1003. X                            hldbuf[entry->pb.prevind + 1] = tracer->pb.buf[0];
  1004. X                            hldbuf[entry->pb.prevind + 2] = tracer->pb.buf[1];
  1005. X                            hldbuf[entry->pb.prevind + 3] = tracer->lastchar;
  1006. X                            trans = hldbuf + entry->pb.prevind + 4;
  1007. X                            memcpy(trans, temp, (entry->stringlen - 4));
  1008. X                        }
  1009. X                        else
  1010. X                        {
  1011. X                            /*
  1012. X                            ** We ended at a long one. So copy stuff from
  1013. X                            ** its holding buffer into ours, then finish
  1014. X                            ** up with whatever was in temp. Use (index-4)
  1015. X                            ** instead of (index-5) for same reasons as 
  1016. X                            ** discussed in comment above.
  1017. X                            */
  1018. X
  1019. X                            trans = hldbuf + (tracer->pb.prevind - CODES - 1);
  1020. X                            trans2 = hldbuf + entry->pb.prevind;
  1021. X                            memcpy(trans2, trans, tracer->stringlen);
  1022. X                            trans = (UCHAR *) (temp + (index - 4));
  1023. X                            trans2 = hldbuf + entry->pb.prevind +
  1024. X                                     tracer->stringlen;
  1025. X                            memcpy(trans2, trans, (entry->stringlen - index));
  1026. X                        }
  1027. X
  1028. X                        /*
  1029. X                        ** Add CODES+1 to prevind to distinguish it from
  1030. X                        ** table indices.
  1031. X                        */
  1032. X
  1033. X                        entry->pb.prevind += (CODES + 1);
  1034. X                    }
  1035. X                }
  1036. X                free(temp);
  1037. X            }
  1038. X            break;
  1039. X    }
  1040. X
  1041. X    return ST_SUCCESS;
  1042. X} /* end of static extract() */
  1043. X
  1044. X#endif /* !MINIMAL */
  1045. X
  1046. X
  1047. X/***************************************************************************
  1048. X*   FUNCTION: REINIT  (STATIC)                                             *
  1049. X*                                                                          *
  1050. X*   DESCRIPTION:                                                           *
  1051. X*                                                                          *
  1052. X*       Reinitializes the code table and other global variables.           *
  1053. X*                                                                          *
  1054. X*   ENTRY:                                                                 *
  1055. X*                                                                          *
  1056. X*       Nothing.                                                           *
  1057. X*                                                                          *
  1058. X*   EXIT:                                                                  *
  1059. X*                                                                          *
  1060. X*       Returns an error/status code.                                      *
  1061. X*                                                                          *
  1062. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1063. X*                                                                          *
  1064. X***************************************************************************/
  1065. Xstatic ULONG
  1066. X#ifdef __STDC__
  1067. Xreinit(VOID)
  1068. X#else
  1069. Xreinit()
  1070. X#endif
  1071. X{
  1072. X    int loop;
  1073. X
  1074. X    /* Reset code size. */
  1075. X
  1076. X    cur_codesize = init_codesize;
  1077. X
  1078. X    /* Reset new code index. */
  1079. X
  1080. X    newcodeindex = (0x1 << (init_codesize - 1)) + 2;
  1081. X
  1082. X    /* Reset all entries. */
  1083. X
  1084. X    for (loop = newcodeindex; loop < CODES; loop++)
  1085. X    {
  1086. X        codetable[loop].stringlen = 0;
  1087. X    }
  1088. X
  1089. X    /* Reset stop-adding-codes flag. */
  1090. X
  1091. X    stop_adding = 0;
  1092. X
  1093. X    /* Reset old code index. */
  1094. X
  1095. X    oldcode = BADCODE;
  1096. X
  1097. X    /* Reset holding buffer used. */
  1098. X
  1099. X    hldbufhi = 0;
  1100. X
  1101. X    return ST_SUCCESS;
  1102. X} /* end of static reinit() */
  1103. X
  1104. X
  1105. X#ifndef MINIMAL
  1106. X
  1107. X/***************************************************************************
  1108. X*   FUNCTION: HANDCHAR  (STATIC)                                           *
  1109. X*                                                                          *
  1110. X*   DESCRIPTION:                                                           *
  1111. X*                                                                          *
  1112. X*       Put a single char in the internal handoff buffer and flush if      *
  1113. X*       needed.                                                            *
  1114. X*                                                                          *
  1115. X*   ENTRY:                                                                 *
  1116. X*                                                                          *
  1117. X*       c - character to be placed in the handoff buffer                   *
  1118. X*                                                                          *
  1119. X*   EXIT:                                                                  *
  1120. X*                                                                          *
  1121. X*       Nothing.                                                           *
  1122. X*                                                                          *
  1123. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1124. X*                                                                          *
  1125. X***************************************************************************/
  1126. Xstatic VOID
  1127. X#ifdef __STDC__
  1128. Xhandchar(UCHAR c)
  1129. X#else
  1130. Xhandchar(c)
  1131. XUCHAR c;
  1132. X#endif
  1133. X{
  1134. X    hndbuf[hndbufind++] = c;
  1135. X
  1136. X    if (hndbufind == HANDBUFSIZ)
  1137. X    {
  1138. X        hndbufind = 0;
  1139. X        dohand(hndbuf, HANDBUFSIZ);
  1140. X    }
  1141. X
  1142. X    return;
  1143. X} /* end of static handchar() */
  1144. X
  1145. X
  1146. X/***************************************************************************
  1147. X*   FUNCTION: FLUSHHAND  (STATIC)                                          *
  1148. X*                                                                          *
  1149. X*   DESCRIPTION:                                                           *
  1150. X*                                                                          *
  1151. X*       Forces a flush of the internal handoff buffer and a call to the    *
  1152. X*       callback function.                                                 *
  1153. X*                                                                          *
  1154. X*   ENTRY:                                                                 *
  1155. X*                                                                          *
  1156. X*       Nothing.                                                           *
  1157. X*                                                                          *
  1158. X*   EXIT:                                                                  *
  1159. X*                                                                          *
  1160. X*       Nothing.                                                           *
  1161. X*                                                                          *
  1162. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1163. X*                                                                          *
  1164. X***************************************************************************/
  1165. Xstatic VOID
  1166. X#ifdef __STDC__
  1167. Xflushhand(VOID)
  1168. X#else
  1169. Xflushhand()
  1170. X#endif
  1171. X{
  1172. X    if (hndbufind != 0)
  1173. X    {
  1174. X        dohand(hndbuf, hndbufind);
  1175. X        hndbufind = 0;
  1176. X    }
  1177. X
  1178. X    (*finalcall)((finalpos + 1), &finbuf, &finbuflen, &finalpos);
  1179. X
  1180. X    return;
  1181. X} /* end of flushhand() */
  1182. X
  1183. X
  1184. X/***************************************************************************
  1185. X*   FUNCTION: HANDOFF  (STATIC)                                            *
  1186. X*                                                                          *
  1187. X*   DESCRIPTION:                                                           *
  1188. X*                                                                          *
  1189. X*       Places a block of characters in the internal handoff buffer and    *
  1190. X*       flushes if as necessary.                                           *
  1191. X*                                                                          *
  1192. X*   ENTRY:                                                                 *
  1193. X*                                                                          *
  1194. X*       input - pointer to block of characters to place in buffer          *
  1195. X*       inlen - length of block                                            *
  1196. X*                                                                          *
  1197. X*   EXIT:                                                                  *
  1198. X*                                                                          *
  1199. X*       Nothing.                                                           *
  1200. X*                                                                          *
  1201. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1202. X*                                                                          *
  1203. X***************************************************************************/
  1204. Xstatic VOID
  1205. X#ifdef __STDC__
  1206. Xhandoff(UCHAR *input, unsigned int inlen)
  1207. X#else
  1208. Xhandoff(input, inlen)
  1209. XUCHAR *input;
  1210. Xunsigned int inlen;
  1211. X#endif
  1212. X{
  1213. X    if (inlen < (HANDBUFSIZ - hndbufind - 1))
  1214. X    {
  1215. X        memcpy((hndbuf + hndbufind), input, inlen);
  1216. X        hndbufind += inlen;
  1217. X    }
  1218. X    else
  1219. X    {
  1220. X        /* Buffer overflow, flush buffer first. */
  1221. X
  1222. X        dohand(hndbuf, hndbufind);
  1223. X        hndbufind = 0;
  1224. X        dohand(input, inlen);
  1225. X    }
  1226. X
  1227. X    return;
  1228. X} /* end of static handoff() */
  1229. X
  1230. X
  1231. X/***************************************************************************
  1232. X*   FUNCTION: DOHAND  (STATIC)                                             *
  1233. X*                                                                          *
  1234. X*   DESCRIPTION:                                                           *
  1235. X*                                                                          *
  1236. X*       Places a block of characters in the final output buffer, flushing  *
  1237. X*       the final output buffer via a call to the callback function as     *
  1238. X*       necessary.                                                         *
  1239. X*                                                                          *
  1240. X*   ENTRY:                                                                 *
  1241. X*                                                                          *
  1242. X*       input - pointer to block of characters to place in buffer          *
  1243. X*       inlen - length of block                                            *
  1244. X*                                                                          *
  1245. X*   EXIT:                                                                  *
  1246. X*                                                                          *
  1247. X*       Nothing.                                                           *
  1248. X*                                                                          *
  1249. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1250. X*                                                                          *
  1251. X***************************************************************************/
  1252. Xstatic VOID
  1253. X#ifdef __STDC__
  1254. Xdohand(UCHAR *input, unsigned int inlen)
  1255. X#else
  1256. Xdohand(input, inlen)
  1257. XUCHAR *input;
  1258. Xunsigned int inlen;
  1259. X#endif
  1260. X{
  1261. X    unsigned int copylen;
  1262. X    UCHAR *trans2;
  1263. X
  1264. X    /* Get length of (first) copy. */
  1265. X
  1266. X    if ((finalpos + inlen) > finbuflen)
  1267. X    {
  1268. X        copylen = (int) (finbuflen - finalpos);
  1269. X    }
  1270. X    else
  1271. X    {
  1272. X        copylen = inlen;
  1273. X    }
  1274. X
  1275. X    /* Do the (first) copy. */
  1276. X
  1277. X    trans2 = finbuf + finalpos;
  1278. X    memcpy(trans2, input, copylen);
  1279. X
  1280. X    finalpos += copylen;
  1281. X
  1282. X    /* Do we need another copy? */
  1283. X
  1284. X    if (copylen != inlen)
  1285. X    {
  1286. X        /* First, do callback to flush present buffer. */
  1287. X
  1288. X        (*finalcall)(finbuflen, &finbuf, &finbuflen, &finalpos);
  1289. X
  1290. X        /* Call dohand() again. */
  1291. X
  1292. X        dohand((input + copylen), (inlen - copylen));
  1293. X    }
  1294. X
  1295. X    return;
  1296. X} /* end of static dohand() */
  1297. X
  1298. X#endif /* !MINIMAL */
  1299. X
  1300. END_OF_FILE
  1301.   if test 40825 -ne `wc -c <'src/gld.c'`; then
  1302.     echo shar: \"'src/gld.c'\" unpacked with wrong size!
  1303.   fi
  1304.   # end of 'src/gld.c'
  1305. fi
  1306. if test -f 'src/tga.c' -a "${1}" != "-c" ; then 
  1307.   echo shar: Will not clobber existing file \"'src/tga.c'\"
  1308. else
  1309.   echo shar: Extracting \"'src/tga.c'\" \(11280 characters\)
  1310.   sed "s/^X//" >'src/tga.c' <<'END_OF_FILE'
  1311. X/***************************************************************************
  1312. X*   TGA.C                                                                  *
  1313. X*   MODULE:  TGA (Targa)                                                   *
  1314. X*   OS:      UNIX                                                          *
  1315. X*                                                                          *
  1316. X*   Copyright (c) 1993 James W. Birdsall. All Rights Reserved.             *
  1317. X*                                                                          *
  1318. X*   $Id: tga.c,v 1.1 1993/03/02 01:00:20 jwbirdsa Exp $
  1319. X*                                                                          *
  1320. X*   This file contains functions to process Targa format files.            *
  1321. X*   Functions:                                                             *
  1322. X*      tga_verify    - checks filename to see if it is an Targa file       *
  1323. X*      tga_getheader - extracts header data from TGA file                  *
  1324. X*                                                                          *
  1325. X*      tga_errstring - converts error code into message                    *
  1326. X*                                                                          *
  1327. X***************************************************************************/
  1328. X
  1329. X#include "config.h"
  1330. X
  1331. X/*
  1332. X** system includes <>
  1333. X*/
  1334. X
  1335. X#include <stdio.h>
  1336. X#ifndef NO_STR_INC
  1337. X#ifdef STRING_PLURAL
  1338. X#include <strings.h>
  1339. X#else
  1340. X#include <string.h>
  1341. X#endif
  1342. X#endif
  1343. X
  1344. X
  1345. X/*
  1346. X** custom includes ""
  1347. X*/
  1348. X
  1349. X#include "depend.h"
  1350. X#include "formats.h"
  1351. X#include "tga.h"
  1352. X
  1353. X
  1354. X/*
  1355. X** local #defines
  1356. X*/
  1357. X
  1358. X/*
  1359. X** misc: copyright strings, version macros, etc.
  1360. X*/
  1361. X
  1362. X/*
  1363. X** typedefs
  1364. X*/
  1365. X
  1366. X/*
  1367. X** global variables
  1368. X*/
  1369. X
  1370. X/*
  1371. X** static globals
  1372. X*/
  1373. X
  1374. Xstatic char CONST rcsid[] = "$Id: tga.c,v 1.1 1993/03/02 01:00:20 jwbirdsa Exp $";
  1375. X
  1376. X
  1377. X/*
  1378. X** function prototypes
  1379. X*/
  1380. X
  1381. X#ifdef NO_STR_INC
  1382. Xextern char *strrchr();
  1383. Xextern int strcmp();
  1384. X#endif
  1385. X
  1386. X
  1387. X/*
  1388. X** functions
  1389. X*/
  1390. X
  1391. X
  1392. X/***************************************************************************
  1393. X*   FUNCTION:    tga_verify                                                *
  1394. X*                                                                          *
  1395. X*   DESCRIPTION:                                                           *
  1396. X*                                                                          *
  1397. X*       Verifies that a file is a Targa file by checking filename against  *
  1398. X*       list of extensions.                                                *
  1399. X*                                                                          *
  1400. X*   ENTRY:                                                                 *
  1401. X*                                                                          *
  1402. X*       filename - name of file to be verified                             *
  1403. X*       version  - pointer to unsigned long in which format/version value  *
  1404. X*                  is returned                                             *
  1405. X*                                                                          *
  1406. X*   EXIT:                                                                  *
  1407. X*                                                                          *
  1408. X*       Returns an error/status code.                                      *
  1409. X*                                                                          *
  1410. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1411. X*                                                                          *
  1412. X***************************************************************************/
  1413. XULONG
  1414. X#ifdef __STDC__
  1415. Xtga_verify(char *filename, ULONG *version, char **exts)
  1416. X#else
  1417. Xtga_verify(filename, version, exts)
  1418. Xchar *filename;
  1419. XULONG *version;
  1420. Xchar **exts;
  1421. X#endif
  1422. X{
  1423. X    char *extptr;
  1424. X    FILE *tgafile;
  1425. X    UCHAR verbuf[4];
  1426. X    int loop;
  1427. X    ULONG retval;
  1428. X
  1429. X    /* Search for '.' marking extension. */
  1430. X
  1431. X    extptr = strrchr(filename, '.');
  1432. X    if (NULL == extptr)
  1433. X    {
  1434. X        /* No extension, cannot classify. */
  1435. X
  1436. X        *version = TGA_NOT;
  1437. X        return 0;
  1438. X    }
  1439. X    extptr++;
  1440. X
  1441. X    /* Now we have the extension, check against list. */
  1442. X
  1443. X    for (loop = 0; exts[loop] != NULL; loop++)
  1444. X    {
  1445. X        /* Case-sensitive string compare. */
  1446. X
  1447. X        if (strcmp(extptr, exts[loop]) == 0)
  1448. X        {
  1449. X            /*  Match, so break out of loop. */
  1450. X
  1451. X            break;
  1452. X        }
  1453. X    }
  1454. X
  1455. X    /* Check exit from loop. */
  1456. X
  1457. X    if (NULL == exts[loop])
  1458. X    {
  1459. X        /* No match, return. */
  1460. X
  1461. X        *version = TGA_NOT;
  1462. X        return 0;
  1463. X    }
  1464. X
  1465. X    /* Extension is valid for type Targa, check format byte. */
  1466. X
  1467. X    if ((tgafile = fopen(filename, FOPEN_READ_BINARY)) == (FILE *) NULL)
  1468. X    {
  1469. X        return TGA_FILEERR_E;
  1470. X    }
  1471. X
  1472. X    if (fread(verbuf, sizeof(UCHAR), 4, tgafile) != 4)
  1473. X    {
  1474. X        *version = TGA_NOT;
  1475. X        retval = (feof(tgafile) ? ST_SUCCESS : TGA_FILEERR_E);
  1476. X        fclose(tgafile);
  1477. X        return retval;
  1478. X    }
  1479. X
  1480. X    /* Close file. */
  1481. X
  1482. X    if (fclose(tgafile))
  1483. X    {
  1484. X        return TGA_FILEERR_E;
  1485. X    }
  1486. X
  1487. X    switch (verbuf[2])
  1488. X    {
  1489. X        case 0:
  1490. X        case 1:
  1491. X        case 2:
  1492. X        case 3:
  1493. X        case 9:
  1494. X        case 10:
  1495. X        case 11:
  1496. X        case 32:
  1497. X        case 33:
  1498. X            /* Is OK format byte. Assume file is Targa. */
  1499. X            *version = TGA_1;
  1500. X            break;
  1501. X
  1502. X        default:
  1503. X            /* Is unknown format byte. Assume file is not Targa. */
  1504. X            *version = TGA_NOT;
  1505. X            break;
  1506. X    }
  1507. X
  1508. X    return ST_SUCCESS;
  1509. X} /* end of tga_verify() */
  1510. X
  1511. X
  1512. X/***************************************************************************
  1513. X*   FUNCTION:    tga_getheader                                             *
  1514. X*                                                                          *
  1515. X*   DESCRIPTION:                                                           *
  1516. X*                                                                          *
  1517. X*       Assumes that file is an TGA file. Reads header from file, extracts *
  1518. X*       data into TGA_HDR structure.                                       *
  1519. X*                                                                          *
  1520. X*   ENTRY:                                                                 *
  1521. X*                                                                          *
  1522. X*       infile  - file to be processed                                     *
  1523. X*       results - pointer to TGA_HDR structure in which data from header   *
  1524. X*                 is returned                                              *
  1525. X*                                                                          *
  1526. X*   EXIT:                                                                  *
  1527. X*                                                                          *
  1528. X*       Returns an error/status code.                                      *
  1529. X*                                                                          *
  1530. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1531. X*                                                                          *
  1532. X*       Leaves file pointing to beginning of image data.                   *
  1533. X*                                                                          *
  1534. X***************************************************************************/
  1535. XULONG
  1536. X#ifdef __STDC__
  1537. Xtga_getheader(FILE *infile, TGA_HDR *results)
  1538. X#else
  1539. Xtga_getheader(infile, results)
  1540. XFILE *infile;
  1541. XTGA_HDR *results;
  1542. X#endif
  1543. X{
  1544. X    UCHAR rawhdr[TGA_HDR_LEN];
  1545. X
  1546. X    /* Make sure we're at beginning of file. */
  1547. X
  1548. X    if (fseek(infile, 0L, SEEK_SET))
  1549. X    {
  1550. X        return TGA_FILEERR_E;
  1551. X    }
  1552. X
  1553. X    /* Read raw bytes into buffer. */
  1554. X
  1555. X    if (fread(rawhdr, 1, TGA_HDR_LEN, infile) != TGA_HDR_LEN)
  1556. X    {
  1557. X        return (feof(infile) ? TGA_UNEOF_E : TGA_FILEERR_E);
  1558. X    }
  1559. X
  1560. X    /* Extract info from raw header. */
  1561. X
  1562. X    results->idfieldlen = (int)(*(rawhdr + TGA_HDR_IDLEN_OFF));
  1563. X    results->maptype = (int)(*(rawhdr + TGA_HDR_MTYPE_OFF));
  1564. X    results->type = (int)(*(rawhdr + TGA_HDR_TYPE_OFF));
  1565. X    results->maporg = CONSTRUCT_I_UINT(rawhdr + TGA_HDR_MORG_OFF);
  1566. X    results->maplen = CONSTRUCT_I_UINT(rawhdr + TGA_HDR_MLEN_OFF);
  1567. X    results->mapentsize = (int)(*(rawhdr + TGA_HDR_MESIZ_OFF));
  1568. X    results->imxorg = CONSTRUCT_I_UINT(rawhdr + TGA_HDR_IMXORG_OFF);
  1569. X    results->imyorg = CONSTRUCT_I_UINT(rawhdr + TGA_HDR_IMYORG_OFF);
  1570. X    results->imwid = CONSTRUCT_I_UINT(rawhdr + TGA_HDR_IMWID_OFF);
  1571. X    results->imhi = CONSTRUCT_I_UINT(rawhdr + TGA_HDR_IMHI_OFF);
  1572. X    results->pixelbits = (int)(*(rawhdr + TGA_HDR_BITS_OFF));
  1573. X    results->raw = *(rawhdr + TGA_HDR_RAW_OFF);
  1574. X
  1575. X    results->attrbits = (int)(results->raw & TGA_MASK_ATTRBITS);
  1576. X    results->attrbits >>= TGA_SHIFT_ATTRBITS;
  1577. X    results->interleave = (int)(results->raw & TGA_MASK_INTERLEAVE);
  1578. X    results->interleave >>= TGA_SHIFT_INTERLEAVE;
  1579. X
  1580. X    /* Set file to point to start of data. */
  1581. X
  1582. X    if (fseek(infile, (long) (TGA_HDR_LEN + 
  1583. X                              ((results->maplen * results->mapentsize) / 8) + 
  1584. X                              results->idfieldlen), SEEK_SET))
  1585. X    {
  1586. X        return TGA_FILEERR_E;
  1587. X    }
  1588. X
  1589. X    /* Return OK. */
  1590. X
  1591. X    return ST_SUCCESS;
  1592. X} /* end of tga_getheader() */
  1593. X
  1594. X
  1595. X/***************************************************************************
  1596. X*   FUNCTION: tga_errstring                                                *
  1597. X*                                                                          *
  1598. X*   DESCRIPTION:                                                           *
  1599. X*                                                                          *
  1600. X*      Returns a string corresponding to an error code.                    *
  1601. X*                                                                          *
  1602. X*   ENTRY:                                                                 *
  1603. X*                                                                          *
  1604. X*      errcode - error code to be translated                               *
  1605. X*                                                                          *
  1606. X*   EXIT:                                                                  *
  1607. X*                                                                          *
  1608. X*      Returns a pointer to the appropriate string, or NULL if there is    *
  1609. X*      no appropriate string.                                              *
  1610. X*                                                                          *
  1611. X*   CONSTRAINTS/SIDE EFFECTS:                                              *
  1612. X*                                                                          *
  1613. X***************************************************************************/
  1614. Xchar *
  1615. X#ifdef __STDC__
  1616. Xtga_errstring(ULONG errcode)
  1617. X#else
  1618. Xtga_errstring(errcode)
  1619. XULONG errcode;
  1620. X#endif
  1621. X{
  1622. X    char *temp;
  1623. X
  1624. X    /* If error code not from this module, return NULL. */
  1625. X
  1626. X    if ((errcode & ST_MOD_MASK) != TGA_MODULE)
  1627. X    {
  1628. X        return NULL;
  1629. X    }
  1630. X
  1631. X    /* Process by code. */
  1632. X
  1633. X    switch (ERRSEV(errcode))
  1634. X    {
  1635. X        case ERRSEV(TGA_NOTTGA_E):
  1636. X            temp = "File is not a TGA format file.";
  1637. X            break;
  1638. X        case ERRSEV(TGA_FILEERR_E):
  1639. X            temp = "Error accessing file.";
  1640. X            break;
  1641. X        case ERRSEV(TGA_UNEOF_E):
  1642. X            temp = "Unexpected End of File";
  1643. X            break;
  1644. X
  1645. X        default:
  1646. X            temp = NULL;
  1647. X            break;
  1648. X    }
  1649. X
  1650. X    return temp;
  1651. X} /* end of tga_errstring() */
  1652. X
  1653. END_OF_FILE
  1654.   if test 11280 -ne `wc -c <'src/tga.c'`; then
  1655.     echo shar: \"'src/tga.c'\" unpacked with wrong size!
  1656.   fi
  1657.   # end of 'src/tga.c'
  1658. fi
  1659. echo shar: End of archive 6 \(of 18\).
  1660. cp /dev/null ark6isdone
  1661. MISSING=""
  1662. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
  1663.     if test ! -f ark${I}isdone ; then
  1664.     MISSING="${MISSING} ${I}"
  1665.     fi
  1666. done
  1667. if test "${MISSING}" = "" ; then
  1668.     echo You have unpacked all 18 archives.
  1669.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1670. else
  1671.     echo You still must unpack the following archives:
  1672.     echo "        " ${MISSING}
  1673. fi
  1674. exit 0
  1675. exit 0 # Just in case...
  1676.