home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / comms / network / grn1src.lha / gmode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-05  |  29.4 KB  |  864 lines

  1. #include        "defs.h"
  2. #include        "memalloc.h"
  3.  
  4. // #define PROCDEBUG
  5.  
  6. #ifdef PROCDEBUG
  7. #define D(x)    printf x
  8. #else
  9. #define D(x)
  10. #endif
  11.  
  12. extern char *NewsGroupToFileName (char *newsgroup);
  13.  
  14. static LIST     nullList;
  15. GLIST           *currentGroup = 0;
  16.  
  17. ULONG           totalGroups = 0, totalArticles = 0, unreadArticles = 0;
  18.  
  19. /************************************************************************/
  20.  
  21. /*
  22.  * As each gadget in the GadDefs array above is created, it is assigned a UserID
  23.  * field value, incremented from zero.  The following defines are useful for switch
  24.  * statements, etc.  Enum would also work.  Be careful, if you add new gadgets in
  25.  * the middle of the initializations above, because you will need to renumber these
  26.  * defines.
  27.  */
  28. static enum GADGET_IDS {
  29.         GROUPLIST_ID,
  30.         QUIT_ID,
  31.         READ_ID,
  32.         POST_ID,
  33.         CATCHUP_ID,
  34.         PUBLISH_ID,
  35.         JUNK_ID,
  36.         BUGREPORT_ID,
  37.         UUCPBUG_ID,
  38.         STATUS_ID,
  39.         MAXGADGET,
  40. };
  41.  
  42. static GADGET   *gadgetArray[MAXGADGET];
  43.  
  44. /*
  45.  * Misc tags arrays
  46.  */
  47. static TAGS     nullTags[] = { GT_Underscore, '_', TAG_DONE,0 };
  48. static TAGS     disableTags[] = { GT_Underscore, '_', GA_Disabled,TRUE, TAG_DONE,0 };
  49. static TAGS     enableTags[] = { GT_Underscore, '_', GA_Disabled,FALSE, TAG_DONE,0 };
  50.  
  51. static TAGS     groupListTags[] = {
  52.         GT_Underscore, '_',
  53.         GTLV_Top, 0,
  54.         GTLV_Labels, &groupList,
  55.         GTLV_ReadOnly, FALSE,
  56.         GTLV_ScrollWidth, 16,
  57.         GTLV_ShowSelected, NULL,
  58.         GTBB_Recessed, FALSE,
  59.         TAG_DONE, 0,
  60. };
  61.  
  62. static TAGS     nullListTags[] = {
  63.         GT_Underscore, '_',
  64.         GTLV_Top, 0,
  65.         GTLV_Labels, &nullList,
  66.         GTLV_ReadOnly, FALSE,
  67.         GTLV_ScrollWidth, 16,
  68.         GTBB_Recessed, FALSE,
  69.         TAG_DONE, 0,
  70. };
  71.  
  72. static char     *nullText = "";
  73. static TAGS     textTags[] = {
  74.         GT_Underscore, '_',
  75.         GTTX_Text, (ULONG)"",
  76.         GTTX_CopyText, TRUE,
  77.         GTTX_Border, TRUE,
  78.         TAG_DONE, 0,
  79. };
  80.  
  81. /*
  82.  * The Array of Gadget definitions.  To create a new gadget, add an initializer
  83.  * here, and create the necessary tags...
  84.  */
  85. static GADDEF   gadDefs[] = {
  86.         groupListTags, LISTVIEW_KIND,0,0,0,0, NG_HIGHLABEL, "",
  87.         enableTags, BUTTON_KIND, 0,0,0,0, NG_HIGHLABEL, "_Quit",
  88.         enableTags, BUTTON_KIND, 0,0,0,0, NG_HIGHLABEL, "_Read",
  89.         enableTags, BUTTON_KIND, 0,0,0,0, NG_HIGHLABEL, "_Post",
  90.         enableTags, BUTTON_KIND, 0,0,0,0, NG_HIGHLABEL, "_Catch up",
  91.         enableTags, BUTTON_KIND, 0,0,0,0, NG_HIGHLABEL, "Publish",
  92.         enableTags, BUTTON_KIND, 0,0,0,0, NG_HIGHLABEL, "_Junk",
  93.         enableTags, BUTTON_KIND, 0,0,0,0, NG_HIGHLABEL, "_Bug Report",
  94.         enableTags, BUTTON_KIND, 0,0,0,0, NG_HIGHLABEL, "_UUCP Bug Report",
  95.         textTags, TEXT_KIND, 0,0,0,0, NG_HIGHLABEL, "",
  96.         0,0,0,0,0,0,0,0,
  97. };
  98.  
  99. static GADGET   *gList = 0;
  100.  
  101. static void     LayoutGadgets(font,width,height,top)
  102. FONT            *font;
  103. short           width,height,top;
  104. {
  105.         short   i, x,y, fh;
  106.         RPORT   rPort, *rp = &rPort;
  107.  
  108.         InitRastPort(rp);
  109.         SetFont(rp, font);
  110.         y = top+INTERHEIGHT/2;
  111.  
  112.         fh = rp->TxHeight+2;
  113.         gadDefs[GROUPLIST_ID].left = INTERWIDTH;
  114.         gadDefs[GROUPLIST_ID].top = y;
  115.         gadDefs[GROUPLIST_ID].width = width-INTERWIDTH-INTERWIDTH;
  116.         gadDefs[GROUPLIST_ID].height = 12*fh+INTERHEIGHT;
  117.         y += 12*fh+INTERHEIGHT;
  118.  
  119.         fh = topazRP->TxHeight+2;
  120.         x = INTERWIDTH;
  121.         for (i=QUIT_ID; i<=UUCPBUG_ID; i++) {
  122.                 gadDefs[i].left = x;
  123.                 gadDefs[i].top = y;
  124.                 gadDefs[i].width = TextLen(topazRP, gadDefs[i].text)+8;
  125.                 gadDefs[i].height = fh+2;
  126.                 x += gadDefs[i].width + INTERWIDTH;
  127.         }
  128.         y += fh+INTERHEIGHT+fh+INTERHEIGHT+fh+INTERHEIGHT;
  129.         y += height-y-fh-fh-INTERHEIGHT-4;
  130.  
  131.         gadDefs[STATUS_ID].left = INTERWIDTH;
  132.         gadDefs[STATUS_ID].top = y;
  133.         gadDefs[STATUS_ID].width = width-INTERWIDTH-INTERWIDTH;
  134.         gadDefs[STATUS_ID].height = fh+2;
  135.         y += fh+4;
  136.  
  137.         return;
  138. }
  139.  
  140. /************************************************************************/
  141.  
  142. void    CloseGroups (void)
  143. {
  144.         if (!gList)
  145.                 return;
  146.         if (RemoveGList (mainWindow, gList, -1) == -1) {
  147.                 t_printf (mainWindow, "RemoveGList() failed!");
  148.                 return;
  149.         }
  150.         FreeGadgets (gList);
  151.         gList = 0;
  152.         ClearWindow ();
  153.         return;
  154. }
  155.  
  156. void    GroupsStatus (void)
  157. {
  158.         GLIST           *gp;
  159.         ART             *ap;
  160.         static char     groupStatus [256];
  161.  
  162.         totalGroups = 0;
  163.         totalArticles = 0;
  164.         unreadArticles = 0;
  165.         for (gp=(GLIST *)groupList.lh_Head; gp->node.ln_Succ; gp=(GLIST *)gp->node.ln_Succ) {
  166.                 gp->articles = 0;
  167.                 gp->unread = 0;
  168.                 totalGroups++;
  169.                 for (ap=(ART *)gp->artList.lh_Head; ap->node.ln_Succ; ap = (ART *)ap->node.ln_Succ) {
  170.                         totalArticles++; gp->articles++;
  171.                         if (ap->state == UNREAD) {
  172.                                 unreadArticles++;
  173.                                 gp->unread++;
  174.                         }
  175.                 }
  176.                 sprintf(gp->header, "%-40.40s %6d articles %6d UnRead", gp->groupName, gp->articles, gp->unread);
  177.         }
  178.         sprintf (groupStatus, " *** %d groups, %d articles (%d unread)", totalGroups, totalArticles, unreadArticles);
  179.         GT_SetGadgetAttrs (gadgetArray [STATUS_ID], mainWindow, NULL,
  180.                            GTTX_Text, groupStatus, TAG_DONE);
  181.         return;
  182. }
  183.  
  184. UWORD   GroupID (void)
  185. {
  186.         UWORD   n;
  187.         GLIST   *gp = (GLIST *)groupList.lh_Head;
  188.         n = 0;
  189.         while (gp->node.ln_Succ) {
  190.                 if (gp == currentGroup) return n;
  191.                 gp = (GLIST *)gp->node.ln_Succ;
  192.                 n++;
  193.         }
  194.         return ~0;
  195. }
  196.  
  197. static void     ValidateOptions (void)
  198. {
  199.         int i;
  200.  
  201.         if (!currentGroup) {
  202.                 for (i = READ_ID; i <= PUBLISH_ID; i++) {
  203.                         GT_SetGadgetAttrs (gadgetArray [i], mainWindow, NULL,
  204.                                            GA_Disabled, TRUE, TAG_DONE);
  205.                 }
  206.                 return;
  207.         }
  208.         if (currentGroup->articles == 0) {
  209.                 GT_SetGadgetAttrs (gadgetArray [READ_ID], mainWindow, NULL,
  210.                                    GA_Disabled, TRUE, TAG_DONE);
  211.                 GT_SetGadgetAttrs (gadgetArray [CATCHUP_ID], mainWindow, NULL,
  212.                                    GA_Disabled, TRUE, TAG_DONE);
  213.                 return;
  214.         }
  215.         if (currentGroup->unread == 0) {
  216.                 GT_SetGadgetAttrs (gadgetArray [READ_ID], mainWindow, NULL,
  217.                                    GA_Disabled, FALSE, TAG_DONE);
  218.                 GT_SetGadgetAttrs (gadgetArray [CATCHUP_ID], mainWindow, NULL,
  219.                                    GA_Disabled, TRUE, TAG_DONE);
  220.                 return;
  221.         }
  222.         for (i = READ_ID; i <= PUBLISH_ID; i++) {
  223.                 GT_SetGadgetAttrs (gadgetArray [i], mainWindow, NULL,
  224.                                    GA_Disabled, FALSE, TAG_DONE);
  225.         }
  226.         return;
  227. }
  228.  
  229. /************************************************************************/
  230.  
  231. // Junk an existing newsgroup
  232. //
  233. // This only involves removing the group (and its articles) from the newstree
  234. // THEY WILL STAY IN THE UUNEWS: DIRECTORY
  235. //
  236. void    Junk (BOOL flag)
  237. {
  238.         ART     *ap;
  239.         GLIST   *gp;
  240.  
  241.         D (("Junk(): enter\n"));
  242.  
  243.         if (flag && TwoGadgetRequest ("GRn - Request",
  244.                                       "Remove this group from your Active list?",
  245.                                       "_YES", "_NO") == 0) {
  246.  
  247.                 D (("Junk(): non confirm, exit\n"));
  248.                 return;
  249.         }
  250.  
  251.         while (!EmptyList (¤tGroup->artList)) {
  252.                 ap = (ART *) RemHead (¤tGroup->artList);
  253.                 FreeART (ap);
  254.         }
  255.  
  256.         GT_SetGadgetAttrs (gadgetArray [GROUPLIST_ID], mainWindow, NULL,
  257.                            GTLV_Labels, ~0, TAG_DONE);
  258.  
  259.         gp = (groupList.lh_TailPred == (NODE *)currentGroup) ? (GLIST *)groupList.lh_Head : (GLIST *)currentGroup->node.ln_Succ;
  260.         Remove ((NODE *) currentGroup);
  261.         FreeNODE (currentGroup);
  262.         currentGroup = gp;
  263.  
  264.         GT_SetGadgetAttrs (gadgetArray [GROUPLIST_ID], mainWindow, NULL,
  265.                            GTLV_Labels, &groupList, TAG_DONE);
  266.  
  267.         GT_SetGadgetAttrs (gadgetArray [GROUPLIST_ID], mainWindow, NULL,
  268.                            GTLV_Selected, GroupID(), TAG_DONE);
  269.  
  270.         GT_SetGadgetAttrs (gadgetArray [GROUPLIST_ID], mainWindow, NULL,
  271.                            GTLV_Top, GroupID(), TAG_DONE);
  272.  
  273.         treeDirty = !0;
  274.  
  275.         D (("Junk(): exit\n"));
  276.         return;
  277. }
  278.  
  279. /************************************************************************/
  280.  
  281. void AppendSignature (int outfd)
  282. {
  283.         int fd;
  284.         int len;
  285.         char *temp, *work;
  286.  
  287.         D (("AppendSignature(): enter\n"));
  288.  
  289.         if (outfd < 0)
  290.                 return;
  291.         if (!(temp = malloc (256))) {
  292.                 t_printf (mainWindow, "Can't malloc 256 bytes for signature");
  293.  
  294.                 D (("AppendSignature(): get mem failure 1, exit\n"));
  295.                 return;
  296.         }
  297.         if (!(work = malloc (256))) {
  298.                 t_printf (mainWindow, "Can't malloc 256 bytes for signature");
  299.                 free (temp);
  300.  
  301.                 D (("AppendSignature(): get mem failure 2, exit\n"));
  302.                 return;
  303.         }
  304.  
  305.         strcpy (temp, uulib);
  306.         CopyStrings (work, userName, ".signature", NULL);
  307.         AddPart (temp, work, 256);
  308.         if ((fd = open (temp, O_RDONLY)) < 0) {
  309.                 strcpy (temp, uulib);
  310.                 AddPart (temp, ".signature", 256);
  311.                 fd = open (temp, O_RDONLY);
  312.         }
  313.         if (fd < 0) {
  314.                 OutputStrings (outfd, ".signature under construction\n", NULL);
  315.         }
  316.         else {
  317.                 while ((len = read (fd, temp, 256)) > 0)
  318.                         write (outfd, temp, len);
  319.                 close (fd);
  320.         }
  321.  
  322.         free (work);
  323.         free (temp);
  324.  
  325.         D (("AppendSignature(): exit\n"));
  326.         return;
  327. }
  328.  
  329. void AppendNewsGroupSignature (int outfd)
  330. {
  331.         int fd;
  332.         int len;
  333.         char    *work, *temp;
  334.  
  335.         D (("AppendNewsGroupSignature(): enter\n"));
  336.  
  337.         if (outfd < 0)
  338.                 return;
  339.         if (!(work = malloc (256))) {
  340.                 t_printf (mainWindow, "Can't malloc 256 bytes for signature");
  341.  
  342.                 D (("AppendNewsGroupSignature(): get mem failure 1\n"));
  343.                 return;
  344.         }
  345.         if (!(temp = malloc (256))) {
  346.                 t_printf (mainWindow, "Can't malloc 256 bytes for signature");
  347.                 free (work);
  348.  
  349.                 D (("AppendNewsGroupSignature(): get mem failure 2\n"));
  350.                 return;
  351.         }
  352.  
  353.         strcpy (temp, uulib);
  354.         CopyStrings (work, userName, ".signature", NULL);
  355.         AddPart (temp, work, 256);
  356.  
  357.         if (currentGroup && (fd = open (temp, O_RDONLY)) < 0) {
  358.                 strcpy (temp, uunews);
  359.                 AddPart (temp, NewsGroupToFileName (currentGroup->groupName),
  360.                                 256);
  361.                 AddPart (temp, work, 256);
  362.                 fd = open (temp, O_RDONLY);
  363.         }
  364.         if (fd < 0) {
  365.                 strcpy (temp, uulib);
  366.                 AddPart (temp, ".signature", 256);
  367.                 fd = open (temp, O_RDONLY);
  368.         }
  369.         if (fd < 0) {
  370.                 OutputStrings (outfd, ".signature under construction\n", NULL);
  371.         }
  372.         else {
  373.                 while ((len = read (fd, temp, 256)) > 0)
  374.                         write (outfd, temp, len);
  375.  
  376.                 close (fd);
  377.         }
  378.  
  379.         free (temp);
  380.         free (work);
  381.  
  382.         D (("AppendNewsGroupSignature(): exit\n"));
  383.         return;
  384. }
  385.  
  386. void    BugReport (void)
  387. {
  388.         int     outfd;
  389.         char    *fname;
  390.  
  391.         D (("BugReport(): enter\n"));
  392.  
  393.         fname = TempName ();
  394.         if ((outfd = creat (fname, 0660)) < 0) {
  395.                 t_printf (mainWindow, "Can't open %s for output", fname);
  396.  
  397.                 D (("BugReport(): open output failure, exit\n"));
  398.                 return;
  399.         }
  400.         //                     To: grnbugs@amiga0.sf-bay.org
  401.         OutputStrings (outfd, "To: grnbugs@adastra.cvl.va.us\n",
  402.                               "Subject: Bug Report For ",
  403.                               GRN_VERSION,
  404.                               "\n"
  405.                               "X-NewsSoftware: ",
  406.                               GRN_VERSION,
  407.                               "\n\n\n-- \n",
  408.                               NULL);
  409.  
  410.         AppendSignature (outfd);
  411.         close (outfd);
  412.  
  413.         SendMail (fname);
  414.  
  415.         GT_RefreshWindow (mainWindow, NULL);
  416.  
  417.         D (("BugReport(): exit\n"));
  418.         return;
  419. }
  420.  
  421. /************************************************************************/
  422.  
  423. void    UUCPBugReport (void)
  424. {
  425.         int     outfd;
  426.         char    *fname;
  427.         char    *ptr;
  428.  
  429.         D (("UUCPBugReport(): enter\n"));
  430.  
  431.         ptr = TempName ();
  432.         if ((outfd = creat (ptr, 0660)) < 0) {
  433.                 t_printf (mainWindow, "Can't open %s for output", fname);
  434.  
  435.                 D (("UUCPBugReport(): open output failure, exit\n"));
  436.                 return;
  437.         }
  438.         fname = malloc (strlen (ptr) + 1);
  439.         if (!fname) {
  440.                 t_printf (mainWindow, "Can't malloc() memory for filename");
  441.                 close (outfd);
  442.  
  443.                 D (("UUCPBugReport(): get mem failure, exit\n"));
  444.                 return;
  445.         }
  446.         strcpy (fname, ptr);
  447.  
  448.         OutputStrings (outfd,
  449.                         "Newsgroups: alt.sys.amiga.uucp\n",
  450.                         "Subject: UUCP Bug report from GRn\n",
  451.                         "Distribution: world\n\n",
  452.                         "##B <personal identifier>\n\n",
  453.                         "The above <personal identifier> is for the\n",
  454.                         "bug reporter to use for whatever internal tracking he wants\n",
  455.                         "to do (it must be unique on a person by person basis).\n",
  456.                         "\n##\n",
  457.                         "\n-- \n",
  458.                         NULL);
  459.  
  460.         AppendSignature (outfd);
  461.         close (outfd);
  462.  
  463.         PostNews (0, fname);
  464.         free (fname);
  465.  
  466.         GT_RefreshWindow (mainWindow, NULL);
  467.  
  468.         D (("UUCPBugReport(): exit\n"));
  469.         return;
  470. }
  471.  
  472. /************************************************************************/
  473.  
  474. void    Catchup (void)
  475. {
  476.         ART     *ap;
  477.  
  478.         if (!currentGroup)
  479.                 return;
  480.         currentGroup->articles = currentGroup->unread = 0;
  481.         for (ap = (ART *) currentGroup->artList.lh_Head; ap->node.ln_Succ; ap = (ART *) ap->node.ln_Succ) {
  482.                 ap->state = READ;
  483.                 currentGroup->articles++;
  484.                 treeDirty = !0;
  485.         }
  486. }
  487.  
  488. /************************************************************************/
  489.  
  490. void    Publish (void)
  491. {
  492.         char    temp [512], work [256];
  493.         STRPTR  filename;
  494.         FILE    *infp, *fp;
  495.         UWORD   i, line;    long rslt, len;
  496.         char    *partname;      // temporary file name for this part
  497.         char    *inname;        // file to be published (provided by user)
  498.         char    *outname;       // uuencoded output file (generated by GRn)
  499.         long    lineCount = 0;  // number of lines in uuencoded file
  500.         long    parts;          // how many articles will it take to publish file
  501.         long    part;           // current article
  502.         int     fd;             // input file descriptor
  503.         int     outfd;          // output file descriptor
  504.         char    *p, *ptr;       // temporaries
  505.  
  506.         D (("Publish(): enter\n"));
  507.  
  508.         if (!AslRequestTags (publishReq, TAG_DONE)) {
  509.                 D (("Publish(): AslRequestTags() failure, exit\n"));
  510.                 return;
  511.         }
  512.         i = strlen (publishReq->rf_Dir) + strlen (publishReq->rf_File) + 10;
  513.         if (!(inname = malloc (i))) {
  514.                 t_printf (mainWindow, "Can't malloc %d bytes for filename", i);
  515.  
  516.                 D (("Publish(): exit, get mem failure 1\n"));
  517.                 return;
  518.         }
  519.         strcpy (inname, publishReq->rf_Dir);
  520.         AddPart (inname, publishReq->rf_File, i);
  521.         D (("Publish(): inname = '%s'\n", inname));
  522.  
  523.         if (!SendItRequest ()) {
  524.                 free (inname);
  525.  
  526.                 D (("Publish(): exit, SendItRequest said no\n"));
  527.                 return;
  528.         }
  529.  
  530.         p = TempName ();
  531.         outname = malloc (strlen (p) + 1);
  532.         if (!outname) {
  533.                 t_printf (mainWindow, "Can't get memory for filename");
  534.                 free (inname);
  535.  
  536.                 D (("Publish(): exit, get mem failure 2\n"));
  537.                 return;
  538.         }
  539.         strcpy (outname, p);
  540.         D (("Publish(): outname = '%s'\n", outname));
  541.  
  542.         filename = FilePart (inname);
  543.         CopyStrings (work, "uuencode ", inname, " ", filename, " >", outname, NULL);
  544.         D (("Publish(): uuencode string = '%s'\n", work));
  545.  
  546.         t_printf (mainWindow, "GRn - UUEncoding %s", filename);
  547.  
  548.         rslt = SystemTags (work, SYS_Input, 0,
  549.                                  SYS_Output, 0,
  550.                                  SYS_Asynch, 0,     // NP_Synchronous, 1,
  551.                                  NP_StackSize, 32000,
  552.                                  TAG_DONE);
  553.         if (rslt != 0) {
  554.                 strcpy (temp, "GRn - Your UUEncode had a return value of ");
  555.                 strcat (temp, itoa (rslt));
  556.                 if (TwoGadgetRequest (temp,
  557.                                      "It may not have completed normally. Shall I continue?",
  558.                                      "_Yes", "_No") == 0) {
  559.                         remove (outname);
  560.                         free (outname);
  561.                         free (inname);
  562.  
  563.                         D (("Publish(): exit, bad uuencode\n"));
  564.                         return;
  565.                 }
  566.         }
  567.  
  568.         // find the numbers of lines in the uuencoded file
  569.         if ((fd = open (outname, O_RDONLY)) < 0) {
  570.                 OneGadgetRequest ("GRn Error", "Can't open uuencoded file", "Cancel Publish");
  571.                 free (inname);
  572.                 free (outname);
  573.  
  574.                 D (("Publish(): exit, missing uuencoded file\n"));
  575.                 return;
  576.         }
  577.         while (i = read (fd, temp, 512)) {
  578.                 p = temp;
  579.                 while (i--) {
  580.                         if (*p == '\n')
  581.                                 lineCount++;
  582.                         p++;
  583.                 }
  584.         }
  585.         close (fd);
  586.  
  587.         // calculate the number of postings required...
  588.         parts = (lineCount + 499) / 500;
  589.  
  590.         // FIXME: remove this last piece of STDIO (use of infp)
  591.  
  592.         if (!(infp = fopen (outname, "r"))) {
  593.                 OneGadgetRequest ("GRn Error", "Can't open uuencoded file", "Cancel Publish");
  594.                 free (inname);
  595.                 free (outname);
  596.  
  597.                 D (("Publish(): exit, missing uuencoded file 2\n"));
  598.                 return;
  599.         }
  600.  
  601.         line = 0;
  602.         for (part = 1; part <= parts; part++) {
  603.                 t_printf (mainWindow, "Publishing part %d of %d", part, parts);
  604.                 partname = TempName ();
  605.                 if ((outfd = creat (partname, 0660)) < 0) {
  606.                         fclose(infp);
  607.                         free (inname);
  608.                         free (outname);
  609.                         OneGadgetRequest("GRn Error", "Can't open uuencoded file", "Cancel Publish");
  610.  
  611.                         D (("Publish(): exit, open output failure\n"));
  612.                         return;
  613.                 }
  614.                 OutputStrings (outfd, "Newsgroups: ", currentGroup->groupName,
  615.                                       "\n", NULL);
  616.                 OutputStrings (outfd, "Subject: Posting of ",
  617.                                       filename,
  618.                                       " (Part ",
  619.                                       itoa (part),
  620.                                       "/",
  621.                                       itoa (parts),
  622.                                       ")\n",
  623.                                       NULL);
  624.  
  625.                 // FIXME - this should be configurable!
  626.                 OutputStrings (outfd, "Distribution: world\n\n", NULL);
  627.  
  628.                 CopyStrings (work, "Posting ", filename, " in ", itoa (parts),
  629.                                    " parts", NULL);
  630.  
  631.                 for (i = 0; line < lineCount && i < 500; i++, line++) {
  632.                         // should we let the user cancel the process?
  633.                         GuageRequest ((100 * line) / lineCount,
  634.                                      "GRn - Publishing",
  635.                                      work,
  636.                                      "Wait");
  637.                         if (!fgets (temp, 512, infp)) {
  638.                                 line = lineCount;
  639.                                 part = parts + 1;
  640.                                 break;
  641.                         }
  642.                         OutputStrings (outfd, temp, NULL);
  643.                 }
  644.                 OutputStrings (outfd, "\n--\n", NULL);
  645.  
  646.                 AppendNewsGroupSignature (outfd);
  647.                 close (outfd);
  648.  
  649.                 PostNews (-1, partname);    // tell'em not to let user edit.
  650.  
  651.                 GT_RefreshWindow (mainWindow, NULL);
  652.         }
  653.  
  654.         GuageRequest (1000, "GRn - Publishing", work, "Wait");
  655.         fclose (infp);
  656.         free (inname);
  657.         free (outname);
  658.  
  659.         t_printf (mainWindow, "GRn - News Directory");
  660.  
  661.         GT_RefreshWindow (mainWindow, NULL);
  662.  
  663.         D (("Publish(): exit\n"));
  664.         return;
  665. }
  666.  
  667. /************************************************************************/
  668.  
  669. /*
  670.  * void ProcessGadget(id, code);
  671.  * UWORD        id;             gadgetID of gadget to process
  672.  * UWORD        code;           IntuiMessage Code
  673.  *
  674.  * Synopsis:
  675.  *      Process IDCMP message for GadTools gadget.  Simply prints an appropriate string
  676.  *      into the event listview, unless it is palette related (handles palette appropriately).
  677.  */
  678. static void     ProcessGadget (UWORD id, UWORD code) {
  679. /*      GADGET  *gad = gadgetArray[id]; */
  680.         GLIST   *gp;
  681.  
  682.         D (("ProcessGadget(): enter, Group Mode\n"));
  683.  
  684.         switch (id) {
  685.                 case GROUPLIST_ID:
  686.                         gp = (GLIST *) FindListItem (&groupList, code);
  687.                         if (gp == currentGroup) {
  688.                                 mode = ARTICLES_MODE;
  689.                                 break;
  690.                         }
  691.                         if (!gp) {
  692.                                 t_printf (mainWindow, "Error: Can't FindListItem (%d)\n", code);
  693.                                 break;
  694.                         }
  695.                         currentGroup = gp;
  696.                         ValidateOptions ();
  697.                         break;
  698.  
  699.                 case QUIT_ID:
  700.                         mode = QUIT_MODE;
  701.                         break;
  702.  
  703.                 case READ_ID:
  704.                         mode = ARTICLES_MODE;
  705.                         break;
  706.  
  707.                 case CATCHUP_ID:
  708.                         Catchup ();
  709.                         GroupsStatus ();
  710.                         GT_SetGadgetAttrs (gadgetArray [GROUPLIST_ID], mainWindow, NULL,
  711.                                            GTLV_Labels, ~0, TAG_DONE);
  712.                         sprintf (currentGroup->header, "%-40.40s %6d articles %6d UnRead",
  713.                                  currentGroup->groupName,
  714.                                  currentGroup->articles,
  715.                                  currentGroup->unread
  716.                         );
  717.                         GT_SetGadgetAttrs (gadgetArray [GROUPLIST_ID], mainWindow, NULL,
  718.                                            GTLV_Labels, &groupList, TAG_DONE);
  719.                         GT_SetGadgetAttrs (gadgetArray [GROUPLIST_ID], mainWindow, NULL,
  720.                                            GTLV_Selected, GroupID (), TAG_DONE);
  721.                         break;
  722.  
  723.                 case POST_ID:
  724.                         Post (FALSE);
  725.                         break;
  726.  
  727.                 case BUGREPORT_ID:
  728.                         BugReport ();
  729.                         break;
  730.  
  731.                 case JUNK_ID:
  732.                         Junk (!0);
  733.                         break;
  734.  
  735.                 case PUBLISH_ID:
  736.                         Publish ();
  737.                         break;
  738.  
  739.                 case UUCPBUG_ID:
  740.                         UUCPBugReport ();
  741.                         break;
  742.  
  743.                 default:
  744.                         t_printf (mainWindow, "ProcessGadget - id = %d", id);
  745.                         break;
  746.         }
  747.  
  748.         D (("ProcessGadget(): exit, Group Mode\n"));
  749.         return;
  750. }
  751.  
  752. static void     IDCMPFunc (IMSG *m)
  753. {
  754.         GLIST   *NextGroup (), *PrevGroup ();
  755.  
  756.         D (("IDCMPFunc(): enter, Group Mode\n"));
  757.  
  758.         switch (m->Class) {
  759.                 case IDCMP_CLOSEWINDOW:
  760.                         mode = ABORT_MODE;
  761.                         break;
  762.  
  763.                 case IDCMP_VANILLAKEY:
  764.                         switch (m->Code) {
  765.                                 case 'Q':
  766.                                         mode = QUIT_MODE;
  767.                                         break;
  768.  
  769.                                 case 'R':
  770.                                         if (currentGroup->articles)
  771.                                                 mode = ARTICLES_MODE;
  772.                                         break;
  773.  
  774.                                 case 'P':
  775.                                         Post (FALSE);
  776.                                         break;
  777.  
  778.                                 case 'C':
  779.                                         if (currentGroup->unread) {
  780.                                                 Catchup ();
  781.                                                 GroupsStatus ();
  782.                                                 GT_SetGadgetAttrs (gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Labels, ~0, TAG_DONE);
  783.                                                 sprintf (currentGroup->header, "%-40.40s %6d articles %6d UnRead",
  784.                                                          currentGroup->groupName,
  785.                                                          currentGroup->articles,
  786.                                                          currentGroup->unread
  787.                                                 );
  788.                                                 GT_SetGadgetAttrs (gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Labels, &groupList, TAG_DONE);
  789.                                                 GT_SetGadgetAttrs (gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Selected, GroupID(), TAG_DONE);
  790.                                         }
  791.                                         break;
  792.  
  793.                                 case 'B':
  794.                                         BugReport ();
  795.                                         break;
  796.  
  797.                                 case 'J':
  798.                                         Junk (0);
  799.                                         break;
  800.  
  801.                                 case 'U':
  802.                                         UUCPBugReport ();
  803.                                         break;
  804.                         }
  805.                         break;
  806.  
  807.                 case IDCMP_RAWKEY:
  808.                         switch (m->Code) {
  809.                                 case 0x4c:      // up key
  810.                                         currentGroup = PrevGroup ();
  811.                                         GT_SetGadgetAttrs (gadgetArray [GROUPLIST_ID], mainWindow, NULL, GTLV_Selected, GroupID(), TAG_DONE);
  812.                                         GT_SetGadgetAttrs (gadgetArray [GROUPLIST_ID], mainWindow, NULL, GTLV_Top, GroupID(), TAG_DONE);
  813.                                         break;
  814.                                 case 0x4d:      // down key
  815.                                         currentGroup = NextGroup ();
  816.                                         GT_SetGadgetAttrs (gadgetArray [GROUPLIST_ID], mainWindow, NULL, GTLV_Selected, GroupID(), TAG_DONE);
  817.                                         GT_SetGadgetAttrs (gadgetArray [GROUPLIST_ID], mainWindow, NULL, GTLV_Top, GroupID(), TAG_DONE);
  818.                                         break;
  819.                         }
  820.                 default:
  821.                         break;
  822.         }
  823.  
  824.         D (("IDCMPFunc(): exit, Group Mode\n"));
  825.         return;
  826. }
  827.  
  828. void    GroupsWindow (void)
  829. {
  830.         D (("GroupsWindow(): enter\n"));
  831.  
  832.         if (!currentGroup)
  833.                 currentGroup = (GLIST *)groupList.lh_Head;
  834.         if (mode == NEXTGROUPS_MODE || mode == PREVGROUPS_MODE) {
  835.                 mode = ARTICLES_MODE;
  836.                 return;
  837.         }
  838.         NewList (&nullList);
  839.         LayoutGadgets (defaultFont, prefWidth,windowHeight, screenTop);
  840.         gList = CreateGadgets (gadgetArray, gadDefs);
  841.         AddGList (mainWindow, gList, -1, -1, 0);
  842.         RefreshGList (gList, mainWindow, 0, -1);
  843.         GT_RefreshWindow (mainWindow, NULL);
  844.         GT_SetGadgetAttrs (gadgetArray [GROUPLIST_ID], mainWindow, NULL,
  845.                            GTLV_Labels, ~0, TAG_DONE);
  846.         GroupsStatus ();
  847.         GT_SetGadgetAttrs (gadgetArray [GROUPLIST_ID], mainWindow, NULL,
  848.                            GTLV_Labels, &groupList, TAG_DONE);
  849.         GT_SetGadgetAttrs (gadgetArray [GROUPLIST_ID], mainWindow, NULL,
  850.                            GTLV_Selected, GroupID (), TAG_DONE);
  851.         GT_SetGadgetAttrs (gadgetArray [GROUPLIST_ID], mainWindow, NULL,
  852.                            GTLV_Top, GroupID(), TAG_DONE);
  853.         ValidateOptions ();
  854.         t_printf (mainWindow, "GRn - News Directory");
  855.         while (mode == GROUPS_MODE) {
  856.                 WaitPort (mainWindow->UserPort);
  857.                 EventHandler (mainWindow, ProcessGadget, IDCMPFunc, NULL);
  858.         }
  859.         CloseGroups ();
  860.  
  861.         D (("GroupsWindow(): exit\n"));
  862.         return;
  863. }
  864.