home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / lib / Xmu / Xct.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-22  |  16.5 KB  |  683 lines

  1. /* 
  2.  * $XConsortium: Xct.c,v 1.17 91/07/22 23:47:13 rws Exp $
  3.  * Copyright 1989 by the Massachusetts Institute of Technology
  4.  *
  5.  * Permission to use, copy, modify, and distribute this software and its
  6.  * documentation for any purpose and without fee is hereby granted, provided 
  7.  * that the above copyright notice appear in all copies and that both that 
  8.  * copyright notice and this permission notice appear in supporting 
  9.  * documentation, and that the name of M.I.T. not be used in advertising
  10.  * or publicity pertaining to distribution of the software without specific, 
  11.  * written prior permission. M.I.T. makes no representations about the 
  12.  * suitability of this software for any purpose.  It is provided "as is"
  13.  * without express or implied warranty.
  14.  *
  15.  */
  16.  
  17. #include <X11/Xfuncs.h>
  18. #include "Xct.h"
  19. #include <stdio.h>
  20.  
  21. #define UsedGraphic    0x0001
  22. #define UsedDirection    0x0002
  23.  
  24. typedef struct _XctPriv {
  25.     XctString        ptr;
  26.     XctString        ptrend;
  27.     unsigned        flags;
  28.     XctHDirection    *dirstack;
  29.     unsigned        dirsize;
  30.     char        **encodings;
  31.     unsigned        enc_count;
  32.     XctString        itembuf;
  33.     unsigned        buf_count;
  34. } *XctPriv;
  35.  
  36. #define IsMore(priv) ((priv)->ptr != (priv)->ptrend)
  37. #define AmountLeft(priv) ((priv)->ptrend - (priv)->ptr)
  38.  
  39. extern char *malloc();
  40. extern char *realloc();
  41.  
  42. #define HT    0x09
  43. #define NL    0x0a
  44. #define ESC    0x1b
  45. #define CSI    0x9b
  46.  
  47. #define IsLegalC0(data, c) (((c) == HT) || ((c) == NL) || \
  48.                 (((data)->version > XctVersion) && \
  49.                  ((data)->flags & XctAcceptC0Extensions)))
  50.  
  51. #define IsLegalC1(priv, c) (((data)->version > XctVersion) && \
  52.                 ((data)->flags & XctAcceptC1Extensions))
  53.  
  54. #define IsI2(c) (((c) >= 0x20) && ((c) <= 0x2f))
  55. #define IsI3(c) (((c) >= 0x30) && ((c) <= 0x3f))
  56. #define IsESCF(c) (((c) >= 0x30) && ((c) <= 0x7e))
  57. #define IsCSIF(c) (((c) >= 0x40) && ((c) <= 0x7e))
  58. #define IsC0(c) ((c) <= 0x1f)
  59. #define IsGL(c) (((c) >= 0x20) && ((c) <= 0x7f))
  60. #define IsC1(c) (((c) >= 0x80) && ((c) <= 0x9f))
  61. #define IsGR(c) ((c) >= 0xa0)
  62.  
  63. #define HasC  1
  64. #define HasGL 2
  65. #define HasGR 4
  66. #define ToGL  8
  67.  
  68. static void
  69. ComputeGLGR(data)
  70.     register XctData data;
  71. {
  72.     /* XXX this will need more work if more sets are registered */
  73.     if ((data->GL_set_size == 94) && (data->GL_char_size == 1) &&
  74.     (data->GL[0] == '\102') &&
  75.     (data->GR_set_size == 96) && (data->GR_char_size == 1))
  76.     data->GLGR_encoding = data->GR_encoding;
  77.     else if ((data->GL_set_size == 94) && (data->GL_char_size == 1) &&
  78.          (data->GL[0] == '\112') &&
  79.          (data->GR_set_size == 94) && (data->GR_char_size == 1))
  80.     data->GLGR_encoding = data->GR_encoding;
  81.     else
  82.     data->GLGR_encoding = (char *)NULL;
  83. }
  84.  
  85. static int
  86. HandleGL(data, c)
  87.     register XctData data;
  88.     unsigned char c;
  89. {
  90.     switch (c) {
  91.     case 0x42:
  92.     data->GL = "\102";
  93.     data->GL_encoding = "ISO8859-1";
  94.     break;
  95.     case 0x4a:
  96.     data->GL = "\112";
  97.     data->GL_encoding = "JISX0201.1976-0";
  98.     break;
  99.     default:
  100.     return 0;
  101.     }
  102.     data->GL_set_size = 94;
  103.     data->GL_char_size = 1;
  104.     ComputeGLGR(data);
  105.     return 1;
  106. }
  107.  
  108. static int
  109. HandleMultiGL(data, c)
  110.     register XctData data;
  111.     unsigned char c;
  112. {
  113.     switch (c) {
  114.     case 0x41:
  115.     data->GL = "\101";
  116.     data->GL_encoding = "GB2312.1980-0";
  117.     break;
  118.     case 0x42:
  119.     data->GL = "\102";
  120.     data->GL_encoding = "JISX0208.1983-0";
  121.     break;
  122.     case 0x43:
  123.     data->GL = "\103";
  124.     data->GL_encoding = "KSC5601.1987-0";
  125.     break;
  126.     default:
  127.     return 0;
  128.     }
  129.     data->GL_set_size = 94;
  130.     data->GL_char_size = 2;
  131. #ifdef notdef
  132.     if (c < 0x60)
  133.     data->GL_char_size = 2;
  134.     else if (c < 0x70)
  135.     data->GL_char_size = 3;
  136.     else
  137.     data->GL_char_size = 4;
  138. #endif
  139.     data->GLGR_encoding = (char *)NULL;
  140.     return 1;
  141. }
  142.  
  143. static int
  144. Handle94GR(data, c)
  145.     register XctData data;
  146.     unsigned char c;
  147. {
  148.     switch (c) {
  149.     case 0x49:
  150.     data->GR = "\111";
  151.     data->GR_encoding = "JISX0201.1976-0";
  152.     break;
  153.     default:
  154.     return 0;
  155.     }
  156.     data->priv->flags &= ~ToGL;
  157.     data->GR_set_size = 94;
  158.     data->GR_char_size = 1;
  159.     data->GLGR_encoding = (char *)NULL;
  160.     return 1;
  161. }
  162.  
  163. static int
  164. Handle96GR(data, c)
  165.     register XctData data;
  166.     unsigned char c;
  167. {
  168.     switch (c) {
  169.     case 0x41:
  170.     data->GR = "\101";
  171.     data->GR_encoding = "ISO8859-1";
  172.     break;
  173.     case 0x42:
  174.     data->GR = "\102";
  175.     data->GR_encoding = "ISO8859-2";
  176.     break;
  177.     case 0x43:
  178.     data->GR = "\103";
  179.     data->GR_encoding = "ISO8859-3";
  180.     break;
  181.     case 0x44:
  182.     data->GR = "\104";
  183.     data->GR_encoding = "ISO8859-4";
  184.     break;
  185.     case 0x46:
  186.     data->GR = "\106";
  187.     data->GR_encoding = "ISO8859-7";
  188.     break;
  189.     case 0x47:
  190.     data->GR = "\107";
  191.     data->GR_encoding = "ISO8859-6";
  192.     break;
  193.     case 0x48:
  194.     data->GR = "\110";
  195.     data->GR_encoding = "ISO8859-8";
  196.     break;
  197.     case 0x4c:
  198.     data->GR = "\114";
  199.     data->GR_encoding = "ISO8859-5";
  200.     break;
  201.     case 0x4d:
  202.     data->GR = "\115";
  203.     data->GR_encoding = "ISO8859-9";
  204.     break;
  205.     default:
  206.     return 0;
  207.     }
  208.     data->priv->flags &= ~ToGL;
  209.     data->GR_set_size = 96;
  210.     data->GR_char_size = 1;
  211.     ComputeGLGR(data);
  212.     return 1;
  213. }
  214.  
  215. static int
  216. HandleMultiGR(data, c)
  217.     register XctData data;
  218.     unsigned char c;
  219. {
  220.     switch (c) {
  221.     case 0x41:
  222.     data->GR = "\101";
  223.     if (data->flags & XctShiftMultiGRToGL)
  224.         data->GR_encoding = "GB2312.1980-0";
  225.     else
  226.         data->GR_encoding = "GB2312.1980-1";
  227.     break;
  228.     case 0x42:
  229.     data->GR = "\102";
  230.     if (data->flags & XctShiftMultiGRToGL)
  231.         data->GR_encoding = "JISX0208.1983-0";
  232.     else
  233.         data->GR_encoding = "JISX0208.1983-1";
  234.     break;
  235.     case 0x43:
  236.     data->GR = "\103";
  237.     if (data->flags & XctShiftMultiGRToGL)
  238.         data->GR_encoding = "KSC5601.1987-0";
  239.     else
  240.         data->GR_encoding = "KSC5601.1987-1";
  241.     break;
  242.     default:
  243.     return 0;
  244.     }
  245.     if (data->flags & XctShiftMultiGRToGL)
  246.     data->priv->flags |= ToGL;
  247.     else
  248.     data->priv->flags &= ~ToGL;
  249.     data->GR_set_size = 94;
  250.     data->GR_char_size = 2;
  251. #ifdef notdef
  252.     if (c < 0x60)
  253.     data->GR_char_size = 2;
  254.     else if (c < 0x70)
  255.     data->GR_char_size = 3;
  256.     else
  257.     data->GR_char_size = 4;
  258. #endif
  259.     data->GLGR_encoding = (char *)NULL;
  260.     return 1;
  261. }
  262.  
  263. static int
  264. HandleExtended(data, c)
  265.     register XctData data;
  266.     unsigned char c;
  267. {
  268.     register XctPriv priv = data->priv;
  269.     XctString enc = data->item + 6;
  270.     register XctString ptr = enc;
  271.     int i, len;
  272.  
  273.     while (*ptr != 0x02) {
  274.     if (!*ptr || (++ptr == priv->ptr))
  275.         return 0;
  276.     }
  277.     data->item = ptr + 1;
  278.     data->item_length = priv->ptr - data->item;
  279.     len = ptr - enc;
  280.     for (i = 0;
  281.      (i < priv->enc_count) &&
  282.      strncmp(priv->encodings[i], (char *)enc, len);
  283.      i++)
  284.     ;
  285.     if (i == priv->enc_count) {
  286.     XctString cp;
  287.  
  288.     for (cp = enc; cp != ptr; cp++) {
  289.         if ((!IsGL(*cp) && !IsGR(*cp)) || (*cp == 0x2a) || (*cp == 0x3f))
  290.         return 0;
  291.     }
  292.     ptr = (XctString)malloc((unsigned)len + 1);
  293.     bcopy((char *)enc, (char *)ptr, len);
  294.     ptr[len] = 0x00;
  295.     priv->enc_count++;
  296.     if (priv->encodings)
  297.         priv->encodings = (char **)realloc(
  298.                         (char *)priv->encodings,
  299.                         priv->enc_count * sizeof(char *));
  300.     else
  301.         priv->encodings = (char **)malloc(sizeof(char *));
  302.     priv->encodings[i] = (char *)ptr;
  303.     }
  304.     data->encoding = priv->encodings[i];
  305.     data->char_size = c - 0x30;
  306.     return 1;
  307. }
  308.  
  309. static void
  310. ShiftGRToGL(data, hasCdata)
  311.     register XctData data;
  312.     int hasCdata;
  313. {
  314.     register XctPriv priv = data->priv;
  315.     register int i;
  316.  
  317.     if (data->item_length > priv->buf_count) {
  318.     priv->buf_count = data->item_length;
  319.     if (priv->itembuf)
  320.         priv->itembuf = (XctString)realloc((char *)priv->itembuf,
  321.                            priv->buf_count);
  322.     else
  323.         priv->itembuf = (XctString)malloc(priv->buf_count);
  324.     }
  325.     bcopy((char *)data->item, (char *)priv->itembuf, data->item_length);
  326.     data->item = priv->itembuf;
  327.     if (hasCdata) {
  328.     for (i = data->item_length; --i >= 0; ) {
  329.         if (IsGR(data->item[i]))
  330.         data->item[i] &= 0x7f;
  331.     }
  332.     } else {
  333.     for (i = data->item_length; --i >= 0; )
  334.         data->item[i] &= 0x7f;
  335.     }
  336. }
  337.  
  338. /* Create an XctData structure for parsing a Compound Text string. */
  339. #if NeedFunctionPrototypes
  340. XctData
  341. XctCreate(_Xconst unsigned char *string, int length, XctFlags flags)
  342. #else
  343. XctData
  344. XctCreate(string, length, flags)
  345.     XctString string;
  346.     int length;
  347.     XctFlags flags;
  348. #endif
  349. {
  350.     register XctData data;
  351.     register XctPriv priv;
  352.  
  353.     data = (XctData)malloc(sizeof(struct _XctRec) + sizeof(struct _XctPriv));
  354.     if (!data)
  355.     return data;
  356.     data->priv = priv = (XctPriv)(data + 1);
  357.     data->total_string = (XctString)string;
  358.     data->total_length = length;
  359.     data->flags = flags;
  360.     priv->dirstack = (XctHDirection *)NULL;
  361.     priv->dirsize = 0;
  362.     priv->encodings = (char **)NULL;
  363.     priv->enc_count = 0;
  364.     priv->itembuf = (XctString)NULL;
  365.     priv->buf_count = 0;
  366.     XctReset(data);
  367.     return data;
  368. }
  369.  
  370. /* Reset the XctData structure to re-parse the string from the beginning. */
  371. void
  372. XctReset(data)
  373.     register XctData data;
  374. {
  375.     register XctPriv priv = data->priv;
  376.  
  377.     priv->ptr = data->total_string;
  378.     priv->ptrend = data->total_string + data->total_length;
  379.     data->item = (XctString)NULL;
  380.     data->item_length = 0;
  381.     data->encoding = (char *)NULL;
  382.     data->char_size = 1;
  383.     data->horizontal = XctUnspecified;
  384.     data->horz_depth = 0;
  385.     priv->flags = 0;
  386.     data->GL_set_size = data->GR_set_size = 0; /* XXX */
  387.     (void)HandleGL(data, (unsigned char)0x42);
  388.     (void)Handle96GR(data, (unsigned char)0x41);
  389.     data->version = 1;
  390.     data->can_ignore_exts = 0;
  391.     /* parse version, if present */
  392.     if ((data->total_length >= 4) &&
  393.     (priv->ptr[0] == ESC) && (priv->ptr[1] == 0x23) &&
  394.     IsI2(priv->ptr[2]) &&
  395.     ((priv->ptr[3] == 0x30) || (priv->ptr[3] == 0x31))) {
  396.     data->version = priv->ptr[2] - 0x1f;
  397.     if (priv->ptr[3] == 0x30)
  398.         data->can_ignore_exts = 1;
  399.     priv->ptr += 4;
  400.     }
  401. }
  402.  
  403. /* Parse the next "item" from the Compound Text string.  The return value
  404.  * indicates what kind of item is returned.  The item itself, and the current
  405.  * contextual state, are reported as components of the XctData structure.
  406.  */
  407. XctResult
  408. XctNextItem(data)
  409.     register XctData data;
  410. {
  411.     register XctPriv priv = data->priv;
  412.     unsigned char c;
  413.     int len, bits;
  414.  
  415. #define NEXT data->item_length++; priv->ptr++
  416.  
  417.     while (IsMore(priv)) {
  418.     data->item = priv->ptr;
  419.     data->item_length = 0;
  420.     c = *priv->ptr;
  421.     if (c == ESC) {
  422.         NEXT;
  423.         while (IsMore(priv) && IsI2(*priv->ptr)) {
  424.         NEXT;
  425.         }
  426.         if (!IsMore(priv))
  427.         return XctError;
  428.         c = *priv->ptr;
  429.         NEXT;
  430.         if (!IsESCF(c))
  431.         return XctError;
  432.         switch (data->item[1]) {
  433.         case 0x24:
  434.         if (data->item_length > 3) {
  435.             if (data->item[2] == 0x28) {
  436.             if (HandleMultiGL(data, c))
  437.                 continue;
  438.             } else if (data->item[2] == 0x29) {
  439.             if (HandleMultiGR(data, c))
  440.                 continue;
  441.             }
  442.         }
  443.         break;
  444.         case 0x25:
  445.         if ((data->item_length == 4) && (data->item[2] == 0x2f) &&
  446.             (c <= 0x3f)) {
  447.             if ((AmountLeft(priv) < 2) ||
  448.             (priv->ptr[0] < 0x80) || (priv->ptr[1] < 0x80))
  449.             return XctError;
  450.             len = *priv->ptr - 0x80;
  451.             NEXT;
  452.             len = (len << 7) + (*priv->ptr - 0x80);
  453.             NEXT;
  454.             if (AmountLeft(priv) < len)
  455.             return XctError;
  456.             data->item_length += len;
  457.             priv->ptr += len;
  458.             if (c <= 0x34) {
  459.             if (!HandleExtended(data, c) ||
  460.                 ((data->horz_depth == 0) &&
  461.                  (priv->flags & UsedDirection)))
  462.                 return XctError;
  463.             priv->flags |= UsedGraphic;
  464.             return XctExtendedSegment;
  465.             }
  466.         }
  467.         break;
  468.         case 0x28:
  469.         if (HandleGL(data, c))
  470.             continue;
  471.         break;
  472.         case 0x29:
  473.         if (Handle94GR(data, c))
  474.             continue;
  475.         break;
  476.         case 0x2d:
  477.         if (Handle96GR(data, c))
  478.             continue;
  479.         break;
  480.         }
  481.     } else if (c == CSI) {
  482.         NEXT;
  483.         while (IsMore(priv) && IsI3(*priv->ptr)) {
  484.         NEXT;
  485.         }
  486.         while (IsMore(priv) && IsI2(*priv->ptr)) {
  487.         NEXT;
  488.         }
  489.         if (!IsMore(priv))
  490.         return XctError;
  491.         c = *priv->ptr;
  492.         NEXT;
  493.         if (!IsCSIF(c))
  494.         return XctError;
  495.         if (c == 0x5d) {
  496.         if ((data->item_length == 3) &&
  497.             ((data->item[1] == 0x31) || (data->item[1] == 0x32))) {
  498.             data->horz_depth++;
  499.             if (priv->dirsize < data->horz_depth) {
  500.             priv->dirsize += 10;
  501.             if (priv->dirstack)
  502.                 priv->dirstack = (XctHDirection *)
  503.                          realloc((char *)priv->dirstack,
  504.                              priv->dirsize *
  505.                              sizeof(XctHDirection));
  506.             else
  507.                 priv->dirstack = (XctHDirection *)
  508.                          malloc(priv->dirsize *
  509.                             sizeof(XctHDirection));
  510.             }
  511.             priv->dirstack[data->horz_depth - 1] = data->horizontal;
  512.             if (data->item[1] == 0x31)
  513.             data->horizontal = XctLeftToRight;
  514.             else
  515.             data->horizontal = XctRightToLeft;
  516.             if ((priv->flags & UsedGraphic) &&
  517.             !(priv->flags & UsedDirection))
  518.             return XctError;
  519.             priv->flags |= UsedDirection;
  520.             if (data->flags & XctHideDirection)
  521.             continue;
  522.             return XctHorizontal;
  523.         } else if (data->item_length == 2) {
  524.             if (!data->horz_depth)
  525.             return XctError;
  526.             data->horz_depth--;
  527.             data->horizontal = priv->dirstack[data->horz_depth];
  528.             if (data->flags & XctHideDirection)
  529.             continue;
  530.             return XctHorizontal;
  531.         }
  532.         }
  533.     } else if (data->flags & XctSingleSetSegments) {
  534.         NEXT;
  535.         if IsC0(c) {
  536.         data->encoding = (char *)NULL;
  537.         data->char_size = 1;
  538.         if (IsLegalC0(data, c))
  539.             return XctC0Segment;
  540.         } else if (IsGL(c)) {
  541.         data->encoding = data->GL_encoding;
  542.         data->char_size = data->GL_char_size;
  543.         while (IsMore(priv) && IsGL(*priv->ptr)) {
  544.             NEXT;
  545.         }
  546.         if (((data->char_size > 1) &&
  547.              (data->item_length % data->char_size)) ||
  548.             ((data->horz_depth == 0) &&
  549.              (priv->flags & UsedDirection)))
  550.             return XctError;
  551.         priv->flags |= UsedGraphic;
  552.         return XctGLSegment;
  553.         } else if (IsC1(c)) {
  554.         data->encoding = (char *)NULL;
  555.         data->char_size = 1;
  556.         if (IsLegalC1(data, c))
  557.             return XctC1Segment;
  558.         } else {
  559.         data->encoding = data->GR_encoding;
  560.         data->char_size = data->GR_char_size;
  561.         while (IsMore(priv) && IsGR(*priv->ptr)) {
  562.             NEXT;
  563.         }
  564.         if (((data->char_size > 1) &&
  565.              (data->item_length % data->char_size)) ||
  566.             ((data->horz_depth == 0) &&
  567.              (priv->flags & UsedDirection)))
  568.             return XctError;
  569.         priv->flags |= UsedGraphic;
  570.         if (!(priv->flags & ToGL))
  571.             return XctGRSegment;
  572.         ShiftGRToGL(data, 0);
  573.         return XctGLSegment;
  574.         }
  575.     } else {
  576.         bits = 0;
  577.         while (1) {
  578.         if (IsC0(c) || IsC1(c)) {
  579.             if ((c == ESC) || (c == CSI))
  580.             break;
  581.             if (IsC0(c) ? !IsLegalC0(data, c) : !IsLegalC1(data, c))
  582.             break;
  583.             bits |= HasC;
  584.             NEXT;
  585.         } else {
  586.             len = data->item_length;
  587.             if (IsGL(c)) {
  588.             if ((data->flags & XctShiftMultiGRToGL) &&
  589.                 (bits & HasGR))
  590.                 break;
  591.             NEXT;
  592.             bits |= HasGL;
  593.             while (IsMore(priv) && IsGL(*priv->ptr)) {
  594.                 NEXT;
  595.             }
  596.             if ((data->GL_char_size > 1) &&
  597.                 ((data->item_length - len) % data->GL_char_size))
  598.                 return XctError;
  599.             } else {
  600.             if ((data->flags & XctShiftMultiGRToGL) &&
  601.                 (bits & HasGL))
  602.                 break;
  603.             NEXT;
  604.             bits |= HasGR;
  605.             while (IsMore(priv) && IsGR(*priv->ptr)) {
  606.                 NEXT;
  607.             }
  608.             if ((data->GR_char_size > 1) &&
  609.                 ((data->item_length - len) % data->GR_char_size))
  610.                 return XctError;
  611.             }
  612.         }
  613.         if (!IsMore(priv))
  614.             break;
  615.         c = *priv->ptr;
  616.         }
  617.         if (data->item_length) {
  618.         if (bits & (HasGL|HasGR)) {
  619.             priv->flags |= UsedGraphic;
  620.             if ((data->horz_depth == 0) &&
  621.             (priv->flags & UsedDirection))
  622.             return XctError;
  623.             if ((data->flags & XctShiftMultiGRToGL) && (bits & HasGR))
  624.             ShiftGRToGL(data, bits & HasC);
  625.         }
  626.         if ((bits == (HasGL|HasGR)) ||
  627.             (data->GLGR_encoding && !(bits & HasC))) {
  628.             data->encoding = data->GLGR_encoding;
  629.             if (data->GL_char_size == data->GR_char_size)
  630.             data->char_size = data->GL_char_size;
  631.             else
  632.             data->char_size = 0;
  633.         } else if (bits == HasGL) {
  634.             data->encoding = data->GL_encoding;
  635.             data->char_size = data->GL_char_size;
  636.         } else if (bits == HasGR) {
  637.             data->encoding = data->GR_encoding;
  638.             data->char_size = data->GR_char_size;
  639.         } else {
  640.             data->encoding = (char *)NULL;
  641.             data->char_size = 1;
  642.             if ((bits & HasGL) &&
  643.             (data->GL_char_size != data->char_size))
  644.             data->char_size = 0;
  645.             if ((bits & HasGR) &&
  646.             (data->GR_char_size != data->char_size))
  647.             data->char_size = 0;
  648.         }
  649.         return XctSegment;
  650.         }
  651.         NEXT;
  652.     }
  653.     if (data->version <= XctVersion)
  654.         return XctError;
  655.     if (data->flags & XctProvideExtensions)
  656.         return XctExtension;
  657.     if (!data->can_ignore_exts)
  658.         return XctError;
  659.     }
  660.     return XctEndOfText;
  661. }
  662.  
  663. /* Free all data associated with an XctDataStructure. */
  664. void
  665. XctFree(data)
  666.     register XctData data;
  667. {
  668.     int i;
  669.     register XctPriv priv = data->priv;
  670.  
  671.     if (priv->dirstack)
  672.     free((char *)priv->dirstack);
  673.     if (data->flags & XctFreeString)
  674.     free((char *)data->total_string);
  675.     for (i = 0; i < priv->enc_count; i++)
  676.     free(priv->encodings[i]);
  677.     if (priv->encodings)
  678.     free((char *)priv->encodings);
  679.     if (priv->itembuf)
  680.     free((char *)priv->itembuf);
  681.     free((char *)data);
  682. }
  683.