GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_vertical_list_scroll.c Lines: 66 66 100.0 %
Date: 2026-03-06 19:21:09 Branches: 62 62 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 * Copyright (c) 2026-present 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
13
/**************************************************************************/
14
/**************************************************************************/
15
/**                                                                       */
16
/** GUIX Component                                                        */
17
/**                                                                       */
18
/**   Vertical List (List)                                                */
19
/**                                                                       */
20
/**************************************************************************/
21
22
#define GX_SOURCE_CODE
23
24
25
/* Include necessary system files.  */
26
27
#include "gx_api.h"
28
#include "gx_widget.h"
29
#include "gx_window.h"
30
#include "gx_system.h"
31
#include "gx_scrollbar.h"
32
33
/**************************************************************************/
34
/*                                                                        */
35
/*  FUNCTION                                               RELEASE        */
36
/*                                                                        */
37
/*    _gx_vertical_list_invisible_page_scroll             PORTABLE C      */
38
/*                                                           6.1.8        */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Ting Zhu, Microsoft Corporation                                     */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    This function moves up or down the vertical list by pages.          */
46
/*                                                                        */
47
/*  INPUT                                                                 */
48
/*                                                                        */
49
/*    list                                  Vertical list widget control  */
50
/*                                            block                       */
51
/*    num_pages                             The number of pages to scroll */
52
/*                                                                        */
53
/*  OUTPUT                                                                */
54
/*                                                                        */
55
/*    None                                                                */
56
/*                                                                        */
57
/*  CALLS                                                                 */
58
/*                                                                        */
59
/*    _gx_widget_first_client_child_get     Get first client child        */
60
/*    _gx_widget_next_client_child_get      Get next client child         */
61
/*                                                                        */
62
/*  CALLED BY                                                             */
63
/*                                                                        */
64
/*    _gx_vertical_list_scroll                                            */
65
/*                                                                        */
66
/**************************************************************************/
67
6
static VOID _gx_vertical_list_invisible_page_scroll(GX_VERTICAL_LIST *list, INT num_pages)
68
{
69
INT maximum_scroll_pages;
70
71
6
    if (!(list -> gx_widget_style & GX_STYLE_WRAP))
72
    {
73
74
        /* Wrap style is not applied, need to calculate scroll limit.  */
75
4
        if (num_pages < 0)
76
        {
77
78
            /* Calculate maximum up scroll num_pages.  */
79
2
            maximum_scroll_pages = (list -> gx_vertical_list_total_rows - list -> gx_vertical_list_top_index - list -> gx_vertical_list_child_count);
80
2
            maximum_scroll_pages /= list -> gx_vertical_list_child_count;
81
82
            /* Remain one page for normal scroll routine. */
83
2
            if (maximum_scroll_pages >= 1)
84
            {
85
1
                maximum_scroll_pages--;
86
            }
87
88
2
            if (maximum_scroll_pages < (-num_pages))
89
            {
90
1
                num_pages = (-maximum_scroll_pages);
91
            }
92
        }
93
        else
94
        {
95
96
            /* Calculate maximum down scroll num_pages.   */
97
2
            maximum_scroll_pages = list -> gx_vertical_list_top_index / list -> gx_vertical_list_child_count;
98
99
            /* Remain one page for normal scroll routine. */
100
2
            if (maximum_scroll_pages >= 1)
101
            {
102
1
                maximum_scroll_pages--;
103
            }
104
105
2
            if (maximum_scroll_pages < num_pages)
106
            {
107
1
                num_pages = maximum_scroll_pages;
108
            }
109
        }
110
    }
111
112
6
    if (num_pages)
113
    {
114
115
        /* Update top index according to scroll num_pages.  */
116
4
        list -> gx_vertical_list_top_index -= num_pages * list -> gx_vertical_list_child_count;
117
118
4
        if (list -> gx_widget_style & GX_STYLE_WRAP)
119
        {
120
121
            /* Wrap page index.  */
122
2
            if (num_pages < 0)
123
            {
124
97
                while (list -> gx_vertical_list_top_index >= list -> gx_vertical_list_total_rows)
125
                {
126
96
                    list -> gx_vertical_list_top_index -= list -> gx_vertical_list_total_rows;
127
                }
128
            }
129
            else
130
            {
131
98
                while (list -> gx_vertical_list_top_index < 0)
132
                {
133
97
                    list -> gx_vertical_list_top_index += list -> gx_vertical_list_total_rows;
134
                }
135
            }
136
        }
137
    }
138
6
}
139
140
/**************************************************************************/
141
/*                                                                        */
142
/*  FUNCTION                                               RELEASE        */
143
/*                                                                        */
144
/*    _gx_vertical_list_scroll                            PORTABLE C      */
145
/*                                                           6.1.8        */
146
/*  AUTHOR                                                                */
147
/*                                                                        */
148
/*    Kenneth Maxwell, Microsoft Corporation                              */
149
/*                                                                        */
150
/*  DESCRIPTION                                                           */
151
/*                                                                        */
152
/*    This function moves up or down the scrollbar.                       */
153
/*                                                                        */
154
/*  INPUT                                                                 */
155
/*                                                                        */
156
/*    vertical_list                         Vertical list widget control  */
157
/*                                            block                       */
158
/*    amount                                Shifting value                */
159
/*                                                                        */
160
/*  OUTPUT                                                                */
161
/*                                                                        */
162
/*    None                                                                */
163
/*                                                                        */
164
/*  CALLS                                                                 */
165
/*                                                                        */
166
/*    _gx_widget_scroll_shift               Shift a widget                */
167
/*    _gx_vertical_list_up_wrap             Scroll up the vertical list   */
168
/*    _gx_vertical_list_down_wrap           Scroll down the vertical list */
169
/*    _gx_widget_block_move                 Widget block move             */
170
/*                                                                        */
171
/*  CALLED BY                                                             */
172
/*                                                                        */
173
/*    _gx_vertical_list_event_process       Vertical list event process   */
174
/*                                                                        */
175
/**************************************************************************/
176
711
VOID _gx_vertical_list_scroll(GX_VERTICAL_LIST *list, INT amount)
177
{
178
GX_WIDGET    *child;
179
GX_WIDGET    *last_child;
180
GX_RECTANGLE  block;
181
GX_SCROLLBAR *scroll;
182
711
GX_BOOL       do_block_move = GX_TRUE;
183
711
GX_BOOL       reuse_child_widgets = GX_FALSE;
184
INT           page_size;
185
INT           num_pages;
186
187
711
    if (!amount)
188
    {
189
18
        return;
190
    }
191
192
695
    if ((list -> gx_vertical_list_callback != GX_NULL) &&
193
686
        (list -> gx_vertical_list_visible_rows < list -> gx_vertical_list_total_rows) &&
194

684
        ((list -> gx_vertical_list_child_count < list -> gx_vertical_list_total_rows) || (list -> gx_widget_style & GX_STYLE_WRAP)))
195
    {
196
680
        reuse_child_widgets = GX_TRUE;
197
198
        /* Calculate the page size.  */
199
680
        page_size = (list -> gx_vertical_list_child_height * list -> gx_vertical_list_child_count);
200
201
680
        if (!page_size)
202
        {
203
2
            return;
204
        }
205
206
        /* Calculate the number of pages to be scrolled.  */
207
678
        if (amount < 0)
208
        {
209
500
            num_pages = (amount + page_size) / page_size;
210
        }
211
        else
212
        {
213
178
            num_pages = (amount - page_size) / page_size;
214
        }
215
216
678
        if (num_pages)
217
        {
218
219
            /* Calculate the remainning scroll amount.  */
220
6
            amount -= (num_pages * page_size);
221
222
            /* Scroll pages.  */
223
6
            _gx_vertical_list_invisible_page_scroll(list, num_pages);
224
        }
225
    }
226
227
    /* first shift my child widgets */
228
693
    child = list -> gx_widget_first_child;
229
230
7281
    while (child)
231
    {
232
6588
        if (!(child -> gx_widget_status & GX_STATUS_NONCLIENT))
233
        {
234
6002
            _gx_widget_scroll_shift(child, 0, amount, GX_TRUE);
235
        }
236
6588
        child = child -> gx_widget_next;
237
    }
238
239
    /* next check to see if we need to wrap any child widgets */
240
241
693
    if (reuse_child_widgets)
242
    {
243
        /* this means we have fewer children than list rows, so we
244
           need to move and re-use the child widgets
245
         */
246
678
        if (amount < 0)
247
        {
248
500
            _gx_vertical_list_up_wrap(list);
249
        }
250
        else
251
        {
252
178
            _gx_vertical_list_down_wrap(list);
253
        }
254
    }
255
256
693
    _gx_window_scrollbar_find((GX_WINDOW *)list, GX_TYPE_VERTICAL_SCROLL, &scroll);
257
258
693
    if (scroll)
259
    {
260
586
        _gx_scrollbar_reset(scroll, GX_NULL);
261
    }
262
263
693
    if (list -> gx_widget_status & GX_STATUS_VISIBLE)
264
    {
265
687
        block = list -> gx_window_client;
266
267
687
        if (!(list -> gx_widget_style & (GX_STYLE_WRAP | GX_STYLE_TRANSPARENT)) &&
268
586
            (list -> gx_widget_style & GX_STYLE_BORDER_THIN))
269
        {
270
552
            child = _gx_widget_first_client_child_get((GX_WIDGET *)list);
271
552
            last_child = _gx_widget_last_client_child_get((GX_WIDGET *)list);
272
273
552
            if (child)
274
            {
275
551
                if ((child -> gx_widget_size.gx_rectangle_top > block.gx_rectangle_top ||
276
466
                     last_child -> gx_widget_size.gx_rectangle_bottom < block.gx_rectangle_bottom))
277
                {
278
                    /* If the widget has thin border, the round corder of the border
279
                       will cover the client area, block move will cause trouble. */
280
140
                    _gx_system_dirty_mark((GX_WIDGET *)list);
281
140
                    do_block_move = GX_FALSE;
282
                }
283
            }
284
        }
285
286
687
        if (do_block_move)
287
        {
288
547
            _gx_widget_block_move((GX_WIDGET *)list, &block, 0, amount);
289
        }
290
    }
291
}
292