home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d8xx / d828 / disktest.lha / DiskTest / Source / ts.c < prev    next >
C/C++ Source or Header  |  2001-02-25  |  10KB  |  399 lines

  1. /*-------------------------------------*
  2.  | File: TS.c - Text scroller routines |
  3.  +------------------------------------------------------------*
  4.  | These routines were inspired from an example due to Martin |
  5.  | Taillefer and published on AmigaMail; altough the original |
  6.  | routines have been heavily modified, I am in debt to M.T.  |
  7.  +---------------------------------------------------------+--*
  8.  | Author:  Maurizio Loreti, aka MLO or I3NOO.             |
  9.  | Address: University of Padova - Department of Physics   |
  10.  |          Via F. Marzolo, 8 - 35131 PADOVA - Italy       |
  11.  | Phone:   (39)(49) 844-313         FAX: (39)(49) 844-245 |
  12.  | E-Mail:  loreti@padova.infn.it (TCP/IP)                 |
  13.  | Home: Via G. Donizetti 6 - 35010 CADONEGHE (PD) - Italy |
  14.  *---------------------------------------------------------*/
  15.  
  16. /**
  17.  | #includes
  18. **/
  19.  
  20. #include <stddef.h>                       /* Standard library */
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <exec/types.h>                   /* AmigaDOS specific */
  25. #include <clib/graphics_protos.h>
  26. #include <clib/layers_protos.h>
  27. #include <clib/gadtools_protos.h>
  28. #include <clib/intuition_protos.h>
  29. #include "main.h"                         /* Local stuff */
  30. #include "ts.h"
  31. #include "ext.h"
  32.  
  33. void AddLine(
  34.   char *s,
  35.   size_t n,
  36.   BOOL update
  37. ){
  38. /**
  39.  | Adds the string "s" ("n" bytes long) to our document:
  40.  | a new "Line" structure is added to the linked list, and
  41.  | filled; if "update" is TRUE, the text is scrolled to
  42.  | display the last line and updated.
  43. **/
  44.  
  45.   Line *pL;
  46.  
  47.   if ((pL = malloc(sizeof(Line) + n)) == NULL) {
  48.     Error("No memory for Line");
  49.   }
  50.  
  51.   pL->sl_Length = n;
  52.   strcpy(pL->sl_Text, s);
  53.   pL->sl_Forw = NULL;
  54.   if ((pL->sl_Back = lastLine) == NULL) {
  55.     firstLine = pL;
  56.   } else {
  57.     lastLine->sl_Forw = pL;
  58.   }
  59.   lastLine = pL;
  60.   numLines++;
  61.  
  62.   if (update) {
  63.     if (numLines > linesVisible) {
  64.       topLine = numLines - linesVisible;
  65.     } else {
  66.       topLine = 0;
  67.     }
  68.     UpdateScroller();
  69.   }
  70. }
  71.  
  72. void BusyState(
  73.   BOOL state
  74. ){
  75. /**
  76.  | Whenever the application is busy, this function should be called
  77.  | as BusyState(TRUE); this will change the pointer to a default
  78.  | OS 2.0 busy-pointer too, to tell the user that we are not
  79.  | listening to the IDCMP's for awhile. When finished, call
  80.  | BusyState(FALSE).
  81. **/
  82.  
  83.   static UWORD __chip waitPointer[] = {
  84.     0x0000, 0x0000, 0x0400, 0x07C0, 0x0000, 0x07C0, 0x0100, 0x0380,
  85.     0x0000, 0x07E0, 0x07C0, 0x1FF8, 0x1FF0, 0x3FEC, 0x3FF8, 0x7FDE,
  86.     0x3FF8, 0x7FBE, 0x7FFC, 0xFF7F, 0x7EFC, 0xFFFF, 0x7FFC, 0xFFFF,
  87.     0x3FF8, 0x7FFE, 0x3FF8, 0x7FFE, 0x1FF0, 0x3FFC, 0x07C0, 0x1FF8,
  88.     0x0000, 0x07E0, 0x0000, 0x0000
  89.   };
  90.  
  91.   if (state == TRUE) {
  92.     SetPointer(pWind, waitPointer, 16, 16, -6, 0);
  93.   } else {
  94.     ClearPointer(pWind);
  95.   }
  96.  
  97.   if (pWind->WLayer->Flags & LAYERREFRESH) {
  98.     RefreshView(TRUE);
  99.   }
  100. }
  101.  
  102. void ClearText(
  103.   BOOL update
  104. ){
  105. /**
  106.  | This procedure free()s all the linked list holding the
  107.  | scrolled text. If "update" is TRUE, the window scrolling
  108.  | region is really cleared.
  109. **/
  110.  
  111.   Line *pL;
  112.  
  113.   for (pL=firstLine; pL!=NULL; ) {
  114.     Line *next = pL->sl_Forw;
  115.  
  116.     free(pL);
  117.     pL = next;
  118.   }
  119.  
  120.   firstLine = lastLine = NULL;
  121.   numLines = topLine = 0;
  122.  
  123.   if (update) {
  124.     SetScroller(pWind, pScroller, linesVisible, numLines, topLine);
  125.     RefreshView(TRUE);
  126.   }
  127. }
  128.  
  129. void InitScroller(void)
  130. {
  131. /**
  132.  | Scroller initialisation.
  133.  | - memory is obtained to hold a copy of the window raster port to
  134.  |   be used for clearing (the originel raster port is used for
  135.  |   rendering); this speeds up these operations avoiding SetAPen() etc.
  136.  | - some local global variables are initialised;
  137.  | - the scrolling region is drawn (with the help text loaded in the
  138.  |   initialisation routines).
  139. **/
  140.  
  141.   memcpy(pClearRP, (pRP = pWind->RPort), sizeof(struct RastPort));
  142.   SetDrMd(pClearRP, JAM2);
  143.   SetAPen(pClearRP, 0);
  144.   SetAPen(pRP, 1);
  145.  
  146.   fontWidth  = pWind->RPort->Font->tf_XSize;
  147.   fontHeight = pWind->RPort->Font->tf_YSize;
  148.  
  149.   bevelLeft   = pWind->BorderLeft + BEVEL_LEFT;
  150.   bevelTop    = pWind->BorderTop  + BEVEL_TOP;
  151.   bevelWidth  = BEVEL_WIDTH;
  152.   bevelHeight = BEVEL_HEIGHT;
  153.   textLeft    = bevelLeft + TEXT_XOFFSET;
  154.   textTop     = bevelTop  + TEXT_YOFFSET;
  155.  
  156.   viewWidth      = bevelWidth - 2 * (TEXT_XOFFSET - 1);
  157.   viewHeight     = bevelHeight - 2 * (TEXT_YOFFSET - 1);
  158.   columnsVisible = viewWidth  / fontWidth;
  159.   linesVisible   = viewHeight / fontHeight;
  160.   usefulWidth    = (USHORT)(columnsVisible * fontWidth);
  161.  
  162.   RefreshView(TRUE);
  163.   SetScroller(pWind, pScroller, linesVisible, numLines, topLine);
  164. }
  165.  
  166. void LastLine(
  167.   char *s,
  168.   size_t n
  169. ){
  170. /**
  171.  | A line is drawn at the end of the text, but NOT inserted
  172.  | in the linked list; it will then be overdrawn from the next
  173.  | AddLine()d or LastLine()d text; the text is scrolled if needed,
  174.  | to display the bottom line.
  175.  | LastLine() here is only used to display the
  176.  | "reading track X head Y" text.
  177.  | "s" is the string to be displayed, "n" bytes long.
  178. **/
  179.  
  180.   USHORT y;
  181.  
  182.   if (numLines >= linesVisible) {
  183.     topLine = numLines - linesVisible + 1;
  184.     UpdateScroller();
  185.     y = linesVisible;
  186.   } else {
  187.     y = numLines - topLine + 1;
  188.   }
  189.   y = (USHORT)(textTop + fontHeight * y);
  190.   RenderLine(textLeft, y, usefulWidth, s, n);
  191. }
  192.  
  193. void RefreshView(
  194.   BOOL damage
  195. ){
  196. /**
  197.  | This function performs most of the rendering work needed.
  198.  | It looks at the current window size and adjusts its rendering
  199.  | variables in consequence; then, if the "damage" parameter is
  200.  | TRUE, this routine explicitly erases any area of the display
  201.  | in which we will not be rendering in the rendering loop: this
  202.  | erases any left over characters that could be there if the
  203.  | user sizes or rearrange the window. Finally, the routine
  204.  | determines which lines of the display need to be updated,
  205.  | and goes on to do it.
  206. **/
  207.  
  208.   USHORT i;
  209.   Line *pL;
  210.   USHORT y;
  211.  
  212. /**
  213.  | What is the top line to be rendered?
  214. **/
  215.  
  216.   if (linesVisible > numLines) {
  217.     usefulHeight = (USHORT)(numLines * fontHeight);
  218.     topLine = 0;
  219.   } else {
  220.     usefulHeight = (USHORT)(linesVisible * fontHeight);
  221.     if (topLine + linesVisible > numLines) {
  222.       topLine = numLines - linesVisible;
  223.     }
  224.   }
  225.  
  226. /**
  227.  | If the layer has been damaged (and the window is to be refreshed),
  228.  | this is handled now (the gadgetry is already OK at this moment).
  229. **/
  230.  
  231.   if (damage) {
  232.     RectFill(pClearRP,
  233.              bevelLeft - 1,
  234.              bevelTop - 1,
  235.              bevelLeft + bevelWidth,
  236.              bevelTop + bevelHeight);
  237.     DrawBevelBox(pRP,
  238.                  bevelLeft, bevelTop,
  239.                  bevelWidth, bevelHeight,
  240.                  GT_VisualInfo, pVI,
  241.                  TAG_END);
  242.   }
  243.  
  244. /**
  245.  | Do we have something to render? If yes, we find the pointer to the
  246.  | top line text, starting from the top or the bottom of the list.
  247. **/
  248.  
  249.   if (usefulHeight   &&   usefulWidth) {
  250.     int n;
  251.  
  252.     if ((n = numLines - (topLine + 1)) < topLine) {
  253.       pL = ScanList(firstLine, topLine);
  254.     } else {
  255.       pL = ScanList(lastLine, -n);
  256.     }
  257.  
  258.     if (damage   ||   (topLine >= oldTopLine + linesVisible - 1)   ||
  259.         ((oldTopLine > linesVisible) &&
  260.          (topLine <= oldTopLine - linesVisible + 1))) {
  261.       y = textTop;
  262.       i = linesVisible;
  263.     } else if (topLine < oldTopLine) {
  264.       ScrollRaster(pRP,
  265.                    0, -((long) (oldTopLine - topLine) * fontHeight),
  266.                    textLeft,
  267.                    textTop + 2,
  268.                    textLeft + usefulWidth,
  269.                    textTop + usefulHeight + 1);
  270.  
  271.       y = textTop;
  272.       i = oldTopLine - topLine;
  273.     } else if (topLine > oldTopLine) {
  274.       ScrollRaster(pRP,
  275.                    0, ((topLine - oldTopLine) * fontHeight),
  276.                    textLeft,
  277.                    textTop + 2,
  278.                    textLeft + usefulWidth,
  279.                    textTop + usefulHeight + 1);
  280.  
  281.       for (i = linesVisible - (topLine - oldTopLine);
  282.            pL->sl_Forw != NULL  &&  i;
  283.            i--) {
  284.         pL = pL->sl_Forw;
  285.       }
  286.  
  287.       y = (USHORT)(textTop +
  288.           (fontHeight * (linesVisible - (topLine - oldTopLine))));
  289.       i = topLine - oldTopLine;
  290.     } else if (oldNumLines < numLines  &&  numLines <= linesVisible) {
  291.       for (i = oldNumLines;   pL->sl_Forw != NULL  &&  i;   i--) {
  292.         pL = pL->sl_Forw;
  293.       }
  294.  
  295.       y = (USHORT)(textTop + fontHeight * oldNumLines);
  296.       i = numLines - oldNumLines;
  297.     } else {
  298.       i = 0;
  299.     }
  300.  
  301.     while (i--   &&   pL != NULL) {
  302.       y += fontHeight;
  303.       RenderLine(textLeft, y, usefulWidth, pL->sl_Text, pL->sl_Length);
  304.       pL = pL->sl_Forw;
  305.     }
  306.   }
  307.  
  308.   oldTopLine = topLine;
  309.   oldNumLines = numLines;
  310. }
  311.  
  312. void SetTopLine(
  313.   UWORD n
  314. ){
  315. /**
  316.  | Sets the top line of the scroller text to "n".
  317. **/
  318.  
  319.   if (topLine != n) {
  320.     topLine = n;
  321.     RefreshView(FALSE);
  322.   }
  323. }
  324.  
  325. /*-------------------------- Local Procedures --------------------------*/
  326.  
  327. static void RenderLine(
  328.   USHORT  x,
  329.   USHORT  y,
  330.   USHORT  w,
  331.   char   *text,
  332.   size_t  len
  333. ){
  334. /**
  335.  | Render a single line of text ("text", "len" characters
  336.  | long) at the given position "x","y" (pixels). "w" is the
  337.  | length (pixels) of the rendering region.
  338. **/
  339.  
  340.   Move(pRP, x, y);
  341.   if (len > columnsVisible) {
  342.     len = columnsVisible;
  343.   }
  344.  
  345.   (void) Text(pRP, text, len);
  346.   if (len < columnsVisible) {
  347.     RectFill(pClearRP,
  348.              pRP->cp_x,
  349.              y - pRP->TxBaseline,
  350.              x + w - 1,
  351.              y - pRP->TxBaseline + fontHeight - 1);
  352.   }
  353. }
  354.  
  355. static void SetScroller(
  356.   struct Window *pW,
  357.   struct Gadget *pG,
  358.   USHORT lV,
  359.   USHORT nL,
  360.   USHORT tL
  361. ){
  362. /**
  363.  | Adjust the scroller gadget to reflect the current setting:
  364.  | "lV" lines visible, "nL" total lines and "tL" number of the
  365.  | top line.
  366. **/
  367.  
  368.   GT_SetGadgetAttrs(pG, pW, NULL,
  369.       GTSC_Visible,   lV,
  370.       GTSC_Total,     nL,
  371.       GTSC_Top,       tL,
  372.       TAG_DONE);
  373. }
  374.  
  375. static Line *ScanList(
  376.   register Line *pL,
  377.   register int n
  378. ){
  379.   register Line *pNew;
  380.  
  381.   if (n > 0) {
  382.     while (n--   &&   (pNew = pL->sl_Forw) != NULL)   pL = pNew;
  383.   } else if (n < 0) {
  384.     while (n++   &&   (pNew = pL->sl_Back) != NULL)   pL = pNew;
  385.   }
  386.   return pL;
  387. }
  388.  
  389. static void UpdateScroller(void)
  390. {
  391. /**
  392.  | Updates the text scrolling region, reflecting
  393.  | the current settings.
  394. **/
  395.  
  396.   SetScroller(pWind, pScroller, linesVisible, numLines, topLine);
  397.   RefreshView(FALSE);
  398. }
  399.