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

  1.  
  2. /*
  3.  *  DISPLAY.C
  4.  *
  5.  *  This module handles all display windows.
  6.  *
  7.  */
  8.  
  9. #include <exec/types.h>
  10. #include "defs.h"
  11. #include <intuition/intuition.h>
  12.  
  13. Prototype int getyn(char *);
  14. Prototype void *OpenBrowseDisplay(char *, char *, short);
  15. Prototype void SetBrowseTitle(void *, char *);
  16. Prototype void CloseBrowseDisplay(void *);
  17. Prototype void ChangeBrowseDisplay(void *, char *, char *);
  18. Prototype int WaitBrowseEvent(void **, int *, int *);
  19. Prototype void    LoadDisplayConfig(void);
  20. Prototype void    SaveDisplayConfig(void);
  21.  
  22. Local void TabExpand(char *, short);
  23.  
  24.  
  25.  
  26. #define MAXCONF 3
  27.  
  28. typedef struct Window        Window;
  29. typedef struct NewWindow    NewWindow;
  30. typedef struct IntuiMessage IMsg;
  31.  
  32. typedef struct Display {
  33.     struct Display *Next;
  34.     Window  *Win;        /*    associated window    */
  35.     char    *Name;        /*    name of file        */
  36.     char    *Title;        /*    window title        */
  37.     FILE    *Fi;        /*    file pointer        */
  38.     long    WMask;        /*    wait mask for window    */
  39.     short   Id;         /*    config id        */
  40.     short   FlagRefresh;
  41.     short   ColStart;
  42.     long    FirstNonHdrLine;/*    first non-header line    */
  43.  
  44.     long    TLineNo;        /*    line # for top line    */
  45.     long    TPos;        /*    position (top line)     */
  46.     long    BPos;        /*    position (bottom line)  */
  47.     long    XPos;        /*    end of file (or scan)   */
  48.     long    WLines;        /*    lines displayed in win    */
  49.     long    FLines;        /*    lines in file if known    */
  50. } Display;
  51.  
  52. typedef struct Config {
  53.     short   TopEdge;
  54.     short   LeftEdge;
  55.     short   Width;
  56.     short   Height;
  57. } Config;
  58.  
  59. static long    WMask;       /*  Window mask       */
  60. static Display *CachDisp;  /*  last display that had an event           */
  61. static Display *DispBase;  /*  list of displays    */
  62. static short   FlagRefresh;
  63.  
  64. static Config  ConfAry[MAXCONF];
  65.  
  66. Local int   HandleEvent(Display *, int *, int *);
  67. Local void  RefreshBrowseDisplay(Display *);
  68. Local void  SaveWindowConfig(Display *);
  69. Local long  BackupFile(Display *, long, long);
  70. Local void  SetRefresh(Display *, int);
  71.  
  72. #ifndef LATTICE
  73. extern void *OpenWindow();
  74. extern void *GetMsg();
  75. #endif
  76.  
  77. void *
  78. OpenBrowseDisplay(fileName, title, id)
  79. char *fileName;
  80. char *title;
  81. short id;
  82. {
  83.     static NewWindow Nw = {
  84.     0, 0, 320, 200, -1, -1,
  85.     CLOSEWINDOW|NEWSIZE|MOUSEBUTTONS|VANILLAKEY|REFRESHWINDOW,
  86.     WINDOWSIZING|WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|
  87.     SIMPLE_REFRESH|ACTIVATE,
  88.     NULL, NULL, NULL, NULL, NULL,
  89.     32, 16, -1, -1, WBENCHSCREEN
  90.     };
  91.     Display *disp = malloc(sizeof(Display));
  92.  
  93.     if (title == NULL)
  94.     title = fileName;
  95.  
  96.     setmem(disp, sizeof(Display), 0);
  97.  
  98.     if (id < 0 || id >= MAXCONF)
  99.     id = MAXCONF - 1;
  100.  
  101.     {
  102.     Config *conf = ConfAry + id;
  103.     Nw.LeftEdge = conf->LeftEdge;
  104.     Nw.TopEdge  = conf->TopEdge;
  105.     Nw.Width    = conf->Width;
  106.     Nw.Height   = conf->Height;
  107.     if (Nw.Width < 32) {
  108.         Nw.LeftEdge = 40;
  109.         Nw.Width = 600;
  110.     }
  111.     if (Nw.Height < 16)
  112.         Nw.Height = 150;
  113.     }
  114.  
  115.     disp->Win = OpenWindow(&Nw);
  116.     if (disp->Win == NULL) {
  117.     Nw.LeftEdge = 0;
  118.     Nw.TopEdge  = 0;
  119.     Nw.Width    = 320;
  120.     Nw.Height   = 100;
  121.     disp->Win = OpenWindow(&Nw);
  122.     }
  123.  
  124.     if (disp->Win) {
  125.     disp->Name = strdup(fileName);
  126.     disp->Title= strdup(title);
  127.     disp->WMask = 1 << disp->Win->UserPort->mp_SigBit;
  128.     disp->Id = id;
  129.  
  130.     SetAPen(disp->Win->RPort, 1);
  131.  
  132.     SetWindowTitles(disp->Win, disp->Title, (char *)-1L);
  133.  
  134.     disp->Next = DispBase;
  135.     DispBase = disp;
  136.  
  137.     WMask |= disp->WMask;
  138.  
  139.     SetRefresh(disp, 0);
  140.     if (disp->Fi = fopen(disp->Name, "r")) {
  141.         disp->FirstNonHdrLine = 0;
  142.         while (fgets(TmpBuf, sizeof(TmpBuf), disp->Fi) && TmpBuf[0] != '\n')
  143.         ++disp->FirstNonHdrLine;
  144.     }
  145.     } else {
  146.     free(disp);
  147.     disp = NULL;
  148.     }
  149.     return((void *)disp);
  150. }
  151.  
  152. void
  153. SetBrowseTitle(_disp, title)
  154. void *_disp;
  155. char *title;
  156. {
  157.     Display *disp = _disp;
  158.     char *old = disp->Title;
  159.  
  160.     disp->Title = strdup(title);
  161.     SetWindowTitles(disp->Win, disp->Title, (char *)-1L);
  162.     free(old);
  163. }
  164.  
  165. void
  166. CloseBrowseDisplay(_disp)
  167. void *_disp;
  168. {
  169.     Display *disp = _disp;
  170.     Display *d;
  171.  
  172.     if (disp == CachDisp)
  173.     CachDisp = NULL;
  174.  
  175.     if (DispBase == disp) {                     /*  unlink display  */
  176.     DispBase = disp->Next;
  177.     } else {
  178.     for (d = DispBase; d; d = d->Next) {
  179.         if (d->Next == disp) {
  180.         d->Next = disp->Next;
  181.         break;
  182.         }
  183.     }
  184.     }
  185.  
  186.     SetWindowTitles(disp->Win, NULL, NULL);
  187.  
  188.     if (disp->Win) {
  189.     SaveWindowConfig(disp);
  190.     CloseWindow(disp->Win);
  191.     }
  192.  
  193.     WMask &= ~disp->WMask;
  194.  
  195.     free(disp->Title);
  196.     free(disp->Name);
  197.     if (disp->Fi)
  198.     fclose(disp->Fi);
  199.     free(disp);
  200. }
  201.  
  202. /*
  203.  *  Change file being displayed
  204.  */
  205.  
  206. void
  207. ChangeBrowseDisplay(_disp, fileName, title)
  208. void *_disp;
  209. char *fileName;
  210. char *title;
  211. {
  212.     Display *disp = _disp;
  213.     Window *win = disp->Win;
  214.  
  215.     if (title == NULL)
  216.     title = fileName;
  217.  
  218.     {
  219.     char *old = disp->Title;
  220.     disp->Title = strdup(title);
  221.     SetWindowTitles(disp->Win, disp->Title, (char *)-1L);
  222.     free(old);
  223.     }
  224.  
  225.     free(disp->Name);
  226.     disp->Name = strdup(fileName);
  227.     if (disp->Fi) {
  228.     fclose(disp->Fi);
  229.     disp->Fi = NULL;
  230.     }
  231.  
  232.     disp->TLineNo = 0;
  233.     disp->TPos = 0;
  234.     disp->XPos = 0;
  235.     disp->WLines = 0;
  236.     disp->FLines = 0;
  237.  
  238.     SetRefresh(disp, 0);
  239. }
  240.  
  241. /*
  242.  *  Wait for an event.    While waiting finish up scanning files for which we
  243.  *  do not know the line number extent.  Returns 0 if there are no windows
  244.  *  left.
  245.  */
  246.  
  247. int
  248. WaitBrowseEvent(_pdisp, prow, pcol)
  249. void **_pdisp;
  250. int *prow;
  251. int *pcol;
  252. {
  253.     long mask;
  254.     Display **pdisp = _pdisp;
  255.  
  256.     if (WMask == 0)
  257.     return(0);
  258.  
  259.     for (;;) {
  260.     Display *disp;
  261.  
  262.     if (FlagRefresh && (SetSignal(0,0) & WMask) == 0) {
  263.         for (disp = DispBase; disp; disp = disp->Next) {
  264.         if (disp->FlagRefresh)
  265.             RefreshBrowseDisplay(disp);
  266.         }
  267.         FlagRefresh = 0;
  268.     }
  269.     mask = Wait(WMask);
  270.     if ((disp = CachDisp) && (disp->WMask & mask)) {
  271.         mask &= ~disp->WMask;
  272.         if (HandleEvent(disp, prow, pcol))
  273.         goto event_handled;
  274.     }
  275.     if (mask) {
  276.         for (disp = DispBase; disp; disp = disp->Next) {
  277.         if (mask & disp->WMask) {
  278.             mask &= ~disp->WMask;
  279.             if (HandleEvent(disp, prow, pcol)) {
  280. event_handled:
  281.             *pdisp = disp;
  282.             if (GetHead(&disp->Win->UserPort->mp_MsgList))
  283.                 mask |= disp->WMask;
  284.             if (mask)
  285.                 SetSignal(mask, mask);
  286.             return(1);
  287.             }
  288.         }
  289.         }
  290.     }
  291.     }
  292. }
  293.  
  294. static int
  295. HandleEvent(disp, prow, pcol)
  296. Display *disp;
  297. int *prow;
  298. int *pcol;
  299. {
  300.     int ret = 0;
  301.     IMsg *im;
  302.     Window *win = disp->Win;
  303.  
  304.     while ((ret == 0) && (im = GetMsg(win->UserPort))) {
  305.     switch(im->Class) {
  306.     case CLOSEWINDOW:
  307.         *prow = -1;
  308.         *pcol = -1;
  309.         ret = 1;
  310.         break;
  311.     case VANILLAKEY:
  312.         switch(im->Code) {
  313.         case '2':       /*  page down   */
  314.         case ' ':
  315.         if (disp->BPos != disp->XPos) {
  316.             disp->TPos = disp->BPos;
  317.             disp->TLineNo += disp->WLines;
  318.             SetRefresh(disp, 0);
  319.         }
  320.         break;
  321.         case '8':       /*  page up   this article  */
  322.         if (disp->TPos != 0) {
  323.             disp->TPos = BackupFile(disp, disp->TPos, disp->WLines);
  324.             disp->TLineNo -= disp->WLines;
  325.             SetRefresh(disp, 0);
  326.         }
  327.         break;
  328.         case '3':
  329.         if (disp->BPos != disp->XPos) {
  330.             disp->TPos = BackupFile(disp, disp->XPos, disp->WLines);
  331.             disp->TLineNo = disp->FLines - disp->WLines;    /* XXX */
  332.             if (disp->TLineNo < 0)
  333.             disp->TLineNo = 0;
  334.             SetRefresh(disp, 0);
  335.         }
  336.         break;
  337.         case '9':
  338.         if (disp->TPos != 0) {
  339.             disp->TPos = 0;
  340.             disp->TLineNo = 0;
  341.             SetRefresh(disp, 0);
  342.         }
  343.         break;
  344.         case '6':
  345.         SetRefresh(disp, disp->ColStart + 40);
  346.         break;
  347.         case '4':
  348.         SetRefresh(disp, disp->ColStart - 40);
  349.         break;
  350.         default:
  351.         *prow = -1;
  352.         *pcol = im->Code;
  353.         ret = 1;
  354.         }
  355.         break;
  356.     case MOUSEBUTTONS:
  357.         if (im->Code == SELECTDOWN) {
  358.         *pcol = (im->MouseX - win->BorderLeft) >> 3;
  359.         *prow = ((im->MouseY - win->BorderTop) >> 3) + disp->TLineNo;
  360.         if (*prow >= 0)
  361.             ret = 1;
  362.         }
  363.         break;
  364.     case NEWSIZE:
  365.         SetRefresh(disp, 0);
  366.         break;
  367.     case REFRESHWINDOW:
  368.         BeginRefresh(win);
  369.         RefreshBrowseDisplay(disp);
  370.         EndRefresh(win, 1);
  371.         break;
  372.     default:
  373.         break;
  374.     }
  375.     ReplyMsg(im);
  376.     }
  377.     return(ret);
  378. }
  379.  
  380. static void
  381. RefreshBrowseDisplay(disp)
  382. Display *disp;
  383. {
  384.     long x, y;
  385.     int maxx;
  386.     int dispLines = 0;
  387.     int lineNo;
  388.     Window *win = disp->Win;
  389.     short b;
  390.     short isHdr;
  391.     short rvsMode;
  392.  
  393.     disp->FlagRefresh = 0;
  394.     SetAPen(win->RPort, 0);
  395.     RectFill(win->RPort, win->BorderLeft, win->BorderTop, win->Width - win->BorderRight, win->Height - win->BorderBottom);
  396.     SetAPen(win->RPort, 1);
  397.  
  398.     if (disp->Fi == NULL) {
  399.     disp->Fi = fopen(disp->Name, "r");
  400.     if (disp->Fi == NULL)       /*  can't refresh if can't open file */
  401.         return;
  402.     fseek(disp->Fi, 0L, 2);
  403.     disp->XPos = ftell(disp->Fi);
  404.     }
  405.     if (ftell(disp->Fi) != disp->TPos)
  406.     fseek(disp->Fi, disp->TPos, 0);
  407.     lineNo = disp->TLineNo - 1;
  408.     x = win->BorderLeft;
  409.     y = win->BorderTop + win->RPort->TxBaseline;
  410.     maxx = (win->Width - win->BorderLeft - win->BorderRight) / win->RPort->TxWidth;
  411.  
  412.     b = 0;
  413.     TmpBuf[0] = 0;
  414.  
  415.     while (y < win->Height - win->BorderBottom - 2) {
  416.     int len;
  417.  
  418.     if (TmpBuf[b] == 0) {
  419.         if (fgets(TmpBuf, sizeof(TmpBuf), disp->Fi) == NULL)
  420.         break;
  421.         rvsMode = 0;
  422.         if (++lineNo < disp->FirstNonHdrLine) {
  423.         isHdr = 1;
  424.         if (strncmp(TmpBuf, "Subject:", 8) == 0)
  425.             rvsMode = 1;
  426.         } else {
  427.         isHdr = 0;
  428.         }
  429.         TabExpand(TmpBuf, sizeof(TmpBuf));
  430.         b = 0;
  431.     }
  432.     len = strlen(TmpBuf + b) - disp->ColStart;
  433.     if (len > maxx)
  434.         len = maxx;
  435.     if (len > 0) {
  436.         if (rvsMode) {
  437.         SetAPen(win->RPort, 0);
  438.         SetBPen(win->RPort, 1);
  439.         }
  440.         Move(win->RPort, x, y);
  441.         Text(win->RPort, TmpBuf + b + disp->ColStart, len);
  442.         if (rvsMode) {
  443.         SetAPen(win->RPort, 1);
  444.         SetBPen(win->RPort, 0);
  445.         }
  446.     }
  447.     ++dispLines;
  448.     y += win->RPort->TxHeight;
  449.     if (isHdr || disp->ColStart || len <= 0)
  450.         b = strlen(TmpBuf);
  451.     else
  452.         b += len;
  453.     }
  454.     disp->BPos = ftell(disp->Fi);
  455.     disp->WLines = dispLines;
  456. }
  457.  
  458. void
  459. LoadDisplayConfig()
  460. {
  461.     FILE *fi;
  462.  
  463.     if (fi = fopen("s:dnews.config", "r")) {
  464.     fread(ConfAry, 1, sizeof(ConfAry), fi);
  465.     fclose(fi);
  466.     }
  467. }
  468.  
  469. void
  470. SaveDisplayConfig()
  471. {
  472.     FILE *fi;
  473.  
  474.     if (fi = fopen("s:dnews.config", "w")) {
  475.     fwrite(ConfAry, 1, sizeof(ConfAry), fi);
  476.     fclose(fi);
  477.     }
  478. }
  479.  
  480. static void
  481. SaveWindowConfig(disp)
  482. Display *disp;
  483. {
  484.     Config *conf = ConfAry + disp->Id;
  485.     Window *win = disp->Win;
  486.  
  487.     conf->TopEdge   = win->TopEdge;
  488.     conf->LeftEdge  = win->LeftEdge;
  489.     conf->Width     = win->Width;
  490.     conf->Height    = win->Height;
  491. }
  492.  
  493. /*
  494.  *  Count lines backwards
  495.  */
  496.  
  497. static long
  498. BackupFile(disp, pos, rlines)
  499. Display *disp;
  500. long pos;
  501. long rlines;
  502. {
  503.     long n;
  504.     long i;
  505.  
  506.     if (disp->Fi == NULL) {
  507.     disp->Fi = fopen(disp->Name, "r");
  508.     if (disp->Fi == NULL)
  509.         return(0);
  510.     }
  511.     ++rlines;    /*  think of the case where rlines is 1 in the below code   */
  512.  
  513.     while (rlines && pos) {
  514.     n = sizeof(TmpBuf);
  515.     if (pos < n)
  516.         n = pos;
  517.     fseek(disp->Fi, pos - n, 0);
  518.     fread(TmpBuf, 1, n, disp->Fi);
  519.     for (i = n - 1; i >= 0; --i) {
  520.         if (TmpBuf[i] == '\n') {
  521.         if (--rlines == 0)
  522.             break;
  523.         }
  524.     }
  525.     ++i;
  526.     pos = pos - n + i;
  527.     }
  528.     return(pos);
  529. }
  530.  
  531. /*
  532.  *  Flag that the display should be refreshed without doing so immediately.
  533.  *  This allows the user to skip around articles without having to wait
  534.  *  for the display to catch up.
  535.  */
  536.  
  537. static void
  538. SetRefresh(disp, lrc)
  539. Display *disp;
  540. int lrc;
  541. {
  542.     FlagRefresh = 1;
  543.  
  544.     if (lrc < 0)
  545.     lrc = 0;
  546.  
  547.     if (lrc > TMPBSIZE - 1)
  548.     lrc = TMPBSIZE - 1;
  549.  
  550.     disp->FlagRefresh = 1;
  551.     disp->ColStart = lrc;
  552. }
  553.  
  554.  
  555. /*
  556.  *                YES OR NO
  557.  */
  558.  
  559. typedef struct IntuiText    ITEXT;
  560. typedef unsigned char    ubyte;
  561.  
  562. int
  563. getyn(text)
  564. char *text;
  565. {
  566.     int result;
  567.     ITEXT *body, *pos, *neg;
  568.  
  569.     if (DispBase == NULL)
  570.     return(0);
  571.  
  572.     body = (ITEXT *)AllocMem(sizeof(ITEXT), 0);
  573.     pos  = (ITEXT *)AllocMem(sizeof(ITEXT), 0);
  574.     neg  = (ITEXT *)AllocMem(sizeof(ITEXT), 0);
  575.     setmem(body, sizeof(ITEXT), 0);
  576.     setmem(pos , sizeof(ITEXT), 0);
  577.     setmem(neg , sizeof(ITEXT), 0);
  578.     body->BackPen = pos->BackPen = neg->BackPen = 1;
  579.     body->DrawMode= pos->DrawMode= neg->DrawMode= AUTODRAWMODE;
  580.     body->LeftEdge = 10;
  581.     body->TopEdge  = 12;
  582.     body->IText    = (ubyte *)text;
  583.     pos->LeftEdge = AUTOLEFTEDGE;
  584.     pos->TopEdge = AUTOTOPEDGE;
  585.     pos->IText = (ubyte *)"OK";
  586.     neg->LeftEdge = AUTOLEFTEDGE;
  587.     neg->TopEdge = AUTOTOPEDGE;
  588.     neg->IText = (ubyte *)"CANCEL";
  589.     result = AutoRequest(DispBase->Win, body, pos, neg, 0, 0, 320, 58);
  590.     FreeMem(body, sizeof(ITEXT));
  591.     FreeMem(pos , sizeof(ITEXT));
  592.     FreeMem(neg , sizeof(ITEXT));
  593.     return(result);
  594. }
  595.  
  596. void
  597. TabExpand(buf, max)
  598. char *buf;
  599. short max;
  600. {
  601.     short i;
  602.     short len = strlen(buf);
  603.     char *ptr;
  604.  
  605.     max -= 9;
  606.     for (i = 0, ptr = buf; *ptr; ++ptr, ++i) {
  607.     if (*ptr == '\n') {
  608.         *ptr = 0;
  609.         break;
  610.     }
  611.     if (*ptr == 9 && len < max) {
  612.         int n = ~i & 7;
  613.         movmem(ptr, ptr + n, len - i + 1);
  614.         setmem(ptr, n + 1, ' ');
  615.         len += n;
  616.     }
  617.     }
  618. }
  619.  
  620.