egra: oops, another agg `closePath()` bug
[iv.d.git] / egtui / utils.d
blob33e325360780e43598772fa93d8fc532a83ad39c
1 /* Invisible Vector Library
2 * simple FlexBox-based TUI engine
4 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
5 * Understanding is not required. Only obedience.
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, version 3 of the License ONLY.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 module iv.egtui.utils /*is aliced*/;
21 import iv.alice;
22 import iv.strex;
23 import iv.rawtty;
25 import iv.egtui.types;
28 // ////////////////////////////////////////////////////////////////////////// //
29 // calculate text bounds (can call delegate to output string too ;-)
30 // use "|...|" to "quote" word
31 void calcTextBounds (out int cols, out int lines, const(char)[] text, int maxwdt,
32 scope void delegate (int x, int y, const(char)[] s) dg=null)
34 int col = 0;
36 void putWord (const(char)[] text) {
37 while (text.length > 0) {
38 while (col == 0 && text.length > maxwdt) {
39 if (dg !is null) dg(0, lines, text[0..maxwdt]);
40 ++lines;
41 text = text[maxwdt..$];
43 if (text.length == 0) break;
44 if (col == 0) {
45 if (dg !is null) dg(0, lines, text);
46 col += cast(int)text.length;
47 if (cols < col) cols = col;
48 break;
50 int nw = col+cast(int)text.length+1;
51 if (nw <= maxwdt) {
52 ++col;
53 if (dg !is null) dg(col, lines, text);
54 col += cast(int)text.length;
55 if (cols < col) cols = col;
56 break;
58 ++lines;
59 col = 0;
63 while (text.length) {
64 int pos = 0;
65 while (pos < text.length && text.ptr[pos] != '\n' && text.ptr[pos] <= ' ') ++pos;
66 if (pos > 0) { text = text[pos..$]; continue; }
67 assert(pos == 0);
68 if (text.ptr[pos] == '\n') {
69 col = 0;
70 ++lines;
71 text = text[1..$];
72 continue;
74 if (text.ptr[pos] == '|') {
75 ++pos;
76 while (pos < text.length && text.ptr[pos] != '|') ++pos;
77 putWord(text[1..pos]);
78 if (pos >= text.length) break;
79 text = text[pos+1..$];
80 } else {
81 while (pos < text.length && text.ptr[pos] > ' ') ++pos;
82 putWord(text[0..pos]);
83 text = text[pos..$];
86 if (col > 0) ++lines;
90 // ////////////////////////////////////////////////////////////////////////// //
91 // calculate text bounds, insert soft wraps, remove excessive spaces
92 // use "|...|" to "quote" word
93 // return new text length
94 uint calcTextBoundsEx (out int cols, out int lines, char[] text, int maxwdt) {
95 enum EOT = 0;
96 enum SoftWrap = 6;
98 if (maxwdt < 1) maxwdt = 1;
100 int col = 0;
101 usize dpos = 0;
102 char[] dtext = text;
104 void putText (const(char)[] s...) {
105 foreach (char ch; s) {
106 if (dpos < dtext.length) dtext.ptr[dpos++] = ch;
110 // replace soft wraps with blanks
111 foreach (char ch; text) {
112 if (ch == EOT) break;
113 if (ch == SoftWrap) ch = ' ';
114 if (ch < 1 || ch > 3) {
115 if (ch != '\n' && (ch < ' ' || ch == 127)) ch = ' ';
117 dtext[dpos++] = ch;
119 // again
120 text = text[0..dpos];
121 dpos = 0;
123 void putWord (const(char)[] text) {
124 while (text.length > 0) {
125 while (col == 0 && text.length > maxwdt) {
126 putText(text[0..maxwdt]);
127 ++lines;
128 text = text[maxwdt..$];
130 if (text.length == 0) break;
131 if (col == 0) {
132 putText(text);
133 col += cast(int)text.length;
134 if (cols < col) cols = col;
135 break;
137 int nw = col+cast(int)text.length+1;
138 if (nw <= maxwdt) {
139 putText(' ');
140 putText(text);
141 col += cast(int)text.length+1;
142 if (cols < col) cols = col;
143 break;
145 // newline
146 if (lines != 0 || col) putText(SoftWrap);
147 ++lines;
148 col = 0;
152 // align chars
153 if (text.length && text.ptr[0] > 0 && text.ptr[0] <= 3) {
154 putText(text.ptr[0]);
155 text = text[1..$];
157 while (text.length) {
158 int pos = 0;
159 while (pos < text.length && text.ptr[pos] != '\n' && text.ptr[pos] <= ' ') ++pos;
160 if (pos > 0) { text = text[pos..$]; continue; }
161 assert(pos == 0);
162 if (text.ptr[pos] == '\n') {
163 if (lines || col) putText('\n');
164 col = 0;
165 ++lines;
166 text = text[1..$];
167 // align chars
168 if (text.length && text.ptr[0] > 0 && text.ptr[0] <= 3) {
169 putText(text.ptr[0]);
170 text = text[1..$];
172 continue;
174 if (text.ptr[pos] == '|') {
175 ++pos;
176 while (pos < text.length && text.ptr[pos] != '|') ++pos;
177 putWord(text[1..pos]);
178 if (pos >= text.length) break;
179 text = text[pos+1..$];
180 } else {
181 while (pos < text.length && text.ptr[pos] > ' ') ++pos;
182 putWord(text[0..pos]);
183 text = text[pos..$];
186 if (col > 0) ++lines;
188 return cast(uint)dpos;