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

  1. #include    "defs.h"
  2.  
  3. extern char *FileNameToNewsGroup (char *filename);
  4. extern char *NewsGroupToFileName (char *newsgroup);
  5.  
  6. static LIST    nullList;
  7. GLIST        *currentGroup = 0;
  8.  
  9. ULONG        totalGroups = 0, totalArticles = 0, unreadArticles = 0;
  10.  
  11. /************************************************************************/
  12.  
  13. /*
  14.  * As each gadget in the GadDefs array above is created, it is assigned a UserID
  15.  * field value, incremented from zero.    The following defines are useful for switch
  16.  * statements, etc.  Enum would also work.  Be careful, if you add new gadgets in
  17.  * the middle of the initializations above, because you will need to renumber these
  18.  * defines.
  19.  */
  20. static enum GADGET_IDS {
  21.     GROUPLIST_ID,
  22.     QUIT_ID,
  23.     READ_ID,
  24.     POST_ID,
  25.     CATCHUP_ID,
  26.     PUBLISH_ID,
  27.     JUNK_ID,
  28.     BUGREPORT_ID,
  29.     UUCPBUG_ID,
  30.     STATUS_ID,
  31.     MAXGADGET,
  32. };
  33.  
  34. static GADGET    *gadgetArray[MAXGADGET];
  35.  
  36. /*
  37.  * Misc tags arrays
  38.  */
  39. static TAGS    nullTags[] = { GT_Underscore, '_', TAG_DONE,0 };
  40. static TAGS    disableTags[] = { GT_Underscore, '_', GA_Disabled,TRUE, TAG_DONE,0 };
  41. static TAGS    enableTags[] = { GT_Underscore, '_', GA_Disabled,FALSE, TAG_DONE,0 };
  42.  
  43. static TAGS    groupListTags[] = {
  44.     GT_Underscore, '_',
  45.     GTLV_Top, 0,
  46.     GTLV_Labels, &groupList,
  47.     GTLV_ReadOnly, FALSE,
  48.     GTLV_ScrollWidth, 16,
  49.     GTLV_ShowSelected, NULL,
  50.     GTBB_Recessed, FALSE,
  51.     TAG_DONE, 0,
  52. };
  53.  
  54. static TAGS    nullListTags[] = {
  55.     GT_Underscore, '_',
  56.     GTLV_Top, 0,
  57.     GTLV_Labels, &nullList,
  58.     GTLV_ReadOnly, FALSE,
  59.     GTLV_ScrollWidth, 16,
  60.     GTBB_Recessed, FALSE,
  61.     TAG_DONE, 0,
  62. };
  63.  
  64. static char    *nullText = "";
  65. static TAGS    textTags[] = {
  66.     GT_Underscore, '_',
  67.     GTTX_Text, (ULONG)"",
  68.     GTTX_CopyText, TRUE,
  69.     GTTX_Border, TRUE,
  70.     TAG_DONE, 0,
  71. };
  72.  
  73. /*
  74.  * The Array of Gadget definitions.  To create a new gadget, add an initializer
  75.  * here, and create the necessary tags...
  76.  */
  77. static GADDEF    gadDefs[] = {
  78.     groupListTags, LISTVIEW_KIND,0,0,0,0, NG_HIGHLABEL, "",
  79.     enableTags, BUTTON_KIND, 0,0,0,0, NG_HIGHLABEL, "Quit",
  80.     enableTags, BUTTON_KIND, 0,0,0,0, NG_HIGHLABEL, "_Read",
  81.     enableTags, BUTTON_KIND, 0,0,0,0, NG_HIGHLABEL, "_Post",
  82.     enableTags, BUTTON_KIND, 0,0,0,0, NG_HIGHLABEL, "_Catch up",
  83.     enableTags, BUTTON_KIND, 0,0,0,0, NG_HIGHLABEL, "Publish",
  84.     enableTags, BUTTON_KIND, 0,0,0,0, NG_HIGHLABEL, "_Junk",
  85.     enableTags, BUTTON_KIND, 0,0,0,0, NG_HIGHLABEL, "_Bug Report",
  86.     enableTags, BUTTON_KIND, 0,0,0,0, NG_HIGHLABEL, "_UUCP Bug Report",
  87.     textTags, TEXT_KIND, 0,0,0,0, NG_HIGHLABEL, "",
  88.     0,0,0,0,0,0,0,0,
  89. };
  90.  
  91. static GADGET    *gList = 0;
  92.  
  93. static void    LayoutGadgets(font,width,height,top)
  94. FONT        *font;
  95. short        width,height,top;
  96. {
  97.     short    i, x,y, fh;
  98.     RPORT    rPort, *rp = &rPort;
  99.  
  100.     InitRastPort(rp);
  101.     SetFont(rp, font);
  102.     y = top+INTERHEIGHT/2;
  103.  
  104.     fh = rp->TxHeight+2;
  105.     gadDefs[GROUPLIST_ID].left = INTERWIDTH;
  106.     gadDefs[GROUPLIST_ID].top = y;
  107.     gadDefs[GROUPLIST_ID].width = width-INTERWIDTH-INTERWIDTH;
  108.     gadDefs[GROUPLIST_ID].height = 12*fh+INTERHEIGHT;
  109.     y += 12*fh+INTERHEIGHT;
  110.  
  111.     fh = topazRP->TxHeight+2;
  112.     x = INTERWIDTH;
  113.     for (i=QUIT_ID; i<=UUCPBUG_ID; i++) {
  114.         gadDefs[i].left = x;
  115.         gadDefs[i].top = y;
  116.         gadDefs[i].width = TextLen(topazRP, gadDefs[i].text)+8;
  117.         gadDefs[i].height = fh+2;
  118.         x += gadDefs[i].width + INTERWIDTH;
  119.     }
  120.     y += fh+INTERHEIGHT+fh+INTERHEIGHT+fh+INTERHEIGHT;
  121.     y += height-y-fh-fh-INTERHEIGHT-4;
  122.  
  123.     gadDefs[STATUS_ID].left = INTERWIDTH;
  124.     gadDefs[STATUS_ID].top = y;
  125.     gadDefs[STATUS_ID].width = width-INTERWIDTH-INTERWIDTH;
  126.     gadDefs[STATUS_ID].height = fh+2;
  127.     y += fh+4;
  128. }
  129.  
  130. /************************************************************************/
  131.  
  132. void    CloseGroups() {
  133.     if (!gList) return;
  134.     if (RemoveGList(mainWindow, gList, -1) == -1) {
  135.         printf("RemoveGList() failed\n");
  136.         return;
  137.     }
  138.     FreeGadgets(gList);
  139.     gList = 0;
  140.     ClearWindow();
  141. }
  142.  
  143. void    GroupsStatus() {
  144.     GLIST        *gp;
  145.     ART        *ap;
  146.     static char    groupStatus[256];
  147.  
  148.  
  149.     totalGroups = 0; totalArticles = 0; unreadArticles = 0;
  150.     for (gp=(GLIST *)groupList.lh_Head; gp->node.ln_Succ; gp=(GLIST *)gp->node.ln_Succ) {
  151.         gp->articles = gp->unread = 0;
  152.         totalGroups++;
  153.         for (ap=(ART *)gp->artList.lh_Head; ap->node.ln_Succ; ap = (ART *)ap->node.ln_Succ) {
  154.             totalArticles++; gp->articles++;
  155.             if (ap->state == UNREAD) { unreadArticles++; gp->unread++; }
  156.         }
  157.         sprintf(gp->header, "%-40.40s %6d articles %6d UnRead", gp->groupName, gp->articles, gp->unread);
  158.     }
  159.     sprintf(groupStatus, " *** %d groups, %d articles (%d unread)", totalGroups, totalArticles, unreadArticles);
  160.     GT_SetGadgetAttrs(gadgetArray[STATUS_ID], mainWindow, NULL, GTTX_Text, groupStatus, TAG_DONE);
  161. }
  162.  
  163. UWORD    GroupID() {
  164.     UWORD    n;
  165.     GLIST    *gp = (GLIST *)groupList.lh_Head;
  166.     n = 0;
  167.     while (gp->node.ln_Succ) {
  168.         if (gp == currentGroup) return n;
  169.         gp = (GLIST *)gp->node.ln_Succ;
  170.         n++;
  171.     }
  172.     return ~0;
  173. }
  174.  
  175. static void    ValidateOptions() {
  176.     short    i;
  177.  
  178.     if (!currentGroup) {
  179.         for (i=READ_ID; i<=PUBLISH_ID; i++) {
  180.             GT_SetGadgetAttrs(gadgetArray[i], mainWindow, NULL, GA_Disabled, TRUE, TAG_DONE);
  181.         }
  182.         return;
  183.     }
  184.     if (currentGroup->articles == 0) {
  185.         GT_SetGadgetAttrs(gadgetArray[READ_ID], mainWindow, NULL, GA_Disabled, TRUE, TAG_DONE);
  186.         GT_SetGadgetAttrs(gadgetArray[CATCHUP_ID], mainWindow, NULL, GA_Disabled, TRUE, TAG_DONE);
  187.         return;
  188.     }
  189.     if (currentGroup->unread == 0) {
  190.         GT_SetGadgetAttrs(gadgetArray[READ_ID], mainWindow, NULL, GA_Disabled, FALSE, TAG_DONE);
  191.         GT_SetGadgetAttrs(gadgetArray[CATCHUP_ID], mainWindow, NULL, GA_Disabled, TRUE, TAG_DONE);
  192.         return;
  193.     }
  194.     for (i=READ_ID; i<=PUBLISH_ID; i++) {
  195.         GT_SetGadgetAttrs(gadgetArray[i], mainWindow, NULL, GA_Disabled, FALSE, TAG_DONE);
  196.     }
  197. }
  198.  
  199. /************************************************************************/
  200.  
  201. // Junk an existing newsgroup
  202. //
  203. // This only involves removing the group (and its articles) from the newstree
  204. // THEY WILL STAY IN THE UUNEWS: DIRECTORY
  205. //
  206. void    Junk(BOOL flag) {
  207.     ART    *ap;
  208.     GLIST    *gp;
  209.  
  210.     if (flag) {
  211.         if (!TwoGadgetRequest("GRn - Request", " Remove this group from your Active list?", "_YES", "_NO")) return;
  212.     }
  213.     while (!EmptyList(¤tGroup->artList)) {
  214.         ap = (ART *)RemHead(¤tGroup->artList);
  215.         if (ap->from) free(ap->from);
  216.         if (ap->subject) free(ap->subject);
  217.         free(ap);
  218.     }
  219.     GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Labels, ~0, TAG_DONE);
  220.     gp = (groupList.lh_TailPred == (NODE *)currentGroup) ? (GLIST *)groupList.lh_Head : (GLIST *)currentGroup->node.ln_Succ;
  221.     Remove((NODE *)currentGroup);
  222.     free(currentGroup);
  223.     currentGroup = gp;
  224.     GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Labels, &groupList, TAG_DONE);
  225.     GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Selected, GroupID(), TAG_DONE);
  226.     GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Top, GroupID(), TAG_DONE);
  227.     treeDirty = !0;
  228. }
  229.  
  230. /************************************************************************/
  231.  
  232. void    BugReport() {
  233.     char    fname[256], temp[512], work[256];
  234.     FILE    *fp, *outfp;
  235.  
  236.     sprintf(fname, "t:%s%x-text.txt", userName, FindTask(0));
  237.     unlink(fname);
  238.     outfp = fopen(fname, "w");
  239.     if (!outfp) {
  240.         t_printf(mainWindow, "Can't open %s for output", fname);
  241.         return;
  242.     }
  243.     fprintf(outfp, "To: grnbugs@amiga0.sf-bay.org\n");
  244.     fprintf(outfp, "Subject: Bug Report For %s\n", GRN_VERSION);
  245.     fprintf(outfp, "X-NewsSoftware: %s\n\n", GRN_VERSION);
  246.     fprintf(outfp, "\n--\n");
  247.     strcpy(temp, uulib);
  248.     sprintf(work, "%s.signature", userName);
  249.     AddPart(temp, work, 256);
  250.     fp = fopen(temp, "r");
  251.     if (!fp) {
  252.         strcpy(temp, uulib);
  253.         AddPart(temp, ".signature", 256);
  254.         fp = fopen(temp, "r");
  255.     }
  256.     if (!fp) {
  257.         fprintf(outfp, ".signature under construction\n");
  258.     }
  259.     else {
  260.         while (fgets(temp, 512, fp)) {
  261.             fprintf(outfp, "%s", temp);
  262.         }
  263.         fclose(fp);
  264.     }
  265.     fclose(outfp);
  266.     sprintf(temp, "%s %s", mailEditor, fname);
  267.     Execute(temp, 0,0);
  268.     if (!TwoGadgetRequest("GRn - Request", "         Send it off?     ", "_YES", "_NO")) return;
  269.     sprintf(temp, "%s >nil: <%s -f %s",
  270.         sendMail, fname, userName
  271.     );
  272.     Execute(temp, 0,0);
  273.     unlink(fname);
  274. }
  275.  
  276. /************************************************************************/
  277.  
  278. void    UUCPBugReport() {
  279.     char    fname[256], rname[256], temp[512];
  280.     char    work[256];
  281.     FILE    *fp, *outfp;
  282.  
  283.     sprintf(fname, "t:%s%x-text.txt", userName, FindTask(0));
  284.     unlink(fname);
  285.     outfp = fopen(fname, "w");
  286.     if (!outfp) {
  287.         t_printf(mainWindow, "Can't open %s for output", fname);
  288.         return;
  289.     }
  290.     fprintf(outfp, "Newsgroups: alt.sys.amiga.uucp\n");
  291.     fprintf(outfp, "Subject: UUCP Bug report from GRn\n");
  292.     fprintf(outfp, "Distribution: world\n\n");
  293.     fprintf(outfp, "##B <personal identifier>\n\n");
  294.     fprintf(outfp, "The above <personal identifier> is for the\n");
  295.     fprintf(outfp, "bug reporter can use for whatever internal tracking he wants\n");
  296.     fprintf(outfp, "to do (it should be unique on a person by person basis).\n");
  297.     fprintf(outfp, "\n##\n");
  298.     fprintf(outfp, "\n--\n");
  299.  
  300.     strcpy(temp, uulib);
  301.     sprintf(work, "%s.signature", userName);
  302.     AddPart(temp, work, 256);
  303.     fp = fopen(temp, "r");
  304.     if (!fp) {
  305.         strcpy(temp, uulib);
  306.         AddPart(temp, ".signature", 256);
  307.         fp = fopen(temp, "r");
  308.     }
  309.     if (!fp) {
  310.         fprintf(outfp, ".signature under construction\n");
  311.     }
  312.     else {
  313.         while (fgets(temp, 512, fp)) {
  314.             fprintf(outfp, "%s", temp);
  315.         }
  316.         fclose(fp);
  317.     }
  318.     fclose(outfp);
  319.     sprintf(temp, "%s %s", newsEditor, fname);
  320.     Execute(temp, 0,0);
  321.     if (!SendItRequest()) return;
  322.     sprintf(rname, "t:%s%x-refs.txt", userName, FindTask(0));
  323.     unlink(rname);
  324.     outfp = fopen(rname, "w");
  325.     if (outfp) fprintf(outfp, "X-NewsSoftware: %s\n", GRN_VERSION);
  326.     if (outfp) {
  327.         fclose(outfp);
  328.         sprintf(temp, "RUN <nil: >nil: %s %s -R %s -x %s -x %s",
  329.             postNews, fname, rname, fname, rname
  330.         );
  331.     }
  332.     else {
  333.         sprintf(temp, "RUN <nil: >nil: %s %s -x %s",
  334.             postNews, fname, fname
  335.         );
  336.     }
  337.     Execute(temp, 0,0);
  338.     GT_RefreshWindow(mainWindow, NULL);
  339. }
  340.  
  341. /************************************************************************/
  342.  
  343. void    Catchup() {
  344.     ART    *ap;
  345.  
  346.     if (!currentGroup) return;
  347.     currentGroup->articles = currentGroup->unread = 0;
  348.     for (ap=(ART *)currentGroup->artList.lh_Head; ap->node.ln_Succ; ap = (ART *)ap->node.ln_Succ) {
  349.         ap->state = READ;
  350.         currentGroup->articles++;
  351.         treeDirty = !0;
  352.     }
  353. }
  354.  
  355. /************************************************************************/
  356.  
  357. void    Publish() {
  358.     char    inname[256], outname[256], partname[256], rname[256], temp[512], work[256];
  359.     STRPTR    filename;
  360.     FILE    *infp, *outfp, *fp;
  361.     UWORD    i, line, lineCount = 0, parts, part;
  362.  
  363.     if (!AslRequestTags(publishReq, TAG_DONE)) return;
  364.     strcpy(inname, publishReq->rf_Dir);
  365.     AddPart(inname, publishReq->rf_File, 256);
  366.  
  367.     if (!SendItRequest()) return;
  368.     sprintf(outname, "t:%s%x-text.uu", userName, FindTask(0));
  369.     unlink(outname);
  370.     filename = FilePart(inname);
  371.     sprintf(work, "uuencode >%s %s %s", outname, inname, filename);
  372.     t_printf(mainWindow, "GRn - UUEncoding %s", filename);
  373.     Execute(work, 0,0);
  374.     infp = fopen(outname, "r");
  375.     if (!infp) {
  376.         OneGadgetRequest("GRN Error", "Can't open uuencoded file", "Cancel Publish");
  377.         return;
  378.     }
  379.     while (fgets(work, 512, infp)) lineCount++;
  380.     fclose(infp);
  381.     parts = (lineCount+499) / 500;
  382.  
  383.     infp = fopen(outname, "r");
  384.     if (!infp) {
  385.         OneGadgetRequest("GRN Error", "Can't open uuencoded file", "Cancel Publish");
  386.         return;
  387.     }
  388.  
  389.     line = 0;
  390.     for (part = 1; part <= parts; part++) {
  391.         t_printf(mainWindow, "Publishing part %d of %d", part, parts);
  392.         sprintf(partname, "t:%s%x-text.txt", userName, FindTask(0));
  393.         outfp = fopen(partname, "w");
  394.         if (!outfp) {
  395.             fclose(infp);
  396.             OneGadgetRequest("GRN Error", "Can't open uuencoded file", "Cancel Publish");
  397.             return;
  398.         }
  399.         fprintf(outfp, "Newsgroups: %s\n", currentGroup->groupName);
  400.         if (parts > 9 && part < 10) {
  401.             fprintf(outfp, "Subject: Posting of %s (Part %02d/%d)\n", filename, part, parts);
  402.         }
  403.         else {
  404.             fprintf(outfp, "Subject: Posting of %s (Part %d/%d)\n", filename, part, parts);
  405.         }
  406.         fprintf(outfp, "Distribution: world\n\n");
  407.  
  408.         sprintf(work, "Posting %s in %d parts", filename, parts);
  409.         for (i=0; line<lineCount && i < 500; i++, line++) {
  410.             GuageRequest(100*line/lineCount, "GRn - Publishing", work, "STOP");
  411.             if (!fgets(temp, 512, infp)) { line = lineCount; part = parts+1; break; }
  412.             fprintf(outfp, "%s", temp);
  413.         }
  414.         fprintf(outfp, "\n--\n");
  415.  
  416.         strcpy(temp, uulib);
  417.         sprintf(work, "%s.signature", userName);
  418.         AddPart(temp, work, 256);
  419.         fp = fopen(temp, "r");
  420.         if (!fp) {
  421.             strcpy(temp, uunews);
  422.             AddPart(temp, NewsGroupToFileName (currentGroup->groupName), 256);
  423.             AddPart(temp, work, 256);
  424.             fp = fopen(temp, "r");
  425.         }
  426.         if (!fp) {
  427.             strcpy(temp, uulib);
  428.             AddPart(temp, ".signature", 256);
  429.             fp = fopen(temp, "r");
  430.         }
  431.         if (!fp) {
  432.             fprintf(outfp, ".signature under construction\n");
  433.         }
  434.         else {
  435.             while (fgets(temp, 512, fp)) {
  436.                 fprintf(outfp, "%s", temp);
  437.             }
  438.             fclose(fp);
  439.         }
  440.         fclose(outfp);
  441.  
  442.         sprintf(rname, "t:%s%x-refs.txt", userName, FindTask(0));
  443.         unlink(rname);
  444.         outfp = fopen(rname, "w");
  445.         if (outfp) fprintf(outfp, "X-NewsSoftware: %s\n", GRN_VERSION);
  446.         if (outfp) {
  447.             fclose(outfp);
  448.             sprintf(temp, "%s %s -R %s -x %s -x %s",
  449.                 postNews, partname, rname, partname, rname
  450.             );
  451.         }
  452.         else {
  453.             sprintf(temp, "%s %s -x %s",
  454.                 postNews, partname, partname
  455.             );
  456.         }
  457.         Execute(temp, 0,0);
  458.         unlink(partname);
  459.     }
  460.     GuageRequest(1000, "GRn - Publishing", work, "STOP");
  461.     fclose(infp);
  462.     t_printf(mainWindow, "GRn - News Directory");
  463.     GT_RefreshWindow(mainWindow, NULL);
  464. }
  465.  
  466. /************************************************************************/
  467.  
  468. /*
  469.  * void ProcessGadget(id, code);
  470.  * UWORD    id;        gadgetID of gadget to process
  471.  * UWORD    code;        IntuiMessage Code
  472.  *
  473.  * Synopsis:
  474.  *    Process IDCMP message for GadTools gadget.  Simply prints an appropriate string
  475.  *    into the event listview, unless it is palette related (handles palette appropriately).
  476.  */
  477. static void    ProcessGadget(UWORD id, UWORD code) {
  478. /*    GADGET    *gad = gadgetArray[id]; */
  479.     GLIST    *gp;
  480.  
  481.     switch (id) {
  482.         case GROUPLIST_ID:
  483.             gp = (GLIST *)FindListItem(&groupList, code);
  484.             if (gp == currentGroup) { mode = ARTICLES_MODE; break; }
  485.             if (!gp) {
  486.                 t_printf(mainWindow, "Error: Can't FindListItem(%d)\n", code);
  487.                 break;
  488.             }
  489.             currentGroup = gp;
  490.             ValidateOptions();
  491.             break;
  492.         case QUIT_ID:
  493.             mode = QUIT_MODE;
  494.             break;
  495.         case READ_ID:
  496.             mode = ARTICLES_MODE;
  497.             break;
  498.         case CATCHUP_ID:
  499.             Catchup();
  500.             GroupsStatus();
  501.             GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Labels, ~0, TAG_DONE);
  502.             sprintf(currentGroup->header, "%-40.40s %6d articles %6d UnRead",
  503.                 currentGroup->groupName,
  504.                 currentGroup->articles,
  505.                 currentGroup->unread
  506.             );
  507.             GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Labels, &groupList, TAG_DONE);
  508.             GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Selected, GroupID(), TAG_DONE);
  509.             break;
  510.         case POST_ID:
  511.             Post(FALSE);
  512.             break;
  513.         case BUGREPORT_ID:
  514.             BugReport();
  515.             break;
  516.         case JUNK_ID:
  517.             Junk(!0);
  518.             break;
  519.         case PUBLISH_ID:
  520.             Publish();
  521.             break;
  522.         case UUCPBUG_ID:
  523.             UUCPBugReport();
  524.             break;
  525.         default:
  526.             t_printf(mainWindow, "ProcessGadget - id = %d", id); break;
  527.     }
  528. }
  529.  
  530. static void    IDCMPFunc(m)
  531. IMSG        *m;
  532. {
  533.     GLIST    *NextGroup(), *PrevGroup();
  534.  
  535.     switch (m->Class) {
  536.         case IDCMP_CLOSEWINDOW:
  537.             mode = ABORT_MODE;
  538.             break;
  539.         case IDCMP_VANILLAKEY:
  540.             switch (m->Code) {
  541.                 case 'R':       if (currentGroup->articles) mode = ARTICLES_MODE;
  542.                         break;
  543.                 case 'P':       Post(FALSE); break;
  544.                 case 'C':       if (currentGroup->unread) {
  545.                             Catchup();
  546.                             GroupsStatus();
  547.                             GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Labels, ~0, TAG_DONE);
  548.                             sprintf(currentGroup->header, "%-40.40s %6d articles %6d UnRead",
  549.                                 currentGroup->groupName,
  550.                                 currentGroup->articles,
  551.                                 currentGroup->unread
  552.                             );
  553.                             GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Labels, &groupList, TAG_DONE);
  554.                             GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Selected, GroupID(), TAG_DONE);
  555.                         }
  556.                         break;
  557.                 case 'B':       BugReport(); break;
  558.                 case 'J':       Junk(0); break;
  559.                 case 'U':       UUCPBugReport(); break;
  560.             }
  561.             break;
  562.         case IDCMP_RAWKEY:
  563.             switch (m->Code) {
  564.                 case 0x4c:    // up key
  565.                         currentGroup = PrevGroup();
  566.                         GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Selected, GroupID(), TAG_DONE);
  567.                         GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Top, GroupID(), TAG_DONE);
  568.                         break;
  569.                 case 0x4d:    // down key
  570.                         currentGroup = NextGroup();
  571.                         GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Selected, GroupID(), TAG_DONE);
  572.                         GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Top, GroupID(), TAG_DONE);
  573.                         break;
  574.             }
  575.         default:
  576.             break;
  577.     }
  578. }
  579.  
  580. void    GroupsWindow() {
  581.     if (!currentGroup) currentGroup = (GLIST *)groupList.lh_Head;
  582.     if (mode == NEXTGROUPS_MODE || mode == PREVGROUPS_MODE) {
  583.         mode = ARTICLES_MODE;
  584.         return;
  585.     }
  586.     NewList(&nullList);
  587.     LayoutGadgets(defaultFont, prefWidth,windowHeight, screenTop);
  588.     gList = CreateGadgets(&gadgetArray[0], &gadDefs[0]);
  589.     AddGList(mainWindow, gList, -1, -1, 0);
  590.     RefreshGList(gList, mainWindow, 0, -1);
  591.     GT_RefreshWindow(mainWindow, NULL);
  592.     GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Labels, ~0, TAG_DONE);
  593.     GroupsStatus();
  594.     GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Labels, &groupList, TAG_DONE);
  595.     GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Selected, GroupID(), TAG_DONE);
  596.     GT_SetGadgetAttrs(gadgetArray[GROUPLIST_ID], mainWindow, NULL, GTLV_Top, GroupID(), TAG_DONE);
  597.     ValidateOptions();
  598.     t_printf(mainWindow, "GRn - News Directory");
  599.     while (mode == GROUPS_MODE) {
  600.         WaitPort (mainWindow->UserPort);
  601.         EventHandler(mainWindow, ProcessGadget, IDCMPFunc, NULL);
  602.     }
  603.     CloseGroups();
  604. }
  605.