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