home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / hl10osrc.lzh / EditLibr / EditCard.cc < prev    next >
Text File  |  1994-04-23  |  13KB  |  499 lines

  1. /* -*- Mode: C -*- */
  2. /* EditCard.cc - Edit an existing card
  3.  * Created by Robert Heller on Wed Dec 11 20:41:43 1991
  4.  *
  5.  * ------------------------------------------------------------------
  6.  * Home Libarian by Deepwoods Software
  7.  * Edit a Librarian Card Catalog file
  8.  * ------------------------------------------------------------------
  9.  * Modification History:
  10.  * ------------------------------------------------------------------
  11.  * Contents:
  12.  * ------------------------------------------------------------------
  13.  * 
  14.  * 
  15.  * Copyright (c) 1991,1992 by Robert heller (D/B/A Deepwoods Software)
  16.  *        All Rights Reserved
  17.  * 
  18.  */
  19.  
  20. #include <stream.h>
  21. #include <vBTree.h>
  22. #include <ctype.h>
  23. #ifdef MESSYDOS
  24. #include <CardRec.h>
  25. #include <ListRec.h>
  26. #else
  27. #include <CardRecord.h>
  28. #include <ListRecord.h>
  29. #endif
  30. #include <Terminal.h>
  31. #ifdef MESSYDOS
  32. #include <CmdScren.h>
  33. #else
  34. #include <CommandScreen.h>
  35. #endif
  36. #include <EditForm.h>
  37. #include "EditDefs.h"
  38. #include "EditGlob.h"
  39.  
  40.  
  41. const BuffSize = 1024;
  42. const DescrSize = 4096;
  43. static Key editkey;
  44. static char Author[BuffSize],Title[BuffSize],Publisher[BuffSize],
  45.         City[BuffSize],Description[DescrSize],SubjList[DescrSize],
  46.         OrigSubjList[DescrSize];
  47. static Card editcard(Book,Author,Title,Publisher,City,Description,0,0);
  48.  
  49. static char* TypeToString(void* f) {CardType ct = *((CardType*)f);return(TypeName(ct));}
  50. static void  StringToType(char* s,void* f){*((CardType*)f) = NameType(s);}
  51. static Card* OrigCard;
  52.  
  53.  
  54. static Boolean streqp(const char* s1,const char* s2)
  55. {
  56.     register char c1,c2;
  57.     do {
  58.         c1 = *s1++;
  59.         if (islower(c1)) c1 = toupper(c1);
  60.         c2 = *s2++;
  61.         if (islower(c2)) c2 = toupper(c2);
  62.         if (c1 != c2) return(false);
  63.     } while (c1 != 0);
  64.     return(true);
  65. }
  66.  
  67. static char* ReadQuotedStringFromBuffer(char* buffer,int buffsize,char* string)
  68. {
  69.     Boolean inquote = false;
  70.  
  71.     if (string == 0 || *string == 0) return((char*)0);
  72.     while (*string != 0 && (inquote || *string != ',')) {
  73.         if (*string == '"') inquote = ~inquote;
  74.         else if (*string == '\\') {
  75.             string++;
  76.             if (buffsize > 0) {
  77.                 *buffer++ = *string;
  78.                 buffsize--;
  79.             }
  80.         } else if (*string >= ' ') {
  81.             if (buffsize > 0) {
  82.                 *buffer++ = *string;
  83.                 buffsize--;
  84.             }
  85.         }
  86.         string++;
  87.     }
  88.     if (*string == ',') string++;
  89.     *buffer = 0;
  90.     return string;
  91. }
  92.  
  93. static char* newelems[500];
  94. void UpdateSubjs(const char* subjs,const char* osubjs,const Key key)
  95. {
  96.     Key subj1;
  97.     Key subj2;
  98.     char* sl1;
  99.     char* sl2;
  100.  
  101.     for (sl1 = (char*)osubjs;(sl1 = ReadQuotedStringFromBuffer((char*)subj1,sizeof(subj1),sl1)) != 0;) {
  102.         Boolean retain = false;
  103.         for (sl2 = (char*)subjs;(sl2 = ReadQuotedStringFromBuffer((char*)subj2,sizeof(subj2),sl2)) != 0;) {
  104.             if (streqp(subj2,subj1)) {
  105.                 retain = true;
  106.                 break;
  107.             }
  108.         }
  109.         if (!retain) {
  110.             CoreItem temp;
  111.             if (Tree->SearchSubj(subj1,&temp)) {
  112.                 ListRecord rec(&temp.data);
  113.                 int nitems = rec.ElementCount();
  114.                 int outitems = 0;
  115.                 for (int i = 0; i < nitems; i++) {
  116.                     if (!streqp(rec[i],key)) {
  117.                         newelems[outitems++] = rec[i];
  118.                     }
  119.                 }
  120.                 if (outitems == 0) Tree->DeleteSubj(subj1);
  121.                 else {
  122.                     ListRecord newrec(outitems,newelems);
  123.                     Record rawrec = newrec;
  124.                     Tree->InsertSubj(subj1,&rawrec);
  125.                 }
  126.             }
  127.         }
  128.     }
  129.     for (sl1 = (char*)subjs;(sl1 = ReadQuotedStringFromBuffer((char*)subj1,sizeof(subj1),sl1)) != 0;) {
  130.         Boolean addnew = true;
  131.         for (sl2 = (char*)osubjs;(sl2 = ReadQuotedStringFromBuffer((char*)subj2,sizeof(subj2),sl2)) != 0;) {
  132.             if (streqp(subj2,subj1)) {
  133.                 addnew = false;
  134.                 break;
  135.             }
  136.         }
  137.         if (addnew) {
  138.             CoreItem temp;
  139.             if (Tree->SearchSubj(subj1,&temp)) {
  140.                 ListRecord rec(&temp.data);
  141.                 int nitems = rec.ElementCount();
  142.                 int outitems = 0;
  143.                 for (int i = 0; i < nitems; i++) {
  144.                     if (!streqp(rec[i],key)) {
  145.                         newelems[outitems++] = rec[i];
  146.                     }
  147.                 }
  148.                 newelems[outitems++] = (char*)key;
  149.                 ListRecord newrec(outitems,newelems);
  150.                 Record rawrec = newrec;
  151.                 Tree->InsertSubj(subj1,&rawrec);
  152.             } else {
  153.                 newelems[0] = (char*)key;
  154.                 ListRecord newrec(1,newelems);
  155.                 Record rawrec = newrec;
  156.                 Tree->InsertSubj(subj1,&rawrec);
  157.             }
  158.         }
  159.     }
  160. }
  161.  
  162. void UpdateAuthor(const char* auth,const char* oauth,const Key key)
  163. {
  164.     Key authkey;
  165.     Key oauthkey;
  166.     strncpy(authkey,auth,KeySize);
  167.     authkey[KeySize-1] = 0;
  168.     strncpy(oauthkey,oauth,KeySize);
  169.     oauthkey[KeySize-1] = 0;
  170.     //cerr << "*** In UpdateAuthor: authkey = '" << authkey << "', oauthkey = '" << oauthkey  << "'\n";
  171.     if (!streqp(authkey,oauthkey)) {
  172.         CoreItem temp;
  173.         //cerr << "Author changed, about to update old author\n";
  174.         if (Tree->SearchAuthor(oauthkey,&temp) &&
  175.             streqp(oauthkey,temp.key)) {
  176.                 //cerr << "Updating old author...\n";
  177.             ListRecord rec(&temp.data);
  178.             int nitems = rec.ElementCount();
  179.             int outitems = 0;
  180.             for (int i = 0; i < nitems; i++) {
  181.                 if (!streqp(rec[i],key)) {
  182.                     newelems[outitems++] = rec[i];
  183.                 }
  184.             }
  185.             if (outitems == 0) Tree->DeleteAuthor(oauthkey);
  186.             else {
  187.                 ListRecord newrec(outitems,newelems);
  188.                 Record rawrec = newrec;
  189.                 Tree->InsertAuthor(oauthkey,&rawrec);
  190.             }
  191.             //cerr << "Old author updated...\n";
  192.         }
  193.         //cerr << "About to fetch new author record\n";
  194.         if (Tree->SearchAuthor(authkey,&temp) &&
  195.             streqp(authkey,temp.key)) {
  196.                 //cerr << "New author record fetched, about to update\n";
  197.             ListRecord rec(&temp.data);
  198.             int nitems = rec.ElementCount();
  199.             int outitems = 0;
  200.             for (int i = 0; i < nitems; i++) {
  201.                 if (!streqp(rec[i],key)) {
  202.                     newelems[outitems++] = rec[i];
  203.                 }
  204.             }
  205.             newelems[outitems++] = (char*)key;
  206.             ListRecord newrec(outitems,newelems);
  207.             Record rawrec = newrec;
  208.             //cerr << "Inserting new record for new author...\n";
  209.             Tree->InsertAuthor(authkey,&rawrec);
  210.         } else if (authkey[0] != 0) {
  211.             //cerr << "Creating new record for new author...\n";
  212.             newelems[0] = (char*)key;
  213.             ListRecord newrec(1,newelems);
  214.             Record rawrec = newrec;
  215.             Tree->InsertAuthor(authkey,&rawrec);
  216.         }
  217.     }
  218. }
  219.  
  220. void UpdateTitle(const char* title,const char* otitle,const Key key)
  221. {
  222.     Key titlekey;
  223.     Key otitlekey;
  224.     strncpy(titlekey,title,KeySize);
  225.     titlekey[KeySize-1] = 0;
  226.     strncpy(otitlekey,otitle,KeySize);
  227.     otitlekey[KeySize-1] = 0;
  228.     //cerr << "*** In UpdateTitle: titlekey = '" << titlekey << "', otitlekey = '" << otitlekey  << "'\n";
  229.     if (!streqp(titlekey,otitlekey)) {
  230.         CoreItem temp;
  231.         if (Tree->SearchTitle(otitlekey,&temp) &&
  232.             streqp(otitlekey,temp.key)) {
  233.             ListRecord rec(&temp.data);
  234.             int nitems = rec.ElementCount();
  235.             int outitems = 0;
  236.             for (int i = 0; i < nitems; i++) {
  237.                 if (!streqp(rec[i],key)) {
  238.                     newelems[outitems++] = rec[i];
  239.                 }
  240.             }
  241.             if (outitems == 0) Tree->DeleteTitle(otitlekey);
  242.             else {
  243.                 ListRecord newrec(outitems,newelems);
  244.                 Record rawrec = newrec;
  245.                 Tree->InsertTitle(otitlekey,&rawrec);
  246.             }
  247.         }
  248.         if (Tree->SearchTitle(titlekey,&temp) &&
  249.             streqp(titlekey,temp.key)) {
  250.             ListRecord rec(&temp.data);
  251.             int nitems = rec.ElementCount();
  252.             int outitems = 0;
  253.             for (int i = 0; i < nitems; i++) {
  254.                 if (!streqp(rec[i],key)) {
  255.                     newelems[outitems++] = rec[i];
  256.                 }
  257.             }
  258.             newelems[outitems++] = (char*)key;
  259.             ListRecord newrec(outitems,newelems);
  260.             Record rawrec = newrec;
  261.             Tree->InsertTitle(titlekey,&rawrec);
  262.         } else if (titlekey[0] != 0) {
  263.             newelems[0] = (char*)key;
  264.             ListRecord newrec(1,newelems);
  265.             Record rawrec = newrec;
  266.             Tree->InsertTitle(titlekey,&rawrec);
  267.         }
  268.     }
  269. }
  270.                         
  271. void QuoteStringBuffer(char* buffer,char* string)
  272. {
  273.     *buffer++ = '"';
  274.     while (*string != 0) {
  275.         if (*string == '"') *buffer++ = '\\';
  276.         *buffer++ = *string++;
  277.     }
  278.     *buffer++ = '"';
  279.     *buffer = 0;
  280. }
  281.  
  282. static char *ptr;
  283. static Key   subjkey;
  284. static void ExamineSubj(CoreItem* item,int level)
  285. {
  286.     if (item->data.size <= 0) return;
  287.     ListRecord rec(&item->data);
  288.     int icount = rec.ElementCount();
  289.     for (int i = 0; i < icount; i++) {
  290.         if (streqp(subjkey,rec[i])) {
  291.             QuoteStringBuffer(ptr,item->key);
  292.             ptr += strlen(ptr);
  293.             *ptr++ = ',';
  294.             return;
  295.         }
  296.     }
  297. }
  298.  
  299. void FetchSubjs(char* subjbuffer,const Key key)
  300. {
  301.     ptr = subjbuffer;
  302.     strcpy(subjkey,key);
  303.     Tree->TraverseSubj(ExamineSubj);
  304.     if (ptr > subjbuffer && *(ptr-1) == ',') ptr--;
  305.     *ptr = '\0';
  306. }
  307.  
  308. Boolean CardsAreDifferent(const Card *c1,const Card *c2)
  309. {
  310.     if (c1->type != c2->type ||
  311.         c1->vol  != c2->vol  ||
  312.         c1->year != c2->year ||
  313.         strcmp(c1->author,c2->author) != 0 ||
  314.         strcmp(c1->title,c2->title) != 0 ||
  315.         strcmp(c1->publisher,c2->publisher) != 0 ||
  316.         strcmp(c1->city,c2->city) != 0 ||
  317.         strcmp(c1->description,c2->description) != 0) return(true);
  318.     else return(false);
  319. }
  320.  
  321. static void SaveCard(EditForm& ef)
  322. {
  323.     if (OrigCard != 0 && CardsAreDifferent(&editcard,OrigCard)) {
  324.         CardRecord rec(&editcard);
  325.         Record rawrec = rec;
  326.         Tree->InsertId(editkey,&rawrec);
  327.         UpdateAuthor(Author,OrigCard->author,editkey);
  328.         UpdateTitle(Title,OrigCard->title,editkey);
  329.     } else {
  330.         CardRecord rec(&editcard);
  331.         Record rawrec = rec;
  332.         Tree->InsertId(editkey,&rawrec);
  333.         UpdateAuthor(Author,"",editkey);
  334.         UpdateTitle(Title,"",editkey);
  335.     }
  336.     UpdateSubjs(SubjList,OrigSubjList,editkey);
  337.     strcpy(OrigSubjList,SubjList);
  338.     Term->Message("Saved");
  339.     ef.IsModified = false;
  340.     return;
  341. }
  342.  
  343. static Field Fields[] = {
  344.     {"Id: ",Literal,0,0,3,1,4,1,0},
  345.     {editkey,Literal,0,0,3,5,KeySize,1,0},
  346.     {"Type: ",Literal,0,0,3,50,6,1,0},
  347.     {&editcard.type,Special,TypeToString,StringToType,3,56,14,1,0},
  348.     {"Title: ",Literal,0,0,4,1,7,1,0},
  349.     {Title,String,0,0,4,8,60,1,BuffSize},
  350.     {"Author: ",Literal,0,0,5,1,8,1,0},
  351.     {Author,String,0,0,5,9,60,1,BuffSize},
  352.     {"Publisher: ",Literal,0,0,6,1,11,1,0},
  353.     {Publisher,String,0,0,6,12,40,1,BuffSize},
  354.     {"Year: ",Literal,0,0,6,60,6,1,0},
  355.     {&editcard.year,Int,0,0,6,66,4,1,0},
  356.     {"City: ",Literal,0,0,7,1,6,1,0},
  357.     {City,String,0,0,7,7,40,1,BuffSize},
  358.     {"Vol: ",Literal,0,0,7,60,5,1,0},
  359.     {&editcard.vol,Int,0,0,7,65,4,1,0},
  360.     {"Description: ",Literal,0,0,8,1,13,1,0},
  361.     {Description,EditorString,0,0,8,14,50,10,DescrSize},
  362.     {"Subjects: ",Literal,0,0,19,1,10,1,0},
  363.     {SubjList,EditorString,0,0,19,11,50,3,DescrSize}
  364. };
  365.  
  366. static const NumFields = sizeof(Fields) / sizeof(Field);
  367.  
  368. static void HelpField(EditForm& ef)
  369. {
  370.     switch (ef.CurField()) {
  371.         case 4: // Type:
  372.             Term->Clear();
  373.             Term->PutStrAt(2,0,"Type field - enter one of:");
  374.             Term->PutStrAt(4,0,"Book, Magazine, CD, AudioCassette, Album, LaserDisk, VHSVideo,");
  375.             Term->PutStrAt(5,0,"BetaVideo, EightMM, EightTrack, DAT, or Other.");
  376.             Term->PutStrAt(7,0,"This is the type of item being cataloged.");
  377.             Term->PutStrAt(0,0,"Hit any key to resume editing:");
  378.             Term->GetKey();
  379.             ef.RePaint();
  380.             break;
  381.         case 6: // Title: (string)
  382.             Term->Message("Title field - enter the title as a string");
  383.             break;
  384.         case 8: // Author: (string)
  385.             Term->Message("Author field - enter the author as a string");
  386.             break;
  387.         case 10: // Publisher: (string)
  388.             Term->Message("Publisher field - enter the publisher as a string");
  389.             break;
  390.         case 12: // Year: (number)
  391.             Term->Message("Year field - enter the year as a number");
  392.             break;
  393.         case 14: // City: (string)
  394.             Term->Message("City field - enter the city as a string");
  395.             break;
  396.         case 16: // Volume: (number)
  397.             Term->Message("Volumn field - enter the volume number as a number");
  398.             break;
  399.         case 18: // Description (long string)
  400.             Term->Message("Description field - enter the description as a multi-line string");
  401.             break;
  402.         case 20: // Subjects (long string)
  403.             Term->Message("Subjects field - enter the subjects as a comma separated list of strings");
  404.             break;
  405.     }
  406. }
  407.  
  408. static KeyBinding Bindings[] = {
  409.     {SaveCard,"^S - Save card",'S' - '@'},
  410.     {HelpField,"H - Give help for the current field",'H'},
  411.     {HelpField,"h - Give help for the current field",'h'}
  412. };
  413. static const NumBindings = sizeof(Bindings) / sizeof(KeyBinding);
  414.  
  415. int EditCard1(Key inkey)
  416. {
  417. #ifdef ILLEGAL_INSTR
  418.     static EditForm editform("Editing a Card",NumFields,Fields,
  419.                           NumBindings,Bindings);
  420. #else
  421.     EditForm *editform = new EditForm("Editing a Card",NumFields,Fields,
  422.                           NumBindings,Bindings);
  423. #endif
  424.  
  425.     strcpy(editkey,inkey);
  426.     CoreItem item;
  427. #ifdef ILLEGAL_INSTR
  428.     editform.ResetField();
  429. #else
  430.     editform->ResetField();
  431. #endif
  432.     if (Tree->SearchId(editkey,&item) &&
  433.         strlen(editkey) == strlen(item.key)) {
  434.         strcpy(editkey,item.key);
  435.         CardRecord crec(&item.data);
  436.         strcpy(Author,crec->author);
  437.         strcpy(Title,crec->title);
  438.         strcpy(Publisher,crec->publisher);
  439.         strcpy(City,crec->city);
  440.         strcpy(Description,crec->description);
  441.         editcard.year = crec->year;
  442.         editcard.vol  = crec->vol;
  443.         editcard.type = crec->type;
  444.         FetchSubjs(SubjList,editkey);
  445.         strcpy(OrigSubjList,SubjList);
  446.         OrigCard = &crec;
  447. #ifdef ILLEGAL_INSTR
  448.             if(editform.RunForm()) {
  449. #else
  450.             if(editform->RunForm()) {
  451. #endif
  452.                 if (Term->YorNp(20,0,"Card modified - save it?")) 
  453. #ifdef ILLEGAL_INSTR
  454.                     SaveCard(editform);
  455. #else
  456.                     SaveCard(*editform);
  457. #endif
  458.             }
  459.     } else if (Term->YorNp(21,0,"Card not found, create it?")) {
  460.         Author[0] = 0;
  461.         Title[0]  = 0;
  462.         Publisher[0] = 0;
  463.         City[0]   = 0;
  464.         Description[0] = 0;
  465.         SubjList[0] = 0;
  466.         OrigSubjList[0] = 0;
  467.         OrigCard = 0;
  468.         editcard.type = Book;
  469.         editcard.vol = 0;
  470.         editcard.year = 0;
  471. #ifdef ILLEGAL_INSTR
  472.             if(editform.RunForm()) {
  473. #else
  474.             if(editform->RunForm()) {
  475. #endif
  476.                 if (Term->YorNp(20,0,"Card modified - save it?")) 
  477. #ifdef ILLEGAL_INSTR
  478.                     SaveCard(editform);
  479. #else
  480.                     SaveCard(*editform);
  481. #endif
  482.             }
  483.     }
  484. #ifndef ILLEGAL_INSTR
  485.     delete editform;
  486. #endif
  487.     return(-1);
  488. }
  489.  
  490.  
  491. int EditCard()
  492. {
  493.     static Key tempkey;
  494.  
  495.     Term->PromptLine(18,0,"Id of card to edit: ",tempkey,KeySize);
  496.     return(EditCard1(tempkey));
  497. }
  498.  
  499.