home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / comm / term33so.lha / termBuffer.c < prev    next >
C/C++ Source or Header  |  1993-04-30  |  11KB  |  636 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(Kick30)
  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.         /* Free the contents of the display buffer. */
  439.  
  440.     if(BufferLines)
  441.     {
  442.         APTR NewPoolHeader;
  443.  
  444.             /* Simple, create another pool header if possible. */
  445.  
  446.         if(BufferPoolHeader)
  447.             NewPoolHeader = CreatePool(MEMF_ANY | MEMF_PUBLIC,STRING_SIZE * STRING_COUNT,STRING_SIZE * STRING_COUNT);
  448.         else
  449.             NewPoolHeader = NULL;
  450.  
  451.             /* If a new pool header is available, free the old
  452.              * pool and replace it with the new pool, else
  453.              * do it again by hand.
  454.              */
  455.  
  456.         if(NewPoolHeader)
  457.         {
  458.             DeletePool(BufferPoolHeader);
  459.  
  460.             BufferPoolHeader = NewPoolHeader;
  461.         }
  462.         else
  463.         {
  464.             LONG i;
  465.  
  466.             for(i = 0 ; i < Lines ; i++)
  467.             {
  468.                 if(BufferLines[i])
  469.                     (*FreeString)(BufferLines[i]);
  470.             }
  471.         }
  472.  
  473.         FreeVec(BufferLines);
  474.  
  475.         Lines = 0;
  476.  
  477.         MaxLines = BUFFER_GROW;
  478.  
  479.         BufferLines = (STRPTR *)AllocVec(MaxLines * sizeof(STRPTR),MEMF_ANY | MEMF_CLEAR);
  480.  
  481.         UpdateReview(TRUE);
  482.     }
  483.  
  484.     BufferSpace = 0;
  485.  
  486.     BufferChanged = FALSE;
  487. }
  488.  
  489.     /* CreateSearchInfo(STRPTR Pattern):
  490.      *
  491.      *    Create auxilary data required by SearchTextBuffer().
  492.      */
  493.  
  494. struct SearchInfo * __regargs
  495. CreateSearchInfo(STRPTR Pattern)
  496. {
  497.     struct SearchInfo *Info;
  498.  
  499.         /* Allocate the buffer. */
  500.  
  501.     if(Info = (struct SearchInfo *)AllocVec(sizeof(struct SearchInfo),MEMF_ANY | MEMF_PUBLIC))
  502.     {
  503.         WORD i;
  504.  
  505.             /* Determine pattern width. */
  506.  
  507.         Info -> PatternWidth = strlen(Pattern);
  508.  
  509.             /* Turn the pattern into upper case characters. */
  510.  
  511.         for(i = 0 ; i <= Info -> PatternWidth ; i++)
  512.             Info -> Pattern[i] = ToUpper(Pattern[i]);
  513.  
  514.             /* Fill the entire range with the maximum pattern width. */
  515.  
  516.         for(i = 0 ; i < 256 ; i++)
  517.             Info -> Distance[i] = Info -> PatternWidth;
  518.  
  519.             /* Fill in the matching distances. */
  520.  
  521.         for(i = 0 ; i < Info -> PatternWidth - 1 ; i++)
  522.             Info -> Distance[Info -> Pattern[i]] = Info -> PatternWidth - i - 1;
  523.  
  524.             /* Restart from scratch. */
  525.  
  526.         Info -> FoundY = -1;
  527.     }
  528.  
  529.     return(Info);
  530. }
  531.  
  532.     /* DeleteSearchInfo(struct SearchInfo *Info):
  533.      *
  534.      *    Free buffer allocated by CreateSearchInfo().
  535.      */
  536.  
  537. VOID __regargs
  538. DeleteSearchInfo(struct SearchInfo *Info)
  539. {
  540.     if(Info)
  541.         FreeVec(Info);
  542. }
  543.  
  544.     /* SearchTextBuffer():
  545.      *
  546.      *    String search function, based on the Boyer-Moore search
  547.      *    algorithm.
  548.      */
  549.  
  550. LONG __regargs
  551. SearchTextBuffer(struct SearchInfo *Info)
  552. {
  553.     if(BufferLines)
  554.     {
  555.         UBYTE    *Distance,
  556.             *Pattern;
  557.         WORD    LineWidth,
  558.             PatternWidth;
  559.         STRPTR    Line;
  560.  
  561.         LONG    i;
  562.         WORD    j,k,l,Index;
  563.  
  564.             /* Extract relevant data. */
  565.  
  566.         Distance    = Info -> Distance;
  567.         Pattern        = Info -> Pattern;
  568.         PatternWidth    = Info -> PatternWidth;
  569.  
  570.             /* Update the search positions. */
  571.  
  572.         if(Info -> FoundY == -1)
  573.         {
  574.             Info -> FoundX    = 0;
  575.             Info -> FoundY    = 0;
  576.             Index        = 0;
  577.         }
  578.         else
  579.         {
  580.             if(!(Index = Info -> Index))
  581.                 Info -> FoundY = (Info -> FoundY + 1) % Lines;
  582.         }
  583.  
  584.             /* Run down the buffer. */
  585.  
  586.         for(i = Info -> FoundY ; i < Lines ; i++)
  587.         {
  588.             Line = BufferLines[i];
  589.  
  590.                 /* Is there anything to search for? */
  591.  
  592.             if((LineWidth = Line[-1]) >= PatternWidth)
  593.             {
  594.                     /* Cast the magic spell of Boyer-Moore... */
  595.  
  596.                 if(Index)
  597.                     j = Index;
  598.                 else
  599.                     j = PatternWidth;
  600.  
  601.                 do
  602.                 {
  603.                     k = PatternWidth - 1;
  604.                     l = j - 1;
  605.  
  606.                     while(k >= 0 && Pattern[k] == ToUpper(Line[l]))
  607.                     {
  608.                         l--;
  609.                         k--;
  610.                     }
  611.  
  612.                     j += Distance[ToUpper(Line[j - 1])];
  613.  
  614.                     if(k < 0)
  615.                     {
  616.                         Info -> FoundX    = l + 1;
  617.                         Info -> FoundY    = i;
  618.  
  619.                         if(j <= LineWidth)
  620.                             Info -> Index = j;
  621.                         else
  622.                             Info -> Index = 0;
  623.  
  624.                         return(i);
  625.                     }
  626.                 }
  627.                 while(j <= LineWidth);
  628.  
  629.                 Index = 0;
  630.             }
  631.         }
  632.     }
  633.  
  634.     return(-1);
  635. }
  636.