GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_single_line_text_input_character_insert.c Lines: 57 57 100.0 %
Date: 2024-12-05 08:52:37 Branches: 13 13 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_context.h"
29
#include "gx_widget.h"
30
#include "gx_single_line_text_input.h"
31
32
33
/**************************************************************************/
34
/*                                                                        */
35
/*  FUNCTION                                               RELEASE        */
36
/*                                                                        */
37
/*    _gx_single_line_text_input_character_insert         PORTABLE C      */
38
/*                                                           6.1          */
39
/*  AUTHOR                                                                */
40
/*                                                                        */
41
/*    Kenneth Maxwell, Microsoft Corporation                              */
42
/*                                                                        */
43
/*  DESCRIPTION                                                           */
44
/*                                                                        */
45
/*    This services inserts a character into the text input string at the */
46
/*    current cursor position.                                            */
47
/*                                                                        */
48
/*  INPUT                                                                 */
49
/*                                                                        */
50
/*    text_input                            Single-line text input widget */
51
/*                                            control block               */
52
/*    insert_str                            Byte string of insert         */
53
/*                                            character                   */
54
/*    insert_size                           String size of insert         */
55
/*                                            character                   */
56
/*                                                                        */
57
/*  OUTPUT                                                                */
58
/*                                                                        */
59
/*    None                                                                */
60
/*                                                                        */
61
/*  CALLS                                                                 */
62
/*                                                                        */
63
/*    memmove                               Move a block of memory        */
64
/*    _gx_widget_font_get                   Get font by specified ID      */
65
/*    _gx_widget_border_width_get           Get the widget border width   */
66
/*    _gx_widget_client_get                 Get widget client rectangle   */
67
/*    _gx_system_string_width_get           Get the width of a string     */
68
/*    _gx_system_dirty_partial_add          Mark the partial area of a    */
69
/*                                            widget as dirty             */
70
/*    _gx_single_line_text_input_backspace  Remove text before the cursor */
71
/*    _gx_single_line_text_input_character_delete                         */
72
/*                                          Remove text after the cursor  */
73
/*                                                                        */
74
/*  CALLED BY                                                             */
75
/*                                                                        */
76
/*    Application Code                                                    */
77
/*    GUIX Internal Code                                                  */
78
/*                                                                        */
79
/*  RELEASE HISTORY                                                       */
80
/*                                                                        */
81
/*    DATE              NAME                      DESCRIPTION             */
82
/*                                                                        */
83
/*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
84
/*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
85
/*                                            resulting in version 6.1    */
86
/*                                                                        */
87
/**************************************************************************/
88
1973
UINT _gx_single_line_text_input_character_insert(GX_SINGLE_LINE_TEXT_INPUT *text_input, GX_UBYTE *insert_str, UINT insert_size)
89
{
90
GX_TEXT_INPUT_CURSOR *cursor_ptr;
91
UINT                  buffer_size;
92
GX_CHAR              *string_buffer;
93
UINT                  string_size;
94
GX_VALUE              new_cursor_pos;
95
UINT                  insert_pos;
96
GX_VALUE              border_width;
97
GX_VALUE              client_right;
98
GX_VALUE              client_width;
99
GX_VALUE              insert_width;
100
GX_VALUE              text_width;
101
GX_FONT              *gx_font;
102
GX_RECTANGLE          dirty_area;
103
GX_STRING             string;
104
105
    /* Delete hightlight text. */
106
1973
    if (text_input -> gx_single_line_text_input_start_mark != text_input -> gx_single_line_text_input_end_mark)
107
    {
108
4
        if (text_input -> gx_single_line_text_input_end_mark > text_input -> gx_single_line_text_input_start_mark)
109
        {
110
3
            _gx_single_line_text_input_backspace(text_input);
111
        }
112
        else
113
        {
114
1
            _gx_single_line_text_input_character_delete(text_input);
115
        }
116
    }
117
118
1973
    cursor_ptr = &text_input -> gx_single_line_text_input_cursor_instance;
119
120
1973
    buffer_size = text_input -> gx_single_line_text_input_buffer_size;
121
1973
    string_size = text_input -> gx_single_line_text_input_string_size;
122
123
    /* Judge whether there have remaining buffer size.  */
124
1973
    if (buffer_size < string_size + insert_size + 1)
125
    {
126
318
        return GX_FAILURE;
127
    }
128
129
1655
    string_buffer = text_input -> gx_single_line_text_input_buffer;
130
131
1655
    _gx_widget_font_get((GX_WIDGET *)text_input, text_input -> gx_prompt_font_id, &gx_font);
132
133
    /* Pick up text witth. */
134
1655
    string.gx_string_ptr = string_buffer;
135
1655
    string.gx_string_length = text_input -> gx_single_line_text_input_string_size;
136
1655
    _gx_system_string_width_get_ext(gx_font, &string, &text_width);
137
138
    /* Insert a char to the string buffer. */
139
1655
    insert_pos = text_input -> gx_single_line_text_input_insert_pos;
140
1655
    memmove(string_buffer + insert_pos + insert_size, string_buffer + insert_pos, string_size - insert_pos);
141
1655
    memmove(string_buffer + insert_pos, insert_str, insert_size);
142
1655
    string_buffer[string_size + insert_size] = '\0';
143
144
    /* Update the input string size and cursor position. */
145
1655
    text_input -> gx_single_line_text_input_string_size += insert_size;
146
1655
    text_input -> gx_single_line_text_input_insert_pos += insert_size;
147
148
    /* Calculate inside widget right. */
149
1655
    _gx_widget_border_width_get((GX_WIDGET *)text_input, &border_width);
150
1655
    _gx_widget_client_get((GX_WIDGET *)text_input, border_width, &dirty_area);
151
1655
    client_right = dirty_area.gx_rectangle_right;
152
153
    /* Get inset character width. */
154
1655
    string.gx_string_ptr = (GX_CONST GX_CHAR *)insert_str;
155
1655
    string.gx_string_length = insert_size;
156
1655
    _gx_system_string_width_get_ext(gx_font, &string, &insert_width);
157
158
1655
    switch (text_input -> gx_widget_style & GX_STYLE_TEXT_ALIGNMENT_MASK)
159
    {
160
375
    case GX_STYLE_TEXT_RIGHT:
161
375
        text_input -> gx_single_line_text_input_xoffset = (GX_VALUE)(text_input -> gx_single_line_text_input_xoffset + insert_width);
162
163
375
        dirty_area.gx_rectangle_right = cursor_ptr -> gx_text_input_cursor_pos.gx_point_x;
164
375
        break;
165
166
373
    case GX_STYLE_TEXT_CENTER:
167
        /* Calculate the cursor position. */
168
373
        client_width = (GX_VALUE)(dirty_area.gx_rectangle_right - dirty_area.gx_rectangle_left + 1);
169
373
        text_width = (GX_VALUE)(text_width + insert_width);
170
373
        new_cursor_pos = (GX_VALUE)(cursor_ptr -> gx_text_input_cursor_pos.gx_point_x -
171
373
                                    (((text_width + 1) >> 1) - text_input -> gx_single_line_text_input_xoffset) +
172
                                    insert_width);
173
        /* Update offset in x axis. */
174
373
        text_input -> gx_single_line_text_input_xoffset = (GX_VALUE)((text_width + 1) >> 1);
175
176
        /* Update offset in x axis. */
177
373
        if (new_cursor_pos < client_right - 1)
178
        {
179
186
            dirty_area.gx_rectangle_left = (GX_VALUE)(dirty_area.gx_rectangle_left + 1 + (client_width >> 1) - text_input -> gx_single_line_text_input_xoffset);
180
186
            dirty_area.gx_rectangle_right = (GX_VALUE)(dirty_area.gx_rectangle_left + text_width);
181
186
            dirty_area.gx_rectangle_left = (GX_VALUE)(dirty_area.gx_rectangle_left - (cursor_ptr -> gx_text_input_cursor_width >> 1));
182
186
            dirty_area.gx_rectangle_right = (GX_VALUE)(dirty_area.gx_rectangle_right + ((cursor_ptr -> gx_text_input_cursor_width + 1) >> 1) - 1);
183
        }
184
185
373
        cursor_ptr -> gx_text_input_cursor_pos.gx_point_x = new_cursor_pos;
186
373
        break;
187
188
907
    case GX_STYLE_TEXT_LEFT:
189
    default:
190
        /* Calculate cursor position. */
191
907
        new_cursor_pos = (GX_VALUE)(cursor_ptr -> gx_text_input_cursor_pos.gx_point_x + insert_width);
192
193
        /* Update offset in x axis. */
194
907
        if (new_cursor_pos > client_right - 1)
195
        {
196
354
            text_input -> gx_single_line_text_input_xoffset = (GX_VALUE)(text_input -> gx_single_line_text_input_xoffset + new_cursor_pos - client_right + 1);
197
198
354
            new_cursor_pos = (GX_VALUE)(client_right - 1);
199
        }
200
        else
201
        {
202
553
            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));
203
553
            dirty_area.gx_rectangle_right = (GX_VALUE)(new_cursor_pos + text_width + cursor_ptr -> gx_text_input_cursor_width - 1);
204
        }
205
206
        /* Update x coordinate of cursor position. */
207
907
        cursor_ptr -> gx_text_input_cursor_pos.gx_point_x = new_cursor_pos;
208
907
        break;
209
    }
210
211
    /* Mark the text input widget be changed. */
212
1655
    text_input -> gx_single_line_text_input_was_modified = GX_TRUE;
213
214
1655
    _gx_system_dirty_partial_add((GX_WIDGET *)text_input, &dirty_area);
215
216
1655
    return GX_SUCCESS;
217
}
218