home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / telecom / uucp_442 / src / dnews / main.c < prev    next >
C/C++ Source or Header  |  1990-10-08  |  11KB  |  523 lines

  1.  
  2. /*
  3.  *  MAIN.C
  4.  */
  5.  
  6. #include "defs.h"
  7.  
  8. #define MSTLEN    64    /*  # of forward referenced articles    */
  9.  
  10. char    User[32];
  11. NGroup    *GBase;
  12. NGroup    *CurGroup;
  13. void    *GrpDisp;
  14. void    *HelpDisp;
  15. void    *DataDisp;
  16. void    *ScanDisp;    /*  subject scan display    */
  17. char    *GroupFile = "T:DNews_Groups";
  18. char    *HelpFile = "T:DNews_Help";
  19. char    TmpBuf[TMPBSIZE];
  20.  
  21. long    MStack[MSTLEN];
  22. short    Mi;
  23. short    Mx;
  24.  
  25. #ifndef LATTICE
  26. void *GfxBase;
  27. void *IntuitionBase;
  28. #endif
  29.  
  30. Prototype char *FileForArticle(NGroup *, int);
  31.  
  32. Local NGroup *FindGroupByIndex(int);
  33. Local void HandleKey(int);
  34. Local void UpdateGroupList(char *);
  35. Local void CreateHelpFile();
  36. Local void SetPrevNo();
  37.  
  38. Local char *TitleForArticle(NGroup *);
  39.  
  40. int
  41. brk()
  42. {
  43.     return(0);
  44. }
  45.  
  46. void
  47. closlib()
  48. {
  49.     if (GfxBase) {
  50.     CloseLibrary(GfxBase);
  51.     GfxBase = NULL;
  52.     }
  53.     if (IntuitionBase) {
  54.     CloseLibrary(IntuitionBase);
  55.     IntuitionBase = NULL;
  56.     }
  57. }
  58. main(ac, av)
  59. char **av;
  60. {
  61.     onbreak(brk);
  62.     atexit(closlib);
  63.  
  64.     IntuitionBase = OpenLibrary("intuition.library", 0);
  65.     GfxBase = OpenLibrary("graphics.library", 0);
  66.     if (IntuitionBase == NULL || GfxBase == NULL) {
  67.     puts("unable to open libraries");
  68.     exit(20);
  69.     }
  70.  
  71.     FindUser(User, sizeof(User));   /*  who am I ?  */
  72.     LoadGroups(User);               /*  load newsrc for user    */
  73.     LoadKillFile(User);
  74.     if (GBase == NULL) {
  75.     CreateNewsrc(User);
  76.     LoadGroups(User);
  77.     if (GBase == NULL) {
  78.         printf("Unable to find any news!\n");
  79.         exit(1);
  80.     }
  81.     }
  82.  
  83.     LoadDisplayConfig();
  84.  
  85.     UpdateGroupList(GroupFile);
  86.     GrpDisp = OpenBrowseDisplay(GroupFile, "h-help", 0);
  87.     if (GrpDisp == NULL) {
  88.     puts("unable to open window");
  89.     exit(1);
  90.     }
  91.  
  92.     /*
  93.      *    Handle browse events
  94.      */
  95.  
  96.     {
  97.     void *disp;
  98.     int row;
  99.     int col;
  100.     NGroup *grp;
  101.  
  102.     while (WaitBrowseEvent(&disp, &row, &col)) {
  103.         if (disp == GrpDisp) {      /*  handle main group list  */
  104.         if (row == -1) {        /*  close window    */
  105.             if (col == -1)
  106.             break;
  107.             HandleKey(col);
  108.             continue;
  109.         }
  110.         if (grp = FindGroupByIndex(row)) {
  111.             if (CurGroup)
  112.             ClearGroupCache(CurGroup);
  113.             CurGroup = grp;
  114.             Mi = 0;
  115.             Mx = 0;
  116.             if (DataDisp)
  117.             ChangeBrowseDisplay(DataDisp, FileForArticle(grp, grp->CurNo), TitleForArticle(grp));
  118.             else
  119.             DataDisp = OpenBrowseDisplay(FileForArticle(grp, grp->CurNo), TitleForArticle(grp), 1);
  120.         }
  121.         continue;
  122.         }
  123.         if (disp == HelpDisp) {
  124.         if (row == -1) {
  125.             if (col == -1) {
  126.             CloseBrowseDisplay(HelpDisp);
  127.             HelpDisp = NULL;
  128.             }
  129.         }
  130.         continue;
  131.         }
  132.         if (disp == DataDisp) {
  133.         if (row == -1) {
  134.             if (col == -1) {
  135.             CloseBrowseDisplay(DataDisp);
  136.             DataDisp = NULL;
  137.             continue;
  138.             }
  139.             HandleKey(col);
  140.             continue;
  141.         }
  142.         }
  143.     }
  144.     }
  145.  
  146.     if (GrpDisp)
  147.     CloseBrowseDisplay(GrpDisp);
  148.     if (HelpDisp)
  149.     CloseBrowseDisplay(HelpDisp);
  150.     if (DataDisp)
  151.     CloseBrowseDisplay(DataDisp);
  152.     SaveKillFile(User);
  153.     UnloadGroups(User);
  154.     SaveDisplayConfig();
  155.     remove(GroupFile);
  156.     return(0);
  157. }
  158.  
  159. static void
  160. UpdateGroupList(file)
  161. char *file;
  162. {
  163.     FILE *fi;
  164.     NGroup *grp;
  165.  
  166.     fi = fopen(file, "w");
  167.     if (fi == NULL)
  168.     return;
  169.  
  170.     for (grp = GBase; ; grp = grp->Next) {
  171.     long unread;
  172.  
  173.     while (grp && grp->Enabled == 0)
  174.         grp = grp->Next;
  175.     if (grp == NULL)
  176.         break;
  177.  
  178.     if ((unread = grp->MaxNo - grp->CurNo) < 0)
  179.         unread += 32767;
  180.     fprintf(fi, "%-3d %-20s\n", unread, grp->Name);
  181.     }
  182.     fclose(fi);
  183. }
  184.  
  185. static void
  186. HandleKey(key)
  187. {
  188.     NGroup *grp = CurGroup;
  189.     short redisp = 0;
  190.     int n;
  191.  
  192.     for (;;) {
  193.     if (key != 'm' && key != 'M') {
  194.         Mi = 0;
  195.         Mx = 0;
  196.     }
  197.  
  198.     switch(key) {
  199.     case 'h':
  200.         if (HelpDisp == NULL) {
  201.         CreateHelpFile();
  202.         HelpDisp = OpenBrowseDisplay(HelpFile, "HELP", 2);
  203.         }
  204.         break;
  205.     case 'v':       /*  first unread article    */
  206.         if (grp) {
  207.         n = NextNotInRange(grp->RList, 0);
  208.         if (n >= grp->MaxNo + 1)
  209.             n = grp->MaxNo;
  210.         grp->CurNo = n - 1;
  211.         redisp = 1;
  212.         key = 's';
  213.         continue;
  214.         }
  215.         break;
  216.     case 'M':       /*  next reference auto-rewind          */
  217.     case 'm':       /*  next reference                      */
  218.         /*
  219.          *    Find an article that references this one.
  220.          */
  221.         if (grp->CurNo < grp->MaxNo)
  222.         RangeAdd(&grp->RList, grp->CurNo, grp->CurNo);
  223.  
  224.         if (grp) {
  225.         char *ref;
  226.         short alloced = 0;
  227.  
  228.         if (Mi || Mx == 0) {
  229.             ref = NewsMessageIdOf(grp, grp->CurNo);
  230.         } else {
  231.             short i;
  232.             char *tmp;
  233.  
  234.             ref = NULL;
  235.             if (tmp = ReferenceLineOf(grp, grp->CurNo)) {
  236.             for (i = Mx; i > 0; --i) {
  237.                 ref = NextRef(&tmp);
  238.                 if (ref == NULL)
  239.                 break;
  240.             }
  241.             }
  242.             if (ref) {
  243.             ref = strdup(ref);
  244.             alloced = 1;
  245.             }
  246.         }
  247.         if (ref) {
  248.             for (n = NextNotInRange(grp->RList, grp->CurNo); n < grp->MaxNo; n = NextNotInRange(grp->RList, n)) {
  249.             if (FindArticleReferencing(grp, ref, n))
  250.                 break;
  251.             }
  252.             if (alloced)
  253.             free(ref);
  254.             if (n >= grp->MaxNo) {      /*  no more references  */
  255.             if (Mi) {               /*  try refs to previous articles on the same line */
  256.                 n = MStack[--Mi];
  257.                 if (grp->CurNo != n) {
  258.                 SetPrevNo(grp);
  259.                 grp->CurNo = n;
  260.                 redisp = 1;
  261.                 }
  262.                 continue;        /*  w/ same key */
  263.             }
  264.             ++Mx;            /*  try References: fields of original    */
  265.             continue;        /*  w/ same key */
  266.             }
  267.             if (Mi != MSTLEN)
  268.             MStack[Mi++] = n;
  269.             if (grp->CurNo != n) {
  270.             SetPrevNo(grp);
  271.             grp->CurNo = n;
  272.             redisp = 1;
  273.             }
  274.         } else {
  275.             Mx = 0;
  276.             Mi = 0;
  277.             if (key == 'M') {
  278.             key = 'v';
  279.             continue;
  280.             }
  281.         }
  282.         }
  283.         break;
  284.     case 'g':
  285.         if (grp) {
  286.         FILE *fi;
  287.         long artno = -1;
  288.         if (fi = fopen("CON:0/0/200/50/Article?", "w+")) {
  289.             fprintf(fi, ": ");
  290.             fflush(fi);
  291.             if (fgets(TmpBuf, sizeof(TmpBuf), fi))
  292.             artno = atoi(TmpBuf);
  293.             fclose(fi);
  294.         }
  295.         if (artno < 0)
  296.             artno = 0;
  297.         if (artno > grp->MaxNo)
  298.             artno = grp->MaxNo;
  299.         SetPrevNo(grp);
  300.         grp->CurNo = artno;
  301.         RangeDel(&grp->RList, artno, artno);
  302.         redisp = 1;
  303.         }
  304.         break;
  305.     case 'n':       /*  mark and go to next article         */
  306.     case '.':
  307.     case '>':
  308.         if (grp->CurNo < grp->MaxNo)
  309.         RangeAdd(&grp->RList, grp->CurNo, grp->CurNo);
  310.     case 's':       /*  do not mark and go to next article  */
  311.         SetPrevNo(grp);
  312.         grp->CurNo = NextNotInRange(grp->RList, grp->CurNo);
  313.         if (grp->CurNo >= grp->MaxNo + 1) {
  314.         grp->CurNo = grp->MaxNo;
  315.         redisp = 1;
  316.         } else {
  317.         /*
  318.          *  skip past killed or non-existant articles, marking them as
  319.          *  we go
  320.          */
  321.  
  322.         if (ArticleRefKilled(grp, grp->CurNo)) {
  323.             RangeAdd(&grp->RList, grp->CurNo, grp->CurNo);
  324.             key = 's';
  325.             continue;
  326.         }
  327.         redisp = 1;
  328.         }
  329.         break;
  330.     case '0':       /*  go to previous article and unmark   */
  331.     case 'b':
  332.     case '<':
  333.         if (grp->PrevNo[0]) {
  334.         grp->CurNo = grp->PrevNo[0];
  335.         movmem(grp->PrevNo + 1, grp->PrevNo, sizeof(grp->PrevNo) - sizeof(grp->PrevNo[0]));
  336.         grp->PrevNo[arysize(grp->PrevNo)-1] = 0;
  337.         } else if (grp->CurNo > 1)
  338.         --grp->CurNo;
  339.         redisp = 1;
  340.         RangeDel(&grp->RList, grp->CurNo, grp->CurNo);
  341.         break;
  342.     case 'k':       /*  kill followups to this article and go to next article */
  343.         if (grp->CurNo < grp->MaxNo)
  344.         RangeAdd(&grp->RList, grp->CurNo, grp->CurNo);
  345.         if (grp) {
  346.         char *ref;
  347.         if (ref = NewsMessageIdOf(grp, grp->CurNo))
  348.             AddKillFile(ref, 0);
  349.         if (ref = ReferenceLineOf(grp, grp->CurNo))
  350.             AddKillFile(ref, 0);
  351.         }
  352.         key = 'n';
  353.         continue;
  354.     case 'K':       /*  kill followups for 30 days  */
  355.         if (grp->CurNo < grp->MaxNo)
  356.         RangeAdd(&grp->RList, grp->CurNo, grp->CurNo);
  357.         if (grp) {
  358.         char *ref;
  359.         if (ref = NewsMessageIdOf(grp, grp->CurNo))
  360.             AddKillFile(ref, 30);
  361.         if (ref = ReferenceLineOf(grp, grp->CurNo))
  362.             AddKillFile(ref, 30);
  363.         }
  364.         key = 'n';
  365.         continue;
  366.     case 'U':       /*  unkill followups            */
  367.         if (grp) {
  368.         char *ref;
  369.         if (ref = NewsMessageIdOf(grp, grp->CurNo))
  370.             RemKillFile(ref);
  371.         if (ref = ReferenceLineOf(grp, grp->CurNo))
  372.             RemKillFile(ref);
  373.         }
  374.         break;
  375.     case CTRL('g'): /*  goto specific article and mark as unread    */
  376.         break;
  377.     case '=':       /*  bring up subject scan window                */
  378.     case '/':       /*  search in article               */
  379.     case CTRL('/'): /*  search in all remaining articles*/
  380.  
  381.     case 'N':       /*  next newsgroup          */
  382.  
  383.     case 'B':       /*  previous newsgroup      */
  384.         break;
  385.     case 'w':       /*  write article to file   */
  386.         if (grp) {
  387.         char *fn;
  388.  
  389.         if (fn = GetFileName(0)) {
  390.             FILE *fi = fopen(FileForArticle(grp, grp->CurNo), "r");
  391.             FILE *fo = fopen(fn, "w");
  392.             long n;
  393.  
  394.             if (fi && fo) {
  395.             while ((n = fread(TmpBuf, 1, sizeof(TmpBuf), fi)) > 0)
  396.                 fwrite(TmpBuf, 1, n, fo);
  397.             }
  398.             if (fi)
  399.             fclose(fi);
  400.             if (fo)
  401.             fclose(fo);
  402.         }
  403.         }
  404.         break;
  405.     case 'r':       /*  reply to sender         */
  406.     case 'R':       /*  w/ text of current art  */
  407.         if (grp)
  408.         ReplyArticle(key, grp);
  409.         break;
  410.     case 'f':       /*  followup to newsgroup   */
  411.     case 'F':       /*  w/ text of current art  */
  412.         if (grp)
  413.         FollowUpArticle(key, grp);
  414.         break;
  415.     case 'p':       /*  post article (asynch)   */
  416.         PostArticle(grp);       /*  grp can be NULL!    */
  417.         break;
  418.     default:
  419.         break;
  420.     }
  421.     break;
  422.     }
  423.     if (redisp && DataDisp && grp)
  424.     ChangeBrowseDisplay(DataDisp, FileForArticle(grp, grp->CurNo), TitleForArticle(grp));
  425. }
  426.  
  427. static NGroup *
  428. FindGroupByIndex(i)
  429. {
  430.     NGroup *grp;
  431.  
  432.     for (grp = GBase; ; grp = grp->Next) {
  433.     while (grp && grp->Enabled == 0)
  434.         grp = grp->Next;
  435.     if (grp == NULL)
  436.         break;
  437.     if (i == 0)
  438.         break;
  439.     --i;
  440.     }
  441.     return(grp);
  442. }
  443.  
  444.  
  445. char *
  446. FileForArticle(grp, artno)
  447. NGroup *grp;
  448. {
  449.     static char buf[256];
  450.  
  451.     sprintf(buf, "%s/%d", grp->Name, artno);
  452.  
  453.     return(MakeConfigPath(UUNEWS, buf));
  454. }
  455.  
  456. void
  457. CreateHelpFile()
  458. {
  459.     FILE *fi;
  460.     if (fi = fopen(HelpFile, "w")) {
  461.     fputs(
  462.         "use mouse buttons to select newsgroup\n"
  463.         "\n"
  464.         "h  -help\n"
  465.         "v  -first unread article (usually after m's)\n"
  466.         "m  -mark article read and follow references, stop at end\n"
  467.         "M  -mark article read and follow references, 'v' at end\n"
  468.         "n  -mark article read and goto next\n"
  469.         "s  -do not mark and goto next unread\n"
  470.         "b  -return to last read article (history of 8)\n"
  471.         "k  -kill refs to article (this session only)\n"
  472.         "K  -kill refs to article for 30 days\n"
  473.         "U  -unkill refs to article\n"
  474.         "w  -write article to file\n"
  475.         "r  -reply to sender of article\n"
  476.         "R  -reply to sender, include article contents\n"
  477.         "f  -followup to newsgroup\n"
  478.         "F  -followup to newsgroup, include article contents\n"
  479.         "p  -post a new article\n"
  480.  
  481.         "4  -left half of article\n"
  482.         "6  -right half of article\n"
  483.         "8  -page up\n"
  484.         "2  -page down (SPACE also pages down)\n"
  485.         "3  -bottom of article\n"
  486.         "9  -top of article\n"
  487.         "\n", fi
  488.     );
  489.     fclose(fi);
  490.     }
  491. }
  492.  
  493. char *
  494. TitleForArticle(grp)
  495. NGroup *grp;
  496. {
  497.     char *fname = FileForArticle(grp, grp->CurNo);
  498.     char *ptr;
  499.  
  500.     ptr = fname + strlen(fname);
  501.  
  502.     while (ptr > fname && *ptr != '/')
  503.     --ptr;
  504.     --ptr;
  505.     while (ptr >= fname && *ptr != '/')
  506.     --ptr;
  507.     ++ptr;
  508.  
  509.     sprintf(TmpBuf, "%s (%d)", ptr, grp->MaxNo - 1);
  510.     return(TmpBuf);
  511. }
  512.  
  513. void
  514. SetPrevNo(grp)
  515. NGroup *grp;
  516. {
  517.     if (grp->PrevNo[0] != grp->CurNo) {
  518.     movmem(grp->PrevNo, grp->PrevNo + 1, sizeof(grp->PrevNo) - sizeof(grp->PrevNo[0]));
  519.     grp->PrevNo[0] = grp->CurNo;
  520.     }
  521. }
  522.  
  523.