GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_multi_line_text_view_line_cache_update.c Lines: 85 85 100.0 %
Date: 2024-12-05 08:52:37 Branches: 30 30 100.0 %

Line Branch Exec Source
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_widget.h"
28
#include "gx_system.h"
29
#include "gx_window.h"
30
#include "gx_multi_line_text_view.h"
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _gx_multi_line_text_view_line_index_find            PORTABLE C      */
37
/*                                                           6.1          */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Kenneth Maxwell, Microsoft Corporation                              */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    Internal helper function to find the first byte index of the        */
45
/*    sepcified line from the specified position.                         */
46
/*                                                                        */
47
/*  INPUT                                                                 */
48
/*                                                                        */
49
/*    text_view                             Multi line text view          */
50
/*                                            control block               */
51
/*    start_line                            Line index to search from     */
52
/*    start_index                           Byte index to search from     */
53
/*    search_line                           Index of the line to search   */
54
/*    return_index                          Retrieved byte index of the   */
55
/*                                            line                        */
56
/*                                                                        */
57
/*  OUTPUT                                                                */
58
/*                                                                        */
59
/*    None                                                                */
60
/*                                                                        */
61
/*  CALLS                                                                 */
62
/*                                                                        */
63
/*    _gx_window_client_width_get           Get window client width       */
64
/*    _gx_multi_line_text_view_display_info_get                           */
65
/*                                          Get the number of character   */
66
/*                                            bytes a line can display    */
67
/*                                                                        */
68
/*  CALLED BY                                                             */
69
/*                                                                        */
70
/*    _gx_multi_line_text_view_line_start_cache_update                    */
71
/*                                                                        */
72
/*  RELEASE HISTORY                                                       */
73
/*                                                                        */
74
/*    DATE              NAME                      DESCRIPTION             */
75
/*                                                                        */
76
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
77
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
78
/*                                            resulting in version 6.1    */
79
/*                                                                        */
80
/**************************************************************************/
81
688
static VOID _gx_multi_line_text_view_line_index_find(GX_MULTI_LINE_TEXT_VIEW *view, UINT start_line, UINT start_index, UINT search_line, UINT *return_index)
82
{
83
GX_VALUE                client_width;
84
GX_MULTI_LINE_TEXT_INFO text_info;
85
86
    /* Pickup widget width. */
87
688
    _gx_window_client_width_get((GX_WINDOW *)view, &client_width);
88
89
    /* Calcualte client width. */
90
688
    client_width = (GX_VALUE)(client_width - (view -> gx_multi_line_text_view_whitespace << 1));
91
688
    client_width = (GX_VALUE)(client_width - 2);
92
93
    /* Calcualte from the start of the text. */
94
28291
    while (start_line < search_line)
95
    {
96
        /* Caculate maximum byte number a line can display in forward direction. */
97
27603
        _gx_multi_line_text_view_display_info_get(view, start_index, view -> gx_multi_line_text_view_text.gx_string_length, &text_info, client_width);
98
99
27603
        start_index += text_info.gx_text_display_number;
100
27603
        start_line++;
101
    }
102
103
688
    *return_index = start_index;
104
688
}
105
106
/**************************************************************************/
107
/*                                                                        */
108
/*  FUNCTION                                               RELEASE        */
109
/*                                                                        */
110
/*    _gx_multi_line_text_view_line_start_cache_create    PORTABLE C      */
111
/*                                                           6.1          */
112
/*  AUTHOR                                                                */
113
/*                                                                        */
114
/*    Kenneth Maxwell, Microsoft Corporation                              */
115
/*                                                                        */
116
/*  DESCRIPTION                                                           */
117
/*                                                                        */
118
/*    Internal helper function to create line index cache for specified   */
119
/*    line range.                                                         */
120
/*                                                                        */
121
/*  INPUT                                                                 */
122
/*                                                                        */
123
/*    text_view                             Multi line text view          */
124
/*                                            control block               */
125
/*    first_line                            The line to start cache       */
126
/*    updated_size                          The numer of lines to cache   */
127
/*                                                                        */
128
/*  OUTPUT                                                                */
129
/*                                                                        */
130
/*    None                                                                */
131
/*                                                                        */
132
/*  CALLS                                                                 */
133
/*                                                                        */
134
/*    _gx_window_client_width_get           Get window client width       */
135
/*    _gx_multi_line_text_view_line_index_find                            */
136
/*                                          Get index of the line         */
137
/*    _gx_multi_line_text_view_display_info_get                           */
138
/*                                          Get the number of character   */
139
/*                                            bytes a line can display    */
140
/*                                                                        */
141
/*  CALLED BY                                                             */
142
/*                                                                        */
143
/*    _gx_multi_line_text_view_line_start_cache_update                    */
144
/*                                                                        */
145
/*  RELEASE HISTORY                                                       */
146
/*                                                                        */
147
/*    DATE              NAME                      DESCRIPTION             */
148
/*                                                                        */
149
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
150
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
151
/*                                            resulting in version 6.1    */
152
/*                                                                        */
153
/**************************************************************************/
154
142
static VOID _gx_multi_line_text_view_line_start_cache_create(GX_MULTI_LINE_TEXT_VIEW *view, UINT first_line, UINT updated_size)
155
{
156
GX_VALUE                client_width;
157
GX_MULTI_LINE_TEXT_INFO text_info;
158
UINT                    index;
159
UINT                    loop;
160
161
    /* Pickup widget width. */
162
142
    _gx_window_client_width_get((GX_WINDOW *)view, &client_width);
163
164
    /* Calcualte client width. */
165
142
    client_width = (GX_VALUE)(client_width - (view -> gx_multi_line_text_view_whitespace << 1));
166
142
    client_width = (GX_VALUE)(client_width - 2);
167
168
    /* Find index of first line. */
169
142
    _gx_multi_line_text_view_line_index_find(view, 0, 0, first_line, &index);
170
171
142
    view -> gx_multi_line_text_view_line_index[0] = index;
172
173
2132
    for (loop = 1; loop < updated_size; loop++)
174
    {
175
        /* Caculate maximum byte number a line can display in forward direction. */
176
1990
        _gx_multi_line_text_view_display_info_get(view, index, view -> gx_multi_line_text_view_text.gx_string_length, &text_info, client_width);
177
178
1990
        index += text_info.gx_text_display_number;
179
1990
        view -> gx_multi_line_text_view_line_index[loop] = index;
180
    }
181
142
}
182
183
/**************************************************************************/
184
/*                                                                        */
185
/*  FUNCTION                                               RELEASE        */
186
/*                                                                        */
187
/*    _gx_multi_line_text_view_line_tail_cache_create     PORTABLE C      */
188
/*                                                           6.1          */
189
/*  AUTHOR                                                                */
190
/*                                                                        */
191
/*    Kenneth Maxwell, Microsoft Corporation                              */
192
/*                                                                        */
193
/*  DESCRIPTION                                                           */
194
/*                                                                        */
195
/*    Internal helper function to create line index cache for specified   */
196
/*    line range with specified byte index and line index to start        */
197
/*    calculating needed line index.                                      */
198
/*                                                                        */
199
/*  INPUT                                                                 */
200
/*                                                                        */
201
/*   view                                   Multi line text view          */
202
/*                                            control block               */
203
/*   start_index                            The first byte index of the   */
204
/*                                            line to search from         */
205
/*   start_line                             The line to search from       */
206
/*   first_line                             The line to start cache       */
207
/*   updated_size                           The number of lines to cache  */
208
/*                                                                        */
209
/*  OUTPUT                                                                */
210
/*                                                                        */
211
/*    None                                                                */
212
/*                                                                        */
213
/*  CALLS                                                                 */
214
/*                                                                        */
215
/*    _gx_window_client_width_get           Get window client width       */
216
/*    _gx_multi_line_text_view_line_index_find                            */
217
/*                                          Search byte index of specified*/
218
/*                                            line                        */
219
/*    _gx_multi_line_text_view_display_info_get                           */
220
/*                                          Calculate the number of bytes */
221
/*                                            that a line can display     */
222
/*    _gx_system_string_get                 Retrieve string by ID         */
223
/*    _gx_system_private_string_get         Retrieve string pointer in a  */
224
/*                                            dynamically copied string   */
225
/*                                            buffer                      */
226
/*                                                                        */
227
/*  CALLED BY                                                             */
228
/*                                                                        */
229
/*    _gx_multi_line_text_view_line_tail_cache_update                     */
230
/*                                                                        */
231
/*  RELEASE HISTORY                                                       */
232
/*                                                                        */
233
/*    DATE              NAME                      DESCRIPTION             */
234
/*                                                                        */
235
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
236
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
237
/*                                            resulting in version 6.1    */
238
/*                                                                        */
239
/**************************************************************************/
240
546
static VOID _gx_multi_line_text_view_line_tail_cache_create(GX_MULTI_LINE_TEXT_VIEW *view, UINT start_index, UINT start_line, UINT first_line, UINT updated_size)
241
{
242
GX_VALUE                client_width;
243
GX_MULTI_LINE_TEXT_INFO text_info;
244
UINT                    index;
245
UINT                    loop;
246
247
    /* Pickup widget width. */
248
546
    _gx_window_client_width_get((GX_WINDOW *)view, &client_width);
249
250
    /* Calcualte client width. */
251
546
    client_width = (GX_VALUE)(client_width - (view -> gx_multi_line_text_view_whitespace << 1));
252
546
    client_width = (GX_VALUE)(client_width - 2);
253
254
    /* Find index of first line. */
255
546
    _gx_multi_line_text_view_line_index_find(view, start_line, start_index, first_line, &index);
256
257
546
    view -> gx_multi_line_text_view_line_index[GX_MULTI_LINE_INDEX_CACHE_SIZE - updated_size] = index;
258
259
3765
    for (loop = GX_MULTI_LINE_INDEX_CACHE_SIZE - updated_size + 1; loop < GX_MULTI_LINE_INDEX_CACHE_SIZE; loop++)
260
    {
261
        /* Calculate maximum byte number a line can display in forward direction. */
262
3219
        _gx_multi_line_text_view_display_info_get(view, (UINT)index, view -> gx_multi_line_text_view_text.gx_string_length, &text_info, client_width);
263
264
3219
        index += text_info.gx_text_display_number;
265
3219
        view -> gx_multi_line_text_view_line_index[loop] = index;
266
    }
267
546
}
268
269
/**************************************************************************/
270
/*                                                                        */
271
/*  FUNCTION                                               RELEASE        */
272
/*                                                                        */
273
/*    _gx_multi_line_text_view_line_start_cache_update    PORTABLE C      */
274
/*                                                           6.1          */
275
/*  AUTHOR                                                                */
276
/*                                                                        */
277
/*    Kenneth Maxwell, Microsoft Corporation                              */
278
/*                                                                        */
279
/*  DESCRIPTION                                                           */
280
/*                                                                        */
281
/*    Internal helper function to update line index cache to cover        */
282
/*    previous lines.                                                     */
283
/*                                                                        */
284
/*  INPUT                                                                 */
285
/*                                                                        */
286
/*    view                                  Multi line text view          */
287
/*                                            control block               */
288
/*    new_first_cache_line                  The new line index that cache */
289
/*                                            start                       */
290
/*                                                                        */
291
/*  OUTPUT                                                                */
292
/*                                                                        */
293
/*    None                                                                */
294
/*                                                                        */
295
/*  CALLS                                                                 */
296
/*                                                                        */
297
/*    _gx_multi_line_text_view_line_start_cache_create                    */
298
/*                                          Create line index cache for   */
299
/*                                            specified range             */
300
/*                                                                        */
301
/*  CALLED BY                                                             */
302
/*                                                                        */
303
/*    _gx_multi_line_text_view_line_cache_update                          */
304
/*                                                                        */
305
/*  RELEASE HISTORY                                                       */
306
/*                                                                        */
307
/*    DATE              NAME                      DESCRIPTION             */
308
/*                                                                        */
309
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
310
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
311
/*                                            resulting in version 6.1    */
312
/*                                                                        */
313
/**************************************************************************/
314
142
static VOID _gx_multi_line_text_view_line_start_cache_update(GX_MULTI_LINE_TEXT_VIEW *view, UINT new_first_cache_line)
315
{
316
UINT first_cache_line;
317
UINT updated_size;
318
319
    /* Pickup first cache line. */
320
142
    first_cache_line = view -> gx_multi_line_text_view_first_cache_line;
321
322
142
    updated_size = first_cache_line - new_first_cache_line;
323
324
142
    if (updated_size < GX_MULTI_LINE_INDEX_CACHE_SIZE)
325
    {
326
        /* Move line index value in [0, index_cache_size - updated_size] to [updated_size, index_cache_size]. */
327
116
        memmove(view -> gx_multi_line_text_view_line_index + updated_size, view -> gx_multi_line_text_view_line_index,
328
116
                sizeof(UINT) * (GX_MULTI_LINE_INDEX_CACHE_SIZE - updated_size));
329
    }
330
    else
331
    {
332
26
        updated_size = GX_MULTI_LINE_INDEX_CACHE_SIZE;
333
    }
334
335
142
    _gx_multi_line_text_view_line_start_cache_create(view, new_first_cache_line, updated_size);
336
337
    /* Update cache size. */
338
142
    view -> gx_multi_line_text_view_cache_size = (GX_UBYTE)(view -> gx_multi_line_text_view_cache_size + updated_size);
339
340
142
    if (view -> gx_multi_line_text_view_cache_size > GX_MULTI_LINE_INDEX_CACHE_SIZE)
341
    {
342
140
        view -> gx_multi_line_text_view_cache_size = GX_MULTI_LINE_INDEX_CACHE_SIZE;
343
    }
344
345
    /* Update first cache line. */
346
142
    view -> gx_multi_line_text_view_first_cache_line = new_first_cache_line;
347
142
}
348
349
/**************************************************************************/
350
/*                                                                        */
351
/*  FUNCTION                                               RELEASE        */
352
/*                                                                        */
353
/*    _gx_multi_line_text_view_line_tail_cache_update     PORTABLE C      */
354
/*                                                           6.1          */
355
/*  AUTHOR                                                                */
356
/*                                                                        */
357
/*    Kenneth Maxwell, Microsoft Corporation                              */
358
/*                                                                        */
359
/*  DESCRIPTION                                                           */
360
/*                                                                        */
361
/*    Internal helper function to update line index cache to cover        */
362
/*    following lines.                                                    */
363
/*                                                                        */
364
/*  INPUT                                                                 */
365
/*                                                                        */
366
/*    view                                  Multi line text view          */
367
/*                                            control block               */
368
/*    new_first_cache_line                  The new line index that cache */
369
/*                                            start                       */
370
/*                                                                        */
371
/*  OUTPUT                                                                */
372
/*                                                                        */
373
/*    None                                                                */
374
/*                                                                        */
375
/*  CALLS                                                                 */
376
/*                                                                        */
377
/*    _gx_multi_line_text_view_line_tail_cache_create                     */
378
/*                                          Create line index cache for   */
379
/*                                            specified range             */
380
/*                                                                        */
381
/*  CALLED BY                                                             */
382
/*                                                                        */
383
/*    _gx_multi_line_text_view_line_cache_update                          */
384
/*                                                                        */
385
/*  RELEASE HISTORY                                                       */
386
/*                                                                        */
387
/*    DATE              NAME                      DESCRIPTION             */
388
/*                                                                        */
389
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
390
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
391
/*                                            resulting in version 6.1    */
392
/*                                                                        */
393
/**************************************************************************/
394
546
static VOID _gx_multi_line_text_view_line_tail_cache_update(GX_MULTI_LINE_TEXT_VIEW *view, UINT new_first_cache_line)
395
{
396
UINT first_cache_line;
397
UINT updated_size;
398
UINT last_cache_index;
399
UINT last_cache_line;
400
401
    /* Pickup first cache line. */
402
546
    first_cache_line = view -> gx_multi_line_text_view_first_cache_line;
403
404
546
    updated_size = new_first_cache_line - first_cache_line;
405
406
546
    last_cache_index = view -> gx_multi_line_text_view_line_index[GX_MULTI_LINE_INDEX_CACHE_SIZE - 1];
407
546
    last_cache_line = view -> gx_multi_line_text_view_first_cache_line + GX_MULTI_LINE_INDEX_CACHE_SIZE - 1;
408
409
546
    if (updated_size < GX_MULTI_LINE_INDEX_CACHE_SIZE)
410
    {
411
        /* Move line index value in [updated_size, index_cache_size - 1] to [0, index_cache_size - updated_size]. */
412
545
        memmove(view -> gx_multi_line_text_view_line_index, view -> gx_multi_line_text_view_line_index + updated_size,
413
545
                sizeof(UINT) * (GX_MULTI_LINE_INDEX_CACHE_SIZE - updated_size));
414
    }
415
    else
416
    {
417
1
        updated_size = GX_MULTI_LINE_INDEX_CACHE_SIZE;
418
    }
419
420
546
    _gx_multi_line_text_view_line_tail_cache_create(view, last_cache_index, last_cache_line,
421
546
                                                    new_first_cache_line + GX_MULTI_LINE_INDEX_CACHE_SIZE - updated_size, updated_size);
422
423
    /* Update cache size. */
424
546
    view -> gx_multi_line_text_view_cache_size = GX_MULTI_LINE_INDEX_CACHE_SIZE;
425
426
    /* Update first cache line. */
427
546
    view -> gx_multi_line_text_view_first_cache_line = new_first_cache_line;
428
546
}
429
430
/**************************************************************************/
431
/*                                                                        */
432
/*  FUNCTION                                               RELEASE        */
433
/*                                                                        */
434
/*    _gx_multi_line_text_view_line_cache_update          PORTABLE C      */
435
/*                                                           6.1.5        */
436
/*  AUTHOR                                                                */
437
/*                                                                        */
438
/*    Kenneth Maxwell, Microsoft Corporation                              */
439
/*                                                                        */
440
/*  DESCRIPTION                                                           */
441
/*                                                                        */
442
/*    This function updates the line index cache of the displayed text.   */
443
/*                                                                        */
444
/*  INPUT                                                                 */
445
/*                                                                        */
446
/*    text_view                             Multi line text view          */
447
/*                                            control block               */
448
/*  OUTPUT                                                                */
449
/*                                                                        */
450
/*    Completion Status                                                   */
451
/*                                                                        */
452
/*  CALLS                                                                 */
453
/*                                                                        */
454
/*    _gx_widget_font_get                   Get font by resource ID       */
455
/*    _gx_multi_line_text_view_line_start_cache_update                    */
456
/*                                          Update line index cache to    */
457
/*                                            cover previous lines        */
458
/*    _gx_multi_line_text_view_line_tail_cache_update                     */
459
/*                                          Update line index cache to    */
460
/*                                            cover following lines       */
461
/*                                                                        */
462
/*  CALLED BY                                                             */
463
/*                                                                        */
464
/*    GUIX Internal Code                                                  */
465
/*                                                                        */
466
/*  RELEASE HISTORY                                                       */
467
/*                                                                        */
468
/*    DATE              NAME                      DESCRIPTION             */
469
/*                                                                        */
470
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
471
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
472
/*                                            added logic to disable line */
473
/*                                            cache process while dynamic */
474
/*                                            bidi text is enabled,       */
475
/*                                            resulting in version 6.1    */
476
/*  03-02-2021     Ting Zhu                 Modified comment(s), fixed    */
477
/*                                            line height calculation,    */
478
/*                                            resulting in version 6.1.5  */
479
/*                                                                        */
480
/**************************************************************************/
481
4051
UINT _gx_multi_line_text_view_line_cache_update(GX_MULTI_LINE_TEXT_VIEW *view)
482
{
483
UINT     first_visible_line;
484
UINT     last_visible_line;
485
UINT     first_cache_line;
486
INT      new_first_cache_line;
487
INT      line_height;
488
GX_FONT *font;
489
490
#if defined(GX_DYNAMIC_BIDI_TEXT_SUPPORT)
491
    if (_gx_system_bidi_text_enabled)
492
    {
493
        /* No need to update line index cache when dynamic bidi text option is on. */
494
        return GX_SUCCESS;
495
    }
496
#endif
497
498
4051
    _gx_widget_font_get((GX_WIDGET *)view, view -> gx_multi_line_text_view_font_id, &font);
499
500
4051
    if (font)
501
    {
502
        /* Pickup line height. */
503
4042
        line_height = font -> gx_font_line_height + view -> gx_multi_line_text_view_line_space;
504
505
4042
        if (line_height <= 0)
506
        {
507
1
            return GX_FAILURE;
508
        }
509
510
        /* Calcualte first visible line. */
511
4041
        if (view -> gx_multi_line_text_view_text_scroll_shift < 0)
512
        {
513
3863
            first_visible_line = ((UINT)-view -> gx_multi_line_text_view_text_scroll_shift) / (UINT)line_height;
514
        }
515
        else
516
        {
517
178
            first_visible_line = 0;
518
        }
519
520
        /* Calculate last visible line. */
521
4041
        last_visible_line = first_visible_line + view -> gx_multi_line_text_view_text_visible_rows;
522
523
        /* Pickuo first cache line. */
524
4041
        first_cache_line = view -> gx_multi_line_text_view_first_cache_line;
525
526
        /* Calculat new first cache line. */
527
4041
        new_first_cache_line = GX_MULTI_LINE_INDEX_CACHE_SIZE;
528
4041
        new_first_cache_line -= (INT)(last_visible_line - first_visible_line + 1);
529
4041
        new_first_cache_line /= 2;
530
4041
        new_first_cache_line = (INT)first_visible_line - new_first_cache_line;
531
532
4041
        if ((UINT)new_first_cache_line + GX_MULTI_LINE_INDEX_CACHE_SIZE > view -> gx_multi_line_text_view_text_total_rows)
533
        {
534
2178
            new_first_cache_line = (INT)(view -> gx_multi_line_text_view_text_total_rows - GX_MULTI_LINE_INDEX_CACHE_SIZE);
535
        }
536
537
4041
        if (first_visible_line <= first_cache_line)
538
        {
539
321
            if (new_first_cache_line < 0)
540
            {
541
288
                new_first_cache_line = 0;
542
            }
543
544
321
            if (new_first_cache_line < (INT)first_cache_line)
545
            {
546
                /* Update line start cache. */
547
142
                _gx_multi_line_text_view_line_start_cache_update(view, (UINT)new_first_cache_line);
548
            }
549
        }
550
3720
        else if (last_visible_line >= first_cache_line + view -> gx_multi_line_text_view_cache_size - 1)
551
        {
552
1816
            if (new_first_cache_line > (INT)first_cache_line)
553
            {
554
                /* Update line tail cache. */
555
546
                _gx_multi_line_text_view_line_tail_cache_update(view, (UINT)new_first_cache_line);
556
            }
557
        }
558
    }
559
4050
    return GX_SUCCESS;
560
}
561