home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1999 November / PCONLINE_11_99.ISO / filesbbs / OS2 / MMSRC029.ZIP / mmail-0.29 / interfac / addrbook.cc next >
Encoding:
C/C++ Source or Header  |  1999-08-17  |  7.3 KB  |  412 lines

  1. /*
  2.  * MultiMail offline mail reader
  3.  * address book
  4.  
  5.  Copyright (c) 1996 Kolossvary Tamas <thomas@vma.bme.hu>
  6.  Copyright (c) 1999 William McBrine <wmcbrine@clark.net>
  7.  
  8.  Distributed under the GNU General Public License.
  9.  For details, see the file COPYING in the parent directory. */
  10.  
  11. #include "interfac.h"
  12.  
  13. Person::Person(const char *sname, const char *saddr)
  14. {
  15.     if (saddr && (*saddr == 'I'))
  16.         saddr++;
  17.     netmail_addr = saddr;
  18.     Init(sname);
  19. }
  20.  
  21. Person::Person(const char *sname, net_address &naddr)
  22. {
  23.     netmail_addr = naddr;
  24.     Init(sname);
  25. }
  26.  
  27. void Person::Init(const char *sname)
  28. {
  29.     if (sname) {
  30.         strncpy(name, sname, 44);
  31.         name[44] = '\0';
  32.     }
  33.     next = 0;
  34. }
  35.  
  36. void Person::dump(FILE *fd)
  37. {
  38.     fprintf(fd, (netmail_addr.isInternet ? "%s\nI%s\n\n" :
  39.         "%s\n%s\n\n"), name, (const char *) netmail_addr);
  40. }
  41.  
  42. AddressBook::AddressBook()
  43. {
  44.     NumOfPersons = 0;
  45. }
  46.  
  47. AddressBook::~AddressBook()
  48. {
  49.     DestroyChain();
  50. }
  51.  
  52. void AddressBook::MakeActive(bool NoEnterA)
  53. {
  54.     statetype s = interface->prevactive();
  55.     if (s != address)
  56.         inletter = ((s == letter) || (s == littlearealist)) &&
  57.             !mm.areaList->isReplyArea();
  58.  
  59.     NoEnter = NoEnterA;
  60.  
  61.     list_max_y = LINES - 12;
  62.     list_max_x = COLS - 6;
  63.     top_offset = 2;
  64.  
  65.     borderCol = C_ADDR1;
  66.  
  67.     int xwidth = list_max_x + 2;
  68.     list = new InfoWin(LINES - 6, xwidth, 2, borderCol,
  69.         "Addressbook", C_ADDR2, 6);
  70.  
  71.     int x = xwidth / 3 + 1;
  72.     int y = list_max_y + 2;
  73.  
  74.     list->attrib(C_ADDR2);
  75.     list->put(1, 2,
  76.         "Name                            Netmail address");
  77.  
  78.     list->horizline(y, list_max_x);
  79.  
  80.     list->put(++y, 3, ": Quit addressbook");
  81.     list->put(y, x + 3, ": Add new address");
  82.     list->put(y, x * 2 + 1, ": search / next");
  83.     list->put(++y, 3, ": Kill current address");
  84.     list->put(y, x + 3, ": Edit address");
  85.  
  86.     if (inletter)
  87.         list->put(y, x * 2 + 1,
  88.               ": address from Letter");
  89.  
  90.     list->attrib(C_ADDR1);
  91.     list->put(y, 2, "K");
  92.     list->put(y, x + 2, "E");
  93.  
  94.     if (inletter)
  95.         list->put(y, x * 2, "L");
  96.  
  97.     list->put(--y, 2, "Q");
  98.     list->put(y, x + 2, "A");
  99.     list->put(y, x * 2 - 3, "/, .");
  100.  
  101.     DrawAll();
  102. }
  103.  
  104. void AddressBook::Delete()
  105. {
  106.     delete list;
  107. }
  108.  
  109. bool AddressBook::extrakeys(int key)
  110. {
  111.     bool end = false;
  112.  
  113.     switch (key) {
  114.     case MM_ENTER:
  115.         SetLetterThings();
  116.         break;
  117.     case 'A':
  118.         NewAddress();
  119.         break;
  120.     case 'E':
  121.         ChangeAddress();
  122.         break;
  123.     case KEY_DC:
  124.     case 'K':
  125.         kill();
  126.         break;
  127.     case 'L':
  128.         GetAddress();
  129.     }
  130.     return end;
  131. }
  132.  
  133. void AddressBook::WriteFile()
  134. {
  135.     FILE *fd = fopen(addfname, "wt");
  136.     for (int x = 0; x < NumOfPersons; x++)
  137.         people[x]->dump(fd);
  138.     fclose(fd);
  139. }
  140.  
  141. void AddressBook::kill()
  142. {
  143.     if (highlighted) {
  144.         if (interface->WarningWindow("Remove this address?")) {
  145.             if (active)
  146.                 people[active - 1]->next = highlighted->next;
  147.             else
  148.                 head.next = highlighted->next;
  149.  
  150.             if (position)
  151.                 position--;
  152.  
  153.             NumOfPersons--;
  154.  
  155.             delete highlighted;
  156.             delete[] people;
  157.  
  158.             MakeChain();
  159.             WriteFile();
  160.         }
  161.         Delete();
  162.         MakeActive(NoEnter);
  163.     }
  164. }
  165.  
  166. void AddressBook::SetLetterThings()
  167. {
  168.     if (!NoEnter && highlighted)
  169.         interface->letterwindow.set_Letter_Params(
  170.             highlighted->netmail_addr, highlighted->name);
  171. }
  172.  
  173. void AddressBook::Add(const char *Name, net_address &Address)
  174. {
  175.     if (Address.isSet) {
  176.         bool found = false;
  177.  
  178.         // Dupe check; also positions curr at end of list:
  179.         curr = &head;
  180.         while (curr->next && !found) {
  181.             curr = curr->next;
  182.             found = (curr->netmail_addr == Address) &&
  183.                 !strcasecmp(curr->name, Name);
  184.         }
  185.  
  186.         if (!found) {
  187.             curr->next = new Person(Name, Address);
  188.  
  189.             FILE *fd = fopen(addfname, "at");
  190.             curr->next->dump(fd);
  191.             fclose(fd);
  192.  
  193.             NumOfPersons++;
  194.             delete[] people;
  195.             MakeChain();
  196.  
  197.             active = NumOfPersons;
  198.             Draw();
  199.         } else
  200.             interface->nonFatalError("Already in addressbook");
  201.     } else
  202.         interface->nonFatalError("No address found");
  203. }
  204.  
  205. void AddressBook::GetAddress()
  206. {
  207.     if (inletter)
  208.         Add(mm.letterList->getFrom(),
  209.             interface->letterwindow.PickNetAddr());
  210. }
  211.  
  212. int AddressBook::HeaderLine(ShadowedWin &win, char *buf, int limit,
  213.                 int pos, int color)
  214. {
  215.     int getit = win.getstring(pos, 8, buf, limit, color, color);
  216.     return getit;
  217. }
  218.  
  219. int AddressBook::Edit(Person &p)
  220. {
  221.     char NAME[45], NETADD[72];
  222.  
  223.     const int maxitems = 2;
  224.     int result, current = 0;
  225.     bool end = false;
  226.  
  227.     if (p.netmail_addr.isSet) {
  228.         strcpy(NAME, p.name);
  229.         strcpy(NETADD, p.netmail_addr);
  230.     } else
  231.         NAME[0] = NETADD[0] = '\0';
  232.  
  233.     ShadowedWin add_edit(4, COLS - 2, (LINES >> 1) - 2, C_LETEXT);
  234.  
  235.     add_edit.put(1, 2, "Name:");
  236.     add_edit.put(2, 2, "Addr:");
  237.  
  238.     add_edit.attrib(C_LEGET1);
  239.     add_edit.put(1, 8, NAME);
  240.  
  241.     add_edit.attrib(C_LEGET2);
  242.     add_edit.put(2, 8, NETADD);
  243.  
  244.     add_edit.update();
  245.  
  246.     do {
  247.         result = HeaderLine(add_edit, current ? NETADD : NAME,
  248.             current ? 69 : 44, current + 1,
  249.             current ? C_LEGET2 : C_LEGET1);
  250.  
  251.         switch (result) {
  252.         case 0:
  253.             end = true;
  254.             break;
  255.         case 1:
  256.             current++;
  257.             if (current == maxitems)
  258.                 end = true;
  259.             break;
  260.         case 2:
  261.             if (current > 0)
  262.                 current--;
  263.             break;
  264.         case 3:
  265.             if (current < maxitems - 1)
  266.                 current++;
  267.         }
  268.     } while (!end);
  269.  
  270.     if (result && NAME[0] && NETADD[0]) {
  271.         strcpy(p.name, NAME);
  272.         p.netmail_addr = NETADD;
  273.         if (!p.netmail_addr.isSet)
  274.             result = 0;
  275.     } else
  276.         result = 0;
  277.     return result;
  278. }
  279.  
  280. void AddressBook::NewAddress()
  281. {
  282.     Person p;
  283.  
  284.     p.netmail_addr.isSet = false;
  285.     if (Edit(p))
  286.         Add(p.name, p.netmail_addr);
  287.     interface->redraw();
  288. }
  289.  
  290. void AddressBook::ChangeAddress()
  291. {
  292.     if (highlighted)
  293.         if (Edit(*highlighted))
  294.             WriteFile();
  295.     interface->redraw();
  296. }
  297.  
  298. void AddressBook::oneLine(int i)
  299. {
  300.     int z = position + i;
  301.     curr = (z < NumOfPersons) ? people[z] : 0;
  302.  
  303.     if (z == active)
  304.         highlighted = curr;
  305.  
  306.     char *tmp = list->lineBuf;
  307.     int x = curr ? sprintf(tmp, " %-31s %s", curr->name,
  308.         (const char *) curr->netmail_addr) : 0;
  309.     for (; x < list_max_x; x++)
  310.         tmp[x] = ' ';
  311.     tmp[x] = '\0';
  312.  
  313.     DrawOne(i, C_ADDR3);
  314. }
  315.  
  316. searchret AddressBook::oneSearch(int x, const char *item, int ignore)
  317. {
  318.     const char *s;
  319.  
  320.     ignore = ignore;
  321.  
  322.     if (!(s = searchstr(people[x]->name, item)))
  323.         s = searchstr(people[x]->netmail_addr, item);
  324.     return s ? True : False;
  325. }
  326.  
  327. int AddressBook::NumOfItems()
  328. {
  329.     return NumOfPersons;
  330. }
  331.  
  332. int perscomp(const void *a, const void *b)
  333. {
  334.     return strcasecmp((*((Person **) a))->name,
  335.         (*((Person **) b))->name);
  336. }
  337.  
  338. void AddressBook::ReadFile()
  339. {
  340.     FILE *fd;
  341.     char name[256], nmaddr[256], other[256];
  342.     bool end = false;
  343.  
  344.     if ((fd = fopen(addfname, "rt"))) {
  345.         curr = &head;
  346.         while (!end) {
  347.             do
  348.                 end = !fgets(name, sizeof name, fd);
  349.             while (name[0] == '\n' && !end);
  350.  
  351.             end = !fgets(nmaddr, sizeof nmaddr, fd);
  352.  
  353.             if (!end) {
  354.                 strtok(name, "\n");
  355.                 strtok(nmaddr, "\n");
  356.                 curr->next = new Person(name, nmaddr);
  357.                 curr = curr->next;
  358.                 NumOfPersons++;
  359.             }
  360.  
  361.             do
  362.                 end = !fgets(other, sizeof other, fd);
  363.             while (other[0] != '\n' && !end);
  364.         }
  365.         fclose(fd);
  366.     }
  367.  
  368.     MakeChain();
  369.  
  370.     if (NumOfPersons > 1) {
  371.         qsort(people, NumOfPersons, sizeof(Person *), perscomp);
  372.         ReChain();
  373.     }
  374. }
  375.  
  376.  
  377. void AddressBook::MakeChain()
  378. {
  379.     if (NumOfPersons) {
  380.         people = new Person *[NumOfPersons];
  381.         curr = head.next;
  382.         int c = 0;
  383.         while (curr) {
  384.             people[c++] = curr;
  385.             curr = curr->next;
  386.         }
  387.     } else
  388.         people = 0;
  389. }
  390.  
  391. void AddressBook::ReChain()
  392. {
  393.     head.next = people[0];
  394.     for (int c = 0; c < (NumOfPersons - 1); c++)
  395.         people[c]->next = people[c + 1];
  396.  
  397.     people[NumOfPersons - 1]->next = 0;
  398. }
  399.  
  400. void AddressBook::DestroyChain()
  401. {
  402.     while (NumOfPersons)
  403.         delete people[--NumOfPersons];
  404.     delete[] people;
  405. }
  406.  
  407. void AddressBook::Init()
  408. {
  409.     addfname = mm.resourceObject->get(AddressFile);
  410.     ReadFile();
  411. }
  412.