This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/blenlib/intern/string_cursor_utf8.c

199 lines
5.0 KiB
C

/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2011 Blender Foundation.
* All rights reserved.
*
* Contributor(s): Campbell Barton.
*
* ***** END GPL LICENSE BLOCK *****
*
*/
/** \file blender/blenlib/intern/string_cursor_utf8.c
* \ingroup bli
*/
#include <stdio.h>
#include <stdlib.h>
#include "BLI_utildefines.h"
#include "BLI_string_utf8.h"
#include "BLI_string_cursor_utf8.h" /* own include */
typedef enum strCursorDelimType {
STRCUR_DELIM_NONE,
STRCUR_DELIM_ALPHA,
STRCUR_DELIM_PUNCT,
STRCUR_DELIM_BRACE,
STRCUR_DELIM_OPERATOR,
STRCUR_DELIM_QUOTE,
STRCUR_DELIM_WHITESPACE,
STRCUR_DELIM_OTHER
} strCursorDelimType;
/* return 1 if char ch is special character, otherwise return 0 */
static strCursorDelimType test_special_char(const char *ch_utf8)
{
/* for full unicode support we really need to have large lookup tables to figure
* out whats what in every possible char set - and python, glib both have these. */
unsigned int uch = BLI_str_utf8_as_unicode(ch_utf8);
if ((uch >= 'a' && uch <= 'z') ||
(uch >= 'A' && uch <= 'Z') ||
(uch == '_') /* not quite correct but allow for python, could become configurable */
)
{
return STRCUR_DELIM_ALPHA;
}
switch (uch) {
case ',':
case '.':
return STRCUR_DELIM_PUNCT;
case '{':
case '}':
case '[':
case ']':
case '(':
case ')':
return STRCUR_DELIM_BRACE;
case '+':
case '-':
case '=':
case '~':
case '%':
case '/':
case '<':
case '>':
case '^':
case '*':
case '&':
return STRCUR_DELIM_OPERATOR;
case '\'':
case '\"': // " - an extra closing one for Aligorith's text editor
return STRCUR_DELIM_QUOTE;
case ' ':
case '\t':
return STRCUR_DELIM_WHITESPACE;
case '\\':
case '!':
case '@':
case '#':
case '$':
case ':':
case ';':
case '?':
/* case '_': *//* special case, for python */
return STRCUR_DELIM_OTHER;
default:
break;
}
return STRCUR_DELIM_NONE;
}
int BLI_str_cursor_step_next_utf8(const char *str, size_t maxlen, int *pos)
{
const char *str_end = str + (maxlen + 1);
const char *str_pos = str + (*pos);
const char *str_next = BLI_str_find_next_char_utf8(str_pos, str_end);
if (str_next) {
(*pos) += (str_next - str_pos);
if ((*pos) > maxlen) {
(*pos) = maxlen;
}
return TRUE;
}
return FALSE;
}
int BLI_str_cursor_step_prev_utf8(const char *str, size_t UNUSED(maxlen), int *pos)
{
if ((*pos) > 0) {
const char *str_pos = str + (*pos);
const char *str_prev = BLI_str_find_prev_char_utf8(str, str_pos);
if (str_prev) {
(*pos) -= (str_pos - str_prev);
return TRUE;
}
}
return FALSE;
}
void BLI_str_cursor_step_utf8(const char *str, size_t maxlen,
int *pos, strCursorJumpDirection direction,
strCursorJumpType jump)
{
const int pos_prev = *pos;
if (direction == STRCUR_DIR_NEXT) {
BLI_str_cursor_step_next_utf8(str, maxlen, pos);
if (jump != STRCUR_JUMP_NONE) {
const strCursorDelimType is_special = (*pos) < maxlen ? test_special_char(&str[*pos]) : STRCUR_DELIM_NONE;
/* jump between special characters (/,\,_,-, etc.),
* look at function test_special_char() for complete
* list of special character, ctr -> */
while ((*pos) < maxlen) {
if (BLI_str_cursor_step_next_utf8(str, maxlen, pos)) {
if ((jump != STRCUR_JUMP_ALL) && (is_special != test_special_char(&str[*pos])))
break;
}
else {
break; /* unlikely but just in case */
}
}
}
}
else if (direction == STRCUR_DIR_PREV) {
BLI_str_cursor_step_prev_utf8(str, maxlen, pos);
if (jump != STRCUR_JUMP_NONE) {
const strCursorDelimType is_special = (*pos) > 1 ? test_special_char(&str[(*pos) - 1]) : STRCUR_DELIM_NONE;
/* jump between special characters (/,\,_,-, etc.),
* look at function test_special_char() for complete
* list of special character, ctr -> */
while ((*pos) > 0) {
if (BLI_str_cursor_step_prev_utf8(str, maxlen, pos)) {
if ((jump != STRCUR_JUMP_ALL) && (is_special != test_special_char(&str[*pos])))
break;
}
else {
break;
}
}
/* left only: compensate for index/change in direction */
if (((*pos) != 0) && ABS(pos_prev - (*pos)) >= 1) {
BLI_str_cursor_step_next_utf8(str, maxlen, pos);
}
}
}
else {
BLI_assert(0);
}
}