/****************************************************************************
*   Extract.c								    *
*   									    *
*   Chas A. Wyndham     18th Aug 1992. 					    *
*									    *	
*   Compiles under Lattice 5 and links with Decomp.o to make Hextract, a    *
*   programme for accessing header-file data.				    *
*									    *
*   This code is Freeware like Hextract itself.  You are welcome to improve *
*   it - but please send me a copy.					    *
*									    *
****************************************************************************/
  		
#include "exec/types.h"
#include "exec/memory.h"
#include "graphics/gfxbase.h"
#include "libraries/dos.h"
#include "intuition/intuition.h"
#include "intuition/intuitionbase.h"
#include "string.h"
#include "stdio.h"

struct IntuitionBase *IntuitionBase ;
struct GfxBase     *GfxBase ;
struct Screen      *screendata ; 
struct FileHandle  *window, *fi ;
char               buffer[100], line[256], *febuf=0, *inbuf=0 ;
int                found = 0, located = 0 ;
int                fesize, insize, n, libh = 0 ;

USHORT chip ptrImage[] = {  
	 0x0000, 0x0000,
	 0x6018, 0x0000,
	 0xc00c, 0x0000,
	 0xc30c, 0x0000,
	 0xc78c, 0x0000,
	 0xcccc, 0x0000,
	 0x7878, 0x0000,
	 0x3030, 0x0000,
	 0x0000, 0x0000,  };

void   search(), showlib(), getwin(), cleanup() ;
 
main(argc, argv)
int   argc ;
char  *argv[] ;
{
   char              ch = NULL, header[2], path[100] ;
   int               i = 0, result = 1, lockset = 0, win = 1, cont, iscomp = 0 ;
   struct FileLock   *lock, *oldlock ;
   struct FileHandle *fum ;
   BPTR              pathlock ;
   
   IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0) ;
   GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0) ;

   screendata = (struct Screen *)AllocMem(30, MEMF_PUBLIC) ;
   GetScreenData (screendata, 30, WBENCHSCREEN, NULL) ;
        
   stcgfp (path, argv[0]) ;
   if (strcmp (path, "")) 
    if (path[strlen(path)-1] !=':')
      strcat (path, "/") ;
   strcat (path, "headers.z") ;
   if ((lock = (struct FileLock *)Lock(path, ACCESS_READ)) == 0)
    { if ((pathlock = findpath("headers.z")) != -1)
       { oldlock = (struct FileLock *)CurrentDir("df0:", ACCESS_READ) ;
         CurrentDir((struct FileLock *)pathlock, ACCESS_READ) ;
         lockset = 1 ;
       }
    }     
   else UnLock (lock) ;   
   
   if ((fi = (struct FileHandle *)Open(path, MODE_OLDFILE)) == NULL) 
     { puts ("No headers.z file\n") ;
       cleanup()  ;
     }

   Seek (fi, 0, 1) ;
   insize = Seek (fi, 0, -1) ;
   Read (fi, &header, 2); 
   if ((header[0] == 'L') && (header[1] == 'H'))
     { iscomp = 1 ;
       Read (fi, &fesize, 4) ;
       fesize = fesize + 4 ;
       Seek (fi, 2, -1) ;
       insize = insize - 2 ;
     }
   else   Seek (fi, 0, -1) ;

   if ((inbuf = (char *)AllocMem(insize, MEMF_PUBLIC)) == NULL)
     { puts ("Insufficient memory\n") ;
       cleanup() ;
     }
    
   Read (fi, inbuf, insize) ;

   if (iscomp)
    { if ((febuf = (char *)AllocMem((fesize), MEMF_PUBLIC)) == NULL)
       { puts ("Insufficient memory\n") ;
         cleanup() ;
       }
      if (iscomp)
        {  SetPointer (IntuitionBase->ActiveWindow, &ptrImage, 7, 16, -4, -4) ;
           result = DECOMPA (inbuf, febuf) ;
           ClearPointer(IntuitionBase->ActiveWindow) ;
           FreeMem (inbuf, insize) ;
        }           
    }
   else
       { febuf = inbuf ;
         fesize = insize ;
       }

   Close (fi) ;
   if      (result == 0)  puts ("Decompression failed\n") ;
   else if (result == 2)  puts ("Out of memory\n") ;
    
   if (argc == 2)
    { fum = (struct FileHandle *)Open(argv[1], MODE_NEWFILE) ;
      Write (fum, febuf, fesize) ;
      Close (fum) ;
    } 

   window = (struct FileHandle *)Open
       ("CON:100/0/344/30/Hextract V1.2 - Enter 'quit' to exit", MODE_NEWFILE) ;
   Write (window, "\n Enter symbol: ", 15) ;
   if (lockset)
     { CurrentDir (oldlock, ACCESS_READ) ;
       UnLock ((struct FileLock *)pathlock) ;
     }
   
   while (1)
    { cont = 0 ;  n = 0 ;
      if (WaitForChar (window, 999999999)) 
      { Read (window, &ch, 1) ;
        buffer[i++] = ch ;
        if (ch == '\n')
         { /*Ctime (1) ;*/
          buffer[--i] = '\0' ;
          if (i)
           { if (!stricmp (buffer, "quit"))   cleanup() ;
             else
              { if (!stricmp (buffer, "ok"))
                {
                 if (!win) 
                  { Close(window) ;
                    window = (struct FileHandle *)Open("CON:100/0/400/30/Hextract V1.2", MODE_NEWFILE) ;
                    Write (window, "\n  Enter symbol: ", 17) ;
                    win = 1 ;  cont = 1 ;
                  }
                 else { i = 0 ; continue ; }
                }
                if (!cont)
                 { if (win)
                    { Close (window) ;
                      getwin() ;
                      win = 0 ;
                      Write (window, "\n     ", 6) ;
                      Write (window, buffer, strlen(buffer)) ;
                      Write (window, "\n", 1) ;
                    }  
                   SetPointer (IntuitionBase->ActiveWindow, &ptrImage, 7, 16, -4, -4) ;
                   search () ; 
                   memset (buffer, '\0', 100) ;
                   ClearPointer(IntuitionBase->ActiveWindow) ;
                   Write (window, "\n  Enter symbol\n\n   ", 19) ;
              } }
             i = 0 ; 
            } /*Cend(1) ;*/
          } 
     } }

   cleanup() ;
}

