home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Graphics / Graphics.zip / xfitsvew.zip / XFITSview / textfile.c < prev    next >
C/C++ Source or Header  |  1998-04-05  |  19KB  |  529 lines

  1. /* TextFile routines for XFITSview */
  2. /*-----------------------------------------------------------------------
  3. *  Copyright (C) 1996
  4. *  Associated Universities, Inc. Washington DC, USA.
  5. *  This program is free software; you can redistribute it and/or
  6. *  modify it under the terms of the GNU General Public License as
  7. *  published by the Free Software Foundation; either version 2 of
  8. *  the License, or (at your option) any later version.
  9. *
  10. *  This program is distributed in the hope that it will be useful,
  11. *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. *  GNU General Public License for more details.
  14. *-----------------------------------------------------------------------*/
  15. #include <Xm/Xm.h> 
  16. #include <Xm/FileSB.h> 
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include "fitsio.h"
  21. #include "zsubs.h"
  22. #include "gzipread.h"
  23. #include "textfile.h" 
  24. #include "messagebox.h" 
  25. #include "helpbox.h" 
  26. #include "xfitsview.h" /* a bit of uglyness for saving directories */
  27.  
  28. /* define file types */
  29. #define TEXTTYPE    1   /* Unix text file (LF only) */
  30. #define FITSTYPE    2   /* FITS file header */
  31. #define DOSTEXTTYPE 3   /* DOS text file (CR, LF) */
  32.   
  33. /* internal functions */
  34. /* Flush output buffer - TFilePtr already locked*/
  35. int TextFileFlush(TextFilePtr TFilePtr); /* returns 1 if OK */
  36. /* read text file buffer */
  37. int TextFileBufferIn(TextFilePtr TFilePtr);/* returns 1 if OK */
  38. /* If file specified then fills in file info in TextFileInfo structure */
  39. void TextFileOKCB (Widget filebox, XtPointer clientData, XtPointer callData);
  40. /* TextFile selection canceled */
  41. void TextFileCancelCB (Widget filebox, XtPointer clientData, XtPointer callData);
  42.  
  43.   
  44. /* create/initialize TextFileInfo structure                               */
  45. /* w is a Widget for dialog boxes to be attached to                       */
  46. /* if non null filename and directory filled in                           */
  47. TextFilePtr TextFileMake (Widget w, char* filename, char* directory)
  48. {
  49.   TextFilePtr TFilePtr;
  50.  
  51. /* create structure */
  52.   TFilePtr = (TextFilePtr)malloc(sizeof(TextFileInfo));
  53.   if (!TFilePtr) return TFilePtr; /* alloc failed? */
  54.  
  55. /* fill in value passed */
  56.   TFilePtr->w = w;
  57.   if (filename) { /* make copy */
  58.     TFilePtr->FileName = (char*)malloc(strlen(filename)+1);
  59.     strcpy (TFilePtr->FileName, filename);}
  60.   else
  61.     TFilePtr->FileName = NULL;
  62.   if (directory) { /* make copy */
  63.     TFilePtr->directory = (char*)malloc(strlen(directory)+1);
  64.     strcpy (TFilePtr->directory, directory);}
  65.   else
  66.     TFilePtr->directory = NULL;
  67.  
  68. /* others */
  69.     TFilePtr->file = NULL;
  70.     TFilePtr->OKfunc = NULL;
  71.     TFilePtr->CancelFunc = NULL;
  72.     TFilePtr->hFile = 0;
  73.     TFilePtr->Good = 0;
  74.     TFilePtr->HitEOF = 0;
  75.     TFilePtr->InBuffer = 0;
  76.     TFilePtr->BufferPos = 0;
  77.     TFilePtr->State = 0;
  78.     TFilePtr->FileType = 0;
  79.     TFilePtr->isGzip = 0;
  80.     TFilePtr->chkGzip = 1;
  81.  
  82.   return TFilePtr;
  83. } /* end TextFileMake */
  84.  
  85. /* delete TextFileInfo structure             */
  86. void TextFileKill (TextFilePtr TFilePtr)
  87. {
  88.   if (!TFilePtr) return; /* anybody home */
  89.  
  90. /* delete any characters string and buffer */
  91.   if (TFilePtr->FileName) free(TFilePtr->FileName);
  92.   if (TFilePtr->directory) free(TFilePtr->directory);
  93.  
  94. /* need to close output file? */
  95.   if (TFilePtr->file) fclose(TFilePtr->file);
  96.   if (TFilePtr->hFile) FileClose(TFilePtr->hFile);
  97.  
  98. /* delete any gzip structures */
  99.   if (TFilePtr->isGzip) gz_close();
  100.  
  101. /* delete structure */
  102.   free(TFilePtr);
  103. } /* end TextFileKill */
  104.  
  105. /* get file specification                                                 */
  106. /* inout = 1 => input; 2=> output                                         */
  107. /* TFilePtr->Good indicated if file selected                              */
  108. void TextFileFind (int inout, TextFilePtr TFilePtr, TextFileProc OKfunc,
  109.            TextFileProc CancelFunc)
  110. {
  111.   Widget       filebox;
  112.   XmString     wierdstring = NULL;
  113.   Arg          wargs[5]; 
  114.  
  115. /* save function pointesr */
  116.   TFilePtr->OKfunc = OKfunc;
  117.   TFilePtr->CancelFunc = CancelFunc;
  118.   TFilePtr->State = inout; /* input or output? */
  119.  
  120. /* bring up selection box */
  121.   filebox = (Widget) XmCreateFileSelectionDialog (TFilePtr->w, 
  122.                           "text_file", NULL, 0);
  123.   XtAddCallback (filebox, XmNokCallback, TextFileOKCB, (XtPointer)TFilePtr);
  124.   XtAddCallback (filebox, XmNcancelCallback, TextFileCancelCB, 
  125.          (XtPointer)TFilePtr);
  126.   XtAddCallback (filebox, XmNhelpCallback, HelpBoxTopicCB, 
  127.            (XtPointer)"Browser");
  128.  
  129. /* set directory if it is defined */
  130.   if (TFilePtr->directory) {
  131.     wierdstring = XmStringCreateSimple (TFilePtr->directory);
  132.     XtSetArg (wargs[0], XmNdirectory, wierdstring);
  133.     XtSetValues (filebox, wargs, 1);
  134.     if (wierdstring) XmStringFree(wierdstring); wierdstring = NULL;
  135.   }
  136.  
  137. /* Shazam appear: */
  138.   XtManageChild (filebox);
  139.   XtPopup (XtParent (filebox), XtGrabNone);
  140. /* all the action is in the callback routine */
  141. } /* end TextFileFind */
  142.   
  143. /* open text file                                                         */ 
  144. /* inout = 1 => input; 2=> output                                         */
  145. /* returns 1 if successful                                                */
  146. int TextFileOpen (TextFilePtr TFilePtr, int inout)
  147. /* use standard c I/O on write and fitsio on read which allows using the
  148.    gzip decompression routines */
  149.   char fullname[120];
  150.   int  length;
  151.   FITSfile *Fname;
  152.  
  153.   TFilePtr->State = inout;
  154.   
  155. /* put together full file name */
  156.   strcpy(fullname, TFilePtr->directory);
  157.   length = strlen(TFilePtr->directory);
  158.   if (length>0) fullname[length] = '/';
  159.   else length = -1;
  160.   strcpy(&fullname[length+1], TFilePtr->FileName);
  161.  
  162.   /* open for read */
  163.   if (inout==1) { 
  164.    Fname = (FITSfile*)MakeString(fullname);
  165.    TFilePtr->hFile = FileOpen(Fname);
  166.    KillString(Fname); /* as ye create shall thou destroy */
  167.    if (!TFilePtr->hFile) { /* open failed */
  168.      MessageShow ("Error openinging text file");
  169.      return 0; } /* end of open failed */
  170.    /* read first block, decide type */
  171.    if (!TextFileBufferIn(TFilePtr)) { /* I/O failed */
  172.      MessageShow ("Error reading text file");
  173.      TextFileClose(TFilePtr);
  174.      return 0; } /* end of I/O failed */
  175.   } /* end open for read */
  176.   /* open for write */
  177.   else if (inout==2) { 
  178.     TFilePtr->file = fopen ((const char*)fullname,"at");
  179.     if (!TFilePtr->file) { /* failed? */
  180.      MessageShow ("Error openinging text file");
  181.      return 0; } /* end of open failed */
  182.   } /* end open for write */
  183.   return 1; /* OK */
  184. } /* end TextFileOpen */
  185.   
  186. /* close file specified by handle TFilePtr                                */ 
  187. /* returns 1 if successful                                                */ 
  188. int TextFileClose(TextFilePtr TFilePtr)
  189. {
  190.   int good = 1;
  191.   if (!TFilePtr) return 0;   /* validity check */
  192.  
  193. /* flush buffer on write */
  194.   if ((TFilePtr->State==2) && (TFilePtr->BufferPos>0))
  195.     if (!TextFileFlush(TFilePtr))
  196.       {MessageShow("Error flushing text file buffer"); good = 0;}
  197. /* Close */
  198.   if (TFilePtr->State==1) {/* close read */
  199.     if (FileClose(TFilePtr->hFile)!=1) { /* close failed */
  200.       MessageShow("Error closing text file"); good = 0;}
  201.     TFilePtr->hFile = 0;
  202.     /* delete any gzip structures */
  203.     if (!TFilePtr->isGzip) gz_close();
  204.     TFilePtr->isGzip = 0;
  205.   } /* end close read */
  206.   else if (TFilePtr->State==2) {/* close write */
  207.     if (fclose(TFilePtr->file))
  208.       {MessageShow("Error closing text file"); good = 0;}
  209.     TFilePtr->file = NULL;
  210.   } /* end close write */
  211.  
  212.  
  213.  TFilePtr->State = 0; /* mark as closed */
  214.  
  215.   return good;
  216. } /* end TextFileClose */
  217.   
  218. /* Read a line of text from a file                                        */ 
  219. /* returns 1 if OK, 0 if failed, -1 -> HitEOF                             */ 
  220. /* maxchar is the maximum number of characters allowed in line */
  221. int TextFileRead(TextFilePtr TFilePtr, char* line, int maxchar)
  222. {
  223.    char *next, CR=13, LF=10, *linein;
  224.    long loop, count=0;
  225.  
  226.    if (!TFilePtr) return 0;   /* validity check */
  227.    if (!TFilePtr->State) return 0; /* active? */
  228.    linein = line;
  229.  
  230. /* branch by file type */
  231.    switch (TFilePtr->FileType) {
  232.       case TEXTTYPE: /* Unix text file */
  233. /* loop through buffer until hitting a LF */
  234.            next = (char *)(TFilePtr->Buffer + TFilePtr->BufferPos);
  235.            for (loop=0; loop<1000; loop++) {
  236.              if (TFilePtr->BufferPos>=TFilePtr->InBuffer) 
  237.            { /* read next buffer full */
  238.                 if (!TextFileBufferIn(TFilePtr)) { /* I/O failed */
  239.                     MessageShow ("Error reading text file");
  240.                      TextFileClose(TFilePtr);
  241.                      return 0;
  242.                      } /* end of I/O failed */
  243.                   next = (char *)(TFilePtr->Buffer);
  244.                   } /*end of read buffer */
  245.                if (TFilePtr->InBuffer<1) break; /* end of file? */
  246.                if (*next!=LF) 
  247.                   {count++; if (count<=maxchar) *line++ = *next; 
  248.            next++; 
  249.            TFilePtr->BufferPos++;}
  250.                else {TFilePtr->BufferPos++; break;}
  251.                } /* end of loop reading card */
  252.             *line = 0; /* terminating null */
  253.       /* done with file ?*/
  254.            if ((TFilePtr->InBuffer==0) && TFilePtr->HitEOF) {return -1;}
  255.            break;
  256.       case FITSTYPE: /* FITS file */
  257.            /* done? */
  258.            if ((TFilePtr->InBuffer==0) && TFilePtr->HitEOF) {return -1;}
  259.            /* Next 80 characters */
  260.            next = (char *)(TFilePtr->Buffer + TFilePtr->BufferPos);
  261.            for (loop=0; loop<80; loop++) {
  262.              if (TFilePtr->BufferPos>=TFilePtr->InBuffer) { /* read next buffer full */
  263.                 if (!TextFileBufferIn(TFilePtr)) { /* I/O failed */
  264.                     MessageShow ("Error reading text file");
  265.                      TextFileClose(TFilePtr);
  266.                      return 0;
  267.                      } /* end of I/O failed */
  268.                   next = (char *)(TFilePtr->Buffer);
  269.                   } /*end of read buffer */
  270.                if (TFilePtr->InBuffer<1) break; /* end of file? */
  271.                count++; 
  272.                if (count<=maxchar) *line++ = *next; 
  273.                next++; 
  274.                TFilePtr->BufferPos++;
  275.                } /* end of loop reading card */
  276.             *line = 0; /* terminating null */
  277.       /* done with file ? - check for "END     " card*/
  278.            if (!strncmp (linein, "END     ", 8)) 
  279.          {TFilePtr->InBuffer=0; TFilePtr->HitEOF = 1; return -1;}
  280.            break;
  281.       case DOSTEXTTYPE: /* line feeds in text file */
  282. /* loop through buffer until hitting a CR, drop LF */
  283.            next = (char *)(TFilePtr->Buffer + TFilePtr->BufferPos);
  284.            for (loop=0; loop<1000; loop++) {
  285.              if (TFilePtr->BufferPos>=TFilePtr->InBuffer) { /* read next buffer full */
  286.                 if (!TextFileBufferIn(TFilePtr)) { /* I/O failed */
  287.                     MessageShow ("Error reading text file");
  288.                      TextFileClose(TFilePtr);
  289.                      return 0;
  290.                      } /* end of I/O failed */
  291.                   next = (char *)(TFilePtr->Buffer);
  292.                   } /*end of read buffer */
  293.                if (TFilePtr->InBuffer<1) break; /* end of file? */
  294.                /*debug if (*next==LF) next++;  ignore line feeds */
  295.                if (*next!=LF) 
  296.                   {count++; if (count<=maxchar) *line++ = *next; 
  297.            next++; 
  298.            TFilePtr->BufferPos++;}
  299.                else {TFilePtr->BufferPos++; break;}
  300.                } /* end of loop reading card */
  301.             *line = 0; /* terminating null */
  302.       /* done with file ?*/
  303.            if ((TFilePtr->InBuffer==0) && TFilePtr->HitEOF) {return -1;}
  304.            break;
  305.       default: 
  306.            if ((TFilePtr->InBuffer==0) && TFilePtr->HitEOF) {return -1;}
  307.            sprintf (line, "Unknown file type ");
  308.            TFilePtr->InBuffer=0; 
  309.            TFilePtr->HitEOF = 1;
  310.            break;
  311.       }  /* end of branch by file type */
  312.    return 1;
  313. } /* end TextFileRead */
  314.   
  315. /* Write a line of text to a file                                          */ 
  316. /* returns 1 if OK, 0 if failed                                           */ 
  317. int TextFileWrite(TextFilePtr TFilePtr, char* line)
  318. {
  319.    long loop, count;
  320.    char *next, LF=10;
  321.  
  322.    if (!TFilePtr) return 0;   /* validity check */
  323.    if (TFilePtr->State!=2) {return 0;} /* Open write? */
  324.    count = strlen (line);
  325.    /* copy string to buffer flushing buffer when full */
  326.     next = (char *)(TFilePtr->Buffer + TFilePtr->BufferPos);
  327.    for (loop = 0; loop<count; loop++) {
  328.       if ((TFilePtr->BufferPos)+1>=TEXTBUFFER_SIZE) { /* flush buffer? */
  329.          if (!TextFileFlush(TFilePtr)) { /* I/O failed */
  330.             MessageShow ("Error writing text file");
  331.             TextFileClose(TFilePtr);
  332.             return 0;
  333.             } /* end of I/O failed */
  334.          next = (char *)(TFilePtr->Buffer);
  335.          } /* end flush buffer */
  336.  
  337.       *next++ = *line++; TFilePtr->BufferPos++;
  338.       } /* end loop copying string */
  339.    if ((TFilePtr->BufferPos)+1>=TEXTBUFFER_SIZE) { /* flush buffer? */
  340.       if (!TextFileFlush(TFilePtr)) { /* I/O failed */
  341.          MessageShow ("Error writing text file");
  342.          TextFileClose(TFilePtr);
  343.          return 0;
  344.          } /* end of I/O failed */
  345.       } /* end of flush buffer */
  346.    *next = LF; TFilePtr->BufferPos++;/* add LF */
  347.    return 1;
  348. } /* end TextFileWrite */
  349.  
  350. /* internal functions */
  351. /* Flush output buffer - TFilePtr already locked*/
  352. /* returns 1 if OK, 0 if failed */
  353. int TextFileFlush(TextFilePtr TFilePtr)
  354. {
  355.    long count;
  356.    size_t size, nout, number=1;
  357.    if (!TFilePtr) return 0;   /* validity check */
  358.    size = TFilePtr->BufferPos;
  359.    if (size<=0) return 1; /* nothing to do */
  360.    nout = fwrite ((const void*)TFilePtr->Buffer, size, number, 
  361.           TFilePtr->file);
  362.    if (nout!=1) return 0; /* write failed? */
  363.    TFilePtr->InBuffer = 0;
  364.    TFilePtr->BufferPos = 0;
  365.    return 1;
  366. } /* end TextFileFlush */
  367.  
  368. /* Read input buffer */
  369. /* returns 1 if OK, 0 if failed */
  370. int TextFileBufferIn(TextFilePtr TFilePtr)
  371. {
  372.    char CR=13, LF=10;
  373.    int hasSimple=0, hasCR=0, hasLF=0, hasBinary=0;
  374.    int count, i, nread, readret, error, nred;
  375.    unsigned char gzip_magic[2] = {"\037\213"}; /* gzip magic number */
  376.    cMemPtr test;
  377.  
  378.    if (!TFilePtr) return 0;   /* validity check */
  379.    if (TFilePtr->HitEOF) { /* previous EOF? */
  380.       TFilePtr->InBuffer = 0;
  381.       TFilePtr->BufferPos = 0;
  382.       return 1;}
  383.  
  384.    count = TEXTBUFFER_SIZE;
  385. /* regular or gzipped file? */
  386.   if (!TFilePtr->isGzip)
  387.     {nread = FileRead (TFilePtr->hFile, (MemPtr)TFilePtr->Buffer, count); 
  388.      error = nread==0; }
  389.   else
  390.     {nred = count;
  391.      readret = gz_read (&nred, (cMemPtr)TFilePtr->Buffer); /* read block */
  392.      nread = nred;
  393.      error = (readret != PR_SUCCESS) || (nread==0); }
  394.    
  395. /* look for magic number for gzip files on first read */
  396.   if ((!error) && TFilePtr->chkGzip) {
  397.     test = (cMemPtr)TFilePtr->Buffer;
  398.     TFilePtr->chkGzip = 0; /* only check first block */
  399.     if ((test[0]==gzip_magic[0]) && (test[1]==gzip_magic[1]))
  400.       { /* TFilePtr file is gzipped - set up */
  401.     TFilePtr->isGzip = 1; /* it's gzip compressed */
  402.     readret = FileSeek (TFilePtr->hFile, 0L);  /* reposition */
  403.     error = (readret != 1);
  404.     if (!error) readret = gz_init (TFilePtr->hFile);  /* init */
  405.     error = error || (readret != PR_SUCCESS);
  406.     if (!error) readret = gz_seek (0L); /* position */
  407.     error = error || (readret != PR_SUCCESS);
  408.     nred = count;
  409.     if (!error) readret = gz_read (&nred, (cMemPtr)TFilePtr->Buffer);
  410.     nread = nred;
  411.     error = error || (readret != PR_SUCCESS) || (nred==0);
  412.       }
  413.   } /* end of gzip check */
  414.  
  415. /*Error check */ 
  416.    if (nread<count) { /* hit EOF in read - some good data */
  417.       TFilePtr->HitEOF = 1; error = 0;}
  418.    if (error) return 0; /* read failed? */
  419.  
  420.    TFilePtr->InBuffer = nread;
  421.    TFilePtr->BufferPos = 0;
  422.  
  423.    /* determine file type if not known */
  424.    if (!TFilePtr->FileType) { /* determine file type from first buffer */
  425.      /* look for FITS intro */
  426.       hasSimple = (!strncmp ((char*)TFilePtr->Buffer, "SIMPLE  =      ", 15));
  427.       /* look for carrage return */
  428.       for (i=0;i<nread;i++) 
  429.     {if (TFilePtr->Buffer[i]==CR)
  430.        {hasCR = 1;  break;}}
  431.       /* look for line feed */
  432.       for (i=0;i<nread;i++) 
  433.     {if (TFilePtr->Buffer[i]==LF)
  434.        {hasLF = 1;  break;}}
  435.       /* look for binary values */
  436.       for (i=0;i<nread;i++) 
  437.     {if (TFilePtr->Buffer[i]>128)
  438.        {hasBinary = 1;  break;}}
  439.       /* decide type */
  440.       /* DOS has CR and LF */
  441.       if (hasCR && hasLF) TFilePtr->FileType = DOSTEXTTYPE;
  442.       /* Unix text has LF but no CR */
  443.       if ((!TFilePtr->FileType) && hasLF) TFilePtr->FileType = TEXTTYPE;
  444.       /* FITS has SIMPLE = ... but no CR or LF */
  445.       if ((!TFilePtr->FileType) && hasSimple) TFilePtr->FileType = FITSTYPE;
  446.       
  447.       /* check for bad file types */
  448.       if (hasBinary && (!hasSimple)) /* can't cope with binary files */
  449.     {MessageShow("Selected file appears to be neither text nor FITS");
  450.      return 0;}
  451.       if (!TFilePtr->FileType) /* Don't recognize text file type */
  452.     {MessageShow("Unrecognized text file type");
  453.      return 0;}
  454.       } /* end of determining file type */
  455.    return 1;
  456. } /* end TextFileBufferIn */
  457.   
  458. void TextFileOKCB (Widget filebox, XtPointer clientData, XtPointer callData)
  459. /* Gets file information and calls OKfunc if non NULL*/
  460. {
  461.   XmFileSelectionBoxCallbackStruct *cbs;
  462.   TextFilePtr TFilePtr = (TextFilePtr)clientData;
  463.   XPointer XPtr;
  464.   char *filename, *directory;
  465.   int i, length, first;
  466.  
  467.   cbs = (XmFileSelectionBoxCallbackStruct *) callData;
  468.  
  469. /* delete any old file names */
  470.   if (TFilePtr->FileName) free(TFilePtr->FileName);
  471.   if (TFilePtr->directory) free(TFilePtr->directory);
  472.  
  473. /* get file name */
  474.  if (!XmStringGetLtoR (cbs->value, XmSTRING_DEFAULT_CHARSET, &filename))
  475.    return; /* error */
  476. /* remove directory part of name */
  477.   length = strlen(filename);
  478.   first = 0;
  479.   for (i=0; i<length; i++) if (filename[i]=='/') first = i+1;
  480.   TFilePtr->FileName = (char*)malloc(length-first+2);
  481.   strcpy (TFilePtr->FileName,&filename[first]);
  482.  
  483. /* get directory name */
  484.   if (!XmStringGetLtoR (cbs->dir, XmSTRING_DEFAULT_CHARSET, &directory))
  485.     return; /* error */
  486.   TFilePtr->directory = directory;
  487.  
  488. /* ugly hack to save directory information */
  489.   if (TFilePtr->State==1)
  490.     {
  491.       if (!FITS_dir) FITS_dir = MakeString(" ");
  492.       StringFill(FITS_dir, directory); 
  493.     }
  494.   if (TFilePtr->State==2)
  495.     {
  496.       if (!log_dir) log_dir = MakeString(" ");
  497.       StringFill(log_dir, directory); 
  498.     }
  499.  
  500. /* Shazam disappear and die */
  501.   XtUnmanageChild (filebox); 
  502.   XtPopdown (XtParent (filebox)); 
  503.   XtDestroyWidget(filebox); 
  504.   XtFree(filename);
  505.  
  506. /* call func if specified */
  507.   XPtr = (XPointer)TFilePtr;
  508.   if (TFilePtr->OKfunc) TFilePtr->OKfunc(XPtr);
  509. } /* end FileOKCB */
  510.  
  511. void TextFileCancelCB (Widget filebox, XtPointer clientData, XtPointer callData)
  512. /* cancel file selection dialog box */
  513. /* deletes box and calls CancelFunc if non NULL*/
  514. {
  515.   TextFilePtr TFilePtr = (TextFilePtr)clientData;
  516.   XPointer XPtr;
  517.  
  518. /* Shazam disappear and die */
  519.   XtUnmanageChild (filebox); 
  520.   XtPopdown (XtParent (filebox)); 
  521.   XtDestroyWidget(filebox); 
  522.  
  523. /* call func if specified */
  524.   XPtr = (XPointer)TFilePtr;
  525.   if (TFilePtr->CancelFunc) TFilePtr->CancelFunc(XPtr);
  526. } /* end FileCancelCB */
  527.  
  528.