1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** GUIX Component */
16 /** */
17 /** Multi Line Text View Management (Multi Line Text View) */
18 /** */
19 /**************************************************************************/
20
21 #define GX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25
26 #include "gx_api.h"
27 #include "gx_system.h"
28 #include "gx_multi_line_text_view.h"
29 #include "gx_utility.h"
30 #include "gx_widget.h"
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _gx_multi_line_text_view_display_info_get PORTABLE C */
37 /* 6.1 */
38 /* AUTHOR */
39 /* */
40 /* Kenneth Maxwell, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function gets the length and pixel width of one word or */
45 /* some characters can be displayed in one line. */
46 /* */
47 /* INPUT */
48 /* */
49 /* text_view Multi line text view */
50 /* control block */
51 /* start_index Start character position in */
52 /* the input buffer */
53 /* end_index End character position in the */
54 /* input buffer */
55 /* text_info Text and word information to */
56 /* be returned */
57 /* available_width Width available to display */
58 /* text in current line */
59 /* */
60 /* OUTPUT */
61 /* */
62 /* None */
63 /* */
64 /* CALLS */
65 /* */
66 /* _gx_widget_font_get Retrieve font */
67 /* _gx_system_string_width_get Get the width of a string */
68 /* _gx_system_private_string_get Get string pointer in a */
69 /* dynamically copied string */
70 /* buffer */
71 /* _gx_utility_utf8_string_character_get Parse utf8 string to */
72 /* multi-byte glyph */
73 /* */
74 /* CALLED BY */
75 /* */
76 /* GUIX Internal Code */
77 /* */
78 /* RELEASE HISTORY */
79 /* */
80 /* DATE NAME DESCRIPTION */
81 /* */
82 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
83 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
84 /* support line break status, */
85 /* resulting in version 6.1 */
86 /* */
87 /**************************************************************************/
_gx_multi_line_text_view_display_info_get(GX_MULTI_LINE_TEXT_VIEW * text_view,UINT start_index,UINT end_index,GX_MULTI_LINE_TEXT_INFO * text_info,GX_VALUE available_width)88 VOID _gx_multi_line_text_view_display_info_get(GX_MULTI_LINE_TEXT_VIEW *text_view, UINT start_index,
89 UINT end_index, GX_MULTI_LINE_TEXT_INFO *text_info, GX_VALUE available_width)
90 {
91 #ifdef GX_UTF8_SUPPORT
92 UINT current_index = start_index;
93 #endif
94 GX_STRING string;
95 GX_STRING ch;
96 GX_VALUE char_width;
97 USHORT display_width;
98 USHORT display_number;
99 UINT glyph_len = 1;
100 GX_FONT *font;
101
102 text_info -> gx_text_display_width = 0;
103 text_info -> gx_text_display_number = 0;
104
105 if (text_view -> gx_multi_line_text_view_text_id)
106 {
107 _gx_widget_string_get_ext((GX_WIDGET *)text_view, text_view -> gx_multi_line_text_view_text_id, &string);
108 }
109 else
110 {
111 _gx_system_private_string_get(&text_view -> gx_multi_line_text_view_text, &string, text_view -> gx_widget_style);
112 }
113
114
115 string.gx_string_ptr += start_index;
116 string.gx_string_length = end_index - start_index;
117
118 if (text_view -> gx_widget_status & GX_STATUS_LINE_BREAK_PROCESSED)
119 {
120 /* Line breaking alreay preprocessed, only need to search for line break characters to do line break. */
121 while (string.gx_string_length > 0)
122 {
123 if (string.gx_string_ptr[0] == GX_KEY_CARRIAGE_RETURN)
124 {
125 text_info -> gx_text_display_number++;
126
127 if ((string.gx_string_length > 1) && string.gx_string_ptr[1] == GX_KEY_LINE_FEED)
128 {
129 text_info -> gx_text_display_number++;
130 }
131 break;
132 }
133 else if (string.gx_string_ptr[0] == GX_KEY_LINE_FEED)
134 {
135 text_info -> gx_text_display_number++;
136 break;
137 }
138 else
139 {
140 text_info -> gx_text_display_number++;
141 }
142
143 string.gx_string_length--;
144 string.gx_string_ptr++;
145 }
146 }
147 else
148 {
149 _gx_widget_font_get((GX_WIDGET *)text_view, text_view -> gx_multi_line_text_view_font_id, &font);
150
151 if (!font)
152 {
153 return;
154 }
155
156 display_width = 0;
157 display_number = 0;
158
159 while (string.gx_string_length > 0)
160 {
161 ch = string;
162
163 #ifdef GX_UTF8_SUPPORT
164 _gx_utility_utf8_string_character_get(&string, GX_NULL, &glyph_len);
165 current_index += glyph_len;
166 #else
167 string.gx_string_ptr++;
168 string.gx_string_length--;
169 #endif /* GX_UTF8_SUPPORT */
170
171 ch.gx_string_length = glyph_len;
172 _gx_system_string_width_get_ext(font, &ch, &char_width);
173
174 if (ch.gx_string_ptr[0] == GX_KEY_CARRIAGE_RETURN)
175 {
176 if (ch.gx_string_ptr[1] == GX_KEY_LINE_FEED)
177 {
178 text_info -> gx_text_display_number = (USHORT)(text_info -> gx_text_display_number + 2);
179 }
180 else
181 {
182 text_info -> gx_text_display_number++;
183 }
184 break;
185 }
186 else if (ch.gx_string_ptr[0] == GX_KEY_LINE_FEED)
187 {
188 text_info -> gx_text_display_number++;
189 break;
190 }
191 else if (((text_info -> gx_text_display_width + char_width) > available_width - 1) &&
192 (text_info -> gx_text_display_number > 0) &&
193 (ch.gx_string_ptr[0] != ' '))
194 {
195 if (display_number == 0)
196 {
197 break;
198 }
199 text_info -> gx_text_display_width = display_width;
200 text_info -> gx_text_display_number = display_number;
201 break;
202 }
203 text_info -> gx_text_display_width = (USHORT)(text_info -> gx_text_display_width + char_width);
204 text_info -> gx_text_display_number = (USHORT)(text_info -> gx_text_display_number + glyph_len);
205
206 if ((ch.gx_string_ptr[0] == ' ') || (ch.gx_string_ptr[0] == ',') || (ch.gx_string_ptr[0] == ';'))
207 {
208 display_width = text_info -> gx_text_display_width;
209 display_number = text_info -> gx_text_display_number;
210 }
211 }
212 }
213 }
214
215