home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d8xx / d832 / term.lha / Term / term-3.1-Source.lha / termBuffer.c < prev    next >
C/C++ Source or Header  |  1993-02-18  |  11KB  |  638 lines

  1. /*
  2. **    termBuffer.c
  3. **
  4. **    Auxilary routines for text buffer/capture management.
  5. **
  6. **    Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* Maximum size of an allocated line string. */
  13.  
  14. #define STRING_SIZE    (1 + 255 + 1)
  15.  
  16.     /* How many strings to include in a single puddle. */
  17.  
  18. #define STRING_COUNT    10
  19.  
  20.     /* The number of lines the buffer will grow. */
  21.  
  22. #define BUFFER_GROW    100
  23.  
  24.     /* Memory allocation routines. */
  25.  
  26. STATIC STRPTR        (* __regargs AllocString)(STRPTR,LONG);
  27. STATIC VOID        (* __regargs FreeString)(STRPTR);
  28.  
  29.     /* Memory pool header (Kickstart 3.0 required). */
  30.  
  31. STATIC APTR        BufferPoolHeader;
  32.  
  33.     /* OldAllocString(STRPTR String,WORD Len):
  34.      *
  35.      +    Allocate space for a string, old flavour.
  36.      */
  37.  
  38. STATIC STRPTR __regargs
  39. OldAllocString(STRPTR String,LONG Len)
  40. {
  41.     STRPTR Mem;
  42.  
  43.     if(Len > 255)
  44.         Len = 255;
  45.  
  46.     if(Mem = (STRPTR)AllocMem(1 + Len + 1,MEMF_ANY | MEMF_PUBLIC))
  47.     {
  48.         *Mem++ = Len;
  49.  
  50.         memcpy(Mem,String,Len);
  51.  
  52.         Mem[Len] = 0;
  53.  
  54.         return((STRPTR)Mem);
  55.     }
  56.     else
  57.         return(NULL);
  58. }
  59.  
  60.     /* OldFreeString(STRPTR String):
  61.      *
  62.      *    Free the space occupied by a string, old flavour.
  63.      */
  64.  
  65. STATIC VOID __regargs
  66. OldFreeString(STRPTR String)
  67. {
  68.     FreeMem(&String[-1],1 + String[-1] + 1);
  69. }
  70.  
  71.     /* NewAllocString(STRPTR String,WORD Len):
  72.      *
  73.      +    Allocate space for a string, new pooled version.
  74.      */
  75.  
  76. STATIC STRPTR __regargs
  77. NewAllocString(STRPTR String,LONG Len)
  78. {
  79.     STRPTR Mem;
  80.  
  81.     if(Len > 255)
  82.         Len = 255;
  83.  
  84.     if(Mem = (STRPTR)AllocPooled(BufferPoolHeader,1 + Len + 1))
  85.     {
  86.         *Mem++ = Len;
  87.  
  88.         memcpy(Mem,String,Len);
  89.  
  90.         Mem[Len] = 0;
  91.  
  92.         return((STRPTR)Mem);
  93.     }
  94.     else
  95.         return(NULL);
  96. }
  97.  
  98.     /* NewFreeString(STRPTR String):
  99.      *
  100.      *    Free the space occupied by a string, new pooled version.
  101.      */
  102.  
  103. STATIC VOID __regargs
  104. NewFreeString(STRPTR String)
  105. {
  106.     FreePooled(BufferPoolHeader,&String[-1],1 + String[-1] + 1);
  107. }
  108.  
  109.     /* AddLine(STRPTR Line,LONG Size):
  110.      *
  111.      *    Add a line to the display buffer.
  112.      */
  113.  
  114. STATIC VOID __regargs
  115. AddLine(register STRPTR Line,register LONG Size)
  116. {
  117.         /* Are we still to update the buffer contents? */
  118.  
  119.     if(!BufferClosed)
  120.     {
  121.             /* Remove trailing spaces. */
  122.  
  123.         while(Size > 0 && Line[Size - 1] == ' ')
  124.             Size--;
  125.  
  126.             /* Is the buffer array initialized? */
  127.  
  128.         if(BufferLines)
  129.         {
  130.             ULONG Signals = 0;
  131.  
  132.                 /* Pick up the global access semaphore
  133.                  * (two tasks are sharing the data).
  134.                  */
  135.  
  136.             ObtainSemaphore(BufferSemaphore);
  137.  
  138.                 /* Check for limit. */
  139.  
  140.             if(Config -> CaptureConfig -> MaxBufferSize && BufferSpace >= Config -> CaptureConfig -> MaxBufferSize)
  141.             {
  142.                 register LONG i;
  143.  
  144.                 BufferSpace -= BufferLines[0][-1];
  145.  
  146.                 (*FreeString)(BufferLines[0]);
  147.  
  148.                 for(i = 1 ; i < MaxLines ; i++)
  149.                     BufferLines[i - 1] = BufferLines[i];
  150.  
  151.                 Lines--;
  152.  
  153.                     /* Tell the buffer task to
  154.                      * refresh the display.
  155.                      */
  156.  
  157.                 Signals = SIG_MOVEUP;
  158.             }
  159.             else
  160.             {
  161.                     /* We've reached the last line in the buffer. */
  162.  
  163.                 if(Lines == MaxLines)
  164.                 {
  165.                     STRPTR *MoreBuffer;
  166.  
  167.                         /* Allocate space for some more lines. */
  168.  
  169.                     if(MoreBuffer = (STRPTR *)AllocVec((MaxLines + BUFFER_GROW) * sizeof(STRPTR),MEMF_ANY | MEMF_CLEAR))
  170.                     {
  171.                         register LONG i;
  172.  
  173.                         BufferChanged = TRUE;
  174.  
  175.                             /* Copy the old lines to the new
  176.                              * buffer.
  177.                              */
  178.  
  179.                         for(i = 0 ; i < Lines ; i++)
  180.                             MoreBuffer[i] = BufferLines[i];
  181.  
  182.                             /* Free the old lines. */
  183.  
  184.                         FreeVec(BufferLines);
  185.  
  186.                             /* Set the new buffer. */
  187.  
  188.                         MaxLines += BUFFER_GROW;
  189.  
  190.                         BufferLines = MoreBuffer;
  191.                     }
  192.                     else
  193.                     {
  194.                         BufferChanged = TRUE;
  195.  
  196.                             /* We couldn't get enough memory
  197.                              * to extend the number of lines
  198.                              * in the buffer, so we'll have
  199.                              * to wrap the contents of the
  200.                              * buffer around.
  201.                              */
  202.  
  203.                         if(Lines)
  204.                         {
  205.                             register LONG i;
  206.  
  207.                             BufferSpace -= BufferLines[0][-1];
  208.  
  209.                             (*FreeString)(BufferLines[0]);
  210.  
  211.                             for(i = 1 ; i < MaxLines ; i++)
  212.                                 BufferLines[i - 1] = BufferLines[i];
  213.  
  214.                             Lines--;
  215.  
  216.                                 /* Tell the buffer task to
  217.                                  * refresh the display.
  218.                                  */
  219.  
  220.                             Signals = SIG_MOVEUP;
  221.                         }
  222.                     }
  223.                 }
  224.             }
  225.  
  226.                 /* Allocate a new line and copy the buffer contents
  227.                  * into it.
  228.                  */
  229.  
  230.             if(BufferLines[Lines] = (*AllocString)(Line,Size))
  231.             {
  232.                 BufferChanged = TRUE;
  233.  
  234.                 Lines++;
  235.  
  236.                 BufferSpace += Size;
  237.             }
  238.  
  239.             ReleaseSemaphore(BufferSemaphore);
  240.  
  241.                 /* Tell the buffer task to update the display. */
  242.  
  243.             if(!Signals)
  244.             {
  245.                 Signals = SIG_UPDATE;
  246.  
  247.                 UpdateReview(FALSE);
  248.             }
  249.             else
  250.                 UpdateReview(TRUE);
  251.  
  252.             if(BufferProcess)
  253.                 Signal(BufferProcess,Signals);
  254.         }
  255.     }
  256. }
  257.  
  258.     /* StoreBuffer(APTR Buffer,LONG Size):
  259.      *
  260.      *    Store data in the display buffer.
  261.      */
  262.  
  263. VOID __regargs
  264. StoreBuffer(register STRPTR Buffer,register LONG Size)
  265. {
  266.     STATIC UBYTE     LineBuffer[BUFFER_LINE_WIDTH];
  267.     STATIC LONG      BufferCount = 0;
  268.  
  269.     register UBYTE c;
  270.  
  271.     while(Size--)
  272.     {
  273.             /* Look which char we are to handle. */
  274.  
  275.         switch(c = *Buffer++)
  276.         {
  277.                 /* Move the cursor one step back. */
  278.  
  279.             case BKS:
  280.  
  281.                 if(BufferCount)
  282.                     BufferCount--;
  283.  
  284.                 break;
  285.  
  286.                 /* Move the cursor to the next tab
  287.                  * stop.
  288.                  */
  289.  
  290.             case TAB:
  291.  
  292.                 if(((BufferCount + 8) & ~7) < LastColumn)
  293.                 {
  294.                     register LONG Delta = ((BufferCount + 8) & ~7) - BufferCount;
  295.  
  296.                     memset(&LineBuffer[BufferCount],' ',Delta);
  297.  
  298.                     BufferCount += Delta;
  299.                 }
  300.                 else
  301.                 {
  302.                     AddLine(LineBuffer,BufferCount);
  303.  
  304.                     BufferCount = 0;
  305.                 }
  306.  
  307.                 break;
  308.  
  309.                 /* Terminate the current line. */
  310.  
  311.             case ENT:
  312.  
  313.                 AddLine(LineBuffer,BufferCount);
  314.  
  315.                 BufferCount = 0;
  316.  
  317.                 break;
  318.  
  319.                 /* Stuff the character into the buffer. */
  320.  
  321.             default:
  322.  
  323.                 if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  324.                 {
  325.                     if(IsPrintable[c])
  326.                         LineBuffer[BufferCount++] = c;
  327.                 }
  328.                 else
  329.                 {
  330.                     if(c)
  331.                         LineBuffer[BufferCount++] = c;
  332.                 }
  333.  
  334.                 break;
  335.         }
  336.  
  337.             /* The line is full, add it to the display buffer. */
  338.  
  339.         if(BufferCount >= LastColumn || BufferCount == BUFFER_LINE_WIDTH)
  340.         {
  341.             AddLine(LineBuffer,BufferCount);
  342.  
  343.             BufferCount = 0;
  344.         }
  345.     }
  346. }
  347.  
  348.     /* DeleteBuffer():
  349.      *
  350.      *    Delete buffer resources.
  351.      */
  352.  
  353. VOID
  354. DeleteBuffer()
  355. {
  356.     if(BufferLines)
  357.     {
  358.         if(!BufferPoolHeader)
  359.         {
  360.             LONG i;
  361.  
  362.             for(i = 0 ; i < Lines ; i++)
  363.             {
  364.                 if(BufferLines[i])
  365.                     (*FreeString)(BufferLines[i]);
  366.             }
  367.         }
  368.  
  369.         FreeVec(BufferLines);
  370.  
  371.         BufferLines = NULL;
  372.     }
  373.  
  374.     if(BufferPoolHeader)
  375.     {
  376.         DeletePool(BufferPoolHeader);
  377.  
  378.         BufferPoolHeader = NULL;
  379.     }
  380.  
  381.     if(BufferSemaphore)
  382.     {
  383.         FreeVec(BufferSemaphore);
  384.  
  385.         BufferSemaphore = NULL;
  386.     }
  387. }
  388.  
  389.     /* CreateBuffer():
  390.      *
  391.      *    Allocate buffer resources.
  392.      */
  393.  
  394. BYTE
  395. CreateBuffer()
  396. {
  397.     if(BufferLines = (STRPTR *)AllocVec(MaxLines * sizeof(STRPTR),MEMF_ANY | MEMF_CLEAR | MEMF_PUBLIC))
  398.     {
  399.         if(BufferSemaphore = (struct SignalSemaphore *)AllocVec(sizeof(struct SignalSemaphore),MEMF_ANY | MEMF_PUBLIC))
  400.         {
  401.             InitSemaphore(BufferSemaphore);
  402.  
  403.                 /* Create a memory pool header if possible. */
  404.  
  405.             if(SysBase -> LibNode . lib_Version >= 39)
  406.             {
  407.                 if(BufferPoolHeader = CreatePool(MEMF_ANY | MEMF_PUBLIC,STRING_SIZE * STRING_COUNT,STRING_SIZE * STRING_COUNT))
  408.                 {
  409.                     AllocString    = NewAllocString;
  410.                     FreeString    = NewFreeString;
  411.  
  412.                     return(TRUE);
  413.                 }
  414.             }
  415.  
  416.             AllocString    = OldAllocString;
  417.             FreeString    = OldFreeString;
  418.  
  419.             return(TRUE);
  420.         }
  421.  
  422.         FreeVec(BufferLines);
  423.  
  424.         BufferLines = NULL;
  425.     }
  426.  
  427.     return(FALSE);
  428. }
  429.  
  430.     /* FreeBuffer():
  431.      *
  432.      *    Release the contents of the text buffer.
  433.      */
  434.  
  435. VOID
  436. FreeBuffer()
  437. {
  438.     BufferChanged = FALSE;
  439.  
  440.         /* Free the contents of the display buffer. */
  441.  
  442.     if(BufferLines)
  443.     {
  444.         APTR NewPoolHeader;
  445.  
  446.             /* Simple, create another pool header if possible. */
  447.  
  448.         if(BufferPoolHeader)
  449.             NewPoolHeader = CreatePool(MEMF_ANY | MEMF_PUBLIC,STRING_SIZE * STRING_COUNT,STRING_SIZE * STRING_COUNT);
  450.         else
  451.             NewPoolHeader = NULL;
  452.  
  453.             /* If a new pool header is available, free the old
  454.              * pool and replace it with the new pool, else
  455.              * do it again by hand.
  456.              */
  457.  
  458.         if(NewPoolHeader)
  459.         {
  460.             DeletePool(BufferPoolHeader);
  461.  
  462.             BufferPoolHeader = NewPoolHeader;
  463.         }
  464.         else
  465.         {
  466.             LONG i;
  467.  
  468.             for(i = 0 ; i < Lines ; i++)
  469.             {
  470.                 if(BufferLines[i])
  471.                     (*FreeString)(BufferLines[i]);
  472.             }
  473.         }
  474.  
  475.         FreeVec(BufferLines);
  476.  
  477.         Lines = 0;
  478.  
  479.         MaxLines = BUFFER_GROW;
  480.  
  481.         BufferLines = (STRPTR *)AllocVec(MaxLines * sizeof(STRPTR),MEMF_ANY|MEMF_CLEAR);
  482.  
  483.         UpdateReview(TRUE);
  484.     }
  485.  
  486.     BufferSpace = 0;
  487.  
  488.     BufferChanged = FALSE;
  489. }
  490.  
  491.     /* CreateSearchInfo(STRPTR Pattern):
  492.      *
  493.      *    Create auxilary data required by SearchTextBuffer().
  494.      */
  495.  
  496. struct SearchInfo * __regargs
  497. CreateSearchInfo(STRPTR Pattern)
  498. {
  499.     struct SearchInfo *Info;
  500.  
  501.         /* Allocate the buffer. */
  502.  
  503.     if(Info = (struct SearchInfo *)AllocVec(sizeof(struct SearchInfo),MEMF_ANY | MEMF_PUBLIC))
  504.     {
  505.         WORD i;
  506.  
  507.             /* Determine pattern width. */
  508.  
  509.         Info -> PatternWidth = strlen(Pattern);
  510.  
  511.             /* Turn the pattern into upper case characters. */
  512.  
  513.         for(i = 0 ; i <= Info -> PatternWidth ; i++)
  514.             Info -> Pattern[i] = ToUpper(Pattern[i]);
  515.  
  516.             /* Fill the entire range with the maximum pattern width. */
  517.  
  518.         for(i = 0 ; i < 256 ; i++)
  519.             Info -> Distance[i] = Info -> PatternWidth;
  520.  
  521.             /* Fill in the matching distances. */
  522.  
  523.         for(i = 0 ; i < Info -> PatternWidth - 1 ; i++)
  524.             Info -> Distance[Info -> Pattern[i]] = Info -> PatternWidth - i - 1;
  525.  
  526.             /* Restart from scratch. */
  527.  
  528.         Info -> FoundY = -1;
  529.     }
  530.  
  531.     return(Info);
  532. }
  533.  
  534.     /* DeleteSearchInfo(struct SearchInfo *Info):
  535.      *
  536.      *    Free buffer allocated by CreateSearchInfo().
  537.      */
  538.  
  539. VOID __regargs
  540. DeleteSearchInfo(struct SearchInfo *Info)
  541. {
  542.     if(Info)
  543.         FreeVec(Info);
  544. }
  545.  
  546.     /* SearchTextBuffer():
  547.      *
  548.      *    String search function, based on the Boyer-Moore search
  549.      *    algorithm.
  550.      */
  551.  
  552. LONG __regargs
  553. SearchTextBuffer(struct SearchInfo *Info)
  554. {
  555.     if(BufferLines)
  556.     {
  557.         UBYTE    *Distance,
  558.             *Pattern;
  559.         WORD    LineWidth,
  560.             PatternWidth;
  561.         STRPTR    Line;
  562.  
  563.         LONG    i;
  564.         WORD    j,k,l,Index;
  565.  
  566.             /* Extract relevant data. */
  567.  
  568.         Distance    = Info -> Distance;
  569.         Pattern        = Info -> Pattern;
  570.         PatternWidth    = Info -> PatternWidth;
  571.  
  572.             /* Update the search positions. */
  573.  
  574.         if(Info -> FoundY == -1)
  575.         {
  576.             Info -> FoundX    = 0;
  577.             Info -> FoundY    = 0;
  578.             Index        = 0;
  579.         }
  580.         else
  581.         {
  582.             if(!(Index = Info -> Index))
  583.                 Info -> FoundY = (Info -> FoundY + 1) % Lines;
  584.         }
  585.  
  586.             /* Run down the buffer. */
  587.  
  588.         for(i = Info -> FoundY ; i < Lines ; i++)
  589.         {
  590.             Line = BufferLines[i];
  591.  
  592.                 /* Is there anything to search for? */
  593.  
  594.             if((LineWidth = Line[-1]) >= PatternWidth)
  595.             {
  596.                     /* Cast the magic spell of Boyer-Moore... */
  597.  
  598.                 if(Index)
  599.                     j = Index;
  600.                 else
  601.                     j = PatternWidth;
  602.  
  603.                 do
  604.                 {
  605.                     k = PatternWidth - 1;
  606.                     l = j - 1;
  607.  
  608.                     while(k >= 0 && Pattern[k] == ToUpper(Line[l]))
  609.                     {
  610.                         l--;
  611.                         k--;
  612.                     }
  613.  
  614.                     j += Distance[ToUpper(Line[j - 1])];
  615.  
  616.                     if(k < 0)
  617.                     {
  618.                         Info -> FoundX    = l + 1;
  619.                         Info -> FoundY    = i;
  620.  
  621.                         if(j <= LineWidth)
  622.                             Info -> Index = j;
  623.                         else
  624.                             Info -> Index = 0;
  625.  
  626.                         return(i);
  627.                     }
  628.                 }
  629.                 while(j <= LineWidth);
  630.  
  631.                 Index = 0;
  632.             }
  633.         }
  634.     }
  635.  
  636.     return(-1);
  637. }
  638.