void getwin()
{
   if (screendata->Height > 511)
    window = (struct FileHandle *)Open("CON:0/0/640/512/Hextract V1.2", MODE_NEWFILE) ;
   else if (screendata->Height >399)
    window = (struct FileHandle *)Open("CON:0/0/640/400/Hextract V1.2", MODE_NEWFILE) ;
   else if (screendata->Height >255)
    window = (struct FileHandle *)Open("CON:0/0/640/256/Hextract V1.2", MODE_NEWFILE) ;
   else 
    window = (struct FileHandle *)Open("CON:0/0/640/200/Hextract V1.2", MODE_NEWFILE) ;
}


void cleanup ()
{
     FreeMem (screendata, 30) ;
     if (febuf)  FreeMem (febuf, fesize) ;
     if (window)  Close (window) ;
     if (GfxBase != NULL) CloseLibrary(GfxBase);
     if (IntuitionBase != NULL) CloseLibrary(IntuitionBase);
     /*Creport() ;*/
     exit(0);
}

void search()
{  
   char   *tok, *tok2, temp[256], *buf1, source[40], change = 0 ; 
   int    numbrackets = 0, libh ;

   located = 0 ;
   libh = 0 ;  
   while (fgts (line) != 0)
    { /*Ctime(2) ;*/ 
      onbreak(&cleanup) ;
      chkabort() ;
      buf1 = stpblk(line) ;
      if (!change)
        if (!strcmp (buf1, "FF\n"))   change = 1 ; 

      if (change)
       { if (stcpmw (buffer,".??????"))
          { showlib() ;
            break ;
          }  
         if (stcpmw (buf1, ".??????")) 
          { tok = strtok (buf1, " \n") ;
            strcpy (source, tok) ;
            libh = 1 ;
          }
       }
      /*Cend(2) ;*/  
      strcpy (temp, buf1) ;
      tok = strtok (temp, " \n") ;
      if (stcpmwa (temp,buffer))
       { located = 1 ;        
         strcpy (temp, line) ;
         tok = strtok (line, " \n") ;
         tok2 = strtok (NULL, "\n") ;
         Write (window, "\n   ", 4) ; 
         Write (window, tok2, strlen(tok2)) ;
         if (libh)
          { Write (window, "  ", 2) ;
            Write (window, source, strlen(source)) ;
          }
         Write (window, "\n", 1) ;

         if (stcpmw (temp, "struct")) 
          { fgts (temp) ;
            if (strchr (temp, '{'))
             { numbrackets++ ;
               Write (window, "    ", 4) ; 
               Write (window, temp, strlen(temp)) ;
               while  (numbrackets) 
                { fgts (temp) ;
                  if (strchr (temp, '{'))
                   { numbrackets++ ;
                     Write (window, "    ", 4) ;
                     Write (window, temp, strlen(temp)) ;
                     continue ;
                   }
                  else if (strchr (temp, '}'))
                   { numbrackets-- ;
                     Write (window, temp, strlen(temp)) ;
                     continue ;
                   }

                  tok = strtok (temp, " \0") ;
                  tok2 = strtok (NULL, " \0") ;
                  Write (window, "    ", 4) ;
                  Write (window, tok2, strlen(tok2)) ;

                  do
                   { tok2 = strtok (NULL, " \0") ;
                     if (stcpmw (tok2, "struct"))
                       { Write (window, "\n", 1) ;
                         break ;
                       } 
                     Write (window, " ", 1) ;
                     Write (window, tok2, strlen(tok2)) ;
                   } while (tok2) ; 
             }  }
          }

         tok = strtok (line, " \n") ;
         tok2 = strtok (NULL, "\n") ;
         Write (window, "\n       ", 8) ; 
         Write (window, tok2, strlen(tok2)) ;
      } 
    }
   if (!located)  Write (window, "        Not found\n", 18) ;
}


void showlib()
{
  char  *tok1, *tok2, buf[256] ;
  int num, i ;

  
  if (stcpmw (buffer,".device") || stcpmw (buffer,".resource")
                                      || stcpmw (buffer,".library"))
    { while (!stcpmw (line, buffer))
       if (!fgts (line)) {  libh = 0 ;  return ; }
    }
  else { libh = 0 ;
         return ;
       } 
   
  tok1 = strtok (line, " \n") ;
  tok2 = strtok (NULL, " \n") ;
  num = atoi (tok2) ;
  for (i = 0 ; i < num ; ++i)
   { fgts (buf) ;
     tok1 = strtok (buf, " \n") ;
     tok2 = strtok (NULL, "\0") ;
     Write (window, "   ", 3) ;
     Write (window, tok2, strlen(tok2)) ;
   }
  located = 1 ;
}
