style cleanup: comment blocks
[blender.git] / source / blender / blenlib / intern / string_cursor_utf8.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2011 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Campbell Barton.
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  *
25  */
26
27 /** \file blender/blenlib/intern/string_cursor_utf8.c
28  *  \ingroup bli
29  */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33
34 #include "BLI_utildefines.h"
35 #include "BLI_string_utf8.h"
36
37 #include "BLI_string_cursor_utf8.h" /* own include */
38
39 typedef enum strCursorDelimType {
40         STRCUR_DELIM_NONE,
41         STRCUR_DELIM_ALPHA,
42         STRCUR_DELIM_PUNCT,
43         STRCUR_DELIM_BRACE,
44         STRCUR_DELIM_OPERATOR,
45         STRCUR_DELIM_QUOTE,
46         STRCUR_DELIM_WHITESPACE,
47         STRCUR_DELIM_OTHER
48 } strCursorDelimType;
49
50 /* return 1 if char ch is special character, otherwise return 0 */
51 static strCursorDelimType test_special_char(const char ch)
52 {
53         /* TODO - use BLI_str_utf8_as_unicode rather then assuming ascii */
54
55         if ((ch >= 'a' && ch <= 'z') ||
56             (ch >= 'A' && ch <= 'Z') ||
57             (ch == '_') /* not quite correct but allow for python, could become configurable */
58             )
59         {
60                 return STRCUR_DELIM_ALPHA;
61         }
62
63         switch (ch) {
64                 case ',':
65                 case '.':
66                         return STRCUR_DELIM_PUNCT;
67
68                 case '{':
69                 case '}':
70                 case '[':
71                 case ']':
72                 case '(':
73                 case ')':
74                         return STRCUR_DELIM_BRACE;
75
76                 case '+':
77                 case '-':
78                 case '=':
79                 case '~':
80                 case '%':
81                 case '/':
82                 case '<':
83                 case '>':
84                 case '^':
85                 case '*':
86                 case '&':
87                         return STRCUR_DELIM_OPERATOR;
88
89                 case '\'':
90                 case '\"': // " - an extra closing one for Aligorith's text editor
91                         return STRCUR_DELIM_QUOTE;
92
93                 case ' ':
94                         return STRCUR_DELIM_WHITESPACE;
95
96                 case '\\':
97                 case '!':
98                 case '@':
99                 case '#':
100                 case '$':
101                 case ':':
102                 case ';':
103                 case '?':
104                 /* case '_': */ /* special case, for python */
105                         return STRCUR_DELIM_OTHER;
106
107                 default:
108                         break;
109         }
110         return STRCUR_DELIM_NONE;
111 }
112
113 int BLI_str_cursor_step_next_utf8(const char *str, size_t maxlen, int *pos)
114 {
115         const char *str_end= str + (maxlen + 1);
116         const char *str_pos= str + (*pos);
117         const char *str_next= BLI_str_find_next_char_utf8(str_pos, str_end);
118         if (str_next) {
119                 (*pos) += (str_next - str_pos);
120                 if((*pos) > maxlen) (*pos)= maxlen;
121                 return TRUE;
122         }
123
124         return FALSE;
125 }
126
127 int BLI_str_cursor_step_prev_utf8(const char *str, size_t UNUSED(maxlen), int *pos)
128 {
129         if((*pos) > 0) {
130                 const char *str_pos= str + (*pos);
131                 const char *str_prev= BLI_str_find_prev_char_utf8(str, str_pos);
132                 if (str_prev) {
133                         (*pos) -= (str_pos - str_prev);
134                         return TRUE;
135                 }
136         }
137
138         return FALSE;
139 }
140
141 void BLI_str_cursor_step_utf8(const char *str, size_t maxlen,
142                               int *pos, strCursorJumpDirection direction,
143                               strCursorJumpType jump)
144 {
145         const short pos_prev= *pos;
146
147         if (direction == STRCUR_DIR_NEXT) {
148                 BLI_str_cursor_step_next_utf8(str, maxlen, pos);
149
150                 if (jump != STRCUR_JUMP_NONE) {
151                         const strCursorDelimType is_special= (*pos) < maxlen ? test_special_char(str[(*pos)]) : STRCUR_DELIM_NONE;
152                         /* jump between special characters (/,\,_,-, etc.),
153                          * look at function test_special_char() for complete
154                          * list of special character, ctr -> */
155                         while ((*pos) < maxlen) {
156                                 if (BLI_str_cursor_step_next_utf8(str, maxlen, pos)) {
157                                         if ((jump != STRCUR_JUMP_ALL) && (is_special != test_special_char(str[(*pos)]))) break;
158                                 }
159                                 else {
160                                         break; /* unlikely but just in case */
161                                 }
162                         }
163                 }
164         }
165         else if (direction == STRCUR_DIR_PREV) {
166                 BLI_str_cursor_step_prev_utf8(str, maxlen, pos);
167
168                 if(jump != STRCUR_JUMP_NONE) {
169                         const strCursorDelimType is_special= (*pos) > 1 ? test_special_char(str[(*pos) - 1]) : STRCUR_DELIM_NONE;
170                         /* jump between special characters (/,\,_,-, etc.),
171                          * look at function test_special_char() for complete
172                          * list of special character, ctr -> */
173                         while ((*pos) > 0) {
174                                 if (BLI_str_cursor_step_prev_utf8(str, maxlen, pos)) {
175                                         if ((jump != STRCUR_JUMP_ALL) && (is_special != test_special_char(str[(*pos)]))) break;
176                                 }
177                                 else {
178                                         break;
179                                 }
180                         }
181
182                         /* left only: compensate for index/change in direction */
183                         if (((*pos) != 0) && ABS(pos_prev - (*pos)) >= 1) {
184                                 BLI_str_cursor_step_next_utf8(str, maxlen, pos);
185                         }
186                 }
187         }
188         else {
189                 BLI_assert(0);
190         }
191 }