home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / ECO30603.ZIP / ECO30603.LZH / ECOLIBBS / ECO_TEXT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-09-26  |  10.5 KB  |  388 lines

  1. (*
  2.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  3.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  4.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  5.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  6.     ▓▓▓▓▓▓▓▓·──                                              ──·▓▓▓▓▓▓▓▓▓▓▓
  7.     ▓▓▓▓▓▓▓▓│                                                  │░░▓▓▓▓▓▓▓▓▓
  8.     ▓▓▓▓▓▓▓▓   ECO_TEXT was Conceived, Designed and Written     ░░▓▓▓▓▓▓▓▓▓
  9.     ▓▓▓▓▓▓▓▓   by Floor A.C. Naaijkens for                      ░░▓▓▓▓▓▓▓▓▓
  10.     ▓▓▓▓▓▓▓▓   UltiHouse Software / The ECO Group.              ░░▓▓▓▓▓▓▓▓▓
  11.     ▓▓▓▓▓▓▓▓                                                    ░░▓▓▓▓▓▓▓▓▓
  12.     ▓▓▓▓▓▓▓▓   (C) MCMXCII by EUROCON PANATIONAL CORPORATION.   ░░▓▓▓▓▓▓▓▓▓
  13.     ▓▓▓▓▓▓▓▓   All Rights Reserved for The ECO Group.           ░░▓▓▓▓▓▓▓▓▓
  14.     ▓▓▓▓▓▓▓▓                                                    ░░▓▓▓▓▓▓▓▓▓
  15.     ▓▓▓▓▓▓▓▓   Textbuffer interface (QHUD RHUD)                 ░░▓▓▓▓▓▓▓▓▓
  16.     ▓▓▓▓▓▓▓▓│                                                  │░░▓▓▓▓▓▓▓▓▓
  17.     ▓▓▓▓▓▓▓▓·──                                              ──·░░▓▓▓▓▓▓▓▓▓
  18.     ▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓▓▓▓▓▓▓
  19.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  20.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  21.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  22. *)
  23. unit eco_text;
  24.  
  25.  
  26. {$A-,B-,D-,E-,F-,I-,L-,N-,O-,R-,S-,V-}
  27. {$M 65520, 0, 655360}
  28.  
  29.  
  30.  
  31. interface
  32.  
  33. type
  34.   strptr = ^string;
  35.   textnodeptr = ^textnode;
  36.   textnode = record
  37.     next,prev :textnodeptr; {line may not be made longer}
  38.     line :strptr;   {allocation is length+1}
  39.   end;
  40.   textbuffer = record
  41.     first,last :textnodeptr;
  42.   end;
  43.  
  44. {-
  45.   Note: Don't mess around inside the data structures defined above.
  46.   Use the procedures to access them instead.  This unit should be
  47.   written object orientated.  Some procedures don't use all their
  48.   parameters at the moment.  This is intentional and will be useful
  49.   if the structures are enhanced.
  50. -}
  51.  
  52. {- initialise an empty buffer -}
  53. procedure newbuffer(var t :textbuffer);
  54.  
  55. {- return true if the buffer is empty -}
  56. function emptybuffer(var t :textbuffer) :boolean;
  57.  
  58. {- return a pointer to the first line of a buffer -}
  59. function firstline(var t :textbuffer) :textnodeptr;
  60.  
  61. {- return a pointer to the last line of a buffer -}
  62. function lastline(var t :textbuffer) :textnodeptr;
  63.  
  64. {- return the next line in a buffer -}
  65. function nextline(var t :textbuffer;  pos :textnodeptr) :textnodeptr;
  66.  
  67. {- return the previous line in a buffer -}
  68. function prevline(var t :textbuffer;  pos :textnodeptr) :textnodeptr;
  69.  
  70. {- add a line to the end of a buffer -}
  71. procedure addtoend(var t :textbuffer;  line :string);
  72.  
  73. {- insert a line before another line -}
  74. procedure addinsert(var t :textbuffer;  pos :textnodeptr;  line :string);
  75.  
  76. {- delete a line and return the next line or nil if it was the last line -}
  77. function deleteline(var t :textbuffer;  var pos :textnodeptr) :textnodeptr;
  78.  
  79. {- delete a buffer -}
  80. procedure deletebuffer(var t :textbuffer);
  81.  
  82. {- retrieve the text value from a line -}
  83. function gettextline(var t: textbuffer;  pos :textnodeptr) :string;
  84.  
  85. {- assign a new string to a line of text -}
  86. procedure modifytextline(var t: textbuffer;  pos :textnodeptr;  line :string);
  87.  
  88. {- word wrap the buffer -}
  89. procedure wrapbuffer(var t :textbuffer;  margin :byte);
  90.  
  91. {- create a new buffer with maximum length (255) lines -}
  92. procedure unwrapbuffer(var t,w :textbuffer);
  93.  
  94. {- count the number of lines in a buffer -}
  95. function bufferlength(var t :textbuffer) :word;
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103. implementation
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.   procedure newbuffer(var t :textbuffer);
  113.   begin
  114.     t.first := nil;
  115.     t.last := nil;
  116.   end; {newbuffer}
  117.  
  118.  
  119.   procedure deletebuffer(var t :textbuffer);
  120.   var step,temp :textnodeptr;
  121.   begin
  122.     step := t.first;
  123.     while (step <> nil) do begin
  124.       freemem(step^.line,length(step^.line^)+1);
  125.       temp := step;
  126.       step := step^.next;
  127.       dispose(temp);
  128.     end; {while}
  129.     newbuffer(t);
  130.   end; {deletebuffer}
  131.  
  132.  
  133.   function emptybuffer(var t :textbuffer) :boolean;
  134.   begin
  135.     emptybuffer := (t.first = nil);
  136.   end; {emptybuffer}
  137.  
  138.  
  139.   function firstline(var t :textbuffer) :textnodeptr;
  140.   begin
  141.     firstline := t.first;
  142.   end; {firstline}
  143.  
  144.  
  145.   function lastline(var t :textbuffer) :textnodeptr;
  146.   begin
  147.     lastline := t.last;
  148.   end; {lastline}
  149.  
  150.  
  151.   function nextline(var t :textbuffer;  pos :textnodeptr) :textnodeptr;
  152.   begin
  153.     nextline := nil;
  154.     if (pos = nil) then exit;
  155.     nextline := pos^.next;
  156.   end; {nextline}
  157.  
  158.  
  159.   function prevline(var t :textbuffer;  pos :textnodeptr) :textnodeptr;
  160.   begin
  161.     prevline := nil;
  162.     if (pos = nil) then exit;
  163.     prevline := pos^.prev;
  164.   end; {prevline}
  165.  
  166.  
  167.   function deleteline(var t :textbuffer;  var pos :textnodeptr) :textnodeptr;
  168.   begin
  169.     deleteline := nextline(t,pos);
  170.     if (pos=nil) or emptybuffer(t) then exit;
  171.     if (pos^.prev <> nil) then pos^.prev^.next := pos^.next;
  172.     if (pos^.next <> nil) then pos^.next^.prev := pos^.prev;
  173.     if (pos = t.first) then t.first := pos^.next; {pos was first node}
  174.     if (pos = t.last) then t.last := pos^.prev;   {pos was last node}
  175.     if (pos^.line <> nil) then freemem(pos^.line,length(pos^.line^)+1);
  176.                                                     {free existing line}
  177.     dispose(pos); pos := nil;
  178.   end;
  179.  
  180.  
  181.   function newnode(line :string) :textnodeptr;
  182.   var temp :textnodeptr;
  183.   begin
  184.     newnode := nil;
  185.     new(temp);
  186.     if (temp=nil) then exit;
  187.     temp^.next := nil;
  188.     temp^.prev := nil;
  189.     getmem(temp^.line,length(line)+1);
  190.     if (temp^.line = nil) then exit;
  191.     temp^.line^ := line;
  192.     newnode := temp;
  193.   end; {newnode}
  194.  
  195.  
  196.   procedure modifytextline(var t: textbuffer;  pos :textnodeptr;  line :string);
  197.   begin
  198.     if pos=nil then exit;
  199.     if (pos^.line <> nil) then    {free existing line}
  200.       freemem(pos^.line,length(pos^.line^)+1);
  201.     getmem(pos^.line,length(line)+1); {space for new line}
  202.     if (pos^.line = nil) then exit;
  203.     pos^.line^ := line;
  204.   end; {modifytextline}
  205.  
  206.  
  207.   function gettextline(var t: textbuffer;  pos :textnodeptr) :string;
  208.   begin
  209.     gettextline := '';
  210.     if pos=nil then exit;
  211.     gettextline := pos^.line^;
  212.   end; {gettextline}
  213.  
  214.  
  215.   procedure addtoend(var t :textbuffer;  line :string);
  216.   var temp :textnodeptr;
  217.   begin
  218.     temp := newnode(line);
  219.     if (temp=nil) then exit;
  220.  
  221.     if (t.first = nil) then begin
  222.       t.first := temp;
  223.       t.last := t.first;
  224.     end else begin
  225.       t.last^.next := temp;
  226.       temp^.prev := t.last;
  227.       t.last := temp;
  228.     end; {else}
  229.   end; {addtoend}
  230.  
  231.  
  232.   procedure addinsert(var t :textbuffer;  pos :textnodeptr;  line :string);
  233.   var temp :textnodeptr;
  234.   begin
  235.     if (emptybuffer(t) or (pos = nil)) then begin
  236.       addtoend(t,line);
  237.     end else begin
  238.       temp := newnode(line);
  239.       if (temp=nil) then exit;
  240.  
  241.       if (pos^.prev <> nil) then
  242.         pos^.prev^.next := temp;
  243.       temp^.next := pos;
  244.       temp^.prev := pos^.prev;
  245.       pos^.prev := temp;
  246.  
  247.       if (pos = t.first) then   {new front}
  248.         t.first := temp;
  249.     end; {else}
  250.   end; {addinsert}
  251.  
  252.  
  253.   function bufferlength(var t :textbuffer) :word;
  254.   var
  255.     count :word;
  256.     step :textnodeptr;
  257.   begin
  258.     count := 0;
  259.     step := t.first;
  260.     while (step <> nil) do begin
  261.       step := step^.next;
  262.       inc(count);
  263.     end; {while}
  264.  
  265.     bufferlength := count;
  266.   end; {bufferlength}
  267.  
  268.   {- Create a new, wrapped, buffer.  Margin must be reasonable, i.e. not too
  269.    close to 0 or 255 -}
  270.  
  271.  
  272.   procedure wrapbuffer(var t :textbuffer;  margin :byte);
  273.   const seperators = [#32..#47,#58..#64,#91..#96,#123..#126];
  274.   var
  275.     w :textbuffer;
  276.     line :string;
  277.     source :word; {can't be Byte, Length may be 255}
  278.     step :textnodeptr;
  279.     ch :char;
  280.  
  281.     procedure finishline;
  282.     begin
  283.       addtoend(w,line);
  284.       line := '';
  285.     end; {finishline}
  286.  
  287.   
  288.     procedure addchar(ch :char);
  289.     var
  290.       overflow :string;
  291.       p :byte;
  292.     begin
  293.       if (length(line) >= margin) then begin  {break the line}
  294.         overflow := '';
  295.           {first remove excess spaces}
  296.         if (line[length(line)]=' ') then
  297.           while (length(line) > 1) and (line[length(line)-1]=' ') do
  298.             dec(line[0]);     {drop last space}
  299.  
  300.         if (length(line) >= margin) then begin
  301.           p := length(line);
  302.           while (p > 0) and not (line[p] in seperators) do
  303.             dec(p);       {look backwards for seperator}
  304.  
  305.           if (p=0) then p := margin;    {no seperator, one huge word}
  306.  
  307.           overflow := copy(line,p+1,length(line)-p);
  308.           line[0] := char(p);
  309.         end; {if}
  310.  
  311.         finishline;
  312.         line := overflow+ch;
  313.       end else begin
  314.         line := line+ch;
  315.       end; {else}
  316.     end; {addchar}
  317.  
  318.   
  319.     procedure tab;
  320.     var count :byte;
  321.     begin
  322.       for count := 1 to 8-((length(line)-1) mod 8) do addchar(' ');
  323.     end; {tab}
  324.  
  325.   begin
  326.     newbuffer(w);
  327.     step := t.first; line := '';
  328.     while (step <> nil) do begin
  329.       source := 1;
  330.       while (source <= length(step^.line^)) do begin
  331.         ch := step^.line^[source];
  332.         case ch of
  333.           ^m : begin
  334.             line := line+^m^j;
  335.             finishline;
  336.           end;
  337.           ^i : tab;
  338.           ^j,#141 : {ignore lf and soft-cr};
  339.           else addchar(ch);
  340.         end; {case}
  341.         inc(source);
  342.       end; {while}
  343.       step := step^.next;
  344.     end; {while}
  345.     if (line <> '') then finishline;
  346.     deletebuffer(t);
  347.     t := w;
  348.   end; {wrapbuffer}
  349.  
  350.  
  351.   {- Create a new, unwrapped, buffer.  All the lines except the last one
  352.    in the new buffer will be of length 255 -}
  353.  
  354.  
  355.   procedure unwrapbuffer(var t,w :textbuffer);
  356.   var
  357.     line :string;
  358.     source :word; {can't be Byte, Length may be 255}
  359.     step :textnodeptr;
  360.  
  361.  
  362.     procedure finishline;
  363.     begin
  364.       addtoend(w,line);
  365.       line := '';
  366.     end; {finishline}
  367.  
  368.  
  369.     procedure addchar(ch :char);
  370.     begin
  371.       if (length(line) = 255) then finishline;
  372.       line := line+ch;
  373.     end; {addchar}
  374.  
  375.  
  376.   begin
  377.     newbuffer(w); step := t.first; line := '';
  378.     while (step <> nil) do begin
  379.       for source := 1 to length(step^.line^) do addchar(step^.line^[source]);
  380.       step := step^.next;
  381.     end; {while}
  382.     if (line <> '') then finishline;
  383.   end; {unwrapbuffer}
  384.  
  385.  
  386.  
  387. end. quickbbs message text, credits to p.j. muller
  388.