Rev 735 | Rev 740 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 735 | Rev 738 | ||
---|---|---|---|
1 | unit VTSCUI; |
1 | unit VTSCUI; |
2 | 2 | ||
3 | (************************************************) |
3 | (************************************************) |
4 | (* VTSCUI.PAS *) |
4 | (* VTSCUI.PAS *) |
5 | (* Author: Daniel Marschall *) |
5 | (* Author: Daniel Marschall *) |
6 | (* Revision: 2022-02-14 *) |
6 | (* Revision: 2022-02-14 *) |
7 | (* License: Apache 2.0 *) |
7 | (* License: Apache 2.0 *) |
8 | (* This file contains: *) |
8 | (* This file contains: *) |
9 | (* - ViaThinkSoft CUI (Console User Interface) *) |
9 | (* - ViaThinkSoft CUI (Console User Interface) *) |
10 | (************************************************) |
10 | (************************************************) |
11 | 11 | ||
12 | interface |
12 | interface |
13 | 13 | ||
14 | uses |
14 | uses |
15 | StrList; |
15 | StrList; |
16 | 16 | ||
17 | const |
17 | const |
18 | ScreenWidth = 80; |
18 | ScreenWidth = 80; |
19 | ScreenHeight = 25; |
19 | ScreenHeight = 25; |
20 | SINGLE_LINE_BOX_PADDING = 3; |
20 | SINGLE_LINE_BOX_PADDING = 3; |
21 | SINGLE_LINE_BOX_PADDING_INNER = 10; |
21 | SINGLE_LINE_BOX_PADDING_INNER = 10; |
22 | 22 | ||
23 | procedure DrawThinBorder(x, y, width, height: integer); |
23 | procedure DrawThinBorder(x, y, width, height: integer); |
24 | procedure DrawDoubleBorder(x, y, width, height: integer); |
24 | procedure DrawDoubleBorder(x, y, width, height: integer); |
25 | procedure DrawTextBar(str: string; line: integer); |
25 | procedure DrawTextBar(str: string; line: integer); |
26 | procedure DrawTitleBar(str: string); |
26 | procedure DrawTitleBar(center, left, right: string); |
27 | procedure DrawStatusBar(str: string); |
27 | procedure DrawStatusBar(str: string); |
28 | function DrawSelectionList(X, Y, ListWidth, ListHeight: integer; |
28 | function DrawSelectionList(X, Y, ListWidth, ListHeight: integer; |
29 | items: PStringList; allowESC: boolean; |
29 | items: PStringList; allowESC: boolean; |
30 | Title: string; borderStrength: integer): integer; |
30 | Title: string; borderStrength: integer): integer; |
31 | procedure ClearSection(x, y, width, height: integer); |
31 | procedure ClearSection(x, y, width, height: integer); |
32 | function QueryVal(var s: string; initX, initY, width, height: integer; |
32 | function QueryVal(var s: string; initX, initY, width, height: integer; |
33 | Title: string; borderStrength: integer): boolean; |
33 | Title: string; borderStrength: integer): boolean; |
34 | procedure ShowMessage(msg: string; title: string; dobeep: boolean); |
34 | procedure ShowMessage(msg: string; title: string; dobeep: boolean); |
35 | 35 | ||
36 | implementation |
36 | implementation |
37 | 37 | ||
38 | uses |
38 | uses |
39 | Crt, Drivers, VtsFuncs; |
39 | Crt, Drivers, VtsFuncs; |
40 | 40 | ||
41 | type |
41 | type |
42 | TCharDefs = array[0..7] of char; |
42 | TCharDefs = array[0..7] of char; |
43 | 43 | ||
44 | const |
44 | const |
45 | ThinLineChars: TCharDefs = |
45 | ThinLineChars: TCharDefs = |
46 | ( #$DA, #$C4, #$BF, |
46 | ( #$DA, #$C4, #$BF, |
47 | #$B3, #$B3, |
47 | #$B3, #$B3, |
48 | #$C0, #$C4, #$D9 |
48 | #$C0, #$C4, #$D9 |
49 | ); |
49 | ); |
50 | DoubleLineChars: TCharDefs = |
50 | DoubleLineChars: TCharDefs = |
51 | ( #$C9, #$CD, #$BB, |
51 | ( #$C9, #$CD, #$BB, |
52 | #$BA, #$BA, |
52 | #$BA, #$BA, |
53 | #$C8, #$CD, #$BC |
53 | #$C8, #$CD, #$BC |
54 | ); |
54 | ); |
55 | 55 | ||
56 | function FillRight(str: string; len: integer; c: char): string; |
56 | function FillRight(str: string; len: integer; c: char): string; |
57 | var |
57 | var |
58 | s: string; |
58 | s: string; |
59 | i: integer; |
59 | i: integer; |
60 | begin |
60 | begin |
61 | s := str; |
61 | s := str; |
62 | for i := Length(str) to len-1 do |
62 | for i := Length(str) to len-1 do |
63 | begin |
63 | begin |
64 | s := s + c; |
64 | s := s + c; |
65 | end; |
65 | end; |
66 | FillRight := s; |
66 | FillRight := s; |
67 | end; |
67 | end; |
68 | 68 | ||
69 | procedure DrawBorder(x, y, width, height, thickness: integer); |
69 | procedure DrawBorder(x, y, width, height, thickness: integer); |
70 | var |
70 | var |
71 | ix,iy: integer; |
71 | ix,iy: integer; |
72 | chars: TCharDefs; |
72 | chars: TCharDefs; |
73 | begin |
73 | begin |
74 | if thickness = 1 then |
74 | if thickness = 1 then |
75 | chars := ThinLineChars; |
75 | chars := ThinLineChars; |
76 | if thickness = 2 then |
76 | if thickness = 2 then |
77 | chars := DoubleLineChars; |
77 | chars := DoubleLineChars; |
78 | 78 | ||
79 | (* Top line *) |
79 | (* Top line *) |
80 | if y >= 1 then |
80 | if y >= 1 then |
81 | begin |
81 | begin |
82 | (* Top left corner *) |
82 | (* Top left corner *) |
83 | if x >= 1 then |
83 | if x >= 1 then |
84 | begin |
84 | begin |
85 | GotoXY(x,y); |
85 | GotoXY(x,y); |
86 | Write(chars[0]); |
86 | Write(chars[0]); |
87 | end |
87 | end |
88 | else |
88 | else |
89 | begin |
89 | begin |
90 | GotoXY(1,y); |
90 | GotoXY(1,y); |
91 | end; |
91 | end; |
92 | 92 | ||
93 | (* Top edge *) |
93 | (* Top edge *) |
94 | for ix := 1 to width-2 do |
94 | for ix := 1 to width-2 do |
95 | Write(chars[1]); |
95 | Write(chars[1]); |
96 | 96 | ||
97 | (* Top right corner *) |
97 | (* Top right corner *) |
98 | if x+width-1 <= ScreenWidth then |
98 | if x+width-1 <= ScreenWidth then |
99 | Write(chars[2]); |
99 | Write(chars[2]); |
100 | end; |
100 | end; |
101 | 101 | ||
102 | (* Left edge *) |
102 | (* Left edge *) |
103 | for iy := 1 to height-2 do |
103 | for iy := 1 to height-2 do |
104 | begin |
104 | begin |
105 | if (x >= 1) and (x <= ScreenWidth) and |
105 | if (x >= 1) and (x <= ScreenWidth) and |
106 | (y+iy >= 1) and (y+iy <= ScreenHeight) then |
106 | (y+iy >= 1) and (y+iy <= ScreenHeight) then |
107 | begin |
107 | begin |
108 | GotoXY(x,y+iy); |
108 | GotoXY(x,y+iy); |
109 | Write(chars[3]); |
109 | Write(chars[3]); |
110 | end; |
110 | end; |
111 | end; |
111 | end; |
112 | 112 | ||
113 | (* Right edge *) |
113 | (* Right edge *) |
114 | for iy := 1 to height-2 do |
114 | for iy := 1 to height-2 do |
115 | begin |
115 | begin |
116 | if (x+width-1 >= 1) and (x+width-1 <= ScreenWidth) and |
116 | if (x+width-1 >= 1) and (x+width-1 <= ScreenWidth) and |
117 | (y+iy >= 1) and (y+iy <= ScreenHeight) then |
117 | (y+iy >= 1) and (y+iy <= ScreenHeight) then |
118 | begin |
118 | begin |
119 | GotoXY(x+width-1,y+iy); |
119 | GotoXY(x+width-1,y+iy); |
120 | Write(chars[4]); |
120 | Write(chars[4]); |
121 | end; |
121 | end; |
122 | end; |
122 | end; |
123 | 123 | ||
124 | (* Bottom line *) |
124 | (* Bottom line *) |
125 | if y+height-1 <= ScreenHeight then |
125 | if y+height-1 <= ScreenHeight then |
126 | begin |
126 | begin |
127 | (* Bottom left corner *) |
127 | (* Bottom left corner *) |
128 | if x >= 1 then |
128 | if x >= 1 then |
129 | begin |
129 | begin |
130 | GotoXY(x,y+height-1); |
130 | GotoXY(x,y+height-1); |
131 | Write(chars[5]); |
131 | Write(chars[5]); |
132 | end |
132 | end |
133 | else |
133 | else |
134 | begin |
134 | begin |
135 | GotoXY(1,y+height-1); |
135 | GotoXY(1,y+height-1); |
136 | end; |
136 | end; |
137 | 137 | ||
138 | (* Bottom edge *) |
138 | (* Bottom edge *) |
139 | for ix := 1 to width-2 do |
139 | for ix := 1 to width-2 do |
140 | Write(chars[6]); |
140 | Write(chars[6]); |
141 | 141 | ||
142 | (* Bottom right corner *) |
142 | (* Bottom right corner *) |
143 | if x+width-1 <= ScreenWidth then |
143 | if x+width-1 <= ScreenWidth then |
144 | Write(chars[7]); |
144 | Write(chars[7]); |
145 | end; |
145 | end; |
146 | end; |
146 | end; |
147 | 147 | ||
148 | procedure DrawThinBorder(x, y, width, height: integer); |
148 | procedure DrawThinBorder(x, y, width, height: integer); |
149 | begin |
149 | begin |
150 | DrawBorder(x, y, width, height, 1); |
150 | DrawBorder(x, y, width, height, 1); |
151 | end; |
151 | end; |
152 | 152 | ||
153 | procedure DrawDoubleBorder(x, y, width, height: integer); |
153 | procedure DrawDoubleBorder(x, y, width, height: integer); |
154 | begin |
154 | begin |
155 | DrawBorder(x, y, width, height, 2); |
155 | DrawBorder(x, y, width, height, 2); |
156 | end; |
156 | end; |
157 | 157 | ||
158 | procedure DrawTextBar(str: string; line: integer); |
158 | procedure DrawTextBar(str: string; line: integer); |
159 | var |
159 | var |
160 | i, left, right: integer; |
160 | i, left, right: integer; |
161 | len: integer; |
161 | len: integer; |
162 | begin |
162 | begin |
163 | GotoXY(1,line); |
163 | GotoXY(1,line); |
164 | 164 | ||
165 | TextBackground(White); |
165 | TextBackground(White); |
166 | TextColor(Black); |
166 | TextColor(Black); |
167 | len := Length(str); |
167 | len := Length(str); |
168 | 168 | ||
169 | left := round((ScreenWidth-len)/2); |
169 | left := round((ScreenWidth-len)/2); |
170 | right := ScreenWidth - left - len; |
170 | right := ScreenWidth - left - len; |
171 | 171 | ||
172 | for i := 1 to left do |
172 | for i := 1 to left do |
173 | begin |
173 | begin |
174 | Write(' '); |
174 | Write(' '); |
175 | end; |
175 | end; |
176 | 176 | ||
177 | Write(str); |
177 | Write(str); |
178 | 178 | ||
179 | (* TODO: If we do "for i := 1 to right", then the console will scroll *) |
179 | (* TODO: If we do "for i := 1 to right", then the console will scroll *) |
180 | (* since the char in the right bottom corner is written! *) |
180 | (* since the char in the right bottom corner is written! *) |
181 | for i := 1 to right-1 do |
181 | for i := 1 to right-1 do |
182 | begin |
182 | begin |
183 | Write(' '); |
183 | Write(' '); |
184 | end; |
184 | end; |
185 | 185 | ||
186 | TextBackground(Black); |
186 | TextBackground(Black); |
187 | TextColor(White); |
187 | TextColor(White); |
188 | end; |
188 | end; |
189 | 189 | ||
190 | procedure DrawTitleBar(str: string); |
190 | procedure DrawTitleBar(center, left, right: string); |
191 | begin |
191 | begin |
192 | DrawTextBar(str, 1); |
192 | DrawTextBar(center, 1); |
- | 193 | ||
- | 194 | (* Put left text into the title bar *) |
|
- | 195 | GoToXY(1,1); |
|
- | 196 | TextBackground(White); |
|
- | 197 | TextColor(Black); |
|
- | 198 | WriteLn(left); |
|
- | 199 | TextBackground(Black); |
|
- | 200 | TextColor(White); |
|
- | 201 | ||
- | 202 | (* Put right text into the title bar *) |
|
- | 203 | GotoXY(ScreenWidth-Length(right)+1,1); |
|
- | 204 | TextBackground(White); |
|
- | 205 | TextColor(Black); |
|
- | 206 | WriteLn(right); |
|
- | 207 | TextBackground(Black); |
|
- | 208 | TextColor(White); |
|
193 | end; |
209 | end; |
194 | 210 | ||
195 | procedure DrawStatusBar(str: string); |
211 | procedure DrawStatusBar(str: string); |
196 | begin |
212 | begin |
197 | DrawTextBar(str, ScreenHeight); |
213 | DrawTextBar(str, ScreenHeight); |
198 | end; |
214 | end; |
199 | 215 | ||
200 | function DrawSelectionList(X, Y, ListWidth, ListHeight: integer; |
216 | function DrawSelectionList(X, Y, ListWidth, ListHeight: integer; |
201 | items: PStringList; allowESC: boolean; |
217 | items: PStringList; allowESC: boolean; |
202 | Title: string; borderStrength: integer): integer; |
218 | Title: string; borderStrength: integer): integer; |
203 | var |
219 | var |
204 | i: integer; |
220 | i: integer; |
205 | itemIndex: integer; |
221 | itemIndex: integer; |
206 | sc: char; |
222 | sc: char; |
207 | iStartScope, iEndScope: integer; |
223 | iStartScope, iEndScope: integer; |
208 | sTmp: string; |
224 | sTmp: string; |
209 | label |
225 | label |
210 | doAgain; |
226 | doAgain; |
211 | begin |
227 | begin |
212 | if borderStrength = 1 then |
228 | if borderStrength = 1 then |
213 | begin |
229 | begin |
214 | DrawThinBorder(X-1, Y-1, ListWidth+2, ListHeight+2); |
230 | DrawThinBorder(X-1, Y-1, ListWidth+2, ListHeight+2); |
215 | end; |
231 | end; |
216 | 232 | ||
217 | if borderStrength = 2 then |
233 | if borderStrength = 2 then |
218 | begin |
234 | begin |
219 | DrawDoubleBorder(X-1, Y-1, ListWidth+2, ListHeight+2); |
235 | DrawDoubleBorder(X-1, Y-1, ListWidth+2, ListHeight+2); |
220 | end; |
236 | end; |
221 | 237 | ||
222 | if Title <> '' then |
238 | if Title <> '' then |
223 | begin |
239 | begin |
224 | if borderStrength > 0 then |
240 | if borderStrength > 0 then |
225 | GoToXY(X+1, Y-1) |
241 | GoToXY(X+1, Y-1) |
226 | else |
242 | else |
227 | GoToXY(X, Y-1); |
243 | GoToXY(X, Y-1); |
228 | Write(Title); |
244 | Write(Title); |
229 | end; |
245 | end; |
230 | 246 | ||
231 | (*CursorOff;*) |
247 | (*CursorOff;*) |
232 | 248 | ||
233 | itemIndex := 0; |
249 | itemIndex := 0; |
234 | iStartScope := itemIndex; |
250 | iStartScope := itemIndex; |
235 | iEndScope := itemIndex + ListHeight; |
251 | iEndScope := itemIndex + ListHeight; |
236 | 252 | ||
237 | doAgain: |
253 | doAgain: |
238 | 254 | ||
239 | if itemIndex < 0 then |
255 | if itemIndex < 0 then |
240 | itemIndex := 0; |
256 | itemIndex := 0; |
241 | if itemIndex > ListCount(items)-1 then |
257 | if itemIndex > ListCount(items)-1 then |
242 | itemIndex := ListCount(items)-1; |
258 | itemIndex := ListCount(items)-1; |
243 | 259 | ||
244 | if itemIndex < iStartScope then |
260 | if itemIndex < iStartScope then |
245 | begin |
261 | begin |
246 | Dec(iEndScope); |
262 | Dec(iEndScope); |
247 | Dec(iStartScope); |
263 | Dec(iStartScope); |
248 | end; |
264 | end; |
249 | 265 | ||
250 | if itemIndex > iEndScope-1 then |
266 | if itemIndex > iEndScope-1 then |
251 | begin |
267 | begin |
252 | Inc(iEndScope); |
268 | Inc(iEndScope); |
253 | Inc(iStartScope); |
269 | Inc(iStartScope); |
254 | end; |
270 | end; |
255 | 271 | ||
256 | if borderStrength > 0 then |
272 | if borderStrength > 0 then |
257 | begin |
273 | begin |
258 | (* Show scroll arrows *) |
274 | (* Show scroll arrows *) |
259 | GotoXY(X+ListWidth, Y); |
275 | GotoXY(X+ListWidth, Y); |
260 | if iStartScope > 0 then |
276 | if iStartScope > 0 then |
261 | begin |
277 | begin |
262 | TextBackground(White); |
278 | TextBackground(White); |
263 | TextColor(Black); |
279 | TextColor(Black); |
264 | WriteLn(#$18(*ArrowUp*)); |
280 | WriteLn(#$18(*ArrowUp*)); |
265 | TextBackground(Black); |
281 | TextBackground(Black); |
266 | TextColor(White); |
282 | TextColor(White); |
267 | end |
283 | end |
268 | else if borderStrength = 1 then |
284 | else if borderStrength = 1 then |
269 | WriteLn(ThinLineChars[4]) |
285 | WriteLn(ThinLineChars[4]) |
270 | else if borderStrength = 2 then |
286 | else if borderStrength = 2 then |
271 | WriteLn(DoubleLineChars[4]); |
287 | WriteLn(DoubleLineChars[4]); |
272 | 288 | ||
273 | GotoXY(X+ListWidth, Y+ListHeight-1); |
289 | GotoXY(X+ListWidth, Y+ListHeight-1); |
274 | if ListCount(items) > iEndScope then |
290 | if ListCount(items) > iEndScope then |
275 | begin |
291 | begin |
276 | TextBackground(White); |
292 | TextBackground(White); |
277 | TextColor(Black); |
293 | TextColor(Black); |
278 | WriteLn(#$19(*ArrowDown*)); |
294 | WriteLn(#$19(*ArrowDown*)); |
279 | TextBackground(Black); |
295 | TextBackground(Black); |
280 | TextColor(White); |
296 | TextColor(White); |
281 | end |
297 | end |
282 | else if borderStrength = 1 then |
298 | else if borderStrength = 1 then |
283 | WriteLn(ThinLineChars[4]) |
299 | WriteLn(ThinLineChars[4]) |
284 | else if borderStrength = 2 then |
300 | else if borderStrength = 2 then |
285 | WriteLn(DoubleLineChars[4]); |
301 | WriteLn(DoubleLineChars[4]); |
286 | end; |
302 | end; |
287 | 303 | ||
288 | for i := iStartScope to iEndScope-1 do |
304 | for i := iStartScope to iEndScope-1 do |
289 | begin |
305 | begin |
290 | if itemIndex = i then |
306 | if itemIndex = i then |
291 | begin |
307 | begin |
292 | TextColor(Black); |
308 | TextColor(Black); |
293 | TextBackground(White); |
309 | TextBackground(White); |
294 | end |
310 | end |
295 | else |
311 | else |
296 | begin |
312 | begin |
297 | TextColor(White); |
313 | TextColor(White); |
298 | TextBackground(Black); |
314 | TextBackground(Black); |
299 | end; |
315 | end; |
300 | GotoXY(x,y+i-iStartScope); |
316 | GotoXY(x,y+i-iStartScope); |
301 | if i > ListCount(items)-1 then |
317 | if i > ListCount(items)-1 then |
302 | Write(FillRight('', ListWidth, ' ')) |
318 | Write(FillRight('', ListWidth, ' ')) |
303 | else |
319 | else |
304 | begin |
320 | begin |
305 | sTmp := ListGetElement(items, i); |
321 | sTmp := ListGetElement(items, i); |
306 | if Length(sTmp) > ListWidth then |
322 | if Length(sTmp) > ListWidth then |
307 | begin |
323 | begin |
308 | (* Cut too long line *) |
324 | (* Cut too long line *) |
309 | sTmp := Copy(sTmp, 1, ListWidth-3) + '...'; |
325 | sTmp := Copy(sTmp, 1, ListWidth-3) + '...'; |
310 | end; |
326 | end; |
311 | Write(FillRight(sTmp, ListWidth, ' ')); |
327 | Write(FillRight(sTmp, ListWidth, ' ')); |
312 | end; |
328 | end; |
313 | TextColor(White); |
329 | TextColor(White); |
314 | TextBackground(Black); |
330 | TextBackground(Black); |
315 | end; |
331 | end; |
316 | 332 | ||
317 | repeat |
333 | repeat |
318 | GotoXY(ScreenWidth, ScreenHeight); |
334 | GotoXY(ScreenWidth, ScreenHeight); |
319 | 335 | ||
320 | sc := ReadKey; |
336 | sc := ReadKey; |
321 | if sc = #$00(*ExtendedKeyCode*) then |
337 | if sc = #$00(*ExtendedKeyCode*) then |
322 | begin |
338 | begin |
323 | sc := ReadKey; |
339 | sc := ReadKey; |
324 | if sc = #$48(*UpKey*) then |
340 | if sc = #$48(*UpKey*) then |
325 | begin |
341 | begin |
326 | dec(itemIndex); |
342 | dec(itemIndex); |
327 | goto doAgain; |
343 | goto doAgain; |
328 | end |
344 | end |
329 | else if sc = #$50(*DownKey*) then |
345 | else if sc = #$50(*DownKey*) then |
330 | begin |
346 | begin |
331 | inc(itemIndex); |
347 | inc(itemIndex); |
332 | goto doAgain; |
348 | goto doAgain; |
333 | end |
349 | end |
334 | else if sc = #$47(*POS1*) then |
350 | else if sc = #$47(*POS1*) then |
335 | begin |
351 | begin |
336 | itemIndex := 0; |
352 | itemIndex := 0; |
337 | goto doAgain; |
353 | goto doAgain; |
338 | end |
354 | end |
339 | else if sc = #$4F(*END*) then |
355 | else if sc = #$4F(*END*) then |
340 | begin |
356 | begin |
341 | itemIndex := ListCount(items); |
357 | itemIndex := ListCount(items); |
342 | goto doAgain; |
358 | goto doAgain; |
343 | end; |
359 | end; |
344 | end; |
360 | end; |
345 | 361 | ||
346 | if sc = #13(*Return*) then |
362 | if sc = #13(*Return*) then |
347 | begin |
363 | begin |
348 | DrawSelectionList := itemIndex; |
364 | DrawSelectionList := itemIndex; |
349 | break; |
365 | break; |
350 | end; |
366 | end; |
351 | 367 | ||
352 | if allowESC and (sc = #27(*ESC*)) then |
368 | if allowESC and (sc = #27(*ESC*)) then |
353 | begin |
369 | begin |
354 | DrawSelectionList := -1; |
370 | DrawSelectionList := -1; |
355 | break; |
371 | break; |
356 | end; |
372 | end; |
357 | until false; |
373 | until false; |
358 | 374 | ||
359 | (*CursorOn;*) |
375 | (*CursorOn;*) |
360 | end; |
376 | end; |
361 | 377 | ||
362 | procedure ClearSection(x, y, width, height: integer); |
378 | procedure ClearSection(x, y, width, height: integer); |
363 | var |
379 | var |
364 | ix, iy: integer; |
380 | ix, iy: integer; |
365 | begin |
381 | begin |
366 | for iy := y to y+height-1 do |
382 | for iy := y to y+height-1 do |
367 | begin |
383 | begin |
368 | for ix := x to x+width-1 do |
384 | for ix := x to x+width-1 do |
369 | begin |
385 | begin |
370 | GoToXY(ix,iy); |
386 | GoToXY(ix,iy); |
371 | Write(' '); |
387 | Write(' '); |
372 | end; |
388 | end; |
373 | end; |
389 | end; |
374 | end; |
390 | end; |
375 | 391 | ||
376 | function QueryVal(var s: string; initX, initY, width, height: integer; |
392 | function QueryVal(var s: string; initX, initY, width, height: integer; |
377 | Title: string; borderStrength: integer): boolean; |
393 | Title: string; borderStrength: integer): boolean; |
378 | var |
394 | var |
379 | x, y: integer; |
395 | x, y: integer; |
380 | i, j: integer; |
396 | i, j: integer; |
381 | sc: char; |
397 | sc: char; |
382 | stmp: string; |
398 | stmp: string; |
383 | begin |
399 | begin |
384 | if borderStrength = 1 then |
400 | if borderStrength = 1 then |
385 | DrawThinBorder(initX-1,initY-1,width+2,height+2); |
401 | DrawThinBorder(initX-1,initY-1,width+2,height+2); |
386 | if borderStrength = 2 then |
402 | if borderStrength = 2 then |
387 | DrawDoubleBorder(initX-1,initY-1,width+2,height+2); |
403 | DrawDoubleBorder(initX-1,initY-1,width+2,height+2); |
388 | if title <> '' then |
404 | if title <> '' then |
389 | begin |
405 | begin |
390 | if borderStrength > 0 then |
406 | if borderStrength > 0 then |
391 | GoToXY(initX+1, initY-1) |
407 | GoToXY(initX+1, initY-1) |
392 | else |
408 | else |
393 | GoToXY(initX, initY-1); |
409 | GoToXY(initX, initY-1); |
394 | Write(title); |
410 | Write(title); |
395 | end; |
411 | end; |
396 | ClearSection(initX,initY,width,height); |
412 | ClearSection(initX,initY,width,height); |
397 | 413 | ||
398 | x := initX; |
414 | x := initX; |
399 | y := initY; |
415 | y := initY; |
400 | 416 | ||
401 | (* Write existing string value and set cursor *) |
417 | (* Write existing string value and set cursor *) |
402 | stmp := s; |
418 | stmp := s; |
403 | s := ''; |
419 | s := ''; |
404 | for i := 1 to Length(stmp) do |
420 | for i := 1 to Length(stmp) do |
405 | begin |
421 | begin |
406 | if stmp[i] = #10 then |
422 | if stmp[i] = #10 then |
407 | begin |
423 | begin |
408 | s := s + stmp[i]; |
424 | s := s + stmp[i]; |
409 | continue; |
425 | continue; |
410 | end; |
426 | end; |
411 | 427 | ||
412 | GoToXY(x,y); |
428 | GoToXY(x,y); |
413 | s := s + stmp[i]; |
429 | s := s + stmp[i]; |
414 | Write(stmp[i]); |
430 | Write(stmp[i]); |
415 | Inc(x); |
431 | Inc(x); |
416 | 432 | ||
417 | if (x=initX+width-1) and (y=initY+height-1) then |
433 | if (x=initX+width-1) and (y=initY+height-1) then |
418 | begin |
434 | begin |
419 | (* Attention: Data following after this will be lost! *) |
435 | (* Attention: Data following after this will be lost! *) |
420 | break; |
436 | break; |
421 | end; |
437 | end; |
422 | 438 | ||
423 | if stmp[i] = #13 then |
439 | if stmp[i] = #13 then |
424 | begin |
440 | begin |
425 | if y=initY+height-1 then |
441 | if y=initY+height-1 then |
426 | begin |
442 | begin |
427 | (* Attention: Data following after this will be lost! *) |
443 | (* Attention: Data following after this will be lost! *) |
428 | s := Copy(s, 1, Length(s)-1); |
444 | s := Copy(s, 1, Length(s)-1); |
429 | Dec(x); |
445 | Dec(x); |
430 | break; |
446 | break; |
431 | end; |
447 | end; |
432 | x := initX; |
448 | x := initX; |
433 | Inc(y); |
449 | Inc(y); |
434 | continue; |
450 | continue; |
435 | end; |
451 | end; |
436 | 452 | ||
437 | if x=initX+width then |
453 | if x=initX+width then |
438 | begin |
454 | begin |
439 | Inc(y); |
455 | Inc(y); |
440 | x := initX; |
456 | x := initX; |
441 | end; |
457 | end; |
442 | end; |
458 | end; |
443 | 459 | ||
444 | repeat |
460 | repeat |
445 | GotoXY(x, y); |
461 | GotoXY(x, y); |
446 | sc := ReadKey; |
462 | sc := ReadKey; |
447 | 463 | ||
448 | if sc = #0 then |
464 | if sc = #0 then |
449 | begin |
465 | begin |
450 | (* Extended key code *) |
466 | (* Extended key code *) |
451 | sc := ReadKey; |
467 | sc := ReadKey; |
452 | (* TODO: Implement keys like DEL, END, POS1, and ArrowKeys *) |
468 | (* TODO: Implement keys like DEL, END, POS1, and ArrowKeys *) |
453 | Beep; |
469 | Beep; |
454 | continue; |
470 | continue; |
455 | end |
471 | end |
456 | else if sc = #8(*Backspace*) then |
472 | else if sc = #8(*Backspace*) then |
457 | begin |
473 | begin |
458 | if x <= initX then |
474 | if x <= initX then |
459 | begin |
475 | begin |
460 | if y = initY then |
476 | if y = initY then |
461 | begin |
477 | begin |
462 | Beep; |
478 | Beep; |
463 | continue; |
479 | continue; |
464 | end; |
480 | end; |
465 | Dec(y); |
481 | Dec(y); |
466 | 482 | ||
467 | (* Find out length of previous line *) |
483 | (* Find out length of previous line *) |
468 | j := Length(s)-2(*CRLF*); |
484 | j := Length(s)-2(*CRLF*); |
469 | while (j >= 0) do |
485 | while (j >= 0) do |
470 | begin |
486 | begin |
471 | if (s[j]=#13) or (s[j]=#10) then break; |
487 | if (s[j]=#13) or (s[j]=#10) then break; |
472 | Dec(j); |
488 | Dec(j); |
473 | end; |
489 | end; |
474 | j := Length(s)-2(*CRLF*)-j; |
490 | j := Length(s)-2(*CRLF*)-j; |
475 | x := initX + j; |
491 | x := initX + j; |
476 | s := Copy(s, 1, Length(s)-1); (* Remove #10 now. #13 will be removed below *) |
492 | s := Copy(s, 1, Length(s)-1); (* Remove #10 now. #13 will be removed below *) |
477 | end |
493 | end |
478 | else |
494 | else |
479 | begin |
495 | begin |
480 | Dec(x); |
496 | Dec(x); |
481 | end; |
497 | end; |
482 | GotoXY(x, y); |
498 | GotoXY(x, y); |
483 | Write(' '); |
499 | Write(' '); |
484 | GotoXY(x, y); |
500 | GotoXY(x, y); |
485 | s := Copy(s, 1, Length(s)-1); |
501 | s := Copy(s, 1, Length(s)-1); |
486 | continue; |
502 | continue; |
487 | end |
503 | end |
488 | else if sc = #13(*Return*) then |
504 | else if sc = #13(*Return*) then |
489 | begin |
505 | begin |
490 | if GetShiftState and kbRightShift <> 0 then |
506 | if GetShiftState and kbRightShift <> 0 then |
491 | begin |
507 | begin |
492 | if y=initY+height-1 then |
508 | if y=initY+height-1 then |
493 | begin |
509 | begin |
494 | Beep; |
510 | Beep; |
495 | continue; |
511 | continue; |
496 | end; |
512 | end; |
497 | s := s + #13 + #10; |
513 | s := s + #13 + #10; |
498 | x := initX; |
514 | x := initX; |
499 | Inc(y); |
515 | Inc(y); |
500 | end |
516 | end |
501 | else |
517 | else |
502 | begin |
518 | begin |
503 | QueryVal := true; |
519 | QueryVal := true; |
504 | exit; |
520 | exit; |
505 | end; |
521 | end; |
506 | end |
522 | end |
507 | else if sc = #27(*ESC*) then |
523 | else if sc = #27(*ESC*) then |
508 | begin |
524 | begin |
509 | QueryVal := false; |
525 | QueryVal := false; |
510 | exit; |
526 | exit; |
511 | end |
527 | end |
512 | else |
528 | else |
513 | begin |
529 | begin |
514 | if (x=initX+width-1) and (y=initY+height-1) then |
530 | if (x=initX+width-1) and (y=initY+height-1) then |
515 | begin |
531 | begin |
516 | Beep; |
532 | Beep; |
517 | continue; |
533 | continue; |
518 | end; |
534 | end; |
519 | s := s + sc; |
535 | s := s + sc; |
520 | Write(sc); |
536 | Write(sc); |
521 | Inc(x); |
537 | Inc(x); |
522 | if x >= initX+width then |
538 | if x >= initX+width then |
523 | begin |
539 | begin |
524 | Inc(y); |
540 | Inc(y); |
525 | x := initX; |
541 | x := initX; |
526 | end; |
542 | end; |
527 | end; |
543 | end; |
528 | until false; |
544 | until false; |
529 | end; |
545 | end; |
530 | 546 | ||
531 | procedure ShowMessage(msg: string; title: string; dobeep: boolean); |
547 | procedure ShowMessage(msg: string; title: string; dobeep: boolean); |
532 | var |
548 | var |
533 | x, y, w, h: integer; |
549 | x, y, w, h: integer; |
534 | begin |
550 | begin |
535 | x := SINGLE_LINE_BOX_PADDING_INNER; |
551 | x := SINGLE_LINE_BOX_PADDING_INNER; |
536 | y := ScreenHeight div 2 - 1; |
552 | y := ScreenHeight div 2 - 1; |
537 | w := ScreenWidth - (SINGLE_LINE_BOX_PADDING_INNER-1)*2; |
553 | w := ScreenWidth - (SINGLE_LINE_BOX_PADDING_INNER-1)*2; |
538 | h := 1; |
554 | h := 1; |
539 | DrawDoubleBorder(x-1, y, w+2, h+2); |
555 | DrawDoubleBorder(x-1, y, w+2, h+2); |
540 | ClearSection(x, y+1, w-2, h); |
556 | ClearSection(x, y+1, w-2, h); |
541 | if title <> '' then |
557 | if title <> '' then |
542 | begin |
558 | begin |
543 | GoToXY(x+1, y); |
559 | GoToXY(x+1, y); |
544 | Write(title); |
560 | Write(title); |
545 | end; |
561 | end; |
546 | GoToXY(x, y+1); |
562 | GoToXY(x, y+1); |
547 | Write(msg); |
563 | Write(msg); |
548 | if DoBeep then Beep; |
564 | if DoBeep then Beep; |
549 | end; |
565 | end; |
550 | 566 | ||
551 | end. |
567 | end. |
552 | 568 |