home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / dirs / lhlib_436.lzh / LhLib / LhEncode.c < prev    next >
C/C++ Source or Header  |  1991-01-15  |  18KB  |  834 lines

  1. /* $Revision Header * Header built automatically - do not edit! *************
  2.  *
  3.  *    (C) Copyright 1990 by Holger P. Krekel & Olaf 'Olsen' Barthel
  4.  *
  5.  *    Name .....: LhEncode.c
  6.  *    Created ..: Wednesday 11-Jul-90 19:40
  7.  *    Revision .: 0
  8.  *
  9.  *    Date            Author          Comment
  10.  *    =========       ========        ====================
  11.  *    11-Jul-90       Olsen           Created this file!
  12.  *
  13.  * $Revision Header ********************************************************/
  14.  
  15.     /* ARP cli template and help information. */
  16.  
  17. char *CLI_Template    = "FROM,TO,N=NoQuery/S,F=Faster/S,H=Header/S";
  18. char *CLI_Help        = "\n\33[33m\33[1mLhEncode \33[0m\33[31m© Copyright 1990 by Holger P. Krekel & Olaf Barthel,\n\
  19.            All rights reserved.\n\n\
  20. Usage: \33[1mLhEncode\33[0m [File or wildcard pattern] [File/directory name]\n\
  21.                 [FASTER] [HEADER] [NOQUERY]\n";
  22.  
  23.     /* Argument vector offsets. */
  24.  
  25. #define ARG_FROM    1
  26. #define ARG_TO        2
  27. #define ARG_NOQUERY    3
  28. #define ARG_FASTER    4
  29. #define ARG_HEADER    5
  30.  
  31.     /* Global and shared data. */
  32.  
  33. struct Library        *LhBase;
  34. struct timerequest    *TimeRequest;
  35. struct MsgPort        *TimePort;
  36. struct Device        *TimerBase;
  37. struct FileRequester    *FileRequester;
  38. struct LhBuffer        *LhBuffer;
  39. BYTE             Faster,Header,Query = TRUE;
  40. ULONG             TotalSecs = 0,TotalMicros = 0;
  41. LONG             TotalRatio,NumEntries = 0;
  42.  
  43.     /* Linked list of file names. */
  44.  
  45. struct NameLink         *RootLink;
  46. char            **NameList;
  47. LONG              NumNames = 0;
  48.  
  49.     /* Function prototypes. */
  50.  
  51. extern int         SubCmp();
  52. LONG             StrCmp(char **Str1,char **Str2);
  53. BYTE             BuildList(VOID);
  54. VOID             FreeLinks(VOID);
  55. BYTE             ScanDir(char *Pattern);
  56. LONG             GetFileSize(char *Name);
  57. BYTE             SetRawMode(BYTE Mode);
  58. BYTE             Encode(char *Src,char *Dst);
  59. VOID             main(int argc,char **argv);
  60.  
  61.     /* Stub routines. */
  62.  
  63. LONG Chk_Abort(VOID)    { return(0); }
  64. VOID _wb_parse(VOID)    {}
  65.  
  66.     /* Assembly language fragment to be used by the QSort
  67.      * routine.
  68.      */
  69.  
  70. #asm
  71.     xdef    _SubCmp
  72.  
  73. _SubCmp:movem.l    d2-d7/a2-a6,-(sp)
  74.     movem.l    a0/a1,-(sp)
  75.  
  76.     jsr    _geta4#
  77.     jsr    _StrCmp
  78.  
  79.     add.w    #8,sp
  80.  
  81.     movem.l    (sp)+,d2-d7/a2-a6
  82.     rts
  83. #endasm
  84.  
  85.     /* StrCmp():
  86.      *
  87.      *    Compare two strings ignoring case (international).
  88.      */
  89.  
  90. LONG
  91. StrCmp(char **Str1,char **Str2)
  92. {
  93.     char *a = *Str1,*b = *Str2;
  94.  
  95.     for( ; ToUpper(*a) == ToUpper(*b) ; a++, b++)
  96.     {
  97.         if(!(*a))
  98.             return(0);
  99.     }
  100.  
  101.     return(ToUpper(*a) - ToUpper(*b));
  102. }
  103.  
  104.     /* BuildList():
  105.      *
  106.      *    Build an array of string pointers to be passed to the
  107.      *    QSort function by scanning a linked list of names.
  108.      */
  109.  
  110. BYTE
  111. BuildList()
  112. {
  113.     struct NameLink    *TempLink;
  114.  
  115.     for(TempLink = RootLink ; TempLink ; TempLink = TempLink -> Next)
  116.         NumNames++;
  117.  
  118.     if(NameList = (char **)ArpAlloc(NumNames * sizeof(char *)))
  119.     {
  120.         NumNames = 0;
  121.  
  122.         for(TempLink = RootLink ; TempLink ; TempLink = TempLink -> Next)
  123.         {
  124.             if(NameList[NumNames] = (char *)ArpAlloc(strlen(TempLink -> Name) + 1))
  125.                 strcpy(NameList[NumNames++],TempLink -> Name);
  126.             else
  127.                 return(FALSE);
  128.         }
  129.  
  130.         return(QSort(NameList,NumNames,sizeof(char *),SubCmp));
  131.     }
  132.  
  133.     return(FALSE);
  134. }
  135.  
  136.     /* FreeLinks():
  137.      *
  138.      *    Free the linked list of names created by the directory
  139.      *    scanner.
  140.      */
  141.  
  142. VOID
  143. FreeLinks()
  144. {
  145.     struct NameLink *TempLink,*LastLink = NULL;
  146.  
  147.     for(TempLink = RootLink ; TempLink ; TempLink = LastLink)
  148.     {
  149.         LastLink = TempLink -> Next;
  150.  
  151.         FreeMem(TempLink,sizeof(struct NameLink));
  152.     }
  153. }
  154.  
  155.     /* ScanDir():
  156.      *
  157.      *    Scan a directory for a given pattern and build a linked
  158.      *    list of the names.
  159.      */
  160.  
  161. BYTE
  162. ScanDir(char *Pattern)
  163. {
  164.     struct NameLink    *LastLink = NULL;
  165.     char        *Temp;
  166.  
  167.     while(Temp = scdir(Pattern))
  168.     {
  169.         if(SetSignal(0,0) & SIGBREAKF_CTRL_C)
  170.         {
  171.             SetSignal(0,SIGBREAKF_CTRL_C);
  172.  
  173.             Puts("\n*** BREAK: LhEncode\a");
  174.  
  175.             return(FALSE);
  176.         }
  177.  
  178.         if(SetSignal(0,0) & SIGBREAKF_CTRL_D)
  179.         {
  180.             SetSignal(0,SIGBREAKF_CTRL_D);
  181.             return(TRUE);
  182.         }
  183.  
  184.         if(RootLink)
  185.         {
  186.             struct NameLink *NextLink;
  187.  
  188.             if(NextLink = (struct NameLink *)AllocMem(sizeof(struct NameLink),MEMF_PUBLIC | MEMF_CLEAR))
  189.             {
  190.                 LastLink -> Next = NextLink;
  191.  
  192.                 strcpy(NextLink -> Name,Temp);
  193.  
  194.                 LastLink = NextLink;
  195.             }
  196.             else
  197.                 return(TRUE);
  198.         }
  199.         else
  200.         {
  201.             if(RootLink = (struct NameLink *)AllocMem(sizeof(struct NameLink),MEMF_PUBLIC | MEMF_CLEAR))
  202.             {
  203.                 strcpy(RootLink -> Name,Temp);
  204.  
  205.                 LastLink = RootLink;
  206.             }
  207.             else
  208.                 return(TRUE);
  209.         }
  210.     }
  211.  
  212.     return(TRUE);
  213. }
  214.  
  215.     /* GetFileSize():
  216.      *
  217.      *    Asks the DOS to return the length of a given file.
  218.      */
  219.  
  220. LONG
  221. GetFileSize(char *Name)
  222. {
  223.     struct FileInfoBlock    *FileInfo;
  224.     BPTR             FileLock;
  225.     LONG             FileSize = 0;
  226.  
  227.     if(FileInfo = (struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC))
  228.     {
  229.         if(FileLock = Lock(Name,ACCESS_READ))
  230.         {
  231.             if(Examine(FileLock,FileInfo))
  232.                 FileSize = FileInfo -> fib_Size;
  233.  
  234.             UnLock(FileLock);
  235.         }
  236.  
  237.         FreeMem(FileInfo,sizeof(struct FileInfoBlock));
  238.     }
  239.  
  240.     return(FileSize);
  241. }
  242.  
  243.     /* SetRawMode():
  244.      *
  245.      *    Toggles between raw (single character) and 'cooked'
  246.      *    (line input) data input from a console window.
  247.      */
  248.  
  249. BYTE
  250. SetRawMode(BYTE Mode)
  251. {
  252.     LONG Args[7];
  253.  
  254.     if(Mode)
  255.         Args[0] = DOSTRUE;
  256.     else
  257.         Args[0] = DOSFALSE;
  258.  
  259.     return(SendPacket(ACTION_SCREEN_MODE,Args,(struct MsgPort *)((struct Process *)SysBase -> ThisTask) -> pr_ConsoleTask));
  260. }
  261.  
  262.     /* Encode():
  263.      *
  264.      *    Encode a file for later usage (by any application or
  265.      *    by LhDecode).
  266.      */
  267.  
  268. BYTE
  269. Encode(char *Src,char *Dst)
  270. {
  271.     BPTR         In,Out;
  272.     LONG         FromSize;
  273.     LONG        *From,*To;
  274.  
  275.     LONG         Secs,Micros;
  276.     BYTE         Ratio;
  277.  
  278.     struct timeval     Req1,Req2;
  279.  
  280.     char         TempName[MaxInputBuf];
  281.     BPTR         CheckLock;
  282.  
  283.     Printf("%-31.31s ",BaseName(Src));
  284.  
  285.         /* How long is our source file? */
  286.  
  287.     if(!(FromSize = GetFileSize(Src)))
  288.     {
  289.         Printf("\33[33munable to examine file (Error %ld)\33[31m\a\n",IoErr());
  290.  
  291.         return(TRUE);
  292.     }
  293.  
  294.         /* Allocate memory for the source buffer. */
  295.  
  296.     if(!(From = AllocMem(FromSize,MEMF_PUBLIC)))
  297.     {
  298.         Printf("\33[33mout of memory (Error 103)\33[31m\a\n");
  299.  
  300.         return(TRUE);
  301.     }
  302.  
  303.         /* Allocate memory for the destination buffer.
  304.          * Note: must be 1/8 larger than the source buffer.
  305.          */
  306.  
  307.     if(!(To = AllocMem(FromSize + ENCODEEXTRA(FromSize),MEMF_PUBLIC|MEMF_CLEAR)))
  308.     {
  309.         FreeMem(From,FromSize);
  310.  
  311.         Printf("\33[33mout of memory (Error 103)\33[31m\a\n");
  312.  
  313.         return(TRUE);
  314.     }
  315.  
  316.         /* Open the file for reading. */
  317.  
  318.     if(!(In = Open(Src,MODE_OLDFILE)))
  319.     {
  320.         FreeMem(From,FromSize);
  321.         FreeMem(To,FromSize + ENCODEEXTRA(FromSize));
  322.  
  323.         Printf("\33[33munable to open file (Error %ld)\33[31m\a\n",IoErr());
  324.  
  325.         return(TRUE);
  326.     }
  327.  
  328.         /* Read the data to be encoded. */
  329.  
  330.     if(Read(In,From,FromSize) != FromSize)
  331.     {
  332.         LONG Error = IoErr();
  333.  
  334.         Close(In);
  335.  
  336.         FreeMem(From,FromSize);
  337.         FreeMem(To,FromSize + ENCODEEXTRA(FromSize));
  338.  
  339.         Printf("\33[33munable to read file (Error %ld)\33[31m\a\n",Error);
  340.  
  341.         return(TRUE);
  342.     }
  343.  
  344.     Close(In);
  345.  
  346.         /* Initialize the LhBuffer structure. */
  347.  
  348.     LhBuffer -> lh_Src    = From;
  349.     LhBuffer -> lh_SrcSize    = FromSize;
  350.     LhBuffer -> lh_Dst    = To;
  351.  
  352.     Printf("\33[33m%07ld\33[31m Encode ",FromSize);
  353.  
  354.         /* If 'faster' encoding selected, disable interrupts
  355.          * and system DMA.
  356.          */
  357.  
  358.     if(Faster)
  359.     {
  360.         custom . dmacon = BITCLR|DMAF_ALL;
  361.         Disable();
  362.         custom . color[0] = 0;
  363.     }
  364.  
  365.         /* Remember starting time. */
  366.  
  367.     DoIO(TimeRequest);
  368.  
  369.     Req1 = TimeRequest -> tr_time;
  370.  
  371.         /* Encode the data. */
  372.  
  373.     LhEncode(LhBuffer);
  374.  
  375.         /* Remember finishing time. */
  376.  
  377.     DoIO(TimeRequest);
  378.  
  379.     Req2 = TimeRequest -> tr_time;
  380.  
  381.         /* Reenable DMA and interrupts. */
  382.  
  383.     if(Faster)
  384.     {
  385.         custom . dmacon = BITSET|DMAF_ALL;
  386.         Enable();
  387.     }
  388.  
  389.         /* Subtract both time values. */
  390.  
  391.     SubTime(&Req2,&Req1);
  392.  
  393.         /* Calculate time and compression ration. */
  394.  
  395.     Ratio    = 100 - (100 * LhBuffer -> lh_DstSize) / FromSize;
  396.  
  397.     Secs    = Req2 . tv_secs;
  398.     Micros    = Req2 . tv_micro / 10000;
  399.  
  400.     Printf("\33[33m%02ld%%\33[31m %02ld:%02ld:%02ld ",(Ratio < 0 ? 0 : Ratio),Secs / 60,Secs % 60,Micros);
  401.  
  402.         /* File didn't gain any size -> exit. */
  403.  
  404.     if(LhBuffer -> lh_DstSize >= FromSize)
  405.     {
  406.         FreeMem(From,FromSize);
  407.         FreeMem(To,FromSize + ENCODEEXTRA(FromSize));
  408.  
  409.         Printf("\33[33m-------\33[31m \33[1moverflow!\33[0m\a\n");
  410.  
  411.         return(TRUE);
  412.     }
  413.  
  414.         /* Add them for the statistics. */
  415.  
  416.     TotalRatio    += Ratio;
  417.  
  418.     TotalSecs    += Secs;
  419.     TotalMicros    += Micros;
  420.  
  421.     NumEntries++;
  422.  
  423.         /* ^C pressed = abort. */
  424.  
  425.     if(SetSignal(0,0) & SIGBREAKF_CTRL_C)
  426.     {
  427.         FreeMem(From,FromSize);
  428.         FreeMem(To,FromSize + ENCODEEXTRA(FromSize));
  429.  
  430.         SetSignal(0,SIGBREAKF_CTRL_C);
  431.         Puts("\n*** BREAK: LhEncode\a");
  432.  
  433.         return(FALSE);
  434.     }
  435.  
  436.         /* Check if we are about to overwrite an existing file. */
  437.  
  438.     if(Query)
  439.     {
  440.         if(CheckLock = Lock(Dst,ACCESS_READ))
  441.         {
  442.             UnLock(CheckLock);
  443.  
  444.             SetRawMode(TRUE);
  445.  
  446.             Printf("\2331A\n\23332C\233KOverwrite (\33[33mN\33[31mo/\33[33mY\33[31mes/\33[33mC\33[31mhange) ? ");
  447.  
  448.                 /* Read a character. */
  449.  
  450. Ask:            if(Read(((struct Process *)SysBase -> ThisTask) -> pr_CIS,TempName,1) > 0)
  451.             {
  452.                 if(toupper(TempName[0]) == 'Y')
  453.                 {
  454.                     Printf("\2331A\n\23332C\233K\33[33m%07ld\33[31m Encode \33[33m%02ld%%\33[31m %02ld:%02ld:%02ld ",FromSize,(Ratio < 0 ? 0 : Ratio),Secs / 60,Secs % 60,Micros);
  455.  
  456.                     SetRawMode(FALSE);
  457.  
  458.                     goto GoOn;
  459.                 }
  460.  
  461.                 if(toupper(TempName[0]) == 'N' || !TempName[0] || TempName[0] == '\n')
  462.                     goto Nope;
  463.  
  464.                 if(toupper(TempName[0]) != 'C')
  465.                     goto Ask;
  466.  
  467.                     /* Ask for a new name to save the file
  468.                      * under.
  469.                      */
  470.  
  471.                 Printf("\2331A\n\233KNew Name: %s\2331A\n\23310C",Dst);
  472.  
  473.                 SetRawMode(FALSE);
  474.  
  475.                 ReadLine(TempName);
  476.  
  477.                 if(!TempName[0] || TempName[0] == '\n')
  478.                 {
  479.                     strcpy(TempName,Dst);
  480.                     Printf("\2331A\233K");
  481.                 }
  482.  
  483.                 Dst = TempName;
  484.  
  485.                 Printf("\2331A\n\233K%-31.31s \33[33m%07ld\33[31m Encode \33[33m%02ld%%\33[31m %02ld:%02ld:%02ld ",BaseName(Dst),FromSize,(Ratio < 0 ? 0 : Ratio),Secs / 60,Secs % 60,Micros);
  486.  
  487.                 goto GoOn;
  488.             }
  489.  
  490.                 /* Free the buffers and return. */
  491.  
  492. Nope:            FreeMem(From,FromSize);
  493.             FreeMem(To,FromSize + ENCODEEXTRA(FromSize));
  494.  
  495.             Printf("\2331A\n\23332C\33[1m\233KSkipped\33[0m\n");
  496.  
  497.             SetRawMode(FALSE);
  498.  
  499.             return(TRUE);
  500.         }
  501.     }
  502.  
  503.         /* Open the output file. */
  504.  
  505. GoOn:    if(!(Out = Open(Dst,MODE_NEWFILE)))
  506.     {
  507.         FreeMem(From,FromSize);
  508.         FreeMem(To,FromSize + ENCODEEXTRA(FromSize));
  509.  
  510.         Printf("\33[33m\nERROR:\33[31m Unable to open file (Error %ld)\a\n",IoErr());
  511.  
  512.         return(TRUE);
  513.     }
  514.  
  515.         /* Add a size header. */
  516.  
  517.     if(Header)
  518.     {
  519.         ULONG TempSize = FromSize | 0xFF000000;
  520.  
  521.             /* Write header, note: size can occupy max. 24
  522.              * bits.
  523.              */
  524.  
  525.         if(Write(Out,&TempSize,sizeof(ULONG)) != sizeof(ULONG))
  526.         {
  527.             LONG Error = IoErr();
  528.  
  529.             Close(Out);
  530.  
  531.             FreeMem(From,FromSize);
  532.             FreeMem(To,FromSize + ENCODEEXTRA(FromSize));
  533.  
  534.             Printf("\33[33m\nERROR:\33[31m Unable to save file (Error %ld)\a\n",Error);
  535.  
  536.             DeleteFile(Dst);
  537.  
  538.             return(TRUE);
  539.         }
  540.     }
  541.  
  542.         /* Write the file to disk. */
  543.  
  544.     if(Write(Out,To,LhBuffer -> lh_DstSize) != LhBuffer -> lh_DstSize)
  545.     {
  546.         LONG Error = IoErr();
  547.  
  548.         Close(Out);
  549.  
  550.         FreeMem(From,FromSize);
  551.         FreeMem(To,FromSize + ENCODEEXTRA(FromSize));
  552.  
  553.         Printf("\33[33m\nERROR:\33[31m Unable to save file (Error %ld)\a\n",Error);
  554.  
  555.         DeleteFile(Dst);
  556.  
  557.         return(TRUE);
  558.     }
  559.  
  560.     Close(Out);
  561.  
  562.         /* Free the buffers and return. That was pretty painless,
  563.          * wasn't it?
  564.          */
  565.  
  566.     FreeMem(From,FromSize);
  567.     FreeMem(To,FromSize + ENCODEEXTRA(FromSize));
  568.  
  569.     Printf("\33[33m%07ld\33[31m Done.\n",LhBuffer -> lh_DstSize);
  570.  
  571.     return(TRUE);
  572. }
  573.  
  574. VOID
  575. main(int argc,char **argv)
  576. {
  577.     char Match[DSIZE],TempName[DSIZE * 5 + FCHARS],TempName2[DSIZE * 5 + FCHARS],TempName3[DSIZE * 5 + FCHARS],*ToFile;
  578.     BYTE Success = RETURN_FAIL;
  579.  
  580.     if(!argc)
  581.         exit(-1);
  582.  
  583.     Enable_Abort = FALSE;
  584.  
  585.         /* Faster decompression? */
  586.  
  587.     if(argv[ARG_FASTER])
  588.         Faster = TRUE;
  589.     else
  590.         Faster = FALSE;
  591.  
  592.         /* Put a 8 + 24 bit size header in front of the
  593.          * compressed file?
  594.          */
  595.  
  596.     if(argv[ARG_HEADER])
  597.         Header = TRUE;
  598.     else
  599.         Header = FALSE;
  600.  
  601.         /* Don't ask before overwriting a file? */
  602.  
  603.     if(argv[ARG_NOQUERY])
  604.         Query = FALSE;
  605.  
  606.         /* If the destination argument is omitted, we'll assume
  607.          * that we will decompress into the current directory.
  608.          */
  609.  
  610.     if(argv[ARG_TO])
  611.         ToFile = argv[ARG_TO];
  612.     else
  613.     {
  614.         if(PathName(((struct Process *)SysBase -> ThisTask) -> pr_CurrentDir,TempName3,DSIZE * 5))
  615.             ToFile = TempName3;
  616.         else
  617.         {
  618.             Puts("\33[1mLhEncode:\33[0m Destination file/directory name required.\a");
  619.             exit(RETURN_ERROR);
  620.         }
  621.     }
  622.  
  623.     Puts("\n\33[33m\33[1mLhEncode \33[0m\33[31m© Copyright 1990 by Holger P. Krekel & Olaf Barthel,\n           All rights reserved.\n");
  624.  
  625.         /* Open lh.library (most important call in this program). */
  626.  
  627.     if(LhBase = (struct Library *)ArpOpenLibrary(LH_NAME,LH_VERSION))
  628.     {
  629.             /* Create an LhBuffer for data compression. */
  630.  
  631.         if(LhBuffer = (struct LhBuffer *)CreateBuffer(FALSE))
  632.         {
  633.             if(FileRequester = ArpAllocFreq())
  634.             {
  635.                 if(TimePort = CreatePort(NULL,0))
  636.                 {
  637.                     if(TimeRequest = (struct timerequest *)CreateExtIO(TimePort,sizeof(struct timerequest)))
  638.                     {
  639.                             /* Open the timer.device, we will need it for
  640.                              * stopwatch functions.
  641.                              */
  642.  
  643.                         if(!OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,0))
  644.                         {
  645.                             TimerBase = TimeRequest -> tr_node . io_Device;
  646.  
  647.                             TimeRequest -> tr_node . io_Command = TR_GETSYSTIME;
  648.  
  649.                                 /* We got a source argument, no need to call the
  650.                                  * ARP file requester.
  651.                                  */
  652.  
  653.                             if(argv[ARG_FROM])
  654.                             {
  655.                                 struct FileInfoBlock    *FileInfo;
  656.                                 BPTR             FileLock;
  657.                                 BYTE             IsDir = FALSE,GotIt = FALSE,IsWild;
  658.  
  659.                                         /* Check if destination is a file or
  660.                                          * a directory.
  661.                                          */
  662.  
  663.                                 if(FileInfo = (struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC))
  664.                                 {
  665.                                     if(FileLock = Lock(ToFile,ACCESS_READ))
  666.                                     {
  667.                                         GotIt = TRUE;
  668.  
  669.                                         if(Examine(FileLock,FileInfo))
  670.                                             IsDir = (FileInfo -> fib_DirEntryType > 0);
  671.  
  672.                                         UnLock(FileLock);
  673.                                     }
  674.  
  675.                                     FreeMem(FileInfo,sizeof(struct FileInfoBlock));
  676.                                 }
  677.  
  678.                                         /* Check if source is a plain file name
  679.                                          * or a wildcard expression.
  680.                                          */
  681.  
  682.                                 IsWild = PreParse(argv[ARG_FROM],Match);
  683.  
  684.                                         /* Strange... */
  685.  
  686.                                 if(IsWild && !GotIt)
  687.                                 {
  688.                                     Puts("\33[1mLhEncode:\33[0m Unable to find destination directory!\a");
  689.                                     goto Quit;
  690.                                 }
  691.  
  692.                                         /* Send a bunch of files to a single file? */
  693.  
  694.                                 if(IsWild && !IsDir)
  695.                                 {
  696.                                     Puts("\33[1mLhEncode:\33[0m Destination is not a directory!\a");
  697.                                     goto Quit;
  698.                                 }
  699.  
  700.                                         /* Source is a plain file. */
  701.  
  702.                                 if(!IsWild)
  703.                                 {
  704.                                     Puts("\33[33mEncoding\33[31m - press \33[1mCTRL-C\33[0m to abort.\n");
  705.  
  706.                                     Puts("File Name                       Size    Mode    %  Time     Result \n------------------------------- ------- ------ --- -------- -------");
  707.  
  708.                                     strcpy(TempName,ToFile);
  709.  
  710.                                     if(IsDir)
  711.                                         TackOn(TempName,BaseName(argv[ARG_FROM]));
  712.  
  713.                                     if(Encode(argv[ARG_FROM],TempName))
  714.                                         Success = RETURN_OK;
  715.                                 }
  716.                                 else
  717.                                 {
  718.                                     LONG i;
  719.  
  720.                                     Success = RETURN_OK;
  721.  
  722.                                     Printf("\33[33mScanning\33[31m - press \33[1mCTRL-D\33[0m to stop, \33[1mCTRL-C\33[0m to abort... ");
  723.  
  724.                                             /* Source is a wildcard expression,
  725.                                              * start the directory scanner.
  726.                                              */
  727.  
  728.                                     if(!ScanDir(argv[ARG_FROM]))
  729.                                         exit(RETURN_WARN);
  730.  
  731.                                     Printf("Sorting.\n");
  732.  
  733.                                             /* Convert the linked list and sort
  734.                                              * it.
  735.                                              */
  736.  
  737.                                     BuildList();
  738.  
  739.                                     Puts("\2331A\233K\33[33mEncoding\33[31m - press \33[1mCTRL-C\33[0m to abort.\n");
  740.  
  741.                                     Puts("File Name                       Size    Mode    %  Time     Result \n------------------------------- ------- ------ --- -------- -------");
  742.  
  743.                                     for(i = 0 ; i < NumNames ; i++)
  744.                                     {
  745.                                         strcpy(TempName,ToFile);
  746.  
  747.                                         if(IsDir)
  748.                                             TackOn(TempName,BaseName(NameList[i]));
  749.  
  750.                                         if(!Encode(NameList[i],TempName))
  751.                                         {
  752.                                             Success = RETURN_FAIL;
  753.                                             break;
  754.                                         }
  755.                                     }
  756.  
  757.                                     FreeLinks();
  758.  
  759.                                     if(!Success)
  760.                                     {
  761.                                         TotalSecs    += TotalMicros / 100;
  762.                                         TotalMicros    %= 100;
  763.  
  764.                                         Printf("\n\33[33mTotal Ratio\33[31m %02ld%%, \33[33mTotal Time\33[31m %02ld:%02ld:%02ld\n",TotalRatio / NumEntries,TotalSecs / 60,TotalSecs % 60,TotalMicros);
  765.                                     }
  766.                                 }
  767.  
  768.                                 Puts("");
  769.                             }
  770.                             else
  771.                             {
  772.                                 Success = RETURN_OK;
  773.  
  774.                                 Puts("File Name                       Size    Mode    %  Time     Result \n------------------------------- ------- ------ --- -------- -------");
  775.  
  776.                                     /* We didn't get a source file and a destination directory,
  777.                                      * so let's bring up the ARP file requester.
  778.                                      */
  779.  
  780.                                 for(;;)
  781.                                 {
  782.                                     FileRequester -> fr_Hail = "Select file to encode";
  783.  
  784.                                     FileRequester -> fr_File[0] = 0;
  785.  
  786.                                     if(!FileRequest(FileRequester))
  787.                                         break;
  788.  
  789.                                     strcpy(TempName,FileRequester -> fr_Dir);
  790.                                     TackOn(TempName,FileRequester -> fr_File);
  791.  
  792.                                     strcpy(FileRequester -> fr_File,"Directories only!");
  793.  
  794.                                     FileRequester -> fr_Hail = "Select destination directory";
  795.  
  796.                                     if(!FileRequest(FileRequester))
  797.                                         break;
  798.  
  799.                                     strcpy(TempName2,FileRequester -> fr_Dir);
  800.                                     TackOn(TempName2,BaseName(TempName));
  801.  
  802.                                     Encode(TempName,TempName2);
  803.                                 }
  804.                             }
  805.  
  806. Quit:                            CloseDevice(TimeRequest);
  807.                         }
  808.                         else
  809.                             Puts("\33[1mLhEncode:\33[0m Unable to open timer.device!\a");
  810.  
  811.                         DeleteExtIO(TimeRequest);
  812.                     }
  813.                     else
  814.                         Puts("\33[1mLhEncode:\33[0m Out of memory!\a");
  815.  
  816.                     DeletePort(TimePort);
  817.                 }
  818.                 else
  819.                     Puts("\33[1mLhEncode:\33[0m Unable to create MsgPort!\a");
  820.             }
  821.             else
  822.                 Puts("\33[1mLhEncode:\33[0m Unable to allocate Arp Filerequester!\a");
  823.  
  824.             DeleteBuffer(LhBuffer);
  825.         }
  826.         else
  827.             Puts("\33[1mLhEncode:\33[0m Out of memory!\a");
  828.     }
  829.     else
  830.         Printf("\33[1mLhDecode:\33[0m You need \"%s\" V%ld.0 or higher!\a\n",LH_NAME,LH_VERSION);
  831.     
  832.     exit(Success);
  833. }
  834.