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

  1. /*
  2. **    termPhone.c
  3. **
  4. **    Phonebook support routines
  5. **
  6. **    Copyright © 1990-1994 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* RemoveDialEntry(LONG Entry):
  13.      *
  14.      *    Remove a phone book entry from the dial list.
  15.      */
  16.  
  17. VOID __regargs
  18. RemoveDialEntry(LONG Entry)
  19. {
  20.     LONG Count = Phonebook[Entry] -> Count,i;
  21.  
  22.     for(i = 0 ; i < NumPhoneEntries ; i++)
  23.     {
  24.         if(Phonebook[i] -> Count > Count)
  25.             SPrintf(Phonebook[i] -> Node -> LocalName,"%3ld - %s",Phonebook[i] -> Count--,Phonebook[i] -> Header -> Name);
  26.     }
  27.  
  28.     Phonebook[Entry] -> Count = -1;
  29.  
  30.     SPrintf(Phonebook[Entry] -> Node -> LocalName,"      %s",Phonebook[Entry] -> Header -> Name);
  31. }
  32.  
  33.     /* RemoveDialNode(struct PhoneNode *Node):
  34.      *
  35.      *    Remove a node from the dialing list.
  36.      */
  37.  
  38. VOID __regargs
  39. RemoveDialNode(struct PhoneNode *Node)
  40. {
  41.     if(Node)
  42.     {
  43.             /* If it's got a name it was built in the phone book panel,
  44.              * else the ARexx interface has linked it into the list.
  45.              */
  46.     
  47.         if(Node -> VanillaNode . ln_Name && Node -> VanillaNode . ln_Name[0])
  48.         {
  49.             LONG Count = Node -> Entry -> Count,i;
  50.     
  51.                 /* Adjust all entries. */
  52.     
  53.             for(i = 0 ; i < NumPhoneEntries ; i++)
  54.             {
  55.                 if(Phonebook[i] -> Count > Count)
  56.                     Phonebook[i] -> Count--;
  57.             }
  58.     
  59.                 /* Can the index count. */
  60.     
  61.             Node -> Entry -> Count = -1;
  62.         }
  63.     }
  64. }
  65.  
  66.     /* SortToList(struct PhoneNode *PhoneNode):
  67.      *
  68.      *    Add a node to the dial list.
  69.      */
  70.  
  71. VOID __regargs
  72. SortToList(struct PhoneNode *PhoneNode)
  73. {
  74.         /* No dial list prepared? Let's create one! */
  75.  
  76.     if(!DialList)
  77.     {
  78.         if(DialList = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY))
  79.             NewList(DialList);
  80.     }
  81.  
  82.         /* Do we have a dial list to mangle? */
  83.  
  84.     if(DialList)
  85.     {
  86.         struct PhoneNode *NewNode;
  87.  
  88.             /* Create a new node to be added to the dial list. */
  89.  
  90.         if(NewNode = (struct PhoneNode *)AllocVecPooled(sizeof(struct PhoneNode),MEMF_ANY | MEMF_CLEAR))
  91.         {
  92.             struct PhoneNode *Node = (struct PhoneNode *)DialList -> lh_Head;
  93.  
  94.                 /* Take care of the name and the corresponding phone book entry. */
  95.  
  96.             NewNode -> VanillaNode . ln_Name    = NewNode -> LocalName;
  97.             NewNode -> Entry            = PhoneNode -> Entry;
  98.  
  99.             strcpy(NewNode -> LocalName,PhoneNode -> LocalName);
  100.  
  101.                 /* Install back-link. */
  102.  
  103.             NewNode -> Entry -> Node = NewNode;
  104.  
  105.                 /* Sort the node into the list. */
  106.  
  107.             while(Node -> VanillaNode . ln_Succ)
  108.             {
  109.                 if(Node -> Entry -> Count > NewNode -> Entry -> Count)
  110.                 {
  111.                     if(Node == (struct PhoneNode *)DialList -> lh_Head)
  112.                         AddHead(DialList,&NewNode -> VanillaNode);
  113.                     else
  114.                         Insert(DialList,&NewNode -> VanillaNode,Node -> VanillaNode . ln_Pred);
  115.  
  116.                     return;
  117.                 }
  118.  
  119.                 Node = (struct PhoneNode *)Node -> VanillaNode . ln_Succ;
  120.             }
  121.  
  122.             AddTail(DialList,&NewNode -> VanillaNode);
  123.         }
  124.     }
  125. }
  126.  
  127.     /* FreeDialList(BYTE ClearAll):
  128.      *
  129.      *    Release the contents of the dial list.
  130.      */
  131.  
  132. VOID __regargs
  133. FreeDialList(BYTE ClearAll)
  134. {
  135.     if(DialList)
  136.     {
  137.         struct PhoneNode *SubNode,*NextNode;
  138.  
  139.         for(SubNode = (struct PhoneNode *)DialList -> lh_Head ; NextNode = (struct PhoneNode *)SubNode -> VanillaNode . ln_Succ ; SubNode = NextNode)
  140.         {
  141.             if(ClearAll || !SubNode -> VanillaNode . ln_Name || !SubNode -> VanillaNode . ln_Name[0])
  142.                 FreeVecPooled(SubNode);
  143.         }
  144.  
  145.         FreeVecPooled(DialList);
  146.  
  147.         DialList = NULL;
  148.     }
  149. }
  150.  
  151.     /* CreatePhoneList():
  152.      *
  153.      *    Turn the array of pointers to phonebook entries into
  154.      *    a linked standard Amiga List (gadtools needs this).
  155.      */
  156.  
  157. struct List *
  158. CreatePhoneList()
  159. {
  160.     struct List *PhoneList;
  161.  
  162.     if(Phonebook && NumPhoneEntries)
  163.     {
  164.         struct PhoneNode *PhoneNode;
  165.  
  166.         if(PhoneList = (struct List *)AllocVecPooled(sizeof(struct List) + NumPhoneEntries * sizeof(struct PhoneNode),MEMF_ANY | MEMF_CLEAR))
  167.         {
  168.             LONG i;
  169.  
  170.             NewList(PhoneList);
  171.  
  172.             PhoneNode = (struct PhoneNode *)(PhoneList + 1);
  173.  
  174.             for(i = 0 ; i < NumPhoneEntries ; i++)
  175.             {
  176.                 if(Phonebook[i] -> Count != -1)
  177.                     SPrintf(PhoneNode[i] . LocalName,"%3ld - %s",Phonebook[i] -> Count + 1,Phonebook[i] -> Header -> Name);
  178.                 else
  179.                     SPrintf(PhoneNode[i] . LocalName,"      %s",Phonebook[i] -> Header -> Name);
  180.  
  181.                 PhoneNode[i] . VanillaNode . ln_Name = PhoneNode[i] . LocalName;
  182.  
  183.                 Phonebook[i] -> Node = &PhoneNode[i];
  184.  
  185.                 PhoneNode[i] . Entry = Phonebook[i];
  186.  
  187.                 AddTail(PhoneList,&PhoneNode[i]);
  188.             }
  189.  
  190.             return(PhoneList);
  191.         }
  192.     }
  193.     else
  194.     {
  195.         if(PhoneList = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY))
  196.         {
  197.             NewList(PhoneList);
  198.  
  199.             return(PhoneList);
  200.         }
  201.     }
  202.  
  203.     return(NULL);
  204. }
  205.  
  206.     /* DeletePhoneList(struct List *PhoneList):
  207.      *
  208.      *    Delete the entries listed in the Amiga List
  209.      *    created by the routine above.
  210.      */
  211.  
  212. VOID __regargs
  213. DeletePhoneList(struct List *PhoneList)
  214. {
  215.     if(PhoneList)
  216.         FreeVecPooled(PhoneList);
  217. }
  218.  
  219.     /* Compare(struct PhoneEntry **A,struct PhoneEntry **B):
  220.      *
  221.      *    Comparison subroutine required by the QuickSort
  222.      *    call below.
  223.      */
  224.  
  225. STATIC int __stdargs
  226. Compare(struct PhoneEntry **A,struct PhoneEntry **B)
  227. {
  228.         /* Has entry A been selected? */
  229.  
  230.     if((*A) -> Count == -1)
  231.     {
  232.             /* If entry B isn't selected either, compare the
  233.              * names lexically, else entry B is supposed
  234.              * to be `smaller' than entry A.
  235.              */
  236.  
  237.         if((*B) -> Count == -1)
  238.             return(Stricmp((*A) -> Header -> Name,(*B) -> Header -> Name));
  239.         else
  240.             return(1);
  241.     }
  242.     else
  243.     {
  244.             /* If entry B isn't selected, entry A is supposed
  245.              * to be `smaller' than entry B, else return
  246.              * the difference between both entries.
  247.              */
  248.  
  249.         if((*B) -> Count == -1)
  250.             return(-1);
  251.         else
  252.             return((*A) -> Count - (*B) -> Count);
  253.     }
  254. }
  255.  
  256.     /* SortPhoneEntries():
  257.      *
  258.      *    Sorts the current phone list array in ascending order.
  259.      */
  260.  
  261. VOID
  262. SortPhoneEntries()
  263. {
  264.     qsort((APTR)Phonebook,NumPhoneEntries,sizeof(struct PhoneEntry *),Compare);
  265. }
  266.  
  267.     /* FreeTimeDateNode(struct TimeDateNode *Node):
  268.      *
  269.      *    Free the memory allocated for a TimeDateNode and
  270.      *    the associated data table.
  271.      */
  272.  
  273. VOID __regargs
  274. FreeTimeDateNode(struct TimeDateNode *Node)
  275. {
  276.     FreeVecPooled(Node -> Table);
  277.  
  278.     FreeVecPooled(Node);
  279. }
  280.  
  281.     /* FreeTimeDateList(struct List *List):
  282.      *
  283.      *    Free a list of TimeDateNodes.
  284.      */
  285.  
  286. VOID __regargs
  287. FreeTimeDateList(struct List *List)
  288. {
  289.     struct Node *Node = List -> lh_Head,*NextNode;
  290.  
  291.     while(NextNode = Node -> ln_Succ)
  292.     {
  293.         Remove(Node);
  294.  
  295.         FreeTimeDateNode((struct TimeDateNode *)Node);
  296.  
  297.         Node = NextNode;
  298.     }
  299. }
  300.  
  301.     /* CopyTimeDateList(struct List *From,struct List *To,BYTE SkipFirst):
  302.      *
  303.      *    Copies the TimeDateNode list from one location into
  304.      *    another.
  305.      */
  306.  
  307. VOID __regargs
  308. CopyTimeDateList(struct List *From,struct List *To,BYTE SkipFirst)
  309. {
  310.     struct TimeDateNode *FromNode,*ToNode;
  311.  
  312.     FromNode = (struct TimeDateNode *)From -> lh_Head;
  313.  
  314.     if(SkipFirst)
  315.         FromNode = (struct TimeDateNode *)FromNode -> VanillaNode . ln_Succ;
  316.  
  317.     while(FromNode -> VanillaNode . ln_Succ)
  318.     {
  319.         if(ToNode = (struct TimeDateNode *)AllocVecPooled(sizeof(struct TimeDateNode),MEMF_ANY))
  320.         {
  321.             CopyMem(FromNode,ToNode,sizeof(struct TimeDateNode));
  322.  
  323.             ToNode -> VanillaNode . ln_Name = ToNode -> Buffer;
  324.  
  325.             if(ToNode -> Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * FromNode -> Table[0] . Count,MEMF_ANY))
  326.             {
  327.                 CopyMem(FromNode -> Table,ToNode -> Table,sizeof(struct TimeDate) * FromNode -> Table[0] . Count);
  328.  
  329.                 AddTail(To,&ToNode -> VanillaNode);
  330.             }
  331.             else
  332.                 FreeVecPooled(ToNode);
  333.         }
  334.  
  335.         FromNode = (struct TimeDateNode *)FromNode -> VanillaNode . ln_Succ;
  336.     }
  337. }
  338.  
  339.     /* AdaptTimeDateNode(struct TimeDateNode *Node):
  340.      *
  341.      *    Adapt the title and comment of a TimeDateNode.
  342.      */
  343.  
  344. VOID __regargs
  345. AdaptTimeDateNode(struct TimeDateNode *Node)
  346. {
  347.     STRPTR Comment = Node -> Header . Comment[0] ? Node -> Header . Comment : LocaleString(MSG_TERMPHONE_NO_COMMENT_TXT);
  348.  
  349.     if(Node -> Header . Month == -1)
  350.     {
  351.         if(Node -> Header . Day == -1)
  352.             strcpy(Node -> Buffer,LocaleString(MSG_TERMPHONE_STANDARD_SETTINGS_TXT));
  353.         else
  354.             SPrintf(Node -> Buffer,LocaleString(MSG_TERMPHONE_DAYS_TXT),Comment);
  355.     }
  356.     else
  357.         SPrintf(Node -> Buffer,"%2ld %s » %s",Node -> Header . Day,LocaleString(MSG_TERMPHONE_JAN_TXT + Node -> Header . Month),Comment);
  358. }
  359.  
  360.     /* TimeCompare(struct TimeDate *A,struct TimeDate *B):
  361.      *
  362.      *    Comparison routine required by SortTimeTable().
  363.      */
  364.  
  365. STATIC int __stdargs
  366. TimeCompare(struct TimeDate *A,struct TimeDate *B)
  367. {
  368.     return(((LONG)A -> Time) - ((LONG)B -> Time));
  369. }
  370.  
  371.     /* SortTimeTable(struct TimeDateNode *Node):
  372.      *
  373.      *    Sort the time table associated with a
  374.      *    TimeDateNode in ascending order.
  375.      */
  376.  
  377. VOID __regargs
  378. SortTimeTable(struct TimeDateNode *Node)
  379. {
  380.     qsort((APTR)Node -> Table,Node -> Table[0] . Count,sizeof(struct TimeDate),TimeCompare);
  381. }
  382.  
  383.     /* BuildTimeList(struct TimeDateNode *Node):
  384.      *
  385.      *    Build a read-to-display time table list from a TimeDateNode.
  386.      */
  387.  
  388. struct List * __regargs
  389. BuildTimeList(struct TimeDateNode *Node)
  390. {
  391.     struct List *List;
  392.  
  393.     if(List = (struct List *)AllocVecPooled(sizeof(struct List) + Node -> Table[0] . Count * sizeof(struct TimeNode),MEMF_ANY | MEMF_CLEAR))
  394.     {
  395.         struct TimeNode    *Time = (struct TimeNode *)(List + 1);
  396.         UBYTE         LocalBuffer[40];
  397.         LONG         i;
  398.  
  399.         NewList(List);
  400.  
  401.         for(i = 0 ; i < Node -> Table[0] . Count ; i++)
  402.         {
  403.             Time[i] . VanillaNode . ln_Name    = Time[i] . Name;
  404.             Time[i] . Time            = Node -> Table[i] . Time;
  405.  
  406.             FormatTime(LocalBuffer,Time[i] . Time / 6,(Time[i] . Time % 6) * 10,-1);
  407.  
  408.             LocalBuffer[19] = 0;
  409.  
  410.             strcpy(Time[i] . Name,LocalBuffer);
  411.  
  412.             AddTail(List,&Time[i]);
  413.         }
  414.     }
  415.  
  416.     return(List);
  417. }
  418.  
  419.     /* ResizeTimeDateNode(struct TimeDateNode *Node,LONG Count,UBYTE Time):
  420.      *
  421.      *    Resize the time table associated with a TimeDateNode.
  422.      */
  423.  
  424. BYTE __regargs
  425. ResizeTimeDateNode(struct TimeDateNode *Node,LONG Count,UBYTE Time)
  426. {
  427.     if(Count != Node -> Table[0] . Count)
  428.     {
  429.         struct TimeDate *Table;
  430.  
  431.         if(Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  432.         {
  433.             LONG i;
  434.  
  435.             CopyMem(Node -> Table,Table,sizeof(struct TimeDate) * Count);
  436.  
  437.             if(Count > Node -> Table[0] . Count)
  438.             {
  439.                 for(i = Node -> Table[0] . Count ; i < Count ; i++)
  440.                 {
  441.                     CopyMem(&Node -> Table[0],&Table[i],sizeof(struct TimeDate));
  442.  
  443.                     Table[i] . Time = Time;
  444.                 }
  445.             }
  446.  
  447.             for(i = 0 ; i < Count ; i++)
  448.                 Table[i] . Count = Count;
  449.  
  450.             FreeVecPooled(Node -> Table);
  451.  
  452.             Node -> Table = Table;
  453.  
  454.             return(TRUE);
  455.         }
  456.         else
  457.             return(FALSE);
  458.     }
  459.     else
  460.         return(TRUE);
  461. }
  462.  
  463.     /* DeleteTimeDateNode(struct TimeDateNode *Node,LONG Index):
  464.      *
  465.      *    Delete a single timetable entry from a TimeDateNode.
  466.      */
  467.  
  468. BYTE __regargs
  469. DeleteTimeDateNode(struct TimeDateNode *Node,LONG Index)
  470. {
  471.     struct TimeDate    *Table;
  472.     LONG         Count = Node -> Table[0] . Count - 1;
  473.  
  474.     if(Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  475.     {
  476.         LONG i,j;
  477.  
  478.         for(i = j = 0 ; i < Node -> Table[0] . Count ; i++)
  479.         {
  480.             if(i != Index)
  481.             {
  482.                 CopyMem(&Node -> Table[i],&Table[j],sizeof(struct TimeDate));
  483.  
  484.                 Table[j++] . Count = Count;
  485.             }
  486.         }
  487.  
  488.         FreeVecPooled(Node -> Table);
  489.  
  490.         Node -> Table = Table;
  491.  
  492.         return(TRUE);
  493.     }
  494.     else
  495.         return(FALSE);
  496. }
  497.  
  498.     /* CreateTimeDateNode(BYTE Month,BYTE Day,STRPTR Comment,LONG Count):
  499.      *
  500.      *    Create a new TimeDateNode including time table entries.
  501.      */
  502.  
  503. struct TimeDateNode * __regargs
  504. CreateTimeDateNode(BYTE Month,BYTE Day,STRPTR Comment,LONG Count)
  505. {
  506.     struct TimeDateNode *Node;
  507.  
  508.     if(Node = (struct TimeDateNode *)AllocVecPooled(sizeof(struct TimeDateNode),MEMF_ANY | MEMF_CLEAR))
  509.     {
  510.         if(Node -> Table = (struct TimeDate *)AllocVecPooled(sizeof(struct TimeDate) * Count,MEMF_ANY | MEMF_CLEAR))
  511.         {
  512.             Node -> VanillaNode . ln_Name            = Node -> Buffer;
  513.  
  514.             Node -> Header . Month                = Month;
  515.             Node -> Header . Day                = Day;
  516. /*
  517.             Node -> Table[0] . PayPerUnit[DT_FIRST_UNIT]    = 23;
  518.             Node -> Table[0] . SecPerUnit[DT_FIRST_UNIT]    =  6 * 60;
  519.             Node -> Table[0] . PayPerUnit[DT_NEXT_UNIT]    = 23;
  520.             Node -> Table[0] . SecPerUnit[DT_NEXT_UNIT]    =  6 * 60;
  521. */
  522.             Node -> Table[0] . PayPerUnit[DT_FIRST_UNIT]    = 0;
  523.             Node -> Table[0] . SecPerUnit[DT_FIRST_UNIT]    = 0;
  524.             Node -> Table[0] . PayPerUnit[DT_NEXT_UNIT]    = 0;
  525.             Node -> Table[0] . SecPerUnit[DT_NEXT_UNIT]    = 0;
  526.             Node -> Table[0] . Time                = DT_GET_TIME( 8,0);
  527.             Node -> Table[0] . Count            = Count;
  528.  
  529.             if(Count > 1)
  530.             {
  531. /*
  532.                 Node -> Table[1] . PayPerUnit[DT_FIRST_UNIT]    = 23;
  533.                 Node -> Table[1] . SecPerUnit[DT_FIRST_UNIT]    = 12 * 60;
  534.                 Node -> Table[1] . PayPerUnit[DT_NEXT_UNIT]    = 23;
  535.                 Node -> Table[1] . SecPerUnit[DT_NEXT_UNIT]    = 12 * 60;
  536. */
  537.                 Node -> Table[1] . PayPerUnit[DT_FIRST_UNIT]    = 0;
  538.                 Node -> Table[1] . SecPerUnit[DT_FIRST_UNIT]    = 0;
  539.                 Node -> Table[1] . PayPerUnit[DT_NEXT_UNIT]    = 0;
  540.                 Node -> Table[1] . SecPerUnit[DT_NEXT_UNIT]    = 0;
  541.                 Node -> Table[1] . Time                = DT_GET_TIME(18,0);
  542.                 Node -> Table[1] . Count            = Count;
  543.             }
  544.  
  545.             strcpy(Node -> Header . Comment,Comment);
  546.  
  547.             AdaptTimeDateNode(Node);
  548.  
  549.             return(Node);
  550.         }
  551.         else
  552.             FreeVecPooled(Node);
  553.     }
  554.  
  555.     return(NULL);
  556. }
  557.  
  558.     /* RemPhoneEntry(LONG Num):
  559.      *
  560.      *    Remove a given entry from the phone book.
  561.      */
  562.  
  563. VOID __regargs
  564. RemPhoneEntry(LONG Num)
  565. {
  566.     struct PhoneEntry    *Entry;
  567.     LONG             i;
  568.  
  569.     Entry = Phonebook[Num];
  570.  
  571.     for(i = Num ; i < NumPhoneEntries ; i++)
  572.         Phonebook[i] = Phonebook[i + 1];
  573.  
  574.     Phonebook[NumPhoneEntries--] = NULL;
  575.  
  576.     if(Entry -> Config)
  577.         DeleteConfiguration(Entry -> Config);
  578.  
  579.     FreeTimeDateList((struct List *)&Entry -> TimeDateList);
  580.  
  581.     FreeVecPooled(Entry);
  582. }
  583.  
  584.     /* NewPhoneEntry():
  585.      *
  586.      *    Create a new phone book entry with default values and
  587.      *    add it to the array. Expand the phone book if necessary.
  588.      */
  589.  
  590. BYTE
  591. NewPhoneEntry()
  592. {
  593.     struct PhoneEntry    **PrivatePhonebook;
  594.     LONG             PrivatePhoneSize,i;
  595.  
  596.         /* The phone book is filled `to the brim', so let's expand
  597.          * it.
  598.          */
  599.  
  600.     if(NumPhoneEntries + 1 > PhoneSize)
  601.     {
  602.             /* Allocate another phone book. */
  603.  
  604.         if(PrivatePhonebook = CreatePhonebook(PhoneSize + 1,&PrivatePhoneSize,FALSE))
  605.         {
  606.                 /* Copy the data. */
  607.  
  608.             if(Phonebook && PhoneSize)
  609.             {
  610.                 for(i = 0 ; i < PhoneSize ; i++)
  611.                     PrivatePhonebook[i] = Phonebook[i];
  612.  
  613.                     /* Remove the old phonebook. */
  614.  
  615.                 DeletePhonebook(Phonebook,PhoneSize,FALSE);
  616.             }
  617.  
  618.                 /* Assign the new pointers. */
  619.  
  620.             Phonebook = PrivatePhonebook;
  621.             PhoneSize = PrivatePhoneSize;
  622.         }
  623.         else
  624.             return(FALSE);
  625.     }
  626.  
  627.         /* Allocate another entry and add it to the phone book. */
  628.  
  629.     if(Phonebook[NumPhoneEntries] = (struct PhoneEntry *)AllocVecPooled(sizeof(struct PhoneEntry) + sizeof(struct PhoneHeader),MEMF_ANY | MEMF_CLEAR))
  630.     {
  631.         if(Phonebook[NumPhoneEntries] -> Config = CreateConfiguration(FALSE))
  632.         {
  633.             struct TimeDateNode *TimeDateNode;
  634.  
  635.             Phonebook[NumPhoneEntries] -> Header = (struct PhoneHeader *)(Phonebook[NumPhoneEntries] + 1);
  636.  
  637.             strcpy(Phonebook[NumPhoneEntries] -> Header -> Name,LocaleString(MSG_TERMPHONE_UNUSED_ENTRY_TXT));
  638.  
  639.             Phonebook[NumPhoneEntries] -> Count = -1;
  640.  
  641.             NewList((struct List *)&Phonebook[NumPhoneEntries] -> TimeDateList);
  642.  
  643.             if(TimeDateNode = CreateTimeDateNode(-1,-1,"",2))
  644.                 AddTail((struct List *)&Phonebook[NumPhoneEntries] -> TimeDateList,&TimeDateNode -> VanillaNode);
  645.  
  646.             NumPhoneEntries++;
  647.  
  648.             return(TRUE);
  649.         }
  650.  
  651.         FreeVecPooled(Phonebook[NumPhoneEntries]);
  652.  
  653.         Phonebook[NumPhoneEntries] = NULL;
  654.     }
  655.  
  656.     return(FALSE);
  657. }
  658.  
  659.     /* CreatePhonebook(LONG Size,LONG *AllocSize,BYTE CreateEntries):
  660.      *
  661.      *    Create a new phone entry array (so-called phone book).
  662.      */
  663.  
  664. struct PhoneEntry ** __regargs
  665. CreatePhonebook(LONG Size,LONG *AllocSize,BYTE CreateEntries)
  666. {
  667.     struct PhoneEntry **PhoneEntry = NULL;
  668.  
  669.     if(Size)
  670.     {
  671.             /* Round the number of phone entries to a
  672.              * multiple of eight.
  673.              */
  674.  
  675.         *AllocSize = (Size + 7) & ~7;
  676.  
  677.             /* Create the list of pointers. */
  678.  
  679.         if(PhoneEntry = (struct PhoneEntry **)AllocVecPooled(*AllocSize * sizeof(struct PhoneEntry *),MEMF_ANY | MEMF_CLEAR))
  680.         {
  681.                 /* And create some entries if necessary. */
  682.  
  683.             if(CreateEntries)
  684.             {
  685.                 BYTE Success = TRUE;
  686.                 LONG i;
  687.  
  688.                 for(i = 0 ; Success && i < Size ; i++)
  689.                 {
  690.                     if(PhoneEntry[i] = (struct PhoneEntry *)AllocVecPooled(sizeof(struct PhoneEntry) + sizeof(struct PhoneHeader),MEMF_ANY | MEMF_CLEAR))
  691.                     {
  692.                         if(PhoneEntry[i] -> Config = CreateConfiguration(FALSE))
  693.                         {
  694.                             PhoneEntry[i] -> Header = (struct PhoneHeader *)(PhoneEntry[i] + 1);
  695.  
  696.                             NewList((struct List *)&PhoneEntry[i] -> TimeDateList);
  697.                         }
  698.                         else
  699.                             Success = FALSE;
  700.                     }
  701.                     else
  702.                         Success = FALSE;
  703.                 }
  704.  
  705.                 if(!Success)
  706.                 {
  707.                     for(i = 0 ; i < *AllocSize ; i++)
  708.                     {
  709.                         if(PhoneEntry[i])
  710.                         {
  711.                             if(PhoneEntry[i] -> Config)
  712.                                 DeleteConfiguration(PhoneEntry[i] -> Config);
  713.  
  714.                             FreeVecPooled(PhoneEntry[i]);
  715.                         }
  716.                     }
  717.  
  718.                     FreeVecPooled(PhoneEntry);
  719.  
  720.                     return(NULL);
  721.                 }
  722.             }
  723.         }
  724.     }
  725.  
  726.     return(PhoneEntry);
  727. }
  728.  
  729.     /* DeletePhonebook(struct PhoneEntry **PhoneBook,LONG Size,BYTE FreeEntries):
  730.      *
  731.      *    Deallocates a given phone book and its entries if necessary.
  732.      */
  733.  
  734. VOID __regargs
  735. DeletePhonebook(struct PhoneEntry **Phonebook,LONG Size,BYTE FreeEntries)
  736. {
  737.     if(FreeEntries)
  738.     {
  739.         LONG i;
  740.  
  741.         for(i = 0 ; i < Size ; i++)
  742.         {
  743.             if(Phonebook[i])
  744.             {
  745.                 FreeTimeDateList((struct List *)&Phonebook[i] -> TimeDateList);
  746.  
  747.                 if(Phonebook[i] -> Config)
  748.                     DeleteConfiguration(Phonebook[i] -> Config);
  749.  
  750.                 FreeVecPooled(Phonebook[i]);
  751.             }
  752.         }
  753.     }
  754.  
  755.     FreeVecPooled(Phonebook);
  756. }
  757.