DEADSOFTWARE

moved compiler options to shared/a_modes.inc; turned on advanced records
[d2df-sdl.git] / src / shared / conbuf.pas
1 (* Copyright (C) DooM 2D:Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *)
16 {$INCLUDE a_modes.inc}
17 {.$MODE OBJFPC}
18 unit conbuf;
20 interface
23 procedure cbufPut (const s: AnsiString);
24 procedure cbufPutChars (buf: PChar; count: Integer);
26 function cbufLastChange (): LongWord;
28 function cbufWalkStart (): LongWord;
29 function cbufWalkEnd (pos: LongWord): LongWord;
30 procedure cbufPrev (var pos: LongWord);
31 procedure cbufNext (var pos: LongWord);
33 function cbufAt (const pos: LongWord): Char;
35 // get last line
36 procedure cbufLastLine (var sp: LongWord; var ep: LongWord);
37 // move one line up; `sp` and `ep` MUST be valid values from previous call to `cbufLastLine()`
38 function cbufLineUp (var sp: LongWord; var ep: LongWord): Boolean;
40 procedure cbufClear ();
42 var
43 conbufDumpToStdOut: Boolean = false;
46 implementation
49 // ////////////////////////////////////////////////////////////////////////// //
50 //const ConBufSize = 64;
51 const ConBufSize = 256*1024;
53 // each line in buffer ends with '\n'; we don't keep offsets or lengthes, as
54 // it's fairly easy to search in buffer, and drawing console is not a common
55 // thing, so it doesn't have to be superfast.
56 var
57 cbuf: packed array [0..ConBufSize-1] of Char;
58 cbufhead: LongWord = 0;
59 cbuftail: LongWord = 0; // `cbuftail` points *at* last char
60 changeCount: LongWord = 1;
63 function cbufLastChange (): LongWord; begin result := changeCount; end;
66 // ////////////////////////////////////////////////////////////////////////// //
67 var
68 needCon: Boolean = true;
70 procedure cbufPutChars (buf: PChar; count: Integer);
71 var
72 np: LongWord;
73 ch, och: Char;
74 begin
75 if count > 0 then
76 begin
77 if conbufDumpToStdOut then
78 begin
79 for np := 0 to count-1 do
80 begin
81 if needCon then begin write(stdout, 'CON: '); needCon := false; end;
82 write(stdout, buf[np]);
83 needCon := (buf[np] = #10);
84 end;
85 end;
86 Inc(changeCount);
87 if changeCount = 0 then changeCount := 1;
88 while count > 0 do
89 begin
90 Dec(count);
91 ch := buf^;
92 Inc(buf);
93 np := (cbuftail+1) mod ConBufSize;
94 if np = cbufhead then
95 begin
96 // we have to make some room; delete top line for this
97 while true do
98 begin
99 och := cbuf[cbufhead];
100 cbufhead := (cbufhead+1) mod ConBufSize;
101 if (cbufhead = np) or (och = #10) then break;
102 end;
103 end;
104 cbuf[np] := ch;
105 cbuftail := np;
106 end;
107 end;
108 end;
111 procedure cbufPut (const s: AnsiString);
112 begin
113 if length(s) > 0 then cbufPutChars(@s[1], length(s));
114 end;
117 // ////////////////////////////////////////////////////////////////////////// //
118 // warning! don't modify conbuf while the range is active!
119 function cbufWalkStart (): LongWord; begin result := cbuftail; end;
120 function cbufWalkEnd (pos: LongWord): LongWord; begin result := cbufhead; end;
121 procedure cbufPrev (var pos: LongWord); begin pos := (pos+ConBufSize-1) mod ConBufSize; end;
122 procedure cbufNext (var pos: LongWord); begin pos := (pos+1) mod ConBufSize; end;
124 function cbufAt (const pos: LongWord): Char; begin result := cbuf[pos mod ConBufSize]; end;
127 // ////////////////////////////////////////////////////////////////////////// //
128 procedure cbufLastLine (var sp: LongWord; var ep: LongWord);
129 var
130 pos, pp: LongWord;
131 begin
132 if cbufhead = cbuftail then
133 begin
134 sp := cbufhead;
135 ep := cbufhead+1;
136 exit;
137 end;
138 pos := cbuftail;
139 ep := pos;
140 while pos <> cbufhead do
141 begin
142 pp := (pos+ConBufSize-1) mod ConBufSize;
143 if cbuf[pp] = #10 then break;
144 pos := pp;
145 end;
146 sp := pos;
147 end;
150 function cbufLineUp (var sp: LongWord; var ep: LongWord): Boolean;
151 var
152 pos, pp: LongWord;
153 begin
154 if sp = cbufhead then begin sp := cbufhead; ep := cbufhead+1; result := false; exit; end;
155 pos := (sp+ConBufSize-1) mod ConBufSize;
156 if (pos = cbufhead) or (cbuf[pos] <> #10) then begin sp := cbufhead; ep := cbufhead+1; result := false; exit; end;
157 ep := pos;
158 while pos <> cbufhead do
159 begin
160 pp := (pos+ConBufSize-1) mod ConBufSize;
161 if cbuf[pp] = #10 then break;
162 pos := pp;
163 end;
164 sp := pos;
165 result := true;
166 end;
169 procedure cbufClear ();
170 begin
171 cbuf[0] := #10;
172 cbufhead := 0;
173 cbuftail := 0;
174 Inc(changeCount);
175 if changeCount = 0 then changeCount := 1;
176 end;
179 begin
180 cbuf[0] := #10;
181 end.