home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / comm / term23_2.lha / Source_Code / termSource / termPhone.c < prev    next >
C/C++ Source or Header  |  1992-08-18  |  38KB  |  1,699 lines

  1. /*
  2. **    $Id: termPhone.c,v 1.11 92/08/18 16:12:51 olsen Sta Locker: olsen $
  3. **    $Revision: 1.11 $
  4. **    $Date: 92/08/18 16:12:51 $
  5. **
  6. **    Phonebook support routines
  7. **
  8. **    Copyright © 1990-1992 by Olaf `Olsen' Barthel & MXM
  9. **        All Rights Reserved
  10. */
  11.  
  12. #include "termGlobal.h"
  13.  
  14.     /* Size of a phonebook entry in the list. */
  15.  
  16. #define RAWSIZE (sizeof(struct PhoneEntry) - offsetof(struct PhoneEntry,Name))
  17.  
  18. #define DATEHEADERSIZE 24
  19.  
  20.     /* Obsolete TimeDate structure. */
  21.  
  22. struct TimeDateOld
  23. {
  24.     WORD            PayPerUnit[2],
  25.                 SecPerUnit[2],
  26.                 TimeOfDay[2];
  27.  
  28.     BYTE            Month,
  29.                 Day;
  30.  
  31.     UBYTE            Comment[22];
  32. };
  33.  
  34.     /* Are we using the new includes? */
  35.  
  36. #ifdef ASLSM_FilterFunc
  37.  
  38.     /* Undefine the following symbols, the preferences header file
  39.      * will use the same names and the same values.
  40.      */
  41.  
  42. #undef PARITY_NONE
  43. #undef PARITY_EVEN
  44. #undef PARITY_ODD
  45. #undef PARITY_MARK
  46. #undef PARITY_SPACE
  47.  
  48.     /* Include the preferences header files. */
  49.  
  50. #include <prefs/prefhdr.h>
  51. #include <prefs/serial.h>
  52.  
  53.     /* Serial preferences data. */
  54.  
  55. STATIC BYTE            SerialPrefsRead        = FALSE,
  56.                 SerialPrefsReadFailed    = FALSE;
  57. STATIC struct SerialPrefs    SerialPrefs;
  58.  
  59.     /* ReadSerialPrefs():
  60.      *
  61.      *    Reads the default serial preferences settings.
  62.      */
  63.  
  64. STATIC BYTE
  65. ReadSerialPrefs()
  66. {
  67.     struct IFFHandle *Handle;
  68.  
  69.         /* Allocate an IFF handle. */
  70.  
  71.     if(Handle = AllocIFF())
  72.     {
  73.             /* Open the preferences settings file. */
  74.  
  75.         if(Handle -> iff_Stream = Open("ENV:sys/serial.prefs",MODE_OLDFILE))
  76.         {
  77.                 /* Make it known as a DOS file handle. */
  78.  
  79.             InitIFFasDOS(Handle);
  80.  
  81.                 /* Open the file for reading. */
  82.  
  83.             if(!OpenIFF(Handle,IFFF_READ))
  84.             {
  85.                     /* Stop at the `body' chunk. */
  86.  
  87.                 if(!StopChunk(Handle,ID_PREF,ID_SERL))
  88.                 {
  89.                         /* Look for it... */
  90.  
  91.                     if(!ParseIFF(Handle,IFFPARSE_SCAN))
  92.                     {
  93.                             /* Read the data. */
  94.  
  95.                         if(ReadChunkBytes(Handle,&SerialPrefs,sizeof(struct SerialPrefs)) == sizeof(struct SerialPrefs))
  96.                             SerialPrefsRead = TRUE;
  97.                     }
  98.                 }
  99.  
  100.                     /* Close the handle. */
  101.  
  102.                 CloseIFF(Handle);
  103.             }
  104.  
  105.                 /* Release the handle. */
  106.  
  107.             Close(Handle -> iff_Stream);
  108.         }
  109.  
  110.             /* Clean up. */
  111.  
  112.         FreeIFF(Handle);
  113.     }
  114.  
  115.         /* Return sucess/failure. */
  116.  
  117.     return(SerialPrefsRead);
  118. }
  119.  
  120. #endif    /* ASLSM_FilterFunc */
  121.  
  122.     /* SetPrefToDefaults():
  123.      *
  124.      *    Initialize configuration with default values.
  125.      */
  126.  
  127. VOID
  128. SetPrefToDefaults(struct Configuration *Config,UBYTE *PathBuffer)
  129. {
  130.     if(!PathBuffer)
  131.         PathBuffer = "TERM:config";
  132.  
  133.     strcpy(Config -> DefaultStorage,PathBuffer);
  134.  
  135. #ifdef ASLSM_FilterFunc
  136.  
  137.         /* The program will only try to read the preferences
  138.          * settings once; if the first access failed, no
  139.          * other accesses will be made.
  140.          */
  141.  
  142.     if(!SerialPrefsRead && !SerialPrefsReadFailed)
  143.         SerialPrefsReadFailed = ReadSerialPrefs() ^ TRUE;
  144.  
  145.         /* Did we succeed in reading the file? */
  146.  
  147.     if(!SerialPrefsRead)
  148.     {
  149.         Config -> BaudRate        = 2400;
  150.         Config -> BitsPerChar        = 8;
  151.         Config -> Parity        = PARITY_NONE;
  152.         Config -> StopBits        = 1;
  153.         Config -> Handshaking        = 42;
  154.         Config -> HandshakingProtocol    = HANDSHAKING_NONE;
  155.         Config -> xONxOFF        = TRUE;
  156.         Config -> SerBuffSize        = 32768;
  157.     }
  158.     else
  159.     {
  160.             /* Fill in the common data. */
  161.  
  162.         Config -> BaudRate        = SerialPrefs . sp_BaudRate;
  163.         Config -> SerBuffSize        = SerialPrefs . sp_InputBuffer;
  164.         Config -> BitsPerChar        = SerialPrefs . sp_BitsPerChar;
  165.         Config -> StopBits        = SerialPrefs . sp_StopBits;
  166.         Config -> Handshaking        = 42;
  167.  
  168.             /* Convert the handshaking mode. */
  169.  
  170.         switch(SerialPrefs . sp_InputHandshake)
  171.         {
  172.             case HSHAKE_NONE:    Config -> HandshakingProtocol    = HANDSHAKING_NONE;
  173.                         Config -> xONxOFF        = FALSE;
  174.  
  175.                         break;
  176.  
  177.             case HSHAKE_RTS:    Config -> HandshakingProtocol    = HANDSHAKING_RTSCTS;
  178.                         Config -> xONxOFF        = FALSE;
  179.  
  180.                         break;
  181.  
  182.             default:        Config -> HandshakingProtocol    = HANDSHAKING_NONE;
  183.                         Config -> xONxOFF        = TRUE;
  184.  
  185.                         break;
  186.         }
  187.  
  188.             /* Convert the parity settings. */
  189.  
  190.         if(SerialPrefs . sp_Parity <= PARITY_SPACE)
  191.             Config -> Parity = SerialPrefs . sp_Parity;
  192.         else
  193.             Config -> Parity = PARITY_NONE;
  194.     }
  195.  
  196. #else
  197.  
  198.     Config -> BaudRate        = 2400;
  199.     Config -> BitsPerChar        = 8;
  200.     Config -> Parity        = PARITY_NONE;
  201.     Config -> StopBits        = 1;
  202.     Config -> Handshaking        = HANDSHAKING_XONXOFF;
  203.     Config -> SerBuffSize        = 32768;
  204.  
  205. #endif    /* ASLSM_FilterFunc */
  206.  
  207.     strcpy(Config -> SerialDevice,SERIALNAME);
  208.  
  209.     Config -> Duplex        = DUPLEX_FULL;
  210.     Config -> HighSpeed        = FALSE;
  211.     Config -> BreakLength        = 250000;
  212.     Config -> UnitNumber        = 0;
  213.  
  214.     /* Modem Preferences. */
  215.  
  216.     Config -> RedialDelay        = 2;
  217.     Config -> DialRetries        = 10;
  218.     Config -> DialTimeout        = 60;
  219.     Config -> ConnectAutoBaud    = FALSE;
  220.  
  221.     strcpy(Config -> ModemInit,    "ATZ\\r");
  222.     strcpy(Config -> ModemExit,    "");
  223.     strcpy(Config -> ModemHangup,    "~~~~~~~~+++\\r~~~~~~ATH0\\r");
  224.     strcpy(Config -> DialPrefix,    "~~ATDP");
  225.     strcpy(Config -> NoCarrier,    "NO CARRIER");
  226.     strcpy(Config -> Connect,    "CONNECT");
  227.     strcpy(Config -> Voice,        "VOICE");
  228.     strcpy(Config -> Ring,        "RING");
  229.     strcpy(Config -> Busy,        "BUSY");
  230.  
  231.     /* Transfer Preferences. */
  232.  
  233.     strcpy(Config -> Protocol,"xprzmodem.library");
  234.  
  235.     /* Macro Preferences. */
  236.  
  237.     if(!LastMacros[0])
  238.     {
  239.         strcpy(LastMacros,PathBuffer);
  240.  
  241.         AddPart(LastMacros,"macros.prefs",256);
  242.     }
  243.  
  244.     strcpy(Config -> MacroFile,LastMacros);
  245.  
  246.     /* Screen Preferences. */
  247.  
  248.     Config -> DisplayMode        = DEFAULT_MONITOR_ID|HIRES_KEY;
  249.     Config -> MakeScreenPublic    = TRUE;
  250.  
  251.     /* Terminal Preferences. */
  252.  
  253.     Config -> CaptureFilter        = TRUE;
  254.     Config -> DestructiveBackspace    = FALSE;
  255.     Config -> AudibleBell        = TRUE;
  256.     Config -> VisibleBell        = FALSE;
  257.     Config -> EightyColumns        = FALSE;
  258.     Config -> SendCR        = CR_ASCR;
  259.     Config -> SendLF        = LF_ASLF;
  260.     Config -> ColourMode        = COLOUR_AMIGA;
  261.     Config -> Emulation        = EMULATION_ANSIVT100;
  262.     Config -> Font            = FONT_TOPAZ;
  263.  
  264.     Config -> SwapBSDelete        = FALSE;
  265.     Config -> StripBit8        = FALSE;
  266.  
  267.     Config -> RasterEnabled        = TRUE;
  268.  
  269.     Config -> EmulationName[0]    = 0;
  270.  
  271.     Config -> StartupMacro[0]    = 0;
  272.     Config -> UploadMacro[0]    = 0;
  273.     Config -> DownloadMacro[0]    = 0;
  274.     Config -> LogoffMacro[0]    = 0;
  275.  
  276.     if(!LastFastMacros[0])
  277.     {
  278.         strcpy(LastFastMacros,PathBuffer);
  279.  
  280.         AddPart(LastFastMacros,"fastmacros.prefs",256);
  281.     }
  282.  
  283.     strcpy(Config -> FastMacroFile,LastFastMacros);
  284.  
  285.     Config -> Priority        = 0;
  286.     Config -> OverridePath        = TRUE;
  287.     Config -> BackupConfig        = FALSE;
  288.     Config -> AutoUpload        = TRUE;
  289.  
  290.     strcpy(Config -> NoDialTone,"NO DIALTONE");
  291.  
  292.     Config -> TitleBar        = TRUE;
  293.     Config -> StatusLine        = TRUE;
  294.  
  295.     Config -> DropDTR        = FALSE;
  296.  
  297.     Config -> MaxLogBuffSize    = 0;
  298.     Config -> BufferEnabled        = TRUE;
  299.  
  300.     Config -> ReceiveCR        = CR_ASCR;
  301.     Config -> ReceiveLF        = LF_ASLF;
  302.  
  303.     Config -> SetArchivedBit    = FALSE;
  304.  
  305.     Config -> KeyMapName[0]        = 0;
  306.  
  307.     Config -> OpenFastMacroPanel    = FALSE;
  308.  
  309.     Config -> PassThrough        = FALSE;
  310.  
  311.     Config -> SystemBeep        = FALSE;
  312.  
  313.     Config -> Alert            = ALERT_BEEP_SCREEN;
  314.  
  315.     Config -> AnswerBack[0]        = 0;
  316.  
  317.     Config -> ClipboardUnit        = 0;
  318.  
  319.     strcpy(Config -> FontName,"topaz.font");
  320.     Config -> FontHeight = 8;
  321.  
  322.     strcpy(Config -> TextFontName,"topaz.font");
  323.     Config -> TextFontHeight = 8;
  324.  
  325.     Config -> NCommLog        = FALSE;
  326.     Config -> PrinterEnabled    = TRUE;
  327.  
  328.     Config -> Pad            = 0;
  329.  
  330.     strcpy(Config -> DialSuffix,"\\r");
  331.  
  332.     Config -> LineDelay        = 0;
  333.     Config -> CharDelay        = 0;
  334. }
  335.  
  336.     /* UpdatePrefs(struct Configuration *Config):
  337.      *
  338.      *    Patch existing preferences entry to
  339.      *    use new flags and definitions.
  340.      */
  341.  
  342. VOID
  343. UpdatePrefs(struct Configuration *Config)
  344. {
  345.     enum { OLDHANDSHAKING_XONXOFF,OLDHANDSHAKING_RTSCTS,OLDHANDSHAKING_NONE,OLDHANDSHAKING_RTSCTS_DSR };
  346.  
  347.     switch(Config -> Handshaking)
  348.     {
  349.         case OLDHANDSHAKING_XONXOFF:    Config -> HandshakingProtocol    = HANDSHAKING_NONE;
  350.                         Config -> xONxOFF        = TRUE;
  351.                         break;
  352.  
  353.         case OLDHANDSHAKING_RTSCTS:    Config -> HandshakingProtocol    = HANDSHAKING_RTSCTS;
  354.                         Config -> xONxOFF        = FALSE;
  355.                         break;
  356.  
  357.         case OLDHANDSHAKING_NONE:    Config -> HandshakingProtocol    = HANDSHAKING_NONE;
  358.                         Config -> xONxOFF        = FALSE;
  359.                         break;
  360.  
  361.         case OLDHANDSHAKING_RTSCTS_DSR:    Config -> HandshakingProtocol    = HANDSHAKING_RTSCTS_DSR;
  362.                         Config -> xONxOFF        = FALSE;
  363.                         break;
  364.     }
  365.  
  366.     Config -> Handshaking = 42;
  367.  
  368.     if(Config -> EmulationName[0])
  369.     {
  370.         WORD i;
  371.  
  372.         for(i = 0 ; i < strlen(Config -> EmulationName) ; i++)
  373.             Config -> EmulationName[i] = ToLower(Config -> EmulationName[i]);
  374.     }
  375.  
  376.     if(Config -> HighSpeed & ~SERIAL_SHARED)
  377.     {
  378.         Config -> BitsPerChar    = 8;
  379.         Config -> StopBits    = 1;
  380.         Config -> Parity    = PARITY_NONE;
  381.     }
  382. }
  383.  
  384. VOID
  385. RemoveDialEntry(LONG Entry)
  386. {
  387.     LONG Count = Phonebook[Entry] -> Count,i;
  388.  
  389.     for(i = 0 ; i < NumPhoneEntries ; i++)
  390.     {
  391.         if(Phonebook[i] -> Count > Count)
  392.             SPrintf(Phonebook[i] -> Node -> LocalName,"%3ld - %s",Phonebook[i] -> Count--,Phonebook[i] -> Name);
  393.     }
  394.  
  395.     Phonebook[Entry] -> Count = -1;
  396.  
  397.     SPrintf(Phonebook[Entry] -> Node -> LocalName,"      %s",Phonebook[Entry] -> Name);
  398. }
  399.  
  400. VOID
  401. RemoveDialNode(struct PhoneNode *Node)
  402. {
  403.     LONG Count = Node -> Entry -> Count,i;
  404.  
  405.     for(i = 0 ; i < NumPhoneEntries ; i++)
  406.     {
  407.         if(Phonebook[i] -> Count > Count)
  408.             SPrintf(Phonebook[i] -> Node -> LocalName,"%3ld - %s",Phonebook[i] -> Count--,Phonebook[i] -> Name);
  409.     }
  410.  
  411.     Node -> Entry -> Count = -1;
  412.  
  413.     SPrintf(Node -> LocalName,"      %s",Node -> Entry -> Name);
  414. }
  415.  
  416. VOID
  417. SortToList(struct PhoneNode *PhoneNode)
  418. {
  419.     if(!DialList)
  420.     {
  421.         if(DialList = (struct List *)AllocVec(sizeof(struct List),MEMF_ANY|MEMF_CLEAR))
  422.             NewList(DialList);
  423.     }
  424.  
  425.     if(DialList)
  426.     {
  427.         struct PhoneNode *Node = (struct PhoneNode *)DialList -> lh_Head,*NewNode;
  428.  
  429.         if(NewNode = (struct PhoneNode *)AllocVec(sizeof(struct PhoneNode),MEMF_ANY))
  430.         {
  431.             CopyMem(PhoneNode,NewNode,sizeof(struct PhoneNode));
  432.  
  433.             while(Node -> VanillaNode . ln_Succ)
  434.             {
  435.                 if(Node -> Entry -> Count > NewNode -> Entry -> Count)
  436.                 {
  437.                     if(Node == (struct NewNode *)DialList -> lh_Head)
  438.                         AddHead(DialList,&NewNode -> VanillaNode);
  439.                     else
  440.                         Insert(DialList,&NewNode -> VanillaNode,Node -> VanillaNode . ln_Pred);
  441.  
  442.                     return;
  443.                 }
  444.  
  445.                 Node = (struct PhoneNode *)Node -> VanillaNode . ln_Succ;
  446.             }
  447.  
  448.             AddTail(DialList,&NewNode -> VanillaNode);
  449.         }
  450.     }
  451. }
  452.  
  453. VOID
  454. FreeDialList()
  455. {
  456.     if(DialList)
  457.     {
  458.         struct PhoneNode *NextNode,*SubNode;
  459.  
  460.         SubNode = (struct PhoneNode *)DialList -> lh_Head;
  461.  
  462.         while(SubNode -> VanillaNode . ln_Succ)
  463.         {
  464.             NextNode = (struct PhoneNode *)SubNode -> VanillaNode . ln_Succ;
  465.  
  466.             FreeVec(SubNode);
  467.  
  468.             SubNode = NextNode;
  469.         }
  470.  
  471.         FreeVec(DialList);
  472.  
  473.         DialList = NULL;
  474.     }
  475. }
  476.  
  477.     /* CreatePhoneList():
  478.      *
  479.      *    Turn the array of pointers to phonebook entries into
  480.      *    a linked standard Amiga List (gadtools needs this).
  481.      */
  482.  
  483. struct List *
  484. CreatePhoneList()
  485. {
  486.     struct List        *PhoneList;
  487.     struct PhoneNode    *PhoneNode;
  488.     LONG             i;
  489.  
  490.     if(Phonebook && NumPhoneEntries)
  491.     {
  492.         if(PhoneList = (struct List *)AllocVec(sizeof(struct List) + NumPhoneEntries * sizeof(struct PhoneNode),MEMF_ANY|MEMF_CLEAR))
  493.         {
  494.             NewList(PhoneList);
  495.  
  496.             PhoneNode = (struct PhoneNode *)(PhoneList + 1);
  497.  
  498.             for(i = 0 ; i < NumPhoneEntries ; i++)
  499.             {
  500.                 if(Phonebook[i] -> Count != -1)
  501.                     SPrintf(PhoneNode[i] . LocalName,"%3ld - %s",Phonebook[i] -> Count + 1,Phonebook[i] -> Name);
  502.                 else
  503.                     SPrintf(PhoneNode[i] . LocalName,"      %s",Phonebook[i] -> Name);
  504.  
  505.                 PhoneNode[i] . VanillaNode . ln_Name = PhoneNode[i] . LocalName;
  506.  
  507.                 Phonebook[i] -> Node = &PhoneNode[i];
  508.  
  509.                 PhoneNode[i] . Entry = Phonebook[i];
  510.  
  511.                 AddTail(PhoneList,&PhoneNode[i]);
  512.             }
  513.  
  514.             return(PhoneList);
  515.         }
  516.     }
  517.     else
  518.     {
  519.         if(PhoneList = (struct List *)AllocVec(sizeof(struct List),MEMF_ANY|MEMF_CLEAR))
  520.         {
  521.             NewList(PhoneList);
  522.  
  523.             return(PhoneList);
  524.         }
  525.     }
  526.  
  527.     return(NULL);
  528. }
  529.  
  530.     /* DeletePhoneList(struct List *PhoneList):
  531.      *
  532.      *    Delete the entries listed in the Amiga List
  533.      *    created by the routine above.
  534.      */
  535.  
  536. VOID
  537. DeletePhoneList(struct List *PhoneList)
  538. {
  539.     if(PhoneList)
  540.     {
  541.         FreeVec(PhoneList);
  542.  
  543.         PhoneList = NULL;
  544.     }
  545. }
  546.  
  547.     /* Compare(struct PhoneEntry **A,struct PhoneEntry **B):
  548.      *
  549.      *    Comparison subroutine required by the QuickSort
  550.      *    call below.
  551.      */
  552.  
  553. STATIC LONG __stdargs
  554. Compare(struct PhoneEntry **A,struct PhoneEntry **B)
  555. {
  556.         /* Has entry A been selected? */
  557.  
  558.     if((*A) -> Count == -1)
  559.     {
  560.             /* If entry B isn't selected either, compare the
  561.              * names lexically, else entry B is supposed
  562.              * to be `smaller' than entry A.
  563.              */
  564.  
  565.         if((*B) -> Count == -1)
  566.             return(Stricmp((*A) -> Name,(*B) -> Name));
  567.         else
  568.             return(1);
  569.     }
  570.     else
  571.     {
  572.             /* If entry B isn't selected, entry A is supposed
  573.              * to be `smaller' than entry B, else return
  574.              * the difference between both entries.
  575.              */
  576.  
  577.         if((*B) -> Count == -1)
  578.             return(-1);
  579.         else
  580.             return((*A) -> Count - (*B) -> Count);
  581.     }
  582. }
  583.  
  584.     /* SortPhoneEntries():
  585.      *
  586.      *    Sorts the current phone list array in ascending order.
  587.      */
  588.  
  589. VOID
  590. SortPhoneEntries()
  591. {
  592.     qsort(Phonebook,NumPhoneEntries,sizeof(struct PhoneEntry *),Compare);
  593. }
  594.  
  595.     /* FreeTimeDateNode(struct TimeDateNode *Node):
  596.      *
  597.      *    Free the memory allocated for a TimeDateNode and
  598.      *    the associated data table.
  599.      */
  600.  
  601. VOID __regargs
  602. FreeTimeDateNode(struct TimeDateNode *Node)
  603. {
  604.     FreeVec(Node -> Table);
  605.  
  606.     FreeVec(Node);
  607. }
  608.  
  609.     /* FreeTimeDateList(struct List *List):
  610.      *
  611.      *    Free a list of TimeDateNodes.
  612.      */
  613.  
  614. VOID
  615. FreeTimeDateList(struct List *List)
  616. {
  617.     struct Node *Node,*NextNode;
  618.  
  619.     Node = List -> lh_Head;
  620.  
  621.     while(NextNode = Node -> ln_Succ)
  622.     {
  623.         Remove(Node);
  624.  
  625.         FreeTimeDateNode((struct TimeDateNode *)Node);
  626.  
  627.         Node = NextNode;
  628.     }
  629. }
  630.  
  631.     /* CopyTimeDateList(struct List *From,struct List *To,BYTE SkipFirst):
  632.      *
  633.      *    Copies the TimeDateNode list from one location into
  634.      *    another.
  635.      */
  636.  
  637. VOID
  638. CopyTimeDateList(struct List *From,struct List *To,BYTE SkipFirst)
  639. {
  640.     struct TimeDateNode *FromNode,*ToNode;
  641.  
  642.     FromNode = (struct TimeDateNode *)From -> lh_Head;
  643.  
  644.     if(SkipFirst)
  645.         FromNode = (struct TimeDateNode *)FromNode -> VanillaNode . ln_Succ;
  646.  
  647.     while(FromNode -> VanillaNode . ln_Succ)
  648.     {
  649.         if(ToNode = (struct TimeDateNode *)AllocVec(sizeof(struct TimeDateNode),MEMF_ANY))
  650.         {
  651.             CopyMem(FromNode,ToNode,sizeof(struct TimeDateNode));
  652.  
  653.             ToNode -> VanillaNode . ln_Name = ToNode -> Buffer;
  654.  
  655.             if(ToNode -> Table = (struct TimeDate *)AllocVec(sizeof(struct TimeDate) * FromNode -> Table[0] . Count,MEMF_ANY))
  656.             {
  657.                 CopyMem(FromNode -> Table,ToNode -> Table,sizeof(struct TimeDate) * FromNode -> Table[0] . Count);
  658.  
  659.                 AddTail(To,&ToNode -> VanillaNode);
  660.             }
  661.             else
  662.                 FreeVec(ToNode);
  663.         }
  664.  
  665.         FromNode = (struct TimeDateNode *)FromNode -> VanillaNode . ln_Succ;
  666.     }
  667. }
  668.  
  669.     /* AdaptTimeDateNode(struct TimeDateNode *Node):
  670.      *
  671.      *    Adapt the title and comment of a TimeDateNode.
  672.      */
  673.  
  674. VOID
  675. AdaptTimeDateNode(struct TimeDateNode *Node)
  676. {
  677.     UBYTE *Comment = Node -> Comment[0] ? Node -> Comment : LocaleString(MSG_TERMPHONE_NO_COMMENT_TXT);
  678.  
  679.     if(Node -> Month == -1)
  680.     {
  681.         if(Node -> Day == -1)
  682.             strcpy(Node -> Buffer,LocaleString(MSG_TERMPHONE_STANDARD_SETTINGS_TXT));
  683.         else
  684.             SPrintf(Node -> Buffer,LocaleString(MSG_TERMPHONE_DAYS_TXT),Comment);
  685.     }
  686.     else
  687.         SPrintf(Node -> Buffer,"%2ld %s » %s",Node -> Day,LocaleString(MSG_TERMPHONE_JAN_TXT + Node -> Month),Comment);
  688. }
  689.  
  690.     /* TimeCompare(struct TimeDate *A,struct TimeDate *B):
  691.      *
  692.      *    Comparison routine required by SortTimeTable().
  693.      */
  694.  
  695. STATIC LONG __stdargs
  696. TimeCompare(struct TimeDate *A,struct TimeDate *B)
  697. {
  698.     return(((LONG)A -> Time) - ((LONG)B -> Time));
  699. }
  700.  
  701.     /* SortTimeTable(struct TimeDateNode *Node):
  702.      *
  703.      *    Sort the time table associated with a
  704.      *    TimeDateNode in ascending order.
  705.      */
  706.  
  707. VOID
  708. SortTimeTable(struct TimeDateNode *Node)
  709. {
  710.     qsort(Node -> Table,Node -> Table[0] . Count,sizeof(struct TimeDate),TimeCompare);
  711. }
  712.  
  713.     /* BuildTimeList(struct TimeDateNode *Node):
  714.      *
  715.      *    Build a read-to-display time table list from a TimeDateNode.
  716.      */
  717.  
  718. struct List *
  719. BuildTimeList(struct TimeDateNode *Node)
  720. {
  721.     struct List *List;
  722.  
  723.     if(List = (struct List *)AllocVec(sizeof(struct List) + Node -> Table[0] . Count * sizeof(struct TimeNode),MEMF_ANY|MEMF_CLEAR))
  724.     {
  725.         struct TimeNode    *Time = (struct TimeNode *)(List + 1);
  726.         LONG         i;
  727.  
  728.         NewList(List);
  729.  
  730.         for(i = 0 ; i < Node -> Table[0] . Count ; i++)
  731.         {
  732.             Time[i] . VanillaNode . ln_Name    = Time[i] . Name;
  733.             Time[i] . Time            = Node -> Table[i] . Time;
  734.  
  735.             SPrintf(Time[i] . Name,"%2ld:%ld0",Time[i] . Time / 6,Time[i] . Time % 6);
  736.  
  737.             AddTail(List,&Time[i]);
  738.         }
  739.     }
  740.  
  741.     return(List);
  742. }
  743.  
  744.     /* ResizeTimeDateNode(struct TimeDateNode *Node,LONG Count,UBYTE Time):
  745.      *
  746.      *    Resize the time table associated with a TimeDateNode.
  747.      */
  748.  
  749. BYTE
  750. ResizeTimeDateNode(struct TimeDateNode *Node,LONG Count,UBYTE Time)
  751. {
  752.     if(Count != Node -> Table[0] . Count)
  753.     {
  754.         struct TimeDate *Table;
  755.  
  756.         if(Table = (struct TimeDate *)AllocVec(sizeof(struct TimeDate) * Count,MEMF_ANY|MEMF_CLEAR))
  757.         {
  758.             LONG i;
  759.  
  760.             CopyMem(Node -> Table,Table,sizeof(struct TimeDate) * Count);
  761.  
  762.             if(Count > Node -> Table[0] . Count)
  763.             {
  764.                 for(i = Node -> Table[0] . Count ; i < Count ; i++)
  765.                 {
  766.                     CopyMem(&Node -> Table[0],&Table[i],sizeof(struct TimeDate));
  767.  
  768.                     Table[i] . Time = Time;
  769.                 }
  770.             }
  771.  
  772.             for(i = 0 ; i < Count ; i++)
  773.                 Table[i] . Count = Count;
  774.  
  775.             FreeVec(Node -> Table);
  776.  
  777.             Node -> Table = Table;
  778.  
  779.             return(TRUE);
  780.         }
  781.         else
  782.             return(FALSE);
  783.     }
  784.     else
  785.         return(TRUE);
  786. }
  787.  
  788.     /* DeleteTimeDateNode(struct TimeDateNode *Node,LONG Index):
  789.      *
  790.      *    Delete a single timetable entry from a TimeDateNode.
  791.      */
  792.  
  793. BYTE
  794. DeleteTimeDateNode(struct TimeDateNode *Node,LONG Index)
  795. {
  796.     struct TimeDate    *Table;
  797.     LONG         Count = Node -> Table[0] . Count - 1;
  798.  
  799.     if(Table = (struct TimeDate *)AllocVec(sizeof(struct TimeDate) * Count,MEMF_ANY|MEMF_CLEAR))
  800.     {
  801.         LONG i,j;
  802.  
  803.         for(i = j = 0 ; i < Node -> Table[0] . Count ; i++)
  804.         {
  805.             if(i != Index)
  806.             {
  807.                 CopyMem(&Node -> Table[i],&Table[j],sizeof(struct TimeDate));
  808.  
  809.                 Table[j++] . Count = Count;
  810.             }
  811.         }
  812.  
  813.         FreeVec(Node -> Table);
  814.  
  815.         Node -> Table = Table;
  816.  
  817.         return(TRUE);
  818.     }
  819.     else
  820.         return(FALSE);
  821. }
  822.  
  823.     /* CreateTimeDateNode(BYTE Month,BYTE Day,UBYTE *Comment,LONG Count):
  824.      *
  825.      *    Create a new TimeDateNode including time table entries.
  826.      */
  827.  
  828. struct TimeDateNode *
  829. CreateTimeDateNode(BYTE Month,BYTE Day,UBYTE *Comment,LONG Count)
  830. {
  831.     struct TimeDateNode *Node;
  832.  
  833.     if(Node = (struct TimeDateNode *)AllocVec(sizeof(struct TimeDateNode),MEMF_ANY|MEMF_CLEAR))
  834.     {
  835.         if(Node -> Table = (struct TimeDate *)AllocVec(sizeof(struct TimeDate) * Count,MEMF_ANY|MEMF_CLEAR))
  836.         {
  837.             Node -> VanillaNode . ln_Name            = Node -> Buffer;
  838.  
  839.             Node -> Month                    = Month;
  840.             Node -> Day                    = Day;
  841.  
  842.             Node -> Table[0] . PayPerUnit[DT_FIRST_UNIT]    = 23;
  843.             Node -> Table[0] . SecPerUnit[DT_FIRST_UNIT]    =  6 * 60;
  844.             Node -> Table[0] . PayPerUnit[DT_NEXT_UNIT]    = 23;
  845.             Node -> Table[0] . SecPerUnit[DT_NEXT_UNIT]    =  6 * 60;
  846.             Node -> Table[0] . Time                = DT_GET_TIME( 8,0);
  847.             Node -> Table[0] . Count            = Count;
  848.  
  849.             if(Count > 1)
  850.             {
  851.                 Node -> Table[1] . PayPerUnit[DT_FIRST_UNIT]    = 23;
  852.                 Node -> Table[1] . SecPerUnit[DT_FIRST_UNIT]    = 12 * 60;
  853.                 Node -> Table[1] . PayPerUnit[DT_NEXT_UNIT]    = 23;
  854.                 Node -> Table[1] . SecPerUnit[DT_NEXT_UNIT]    = 12 * 60;
  855.                 Node -> Table[1] . Time                = DT_GET_TIME(18,0);
  856.                 Node -> Table[1] . Count            = Count;
  857.             }
  858.  
  859.             strcpy(Node -> Comment,Comment);
  860.  
  861.             AdaptTimeDateNode(Node);
  862.  
  863.             return(Node);
  864.         }
  865.         else
  866.             FreeVec(Node);
  867.     }
  868.  
  869.     return(NULL);
  870. }
  871.  
  872.     /* RemPhoneEntry(LONG Num):
  873.      *
  874.      *    Remove a given entry from the phone book.
  875.      */
  876.  
  877. VOID
  878. RemPhoneEntry(LONG Num)
  879. {
  880.     struct PhoneEntry    *Entry;
  881.     LONG             i;
  882.  
  883.     Entry = Phonebook[Num];
  884.  
  885.     for(i = Num ; i < NumPhoneEntries ; i++)
  886.         Phonebook[i] = Phonebook[i + 1];
  887.  
  888.     Phonebook[NumPhoneEntries--] = NULL;
  889.  
  890.     FreeTimeDateList((struct List *)&Entry -> TimeDateList);
  891.  
  892.     FreeVec(Entry);
  893. }
  894.  
  895.     /* NewPhoneEntry():
  896.      *
  897.      *    Create a new phone book entry with default values and
  898.      *    add it to the array. Expand the phone book if necessary.
  899.      */
  900.  
  901. BYTE
  902. NewPhoneEntry()
  903. {
  904.     struct PhoneEntry    **PrivatePhonebook;
  905.     LONG             PrivatePhoneSize;
  906.     LONG             i;
  907.  
  908.         /* The phone book is filled `to the brim', so let's expand
  909.          * it.
  910.          */
  911.  
  912.     if(NumPhoneEntries + 1 > PhoneSize)
  913.     {
  914.             /* Allocate another phone book. */
  915.  
  916.         if(PrivatePhonebook = CreatePhonebook(PhoneSize + 1,&PrivatePhoneSize,FALSE))
  917.         {
  918.                 /* Copy the data. */
  919.  
  920.             if(Phonebook && PhoneSize)
  921.             {
  922.                 for(i = 0 ; i < PhoneSize ; i++)
  923.                     PrivatePhonebook[i] = Phonebook[i];
  924.  
  925.                     /* Remove the old phonebook. */
  926.  
  927.                 DeletePhonebook(Phonebook,PhoneSize,FALSE);
  928.             }
  929.  
  930.                 /* Assign the new pointers. */
  931.  
  932.             Phonebook = PrivatePhonebook;
  933.             PhoneSize = PrivatePhoneSize;
  934.         }
  935.         else
  936.             return(FALSE);
  937.     }
  938.  
  939.         /* Allocate another entry and add it to the phone book. */
  940.  
  941.     if(Phonebook[NumPhoneEntries] = (struct PhoneEntry *)AllocVec(sizeof(struct PhoneEntry),MEMF_ANY|MEMF_CLEAR))
  942.     {
  943.         struct TimeDateNode *TimeDateNode;
  944.  
  945.         strcpy(Phonebook[NumPhoneEntries] -> Name,LocaleString(MSG_TERMPHONE_UNUSED_ENTRY_TXT));
  946.  
  947.         CopyMem(&Config,&Phonebook[NumPhoneEntries] -> Config,sizeof(struct Configuration));
  948.  
  949.         Phonebook[NumPhoneEntries] -> Count = -1;
  950.  
  951.         NewList((struct List *)&Phonebook[NumPhoneEntries] -> TimeDateList);
  952.  
  953.         if(TimeDateNode = CreateTimeDateNode(-1,-1,"",2))
  954.             AddTail((struct List *)&Phonebook[NumPhoneEntries] -> TimeDateList,&TimeDateNode -> VanillaNode);
  955.  
  956.         NumPhoneEntries++;
  957.  
  958.         return(TRUE);
  959.     }
  960.  
  961.     return(FALSE);
  962. }
  963.  
  964.     /* CreatePhonebook(LONG Size,LONG *AllocSize,BYTE CreateEntries):
  965.      *
  966.      *    Create a new phone entry array (so-called phone book).
  967.      */
  968.  
  969. struct PhoneEntry **
  970. CreatePhonebook(LONG Size,LONG *AllocSize,BYTE CreateEntries)
  971. {
  972.     struct PhoneEntry **PhoneEntry = NULL;
  973.  
  974.     if(Size)
  975.     {
  976.             /* Round the number of phone entries to a
  977.              * multiple of eight.
  978.              */
  979.  
  980.         *AllocSize = (((Size + 7) >> 3) << 3);
  981.  
  982.             /* Create the list of pointers. */
  983.  
  984.         if(PhoneEntry = (struct PhoneEntry **)AllocVec(*AllocSize * sizeof(struct PhoneEntry *),MEMF_ANY|MEMF_CLEAR))
  985.         {
  986.                 /* And create some entries if necessary. */
  987.  
  988.             if(CreateEntries)
  989.             {
  990.                 LONG i;
  991.  
  992.                 for(i = 0 ; i < Size ; i++)
  993.                 {
  994.                     if(!(PhoneEntry[i] = (struct PhoneEntry *)AllocVec(sizeof(struct PhoneEntry),MEMF_ANY|MEMF_CLEAR)))
  995.                     {
  996.                         LONG j;
  997.  
  998.                         for(j = 0 ; j < i ; j++)
  999.                             FreeVec(PhoneEntry[j]);
  1000.  
  1001.                         FreeVec(PhoneEntry);
  1002.  
  1003.                         return(NULL);
  1004.                     }
  1005.                     else
  1006.                         NewList((struct List *)&PhoneEntry[i] -> TimeDateList);
  1007.                 }
  1008.             }
  1009.         }
  1010.     }
  1011.  
  1012.     return(PhoneEntry);
  1013. }
  1014.  
  1015.     /* DeletePhonebook(struct PhoneEntry **PhoneBook,LONG Size,BYTE FreeEntries):
  1016.      *
  1017.      *    Deallocates a given phone book and its entries if necessary.
  1018.      */
  1019.  
  1020. VOID
  1021. DeletePhonebook(struct PhoneEntry **Phonebook,LONG Size,BYTE FreeEntries)
  1022. {
  1023.     if(FreeEntries)
  1024.     {
  1025.         LONG i;
  1026.  
  1027.         for(i = 0 ; i < Size ; i++)
  1028.         {
  1029.             if(Phonebook[i])
  1030.             {
  1031.                 FreeTimeDateList((struct List *)&Phonebook[i] -> TimeDateList);
  1032.  
  1033.                 FreeVec(Phonebook[i]);
  1034.             }
  1035.         }
  1036.     }
  1037.  
  1038.     FreeVec(Phonebook);
  1039. }
  1040.  
  1041.     /* SavePhonebook(UBYTE *Name):
  1042.      *
  1043.      *    Save the current phone book to a disk file.
  1044.      */
  1045.  
  1046. BYTE
  1047. SavePhonebook(UBYTE *Name)
  1048. {
  1049.     struct IFFHandle    *Handle;
  1050.     BYTE             Success = FALSE;
  1051.  
  1052.     if(Phonebook && NumPhoneEntries)
  1053.     {
  1054.         if(Handle = (struct IFFHandle *)AllocIFF())
  1055.         {
  1056.             if(Handle -> iff_Stream = Open(Name,MODE_NEWFILE))
  1057.             {
  1058.                 InitIFFasDOS(Handle);
  1059.  
  1060.                 if(!OpenIFF(Handle,IFFF_WRITE))
  1061.                 {
  1062.                     if(!PushChunk(Handle,'TERM',ID_CAT,IFFSIZE_UNKNOWN))
  1063.                     {
  1064.                         if(!PushChunk(Handle,'TERM',ID_FORM,IFFSIZE_UNKNOWN))
  1065.                         {
  1066.                             if(!PushChunk(Handle,0,'VERS',IFFSIZE_UNKNOWN))
  1067.                             {
  1068.                                 struct TermInfo TermInfo;
  1069.  
  1070.                                 TermInfo . Version    = TermVersion;
  1071.                                 TermInfo . Revision    = TermRevision;
  1072.  
  1073.                                 if(WriteChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
  1074.                                 {
  1075.                                     if(PopChunk(Handle))
  1076.                                         Success = FALSE;
  1077.                                     else
  1078.                                     {
  1079.                                         UBYTE *TempBuffer = NULL;
  1080.  
  1081.                                         if(PhonePasswordUsed)
  1082.                                         {
  1083.                                             if(!PushChunk(Handle,0,'PSWD',20))
  1084.                                             {
  1085.                                                 Success = TRUE;
  1086.  
  1087.                                                 if(WriteChunkBytes(Handle,PhonePassword,20) != 20)
  1088.                                                     Success = FALSE;
  1089.  
  1090.                                                 if(PopChunk(Handle))
  1091.                                                     Success = FALSE;
  1092.  
  1093.                                                 if(Success)
  1094.                                                 {
  1095.                                                     if(!(TempBuffer = AllocVec(RAWSIZE,MEMF_ANY)))
  1096.                                                         Success = FALSE;
  1097.                                                 }
  1098.                                             }
  1099.                                         }
  1100.                                         else
  1101.                                             Success = TRUE;
  1102.  
  1103.                                         if(Success)
  1104.                                         {
  1105.                                             Success = FALSE;
  1106.  
  1107.                                             if(!PushChunk(Handle,0,'DIAL',IFFSIZE_UNKNOWN))
  1108.                                             {
  1109.                                                 if(WriteChunkBytes(Handle,&NumPhoneEntries,sizeof(LONG)) == sizeof(LONG))
  1110.                                                 {
  1111.                                                     if(PopChunk(Handle))
  1112.                                                         Success = FALSE;
  1113.                                                     else
  1114.                                                     {
  1115.                                                         if(PopChunk(Handle))
  1116.                                                             Success = FALSE;
  1117.                                                         else
  1118.                                                         {
  1119.                                                             LONG i;
  1120.  
  1121.                                                             for(i = 0 ; i < NumPhoneEntries ; i++)
  1122.                                                             {
  1123.                                                                 if(!PushChunk(Handle,'TERM',ID_FORM,IFFSIZE_UNKNOWN))
  1124.                                                                 {
  1125.                                                                     if(!PushChunk(Handle,0,'PREF',IFFSIZE_UNKNOWN))
  1126.                                                                     {
  1127.                                                                         if(TempBuffer)
  1128.                                                                         {
  1129.                                                                             Encrypt((UBYTE *)Phonebook[i] -> Name,RAWSIZE,TempBuffer,PhonePassword,20,TRUE);
  1130.  
  1131.                                                                             if(WriteChunkBytes(Handle,TempBuffer,RAWSIZE) != RAWSIZE)
  1132.                                                                             {
  1133.                                                                                 Success = FALSE;
  1134.  
  1135.                                                                                 break;
  1136.                                                                             }
  1137.                                                                             else
  1138.                                                                                 Success = TRUE;
  1139.                                                                         }
  1140.                                                                         else
  1141.                                                                         {
  1142.                                                                             if(WriteChunkBytes(Handle,Phonebook[i] -> Name,RAWSIZE) != RAWSIZE)
  1143.                                                                             {
  1144.                                                                                 Success = FALSE;
  1145.  
  1146.                                                                                 break;
  1147.                                                                             }
  1148.                                                                             else
  1149.                                                                                 Success = TRUE;
  1150.                                                                         }
  1151.  
  1152.                                                                         if(PopChunk(Handle))
  1153.                                                                         {
  1154.                                                                             Success = FALSE;
  1155.  
  1156.                                                                             break;
  1157.                                                                         }
  1158.                                                                     }
  1159.  
  1160.                                                                     if(Success)
  1161.                                                                     {
  1162.                                                                         struct TimeDateNode *TimeDateNode;
  1163.  
  1164.                                                                         TimeDateNode = (struct TimeDateNode *)Phonebook[i] -> TimeDateList . mlh_Head;
  1165.  
  1166.                                                                         while(TimeDateNode -> VanillaNode . ln_Succ)
  1167.                                                                         {
  1168.                                                                             if(!PushChunk(Handle,0,'DATE',IFFSIZE_UNKNOWN))
  1169.                                                                             {
  1170.                                                                                 if(WriteChunkBytes(Handle,TimeDateNode -> Comment,DATEHEADERSIZE) != DATEHEADERSIZE)
  1171.                                                                                 {
  1172.                                                                                     Success = FALSE;
  1173.  
  1174.                                                                                     break;
  1175.                                                                                 }
  1176.                                                                                 else
  1177.                                                                                 {
  1178.                                                                                     if(WriteChunkBytes(Handle,TimeDateNode -> Table,TimeDateNode -> Table[0] . Count * sizeof(struct TimeDate)) != TimeDateNode -> Table[0] . Count * sizeof(struct TimeDate))
  1179.                                                                                     {
  1180.                                                                                         Success = FALSE;
  1181.  
  1182.                                                                                         break;
  1183.                                                                                     }
  1184.                                                                                 }
  1185.  
  1186.                                                                                 if(PopChunk(Handle))
  1187.                                                                                 {
  1188.                                                                                     Success = FALSE;
  1189.  
  1190.                                                                                     break;
  1191.                                                                                 }
  1192.  
  1193.                                                                                 TimeDateNode = (struct TimeDateNode *)TimeDateNode -> VanillaNode . ln_Succ;
  1194.                                                                             }
  1195.                                                                         }
  1196.                                                                     }
  1197.  
  1198.                                                                     if(PopChunk(Handle))
  1199.                                                                     {
  1200.                                                                         Success = FALSE;
  1201.  
  1202.                                                                         break;
  1203.                                                                     }
  1204.                                                                 }
  1205.                                                             }
  1206.                                                         }
  1207.                                                     }
  1208.                                                 }
  1209.                                             }
  1210.  
  1211.                                             if(TempBuffer)
  1212.                                                 FreeVec(TempBuffer);
  1213.                                         }
  1214.                                     }
  1215.                                 }
  1216.                             }
  1217.                         }
  1218.  
  1219.                         if(PopChunk(Handle))
  1220.                             Success = FALSE;
  1221.                     }
  1222.  
  1223.                     CloseIFF(Handle);
  1224.                 }
  1225.  
  1226.                 Close(Handle -> iff_Stream);
  1227.             }
  1228.  
  1229.             FreeIFF(Handle);
  1230.         }
  1231.  
  1232.         if(Success)
  1233.             SetProtection(Name,FIBF_EXECUTE);
  1234.         else
  1235.             DeleteFile(Name);
  1236.     }
  1237.  
  1238.     return(Success);
  1239. }
  1240.  
  1241.     /* OldLoadPhonebook(UBYTE *Name):
  1242.      *
  1243.      *    Restore a phone book from a disk file (old version).
  1244.      */
  1245.  
  1246. STATIC BYTE __regargs
  1247. OldLoadPhonebook(UBYTE *Name)
  1248. {
  1249.     struct PhoneEntry    **PrivatePhonebook;
  1250.     LONG             PrivatePhoneSize;
  1251.     LONG             Size,i;
  1252.     struct IFFHandle    *Handle;
  1253.     BYTE             Success = FALSE;
  1254.     struct StoredProperty    *Prop;
  1255.     struct TermInfo        *TermInfo;
  1256.  
  1257.     if(Handle = AllocIFF())
  1258.     {
  1259.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  1260.         {
  1261.             InitIFFasDOS(Handle);
  1262.  
  1263.             if(!OpenIFF(Handle,IFFF_READ))
  1264.             {
  1265.                 if(!PropChunks(Handle,&VersionProps[0],1))
  1266.                 {
  1267.                     if(!StopChunk(Handle,'TERM','DIAL'))
  1268.                     {
  1269.                         if(!ParseIFF(Handle,IFFPARSE_SCAN))
  1270.                         {
  1271.                             if(Prop = FindProp(Handle,'TERM','VERS'))
  1272.                             {
  1273.                                 TermInfo = (struct TermInfo *)Prop -> sp_Data;
  1274.  
  1275.                                 if(TermInfo -> Version == 1 && TermInfo -> Revision >= 6)
  1276.                                 {
  1277.                                     if(ReadChunkRecords(Handle,&Size,sizeof(LONG),1))
  1278.                                     {
  1279.                                         if(Size)
  1280.                                         {
  1281.                                             if(PrivatePhonebook = CreatePhonebook(Size,&PrivatePhoneSize,TRUE))
  1282.                                             {
  1283.                                                 struct ContextNode    *Chunk;
  1284.                                                 LONG             ItemSize;
  1285.                                                 struct TimeDateNode    *TimeDateNode;
  1286.  
  1287.                                                 Chunk = CurrentChunk(Handle);
  1288.  
  1289.                                                 ItemSize = Chunk -> cn_Size / Size;
  1290.  
  1291.                                                 for(i = 0 ; i < Size ; i++)
  1292.                                                 {
  1293.                                                     SetPrefToDefaults(&PrivatePhonebook[i] -> Config,NULL);
  1294.  
  1295.                                                     if(ReadChunkRecords(Handle,PrivatePhonebook[i] -> Name,ItemSize,1))
  1296.                                                     {
  1297.                                                         UpdatePrefs(&PrivatePhonebook[i] -> Config);
  1298.  
  1299.                                                         PrivatePhonebook[i] -> Count = -1;
  1300.  
  1301.                                                         if(strlen(PrivatePhonebook[i] -> Password) > 19)
  1302.                                                         {
  1303.                                                             PrivatePhonebook[i] -> Password[19] = 0;
  1304.                                                             PrivatePhonebook[i] -> UserName[ 0] = 0;
  1305.                                                         }
  1306.  
  1307.                                                         if(TimeDateNode = CreateTimeDateNode(-1,-1,"",2))
  1308.                                                             AddTail((struct List *)&PrivatePhonebook[i] -> TimeDateList,&TimeDateNode -> VanillaNode);
  1309.                                                     }
  1310.                                                     else
  1311.                                                     {
  1312.                                                         if(i)
  1313.                                                             Size = i - 1;
  1314.                                                         else
  1315.                                                             Size = 0;
  1316.  
  1317.                                                         break;
  1318.                                                     }
  1319.                                                 }
  1320.  
  1321.                                                 if(Size)
  1322.                                                 {
  1323.                                                     if(Phonebook)
  1324.                                                         DeletePhonebook(Phonebook,PhoneSize,TRUE);
  1325.  
  1326.                                                     Phonebook = PrivatePhonebook;
  1327.                                                     PhoneSize = PrivatePhoneSize;
  1328.  
  1329.                                                     NumPhoneEntries = Size;
  1330.  
  1331.                                                     Success = TRUE;
  1332.                                                 }
  1333.                                                 else
  1334.                                                 {
  1335.                                                     DeletePhonebook(PrivatePhonebook,PrivatePhoneSize,TRUE);
  1336.  
  1337.                                                     Success = FALSE;
  1338.                                                 }
  1339.  
  1340.                                                 FreeDialList();
  1341.                                             }
  1342.                                         }
  1343.                                     }
  1344.                                 }
  1345.                             }
  1346.                         }
  1347.                     }
  1348.                 }
  1349.  
  1350.                 CloseIFF(Handle);
  1351.             }
  1352.  
  1353.             Close(Handle -> iff_Stream);
  1354.         }
  1355.  
  1356.         FreeIFF(Handle);
  1357.     }
  1358.  
  1359.     return(Success);
  1360. }
  1361.  
  1362.     /* LoadPhonebook(UBYTE *Name):
  1363.      *
  1364.      *    Restore a phone book from a disk file.
  1365.      */
  1366.  
  1367. BYTE
  1368. LoadPhonebook(UBYTE *Name)
  1369. {
  1370.     STATIC ULONG Stops[2 * 7] =
  1371.     {
  1372.         'TERM','VERS',
  1373.         'TERM','DIAL',
  1374.         'TERM','PREF',
  1375.         'TERM','DATE',
  1376.         'TERM','TIME',
  1377.         'TERM','PASS',
  1378.         'TERM','PSWD'
  1379.     };
  1380.  
  1381.     struct PhoneEntry    **PrivatePhonebook;
  1382.     LONG             PrivatePhoneSize = 0;
  1383.     LONG             Size = 0,i,j,Last = -1;
  1384.     struct IFFHandle    *Handle;
  1385.     BYTE             Success = FALSE;
  1386.     struct ContextNode    *Chunk;
  1387.     BYTE             UseOld        = FALSE,
  1388.                  LastHadTime    = TRUE,
  1389.                  HadPassword    = FALSE,
  1390.                  NewStyle    = TRUE;
  1391.     struct TimeDateNode    *TimeDateNode;
  1392.  
  1393.     if(Handle = AllocIFF())
  1394.     {
  1395.         if(Handle -> iff_Stream = Open(Name,MODE_OLDFILE))
  1396.         {
  1397.             InitIFFasDOS(Handle);
  1398.  
  1399.             if(!OpenIFF(Handle,IFFF_READ))
  1400.             {
  1401.                 if(!StopChunks(Handle,&Stops[0],7))
  1402.                 {
  1403.                     while(!ParseIFF(Handle,IFFPARSE_SCAN))
  1404.                     {
  1405.                         Chunk = CurrentChunk(Handle);
  1406.  
  1407.                         if(Chunk -> cn_ID == 'VERS')
  1408.                         {
  1409.                             struct TermInfo TermInfo;
  1410.  
  1411.                             if(ReadChunkBytes(Handle,&TermInfo,sizeof(struct TermInfo)) == sizeof(struct TermInfo))
  1412.                             {
  1413.                                 if(TermInfo . Version == 1 && TermInfo . Revision < 9)
  1414.                                 {
  1415.                                     UseOld = TRUE;
  1416.  
  1417.                                     break;
  1418.                                 }
  1419.  
  1420.                                 if((TermInfo . Version > TermVersion) || (TermInfo . Version == TermVersion && TermInfo . Revision > TermRevision) || (TermInfo . Version == 1 && TermInfo . Revision < 6))
  1421.                                     break;
  1422.                             }
  1423.                             else
  1424.                                 break;
  1425.                         }
  1426.  
  1427.                         if(Chunk -> cn_ID == 'PASS')
  1428.                         {
  1429.                             UBYTE DummyBuffer[20];
  1430.  
  1431.                             HadPassword = TRUE;
  1432.  
  1433.                             if(ReadChunkBytes(Handle,DummyBuffer,20) == 20)
  1434.                             {
  1435.                                 if(PhonePasswordUsed)
  1436.                                 {
  1437.                                     if(!memcmp(PhonePassword,DummyBuffer,20))
  1438.                                         continue;
  1439.                                 }
  1440.  
  1441.                                 memset(SharedBuffer,0,20);
  1442.  
  1443.                                 if(CryptPanel(SharedBuffer))
  1444.                                 {
  1445.                                     UBYTE AnotherBuffer[20];
  1446.  
  1447.                                     Encrypt(SharedBuffer,20,AnotherBuffer,SharedBuffer,20,NewStyle = FALSE);
  1448.  
  1449.                                     if(!memcmp(DummyBuffer,AnotherBuffer,20))
  1450.                                     {
  1451.                                         memcpy(PhonePassword,DummyBuffer,20);
  1452.  
  1453.                                         PhonePasswordUsed = TRUE;
  1454.  
  1455.                                         continue;
  1456.                                     }
  1457.                                     else
  1458.                                     {
  1459.                                         MyEasyRequest(Window,LocaleString(MSG_TERMPHONE_WRONG_PASSWORD_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Name);
  1460.  
  1461.                                         break;
  1462.                                     }
  1463.                                 }
  1464.                                 else
  1465.                                     break;
  1466.                             }
  1467.                             else
  1468.                                 break;
  1469.                         }
  1470.  
  1471.                         if(Chunk -> cn_ID == 'PSWD')
  1472.                         {
  1473.                             UBYTE DummyBuffer[20];
  1474.  
  1475.                             HadPassword = TRUE;
  1476.  
  1477.                             if(ReadChunkBytes(Handle,DummyBuffer,20) == 20)
  1478.                             {
  1479.                                 if(PhonePasswordUsed)
  1480.                                 {
  1481.                                     if(!memcmp(PhonePassword,DummyBuffer,20))
  1482.                                         continue;
  1483.                                 }
  1484.  
  1485.                                 memset(SharedBuffer,0,20);
  1486.  
  1487.                                 if(CryptPanel(SharedBuffer))
  1488.                                 {
  1489.                                     UBYTE AnotherBuffer[20];
  1490.  
  1491.                                     Encrypt(SharedBuffer,20,AnotherBuffer,SharedBuffer,strlen(SharedBuffer),NewStyle = TRUE);
  1492.  
  1493.                                     if(!memcmp(DummyBuffer,AnotherBuffer,20))
  1494.                                     {
  1495.                                         memcpy(PhonePassword,DummyBuffer,20);
  1496.  
  1497.                                         PhonePasswordUsed = TRUE;
  1498.  
  1499.                                         continue;
  1500.                                     }
  1501.                                     else
  1502.                                     {
  1503.                                         MyEasyRequest(Window,LocaleString(MSG_TERMPHONE_WRONG_PASSWORD_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Name);
  1504.  
  1505.                                         break;
  1506.                                     }
  1507.                                 }
  1508.                                 else
  1509.                                     break;
  1510.                             }
  1511.                             else
  1512.                                 break;
  1513.                         }
  1514.  
  1515.                         if(Chunk -> cn_ID == 'DIAL')
  1516.                         {
  1517.                             if(ReadChunkBytes(Handle,&Size,sizeof(LONG)) == sizeof(LONG))
  1518.                             {
  1519.                                 i = 0;
  1520.  
  1521.                                 if(!(PrivatePhonebook = CreatePhonebook(Size,&PrivatePhoneSize,TRUE)))
  1522.                                     break;
  1523.                             }
  1524.                             else
  1525.                                 break;
  1526.                         }
  1527.  
  1528.                         if(Chunk -> cn_ID == 'PREF')
  1529.                         {
  1530.                             if(Last != -1)
  1531.                             {
  1532.                                 if(strlen(PrivatePhonebook[i] -> Password) > 19)
  1533.                                 {
  1534.                                     PrivatePhonebook[i] -> Password[19] = 0;
  1535.                                     PrivatePhonebook[i] -> UserName[ 0] = 0;
  1536.                                 }
  1537.  
  1538.                                 if(!LastHadTime)
  1539.                                 {
  1540.                                     if(TimeDateNode = CreateTimeDateNode(-1,-1,"",2))
  1541.                                         AddTail((struct List *)&PrivatePhonebook[Last] -> TimeDateList,&TimeDateNode -> VanillaNode);
  1542.                                 }
  1543.                             }
  1544.  
  1545.                             if(Size && i < Size)
  1546.                             {
  1547.                                 WORD LastSize = sizeof(struct PhoneEntry);
  1548.  
  1549.                                 PhonePasswordUsed = HadPassword;
  1550.  
  1551.                                 if(Chunk -> cn_Size < LastSize)
  1552.                                     LastSize = Chunk -> cn_Size;
  1553.  
  1554.                                 SetPrefToDefaults(&PrivatePhonebook[i] -> Config,NULL);
  1555.  
  1556.                                 if(ReadChunkBytes(Handle,PrivatePhonebook[i] -> Name,LastSize) == LastSize)
  1557.                                 {
  1558.                                     UpdatePrefs(&PrivatePhonebook[i] -> Config);
  1559.  
  1560.                                     if(PhonePasswordUsed)
  1561.                                         Decrypt((UBYTE *)PrivatePhonebook[i] -> Name,LastSize,PrivatePhonebook[i] -> Name,PhonePassword,20,NewStyle);
  1562.  
  1563.                                     Last = i;
  1564.  
  1565.                                     PrivatePhonebook[i] -> Count = -1;
  1566.  
  1567.                                     i++;
  1568.  
  1569.                                     LastHadTime = FALSE;
  1570.                                 }
  1571.                                 else
  1572.                                 {
  1573.                                     if(i)
  1574.                                         Size = i - 1;
  1575.                                     else
  1576.                                         Size = 0;
  1577.  
  1578.                                     break;
  1579.                                 }
  1580.                             }
  1581.                         }
  1582.  
  1583.                         if(Chunk -> cn_ID == 'TIME')
  1584.                         {
  1585.                             if(Last != -1)
  1586.                             {
  1587.                                 struct TimeDateOld TimeDateOld;
  1588.  
  1589.                                 for(j = 0 ; j < Chunk -> cn_Size / sizeof(struct TimeDateOld) ; j++)
  1590.                                 {
  1591.                                     if(TimeDateNode = CreateTimeDateNode(-1,-1,"",2))
  1592.                                     {
  1593.                                         if(ReadChunkBytes(Handle,&TimeDateOld,sizeof(struct TimeDateOld)) == sizeof(struct TimeDateOld))
  1594.                                         {
  1595.                                             if(PhonePasswordUsed)
  1596.                                                 Decrypt((UBYTE *)&TimeDateOld,sizeof(struct TimeDateOld),(UBYTE *)&TimeDateOld,PhonePassword,20,NewStyle);
  1597.  
  1598.                                             strcpy(TimeDateNode -> Comment,TimeDateOld . Comment);
  1599.  
  1600.                                             TimeDateNode -> Month    = TimeDateOld . Month;
  1601.                                             TimeDateNode -> Day    = TimeDateOld . Day;
  1602.  
  1603.                                             TimeDateNode -> Table[0] . PayPerUnit[0]    = TimeDateOld . PayPerUnit[0];
  1604.                                             TimeDateNode -> Table[0] . SecPerUnit[0]    = TimeDateOld . SecPerUnit[0];
  1605.                                             TimeDateNode -> Table[0] . PayPerUnit[1]    = TimeDateOld . PayPerUnit[0];
  1606.                                             TimeDateNode -> Table[0] . SecPerUnit[1]    = TimeDateOld . SecPerUnit[0];
  1607.                                             TimeDateNode -> Table[0] . Time            = TimeDateOld . TimeOfDay[0];
  1608.  
  1609.                                             TimeDateNode -> Table[1] . PayPerUnit[0]    = TimeDateOld . PayPerUnit[1];
  1610.                                             TimeDateNode -> Table[1] . SecPerUnit[0]    = TimeDateOld . SecPerUnit[1];
  1611.                                             TimeDateNode -> Table[1] . PayPerUnit[1]    = TimeDateOld . PayPerUnit[1];
  1612.                                             TimeDateNode -> Table[1] . SecPerUnit[1]    = TimeDateOld . SecPerUnit[1];
  1613.                                             TimeDateNode -> Table[1] . Time            = TimeDateOld . TimeOfDay[1];
  1614.  
  1615.                                             AdaptTimeDateNode(TimeDateNode);
  1616.  
  1617.                                             AddTail((struct List *)&PrivatePhonebook[Last] -> TimeDateList,&TimeDateNode -> VanillaNode);
  1618.  
  1619.                                             LastHadTime = TRUE;
  1620.                                         }
  1621.                                     }
  1622.                                 }
  1623.                             }
  1624.                         }
  1625.  
  1626.                         if(Chunk -> cn_ID == 'DATE')
  1627.                         {
  1628.                             if(Last != -1)
  1629.                             {
  1630.                                 WORD Count = (Chunk -> cn_Size - DATEHEADERSIZE) / sizeof(struct TimeDate);
  1631.  
  1632.                                 if(TimeDateNode = CreateTimeDateNode(-1,-1,"",Count))
  1633.                                 {
  1634.                                     if(ReadChunkBytes(Handle,TimeDateNode -> Comment,DATEHEADERSIZE) == DATEHEADERSIZE)
  1635.                                     {
  1636.                                         if(ReadChunkBytes(Handle,TimeDateNode -> Table,sizeof(struct TimeDate) * Count) == sizeof(struct TimeDate) * Count)
  1637.                                         {
  1638.                                             AdaptTimeDateNode(TimeDateNode);
  1639.  
  1640.                                             AddTail((struct List *)&PrivatePhonebook[Last] -> TimeDateList,&TimeDateNode -> VanillaNode);
  1641.  
  1642.                                             LastHadTime = TRUE;
  1643.                                         }
  1644.                                         else
  1645.                                             FreeTimeDateNode(TimeDateNode);
  1646.                                     }
  1647.                                     else
  1648.                                         FreeTimeDateNode(TimeDateNode);
  1649.                                 }
  1650.                             }
  1651.                         }
  1652.                     }
  1653.  
  1654.                     if(Size)
  1655.                     {
  1656.                         if(!LastHadTime && Last != -1)
  1657.                         {
  1658.                             if(TimeDateNode = CreateTimeDateNode(-1,-1,"",2))
  1659.                                 AddTail((struct List *)&PrivatePhonebook[Last] -> TimeDateList,&TimeDateNode -> VanillaNode);
  1660.                         }
  1661.  
  1662.                         if(Phonebook)
  1663.                             DeletePhonebook(Phonebook,PhoneSize,TRUE);
  1664.  
  1665.                         Phonebook = PrivatePhonebook;
  1666.                         PhoneSize = PrivatePhoneSize;
  1667.  
  1668.                         NumPhoneEntries = Size;
  1669.  
  1670.                         Success = TRUE;
  1671.                     }
  1672.                     else
  1673.                     {
  1674.                         if(PrivatePhoneSize)
  1675.                         {
  1676.                             DeletePhonebook(PrivatePhonebook,PrivatePhoneSize,TRUE);
  1677.  
  1678.                             Success = FALSE;
  1679.                         }
  1680.                     }
  1681.  
  1682.                     FreeDialList();
  1683.                 }
  1684.  
  1685.                 CloseIFF(Handle);
  1686.             }
  1687.  
  1688.             Close(Handle -> iff_Stream);
  1689.         }
  1690.  
  1691.         FreeIFF(Handle);
  1692.     }
  1693.  
  1694.     if(UseOld)
  1695.         Success = OldLoadPhonebook(Name);
  1696.  
  1697.     return(Success);
  1698. }
  1699.