home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d8xx / d832 / term.lha / Term / term-3.1-Source.lha / termXPR.c < prev    next >
C/C++ Source or Header  |  1993-02-18  |  49KB  |  2,164 lines

  1. /*
  2. **    termXPR.c
  3. **
  4. **    External transfer protocol support routines
  5. **
  6. **    Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* How many options xpr_options() will display in a single column. */
  13.  
  14. #define OPTION_WRAP     16
  15.  
  16.     /* These variables keep the transferred bytes and transfer
  17.      * time in seconds.
  18.      */
  19.  
  20. STATIC LONG         ByteVal,
  21.              ByteMax,
  22.              TimeVal,
  23.              TimeMax;
  24.  
  25.     /* Transfer statistics. */
  26.  
  27. STATIC ULONG         CPS_Minimum,
  28.              CPS_Maximum,
  29.              CPS_Average,
  30.              CPS_Count;
  31.  
  32.     /* The name of the file being transmitted, in case the
  33.      * `override transfer path' feature is enabled.
  34.      */
  35.  
  36. STATIC struct Buffer    *CurrentFile;
  37.  
  38.     /* Yet another flag, this one determines whether we already told
  39.      * the user that the file we are currently processing will fit
  40.      * on the destination device.
  41.      */
  42.  
  43. STATIC BYTE         Alerted;
  44.  
  45.     /* OpenTransferWindow():
  46.      *
  47.      *    Local routine to open the transfer window.
  48.      */
  49.  
  50. STATIC BYTE
  51. OpenTransferWindow(VOID)
  52. {
  53.         /* Block window input. */
  54.  
  55.     BlockWindows();
  56.  
  57.         /* Try to open the transfer window panel. */
  58.  
  59.     if(TransferPanel(LocaleString(MSG_TERMXPR_RECEIVE_FILES_TXT)))
  60.     {
  61.             /* Supply the log text. */
  62.  
  63.         LogAction(LocaleString(MSG_TERMXPR_LOGMSG_INITIATE_BINARY_DOWNLOAD_TXT));
  64.  
  65.             /* Return success. */
  66.  
  67.         return(TRUE);
  68.     }
  69.     else
  70.     {
  71.             /* Re-enable window input. */
  72.  
  73.         ReleaseWindows();
  74.  
  75.             /* Return failure. */
  76.  
  77.         return(FALSE);
  78.     }
  79. }
  80.  
  81.     /* NewFileName(STRPTR Source,STRPTR Buffer):
  82.      *
  83.      *    Build a valid file and path name, including path
  84.      *    substitution, etc.
  85.      */
  86.  
  87. STATIC STRPTR __regargs
  88. NewFileName(STRPTR Source,STRPTR Buffer)
  89. {
  90.     if(Config -> MiscConfig -> OverridePath && !Uploading)
  91.     {
  92.         if(DownloadPath)
  93.             strcpy(Buffer,DownloadPath);
  94.         else
  95.             strcpy(Buffer,Config -> PathConfig -> BinaryDownloadPath);
  96.  
  97.         if(!Buffer[0])
  98.         {
  99.             if(!GetCurrentDirName(Buffer,MAX_FILENAME_LENGTH))
  100.                 Buffer[0] = 0;
  101.         }
  102.  
  103.         if(Buffer[0])
  104.         {
  105.             if(AddPart(Buffer,FilePart(Source),MAX_FILENAME_LENGTH))
  106.                 return(Buffer);
  107.         }
  108.     }
  109.     else
  110.     {
  111.         if(FilePart(Source) == Source)
  112.         {
  113.             if(GetCurrentDirName(Buffer,MAX_FILENAME_LENGTH))
  114.             {
  115.                 if(AddPart(Buffer,Source,MAX_FILENAME_LENGTH))
  116.                     return(Buffer);
  117.             }
  118.         }
  119.     }
  120.  
  121.     return(Source);
  122. }
  123.  
  124.     /* IdentifySource(STRPTR Name,STRPTR BBSName,struct DateStamp *OpenDate):
  125.      *
  126.      *    Attach source information (BBS name, date and time) to a file.
  127.      */
  128.  
  129. STATIC VOID __inline
  130. IdentifySource(STRPTR Name,STRPTR BBSName,struct DateStamp *OpenDate)
  131. {
  132.     UBYTE        SharedBuffer[MAX_FILENAME_LENGTH],
  133.             Time[20],
  134.             Date[20];
  135.     struct DateTime    DateTime;
  136.  
  137.     memcpy(&DateTime . dat_Stamp,OpenDate,sizeof(struct DateStamp));
  138.  
  139.         /* Prepare for date conversion. */
  140.  
  141.     DateTime . dat_Format    = FORMAT_DOS;
  142.     DateTime . dat_Flags    = 0;
  143.     DateTime . dat_StrDay    = NULL;
  144.     DateTime . dat_StrDate    = Date;
  145.     DateTime . dat_StrTime    = Time;
  146.  
  147.         /* Convert the date. */
  148.  
  149.     if(DateToStr(&DateTime))
  150.     {
  151.         if(BBSName[0])
  152.             SPrintf(SharedBuffer,"%s %s %s",BBSName,Date,Time);
  153.         else
  154.             SPrintf(SharedBuffer,"%s %s",Date,Time);
  155.  
  156.         SetComment(Name,SharedBuffer);
  157.     }
  158. }
  159.  
  160.     /* GetSeconds(STRPTR String):
  161.      *
  162.      *    Tries to turn a string of the format hh:mm:ss into
  163.      *    an integer number.
  164.      */
  165.  
  166. STATIC LONG __inline
  167. GetSeconds(STRPTR String)
  168. {
  169.     UBYTE    Buffer[20];
  170.     LONG    Seconds = 0;
  171.  
  172.     memset(Buffer,0,20);
  173.  
  174.     strcpy(Buffer,String);
  175.  
  176.     Seconds += Atol(&Buffer[6]);
  177.  
  178.     Buffer[5] = 0;
  179.  
  180.     Seconds += Atol(&Buffer[3]) * 60;
  181.  
  182.     Buffer[2] = 0;
  183.  
  184.     Seconds += Atol(&Buffer[0]) * 3600;
  185.  
  186.     return(Seconds);
  187. }
  188.  
  189.     /* TruncateName(STRPTR FileName):
  190.      *
  191.      *    Truncates a file name to a maximum of 48 characters.
  192.      */
  193.  
  194. STATIC STRPTR __inline
  195. TruncateName(STRPTR FileName)
  196. {
  197.     WORD Len = strlen(FileName);
  198.  
  199.     if(Len > 48)
  200.     {
  201.         WORD i;
  202.  
  203.         for(i = Len - 48 ; i < Len ; i++)
  204.         {
  205.             if(i >= Len - 44 && FileName[i] == '/')
  206.             {
  207.                 STATIC UBYTE NameBuffer[MAX_FILENAME_LENGTH];
  208.  
  209.                 strcpy(NameBuffer,".../");
  210.  
  211.                 strcat(NameBuffer,&FileName[i + 1]);
  212.  
  213.                 return(NameBuffer);
  214.             }
  215.         }
  216.     }
  217.  
  218.     return(FileName);
  219. }
  220.  
  221.     /* CalculateBlocks(LONG Size,LONG BlockSize):
  222.      *
  223.      *    Calculate the number of blocks a file will
  224.      *    occupy if saved to a disk.
  225.      */
  226.  
  227. STATIC LONG __inline
  228. CalculateBlocks(LONG Size,LONG BlockSize)
  229. {
  230.     LONG    Blocks        = 1;        /* One for the file header. */
  231.     BYTE    HasExtension    = FALSE,    /* No extension block yet. */
  232.         Extension    = 0;        /* How many block pointers yet. */
  233.  
  234.         /* Round to next block. */
  235.  
  236.     Size = ((Size + BlockSize - 1) / BlockSize) * BlockSize;
  237.  
  238.     while(Size)
  239.     {
  240.             /* Add another block. */
  241.  
  242.         Blocks++;
  243.  
  244.             /* Subtract another block. */
  245.  
  246.         Size -= BlockSize;
  247.  
  248.             /* Add another block pointer, if 72 have been
  249.              * added, add another extension block.
  250.              */
  251.  
  252.         if((Extension++) == 72)
  253.         {
  254.                 /* If no extension block has been generated
  255.                  * yet, we were running on the block pointers
  256.                  * of the file header itself.
  257.                  */
  258.  
  259.             if(!HasExtension)
  260.                 HasExtension = TRUE;
  261.             else
  262.                 Blocks++;
  263.  
  264.                 /* Reset extension block counter. */
  265.  
  266.             Extension = 0;
  267.         }
  268.     }
  269.  
  270.     return(Blocks);
  271. }
  272.  
  273.     /* GetOptionMode(struct xpr_option *Option):
  274.      *
  275.      *    Turn text into a boolean value.
  276.      */
  277.  
  278. STATIC BYTE __inline
  279. GetOptionMode(struct xpr_option *Option)
  280. {
  281.     if(Option)
  282.     {
  283.         STATIC STRPTR TrueOptions[] =
  284.         {
  285.             "ON",
  286.             "TRUE",
  287.             "T",
  288.             "YES",
  289.             "Y",
  290.             NULL
  291.         };
  292.  
  293.         register WORD i;
  294.  
  295.         for(i = 0 ; TrueOptions[i] ; i++)
  296.         {
  297.             if(!Stricmp(Option -> xpro_value,TrueOptions[i]))
  298.                 return(TRUE);
  299.         }
  300.     }
  301.  
  302.     return(FALSE);
  303. }
  304.  
  305.     /* CreateAllOptionGadgets():
  306.      *
  307.      *    Create all the gadgets for the xpr options control panel.
  308.      */
  309.  
  310. STATIC struct Gadget *
  311. CreateAllOptionGadgets(LONG *Count,LONG NumOpts,struct xpr_option *Opts[],struct Gadget *GadgetArray[],struct Gadget **GadgetList,APTR VisualInfo)
  312. {
  313.     struct Gadget        *Gadget;
  314.     struct NewGadget     NewGadget;
  315.     LONG             i,MaxLength = 0,MaxLength1 = 0,MaxWidth,MaxWidth1,Len,NumOptsSmall;
  316.     BYTE             WrapIt = FALSE;
  317.  
  318.     SZ_SizeSetup(Window -> WScreen,&UserFont,TRUE);
  319.  
  320.     memset(&NewGadget,0,sizeof(struct NewGadget));
  321.  
  322.     *Count = 0;
  323.  
  324.     SZ_ResetMaxWidth();
  325.  
  326.     if(Gadget = CreateContext(GadgetList))
  327.     {
  328.         NewGadget . ng_TextAttr        = &UserFont;
  329.         NewGadget . ng_VisualInfo    = VisualInfo;
  330.         NewGadget . ng_Flags        = NG_HIGHLABEL;
  331.  
  332.             /* Precalculate gadget left edge offset. */
  333.  
  334.         if((NumOptsSmall = NumOpts) > OPTION_WRAP)
  335.             NumOptsSmall = OPTION_WRAP;
  336.  
  337.         for(i = 0 ; i < NumOptsSmall ; i++)
  338.         {
  339.             if(Opts[i])
  340.             {
  341.                 switch(Opts[i] -> xpro_type)
  342.                 {
  343.                     case XPRO_BOOLEAN:
  344.  
  345.                         if((Len = SZ_TextWidth(Opts[i] -> xpro_description)) > MaxLength)
  346.                             MaxLength = Len;
  347.  
  348.                         SZ_UpdateMaxWidth(CHECKBOX_KIND,NULL,0,NULL);
  349.  
  350.                         break;
  351.  
  352.                     case XPRO_HEADER:
  353.  
  354.                         if((Len = SZ_TextWidth(Opts[i] -> xpro_description)) > MaxLength)
  355.                             MaxLength = Len;
  356.  
  357.                         break;
  358.  
  359.                     case XPRO_LONG:
  360.                     case XPRO_STRING:
  361.                     case XPRO_COMMPAR:
  362.  
  363.                         if((Len = SZ_TextWidth(Opts[i] -> xpro_description)) > MaxLength)
  364.                             MaxLength = Len;
  365.  
  366.                         SZ_UpdateMaxWidth(STRING_KIND,NULL,20,NULL);
  367.  
  368.                         break;
  369.  
  370.                     case XPRO_COMMAND:
  371.  
  372.                         SZ_UpdateMaxWidth(TEXT_KIND,Opts[i] -> xpro_description,0,NULL);
  373.  
  374.                         break;
  375.  
  376.                     default:
  377.  
  378.                         break;
  379.                 }
  380.             }
  381.         }
  382.  
  383.         MaxWidth = SZ_ResetMaxWidth();
  384.  
  385.         SZ_AddLeftOffset(MaxLength + INTERWIDTH);
  386.  
  387.         for(i = OPTION_WRAP ; i < NumOpts ; i++)
  388.         {
  389.             if(Opts[i])
  390.             {
  391.                 switch(Opts[i] -> xpro_type)
  392.                 {
  393.                     case XPRO_BOOLEAN:
  394.  
  395.                         if((Len = SZ_TextWidth(Opts[i] -> xpro_description)) > MaxLength1)
  396.                             MaxLength1 = Len;
  397.  
  398.                         SZ_UpdateMaxWidth(CHECKBOX_KIND,NULL,0,NULL);
  399.  
  400.                         break;
  401.  
  402.                     case XPRO_HEADER:
  403.  
  404.                         if((Len = SZ_TextWidth(Opts[i] -> xpro_description)) > MaxLength1)
  405.                             MaxLength1 = Len;
  406.  
  407.                         break;
  408.  
  409.                     case XPRO_LONG:
  410.                     case XPRO_STRING:
  411.                     case XPRO_COMMPAR:
  412.  
  413.                         if((Len = SZ_TextWidth(Opts[i] -> xpro_description)) > MaxLength1)
  414.                             MaxLength1 = Len;
  415.  
  416.                         SZ_UpdateMaxWidth(STRING_KIND,NULL,20,NULL);
  417.  
  418.                         break;
  419.  
  420.                     case XPRO_COMMAND:
  421.  
  422.                         SZ_UpdateMaxWidth(TEXT_KIND,Opts[i] -> xpro_description,0,NULL);
  423.  
  424.                         break;
  425.  
  426.                     default:
  427.  
  428.                         break;
  429.                 }
  430.             }
  431.         }
  432.  
  433.         MaxWidth1 = SZ_ResetMaxWidth();
  434.  
  435.         SZ_SetWidth(MaxWidth);
  436.  
  437.         for(i = 0 ; i < NumOpts ; i++)
  438.         {
  439.             if(i == OPTION_WRAP + 1)
  440.                 WrapIt = TRUE;
  441.  
  442.             if(!Opts[i])
  443.                 continue;
  444.  
  445.             if(WrapIt)
  446.             {
  447.                 SZ_SetWidth(MaxWidth1);
  448.                 SZ_AddLeftOffset(MaxLength1 + INTERWIDTH);
  449.             }
  450.  
  451.             switch(Opts[i] -> xpro_type)
  452.             {
  453.                 case XPRO_BOOLEAN:
  454.  
  455.                     NewGadget . ng_GadgetText    = Opts[i] -> xpro_description;
  456.                     NewGadget . ng_GadgetID        = i;
  457.  
  458.                     GadgetArray[i] = Gadget = CreateGadget(CHECKBOX_KIND,Gadget,&NewGadget,
  459.                         SZ_Adjust,    TRUE,
  460.                         SZ_AutoWidth,    TRUE,
  461.                         SZ_NewColumn,    WrapIt,
  462.  
  463.                         GTCB_Checked,    GetOptionMode(Opts[i]),
  464.                     TAG_DONE);
  465.  
  466.                     break;
  467.  
  468.                 case XPRO_LONG:
  469.  
  470.                     NewGadget . ng_GadgetText    = Opts[i] -> xpro_description;
  471.                     NewGadget . ng_GadgetID        = i;
  472.  
  473.                     GadgetArray[i] = Gadget = CreateGadget(INTEGER_KIND,Gadget,&NewGadget,
  474.                         SZ_Adjust,    TRUE,
  475.                         SZ_AutoWidth,    TRUE,
  476.                         SZ_NewColumn,    WrapIt,
  477.  
  478.                         GTIN_Number,    Atol(Opts[i] -> xpro_value),
  479.                         GTST_EditHook,    &CommandHook,
  480.                     TAG_DONE);
  481.  
  482.                     break;
  483.  
  484.                 case XPRO_STRING:
  485.                 case XPRO_COMMPAR:
  486.  
  487.                     NewGadget . ng_GadgetText    = Opts[i] -> xpro_description;
  488.                     NewGadget . ng_GadgetID        = i;
  489.  
  490.                     GadgetArray[i] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  491.                         SZ_Adjust,    TRUE,
  492.                         SZ_AutoWidth,    TRUE,
  493.                         SZ_NewColumn,    WrapIt,
  494.  
  495.                         GTST_String,    Opts[i] -> xpro_value,
  496.                         GTST_MaxChars,    Opts[i] -> xpro_length - 1,
  497.                         GTST_EditHook,    &CommandHook,
  498.                     TAG_DONE);
  499.  
  500.                     break;
  501.  
  502.                 case XPRO_HEADER:
  503.  
  504.                     NewGadget . ng_GadgetText    = Opts[i] -> xpro_description;
  505.                     NewGadget . ng_GadgetID        = i;
  506.                     NewGadget . ng_Flags        = NG_HIGHLABEL;
  507.  
  508.                     GadgetArray[i] = Gadget = CreateGadget(TEXT_KIND,Gadget,&NewGadget,
  509.                         SZ_Adjust,    TRUE,
  510.                         SZ_AutoWidth,    TRUE,
  511.  
  512.                         GTTX_Text,    " ",
  513.                     TAG_DONE);
  514.  
  515.                     NewGadget . ng_Flags = 0;
  516.  
  517.                     break;
  518.  
  519.                 case XPRO_COMMAND:
  520.  
  521.                     NewGadget . ng_GadgetText    = Opts[i] -> xpro_description;
  522.                     NewGadget . ng_GadgetID        = i;
  523.  
  524.                     GadgetArray[i] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  525.                         SZ_Adjust,    TRUE,
  526.                         SZ_AutoWidth,    TRUE,
  527.                     TAG_DONE);
  528.  
  529.                     break;
  530.  
  531.                 default:break;
  532.             }
  533.  
  534.             WrapIt = FALSE;
  535.         }
  536.  
  537.         SZ_ResetMaxWidth();
  538.  
  539.         SZ_UpdateMaxWidth(BUTTON_KIND,LocaleString(MSG_GLOBAL_USE_GAD),0,NULL);
  540.         SZ_UpdateMaxWidth(BUTTON_KIND,LocaleString(MSG_GLOBAL_CANCEL_GAD),0,NULL);
  541.  
  542.         SZ_SetWidth(SZ_ResetMaxWidth());
  543.  
  544.         NewGadget . ng_GadgetText    = LocaleString(MSG_GLOBAL_USE_GAD);
  545.         NewGadget . ng_GadgetID        = GAD_XPROPTIONS_USE;
  546.  
  547.         GadgetArray[i++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  548.             SZ_AlignExtra,    TRUE,
  549.             SZ_Adjust,    TRUE,
  550.             SZ_AutoWidth,    TRUE,
  551.             SZ_AlignLeft,    TRUE,
  552.             SZ_AlignBottom,    TRUE,
  553.  
  554.             GT_Underscore,    '_',
  555.         TAG_DONE);
  556.  
  557.         NewGadget . ng_GadgetText    = LocaleString(MSG_GLOBAL_CANCEL_GAD);
  558.         NewGadget . ng_GadgetID        = GAD_XPROPTIONS_CANCEL;
  559.  
  560.         GadgetArray[i++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  561.             SZ_Adjust,    TRUE,
  562.             SZ_AutoWidth,    TRUE,
  563.             SZ_AlignRight,    TRUE,
  564.  
  565.             GT_Underscore,    '_',
  566.         TAG_DONE);
  567.  
  568.         if(Gadget)
  569.             *Count = i;
  570.     }
  571.  
  572.     return(Gadget);
  573. }
  574.  
  575.     /* xpr_fopen(STRPTR FileName,STRPTR AccessMode):
  576.      *
  577.      *    Open a file for random access.
  578.      */
  579.  
  580. LONG __saveds __asm
  581. xpr_fopen(register __a0 STRPTR FileName,register __a1 STRPTR AccessMode)
  582. {
  583.     UBYTE         RealName[MAX_FILENAME_LENGTH];
  584.     struct Buffer    *File;
  585.  
  586.     Alerted = FALSE;
  587.  
  588.         /* Reset transfer counters. */
  589.  
  590.     ByteVal = ByteMax = TimeVal = TimeMax = 0;
  591.  
  592.         /* Reset CPS statistics. */
  593.  
  594.     CPS_Minimum    = (ULONG)~0;
  595.     CPS_Maximum    = 0;
  596.     CPS_Average    = 0;
  597.     CPS_Count    = 0;
  598.  
  599.         /* No window available for output? */
  600.  
  601.     if(!TransferWindow)
  602.         OpenTransferWindow();
  603.  
  604.         /* Disable the time and data bars in the transfer window. */
  605.  
  606.     if(TransferWindow)
  607.     {
  608.         GhostStats(TransferGadgetArray[GAD_TRANSFER_PERCENT]);
  609.         GhostStats(TransferGadgetArray[GAD_TRANSFER_TIME]);
  610.     }
  611.  
  612.         /* Determine the file name. */
  613.  
  614.     FileName = NewFileName(FileName,RealName);
  615.  
  616.         /* Determine file transfer mode... */
  617.  
  618.     if(File = BufferOpen(FileName,AccessMode))
  619.     {
  620.         switch(AccessMode[0])
  621.         {
  622.             case 'r':
  623.  
  624.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_SEND_FILE_TXT),FileName);
  625.                 break;
  626.  
  627.             case 'w':
  628.  
  629.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_RECEIVE_FILE_TXT),FileName);
  630.                 break;
  631.  
  632.             case 'a':
  633.  
  634.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_UPDATE_FILE_TXT),FileName);
  635.                 break;
  636.         }
  637.  
  638.         CurrentFile = File;
  639.     }
  640.  
  641.     DidTransfer = TRUE;
  642.  
  643.     return((LONG)File);
  644. }
  645.  
  646.     /* xpr_fclose(struct Buffer *File):
  647.      *
  648.      *    Close a file opened by xpr_fopen.
  649.      */
  650.  
  651. LONG __saveds __asm
  652. xpr_fclose(register __a0 struct Buffer *File)
  653. {
  654.     UBYTE            RealName[MAX_FILENAME_LENGTH];
  655.     struct DateStamp    OpenDate;
  656.     BYTE            WriteAccess,
  657.                 Used;
  658.  
  659.         /* Save some information. */
  660.  
  661.     OpenDate    = File -> OpenDate;
  662.     WriteAccess    = File -> WriteAccess;
  663.     Used        = File -> Used;
  664.  
  665.         /* Get the name of the file. */
  666.  
  667.     if(!NameFromFH(File -> FileHandle,RealName,MAX_FILENAME_LENGTH))
  668.         RealName[0] = 0;
  669.  
  670.         /* Close the file and see what it brings... */
  671.  
  672.     if(BufferClose(File) && RealName[0])
  673.     {
  674.             /* Did any access take place at all?
  675.              * xprzmodem.library for example just
  676.              * opens and closes a file in order to
  677.              * see if it exists.
  678.              */
  679.  
  680.         if(!Used)
  681.             LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  682.         else
  683.         {
  684.                 /* Did we receive or send a file? */
  685.  
  686.             if(WriteAccess)
  687.             {
  688.                 LONG Size;
  689.  
  690.                     /* Did the file remain empty? */
  691.  
  692.                 if(!(Size = GetFileSize(RealName)))
  693.                 {
  694.                     AddTransferInfo(LocaleString(MSG_TERMXPR_FILE_REMOVED_TXT),FilePart(RealName));
  695.  
  696.                         /* Delete empty file. */
  697.  
  698.                     if(DeleteFile(RealName))
  699.                         LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_REMOVED_TXT),RealName);
  700.                     else
  701.                         LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  702.                 }
  703.                 else
  704.                 {
  705.                     struct Node *SomeNode;
  706.  
  707.                     if(ByteMax)
  708.                     {
  709.                         if(Size >= ByteMax)
  710.                             AddTransferInfo(LocaleString(MSG_TERMXPR_FILE_RECEIVED_TXT),FilePart(RealName));
  711.                         else
  712.                             AddTransferInfo(LocaleString(MSG_TERMXPR_INCOMPLETE_FILE_RECEIVED_TXT),FilePart(RealName));
  713.                     }
  714.  
  715.                         /* Try to identify the file type. */
  716.  
  717.                     switch(Config -> MiscConfig -> IdentifyFiles)
  718.                     {
  719.                         case IDENTIFY_FILETYPE:
  720.  
  721.                             Identify(RealName);
  722.                             break;
  723.  
  724.                         case IDENTIFY_SOURCE:
  725.  
  726.                             IdentifySource(RealName,CurrentBBSName,&OpenDate);
  727.                             break;
  728.                     }
  729.  
  730.                     if(CPS_Minimum == (ULONG)~0)
  731.                         CPS_Minimum = 0;
  732.  
  733.                     if(CPS_Count == 0)
  734.                     {
  735.                         CPS_Average    = 0;
  736.                         CPS_Count    = 1;
  737.                     }
  738.  
  739.                     LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_BYTES_TXT),RealName,Size,CPS_Minimum,CPS_Average / CPS_Count,CPS_Maximum);
  740.  
  741.                     if(SomeNode = CreateGenericListNode(0,RealName))
  742.                         AddGenericListNode(GenericListTable[GLIST_DOWNLOAD],SomeNode,ADD_GLIST_BOTTOM);
  743.                 }
  744.             }
  745.             else
  746.             {
  747.                     /* Set the archived bit on files we uploaded? */
  748.  
  749.                 if(Config -> MiscConfig -> SetArchivedBit)
  750.                 {
  751.                     struct FileInfoBlock *FileInfo;
  752.  
  753.                     if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  754.                     {
  755.                         BPTR FileLock;
  756.  
  757.                             /* Get a lock on it. */
  758.  
  759.                         if(FileLock = Lock(RealName,ACCESS_READ))
  760.                         {
  761.                                 /* Examine the file. */
  762.  
  763.                             if(Examine(FileLock,FileInfo))
  764.                             {
  765.                                     /* Remove the lock. */
  766.  
  767.                                 UnLock(FileLock);
  768.  
  769.                                     /* Set the `archived' bit. */
  770.  
  771.                                 SetProtection(RealName,FileInfo -> fib_Protection | FIBF_ARCHIVE);
  772.                             }
  773.                             else
  774.                                 UnLock(FileLock);
  775.                         }
  776.  
  777.                         FreeDosObject(DOS_FIB,FileInfo);
  778.                     }
  779.                 }
  780.  
  781.                 AddTransferInfo(LocaleString(MSG_TERMXPR_FILE_SENT_TXT),FilePart(RealName));
  782.  
  783.                 LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  784.  
  785.                 RemoveUploadListItem(RealName);
  786.             }
  787.         }
  788.     }
  789.  
  790.     CurrentFile = NULL;
  791.  
  792.     return(1);
  793. }
  794.  
  795.     /* xpr_fread(APTR Buffer,LONG Size,LONG Count,struct Buffer *File):
  796.      *
  797.      *    Read a few bytes from a file.
  798.      */
  799.  
  800. LONG __saveds __asm
  801. xpr_fread(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 LONG Count,register __a1 struct Buffer *File)
  802. {
  803.     return(BufferRead(File,Buffer,Size * Count) / Size);
  804. }
  805.  
  806.     /* xpr_fwrite(APTR Buffer,LONG Size,LONG Count,struct Buffer *File):
  807.      *
  808.      *    Write a few bytes to a file.
  809.      */
  810.  
  811. LONG __saveds __asm
  812. xpr_fwrite(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 LONG Count,register __a1 struct Buffer *File)
  813. {
  814.     return(BufferWrite(File,Buffer,Size * Count) / Size);
  815. }
  816.  
  817.     /* xpr_fseek(struct Buffer *File,LONG Offset,LONG Origin):
  818.      *
  819.      *    Move the read/write pointer in a file.
  820.      */
  821.  
  822. LONG __saveds __asm
  823. xpr_fseek(register __a0 struct Buffer *File,register __d0 LONG Offset,register __d1 LONG Origin)
  824. {
  825.     return(BufferSeek(File,Offset,Origin) ? 0 : -1);
  826. }
  827.  
  828.     /* xpr_sread(APTR Buffer,LONG Size,LONG Timeout):
  829.      *
  830.      *    Read a few bytes from the serial port (including
  831.      *    timeouts).
  832.      */
  833.  
  834. LONG __saveds __asm
  835. xpr_sread(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 ULONG Timeout)
  836. {
  837.         /* Are both IORequests available? */
  838.  
  839.     if(WriteRequest && ReadRequest)
  840.     {
  841.             /* No window available for output? */
  842.  
  843.         if(!TransferWindow)
  844.         {
  845.             if(!OpenTransferWindow())
  846.                 return(-1);
  847.         }
  848.  
  849.             /* Valid size parameter? */
  850.  
  851.         if(Size > 0)
  852.         {
  853.                 /* How many bytes are still in the serial buffer? */
  854.  
  855.             WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  856.  
  857.             DoIO(WriteRequest);
  858.  
  859.                 /* Return error if carrier is lost. */
  860.  
  861.             if((WriteRequest -> io_Status & CIAF_COMCD) && Config -> SerialConfig -> CheckCarrier)
  862.             {
  863.                 Online = FALSE;
  864.  
  865.                 return(-1);
  866.             }
  867.             else
  868.             {
  869.                     /* Any timeout specified? */
  870.  
  871.                 if(Timeout)
  872.                 {
  873.                         /* Any data available? */
  874.  
  875.                     if(WriteRequest -> IOSer . io_Actual < Size)
  876.                     {
  877.                         register ULONG SignalSet,WindowMask = PORTMASK(TransferWindow -> UserPort);
  878.  
  879.                             /* Set up the timer. */
  880.  
  881.                         TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  882.                         TimeRequest -> tr_time . tv_secs    = Timeout / MILLION;
  883.                         TimeRequest -> tr_time . tv_micro    = Timeout % MILLION;
  884.  
  885.                             /* Set up the read request. */
  886.  
  887.                         ReadRequest -> IOSer . io_Command    = CMD_READ;
  888.                         ReadRequest -> IOSer . io_Data        = Buffer;
  889.                         ReadRequest -> IOSer . io_Length    = Size;
  890.  
  891.                             /* Prevent early termination. */
  892.  
  893.                         SetSignal(0,SIG_SERIAL | SIG_TIMER);
  894.  
  895.                             /* Start IO... */
  896.  
  897.                         BeginIO(ReadRequest);
  898.                         BeginIO(TimeRequest);
  899.  
  900.                         FOREVER
  901.                         {
  902.                             SignalSet = Wait(SIG_SERIAL | SIG_TIMER | WindowMask);
  903.  
  904.                                 /* Abort file transfer? */
  905.  
  906.                             if(SignalSet & WindowMask)
  907.                             {
  908.                                 if(xpr_chkabort() == -1)
  909.                                 {
  910.                                     if(!CheckIO(ReadRequest))
  911.                                         AbortIO(ReadRequest);
  912.  
  913.                                     if(!CheckIO(TimeRequest))
  914.                                         AbortIO(TimeRequest);
  915.  
  916.                                     WaitIO(ReadRequest);
  917.                                     WaitIO(TimeRequest);
  918.  
  919.                                     SendAbort = TRUE;
  920.  
  921.                                     return(-1);
  922.                                 }
  923.                             }
  924.  
  925.                                 /* Receive buffer filled? */
  926.  
  927.                             if(SignalSet & SIG_SERIAL)
  928.                             {
  929.                                     /* Abort the timer request. */
  930.  
  931.                                 if(!CheckIO(TimeRequest))
  932.                                     AbortIO(TimeRequest);
  933.  
  934.                                 WaitIO(TimeRequest);
  935.  
  936.                                     /* Did the request terminate gracefully? */
  937.  
  938.                                 if(!WaitIO(ReadRequest))
  939.                                 {
  940.                                     BytesIn += Size;
  941.  
  942.                                     return(Size);
  943.                                 }
  944.                                 else
  945.                                     return(-1);
  946.                             }
  947.  
  948.                                 /* Hit by timeout? */
  949.  
  950.                             if(SignalSet & SIG_TIMER)
  951.                             {
  952.                                     /* Abort the read request. */
  953.  
  954.                                 if(!CheckIO(ReadRequest))
  955.                                     AbortIO(ReadRequest);
  956.  
  957.                                 WaitIO(ReadRequest);
  958.  
  959.                                     /* Remove the timer request. */
  960.  
  961.                                 WaitIO(TimeRequest);
  962.  
  963.                                     /* Did the driver receive any
  964.                                      * data?
  965.                                      */
  966.  
  967.                                 if(ReadRequest -> IOSer . io_Actual)
  968.                                 {
  969.                                     BytesIn += ReadRequest -> IOSer . io_Actual;
  970.  
  971.                                     return((LONG)ReadRequest -> IOSer . io_Actual);
  972.                                 }
  973.                                 else
  974.                                 {
  975.                                     LONG Length;
  976.  
  977.                                         /* Take a second look and query the number of
  978.                                          * bytes ready to be received, there may
  979.                                          * still be some bytes in the buffer.
  980.                                          * Note: this depends on the way the
  981.                                          * driver handles read abort.
  982.                                          */
  983.  
  984.                                     WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  985.  
  986.                                     DoIO(WriteRequest);
  987.  
  988.                                         /* Are there any bytes to be transferred? */
  989.  
  990.                                     if(Length = WriteRequest -> IOSer . io_Actual)
  991.                                     {
  992.                                             /* Don't read too much. */
  993.  
  994.                                         if(Length > Size)
  995.                                             Length = Size;
  996.  
  997.                                             /* Read the data. */
  998.  
  999.                                         ReadRequest -> IOSer . io_Command    = CMD_READ;
  1000.                                         ReadRequest -> IOSer . io_Data        = Buffer;
  1001.                                         ReadRequest -> IOSer . io_Length    = Length;
  1002.  
  1003.                                             /* Read the data. */
  1004.  
  1005.                                         if(!DoIO(ReadRequest))
  1006.                                         {
  1007.                                             BytesIn += Length;
  1008.  
  1009.                                             return(Length);
  1010.                                         }
  1011.                                         else
  1012.                                             return(-1);
  1013.                                     }
  1014.                                     else
  1015.                                         return(0);
  1016.                                 }
  1017.                             }
  1018.                         }
  1019.                     }
  1020.                     else
  1021.                     {
  1022.                             /* There is enough data pending to be read. */
  1023.  
  1024.                         ReadRequest -> IOSer . io_Command    = CMD_READ;
  1025.                         ReadRequest -> IOSer . io_Data        = Buffer;
  1026.                         ReadRequest -> IOSer . io_Length    = Size;
  1027.  
  1028.                         if(!DoIO(ReadRequest))
  1029.                         {
  1030.                             BytesIn += Size;
  1031.  
  1032.                             return(Size);
  1033.                         }
  1034.                         else
  1035.                             return(-1);
  1036.                     }
  1037.                 }
  1038.                 else
  1039.                 {
  1040.                     LONG Length = WriteRequest -> IOSer . io_Actual;
  1041.  
  1042.                         /* No timeout specified? Return as many bytes
  1043.                          * as are currently in the buffer.
  1044.                          */
  1045.  
  1046.                     if(Length)
  1047.                     {
  1048.                             /* Don't read too much! */
  1049.  
  1050.                         if(Length > Size)
  1051.                             Length = Size;
  1052.  
  1053.                             /* Fill the buffer. */
  1054.  
  1055.                         ReadRequest -> IOSer . io_Command    = CMD_READ;
  1056.                         ReadRequest -> IOSer . io_Data        = Buffer;
  1057.                         ReadRequest -> IOSer . io_Length    = Length;
  1058.  
  1059.                         if(!DoIO(ReadRequest))
  1060.                         {
  1061.                             BytesIn += Length;
  1062.  
  1063.                             return(Length);
  1064.                         }
  1065.                         else
  1066.                             return(-1);
  1067.                     }
  1068.                     else
  1069.                         return(0);
  1070.                 }
  1071.             }
  1072.         }
  1073.         else
  1074.             return(0);
  1075.     }
  1076.     else
  1077.         return(-1);
  1078. }
  1079.  
  1080.     /* xpr_swrite(APTR Buffer,LONG Size):
  1081.      *
  1082.      *    Write a few bytes to the serial port.
  1083.      */
  1084.  
  1085. LONG __saveds __asm
  1086. xpr_swrite(register __a0 APTR Buffer,register __d0 LONG Size)
  1087. {
  1088.     if(WriteRequest)
  1089.     {
  1090.             /* Return error if carrier is lost. */
  1091.  
  1092.         if(Config -> SerialConfig -> CheckCarrier)
  1093.         {
  1094.                 /* Query the serial status bits. */
  1095.  
  1096.             WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  1097.  
  1098.             DoIO(WriteRequest);
  1099.  
  1100.                 /* Is the carrier signal still present? */
  1101.  
  1102.             if(WriteRequest -> io_Status & CIAF_COMCD)
  1103.             {
  1104.                 Online = FALSE;
  1105.  
  1106.                 return(-1);
  1107.             }
  1108.         }
  1109.  
  1110.             /* Send the data. */
  1111.  
  1112.         WriteRequest -> IOSer . io_Command    = CMD_WRITE;
  1113.         WriteRequest -> IOSer . io_Data        = Buffer;
  1114.         WriteRequest -> IOSer . io_Length    = Size;
  1115.  
  1116.         if(!DoIO(WriteRequest))
  1117.         {
  1118.             BytesOut += Size;
  1119.  
  1120.             return(0);
  1121.         }
  1122.     }
  1123.  
  1124.     return(-1);
  1125. }
  1126.  
  1127.     /* xpr_sflush():
  1128.      *
  1129.      *    Release the contents of all serial buffers.
  1130.      */
  1131.  
  1132. LONG __asm __saveds
  1133. xpr_sflush()
  1134. {
  1135.     if(WriteRequest)
  1136.     {
  1137.         WriteRequest -> IOSer . io_Command = CMD_CLEAR;
  1138.  
  1139.         if(!DoIO(WriteRequest))
  1140.             return(0);
  1141.     }
  1142.  
  1143.     return(-1);
  1144. }
  1145.  
  1146.     /* xpr_update(struct XPR_UPDATE *UpdateInfo):
  1147.      *
  1148.      *    Update the information displayed in the transfer window.
  1149.      */
  1150.  
  1151. LONG __saveds __asm
  1152. xpr_update(register __a0 struct XPR_UPDATE *UpdateInfo)
  1153. {
  1154.         /* No window available for output? */
  1155.  
  1156.     if(!TransferWindow)
  1157.     {
  1158.         if(!OpenTransferWindow())
  1159.             return(0);
  1160.     }
  1161.  
  1162.     if(UpdateInfo)
  1163.     {
  1164.         struct RastPort    *RPort        = TransferWindow -> RPort;
  1165.         BYTE         NewByte    = FALSE,
  1166.                  NewTime    = FALSE;
  1167.  
  1168.         if((UpdateInfo -> xpru_updatemask & XPRU_PROTOCOL) && UpdateInfo -> xpru_protocol)
  1169.             SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_1],0,UpdateInfo -> xpru_protocol);
  1170.  
  1171.         if((UpdateInfo -> xpru_updatemask & XPRU_MSG) && UpdateInfo -> xpru_msg)
  1172.             AddTransferInfo(UpdateInfo -> xpru_msg);
  1173.  
  1174.         if((UpdateInfo -> xpru_updatemask & XPRU_ERRORMSG) && UpdateInfo -> xpru_errormsg)
  1175.             AddTransferInfo(UpdateInfo -> xpru_errormsg);
  1176.  
  1177.         if((UpdateInfo -> xpru_updatemask & XPRU_FILENAME) && UpdateInfo -> xpru_filename)
  1178.         {
  1179.             UBYTE    RealName[MAX_FILENAME_LENGTH];
  1180.             STRPTR    FileName;
  1181.  
  1182.             FileName = NewFileName(UpdateInfo -> xpru_filename,RealName);
  1183.  
  1184.             SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_2],0,TruncateName(FileName));
  1185.  
  1186.             if(FileTransferInfo)
  1187.             {
  1188.                 if(FileTransferInfo -> CurrentFile)
  1189.                 {
  1190.                     struct FileTransferNode *Node = (struct FileTransferNode *)FileTransferInfo -> CurrentFile -> Node . mln_Succ;
  1191.  
  1192.                     if(Node -> Node . mln_Succ)
  1193.                         SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_2],1,TruncateName(Node -> Name));
  1194.                     else
  1195.                         SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_2],1,LocaleString(MSG_GLOBAL_NONE_TXT));
  1196.                 }
  1197.  
  1198.                 SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],2,ConvNumber,FileTransferInfo -> TotalSize);
  1199.  
  1200.                 if(FileTransferInfo -> TotalFiles)
  1201.                     SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],4,LocaleString(MSG_TRANSFERPANEL_NUMBER_TO_GO_PERCENT_TXT),FileTransferInfo -> DoneFiles,FileTransferInfo -> TotalFiles,(100 * FileTransferInfo -> DoneFiles) / FileTransferInfo -> TotalFiles);
  1202.                 else
  1203.                     SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],4,LocaleString(MSG_TRANSFERPANEL_NUMBER_TO_GO_PERCENT_TXT),FileTransferInfo -> DoneFiles,FileTransferInfo -> TotalFiles,0);
  1204.             }
  1205.         }
  1206.  
  1207.         if((UpdateInfo -> xpru_updatemask & XPRU_FILESIZE) && UpdateInfo -> xpru_filesize != -1)
  1208.         {
  1209.             if(CurrentFile)
  1210.             {
  1211.                 if(CurrentFile -> DirLock && CurrentFile -> InfoData . id_NumBlocks && CurrentFile -> InfoData . id_BytesPerBlock)
  1212.                     SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],0,ConvNumber10,UpdateInfo -> xpru_filesize);
  1213.                 else
  1214.                     SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],0,ConvNumber,UpdateInfo -> xpru_filesize);
  1215.             }
  1216.             else
  1217.                 SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],0,ConvNumber,UpdateInfo -> xpru_filesize);
  1218.  
  1219.             if(ByteMax = UpdateInfo -> xpru_filesize)
  1220.                 NewByte = TRUE;
  1221.         }
  1222.  
  1223.         if((UpdateInfo -> xpru_updatemask & XPRU_BYTES) && UpdateInfo -> xpru_bytes != -1)
  1224.         {
  1225.             if(CurrentFile)
  1226.             {
  1227.                 if(CurrentFile -> DirLock && CurrentFile -> InfoData . id_NumBlocks && CurrentFile -> InfoData . id_BytesPerBlock)
  1228.                     SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],1,ConvNumber10,ByteVal = UpdateInfo -> xpru_bytes);
  1229.                 else
  1230.                     SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],1,ConvNumber,ByteVal = UpdateInfo -> xpru_bytes);
  1231.             }
  1232.             else
  1233.                 SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],1,ConvNumber,ByteVal = UpdateInfo -> xpru_bytes);
  1234.  
  1235.             if(FileTransferInfo)
  1236.             {
  1237.                 ULONG Len = FileTransferInfo -> DoneSize + UpdateInfo -> xpru_bytes;
  1238.  
  1239.                 if(FileTransferInfo -> TotalSize)
  1240.                     SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],3,LocaleString(MSG_TRANSFERPANEL_NUMBER_PERCENT_TXT),Len,(100 * Len) / FileTransferInfo -> TotalSize);
  1241.                 else
  1242.                     SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],3,LocaleString(MSG_TRANSFERPANEL_NUMBER_PERCENT_TXT),Len,0);
  1243.             }
  1244.  
  1245.             if(ByteMax)
  1246.                 NewByte = TRUE;
  1247.  
  1248.             if(CurrentFile)
  1249.             {
  1250.                 if(CurrentFile -> DirLock && !Uploading)
  1251.                 {
  1252.                     if(CurrentFile -> InfoData . id_NumBlocks && CurrentFile -> InfoData . id_BytesPerBlock)
  1253.                     {
  1254.                         if(ByteMax)
  1255.                         {
  1256.                             register LONG Space = CurrentFile -> InfoData . id_NumBlocks - CurrentFile -> InfoData . id_NumBlocksUsed;
  1257.  
  1258.                             if(Space >= 0)
  1259.                             {
  1260.                                 register LONG Blocks = CalculateBlocks(ByteMax,CurrentFile -> InfoData . id_BytesPerBlock);
  1261.  
  1262.                                 if(Space < Blocks)
  1263.                                 {
  1264.                                     if(!Alerted)
  1265.                                     {
  1266.                                         Alerted = TRUE;
  1267.  
  1268.                                         BumpWindow(TransferWindow);
  1269.  
  1270.                                         Say(LocaleString(MSG_TERMXPR_SAY_FILE_MAY_NOT_FIT_TXT));
  1271.                                     }
  1272.  
  1273.                                     SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_2],2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),Space * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks,LocaleString(MSG_TERMXPR_FILE_MAY_NOT_FIT_TXT));
  1274.                                 }
  1275.                                 else
  1276.                                     SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_2],2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),Space * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks,"");
  1277.                             }
  1278.                             else
  1279.                                 SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_2],2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),(CurrentFile -> InfoData . id_NumBlocks - CurrentFile -> InfoData . id_NumBlocksUsed) * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks);
  1280.                         }
  1281.                         else
  1282.                             SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_2],2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),(CurrentFile -> InfoData . id_NumBlocks - CurrentFile -> InfoData . id_NumBlocksUsed) * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks);
  1283.                     }
  1284.                 }
  1285.             }
  1286.         }
  1287.  
  1288.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKS) && UpdateInfo -> xpru_blocks != -1)
  1289.             SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_LEFT1],5,ConvNumber,UpdateInfo -> xpru_blocks);
  1290.  
  1291.  
  1292.         if((UpdateInfo -> xpru_updatemask & XPRU_DATARATE) && UpdateInfo -> xpru_datarate != -1)
  1293.         {
  1294.             if(UpdateInfo -> xpru_datarate)
  1295.             {
  1296.                 if(UpdateInfo -> xpru_datarate < CPS_Minimum)
  1297.                     CPS_Minimum = UpdateInfo -> xpru_datarate;
  1298.  
  1299.                 if(UpdateInfo -> xpru_datarate > CPS_Maximum)
  1300.                     CPS_Maximum = UpdateInfo -> xpru_datarate;
  1301.  
  1302.                 if((ULONG)(CPS_Average + UpdateInfo -> xpru_datarate) >= CPS_Average)
  1303.                 {
  1304.                     CPS_Average += UpdateInfo -> xpru_datarate;
  1305.  
  1306.                     CPS_Count++;
  1307.                 }
  1308.  
  1309.                 SZ_PrintLine(TransferWindow -> RPort,TransferBoxArray[BOX_TRANSFER_RIGHT1],0,ConvNumber,UpdateInfo -> xpru_datarate);
  1310.             }
  1311.             else
  1312.                 SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_RIGHT1],0,"0");
  1313.         }
  1314.  
  1315.         if((UpdateInfo -> xpru_updatemask & XPRU_CHARDELAY) && UpdateInfo -> xpru_chardelay != -1)
  1316.             SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_RIGHT1],1,ConvNumber,UpdateInfo -> xpru_chardelay);
  1317.  
  1318.         if((UpdateInfo -> xpru_updatemask & XPRU_PACKETDELAY) && UpdateInfo -> xpru_packetdelay != -1)
  1319.             SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_RIGHT1],2,ConvNumber,UpdateInfo -> xpru_packetdelay);
  1320.  
  1321.         if((UpdateInfo -> xpru_updatemask & XPRU_PACKETTYPE) && UpdateInfo -> xpru_packettype != -1)
  1322.         {
  1323.             if(UpdateInfo -> xpru_packettype > 32 && UpdateInfo -> xpru_packettype < 256)
  1324.             {
  1325.                 if(IsPrintable[UpdateInfo -> xpru_packettype])
  1326.                     SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_RIGHT1],3,"`%lc'",UpdateInfo -> xpru_packettype);
  1327.                 else
  1328.                     SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_RIGHT1],3,ConvNumber,UpdateInfo -> xpru_packettype);
  1329.             }
  1330.             else
  1331.                 SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_RIGHT1],3,ConvNumber,UpdateInfo -> xpru_packettype);
  1332.         }
  1333.  
  1334.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKCHECK) && UpdateInfo -> xpru_blockcheck)
  1335.             SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_RIGHT1],4,UpdateInfo -> xpru_blockcheck);
  1336.  
  1337.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKSIZE) && UpdateInfo -> xpru_blocksize != -1)
  1338.             SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_RIGHT1],5,ConvNumber,UpdateInfo -> xpru_blocksize);
  1339.  
  1340.  
  1341.         if((UpdateInfo -> xpru_updatemask & XPRU_EXPECTTIME) && UpdateInfo -> xpru_expecttime)
  1342.         {
  1343.             SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_LEFT2],0,UpdateInfo -> xpru_expecttime);
  1344.  
  1345.             if(TimeMax = GetSeconds((STRPTR)UpdateInfo -> xpru_expecttime))
  1346.                 NewTime = TRUE;
  1347.         }
  1348.  
  1349.         if((UpdateInfo -> xpru_updatemask & XPRU_ELAPSEDTIME) && UpdateInfo -> xpru_elapsedtime)
  1350.         {
  1351.             SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_LEFT2],1,UpdateInfo -> xpru_elapsedtime);
  1352.  
  1353.             TimeVal = GetSeconds((STRPTR)UpdateInfo -> xpru_elapsedtime);
  1354.  
  1355.             if(TimeMax)
  1356.                 NewTime = TRUE;
  1357.         }
  1358.  
  1359.         if((UpdateInfo -> xpru_updatemask & XPRU_ERRORS) && UpdateInfo -> xpru_errors != -1)
  1360.             SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_RIGHT2],0,ConvNumber,UpdateInfo -> xpru_errors);
  1361.  
  1362.         if((UpdateInfo -> xpru_updatemask & XPRU_TIMEOUTS) && UpdateInfo -> xpru_timeouts != -1)
  1363.             SZ_PrintLine(RPort,TransferBoxArray[BOX_TRANSFER_RIGHT2],1,ConvNumber,UpdateInfo -> xpru_timeouts);
  1364.  
  1365.         if(NewByte)
  1366.         {
  1367.             ShowStats(TransferGadgetArray[GAD_TRANSFER_PERCENT],ByteVal,ByteMax);
  1368.  
  1369.             if(ByteMax)
  1370.                 ShowString(TransferGadgetArray[GAD_TRANSFER_PERCENT],"%ld%%",(100 * ByteVal) / ByteMax);
  1371.             else
  1372.                 ShowString(TransferGadgetArray[GAD_TRANSFER_PERCENT],"%ld%%",0);
  1373.         }
  1374.  
  1375.         if(NewTime)
  1376.         {
  1377.             LONG TimeDif = (TimeMax - TimeVal) < 0 ? 0 : TimeMax - TimeVal;
  1378.  
  1379.             ShowStats(TransferGadgetArray[GAD_TRANSFER_TIME],TimeDif,TimeMax);
  1380.  
  1381.             ShowString(TransferGadgetArray[GAD_TRANSFER_TIME],"%2ld:%02ld:%02ld",TimeDif / 3600,(TimeDif / 60) % 60,TimeDif % 60);
  1382.         }
  1383.     }
  1384.  
  1385.     return(1);
  1386. }
  1387.  
  1388.     /* xpr_chkabort():
  1389.      *
  1390.      *    Check if the user has aborted the transfer.
  1391.      */
  1392.  
  1393. LONG __asm __saveds
  1394. xpr_chkabort()
  1395. {
  1396.     struct IntuiMessage    *Massage;
  1397.     ULONG             IClass,
  1398.                  Code;
  1399.     struct Gadget        *Gadget;
  1400.     LONG             Result = 0;
  1401.  
  1402.         /* No window available for output? */
  1403.  
  1404.     if(!TransferWindow)
  1405.     {
  1406.         if(!OpenTransferWindow())
  1407.             return(0);
  1408.     }
  1409.  
  1410.         /* Process all incoming messages. */
  1411.  
  1412.     while(Massage = (struct IntuiMessage *)GT_GetIMsg(TransferWindow -> UserPort))
  1413.     {
  1414.         IClass    = Massage -> Class;
  1415.         Code    = Massage -> Code;
  1416.         Gadget    = (struct Gadget *)Massage -> IAddress;
  1417.  
  1418.         GT_ReplyIMsg(Massage);
  1419.  
  1420.         KeySelect(TransferGadgetArray,4,Code,TransferWindow,&Gadget,&IClass,&Code);
  1421.  
  1422.         if(!Result)
  1423.         {
  1424.             if(IClass == IDCMP_NEWSIZE)
  1425.             {
  1426.                 if(!(TransferWindow -> Flags & WFLG_ZOOMED))
  1427.                     RefreshTransferWindow();
  1428.             }
  1429.  
  1430.             if(IClass == IDCMP_CLOSEWINDOW)
  1431.             {
  1432.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_TRANSFER_ABORTED_TXT));
  1433.  
  1434.                 TransferAborted = TRUE;
  1435.  
  1436.                 Result = -1;
  1437.             }
  1438.  
  1439.             if(IClass == IDCMP_GADGETUP)
  1440.             {
  1441.                 switch(Gadget -> GadgetID)
  1442.                 {
  1443.                     case GAD_TRANSFER_ABORT:
  1444.  
  1445.                         LogAction(LocaleString(MSG_TERMXPR_LOGMSG_TRANSFER_ABORTED_TXT));
  1446.  
  1447.                         TransferAborted = TRUE;
  1448.  
  1449.                         Result = -1;
  1450.  
  1451.                         break;
  1452.  
  1453.                     case GAD_TRANSFER_SKIP:
  1454.  
  1455.                         LogAction(LocaleString(MSG_TERMXPR_LOGMSG_FILE_SKIPPED_TXT));
  1456.  
  1457.                         Result = 1;
  1458.  
  1459.                         break;
  1460.                 }
  1461.             }
  1462.         }
  1463.     }
  1464.  
  1465.     return(Result);
  1466. }
  1467.  
  1468.     /* CreateAllGetsGadgets():
  1469.      *
  1470.      *    Create all the gadgets required by xpr_gets() and the like.
  1471.      */
  1472.  
  1473. struct Gadget *
  1474. CreateAllGetsGadgets(BYTE LoadGadget,BYTE Password,WORD MaxChars,STRPTR String,STRPTR Prompt,struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,struct Screen *Screen)
  1475. {
  1476.     struct Gadget        *Gadget;
  1477.     struct NewGadget     NewGadget;
  1478.  
  1479.     if(MaxChars < 1)
  1480.         MaxChars = 255;
  1481.  
  1482.     memset(&NewGadget,0,sizeof(struct NewGadget));
  1483.  
  1484.     SZ_SizeSetup(Screen,&UserFont,TRUE);
  1485.  
  1486.     if(Gadget = CreateContext(GadgetList))
  1487.     {
  1488.         WORD Width = SZ_TextWidth(Prompt),Counter = 0;
  1489.  
  1490.         if(Width < SZ_Width(STRING_KIND,NULL,60,NULL))
  1491.             Width = SZ_Width(STRING_KIND,NULL,60,NULL);
  1492.  
  1493.         SZ_SetWidth(Width);
  1494.  
  1495.         NewGadget . ng_GadgetText    = Prompt;
  1496.         NewGadget . ng_TextAttr        = &UserFont;
  1497.         NewGadget . ng_VisualInfo    = VisualInfo;
  1498.         NewGadget . ng_GadgetID        = Counter;
  1499.         NewGadget . ng_Flags        = PLACETEXT_ABOVE;
  1500.  
  1501.         if(LoadGadget)
  1502.         {
  1503.             GadgetArray[Counter++] = Gadget = CreateGadget(Password ? PASSWORD_KIND : STRING_KIND,Gadget,&NewGadget,
  1504.                 SZ_Adjust,    TRUE,
  1505.                 SZ_AutoWidth,    TRUE,
  1506.                 SZ_LeaveFolder,    TRUE,
  1507.  
  1508.                 GTST_MaxChars,    MaxChars,
  1509.                 GTST_String,    String,
  1510.                 GA_TabCycle,    FALSE,
  1511.             TAG_DONE);
  1512.  
  1513.             NewGadget . ng_GadgetID = Counter;
  1514.  
  1515.             GadgetArray[Counter++] = Gadget = CreateGadget(FILE_KIND,Gadget,&NewGadget,
  1516.                 SZ_Adjust,    TRUE,
  1517.                 SZ_AutoWidth,    TRUE,
  1518.                 SZ_PlaceLeft,    TRUE,
  1519.             TAG_DONE);
  1520.         }
  1521.         else
  1522.         {
  1523.             GadgetArray[Counter++] = Gadget = CreateGadget(Password ? PASSWORD_KIND : STRING_KIND,Gadget,&NewGadget,
  1524.                 SZ_Adjust,    TRUE,
  1525.                 SZ_AutoWidth,    TRUE,
  1526.  
  1527.                 GTST_MaxChars,    MaxChars,
  1528.                 GTST_String,    String,
  1529.                 GA_TabCycle,    FALSE,
  1530.             TAG_DONE);
  1531.  
  1532.             GadgetArray[Counter++] = NULL;
  1533.         }
  1534.  
  1535.         SZ_UpdateMaxWidth(BUTTON_KIND,LocaleString(MSG_TERMXPR_OKAY_GAD),0,NULL);
  1536.         SZ_UpdateMaxWidth(BUTTON_KIND,LocaleString(MSG_GLOBAL_CANCEL_GAD),0,NULL);
  1537.  
  1538.         SZ_SetWidth(SZ_ResetMaxWidth());
  1539.  
  1540.         NewGadget . ng_GadgetText    = LocaleString(MSG_TERMXPR_OKAY_GAD);
  1541.         NewGadget . ng_GadgetID        = Counter;
  1542.         NewGadget . ng_Flags        = 0;
  1543.  
  1544.         GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  1545.             SZ_Adjust,    TRUE,
  1546.             SZ_AutoWidth,    TRUE,
  1547.             SZ_AlignExtra,    TRUE,
  1548.             SZ_AlignLeft,    TRUE,
  1549.             SZ_AlignBottom,    TRUE,
  1550.  
  1551.             GT_Underscore,    '_',
  1552.         TAG_DONE);
  1553.  
  1554.         NewGadget . ng_GadgetText    = LocaleString(MSG_GLOBAL_CANCEL_GAD);
  1555.         NewGadget . ng_GadgetID        = Counter;
  1556.  
  1557.         GadgetArray[Counter] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  1558.             SZ_Adjust,    TRUE,
  1559.             SZ_AutoWidth,    TRUE,
  1560.             SZ_AlignRight,    TRUE,
  1561.  
  1562.             GT_Underscore,    '_',
  1563.         TAG_DONE);
  1564.     }
  1565.  
  1566.     return(Gadget);
  1567. }
  1568.  
  1569.     /* xpr_gets(STRPTR Prompt,STRPTR Buffer):
  1570.      *
  1571.      *    Prompt the user for string input.
  1572.      */
  1573.  
  1574. LONG __saveds __asm
  1575. xpr_gets(register __a0 STRPTR Prompt,register __a1 STRPTR Buffer)
  1576. {
  1577.     struct Gadget    *GadgetList = NULL;
  1578.     struct Gadget    *GadgetArray[4];
  1579.     struct Window    *PanelWindow;
  1580.     LONG         Success = FALSE;
  1581.  
  1582.     if(!Prompt)
  1583.         Prompt = LocaleString(MSG_TERMXPR_INPUT_REQUIRED_TXT);
  1584.  
  1585.     if(CreateAllGetsGadgets(FALSE,FALSE,0,Buffer,Prompt,GadgetArray,&GadgetList,VisualInfo,Window -> WScreen))
  1586.     {
  1587.         if(PanelWindow = OpenWindowTags(NULL,
  1588.             WA_Left,    GetScreenLeft(Window) + (GetScreenWidth(Window) - SZ_GetWindowWidth()) / 2,
  1589.             WA_Top,        GetScreenTop(Window) + (GetScreenHeight(Window) - SZ_GetWindowHeight())    / 2,
  1590.             WA_Width,    SZ_GetWindowWidth(),
  1591.             WA_Height,    SZ_GetWindowHeight(),
  1592.  
  1593.             WA_Activate,    TRUE,
  1594.             WA_DragBar,    TRUE,
  1595.             WA_DepthGadget,    TRUE,
  1596.             WA_CloseGadget,    TRUE,
  1597.             WA_RMBTrap,    TRUE,
  1598.             WA_CustomScreen,Window -> WScreen,
  1599.  
  1600.             WA_IDCMP,    IDCMP_GADGETDOWN | IDCMP_ACTIVEWINDOW | IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | IDCMP_RAWKEY | BUTTONIDCMP | STRINGIDCMP,
  1601.  
  1602.             WA_Title,    LocaleString(MSG_GLOBAL_ENTER_TEXT_TXT),
  1603.         TAG_DONE))
  1604.         {
  1605.             struct IntuiMessage    *Massage;
  1606.             ULONG             IClass,Code;
  1607.             struct Gadget        *Gadget;
  1608.             BYTE             Terminated = FALSE;
  1609.  
  1610.             PushWindow(PanelWindow);
  1611.  
  1612.             AddGList(PanelWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  1613.             RefreshGList(GadgetList,PanelWindow,NULL,(UWORD)-1);
  1614.             GT_RefreshWindow(PanelWindow,NULL);
  1615.  
  1616.             ActiveGadget = NULL;
  1617.  
  1618.             while(!Terminated)
  1619.             {
  1620.                 WaitPort(PanelWindow -> UserPort);
  1621.  
  1622.                 while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort)))
  1623.                 {
  1624.                     IClass    = Massage -> Class;
  1625.                     Code    = Massage -> Code;
  1626.                     Gadget    = (struct Gadget *)Massage -> IAddress;
  1627.  
  1628.                     GT_ReplyIMsg(Massage);
  1629.  
  1630.                     if(IClass == IDCMP_VANILLAKEY)
  1631.                         KeySelect(GadgetArray,3,Code,PanelWindow,&Gadget,&IClass,&Code);
  1632.  
  1633.                     if(IClass == IDCMP_RAWKEY && Code == HELP_CODE)
  1634.                         DisplayBeep(PanelWindow -> WScreen);
  1635.  
  1636.                     if(IClass == IDCMP_GADGETDOWN)
  1637.                     {
  1638.                         if((Gadget -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
  1639.                             ActiveGadget = Gadget;
  1640.                     }
  1641.  
  1642.                     if(IClass == IDCMP_ACTIVEWINDOW && ActiveGadget)
  1643.                         ActivateGadget(ActiveGadget,PanelWindow,NULL);
  1644.  
  1645.                     if(IClass == IDCMP_CLOSEWINDOW)
  1646.                         Terminated = TRUE;
  1647.  
  1648.                     if(IClass == IDCMP_GADGETUP)
  1649.                     {
  1650.                         switch(Gadget -> GadgetID)
  1651.                         {
  1652.                             case 0:
  1653.                             case 2:    strcpy(Buffer,SZ_GetString(GadgetArray[0]));
  1654.  
  1655.                                 Success = TRUE;
  1656.  
  1657.                                 Terminated = TRUE;
  1658.  
  1659.                                 break;
  1660.  
  1661.                             case 3:    Terminated = TRUE;
  1662.  
  1663.                                 break;
  1664.                         }
  1665.                     }
  1666.                 }
  1667.             }
  1668.  
  1669.             ActiveGadget = NULL;
  1670.  
  1671.             RemoveGList(PanelWindow,GadgetList,(UWORD)-1);
  1672.  
  1673.             PopWindow();
  1674.  
  1675.             CloseWindow(PanelWindow);
  1676.         }
  1677.  
  1678.         FreeGadgets(GadgetList);
  1679.     }
  1680.  
  1681.     return(Success);
  1682. }
  1683.  
  1684.     /* xpr_setserial(LONG Status):
  1685.      *
  1686.      *    Set/read the serial status (parameters).
  1687.      */
  1688.  
  1689. LONG __saveds __asm
  1690. xpr_setserial(register __d0 LONG Status)
  1691. {
  1692.     if(WriteRequest)
  1693.     {
  1694.         STATIC LONG XprBauds[12] =
  1695.         {
  1696.                110,
  1697.                300,
  1698.               1200,
  1699.               2400,
  1700.               4800,
  1701.               9600,
  1702.              19200,
  1703.              31250,
  1704.              38400,
  1705.              57600,
  1706.              76800,
  1707.             115200
  1708.         };
  1709.  
  1710.         LONG Return,Min = MILLION,Diff,Index,i;
  1711.  
  1712.         WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  1713.  
  1714.         DoIO(WriteRequest);
  1715.  
  1716.         Return = WriteRequest -> io_SerFlags & 0xFF;
  1717.  
  1718.         if(WriteRequest -> io_ExtFlags & SEXTF_MSPON)
  1719.             Return |= ST_PARTYMARKON;
  1720.  
  1721.         if(WriteRequest -> io_ExtFlags & SEXTF_MARK)
  1722.             Return |= ST_PARTYMARK;
  1723.  
  1724.         if(WriteRequest -> io_StopBits == 2)
  1725.             Return |= ST_2BITS;
  1726.  
  1727.         if(WriteRequest -> io_ReadLen == 7)
  1728.             Return |= ST_READ7;
  1729.  
  1730.         if(WriteRequest -> io_WriteLen == 7)
  1731.             Return |= ST_WRITE7;
  1732.  
  1733.         for(i = 0 ; i < 12 ; i++)
  1734.         {
  1735.             Diff = WriteRequest -> io_Baud - XprBauds[i];
  1736.  
  1737.             if(Diff >= 0 && Diff < Min)
  1738.             {
  1739.                 Min    = Diff;
  1740.                 Index    = i;
  1741.             }
  1742.         }
  1743.  
  1744.         Return |= (Index << 16);
  1745.  
  1746.             /* `term' supports a number of serial transfer speed rates
  1747.              * not included in the XPR standard. For this reason this
  1748.              * xpr_setserial() implementation will not change the serial
  1749.              * line parameters.
  1750.              */
  1751. /*
  1752.         if(Status != -1)
  1753.         {
  1754.             WriteRequest -> io_SerFlags = Status & 0xFF;
  1755.             WriteRequest -> io_ExtFlags = 0;
  1756.  
  1757.             if(Status & ST_PARTYMARKON)
  1758.                 WriteRequest -> io_ExtFlags |= SEXTF_MSPON;
  1759.  
  1760.             if(Status & ST_PARTYMARK)
  1761.                 WriteRequest -> io_ExtFlags |= SEXTF_MARK;
  1762.  
  1763.             if(Status & ST_2BITS)
  1764.                 WriteRequest -> io_StopBits = 2;
  1765.             else
  1766.                 WriteRequest -> io_StopBits = 1;
  1767.  
  1768.             if(Status & ST_READ7)
  1769.                 WriteRequest -> io_ReadLen = 7;
  1770.             else
  1771.                 WriteRequest -> io_ReadLen = 8;
  1772.  
  1773.             if(Status & ST_WRITE7)
  1774.                 WriteRequest -> io_WriteLen = 7;
  1775.             else
  1776.                 WriteRequest -> io_WriteLen = 8;
  1777.  
  1778.             ReadRequest -> io_Baud        = WriteRequest -> io_Baud;
  1779.             ReadRequest -> io_SerFlags    = WriteRequest -> io_SerFlags;
  1780.             ReadRequest -> io_ExtFlags    = WriteRequest -> io_ExtFlags;
  1781.             ReadRequest -> io_StopBits    = WriteRequest -> io_StopBits;
  1782.             ReadRequest -> io_ReadLen    = WriteRequest -> io_ReadLen;
  1783.             ReadRequest -> io_WriteLen    = WriteRequest -> io_WriteLen;
  1784.  
  1785.             WriteRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
  1786.  
  1787.             DoIO(WriteRequest);
  1788.  
  1789.             ReadRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
  1790.  
  1791.             DoIO(ReadRequest);
  1792.         }
  1793. */
  1794.         return(Return);
  1795.     }
  1796.     else
  1797.         return(-1);
  1798. }
  1799.  
  1800.     /* xpr_ffirst(STRPTR Buffer,STRPTR Pattern):
  1801.      *
  1802.      *    Batch file upload: find the first matching file and return
  1803.      *    its name.
  1804.      */
  1805.  
  1806. LONG __saveds __asm
  1807. xpr_ffirst(register __a0 STRPTR Buffer,register __a1 STRPTR Pattern)
  1808. {
  1809.     if(FileTransferInfo)
  1810.     {
  1811.         FileTransferInfo -> DoneSize    = 0;
  1812.         FileTransferInfo -> DoneFiles    = 0;
  1813.  
  1814.         FileTransferInfo -> CurrentFile    = (struct FileTransferNode *)FileTransferInfo -> FileList . mlh_Head;
  1815.         FileTransferInfo -> CurrentSize    = FileTransferInfo -> CurrentFile -> Size;
  1816.  
  1817.         strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  1818.  
  1819.         return(1);
  1820.     }
  1821.     else
  1822.         return(0);
  1823. }
  1824.  
  1825.     /* xpr_fnext(LONG OldState,STRPTR Buffer,STRPTR Pattern):
  1826.      *
  1827.      *    Batch file upload: find the next matching file
  1828.      *    - if any - and return its name.
  1829.      */
  1830.  
  1831. LONG __saveds __asm
  1832. xpr_fnext(register __d0 LONG OldState,register __a0 STRPTR Buffer,register __a1 STRPTR Pattern)
  1833. {
  1834.     if(FileTransferInfo)
  1835.     {
  1836.         if(FileTransferInfo -> CurrentFile -> Node . mln_Succ -> mln_Succ)
  1837.         {
  1838.             FileTransferInfo -> DoneSize    += FileTransferInfo -> CurrentSize;
  1839.             FileTransferInfo -> DoneFiles    += 1;
  1840.  
  1841.             FileTransferInfo -> CurrentFile  = (struct FileTransferNode *)FileTransferInfo -> CurrentFile -> Node . mln_Succ;
  1842.             FileTransferInfo -> CurrentSize  = FileTransferInfo -> CurrentFile -> Size;
  1843.  
  1844.             strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  1845.  
  1846.             return(1);
  1847.         }
  1848.     }
  1849.  
  1850.     return(0);
  1851. }
  1852.  
  1853.     /* xpr_finfo(STRPTR FileName,LONG InfoType):
  1854.      *
  1855.      *    Return information on a given file.
  1856.      */
  1857.  
  1858. LONG __saveds __asm
  1859. xpr_finfo(register __a0 STRPTR FileName,register __d0 LONG InfoType)
  1860. {
  1861.     struct FileInfoBlock    *FileInfo;
  1862.     LONG             Size;
  1863.  
  1864.     switch(InfoType)
  1865.     {
  1866.             /* Return the file size. */
  1867.  
  1868.         case 1:    Size = 0;
  1869.  
  1870.             if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  1871.             {
  1872.                 UBYTE    RealName[MAX_FILENAME_LENGTH];
  1873.                 BPTR    FileLock;
  1874.  
  1875.                 FileName = NewFileName(FileName,RealName);
  1876.  
  1877.                 if(FileLock = Lock(FileName,ACCESS_READ))
  1878.                 {
  1879.                     if(Examine(FileLock,FileInfo))
  1880.                     {
  1881.                         if(FileInfo -> fib_DirEntryType < 0)
  1882.                             Size = FileInfo -> fib_Size;
  1883.                     }
  1884.  
  1885.                     UnLock(FileLock);
  1886.                 }
  1887.  
  1888.                 FreeDosObject(DOS_FIB,FileInfo);
  1889.             }
  1890.  
  1891.             return(Size);
  1892.  
  1893.             break;
  1894.  
  1895.             /* Return the file transfer mode. */
  1896.  
  1897.         case 2:    return(BinaryTransfer ? 1 : 2);
  1898.  
  1899.             /* Ignore the rest. */
  1900.  
  1901.         default:return(0);
  1902.     }
  1903. }
  1904.  
  1905.     /* xpr_options(LONG NumOpts,struct xpr_option **Opts):
  1906.      *
  1907.      *    Provide a more polished user interface to set the
  1908.      *    transfer protocol options.
  1909.      */
  1910.  
  1911. ULONG __saveds __asm
  1912. xpr_options(register __d0 LONG NumOpts,register __a0 struct xpr_option **Opts)
  1913. {
  1914.     struct Gadget    *GadgetList = NULL;
  1915.     struct Gadget    *GadgetArray[34];
  1916.     struct Window    *PanelWindow;
  1917.     LONG         i,Count;
  1918.  
  1919.     ULONG         Flags = 0;
  1920.  
  1921.         /* We only have 32 bits! */
  1922.  
  1923.     if(NumOpts > 32)
  1924.         NumOpts = 32;
  1925.  
  1926.     if(CreateAllOptionGadgets(&Count,NumOpts,Opts,GadgetArray,&GadgetList,VisualInfo))
  1927.     {
  1928.         if(PanelWindow = OpenWindowTags(NULL,
  1929.             WA_Left,    GetScreenLeft(Window) + (GetScreenWidth(Window) - SZ_GetWindowWidth()) / 2,
  1930.             WA_Top,        GetScreenTop(Window) + (GetScreenHeight(Window) - SZ_GetWindowHeight())    / 2,
  1931.             WA_Width,    SZ_GetWindowWidth(),
  1932.             WA_Height,    SZ_GetWindowHeight(),
  1933.  
  1934.             WA_Activate,    TRUE,
  1935.             WA_DragBar,    TRUE,
  1936.             WA_DepthGadget,    TRUE,
  1937.             WA_CloseGadget,    TRUE,
  1938.             WA_RMBTrap,    TRUE,
  1939.             WA_CustomScreen,Window -> WScreen,
  1940.  
  1941.             WA_IDCMP,    IDCMP_GADGETDOWN | IDCMP_ACTIVEWINDOW | IDCMP_CLOSEWINDOW | IDCMP_RAWKEY | IDCMP_VANILLAKEY | CHECKBOXIDCMP | STRINGIDCMP | INTEGERIDCMP | BUTTONIDCMP,
  1942.  
  1943.             WA_Title,    OptionTitle ? OptionTitle : LocaleString(MSG_TERMXPR_TRANSFER_OPTIONS_TXT),
  1944.         TAG_DONE))
  1945.         {
  1946.             struct IntuiMessage    *Massage;
  1947.             ULONG             IClass,Code;
  1948.             struct Gadget        *Gadget;
  1949.             BYTE             Terminated = FALSE,
  1950.                          CheckFlags = FALSE;
  1951.  
  1952.             PushWindow(PanelWindow);
  1953.  
  1954.             AddGList(PanelWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  1955.             RefreshGList(GadgetList,PanelWindow,NULL,(UWORD)-1);
  1956.             GT_RefreshWindow(PanelWindow,NULL);
  1957.  
  1958.             ActiveGadget = NULL;
  1959.  
  1960.             SetSignal(0,SIG_BREAK);
  1961.  
  1962.             while(!Terminated)
  1963.             {
  1964.                 if(Wait(PORTMASK(PanelWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
  1965.                     break;
  1966.  
  1967.                 while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort)))
  1968.                 {
  1969.                     IClass    = Massage -> Class;
  1970.                     Code    = Massage -> Code;
  1971.                     Gadget    = (struct Gadget *)Massage -> IAddress;
  1972.  
  1973.                     GT_ReplyIMsg(Massage);
  1974.  
  1975.                     if(IClass == IDCMP_VANILLAKEY)
  1976.                         KeySelect(GadgetArray,Count,Code,PanelWindow,&Gadget,&IClass,&Code);
  1977.  
  1978.                     if(IClass == IDCMP_RAWKEY && Code == HELP_CODE)
  1979.                         DisplayBeep(PanelWindow -> WScreen);
  1980.  
  1981.                     if(IClass == IDCMP_GADGETDOWN)
  1982.                     {
  1983.                         if((Gadget -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
  1984.                             ActiveGadget = Gadget;
  1985.                     }
  1986.  
  1987.                     if(IClass == IDCMP_ACTIVEWINDOW && ActiveGadget)
  1988.                         ActivateGadget(ActiveGadget,PanelWindow,NULL);
  1989.  
  1990.                     if(IClass == IDCMP_CLOSEWINDOW)
  1991.                         Terminated = TRUE;
  1992.  
  1993.                     if(IClass == IDCMP_GADGETUP)
  1994.                     {
  1995.                         switch(Gadget -> GadgetID)
  1996.                         {
  1997.                             case GAD_XPROPTIONS_USE:
  1998.  
  1999.                                 Terminated = CheckFlags = TRUE;
  2000.                                 break;
  2001.  
  2002.                             case GAD_XPROPTIONS_CANCEL:
  2003.  
  2004.                                 Terminated = TRUE;
  2005.                                 break;
  2006.  
  2007.                             default:
  2008.  
  2009.                                 if(Gadget -> GadgetID < NumOpts)
  2010.                                 {
  2011.                                     if(Opts[Gadget -> GadgetID] -> xpro_type == XPRO_COMMAND)
  2012.                                     {
  2013.                                         Flags |= (1 << Gadget -> GadgetID);
  2014.  
  2015.                                         Terminated = CheckFlags = TRUE;
  2016.                                     }
  2017.                                 }
  2018.  
  2019.                                 break;
  2020.                         }
  2021.                     }
  2022.                 }
  2023.             }
  2024.  
  2025.             if(CheckFlags)
  2026.             {
  2027.                 for(i = 0 ; i < NumOpts ; i++)
  2028.                 {
  2029.                     switch(Opts[i] -> xpro_type)
  2030.                     {
  2031.                         case XPRO_BOOLEAN:
  2032.  
  2033.                             if(SZ_GetChecked(GadgetArray[i]) != GetOptionMode(Opts[i]))
  2034.                             {
  2035.                                 Flags |= (1 << i);
  2036.  
  2037.                                 if(SZ_GetChecked(GadgetArray[i]))
  2038.                                     strcpy(Opts[i] -> xpro_value,"yes");
  2039.                                 else
  2040.                                     strcpy(Opts[i] -> xpro_value,"no");
  2041.  
  2042.                                 NewOptions = TRUE;
  2043.                             }
  2044.  
  2045.                             break;
  2046.  
  2047.                         case XPRO_COMMPAR:
  2048.                         case XPRO_LONG:
  2049.                         case XPRO_STRING:
  2050.  
  2051.                             if(strcmp(Opts[i] -> xpro_value,SZ_GetString(GadgetArray[i])))
  2052.                             {
  2053.                                 Flags |= (1 << i);
  2054.  
  2055.                                 strcpy(Opts[i] -> xpro_value,SZ_GetString(GadgetArray[i]));
  2056.  
  2057.                                 NewOptions = TRUE;
  2058.                             }
  2059.  
  2060.                             break;
  2061.                     }
  2062.                 }
  2063.             }
  2064.             else
  2065.             {
  2066.                 NewOptions    = FALSE;
  2067.                 Flags        = NULL;
  2068.             }
  2069.  
  2070.             ActiveGadget = NULL;
  2071.  
  2072.             RemoveGList(PanelWindow,GadgetList,(UWORD)-1);
  2073.  
  2074.             PopWindow();
  2075.  
  2076.             CloseWindow(PanelWindow);
  2077.         }
  2078.     }
  2079.  
  2080.     FreeGadgets(GadgetList);
  2081.  
  2082.     return(Flags);
  2083. }
  2084.  
  2085.     /* xpr_unlink(STRPTR FileName):
  2086.      *
  2087.      *    Remove (delete) a given file.
  2088.      */
  2089.  
  2090. LONG __saveds __asm
  2091. xpr_unlink(register __a0 STRPTR FileName)
  2092. {
  2093.         /* Sorry, but it is far too dangerous to let the protocol
  2094.          * remove any files with path name substitution enabled.
  2095.          * The protocol could accidentally hit the wrong file.
  2096.          */
  2097.  
  2098.     if(!Config -> MiscConfig -> OverridePath)
  2099.     {
  2100.         if(DeleteFile(FileName))
  2101.         {
  2102.             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_DELETE_FILE_TXT),FilePart(FileName));
  2103.  
  2104.             return(0);
  2105.         }
  2106.     }
  2107.  
  2108.     return(-1);
  2109. }
  2110.  
  2111.     /* xpr_squery():
  2112.      *
  2113.      *    Check how many characters are present in the serial buffer.
  2114.      */
  2115.  
  2116. LONG __asm __saveds
  2117. xpr_squery()
  2118. {
  2119.     if(WriteRequest)
  2120.     {
  2121.         WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  2122.  
  2123.         DoIO(WriteRequest);
  2124.  
  2125.             /* Return error if carrier is lost. */
  2126.  
  2127.         if((WriteRequest -> io_Status & CIAF_COMCD) && Config -> SerialConfig -> CheckCarrier)
  2128.             Online = FALSE;
  2129.         else
  2130.             return((LONG)WriteRequest -> IOSer . io_Actual);
  2131.     }
  2132.  
  2133.     return(-1);
  2134. }
  2135.  
  2136.     /* xpr_getptr(LONG InfoType):
  2137.      *
  2138.      *    Return a pointer to the term custom screen.
  2139.      */
  2140.  
  2141. LONG __saveds __asm
  2142. xpr_getptr(register __d0 LONG InfoType)
  2143. {
  2144.     if(InfoType == 1)
  2145.         return((LONG)Window -> WScreen);
  2146.     else
  2147.         return(-1);
  2148. }
  2149.  
  2150.     /* xpr_stealopts(STRPTR Prompt,STRPTR Buffer):
  2151.      *
  2152.      *    Steal the contents of the options buffer (replacement
  2153.      *    for xpr_gets).
  2154.      */
  2155.  
  2156. LONG __saveds __asm
  2157. xpr_stealopts(register __a0 STRPTR Prompt,register __a1 STRPTR Buffer)
  2158. {
  2159.     if(Buffer)
  2160.         strcpy(ProtocolOptsBuffer,Buffer);
  2161.  
  2162.     return(1);
  2163. }
  2164.