home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / term43-source.lha / Extras / Source / term-Source.lha / termXPR.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-20  |  56.4 KB  |  2,721 lines

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