GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_single_line_text_input_character_delete.c Lines: 72 72 100.0 %
Date: 2024-12-05 08:52:37 Branches: 25 25 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
/**   Text Input Management (Single Line Text Input)                      */
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_widget.h"
29
#include "gx_single_line_text_input.h"
30
#include "gx_utility.h"
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _gx_single_line_text_input_character_delete         PORTABLE C      */
37
/*                                                           6.1          */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Kenneth Maxwell, Microsoft Corporation                              */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    This service deletes the character after the text input cursor      */
45
/*    position.                                                           */
46
/*                                                                        */
47
/*  INPUT                                                                 */
48
/*                                                                        */
49
/*    text_input                             Single line text input       */
50
/*                                            control blcok               */
51
/*                                                                        */
52
/*  OUTPUT                                                                */
53
/*                                                                        */
54
/*    None                                                                */
55
/*                                                                        */
56
/*  CALLS                                                                 */
57
/*                                                                        */
58
/*    memmove                               Move a block of memory        */
59
/*    _gx_widget_border_width_get           Get widget border width       */
60
/*    _gx_widget_client_get                 Get widget client rectangle   */
61
/*    _gx_widget_font_get                   Get font by specified ID      */
62
/*    _gx_system_string_width_get           Get the width of a string     */
63
/*    _gx_system_dirty_partial_add          Mark the partial area of a    */
64
/*                                            widget as dirty             */
65
/*    _gx_utility_utf8_string_character_get Parse utf8 string to          */
66
/*                                            multi-byte glyph            */
67
/*    _gx_single_line_text_input_position_update                          */
68
/*                                          Update cursor position        */
69
/*                                            according to insert position*/
70
/*                                                                        */
71
/*  CALLED BY                                                             */
72
/*                                                                        */
73
/*    Application Code                                                    */
74
/*    GUIX Internal Code                                                  */
75
/*                                                                        */
76
/*  RELEASE HISTORY                                                       */
77
/*                                                                        */
78
/*    DATE              NAME                      DESCRIPTION             */
79
/*                                                                        */
80
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
81
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
82
/*                                            resulting in version 6.1    */
83
/*                                                                        */
84
/**************************************************************************/
85
586
UINT _gx_single_line_text_input_character_delete(GX_SINGLE_LINE_TEXT_INPUT *text_input)
86
{
87
586
GX_TEXT_INPUT_CURSOR *cursor_ptr = &text_input -> gx_single_line_text_input_cursor_instance;
88
UINT                  insert_pos;
89
GX_CHAR              *string_buffer;
90
UINT                  string_size;
91
GX_VALUE              border_width;
92
GX_VALUE              text_width;
93
GX_RECTANGLE          client;
94
GX_RECTANGLE          dirty_area;
95
GX_FONT              *gx_font;
96
GX_VALUE              x_pos;
97
GX_VALUE              offset;
98
GX_VALUE              del_char_width;
99
586
UINT                  glyph_len = 1;
100
101
GX_STRING             string;
102
103
586
    if (text_input -> gx_single_line_text_input_end_mark > text_input -> gx_single_line_text_input_start_mark)
104
    {
105
18
        return _gx_single_line_text_input_backspace(text_input);
106
    }
107
108
568
    insert_pos = text_input -> gx_single_line_text_input_insert_pos;
109
568
    string_buffer = text_input -> gx_single_line_text_input_buffer;
110
568
    string_size = text_input -> gx_single_line_text_input_string_size;
111
112
568
    if (insert_pos < string_size)
113
    {
114
542
        _gx_widget_border_width_get((GX_WIDGET *)text_input, &border_width);
115
542
        _gx_widget_client_get((GX_WIDGET *)text_input, border_width, &client);
116
117
542
        if (text_input -> gx_single_line_text_input_start_mark != text_input -> gx_single_line_text_input_end_mark)
118
        {
119
47
            glyph_len = text_input -> gx_single_line_text_input_start_mark - text_input -> gx_single_line_text_input_end_mark;
120
121
47
            if (cursor_ptr -> gx_text_input_cursor_pos.gx_point_x <= client.gx_rectangle_left ||
122
29
                cursor_ptr -> gx_text_input_cursor_pos.gx_point_x >= client.gx_rectangle_right)
123
            {
124
24
                _gx_single_line_text_input_left_arrow(text_input);
125
            }
126
47
            text_input -> gx_single_line_text_input_start_mark = 0;
127
47
            text_input -> gx_single_line_text_input_end_mark = 0;
128
        }
129
#ifdef GX_UTF8_SUPPORT
130
        else
131
        {
132
495
            string.gx_string_ptr = string_buffer + insert_pos;
133
495
            string.gx_string_length = string_size - insert_pos;
134
135
495
            _gx_utility_utf8_string_character_get(&string, GX_NULL, &glyph_len);
136
        }
137
#endif
138
542
        dirty_area = client;
139
140
542
        _gx_widget_font_get((GX_WIDGET *)text_input, text_input -> gx_prompt_font_id, &gx_font);
141
142
        /* Pick up text witth. */
143
542
        string.gx_string_ptr = string_buffer;
144
542
        string.gx_string_length = text_input -> gx_single_line_text_input_string_size;
145
146
542
        _gx_system_string_width_get_ext(gx_font, &string, &text_width);
147
148
542
        string.gx_string_ptr = string_buffer + insert_pos;
149
542
        string.gx_string_length = glyph_len;
150
151
542
        _gx_system_string_width_get_ext(gx_font, &string, &del_char_width);
152
153
542
        switch (text_input -> gx_widget_style & GX_STYLE_TEXT_ALIGNMENT_MASK)
154
        {
155
138
        case GX_STYLE_TEXT_RIGHT:
156
138
            x_pos = (GX_VALUE)(client.gx_rectangle_right - 1);
157
138
            x_pos = (GX_VALUE)(x_pos - text_input -> gx_single_line_text_input_xoffset);
158
159
138
            if (x_pos + text_width > client.gx_rectangle_right - 1)
160
            {
161
105
                offset = (GX_VALUE)((x_pos + text_width - del_char_width) - (client.gx_rectangle_right - 1));
162
163
105
                if (offset < 0)
164
                {
165
7
                    text_input -> gx_single_line_text_input_xoffset = (GX_VALUE)(text_input -> gx_single_line_text_input_xoffset + offset);
166
7
                    cursor_ptr -> gx_text_input_cursor_pos.gx_point_x = (GX_VALUE)(cursor_ptr -> gx_text_input_cursor_pos.gx_point_x - offset);
167
                }
168
            }
169
            else
170
            {
171
33
                text_input -> gx_single_line_text_input_xoffset = (GX_VALUE)(text_input -> gx_single_line_text_input_xoffset - del_char_width);
172
33
                cursor_ptr -> gx_text_input_cursor_pos.gx_point_x = (GX_VALUE)(cursor_ptr -> gx_text_input_cursor_pos.gx_point_x + del_char_width);
173
174
33
                dirty_area.gx_rectangle_right = cursor_ptr -> gx_text_input_cursor_pos.gx_point_x;
175
            }
176
138
            break;
177
178
135
        case GX_STYLE_TEXT_CENTER:
179
135
            x_pos = (GX_VALUE)(client.gx_rectangle_left + 1);
180
135
            x_pos = (GX_VALUE)(x_pos + ((client.gx_rectangle_right - client.gx_rectangle_left + 1) >> 1));
181
135
            x_pos = (GX_VALUE)(x_pos - text_input -> gx_single_line_text_input_xoffset);
182
135
            if (text_width <= (client.gx_rectangle_right - client.gx_rectangle_left + 1 - border_width))
183
            {
184
25
                dirty_area.gx_rectangle_left = (GX_VALUE)(x_pos - (cursor_ptr -> gx_text_input_cursor_width >> 1));
185
25
                dirty_area.gx_rectangle_right = (GX_VALUE)(x_pos + text_width + ((cursor_ptr -> gx_text_input_cursor_width + 1) >> 1) - 1);
186
            }
187
            /* Calculate the cursor position. */
188
135
            text_input -> gx_single_line_text_input_xoffset = (GX_VALUE)((text_width - del_char_width + 1) >> 1);
189
135
            cursor_ptr -> gx_text_input_cursor_pos.gx_point_x = (GX_VALUE)(cursor_ptr -> gx_text_input_cursor_pos.gx_point_x +
190
135
                                                                           (((text_width + 1) >> 1) - text_input -> gx_single_line_text_input_xoffset));
191
135
            break;
192
193
269
        case GX_STYLE_TEXT_LEFT:
194
        default:
195
269
            x_pos = (GX_VALUE)(client.gx_rectangle_left + 1);
196
269
            x_pos = (GX_VALUE)(x_pos - text_input -> gx_single_line_text_input_xoffset);
197
198
269
            if (x_pos < client.gx_rectangle_left + 1)
199
            {
200
34
                offset = (GX_VALUE)((client.gx_rectangle_right - 1) - (x_pos + text_width - del_char_width));
201
202
34
                if (offset > 0)
203
                {
204
18
                    if (offset > (client.gx_rectangle_left + 1 - x_pos))
205
                    {
206
6
                        offset = (GX_VALUE)(client.gx_rectangle_left + 1 - x_pos);
207
                    }
208
209
18
                    text_input -> gx_single_line_text_input_xoffset = (GX_VALUE)(text_input -> gx_single_line_text_input_xoffset - offset);
210
18
                    cursor_ptr -> gx_text_input_cursor_pos.gx_point_x = (GX_VALUE)(cursor_ptr -> gx_text_input_cursor_pos.gx_point_x + offset);
211
                }
212
            }
213
            else
214
            {
215
235
                dirty_area.gx_rectangle_left = (GX_VALUE)(cursor_ptr -> gx_text_input_cursor_pos.gx_point_x - (cursor_ptr -> gx_text_input_cursor_width >> 1));
216
235
                dirty_area.gx_rectangle_right = (GX_VALUE)(x_pos + text_width + cursor_ptr -> gx_text_input_cursor_width - 1);
217
            }
218
269
            break;
219
        }
220
221
222
        /* Delete a character from the string buffer. */
223
542
        memmove(string_buffer + insert_pos, string_buffer + insert_pos + glyph_len, string_size - insert_pos - glyph_len);
224
225
542
        string_buffer[string_size - glyph_len] = '\0';
226
542
        text_input -> gx_single_line_text_input_string_size -= glyph_len;
227
228
        /* Mark text input be changed.  */
229
542
        text_input -> gx_single_line_text_input_was_modified = GX_TRUE;
230
231
542
        _gx_system_dirty_partial_add((GX_WIDGET *)text_input, &dirty_area);
232
    }
233
234
568
    return GX_SUCCESS;
235
}
236