1 |
|
|
/*************************************************************************** |
2 |
|
|
* Copyright (c) 2024 Microsoft Corporation |
3 |
|
|
* Copyright (c) 2026 Eclipse ThreadX contributors |
4 |
|
|
* |
5 |
|
|
* This program and the accompanying materials are made available under the |
6 |
|
|
* terms of the MIT License which is available at |
7 |
|
|
* https://opensource.org/licenses/MIT. |
8 |
|
|
* |
9 |
|
|
* SPDX-License-Identifier: MIT |
10 |
|
|
**************************************************************************/ |
11 |
|
|
|
12 |
|
|
// Some portions generated by Copilot (Sonnet 4.6). |
13 |
|
|
// Some portions generated by Claude Code (Opus 5). |
14 |
|
|
|
15 |
|
|
|
16 |
|
|
/**************************************************************************/ |
17 |
|
|
/**************************************************************************/ |
18 |
|
|
/** */ |
19 |
|
|
/** GUIX Component */ |
20 |
|
|
/** */ |
21 |
|
|
/** Multi Line Text View Management (Multi Line Text View) */ |
22 |
|
|
/** */ |
23 |
|
|
/**************************************************************************/ |
24 |
|
|
|
25 |
|
|
#define GX_SOURCE_CODE |
26 |
|
|
|
27 |
|
|
|
28 |
|
|
/* Include necessary system files. */ |
29 |
|
|
|
30 |
|
|
#include "gx_api.h" |
31 |
|
|
#include "gx_system.h" |
32 |
|
|
#include "gx_multi_line_text_view.h" |
33 |
|
|
#include "gx_utility.h" |
34 |
|
|
#include "gx_widget.h" |
35 |
|
|
|
36 |
|
|
/**************************************************************************/ |
37 |
|
|
/* */ |
38 |
|
|
/* FUNCTION RELEASE */ |
39 |
|
|
/* */ |
40 |
|
|
/* _gx_multi_line_text_view_display_info_get PORTABLE C */ |
41 |
|
|
/* 6.1 */ |
42 |
|
|
/* AUTHOR */ |
43 |
|
|
/* */ |
44 |
|
|
/* Kenneth Maxwell, Microsoft Corporation */ |
45 |
|
|
/* */ |
46 |
|
|
/* DESCRIPTION */ |
47 |
|
|
/* */ |
48 |
|
|
/* This function gets the length and pixel width of one word or */ |
49 |
|
|
/* some characters can be displayed in one line. */ |
50 |
|
|
/* */ |
51 |
|
|
/* INPUT */ |
52 |
|
|
/* */ |
53 |
|
|
/* text_view Multi line text view */ |
54 |
|
|
/* control block */ |
55 |
|
|
/* start_index Start character position in */ |
56 |
|
|
/* the input buffer */ |
57 |
|
|
/* end_index End character position in the */ |
58 |
|
|
/* input buffer */ |
59 |
|
|
/* text_info Text and word information to */ |
60 |
|
|
/* be returned */ |
61 |
|
|
/* available_width Width available to display */ |
62 |
|
|
/* text in current line */ |
63 |
|
|
/* */ |
64 |
|
|
/* OUTPUT */ |
65 |
|
|
/* */ |
66 |
|
|
/* None */ |
67 |
|
|
/* */ |
68 |
|
|
/* CALLS */ |
69 |
|
|
/* */ |
70 |
|
|
/* _gx_widget_font_get Retrieve font */ |
71 |
|
|
/* _gx_system_string_width_get Get the width of a string */ |
72 |
|
|
/* _gx_system_private_string_get Get string pointer in a */ |
73 |
|
|
/* dynamically copied string */ |
74 |
|
|
/* buffer */ |
75 |
|
|
/* _gx_utility_utf8_string_character_get Parse utf8 string to */ |
76 |
|
|
/* multi-byte glyph */ |
77 |
|
|
/* */ |
78 |
|
|
/* CALLED BY */ |
79 |
|
|
/* */ |
80 |
|
|
/* GUIX Internal Code */ |
81 |
|
|
/* */ |
82 |
|
|
/**************************************************************************/ |
83 |
|
133485 |
VOID _gx_multi_line_text_view_display_info_get(GX_MULTI_LINE_TEXT_VIEW *text_view, UINT start_index, |
84 |
|
|
UINT end_index, GX_MULTI_LINE_TEXT_INFO *text_info, GX_VALUE available_width) |
85 |
|
|
{ |
86 |
|
|
#ifdef GX_UTF8_SUPPORT |
87 |
|
133485 |
UINT current_index = start_index; |
88 |
|
|
#endif |
89 |
|
|
GX_STRING string; |
90 |
|
|
GX_STRING ch; |
91 |
|
|
GX_VALUE char_width; |
92 |
|
|
USHORT display_width; |
93 |
|
|
USHORT display_number; |
94 |
|
133485 |
UINT glyph_len = 1; |
95 |
|
|
GX_FONT *font; |
96 |
|
|
|
97 |
|
133485 |
text_info -> gx_text_display_width = 0; |
98 |
|
133485 |
text_info -> gx_text_display_number = 0; |
99 |
|
|
|
100 |
✓✓ |
133485 |
if (text_view -> gx_multi_line_text_view_text_id) |
101 |
|
|
{ |
102 |
|
1751 |
_gx_widget_string_get_ext((GX_WIDGET *)text_view, text_view -> gx_multi_line_text_view_text_id, &string); |
103 |
|
|
} |
104 |
|
|
else |
105 |
|
|
{ |
106 |
|
131734 |
_gx_system_private_string_get(&text_view -> gx_multi_line_text_view_text, &string, text_view -> gx_widget_style); |
107 |
|
|
} |
108 |
|
|
|
109 |
|
|
|
110 |
|
133485 |
string.gx_string_ptr += start_index; |
111 |
|
133485 |
string.gx_string_length = end_index - start_index; |
112 |
|
|
|
113 |
✓✓ |
133485 |
if (text_view -> gx_widget_status & GX_STATUS_LINE_BREAK_PROCESSED) |
114 |
|
|
{ |
115 |
|
|
/* Line breaking alreay preprocessed, only need to search for line break characters to do line break. */ |
116 |
✓✓ |
447 |
while (string.gx_string_length > 0) |
117 |
|
|
{ |
118 |
✓✓ |
434 |
if (string.gx_string_ptr[0] == GX_KEY_CARRIAGE_RETURN) |
119 |
|
|
{ |
120 |
|
16 |
text_info -> gx_text_display_number++; |
121 |
|
|
|
122 |
✓✓✓✓
|
16 |
if ((string.gx_string_length > 1) && string.gx_string_ptr[1] == GX_KEY_LINE_FEED) |
123 |
|
|
{ |
124 |
|
1 |
text_info -> gx_text_display_number++; |
125 |
|
|
} |
126 |
|
16 |
break; |
127 |
|
|
} |
128 |
✓✓ |
418 |
else if (string.gx_string_ptr[0] == GX_KEY_LINE_FEED) |
129 |
|
|
{ |
130 |
|
1 |
text_info -> gx_text_display_number++; |
131 |
|
1 |
break; |
132 |
|
|
} |
133 |
|
|
else |
134 |
|
|
{ |
135 |
|
417 |
text_info -> gx_text_display_number++; |
136 |
|
|
} |
137 |
|
|
|
138 |
|
417 |
string.gx_string_length--; |
139 |
|
417 |
string.gx_string_ptr++; |
140 |
|
|
} |
141 |
|
|
} |
142 |
|
|
else |
143 |
|
|
{ |
144 |
|
133455 |
_gx_widget_font_get((GX_WIDGET *)text_view, text_view -> gx_multi_line_text_view_font_id, &font); |
145 |
|
|
|
146 |
✓✓ |
133455 |
if (!font) |
147 |
|
|
{ |
148 |
|
1 |
return; |
149 |
|
|
} |
150 |
|
|
|
151 |
|
133454 |
display_width = 0; |
152 |
|
133454 |
display_number = 0; |
153 |
|
|
|
154 |
✓✓ |
1217894 |
while (string.gx_string_length > 0) |
155 |
|
|
{ |
156 |
|
1212203 |
ch = string; |
157 |
|
|
|
158 |
|
|
#ifdef GX_UTF8_SUPPORT |
159 |
|
1212203 |
_gx_utility_utf8_string_character_get(&string, GX_NULL, &glyph_len); |
160 |
|
1212203 |
current_index += glyph_len; |
161 |
|
|
#else |
162 |
|
|
string.gx_string_ptr++; |
163 |
|
|
string.gx_string_length--; |
164 |
|
|
#endif /* GX_UTF8_SUPPORT */ |
165 |
|
|
|
166 |
|
1212203 |
ch.gx_string_length = glyph_len; |
167 |
|
1212203 |
_gx_system_string_width_get_ext(font, &ch, &char_width); |
168 |
|
|
|
169 |
✓✓ |
1212203 |
if (ch.gx_string_ptr[0] == GX_KEY_CARRIAGE_RETURN) |
170 |
|
|
{ |
171 |
|
|
/* string now points at the byte after ch, and its length is the |
172 |
|
|
number of bytes still readable there. A GX_STRING carries its |
173 |
|
|
own length and need not be NUL terminated, so the byte after a |
174 |
|
|
trailing carriage return may lie outside the caller's buffer: |
175 |
|
|
it must not be examined. */ |
176 |
✓✓✓✓
|
90378 |
if ((string.gx_string_length > 0) && (string.gx_string_ptr[0] == GX_KEY_LINE_FEED)) |
177 |
|
|
{ |
178 |
|
1870 |
text_info -> gx_text_display_number = (USHORT)(text_info -> gx_text_display_number + 2); |
179 |
|
|
} |
180 |
|
|
else |
181 |
|
|
{ |
182 |
|
88508 |
text_info -> gx_text_display_number++; |
183 |
|
|
} |
184 |
|
90378 |
break; |
185 |
|
|
} |
186 |
✓✓ |
1121825 |
else if (ch.gx_string_ptr[0] == GX_KEY_LINE_FEED) |
187 |
|
|
{ |
188 |
|
11434 |
text_info -> gx_text_display_number++; |
189 |
|
11434 |
break; |
190 |
|
|
} |
191 |
✓✓ |
1110391 |
else if (((text_info -> gx_text_display_width + char_width) > available_width - 1) && |
192 |
✓✓ |
26137 |
(text_info -> gx_text_display_number > 0)) |
193 |
|
|
{ |
194 |
✓✓ |
25951 |
if (ch.gx_string_ptr[0] == ' ') |
195 |
|
|
{ |
196 |
|
|
/* Space itself causes overflow: consume it and any consecutive |
197 |
|
|
trailing spaces so the next line starts at the next word. |
198 |
|
|
Do NOT add to display_width -- the line's visual width stays |
199 |
|
|
within available_width. */ |
200 |
|
1821 |
text_info -> gx_text_display_number = (USHORT)(text_info -> gx_text_display_number + glyph_len); |
201 |
✓✓✓✓
|
26859 |
while ((string.gx_string_length > 0) && (string.gx_string_ptr[0] == ' ')) |
202 |
|
|
{ |
203 |
|
25038 |
text_info -> gx_text_display_number++; |
204 |
|
25038 |
string.gx_string_ptr++; |
205 |
|
25038 |
string.gx_string_length--; |
206 |
|
|
} |
207 |
|
|
|
208 |
|
|
/* If that whitespace ran to the end of the source line, take the |
209 |
|
|
line terminator with it. Left behind, the terminator becomes a |
210 |
|
|
row of its own, which draws as a blank line that is not present |
211 |
|
|
in the text. */ |
212 |
✓✓ |
1821 |
if (string.gx_string_length > 0) |
213 |
|
|
{ |
214 |
✓✓ |
1791 |
if (string.gx_string_ptr[0] == GX_KEY_CARRIAGE_RETURN) |
215 |
|
|
{ |
216 |
|
1 |
text_info -> gx_text_display_number++; |
217 |
|
|
|
218 |
✓✗✓✗
|
1 |
if ((string.gx_string_length > 1) && (string.gx_string_ptr[1] == GX_KEY_LINE_FEED)) |
219 |
|
|
{ |
220 |
|
1 |
text_info -> gx_text_display_number++; |
221 |
|
|
} |
222 |
|
|
} |
223 |
✓✓ |
1790 |
else if (string.gx_string_ptr[0] == GX_KEY_LINE_FEED) |
224 |
|
|
{ |
225 |
|
40 |
text_info -> gx_text_display_number++; |
226 |
|
|
} |
227 |
|
|
else |
228 |
|
|
{ |
229 |
|
|
/* More text follows the whitespace, so the next row starts |
230 |
|
|
at the next word. */ |
231 |
|
|
} |
232 |
|
|
} |
233 |
|
|
|
234 |
|
1821 |
break; |
235 |
|
|
} |
236 |
✓✓ |
24130 |
if (display_number == 0) |
237 |
|
|
{ |
238 |
|
8028 |
break; |
239 |
|
|
} |
240 |
|
16102 |
text_info -> gx_text_display_width = display_width; |
241 |
|
16102 |
text_info -> gx_text_display_number = display_number; |
242 |
|
16102 |
break; |
243 |
|
|
} |
244 |
|
1084440 |
text_info -> gx_text_display_width = (USHORT)(text_info -> gx_text_display_width + char_width); |
245 |
|
1084440 |
text_info -> gx_text_display_number = (USHORT)(text_info -> gx_text_display_number + glyph_len); |
246 |
|
|
|
247 |
✓✓✓✓ ✓✓ |
1084440 |
if ((ch.gx_string_ptr[0] == ' ') || (ch.gx_string_ptr[0] == ',') || (ch.gx_string_ptr[0] == ';')) |
248 |
|
|
{ |
249 |
|
184590 |
display_width = text_info -> gx_text_display_width; |
250 |
|
184590 |
display_number = text_info -> gx_text_display_number; |
251 |
|
|
} |
252 |
|
|
} |
253 |
|
|
} |
254 |
|
|
} |
255 |
|
|
|