home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / telecomm / terms / term-4.1-source.lha / Extras / Source / term-Source.lha / termXPR.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-27  |  52.5 KB  |  2,526 lines

  1. /*
  2. **    termXPR.c
  3. **
  4. **    External transfer protocol support routines
  5. **
  6. **    Copyright © 1990-1994 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* These variables keep the transferred bytes and transfer
  13.      * time in seconds.
  14.      */
  15.  
  16. STATIC LONG         ByteVal,
  17.              ByteMax,
  18.              TimeVal,
  19.              TimeMax,
  20.  
  21.              LastTimeDif,
  22.              LastPercent;
  23.  
  24.     /* Transfer statistics. */
  25.  
  26. STATIC ULONG         CPS_Minimum,
  27.              CPS_Maximum,
  28.              CPS_Average,
  29.              CPS_Current,
  30.              CPS_Count,
  31.              CPS_Last;
  32.  
  33.     LONG         CPL_Min,
  34.              CPL_Avg,
  35.              CPL_Cur;
  36.  
  37.     /* The name of the file being transmitted, in case the
  38.      * `override transfer path' feature is enabled.
  39.      */
  40.  
  41. STATIC struct Buffer    *CurrentFile;
  42.  
  43.     /* Yet another flag, this one determines whether we already told
  44.      * the user that the file we are currently processing will fit
  45.      * on the destination device.
  46.      */
  47.  
  48. STATIC BYTE         Alerted,
  49.              CarrierMessage;
  50.  
  51. STATIC UBYTE __far     RealName[MAX_FILENAME_LENGTH];
  52. STATIC ULONG         LastSeconds;
  53.  
  54.     /* PrintBox(LONG Box,LONG Line,STRPTR String,...):
  55.      *
  56.      *    Update the contents of a text box.
  57.      */
  58.  
  59. STATIC VOID __stdargs
  60. PrintBox(LONG Box,LONG Line,STRPTR String,...)
  61. {
  62.     UBYTE     LocalBuffer[256];
  63.     va_list     VarArgs;
  64.  
  65.     va_start(VarArgs,String);
  66.     VSPrintf(LocalBuffer,String,VarArgs);
  67.     va_end(VarArgs);
  68.  
  69.     LT_SetAttributes(TransferHandle,Box,LABX_Index,Line,LABX_Text,LocalBuffer,TAG_DONE);
  70. }
  71.  
  72.     /* OpenTransferWindow():
  73.      *
  74.      *    Local routine to open the transfer window.
  75.      */
  76.  
  77. STATIC BYTE
  78. OpenTransferWindow(VOID)
  79. {
  80.         /* Block window input. */
  81.  
  82.     BlockWindows();
  83.  
  84.         /* Try to open the transfer window panel. */
  85.  
  86.     if(TransferPanel(LocaleString(MSG_TERMXPR_RECEIVE_FILES_TXT)))
  87.     {
  88.             /* Supply the log text. */
  89.  
  90.         LogAction(LocaleString(MSG_TERMXPR_LOGMSG_INITIATE_BINARY_DOWNLOAD_TXT));
  91.  
  92.             /* Return success. */
  93.  
  94.         return(TRUE);
  95.     }
  96.     else
  97.     {
  98.             /* Re-enable window input. */
  99.  
  100.         ReleaseWindows();
  101.  
  102.             /* Return failure. */
  103.  
  104.         return(FALSE);
  105.     }
  106. }
  107.  
  108.     /* CheckAbort(BOOLEAN CheckCarrier):
  109.      *
  110.      *    Check for transfer abort.
  111.      */
  112.  
  113. STATIC LONG __regargs
  114. CheckAbort(BOOLEAN CheckCarrier)
  115. {
  116.     struct IntuiMessage    *Message;
  117.     ULONG             MsgClass,
  118.                  MsgQualifier;
  119.     UWORD             MsgCode;
  120.     struct Gadget        *MsgGadget;
  121.     struct Window        *MsgWindow;
  122.     LONG             Result = 0;
  123.  
  124.         /* No window available for output? */
  125.  
  126.     if(!TransferWindow)
  127.     {
  128.         if(!OpenTransferWindow())
  129.             return(-1);
  130.     }
  131.  
  132.         /* Are we to check the carrier status? */
  133.  
  134.     if(CheckCarrier)
  135.     {
  136.             /* Return error if carrier is lost. */
  137.  
  138.         if(GetSerialStatus() & CIAF_COMCD)
  139.         {
  140.             if(!CarrierMessage)
  141.             {
  142.                 CarrierMessage = TRUE;
  143.  
  144.                 AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  145.             }
  146.  
  147.             ObtainSemaphore(&OnlineSemaphore);
  148.  
  149.             WasOnline    = Online;
  150.             Online        = FALSE;
  151.  
  152.             ReleaseSemaphore(&OnlineSemaphore);
  153.  
  154.             TransferError = TRUE;
  155.  
  156.             return(-1);
  157.         }
  158.     }
  159.  
  160.         /* Process all incoming messages. */
  161.  
  162.     while(Message = (struct IntuiMessage *)GT_GetIMsg(TransferWindow -> UserPort))
  163.     {
  164.         MsgClass    = Message -> Class;
  165.         MsgQualifier    = Message -> Qualifier;
  166.         MsgCode        = Message -> Code;
  167.         MsgGadget    = (struct Gadget *)Message -> IAddress;
  168.         MsgWindow    = Message -> IDCMPWindow;
  169.  
  170.         GT_ReplyIMsg(Message);
  171.  
  172.         if(MsgWindow == TransferWindow)
  173.         {
  174.             LT_HandleInput(TransferHandle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
  175.  
  176.             if(!Result)
  177.             {
  178.                 if(MsgClass == IDCMP_CLOSEWINDOW)
  179.                 {
  180.                     LogAction(LocaleString(MSG_TERMXPR_LOGMSG_TRANSFER_ABORTED_TXT));
  181.  
  182.                     TransferAborted = TRUE;
  183.  
  184.                     Result = -1;
  185.                 }
  186.  
  187.                 if(MsgClass == IDCMP_GADGETUP)
  188.                 {
  189.                     switch(MsgGadget -> GadgetID)
  190.                     {
  191.                         case GAD_TRANSFER_ABORT:
  192.  
  193.                             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_TRANSFER_ABORTED_TXT));
  194.  
  195.                             TransferAborted = TRUE;
  196.  
  197.                             Result = -1;
  198.  
  199.                             break;
  200.  
  201.                         case GAD_TRANSFER_SKIP:
  202.  
  203.                             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_FILE_SKIPPED_TXT));
  204.  
  205.                             Result = 1;
  206.  
  207.                             break;
  208.  
  209.                         case GAD_TRANSFER_ABORT_FILE:
  210.  
  211.                             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_FILE_ABORTED_TXT));
  212.  
  213.                             Result = 2;
  214.  
  215.                             break;
  216.                     }
  217.                 }
  218.             }
  219.         }
  220.         else
  221.         {
  222.             if(TransferPerfWindow)
  223.             {
  224.                 struct RastPort *RPort = TransferPerfWindow -> RPort;
  225.  
  226.                 if(MsgClass == IDCMP_NEWSIZE)
  227.                 {
  228.                     SetAPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  229.  
  230.                     RectFill(RPort,TransferPerfWindow -> BorderLeft,TransferPerfWindow -> BorderTop,TransferPerfWindow -> Width - (TransferPerfWindow -> BorderRight + 1),TransferPerfWindow -> Height - (TransferPerfWindow -> BorderBottom + 1));
  231.  
  232.                     CPL_Min = CPL_Avg = CPL_Cur = -1;
  233.                 }
  234.  
  235.                 if(MsgClass == IDCMP_CLOSEWINDOW)
  236.                 {
  237.                     PutWindowInfo(WINDOW_PERF,TransferPerfWindow -> LeftEdge,TransferPerfWindow -> TopEdge,TransferPerfWindow -> Width,TransferPerfWindow -> Height);
  238.  
  239.                     CloseWindowSafely(TransferPerfWindow);
  240.  
  241.                     TransferPerfWindow = NULL;
  242.                 }
  243.             }
  244.         }
  245.     }
  246.  
  247.     return(Result);
  248. }
  249.  
  250.     /* NewFileName(STRPTR Source,STRPTR Buffer):
  251.      *
  252.      *    Build a valid file and path name, including path
  253.      *    substitution, etc.
  254.      */
  255.  
  256. STATIC STRPTR __regargs
  257. NewFileName(STRPTR Source,STRPTR Buffer)
  258. {
  259.     if(Config -> MiscConfig -> OverridePath && !Uploading)
  260.     {
  261.         if(DownloadPath)
  262.             strcpy(Buffer,DownloadPath);
  263.         else
  264.             strcpy(Buffer,Config -> PathConfig -> BinaryDownloadPath);
  265.  
  266.         if(!Buffer[0])
  267.         {
  268.             if(!GetCurrentDirName(Buffer,MAX_FILENAME_LENGTH))
  269.                 Buffer[0] = 0;
  270.         }
  271.  
  272.         if(Buffer[0])
  273.         {
  274.             if(AddPart(Buffer,FilePart(Source),MAX_FILENAME_LENGTH))
  275.                 return(Buffer);
  276.         }
  277.     }
  278.     else
  279.     {
  280.         if(FilePart(Source) == Source)
  281.         {
  282.             if(GetCurrentDirName(Buffer,MAX_FILENAME_LENGTH))
  283.             {
  284.                 if(AddPart(Buffer,Source,MAX_FILENAME_LENGTH))
  285.                     return(Buffer);
  286.             }
  287.         }
  288.     }
  289.  
  290.     strcpy(Buffer,Source);
  291.  
  292.     return(Source);
  293. }
  294.  
  295.     /* IdentifySource(STRPTR Name,STRPTR BBSName,struct DateStamp *OpenDate):
  296.      *
  297.      *    Attach source information (BBS name, date and time) to a file.
  298.      */
  299.  
  300. STATIC VOID __regargs
  301. IdentifySource(STRPTR Name,STRPTR BBSName,struct DateStamp *OpenDate)
  302. {
  303.     UBYTE        LocalBuffer[MAX_FILENAME_LENGTH],
  304.             Time[40],
  305.             Date[40];
  306.     struct DateTime    DateTime;
  307.  
  308.     CopyMem(OpenDate,&DateTime . dat_Stamp,sizeof(struct DateStamp));
  309.  
  310.         /* Prepare for date conversion. */
  311.  
  312.     DateTime . dat_Format    = FORMAT_DOS;
  313.     DateTime . dat_Flags    = 0;
  314.     DateTime . dat_StrDay    = NULL;
  315.     DateTime . dat_StrDate    = Date;
  316.     DateTime . dat_StrTime    = Time;
  317.  
  318.         /* Convert the date. */
  319.  
  320.     if(DateToStr(&DateTime))
  321.     {
  322.         StripSpaces(BBSName);
  323.         StripSpaces(Date);
  324.         StripSpaces(Time);
  325.  
  326.         if(BBSName[0])
  327.             SPrintf(LocalBuffer,"%s %s %s",BBSName,Date,Time);
  328.         else
  329.             SPrintf(LocalBuffer,"%s %s",Date,Time);
  330.  
  331.         SetComment(Name,LocalBuffer);
  332.     }
  333. }
  334.  
  335.     /* GetSeconds(STRPTR String):
  336.      *
  337.      *    Tries to turn a string of the format hh:mm:ss into
  338.      *    an integer number.
  339.      */
  340.  
  341. STATIC LONG __regargs
  342. GetSeconds(STRPTR String)
  343. {
  344.     UBYTE    Buffer[20];
  345.     LONG    Seconds = 0;
  346.  
  347.     memset(Buffer,0,20);
  348.  
  349.     strcpy(Buffer,String);
  350.  
  351.     Seconds += Atol(&Buffer[6]);
  352.  
  353.     Buffer[5] = 0;
  354.  
  355.     Seconds += Atol(&Buffer[3]) * 60;
  356.  
  357.     Buffer[2] = 0;
  358.  
  359.     Seconds += Atol(&Buffer[0]) * 3600;
  360.  
  361.     return(Seconds);
  362. }
  363.  
  364.     /* TruncateName(STRPTR FileName):
  365.      *
  366.      *    Truncates a file name to a maximum of 48 characters.
  367.      */
  368.  
  369. STATIC STRPTR __regargs
  370. TruncateName(STRPTR FileName)
  371. {
  372.     WORD Len = strlen(FileName);
  373.  
  374.     if(Len > 48)
  375.     {
  376.         WORD i;
  377.  
  378.         for(i = Len - 48 ; i < Len ; i++)
  379.         {
  380.             if(i >= Len - 44 && FileName[i] == '/')
  381.             {
  382.                 STATIC UBYTE __far NameBuffer[MAX_FILENAME_LENGTH];
  383.  
  384.                 strcpy(NameBuffer,".../");
  385.  
  386.                 strcat(NameBuffer,&FileName[i + 1]);
  387.  
  388.                 return(NameBuffer);
  389.             }
  390.         }
  391.     }
  392.  
  393.     return(FileName);
  394. }
  395.  
  396.     /* CalculateBlocks(LONG Size,LONG BlockSize):
  397.      *
  398.      *    Calculate the number of blocks a file will
  399.      *    occupy if saved to a disk.
  400.      */
  401.  
  402. STATIC LONG __regargs
  403. CalculateBlocks(LONG Size,LONG BlockSize)
  404. {
  405.     LONG    Blocks        = 1;        /* One for the file header. */
  406.     BYTE    HasExtension    = FALSE,    /* No extension block yet. */
  407.         Extension    = 0;        /* How many block pointers yet. */
  408.  
  409.         /* Round to next block. */
  410.  
  411.     Size = ((Size + BlockSize - 1) / BlockSize) * BlockSize;
  412.  
  413.     while(Size)
  414.     {
  415.             /* Add another block. */
  416.  
  417.         Blocks++;
  418.  
  419.             /* Subtract another block. */
  420.  
  421.         Size -= BlockSize;
  422.  
  423.             /* Add another block pointer, if 72 have been
  424.              * added, add another extension block.
  425.              */
  426.  
  427.         if((Extension++) == 72)
  428.         {
  429.                 /* If no extension block has been generated
  430.                  * yet, we were running on the block pointers
  431.                  * of the file header itself.
  432.                  */
  433.  
  434.             if(!HasExtension)
  435.                 HasExtension = TRUE;
  436.             else
  437.                 Blocks++;
  438.  
  439.                 /* Reset extension block counter. */
  440.  
  441.             Extension = 0;
  442.         }
  443.     }
  444.  
  445.     return(Blocks);
  446. }
  447.  
  448.     /* GetOptionMode(struct xpr_option *Option):
  449.      *
  450.      *    Turn text into a boolean value.
  451.      */
  452.  
  453. STATIC BYTE __regargs
  454. GetOptionMode(struct xpr_option *Option)
  455. {
  456.     if(Option)
  457.     {
  458.         STATIC STRPTR TrueOptions[] =
  459.         {
  460.             "ON",
  461.             "TRUE",
  462.             "T",
  463.             "YES",
  464.             "Y",
  465.             NULL
  466.         };
  467.  
  468.         register WORD i;
  469.  
  470.         for(i = 0 ; TrueOptions[i] ; i++)
  471.         {
  472.             if(!Stricmp(Option -> xpro_value,TrueOptions[i]))
  473.                 return(TRUE);
  474.         }
  475.     }
  476.  
  477.     return(FALSE);
  478. }
  479.  
  480.     /* SerialErrorReport(struct IOExtSer *Request):
  481.      *
  482.      *    Report a certain I/O error cause.
  483.      */
  484.  
  485. STATIC BYTE __regargs
  486. SerialErrorReport(struct IOExtSer *Request)
  487. {
  488.     STRPTR    ErrorMessage;
  489.     BYTE    IsFatal;
  490.  
  491.     switch(Request -> IOSer . io_Error)
  492.     {
  493.         case SerErr_LineErr:
  494.  
  495.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_HARDWARE_DATA_OVERRUN_TXT);
  496.  
  497.             IsFatal = FALSE;
  498.  
  499.             break;
  500.  
  501.         case SerErr_ParityErr:
  502.  
  503.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_PARITY_ERROR_TXT);
  504.  
  505.             IsFatal = TRUE;
  506.  
  507.             break;
  508.  
  509.         case SerErr_TimerErr:
  510.  
  511.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_TIMER_ERROR_TXT);
  512.  
  513.             IsFatal = FALSE;
  514.  
  515.             break;
  516.  
  517.         case SerErr_BufOverflow:
  518.  
  519.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_READ_BUFFER_OVERFLOWED_TXT);
  520.  
  521.             IsFatal = FALSE;
  522.  
  523.             break;
  524.  
  525.         case SerErr_NoDSR:
  526.  
  527.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_NO_DSR_TXT);
  528.  
  529.             IsFatal = TRUE;
  530.  
  531.             break;
  532.  
  533.         case SerErr_DetectedBreak:
  534.  
  535.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_BREAK_DETECTED_TXT);
  536.  
  537.             IsFatal = TRUE;
  538.  
  539.             break;
  540.  
  541.         default:
  542.  
  543.             ErrorMessage = LocaleString(MSG_TERMXPR_ERROR_UNKNOWN_CAUSE_TXT);
  544.  
  545.             IsFatal = FALSE;
  546.  
  547.             break;
  548.     }
  549.  
  550.     AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_ERROR_TEMPLATE_TXT),Request -> IOSer . io_Error,ErrorMessage);
  551.  
  552.     if(IsFatal)
  553.     {
  554.         TransferError = TRUE;
  555.  
  556.         return(TRUE);
  557.     }
  558.     else
  559.         return(FALSE);
  560. }
  561.  
  562.     /* xpr_fopen(STRPTR FileName,STRPTR AccessMode):
  563.      *
  564.      *    Open a file for random access.
  565.      */
  566.  
  567. LONG __saveds __asm
  568. xpr_fopen(register __a0 STRPTR FileName,register __a1 STRPTR AccessMode)
  569. {
  570.     UBYTE         RealName[MAX_FILENAME_LENGTH];
  571.     struct Buffer    *File;
  572.  
  573. /*    kprintf("xpr_fopen(\"%s\",\"%s\")\n",FileName,AccessMode);*/
  574.  
  575.     Alerted = CarrierMessage = FALSE;
  576.  
  577.         /* Reset transfer counters. */
  578.  
  579.     ByteVal = ByteMax = TimeVal = TimeMax = LastTimeDif = 0;
  580.  
  581.     LastPercent = -1;
  582.  
  583.         /* Reset CPS statistics. */
  584.  
  585.     CPS_Minimum    = (ULONG)~0;
  586.     CPS_Maximum    = 0;
  587.     CPS_Average    = 0;
  588.     CPS_Current    = 0;
  589.     CPS_Count    = 0;
  590.     CPS_Last    = 0;
  591.  
  592.         /* No window available for output? */
  593.  
  594.     if(!TransferWindow)
  595.         OpenTransferWindow();
  596.  
  597.     if(OriginalName[0])
  598.     {
  599.         if(!Stricmp(ShrunkenName,FileName))
  600.             FileName = OriginalName;
  601.     }
  602.  
  603.         /* Determine the file name. */
  604.  
  605.     FileName = NewFileName(FileName,RealName);
  606.  
  607.         /* Determine file transfer mode... */
  608.  
  609.     if(File = BufferOpen(FileName,AccessMode))
  610.     {
  611.         switch(AccessMode[0])
  612.         {
  613.             case 'r':
  614.  
  615.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_SEND_FILE_TXT),FileName);
  616.                 break;
  617.  
  618.             case 'w':
  619.  
  620.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_RECEIVE_FILE_TXT),FileName);
  621.                 break;
  622.  
  623.             case 'a':
  624.  
  625.                 LogAction(LocaleString(MSG_TERMXPR_LOGMSG_UPDATE_FILE_TXT),FileName);
  626.                 break;
  627.         }
  628.  
  629.         CurrentFile = File;
  630.     }
  631.  
  632.     DidTransfer = TRUE;
  633.  
  634.     return((LONG)File);
  635. }
  636.  
  637.     /* xpr_fclose(struct Buffer *File):
  638.      *
  639.      *    Close a file opened by xpr_fopen.
  640.      */
  641.  
  642. LONG __saveds __asm
  643. xpr_fclose(register __a0 struct Buffer *File)
  644. {
  645.     UBYTE            RealName[MAX_FILENAME_LENGTH];
  646.     struct DateStamp    OpenDate;
  647.     BYTE            WriteAccess,
  648.                 Used;
  649.  
  650. /*    kprintf("xpr_fclose(0x%08lx)\n",File);*/
  651.  
  652.         /* Save some information. */
  653.  
  654.     OpenDate    = File -> OpenDate;
  655.     WriteAccess    = File -> WriteAccess;
  656.     Used        = File -> Used;
  657.  
  658.         /* Get the name of the file. */
  659.  
  660.     if(!NameFromFH(File -> FileHandle,RealName,MAX_FILENAME_LENGTH))
  661.         RealName[0] = 0;
  662.  
  663.         /* Close the file and see what it brings... */
  664.  
  665.     if(BufferClose(File) && RealName[0])
  666.     {
  667.             /* Did any access take place at all?
  668.              * xprzmodem.library for example just
  669.              * opens and closes a file in order to
  670.              * see if it exists.
  671.              */
  672.  
  673.         if(!Used)
  674.             LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  675.         else
  676.         {
  677.                 /* Did we receive or send a file? */
  678.  
  679.             if(WriteAccess)
  680.             {
  681.                 LONG Size;
  682.  
  683.                     /* Did the file remain empty? */
  684.  
  685.                 if(!(Size = GetFileSize(RealName)))
  686.                 {
  687.                     AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_FILE_REMOVED_TXT),FilePart(RealName));
  688.  
  689.                         /* Delete empty file. */
  690.  
  691.                     if(DeleteFile(RealName))
  692.                         LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_REMOVED_TXT),RealName);
  693.                     else
  694.                         LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  695.                 }
  696.                 else
  697.                 {
  698.                     struct Node *SomeNode;
  699.  
  700.                     if(ByteMax)
  701.                     {
  702.                         if(Size >= ByteMax)
  703.                             AddTransferInfo(FALSE,LocaleString(MSG_TERMXPR_FILE_RECEIVED_TXT),FilePart(RealName));
  704.                         else
  705.                             AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_INCOMPLETE_FILE_RECEIVED_TXT),FilePart(RealName));
  706.                     }
  707.  
  708.                         /* Try to identify the file type. */
  709.  
  710.                     switch(Config -> MiscConfig -> IdentifyFiles)
  711.                     {
  712.                         case IDENTIFY_IGNORE:
  713.  
  714.                             if(Config -> MiscConfig -> CreateIcons)
  715.                                 Identify(RealName,FALSE);
  716.  
  717.                             break;
  718.  
  719.                         case IDENTIFY_FILETYPE:
  720.  
  721.                             Identify(RealName,TRUE);
  722.                             break;
  723.  
  724.                         case IDENTIFY_SOURCE:
  725.  
  726.                             IdentifySource(RealName,CurrentBBSName,&OpenDate);
  727.  
  728.                             if(Config -> MiscConfig -> CreateIcons)
  729.                                 Identify(RealName,FALSE);
  730.  
  731.                             break;
  732.                     }
  733.  
  734.                     if(CPS_Minimum == (ULONG)~0)
  735.                         CPS_Minimum = 0;
  736.  
  737.                     if(CPS_Count == 0)
  738.                     {
  739.                         CPS_Average    = 0;
  740.                         CPS_Count    = 1;
  741.                     }
  742.  
  743.                     LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_BYTES_TXT),RealName,Size,CPS_Minimum,CPS_Average / CPS_Count,CPS_Maximum);
  744.  
  745.                     if(SomeNode = CreateGenericListNode(0,RealName))
  746.                         AddGenericListNode(GenericListTable[GLIST_DOWNLOAD],SomeNode,ADD_GLIST_BOTTOM);
  747.                 }
  748.             }
  749.             else
  750.             {
  751.                     /* Set the archived bit on files we uploaded? */
  752.  
  753.                 if(Config -> MiscConfig -> SetArchivedBit)
  754.                 {
  755.                     struct FileInfoBlock *FileInfo;
  756.  
  757.                     if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  758.                     {
  759.                         BPTR FileLock;
  760.  
  761.                             /* Get a lock on it. */
  762.  
  763.                         if(FileLock = Lock(RealName,ACCESS_READ))
  764.                         {
  765.                                 /* Examine the file. */
  766.  
  767.                             if(Examine(FileLock,FileInfo))
  768.                             {
  769.                                     /* Remove the lock. */
  770.  
  771.                                 UnLock(FileLock);
  772.  
  773.                                     /* Set the `archived' bit. */
  774.  
  775.                                 SetProtection(RealName,FileInfo -> fib_Protection | FIBF_ARCHIVE);
  776.                             }
  777.                             else
  778.                                 UnLock(FileLock);
  779.                         }
  780.  
  781.                         FreeDosObject(DOS_FIB,FileInfo);
  782.                     }
  783.                 }
  784.  
  785.                 AddTransferInfo(FALSE,LocaleString(MSG_TERMXPR_FILE_SENT_TXT),FilePart(RealName));
  786.  
  787.                 LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  788.  
  789.                 RemoveUploadListItem(RealName);
  790.             }
  791.         }
  792.     }
  793.  
  794.     CurrentFile = NULL;
  795.  
  796.     return(1);
  797. }
  798.  
  799.     /* xpr_fread(APTR Buffer,LONG Size,LONG Count,struct Buffer *File):
  800.      *
  801.      *    Read a few bytes from a file.
  802.      */
  803.  
  804. LONG __saveds __asm
  805. xpr_fread(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 LONG Count,register __a1 struct Buffer *File)
  806. {
  807. /*    kprintf("xpr_fread(0x%08lx,%ld,%ld,0x%08lx)\n",Buffer,Size,Count,File);*/
  808.  
  809.     return(BufferRead(File,Buffer,Size * Count) / Size);
  810. }
  811.  
  812.     /* xpr_fwrite(APTR Buffer,LONG Size,LONG Count,struct Buffer *File):
  813.      *
  814.      *    Write a few bytes to a file.
  815.      */
  816.  
  817. LONG __saveds __asm
  818. xpr_fwrite(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 LONG Count,register __a1 struct Buffer *File)
  819. {
  820. /*    kprintf("xpr_fwrite(0x%08lx,%ld,%ld,0x%08lx)\n",Buffer,Size,Count,File);*/
  821.  
  822.     return(BufferWrite(File,Buffer,Size * Count) / Size);
  823. }
  824.  
  825.     /* xpr_fseek(struct Buffer *File,LONG Offset,LONG Origin):
  826.      *
  827.      *    Move the read/write pointer in a file.
  828.      */
  829.  
  830. LONG __saveds __asm
  831. xpr_fseek(register __a0 struct Buffer *File,register __d0 LONG Offset,register __d1 LONG Origin)
  832. {
  833. /*    kprintf("xpr_fseek(0x%08lx,%ld,%ld)\n",File,Offset,Origin);*/
  834.  
  835.     return(BufferSeek(File,Offset,Origin) ? 0 : -1);
  836. }
  837.  
  838.     /* xpr_sread(APTR Buffer,LONG Size,LONG Timeout):
  839.      *
  840.      *    Read a few bytes from the serial port (including
  841.      *    timeouts).
  842.      */
  843.  
  844. LONG __saveds __asm
  845. xpr_sread(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 ULONG Timeout)
  846. {
  847. /*    kprintf("xpr_sread(0x%08lx,%ld,%ld)\n",Buffer,Size,Timeout);*/
  848.  
  849.         /* No window available for output? */
  850.  
  851.     if(!TransferWindow)
  852.     {
  853.         if(!OpenTransferWindow())
  854.             return(-1);
  855.     }
  856.  
  857.         /* Are both IORequests available? */
  858.  
  859.     if(WriteRequest && ReadRequest)
  860.     {
  861.             /* Valid size parameter? */
  862.  
  863.         if(Size > 0)
  864.         {
  865.             ULONG    Waiting;
  866.             UWORD    Status;
  867.  
  868.             GetSerialInfo(&Waiting,&Status);
  869.  
  870.                 /* Return error if carrier is lost. */
  871.  
  872.             if(Config -> SerialConfig -> CheckCarrier)
  873.             {
  874.                 if(Status & CIAF_COMCD)
  875.                 {
  876.                     if(!CarrierMessage)
  877.                     {
  878.                         CarrierMessage = TRUE;
  879.  
  880.                         AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  881.                     }
  882.  
  883.                     ObtainSemaphore(&OnlineSemaphore);
  884.  
  885.                     WasOnline    = Online;
  886.                     Online        = FALSE;
  887.  
  888.                     ReleaseSemaphore(&OnlineSemaphore);
  889.  
  890.                     TransferError = TRUE;
  891.  
  892.                     return(-1);
  893.                 }
  894.             }
  895.  
  896.             /* ALWAYS */
  897.             {
  898.                 if(Waiting)
  899.                 {
  900.                         /* No timeout specified? Read as many
  901.                          * bytes as available.
  902.                          */
  903.  
  904.                     if(!Timeout)
  905.                     {
  906.                         if(Waiting > Size)
  907.                             Waiting = Size;
  908.  
  909.                         if(DoSerialRead(Buffer,Waiting))
  910.                         {
  911.                             if(SerialErrorReport(ReadRequest))
  912.                                 return(-1);
  913.                             else
  914.                                 Waiting = ReadRequest -> IOSer . io_Actual;
  915.                         }
  916.  
  917.                         BytesIn += Waiting;
  918.  
  919.                         return((LONG)Waiting);
  920.                     }
  921.  
  922.                         /* Enough data pending to be read? */
  923.  
  924.                     if(Waiting >= Size)
  925.                     {
  926.                         if(DoSerialRead(Buffer,Size))
  927.                         {
  928.                             if(SerialErrorReport(ReadRequest))
  929.                                 return(-1);
  930.                             else
  931.                                 Size = ReadRequest -> IOSer . io_Actual;
  932.                         }
  933.  
  934.                         BytesIn += Size;
  935.  
  936.                         return(Size);
  937.                     }
  938.                 }
  939.                 else
  940.                 {
  941.                         /* No timeout & no bytes available:
  942.                          * return immediately.
  943.                          */
  944.  
  945.                     if(!Timeout)
  946.                         return(0);
  947.                 }
  948.             }
  949.  
  950.             /* ALWAYS */
  951.             {
  952.                 register ULONG    SignalSet,
  953.                         SerialMask = PORTMASK(ReadPort),
  954.                         WindowMask = PORTMASK(TransferWindow -> UserPort);
  955.  
  956.                     /* Set up the timer. */
  957.  
  958.                 TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  959.                 TimeRequest -> tr_time . tv_secs    = Timeout / MILLION;
  960.                 TimeRequest -> tr_time . tv_micro    = Timeout % MILLION;
  961.  
  962.                     /* Prevent early termination. */
  963.  
  964.                 ClrSignal(SerialMask | SIG_TIMER);
  965.  
  966.                     /* Start IO... */
  967.  
  968.                 SendIO(TimeRequest);
  969.  
  970.                     /* Set up the read request. */
  971.  
  972.                 StartSerialRead(Buffer,Size);
  973.  
  974.                 FOREVER
  975.                 {
  976.                     SignalSet = Wait(SerialMask | SIG_TIMER | WindowMask);
  977.  
  978.                         /* Abort file transfer? */
  979.  
  980.                     if(SignalSet & WindowMask)
  981.                     {
  982.                         if(CheckAbort(FALSE) == -1)
  983.                         {
  984.                             StopSerialRead();
  985.  
  986.                             if(!CheckIO(TimeRequest))
  987.                                 AbortIO(TimeRequest);
  988.  
  989.                             WaitIO(TimeRequest);
  990.  
  991.                             SendAbort = TRUE;
  992.  
  993.                             return(-1);
  994.                         }
  995.                     }
  996.  
  997.                         /* Receive buffer filled? */
  998.  
  999.                     if(SignalSet & SerialMask)
  1000.                     {
  1001.                             /* Abort the timer request. */
  1002.  
  1003.                         if(!CheckIO(TimeRequest))
  1004.                             AbortIO(TimeRequest);
  1005.  
  1006.                         WaitIO(TimeRequest);
  1007.  
  1008.                             /* Did the request terminate gracefully? */
  1009.  
  1010.                         if(WaitSerialRead())
  1011.                         {
  1012.                             if(SerialErrorReport(ReadRequest))
  1013.                                 return(-1);
  1014.                             else
  1015.                                 Size = ReadRequest -> IOSer . io_Actual;
  1016.                         }
  1017.  
  1018.                         BytesIn += Size;
  1019.  
  1020.                         return(Size);
  1021.                     }
  1022.  
  1023.                         /* Hit by timeout? */
  1024.  
  1025.                     if(SignalSet & SIG_TIMER)
  1026.                     {
  1027.                             /* Abort the read request. */
  1028.  
  1029.                         StopSerialRead();
  1030.  
  1031.                             /* Remove the timer request. */
  1032.  
  1033.                         WaitIO(TimeRequest);
  1034.  
  1035.                             /* Did the driver receive any
  1036.                              * data?
  1037.                              */
  1038.  
  1039.                         if(ReadRequest -> IOSer . io_Actual)
  1040.                         {
  1041.                             BytesIn += ReadRequest -> IOSer . io_Actual;
  1042.  
  1043.                             return((LONG)ReadRequest -> IOSer . io_Actual);
  1044.                         }
  1045.                         else
  1046.                         {
  1047.                                 /* Take a second look and query the number of
  1048.                                  * bytes ready to be received, there may
  1049.                                  * still be some bytes in the buffer.
  1050.                                  * Note: this depends on the way the
  1051.                                  * driver handles read abort.
  1052.                                  */
  1053.  
  1054.                             Waiting = GetSerialWaiting();
  1055.  
  1056.                                 /* Don't read too much. */
  1057.  
  1058.                             if(Size > Waiting)
  1059.                                 Size = Waiting;
  1060.  
  1061.                                 /* Are there any bytes to be transferred? */
  1062.  
  1063.                             if(Size)
  1064.                             {
  1065.                                     /* Read the data. */
  1066.  
  1067.                                 if(DoSerialRead(Buffer,Size))
  1068.                                 {
  1069.                                     if(SerialErrorReport(ReadRequest))
  1070.                                         return(-1);
  1071.                                     else
  1072.                                         Size = ReadRequest -> IOSer . io_Actual;
  1073.                                 }
  1074.  
  1075.                                 BytesIn += Size;
  1076.                             }
  1077.  
  1078.                             return(Size);
  1079.                         }
  1080.                     }
  1081.                 }
  1082.             }
  1083.         }
  1084.         else
  1085.             return(0);
  1086.     }
  1087.     else
  1088.         return(-1);
  1089. }
  1090.  
  1091.     /* xpr_swrite(APTR Buffer,LONG Size):
  1092.      *
  1093.      *    Write a few bytes to the serial port.
  1094.      */
  1095.  
  1096. LONG __saveds __asm
  1097. xpr_swrite(register __a0 APTR Buffer,register __d0 LONG Size)
  1098. {
  1099. /*    kprintf("xpr_swrite(0x%08lx,%ld)\n",Buffer,Size);*/
  1100.  
  1101.     if(WriteRequest)
  1102.     {
  1103.             /* Return error if carrier is lost. */
  1104.  
  1105.         if(Config -> SerialConfig -> CheckCarrier)
  1106.         {
  1107.                 /* Is the carrier signal still present? */
  1108.  
  1109.             if(GetSerialStatus() & CIAF_COMCD)
  1110.             {
  1111.                 if(!CarrierMessage)
  1112.                 {
  1113.                     CarrierMessage = TRUE;
  1114.  
  1115.                     AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  1116.                 }
  1117.  
  1118.                 ObtainSemaphore(&OnlineSemaphore);
  1119.  
  1120.                 WasOnline    = Online;
  1121.                 Online        = FALSE;
  1122.  
  1123.                 ReleaseSemaphore(&OnlineSemaphore);
  1124.  
  1125.                 TransferError = TRUE;
  1126.  
  1127.                 return(-1);
  1128.             }
  1129.         }
  1130.  
  1131.             /* Send the data. */
  1132.  
  1133.         if(DoSerialWrite(Buffer,Size))
  1134.         {
  1135.             if(SerialErrorReport(WriteRequest))
  1136.                 return(-1);
  1137.         }
  1138.         else
  1139.             BytesOut += Size;
  1140.  
  1141.         return(0);
  1142.     }
  1143.     else
  1144.         return(-1);
  1145. }
  1146.  
  1147.     /* xpr_sflush():
  1148.      *
  1149.      *    Release the contents of all serial buffers.
  1150.      */
  1151.  
  1152. LONG __saveds __asm
  1153. xpr_sflush()
  1154. {
  1155. /*    kprintf("xpr_sflush()\n");*/
  1156.  
  1157.     return((LONG)DoSerialCmd(CMD_CLEAR));
  1158. }
  1159.  
  1160.     /* xpr_update(struct XPR_UPDATE *UpdateInfo):
  1161.      *
  1162.      *    Update the information displayed in the transfer window.
  1163.      */
  1164.  
  1165. LONG __saveds __asm
  1166. xpr_update(register __a0 struct XPR_UPDATE *UpdateInfo)
  1167. {
  1168. /*    kprintf("xpr_update(0x%08lx)\n",UpdateInfo);*/
  1169.  
  1170.         /* No window available for output? */
  1171.  
  1172.     if(!TransferWindow)
  1173.     {
  1174.         if(!OpenTransferWindow())
  1175.             return(0);
  1176.     }
  1177.  
  1178.     if(UpdateInfo)
  1179.     {
  1180.         BYTE    NewByte = FALSE,
  1181.             NewTime = FALSE;
  1182.  
  1183.         if(TransferWindow -> Flags & WFLG_ZOOMED)
  1184.         {
  1185.             BOOLEAN Refresh;
  1186.  
  1187.             if(!TransferZoomed)
  1188.             {
  1189.                 ULONG Micros;
  1190.  
  1191.                 CurrentTime(&LastSeconds,&Micros);
  1192.  
  1193.                 Refresh = TRUE;
  1194.  
  1195.                 TransferZoomed = TRUE;
  1196.             }
  1197.             else
  1198.             {
  1199.                 ULONG Seconds,Micros;
  1200.  
  1201.                 CurrentTime(&Seconds,&Micros);
  1202.  
  1203.                 if(Seconds > LastSeconds)
  1204.                 {
  1205.                     LastSeconds = Seconds;
  1206.  
  1207.                     Refresh = TRUE;
  1208.                 }
  1209.             }
  1210.  
  1211.             if(Refresh)
  1212.             {
  1213.                 if(LastPercent > 0)
  1214.                     SPrintf(TransferTitleBuffer,"%s [%s %ld%%]",TransferWindowTitle,TruncateName(RealName),LastPercent);
  1215.                 else
  1216.                     SPrintf(TransferTitleBuffer,"%s [%s]",TransferWindowTitle,TruncateName(RealName));
  1217.  
  1218.                 SetWindowTitles(TransferWindow,TransferTitleBuffer,(STRPTR)-1);
  1219.             }
  1220.         }
  1221.         else
  1222.         {
  1223.             if(TransferZoomed)
  1224.             {
  1225.                 SetWindowTitles(TransferWindow,TransferWindowTitle,(STRPTR)-1);
  1226.  
  1227.                 TransferZoomed = FALSE;
  1228.             }
  1229.         }
  1230.  
  1231.         if((UpdateInfo -> xpru_updatemask & XPRU_PROTOCOL) && UpdateInfo -> xpru_protocol)
  1232.             LT_SetAttributes(TransferHandle,GAD_TRANSFER_PROTOCOL,GTTX_Text,UpdateInfo -> xpru_protocol,TAG_DONE);
  1233.  
  1234.         if((UpdateInfo -> xpru_updatemask & XPRU_MSG) && UpdateInfo -> xpru_msg)
  1235.             AddTransferInfo(FALSE,UpdateInfo -> xpru_msg);
  1236.  
  1237.         if((UpdateInfo -> xpru_updatemask & XPRU_ERRORMSG) && UpdateInfo -> xpru_errormsg)
  1238.             AddTransferInfo(TRUE,UpdateInfo -> xpru_errormsg);
  1239.  
  1240.         if((UpdateInfo -> xpru_updatemask & XPRU_FILENAME) && UpdateInfo -> xpru_filename)
  1241.         {
  1242.             STRPTR FileName = UpdateInfo -> xpru_filename;
  1243.  
  1244.             if(OriginalName[0])
  1245.             {
  1246.                 if(!Stricmp(ShrunkenName,FileName))
  1247.                     FileName = OriginalName;
  1248.             }
  1249.  
  1250.             FileName = NewFileName(FileName,RealName);
  1251.  
  1252.             LT_SetAttributes(TransferHandle,GAD_TRANSFER_FILE,LABX_Index,0,LABX_Text,TruncateName(FileName),TAG_DONE);
  1253.  
  1254.             if(FileTransferInfo)
  1255.             {
  1256.                 if(FileTransferInfo -> CurrentFile)
  1257.                 {
  1258.                     struct FileTransferNode *Node = (struct FileTransferNode *)FileTransferInfo -> CurrentFile -> Node . mln_Succ;
  1259.  
  1260.                     if(Node -> Node . mln_Succ)
  1261.                         LT_SetAttributes(TransferHandle,GAD_TRANSFER_FILE,LABX_Index,1,LABX_Text,TruncateName(Node -> Name),TAG_DONE);
  1262.                     else
  1263.                         LT_SetAttributes(TransferHandle,GAD_TRANSFER_FILE,LABX_Index,1,LABX_Text,LocaleString(MSG_GLOBAL_NONE_TXT),TAG_DONE);
  1264.                 }
  1265.  
  1266.                 PrintBox(GAD_TRANSFER_SIZE,2,ConvNumber,FileTransferInfo -> TotalSize);
  1267.  
  1268.                 if(FileTransferInfo -> TotalFiles)
  1269.                     PrintBox(GAD_TRANSFER_SIZE,4,LocaleString(MSG_TRANSFERPANEL_NUMBER_TO_GO_PERCENT_TXT),FileTransferInfo -> DoneFiles,FileTransferInfo -> TotalFiles,(100 * FileTransferInfo -> DoneFiles) / FileTransferInfo -> TotalFiles);
  1270.                 else
  1271.                     PrintBox(GAD_TRANSFER_SIZE,4,LocaleString(MSG_TRANSFERPANEL_NUMBER_TO_GO_PERCENT_TXT),FileTransferInfo -> DoneFiles,FileTransferInfo -> TotalFiles,0);
  1272.             }
  1273.         }
  1274.  
  1275.         if((UpdateInfo -> xpru_updatemask & XPRU_FILESIZE) && UpdateInfo -> xpru_filesize != -1)
  1276.         {
  1277.             if(CurrentFile)
  1278.             {
  1279.                 if(CurrentFile -> DirLock)
  1280.                     PrintBox(GAD_TRANSFER_SIZE,0,ConvNumber10,UpdateInfo -> xpru_filesize);
  1281.                 else
  1282.                     PrintBox(GAD_TRANSFER_SIZE,0,ConvNumber,UpdateInfo -> xpru_filesize);
  1283.             }
  1284.             else
  1285.                 PrintBox(GAD_TRANSFER_SIZE,0,ConvNumber,UpdateInfo -> xpru_filesize);
  1286.  
  1287.             if(ByteMax = UpdateInfo -> xpru_filesize)
  1288.                 NewByte = TRUE;
  1289.         }
  1290.  
  1291.         if((UpdateInfo -> xpru_updatemask & XPRU_BYTES) && UpdateInfo -> xpru_bytes != -1)
  1292.         {
  1293.             if(CurrentFile)
  1294.             {
  1295.                 if(CurrentFile -> DirLock)
  1296.                     PrintBox(GAD_TRANSFER_SIZE,1,ConvNumber10,ByteVal = UpdateInfo -> xpru_bytes);
  1297.                 else
  1298.                     PrintBox(GAD_TRANSFER_SIZE,1,ConvNumber,ByteVal = UpdateInfo -> xpru_bytes);
  1299.             }
  1300.             else
  1301.                 PrintBox(GAD_TRANSFER_SIZE,1,ConvNumber,ByteVal = UpdateInfo -> xpru_bytes);
  1302.  
  1303.             if(FileTransferInfo)
  1304.             {
  1305.                 ULONG Len = FileTransferInfo -> DoneSize + UpdateInfo -> xpru_bytes;
  1306.  
  1307.                 if(FileTransferInfo -> TotalSize)
  1308.                     PrintBox(GAD_TRANSFER_SIZE,3,LocaleString(MSG_TRANSFERPANEL_NUMBER_PERCENT_TXT),Len,(100 * Len) / FileTransferInfo -> TotalSize);
  1309.                 else
  1310.                     PrintBox(GAD_TRANSFER_SIZE,3,LocaleString(MSG_TRANSFERPANEL_NUMBER_PERCENT_TXT),Len,0);
  1311.             }
  1312.  
  1313.             if(ByteMax)
  1314.                 NewByte = TRUE;
  1315.  
  1316.             if(CurrentFile)
  1317.             {
  1318.                 if(CurrentFile -> DirLock && !Uploading)
  1319.                 {
  1320.                     if(CurrentFile -> InfoData . id_NumBlocks && CurrentFile -> InfoData . id_BytesPerBlock)
  1321.                     {
  1322.                         if(ByteMax)
  1323.                         {
  1324.                             register LONG Space = CurrentFile -> InfoData . id_NumBlocks - CurrentFile -> InfoData . id_NumBlocksUsed;
  1325.  
  1326.                             if(Space >= 0)
  1327.                             {
  1328.                                 register LONG Blocks = CalculateBlocks(ByteMax,CurrentFile -> InfoData . id_BytesPerBlock);
  1329.  
  1330.                                 if(Space < Blocks)
  1331.                                 {
  1332.                                     if(!Alerted)
  1333.                                     {
  1334.                                         Alerted = TRUE;
  1335.  
  1336.                                         Say(LocaleString(MSG_TERMXPR_SAY_FILE_MAY_NOT_FIT_TXT));
  1337.                                     }
  1338.  
  1339.                                     PrintBox(GAD_TRANSFER_FILE,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));
  1340.                                 }
  1341.                                 else
  1342.                                     PrintBox(GAD_TRANSFER_FILE,2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),Space * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks,"");
  1343.                             }
  1344.                             else
  1345.                                 PrintBox(GAD_TRANSFER_FILE,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);
  1346.                         }
  1347.                         else
  1348.                             PrintBox(GAD_TRANSFER_FILE,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);
  1349.                     }
  1350.                 }
  1351.             }
  1352.         }
  1353.  
  1354.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKS) && UpdateInfo -> xpru_blocks != -1)
  1355.             PrintBox(GAD_TRANSFER_SIZE,5,ConvNumber,UpdateInfo -> xpru_blocks);
  1356.  
  1357.         if((UpdateInfo -> xpru_updatemask & XPRU_DATARATE) && UpdateInfo -> xpru_datarate > 0)
  1358.         {
  1359.             register LONG Change;
  1360.  
  1361.             CPS_Current = UpdateInfo -> xpru_datarate;
  1362.  
  1363.             if(CPS_Last)
  1364.             {
  1365.                 if(CPS_Last < UpdateInfo -> xpru_datarate)
  1366.                     Change = (100 * (UpdateInfo -> xpru_datarate - CPS_Last)) / CPS_Last;
  1367.                 else
  1368.                     Change = (100 * (CPS_Last - UpdateInfo -> xpru_datarate)) / CPS_Last;
  1369.             }
  1370.             else
  1371.                 Change = 100;
  1372.  
  1373.             if(Change > 1)
  1374.             {
  1375.                 PrintBox(GAD_TRANSFER_SECONDS,0,ConvNumber,UpdateInfo -> xpru_datarate);
  1376.  
  1377.                 CPS_Last = UpdateInfo -> xpru_datarate;
  1378.             }
  1379.  
  1380.             if(UpdateInfo -> xpru_datarate < CPS_Minimum)
  1381.                 CPS_Minimum = UpdateInfo -> xpru_datarate;
  1382.  
  1383.             if(UpdateInfo -> xpru_datarate > CPS_Maximum)
  1384.                 CPS_Maximum = UpdateInfo -> xpru_datarate;
  1385.  
  1386.             if((ULONG)(CPS_Average + UpdateInfo -> xpru_datarate) >= CPS_Average)
  1387.             {
  1388.                 CPS_Average += UpdateInfo -> xpru_datarate;
  1389.  
  1390.                 CPS_Count++;
  1391.             }
  1392.         }
  1393.  
  1394.         if((UpdateInfo -> xpru_updatemask & XPRU_CHARDELAY) && UpdateInfo -> xpru_chardelay != -1)
  1395.             PrintBox(GAD_TRANSFER_SECONDS,1,ConvNumber,UpdateInfo -> xpru_chardelay);
  1396.  
  1397.         if((UpdateInfo -> xpru_updatemask & XPRU_PACKETDELAY) && UpdateInfo -> xpru_packetdelay != -1)
  1398.             PrintBox(GAD_TRANSFER_SECONDS,2,ConvNumber,UpdateInfo -> xpru_packetdelay);
  1399.  
  1400.         if((UpdateInfo -> xpru_updatemask & XPRU_PACKETTYPE) && UpdateInfo -> xpru_packettype != -1)
  1401.         {
  1402.             if(UpdateInfo -> xpru_packettype > 32 && UpdateInfo -> xpru_packettype < 256)
  1403.             {
  1404.                 if(IsPrintable[UpdateInfo -> xpru_packettype])
  1405.                     PrintBox(GAD_TRANSFER_SECONDS,3,"`%lc'",UpdateInfo -> xpru_packettype);
  1406.                 else
  1407.                     PrintBox(GAD_TRANSFER_SECONDS,3,ConvNumber,UpdateInfo -> xpru_packettype);
  1408.             }
  1409.             else
  1410.                 PrintBox(GAD_TRANSFER_SECONDS,3,ConvNumber,UpdateInfo -> xpru_packettype);
  1411.         }
  1412.  
  1413.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKCHECK) && UpdateInfo -> xpru_blockcheck)
  1414.             PrintBox(GAD_TRANSFER_SECONDS,4,UpdateInfo -> xpru_blockcheck);
  1415.  
  1416.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKSIZE) && UpdateInfo -> xpru_blocksize != -1)
  1417.             PrintBox(GAD_TRANSFER_SECONDS,5,ConvNumber,UpdateInfo -> xpru_blocksize);
  1418.  
  1419.  
  1420.         if((UpdateInfo -> xpru_updatemask & XPRU_EXPECTTIME) && UpdateInfo -> xpru_expecttime)
  1421.         {
  1422.             PrintBox(GAD_TRANSFER_TOTALTIME,0,UpdateInfo -> xpru_expecttime);
  1423.  
  1424.             if(TimeMax = GetSeconds((STRPTR)UpdateInfo -> xpru_expecttime))
  1425.                 NewTime = TRUE;
  1426.         }
  1427.  
  1428.         if((UpdateInfo -> xpru_updatemask & XPRU_ELAPSEDTIME) && UpdateInfo -> xpru_elapsedtime)
  1429.         {
  1430.             PrintBox(GAD_TRANSFER_TOTALTIME,1,UpdateInfo -> xpru_elapsedtime);
  1431.  
  1432.             TimeVal = GetSeconds((STRPTR)UpdateInfo -> xpru_elapsedtime);
  1433.  
  1434.             if(TimeMax)
  1435.                 NewTime = TRUE;
  1436.         }
  1437.  
  1438.         if((UpdateInfo -> xpru_updatemask & XPRU_ERRORS) && UpdateInfo -> xpru_errors != -1)
  1439.             PrintBox(GAD_TRANSFER_ERRORS,0,ConvNumber,UpdateInfo -> xpru_errors);
  1440.  
  1441.         if((UpdateInfo -> xpru_updatemask & XPRU_TIMEOUTS) && UpdateInfo -> xpru_timeouts != -1)
  1442.             PrintBox(GAD_TRANSFER_ERRORS,1,ConvNumber,UpdateInfo -> xpru_timeouts);
  1443.  
  1444.         if(NewByte)
  1445.         {
  1446.             LONG Percent;
  1447.  
  1448.             if(ByteMax)
  1449.                 Percent = (100 * ByteVal) / ByteMax;
  1450.             else
  1451.                 Percent = 0;
  1452.  
  1453.             if(Percent != LastPercent)
  1454.             {
  1455.                 UBYTE LocalBuffer[10];
  1456.  
  1457.                 SPrintf(LocalBuffer,"%ld%%",Percent);
  1458.  
  1459.                 LastPercent = Percent;
  1460.  
  1461.                 LT_SetAttributes(TransferHandle,GAD_TRANSFER_PERCENT,
  1462.                     LAGA_Percent,    Percent,
  1463.                     LAGA_InfoText,    LocalBuffer,
  1464.                 TAG_DONE);
  1465.             }
  1466.         }
  1467.  
  1468.         if(NewTime)
  1469.         {
  1470.             register LONG TimeDif,Change;
  1471.  
  1472.             if(TimeVal > TimeMax)
  1473.                 TimeDif = 0;
  1474.             else
  1475.                 TimeDif = TimeMax - TimeVal;
  1476.  
  1477.             if(LastTimeDif)
  1478.             {
  1479.                 if(LastTimeDif < TimeDif)
  1480.                     Change = (100 * (TimeDif - LastTimeDif)) / LastTimeDif;
  1481.                 else
  1482.                     Change = (100 * (LastTimeDif - TimeDif)) / LastTimeDif;
  1483.             }
  1484.             else
  1485.                 Change = 100;
  1486.  
  1487.                 /* Don't update the display unless the change
  1488.                  * exceeds 2% of the previous value.
  1489.                  */
  1490.  
  1491.             if(Change > 2)
  1492.             {
  1493.                 UBYTE    LocalBuffer[10];
  1494.                 LONG    Percent;
  1495.  
  1496.                 LastTimeDif = TimeDif;
  1497.  
  1498.                 if(TimeMax)
  1499.                     Percent = (100 * TimeDif) / TimeMax;
  1500.                 else
  1501.                     Percent = 0;
  1502.  
  1503.                 SPrintf(LocalBuffer,"%2ld:%02ld:%02ld",TimeDif / 3600,(TimeDif / 60) % 60,TimeDif % 60);
  1504.  
  1505.                 LT_SetAttributes(TransferHandle,GAD_TRANSFER_TIME,
  1506.                     LAGA_Percent,    Percent,
  1507.                     LAGA_InfoText,    LocalBuffer,
  1508.                 TAG_DONE);
  1509.  
  1510.                     /* A rapidly changing transfer time display would
  1511.                      * cause the transfer completion time display to
  1512.                      * change at the same pace. As the completion time
  1513.                      * display calculation is rather costly, a change smaller
  1514.                      * than 5% of the previous value is silently ignored.
  1515.                      */
  1516.  
  1517.                 if(Change > 5)
  1518.                 {
  1519.                     UBYTE            DateTimeBuffer[256];
  1520.                     struct DateStamp    Stamp;
  1521.  
  1522.                         /* Obtain current time. */
  1523.  
  1524.                     DateStamp(&Stamp);
  1525.  
  1526.                         /* Add the time to go. */
  1527.  
  1528.                     Stamp . ds_Tick        += (TimeDif % 60) * TICKS_PER_SECOND;
  1529.                     Stamp . ds_Minute    += TimeDif / 60 + Stamp . ds_Tick / (60 * TICKS_PER_SECOND);
  1530.                     Stamp . ds_Days        += Stamp . ds_Minute / 1440;
  1531.  
  1532.                     Stamp . ds_Tick        %= 60 * TICKS_PER_SECOND;
  1533.                     Stamp . ds_Minute    %= 1440;
  1534.  
  1535.                         /* Conversion succeeded? */
  1536.  
  1537.                     if(FormatStamp(&Stamp,NULL,NULL,DateTimeBuffer,TRUE))
  1538.                         PrintBox(GAD_TRANSFER_FILE,3,DateTimeBuffer);
  1539.                 }
  1540.             }
  1541.         }
  1542.     }
  1543.  
  1544.     if(TransferPerfWindow)
  1545.     {
  1546.         struct RastPort *RPort = TransferPerfWindow -> RPort;
  1547.         LONG Height,Left,Top,Min,Avg,Cur;
  1548.  
  1549.         Left = TransferPerfWindow -> Width - (TransferPerfWindow -> BorderRight + 1);
  1550.         Height = TransferPerfWindow -> Height - (TransferPerfWindow -> BorderTop + TransferPerfWindow -> BorderBottom + 1);
  1551.         Top = TransferPerfWindow -> BorderTop + Height;
  1552.  
  1553.         if(CPS_Maximum && CPS_Maximum != ~0)
  1554.         {
  1555.             Min = (Height * CPS_Minimum) / CPS_Maximum;
  1556.             Cur = (Height * CPS_Current) / CPS_Maximum;
  1557.  
  1558.             if(CPS_Count)
  1559.                 Avg = ((CPS_Average / CPS_Count) * Height) / CPS_Maximum;
  1560.             else
  1561.                 Avg = 0;
  1562.         }
  1563.         else
  1564.             Min = Avg = Cur = 0;
  1565.  
  1566.         if(CPL_Min == -1)
  1567.             CPL_Min = Min;
  1568.  
  1569.         if(CPL_Avg == -1)
  1570.             CPL_Avg = Avg;
  1571.  
  1572.         if(CPL_Cur == -1)
  1573.             CPL_Cur = Cur;
  1574.  
  1575.         ScrollRaster(RPort,1,0,TransferPerfWindow -> BorderLeft,TransferPerfWindow -> BorderTop,TransferPerfWindow -> Width - (TransferPerfWindow -> BorderRight + 1),TransferPerfWindow -> Height - (TransferPerfWindow -> BorderBottom + 1));
  1576.  
  1577.         if(CPL_Cur != -1 && Cur != -1)
  1578.         {
  1579.             SetAPen(RPort,DrawInfo -> dri_Pens[SHADOWPEN]);
  1580.             Move(RPort,Left,Top - CPL_Cur);
  1581.             Draw(RPort,Left,Top - Cur);
  1582.         }
  1583.  
  1584.         if(CPL_Min != -1 && Min != -1)
  1585.         {
  1586.             SetAPen(RPort,DrawInfo -> dri_Pens[HIGHLIGHTTEXTPEN]);
  1587.             Move(RPort,Left,Top - CPL_Min);
  1588.             Draw(RPort,Left,Top - Min);
  1589.         }
  1590.  
  1591.         if(CPL_Avg != -1 && Avg != -1)
  1592.         {
  1593.             SetAPen(RPort,DrawInfo -> dri_Pens[FILLPEN]);
  1594.             Move(RPort,Left,Top - CPL_Avg);
  1595.             Draw(RPort,Left,Top - Avg);
  1596.         }
  1597.  
  1598.         CPL_Min = Min;
  1599.         CPL_Avg = Avg;
  1600.         CPL_Cur = Cur;
  1601.     }
  1602.  
  1603.     return(1);
  1604. }
  1605.  
  1606.     /* xpr_chkabort():
  1607.      *
  1608.      *    Check if the user has aborted the transfer.
  1609.      */
  1610.  
  1611. LONG __saveds __asm
  1612. xpr_chkabort()
  1613. {
  1614.     LONG Result;
  1615.  
  1616. /*    kprintf("xpr_chkabort()\n");*/
  1617.  
  1618.     Result = CheckAbort(Config -> SerialConfig -> CheckCarrier);
  1619.  
  1620.     return(Result);
  1621. }
  1622.  
  1623.     /* xpr_gets(STRPTR Prompt,STRPTR Buffer):
  1624.      *
  1625.      *    Prompt the user for string input.
  1626.      */
  1627.  
  1628. LONG __saveds __asm
  1629. xpr_gets(register __a0 STRPTR Prompt,register __a1 STRPTR Buffer)
  1630. {
  1631.     enum    {    GAD_OK=1,GAD_CANCEL,GAD_STRING };
  1632.  
  1633.     struct LayoutHandle    *Handle;
  1634.     LONG             Success = FALSE;
  1635.     UBYTE             LocalBuffer[256];
  1636.  
  1637. /*    kprintf("xpr_gets(\"%s\",\"%s\")\n",Prompt,Buffer);*/
  1638.  
  1639.     if(strlen(Buffer) > 255)
  1640.     {
  1641.         CopyMem(Buffer,LocalBuffer,255);
  1642.  
  1643.         LocalBuffer[255] = 0;
  1644.     }
  1645.     else
  1646.         strcpy(LocalBuffer,Buffer);
  1647.  
  1648.     if(!Prompt)
  1649.         Prompt = LocaleString(MSG_TERMXPR_INPUT_REQUIRED_TXT);
  1650.  
  1651.     if(Handle = LT_CreateHandleTags(Window -> WScreen,
  1652.         LH_LocaleHook,    &LocaleHook,
  1653.     TAG_DONE))
  1654.     {
  1655.         struct Window *PanelWindow;
  1656.  
  1657.         LT_New(Handle,
  1658.             LA_Type,    VERTICAL_KIND,
  1659.         TAG_DONE);
  1660.         {
  1661.             LT_New(Handle,
  1662.                 LA_Type,    VERTICAL_KIND,
  1663.                 LA_LabelText,    Prompt,
  1664.             TAG_DONE);
  1665.             {
  1666.                 LT_New(Handle,
  1667.                     LA_Type,    STRING_KIND,
  1668.                     LA_STRPTR,    LocalBuffer,
  1669.                     LA_ID,        GAD_STRING,
  1670.                     LA_Chars,    30,
  1671.                 TAG_DONE);
  1672.  
  1673.                 LT_EndGroup(Handle);
  1674.             }
  1675.  
  1676.             LT_New(Handle,
  1677.                 LA_Type,VERTICAL_KIND,
  1678.             TAG_DONE);
  1679.             {
  1680.                 LT_New(Handle,
  1681.                     LA_Type,    XBAR_KIND,
  1682.                     LAXB_FullSize,    TRUE,
  1683.                 TAG_DONE);
  1684.  
  1685.                 LT_EndGroup(Handle);
  1686.             }
  1687.  
  1688.             LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  1689.                 LAGR_SameSize,    TRUE,
  1690.                 LAGR_Spread,    TRUE,
  1691.             TAG_DONE);
  1692.             {
  1693.                 LT_New(Handle,
  1694.                     LA_Type,    BUTTON_KIND,
  1695.                     LA_LabelID,    MSG_TERMXPR_OKAY_GAD,
  1696.                     LA_ID,        GAD_OK,
  1697.                     LABT_ReturnKey,    TRUE,
  1698.                     LABT_ExtraFat,    TRUE,
  1699.                 TAG_DONE);
  1700.  
  1701.                 LT_New(Handle,
  1702.                     LA_Type,    BUTTON_KIND,
  1703.                     LA_LabelID,    MSG_GLOBAL_CANCEL_GAD,
  1704.                     LA_ID,        GAD_CANCEL,
  1705.                     LABT_EscKey,    TRUE,
  1706.                     LABT_ExtraFat,    TRUE,
  1707.                 TAG_DONE);
  1708.  
  1709.                 LT_EndGroup(Handle);
  1710.             }
  1711.         }
  1712.  
  1713.         if(PanelWindow = LT_Layout(Handle,LocaleString(MSG_GLOBAL_ENTER_TEXT_TXT),NULL,0,0,IDCMP_CLOSEWINDOW,0,
  1714.             LAWN_HelpHook,        &GuideHook,
  1715.             LAWN_Parent,        Window,
  1716.             WA_DepthGadget,        TRUE,
  1717.             WA_CloseGadget,        TRUE,
  1718.             WA_DragBar,        TRUE,
  1719.             WA_RMBTrap,        TRUE,
  1720.             WA_Activate,        TRUE,
  1721.         TAG_DONE))
  1722.         {
  1723.             struct IntuiMessage    *Message;
  1724.             BOOLEAN             Done = FALSE;
  1725.             ULONG             MsgClass,
  1726.                          MsgQualifier;
  1727.             UWORD             MsgCode;
  1728.             struct Gadget        *MsgGadget;
  1729.  
  1730.             PushWindow(PanelWindow);
  1731.  
  1732.             LT_ShowWindow(Handle,TRUE);
  1733.  
  1734.             LT_Activate(Handle,GAD_STRING);
  1735.  
  1736.             do
  1737.             {
  1738.                 if(Wait(PORTMASK(PanelWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
  1739.                     break;
  1740.  
  1741.                 while(Message = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort))
  1742.                 {
  1743.                     MsgClass    = Message -> Class;
  1744.                     MsgQualifier    = Message -> Qualifier;
  1745.                     MsgCode        = Message -> Code;
  1746.                     MsgGadget    = (struct Gadget *)Message -> IAddress;
  1747.  
  1748.                     GT_ReplyIMsg(Message);
  1749.  
  1750.                     LT_HandleInput(Handle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
  1751.  
  1752.                     if(MsgClass == IDCMP_CLOSEWINDOW)
  1753.                         Done = TRUE;
  1754.  
  1755.                     if(MsgClass == IDCMP_GADGETUP)
  1756.                     {
  1757.                         switch(MsgGadget -> GadgetID)
  1758.                         {
  1759.                             case GAD_STRING:
  1760.  
  1761.                                 if(MsgCode == '\r')
  1762.                                 {
  1763.                                     if(strcmp(Buffer,LocalBuffer))
  1764.                                         NewOptions = TRUE;
  1765.  
  1766.                                     strcpy(Buffer,LocalBuffer);
  1767.  
  1768.                                     Success = Done = TRUE;
  1769.  
  1770.                                     LT_PressButton(Handle,GAD_OK);
  1771.                                 }
  1772.  
  1773.                                 break;
  1774.  
  1775.                             case GAD_OK:
  1776.  
  1777.                                 if(strcmp(Buffer,LocalBuffer))
  1778.                                     NewOptions = TRUE;
  1779.  
  1780.                                 strcpy(Buffer,LocalBuffer);
  1781.  
  1782.                                 Success = Done = TRUE;
  1783.  
  1784.                                 break;
  1785.  
  1786.                             case GAD_CANCEL:
  1787.  
  1788.                                 Done = TRUE;
  1789.                                 break;
  1790.                         }
  1791.                     }
  1792.                 }
  1793.             }
  1794.             while(!Done);
  1795.  
  1796.             PopWindow();
  1797.         }
  1798.  
  1799.         LT_DeleteHandle(Handle);
  1800.     }
  1801.  
  1802.     return(Success);
  1803. }
  1804.  
  1805.     /* xpr_setserial(LONG Status):
  1806.      *
  1807.      *    Set/read the serial status (parameters).
  1808.      */
  1809.  
  1810. LONG __saveds __asm
  1811. xpr_setserial(register __d0 LONG Status)
  1812. {
  1813. /*    kprintf("xpr_setserial(0x%08lx)\n",Status);*/
  1814.  
  1815.     if(WriteRequest)
  1816.     {
  1817.         STATIC LONG XprBauds[12] =
  1818.         {
  1819.                110,
  1820.                300,
  1821.               1200,
  1822.               2400,
  1823.               4800,
  1824.               9600,
  1825.              19200,
  1826.              31250,
  1827.              38400,
  1828.              57600,
  1829.              76800,
  1830.             115200
  1831.         };
  1832.  
  1833.         LONG Return,i;
  1834.  
  1835.         StopSerialRead();
  1836.         StopSerialWrite();
  1837.  
  1838.         DoSerialCmd(SDCMD_QUERY);
  1839.  
  1840.         Return = WriteRequest -> io_SerFlags & 0xFF;
  1841.  
  1842.         if(WriteRequest -> io_ExtFlags & SEXTF_MSPON)
  1843.             Return |= ST_PARTYMARKON;
  1844.  
  1845.         if(WriteRequest -> io_ExtFlags & SEXTF_MARK)
  1846.             Return |= ST_PARTYMARK;
  1847.  
  1848.         if(WriteRequest -> io_StopBits == 2)
  1849.             Return |= ST_2BITS;
  1850.  
  1851.         if(WriteRequest -> io_ReadLen == 7)
  1852.             Return |= ST_READ7;
  1853.  
  1854.         if(WriteRequest -> io_WriteLen == 7)
  1855.             Return |= ST_WRITE7;
  1856.  
  1857.         for(i = 0 ; i < 12 ; i++)
  1858.         {
  1859.             if(XprBauds[i] >= WriteRequest -> io_Baud)
  1860.             {
  1861.                 Return |= (i << 16);
  1862.  
  1863.                 break;
  1864.             }
  1865.         }
  1866.  
  1867.             /* Update serial parameters, don't change
  1868.              * the baud rate however.
  1869.              */
  1870.  
  1871.         if(Status != -1)
  1872.         {
  1873.             WriteRequest -> io_SerFlags = Status & 0xFF;
  1874.             WriteRequest -> io_ExtFlags = 0;
  1875.  
  1876.             if(Status & ST_PARTYMARKON)
  1877.                 WriteRequest -> io_ExtFlags |= SEXTF_MSPON;
  1878.  
  1879.             if(Status & ST_PARTYMARK)
  1880.                 WriteRequest -> io_ExtFlags |= SEXTF_MARK;
  1881.  
  1882.             if(Status & ST_2BITS)
  1883.                 WriteRequest -> io_StopBits = 2;
  1884.             else
  1885.                 WriteRequest -> io_StopBits = 1;
  1886.  
  1887.             if(Status & ST_READ7)
  1888.                 WriteRequest -> io_ReadLen = 7;
  1889.             else
  1890.                 WriteRequest -> io_ReadLen = 8;
  1891.  
  1892.             if(Status & ST_WRITE7)
  1893.                 WriteRequest -> io_WriteLen = 7;
  1894.             else
  1895.                 WriteRequest -> io_WriteLen = 8;
  1896.  
  1897.             ReadRequest -> io_Baud        = WriteRequest -> io_Baud;
  1898.             ReadRequest -> io_SerFlags    = WriteRequest -> io_SerFlags;
  1899.             ReadRequest -> io_ExtFlags    = WriteRequest -> io_ExtFlags;
  1900.             ReadRequest -> io_StopBits    = WriteRequest -> io_StopBits;
  1901.             ReadRequest -> io_ReadLen    = WriteRequest -> io_ReadLen;
  1902.             ReadRequest -> io_WriteLen    = WriteRequest -> io_WriteLen;
  1903.  
  1904.             WriteRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
  1905.  
  1906.             DoIO(WriteRequest);
  1907.  
  1908.             ReadRequest -> IOSer . io_Command = SDCMD_SETPARAMS;
  1909.  
  1910.             DoIO(ReadRequest);
  1911.  
  1912.             CopyWriteFlags();
  1913.         }
  1914.  
  1915.         return(Return);
  1916.     }
  1917.     else
  1918.         return(-1);
  1919. }
  1920.  
  1921.     /* xpr_ffirst(STRPTR Buffer,STRPTR Pattern):
  1922.      *
  1923.      *    Batch file upload: find the first matching file and return
  1924.      *    its name.
  1925.      */
  1926.  
  1927. LONG __saveds __asm
  1928. xpr_ffirst(register __a0 STRPTR Buffer,register __a1 STRPTR Pattern)
  1929. {
  1930. /*    kprintf("xpr_ffirst(0x%08lx,\"%s\")\n",Buffer,Pattern);*/
  1931.  
  1932.     if(FileTransferInfo)
  1933.     {
  1934.         FileTransferInfo -> DoneSize    = 0;
  1935.         FileTransferInfo -> DoneFiles    = 0;
  1936.  
  1937.         FileTransferInfo -> CurrentFile    = (struct FileTransferNode *)FileTransferInfo -> FileList . mlh_Head;
  1938.         FileTransferInfo -> CurrentSize    = FileTransferInfo -> CurrentFile -> Size;
  1939.  
  1940.         if(Config -> TransferConfig -> MangleFileNames)
  1941.         {
  1942.             UBYTE LocalName[MAX_FILENAME_LENGTH],*Char;
  1943.  
  1944.             strcpy(OriginalName,FileTransferInfo -> CurrentFile -> Name);
  1945.  
  1946.             ShrinkName(FilePart(FileTransferInfo -> CurrentFile -> Name),LocalName,12,TRUE);
  1947.  
  1948.             strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  1949.  
  1950.             Char = PathPart(Buffer);
  1951.  
  1952.             *Char = 0;
  1953.  
  1954.             AddPart(Buffer,LocalName,MAX_FILENAME_LENGTH);
  1955.  
  1956.             strcpy(ShrunkenName,Buffer);
  1957.         }
  1958.         else
  1959.         {
  1960.             OriginalName[0] = 0;
  1961.  
  1962.             strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  1963.         }
  1964.  
  1965.         return(1);
  1966.     }
  1967.     else
  1968.         return(0);
  1969. }
  1970.  
  1971.     /* xpr_fnext(LONG OldState,STRPTR Buffer,STRPTR Pattern):
  1972.      *
  1973.      *    Batch file upload: find the next matching file
  1974.      *    - if any - and return its name.
  1975.      */
  1976.  
  1977. LONG __saveds __asm
  1978. xpr_fnext(register __d0 LONG OldState,register __a0 STRPTR Buffer,register __a1 STRPTR Pattern)
  1979. {
  1980. /*    kprintf("xpr_fnext(%ld,0x%08lx,\"%s\")\n",OldState,Buffer,Pattern);*/
  1981.  
  1982.     if(FileTransferInfo)
  1983.     {
  1984.         if(FileTransferInfo -> CurrentFile -> Node . mln_Succ -> mln_Succ)
  1985.         {
  1986.             FileTransferInfo -> DoneSize    += FileTransferInfo -> CurrentSize;
  1987.             FileTransferInfo -> DoneFiles    += 1;
  1988.  
  1989.             FileTransferInfo -> CurrentFile  = (struct FileTransferNode *)FileTransferInfo -> CurrentFile -> Node . mln_Succ;
  1990.             FileTransferInfo -> CurrentSize  = FileTransferInfo -> CurrentFile -> Size;
  1991.  
  1992.             if(Config -> TransferConfig -> MangleFileNames)
  1993.             {
  1994.                 UBYTE LocalName[MAX_FILENAME_LENGTH],*Char;
  1995.  
  1996.                 strcpy(OriginalName,FileTransferInfo -> CurrentFile -> Name);
  1997.  
  1998.                 ShrinkName(FilePart(FileTransferInfo -> CurrentFile -> Name),LocalName,12,TRUE);
  1999.  
  2000.                 strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  2001.  
  2002.                 Char = PathPart(Buffer);
  2003.  
  2004.                 *Char = 0;
  2005.  
  2006.                 AddPart(Buffer,LocalName,MAX_FILENAME_LENGTH);
  2007.  
  2008.                 strcpy(ShrunkenName,Buffer);
  2009.             }
  2010.             else
  2011.             {
  2012.                 OriginalName[0] = 0;
  2013.  
  2014.                 strcpy(Buffer,FileTransferInfo -> CurrentFile -> Name);
  2015.             }
  2016.  
  2017.             return(1);
  2018.         }
  2019.     }
  2020.  
  2021.     return(0);
  2022. }
  2023.  
  2024.     /* xpr_finfo(STRPTR FileName,LONG InfoType):
  2025.      *
  2026.      *    Return information on a given file.
  2027.      */
  2028.  
  2029. LONG __saveds __asm
  2030. xpr_finfo(register __a0 STRPTR FileName,register __d0 LONG InfoType)
  2031. {
  2032.     struct FileInfoBlock    *FileInfo;
  2033.     LONG             Size;
  2034.  
  2035. /*    kprintf("xpr_finfo(\"%s\",%ld)\n",FileName,InfoType);*/
  2036.  
  2037.     switch(InfoType)
  2038.     {
  2039.             /* Return the file size. */
  2040.  
  2041.         case 1:    Size = 0;
  2042.  
  2043.             if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE))
  2044.             {
  2045.                 UBYTE    RealName[MAX_FILENAME_LENGTH];
  2046.                 BPTR    FileLock;
  2047.  
  2048.                 if(OriginalName[0])
  2049.                 {
  2050.                     if(!Stricmp(ShrunkenName,FileName))
  2051.                         FileName = NewFileName(OriginalName,RealName);
  2052.                     else
  2053.                         FileName = NewFileName(FileName,RealName);
  2054.                 }
  2055.                 else
  2056.                     FileName = NewFileName(FileName,RealName);
  2057.  
  2058.                 if(FileLock = Lock(FileName,ACCESS_READ))
  2059.                 {
  2060.                     if(Examine(FileLock,FileInfo))
  2061.                     {
  2062.                         if(FileInfo -> fib_DirEntryType < 0)
  2063.                             Size = FileInfo -> fib_Size;
  2064.                     }
  2065.  
  2066.                     UnLock(FileLock);
  2067.                 }
  2068.  
  2069.                 FreeDosObject(DOS_FIB,FileInfo);
  2070.             }
  2071.  
  2072.             return(Size);
  2073.  
  2074.             /* Return the file transfer mode. */
  2075.  
  2076.         case 2:    return(BinaryTransfer ? 1 : 2);
  2077.  
  2078.             /* Ignore the rest. */
  2079.  
  2080.         default:return(0);
  2081.     }
  2082. }
  2083.  
  2084.     /* xpr_options(LONG NumOpts,struct xpr_option **Opts):
  2085.      *
  2086.      *    Provide a more polished user interface to set the
  2087.      *    transfer protocol options.
  2088.      */
  2089.  
  2090. ULONG __saveds __asm
  2091. xpr_options(register __d0 LONG NumOpts,register __a0 struct xpr_option **Opts)
  2092. {
  2093. /*    kprintf("xpr_options(%ld,0x%08lx)\n",NumOpts,Opts);*/
  2094.  
  2095.     if(NumOpts && Opts)
  2096.     {
  2097.         enum    {    GAD_USE=1,GAD_CANCEL,GAD_SPECIAL };
  2098.  
  2099.         struct LayoutHandle    *Handle;
  2100.         ULONG             Flags = NULL;
  2101.  
  2102.             /* We only have 32 bits! */
  2103.  
  2104.         if(NumOpts > 32)
  2105.             NumOpts = 32;
  2106.  
  2107.         if(Handle = LT_CreateHandleTags(Window -> WScreen,
  2108.             LH_LocaleHook,    &LocaleHook,
  2109.         TAG_DONE))
  2110.         {
  2111.             struct Window    *PanelWindow;
  2112.             LONG         i,Split;
  2113.  
  2114.             if(NumOpts > 16)
  2115.                 Split = NumOpts / 2;
  2116.             else
  2117.                 Split = -1;
  2118.  
  2119.             LT_New(Handle,
  2120.                 LA_Type,    VERTICAL_KIND,
  2121.             TAG_DONE);
  2122.             {
  2123.                 LT_New(Handle,
  2124.                     LA_Type,    HORIZONTAL_KIND,
  2125.                     LA_LabelID,    MSG_V36_1501,
  2126.                 TAG_DONE);
  2127.                 {
  2128.                     LT_New(Handle,
  2129.                         LA_Type,    VERTICAL_KIND,
  2130.                     TAG_DONE);
  2131.                     {
  2132.                         for(i = 0 ; i < NumOpts ; i++)
  2133.                         {
  2134.                             if(Opts[i])
  2135.                             {
  2136.                                 switch(Opts[i] -> xpro_type)
  2137.                                 {
  2138.                                     case XPRO_BOOLEAN:
  2139.  
  2140.                                         LT_New(Handle,
  2141.                                             LA_Type,    CHECKBOX_KIND,
  2142.                                             LA_LabelText,    Opts[i] -> xpro_description,
  2143.                                             LA_ID,        GAD_SPECIAL + i,
  2144.                                             GTCB_Checked,    GetOptionMode(Opts[i]),
  2145.                                         TAG_DONE);
  2146.  
  2147.                                         break;
  2148.  
  2149.                                     case XPRO_LONG:
  2150.  
  2151.                                         LT_New(Handle,
  2152.                                             LA_Type,        INTEGER_KIND,
  2153.                                             LA_LabelText,        Opts[i] -> xpro_description,
  2154.                                             LA_ID,            GAD_SPECIAL + i,
  2155.                                             LA_Chars,        15,
  2156.                                             GTIN_Number,        Atol(Opts[i] -> xpro_value),
  2157.                                             LAIN_UseIncrementers,    TRUE,
  2158.                                         TAG_DONE);
  2159.  
  2160.                                         break;
  2161.  
  2162.                                     case XPRO_STRING:
  2163.  
  2164.                                         LT_New(Handle,
  2165.                                             LA_Type,    STRING_KIND,
  2166.                                             LA_LabelText,    Opts[i] -> xpro_description,
  2167.                                             LA_ID,        GAD_SPECIAL + i,
  2168.                                             LA_Chars,    15,
  2169.                                             GTST_String,    Opts[i] -> xpro_value,
  2170.                                             GTST_MaxChars,    Opts[i] -> xpro_length - 1,
  2171.                                         TAG_DONE);
  2172.  
  2173.                                         break;
  2174.  
  2175.                                     case XPRO_COMMPAR:
  2176.  
  2177.                                         LT_New(Handle,
  2178.                                             LA_Type,    STRING_KIND,
  2179.                                             LA_LabelText,    Opts[i] -> xpro_description,
  2180.                                             LA_ID,        GAD_SPECIAL + i,
  2181.                                             LA_Chars,    15,
  2182.                                             LA_HighLabel,    TRUE,
  2183.                                             GTST_String,    Opts[i] -> xpro_value,
  2184.                                             GTST_MaxChars,    Opts[i] -> xpro_length - 1,
  2185.                                         TAG_DONE);
  2186.  
  2187.                                         break;
  2188.  
  2189.                                     case XPRO_HEADER:
  2190.  
  2191.                                         LT_New(Handle,
  2192.                                             LA_Type,    TEXT_KIND,
  2193.                                             LA_LabelText,    Opts[i] -> xpro_description,
  2194.                                             LA_HighLabel,    TRUE,
  2195.                                             GTTX_Text,    " ",
  2196.                                         TAG_DONE);
  2197.  
  2198.                                         break;
  2199.  
  2200.                                     case XPRO_COMMAND:
  2201.  
  2202.                                         LT_New(Handle,
  2203.                                             LA_Type,    BUTTON_KIND,
  2204.                                             LA_LabelText,    Opts[i] -> xpro_description,
  2205.                                             LA_ID,        GAD_SPECIAL + i,
  2206.                                             LA_Chars,    15,
  2207.                                         TAG_DONE);
  2208.  
  2209.                                         break;
  2210.                                 }
  2211.                             }
  2212.  
  2213.                             if(i == Split)
  2214.                             {
  2215.                                 LT_EndGroup(Handle);
  2216.  
  2217.                                 LT_New(Handle,
  2218.                                     LA_Type,    VERTICAL_KIND,
  2219.                                 TAG_DONE);
  2220.                             }
  2221.                         }
  2222.  
  2223.                         LT_EndGroup(Handle);
  2224.                     }
  2225.  
  2226.                     LT_EndGroup(Handle);
  2227.                 }
  2228.  
  2229.                 LT_New(Handle,
  2230.                     LA_Type,VERTICAL_KIND,
  2231.                 TAG_DONE);
  2232.                 {
  2233.                     LT_New(Handle,
  2234.                         LA_Type,    XBAR_KIND,
  2235.                         LAXB_FullSize,    TRUE,
  2236.                     TAG_DONE);
  2237.  
  2238.                     LT_EndGroup(Handle);
  2239.                 }
  2240.  
  2241.                 LT_New(Handle,LA_Type,HORIZONTAL_KIND,
  2242.                     LAGR_SameSize,    TRUE,
  2243.                     LAGR_Spread,    TRUE,
  2244.                 TAG_DONE);
  2245.                 {
  2246.                     LT_New(Handle,
  2247.                         LA_Type,    BUTTON_KIND,
  2248.                         LA_LabelID,    MSG_GLOBAL_USE_GAD,
  2249.                         LA_ID,        GAD_USE,
  2250.                         LABT_ReturnKey,    TRUE,
  2251.                         LABT_ExtraFat,    TRUE,
  2252.                     TAG_DONE);
  2253.  
  2254.                     LT_New(Handle,
  2255.                         LA_Type,    BUTTON_KIND,
  2256.                         LA_LabelID,    MSG_GLOBAL_CANCEL_GAD,
  2257.                         LA_ID,        GAD_CANCEL,
  2258.                         LABT_EscKey,    TRUE,
  2259.                         LABT_ExtraFat,    TRUE,
  2260.                     TAG_DONE);
  2261.  
  2262.                     LT_EndGroup(Handle);
  2263.                 }
  2264.  
  2265.                 LT_EndGroup(Handle);
  2266.             }
  2267.  
  2268.             if(PanelWindow = LT_Layout(Handle,OptionTitle ? OptionTitle : LocaleString(MSG_TERMXPR_TRANSFER_OPTIONS_TXT),NULL,0,0,IDCMP_CLOSEWINDOW,0,
  2269.                 LAWN_HelpHook,        &GuideHook,
  2270.                 LAWN_Parent,        Window,
  2271.                 WA_DepthGadget,        TRUE,
  2272.                 WA_CloseGadget,        TRUE,
  2273.                 WA_DragBar,        TRUE,
  2274.                 WA_RMBTrap,        TRUE,
  2275.                 WA_Activate,        TRUE,
  2276.             TAG_DONE))
  2277.             {
  2278.                 struct IntuiMessage    *Message;
  2279.                 BOOLEAN             Done = FALSE;
  2280.                 ULONG             MsgClass,
  2281.                              MsgQualifier;
  2282.                 UWORD             MsgCode;
  2283.                 struct Gadget        *MsgGadget;
  2284.                 BOOLEAN             CheckFlags = FALSE;
  2285.  
  2286.                 PushWindow(PanelWindow);
  2287.  
  2288.                 LT_ShowWindow(Handle,TRUE);
  2289.  
  2290.                 do
  2291.                 {
  2292.                     if(Wait(PORTMASK(PanelWindow -> UserPort) | SIG_BREAK) & SIG_BREAK)
  2293.                         break;
  2294.  
  2295.                     while(Message = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort))
  2296.                     {
  2297.                         MsgClass    = Message -> Class;
  2298.                         MsgQualifier    = Message -> Qualifier;
  2299.                         MsgCode        = Message -> Code;
  2300.                         MsgGadget    = (struct Gadget *)Message -> IAddress;
  2301.  
  2302.                         GT_ReplyIMsg(Message);
  2303.  
  2304.                         LT_HandleInput(Handle,MsgQualifier,&MsgClass,&MsgCode,&MsgGadget);
  2305.  
  2306.                         if(MsgClass == IDCMP_CLOSEWINDOW)
  2307.                             Done = TRUE;
  2308.  
  2309.                         if(MsgClass == IDCMP_GADGETUP)
  2310.                         {
  2311.                             switch(MsgGadget -> GadgetID)
  2312.                             {
  2313.                                 case GAD_USE:
  2314.  
  2315.                                     Done = CheckFlags = TRUE;
  2316.                                     break;
  2317.  
  2318.                                 case GAD_CANCEL:
  2319.  
  2320.                                     Done = TRUE;
  2321.                                     break;
  2322.  
  2323.                                 default:
  2324.  
  2325.                                     if(MsgGadget -> GadgetID - GAD_SPECIAL < NumOpts)
  2326.                                     {
  2327.                                         i = MsgGadget -> GadgetID - GAD_SPECIAL;
  2328.  
  2329.                                         if(Opts[i] -> xpro_type == XPRO_COMMAND || (Opts[i] -> xpro_type == XPRO_COMMPAR && MsgCode != '\t'))
  2330.                                         {
  2331.                                             Flags = (1L << i);
  2332.  
  2333.                                             XPRCommandSelected = Done = CheckFlags = TRUE;
  2334.                                         }
  2335.                                     }
  2336.  
  2337.                                     break;
  2338.                             }
  2339.                         }
  2340.                     }
  2341.                 }
  2342.                 while(!Done);
  2343.  
  2344.                 PopWindow();
  2345.  
  2346.                 if(CheckFlags)
  2347.                 {
  2348.                     LT_LockWindow(PanelWindow);
  2349.  
  2350.                     for(i = 0 ; i < NumOpts ; i++)
  2351.                     {
  2352.                         if(Opts[i])
  2353.                         {
  2354.                             switch(Opts[i] -> xpro_type)
  2355.                             {
  2356.                                 case XPRO_BOOLEAN:
  2357.  
  2358.                                     if(LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE) != GetOptionMode(Opts[i]))
  2359.                                     {
  2360.                                         Flags |= (1L << i);
  2361.  
  2362.                                         if(LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE))
  2363.                                             strcpy(Opts[i] -> xpro_value,"yes");
  2364.                                         else
  2365.                                             strcpy(Opts[i] -> xpro_value,"no");
  2366.  
  2367.                                         NewOptions = TRUE;
  2368.                                     }
  2369.  
  2370.                                     break;
  2371.  
  2372.                                 case XPRO_LONG:
  2373.  
  2374.                                     if(Atol(Opts[i] -> xpro_value) != LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE))
  2375.                                     {
  2376.                                         Flags |= (1L << i);
  2377.  
  2378.                                         SPrintf(Opts[i] -> xpro_value,"%ld",LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE));
  2379.  
  2380.                                         NewOptions = TRUE;
  2381.                                     }
  2382.  
  2383.                                     break;
  2384.  
  2385.                                 case XPRO_STRING:
  2386.  
  2387.                                     if(strcmp(Opts[i] -> xpro_value,(STRPTR)LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE)))
  2388.                                     {
  2389.                                         Flags |= (1L << i);
  2390.  
  2391.                                         strcpy(Opts[i] -> xpro_value,(STRPTR)LT_GetAttributes(Handle,GAD_SPECIAL + i,TAG_DONE));
  2392.  
  2393.                                         NewOptions = TRUE;
  2394.                                     }
  2395.  
  2396.                                     break;
  2397.                             }
  2398.                         }
  2399.                     }
  2400.  
  2401.                     LT_UnlockWindow(PanelWindow);
  2402.                 }
  2403.                 else
  2404.                     Flags = NULL;
  2405.             }
  2406.  
  2407.             LT_DeleteHandle(Handle);
  2408.         }
  2409.  
  2410.         return(Flags);
  2411.     }
  2412.     else
  2413.         return(NULL);
  2414. }
  2415.  
  2416.     /* xpr_unlink(STRPTR FileName):
  2417.      *
  2418.      *    Remove (delete) a given file.
  2419.      */
  2420.  
  2421. LONG __saveds __asm
  2422. xpr_unlink(register __a0 STRPTR FileName)
  2423. {
  2424. /*    kprintf("xpr_unlink(\"%s\")\n",FileName);*/
  2425.  
  2426.         /* Sorry, but it is far too dangerous to let the protocol
  2427.          * remove any files with path name substitution enabled.
  2428.          * The protocol could accidentally hit the wrong file.
  2429.          */
  2430.  
  2431.     if(!Config -> MiscConfig -> OverridePath)
  2432.     {
  2433.         if(OriginalName[0])
  2434.         {
  2435.             if(!Stricmp(ShrunkenName,FileName))
  2436.                 FileName = OriginalName;
  2437.         }
  2438.  
  2439.         if(DeleteFile(FileName))
  2440.         {
  2441.             LogAction(LocaleString(MSG_TERMXPR_LOGMSG_DELETE_FILE_TXT),FilePart(FileName));
  2442.  
  2443.             return(0);
  2444.         }
  2445.     }
  2446.  
  2447.     return(-1);
  2448. }
  2449.  
  2450.     /* xpr_squery():
  2451.      *
  2452.      *    Check how many characters are present in the serial buffer.
  2453.      */
  2454.  
  2455. LONG __saveds __asm
  2456. xpr_squery()
  2457. {
  2458. /*    kprintf("xpr_squery()\n");*/
  2459.  
  2460.     if(WriteRequest)
  2461.     {
  2462.         ULONG    Waiting;
  2463.         UWORD    Status;
  2464.  
  2465.         GetSerialInfo(&Waiting,&Status);
  2466.  
  2467.             /* Return error if carrier is lost. */
  2468.  
  2469.         if((Status & CIAF_COMCD) && Config -> SerialConfig -> CheckCarrier)
  2470.         {
  2471.             if(!CarrierMessage)
  2472.             {
  2473.                 CarrierMessage = TRUE;
  2474.  
  2475.                 AddTransferInfo(TRUE,LocaleString(MSG_TERMXPR_CARRIER_LOST_TXT));
  2476.             }
  2477.  
  2478.             ObtainSemaphore(&OnlineSemaphore);
  2479.  
  2480.             WasOnline    = Online;
  2481.             Online        = FALSE;
  2482.  
  2483.             ReleaseSemaphore(&OnlineSemaphore);
  2484.  
  2485.             TransferError = TRUE;
  2486.         }
  2487.         else
  2488.             return((LONG)Waiting);
  2489.     }
  2490.  
  2491.     return(-1);
  2492. }
  2493.  
  2494.     /* xpr_getptr(LONG InfoType):
  2495.      *
  2496.      *    Return a pointer to the term custom screen.
  2497.      */
  2498.  
  2499. LONG __saveds __asm
  2500. xpr_getptr(register __d0 LONG InfoType)
  2501. {
  2502. /*    kprintf("xpr_getptr(%ld)\n",InfoType);*/
  2503.  
  2504.     if(InfoType == 1)
  2505.         return((LONG)Window -> WScreen);
  2506.     else
  2507.         return(-1);
  2508. }
  2509.  
  2510.     /* xpr_stealopts(STRPTR Prompt,STRPTR Buffer):
  2511.      *
  2512.      *    Steal the contents of the options buffer (replacement
  2513.      *    for xpr_gets).
  2514.      */
  2515.  
  2516. LONG __saveds __asm
  2517. xpr_stealopts(register __a0 STRPTR Prompt,register __a1 STRPTR Buffer)
  2518. {
  2519. /*    kprintf("xpr_stealops(\"%s\",\"%s\")\n",Prompt,Buffer);*/
  2520.  
  2521.     if(Buffer)
  2522.         strcpy(ProtocolOptsBuffer,Buffer);
  2523.  
  2524.     return(1);
  2525. }
  2526.