void menupage_display(menu_t *menu) { int i; char buffer[LP_MAX_WORD]; menupage_t *page = menu->current_page; int pad1, pad2, len = strlen_utf8(page->name); if (page->sibilings) { pad1 = ( MENU_WIDTH - 2 - len) / 2; pad2 = (1 + MENU_WIDTH - 4 - len) / 2; sprintf(buffer, "<<%*s%s%*s>>", pad1, "", page->name, pad2, ""); } else { pad1 = ( MENU_WIDTH - 0 - len) / 2; pad2 = (1 + MENU_WIDTH - 2 - len) / 2; sprintf(buffer, "%*s%s%*s", pad1, "", page->name, pad2, ""); } menu_set_text(7, buffer); for(i = 0; i < MENU_HEIGHT; i++) menupage_display_line(page, i); menu_highlight(page->current_line); }
void gui_entry_insert_text(GUI_ENTRY_REC *entry, const char *str) { unichar chr; int i, len; g_return_if_fail(entry != NULL); g_return_if_fail(str != NULL); gui_entry_redraw_from(entry, entry->pos); len = !entry->utf8 ? strlen(str) : strlen_utf8(str); entry_text_grow(entry, len); /* make space for the string */ g_memmove(entry->text + entry->pos + len, entry->text + entry->pos, (entry->text_len-entry->pos + 1) * sizeof(unichar)); if (!entry->utf8) { for (i = 0; i < len; i++) entry->text[entry->pos+i] = str[i]; } else { chr = entry->text[entry->pos+len]; utf8_to_utf16(str, entry->text+entry->pos); entry->text[entry->pos+len] = chr; } entry->text_len += len; entry->pos += len; gui_entry_fix_cursor(entry); gui_entry_draw(entry); }
size_t gp_strlen(const char *s) { if (encoding == S_ENC_UTF8) return strlen_utf8(s); else return strlen(s); }
static Term readFromBuffer(const char *s, Term opts) { Term rval; int sno; encoding_t enc = ENC_ISO_UTF8; sno = Yap_open_buf_read_stream( (char *)s, strlen_utf8((unsigned char *)s), &enc, MEM_BUF_USER, Yap_LookupAtom(Yap_StrPrefix((char *)s, 16)), TermNone); rval = Yap_read_term(sno, opts, 3); Yap_CloseStream(sno); return rval; }
static void test_random_edits() { // This string should always have the same content as the rope. _string *str = str_create(); rope *r = rope_new(); const size_t max_stringsize = 1000; uint8_t strbuffer[max_stringsize + 1]; for (int i = 0; i < 1000; i++) { // First, some sanity checks. check(r, (char *)str->mem); rope *r2 = rope_copy(r); check(r2, (char *)str->mem); rope_free(r2); // printf("String contains '%s'\n", str->mem); test(rope_byte_count(r) == str->len); size_t len = strlen_utf8(str->mem); test(rope_char_count(r) == len); test(str_num_chars(str) == len); if (len == 0 || rand_float() < 0.5f) { // Insert. //uint8_t *text = random_ascii_string(11); random_unicode_string(strbuffer, 1 + random() % max_stringsize); size_t pos = random() % (len + 1); // printf("inserting %s at %zd\n", strbuffer, pos); rope_insert(r, pos, strbuffer); str_insert(str, pos, strbuffer); } else { // Delete size_t pos = random() % len; size_t dellen = random() % 10; dellen = MIN(len - pos, dellen); // printf("deleting %zd chars at %zd\n", dellen, pos); //deletedText = str[pos...pos + length] //test.strictEqual deletedText, r.substring pos, length rope_del(r, pos, dellen); str_del(str, pos, dellen); } } rope_free(r); str_destroy(str); }
static void string_reverse_implementation(sqlite3_context* ctx, int argc, sqlite3_value** argv) { const unsigned char* input = 0; int input_type; sqlite_uint64 input_length; char* result; int* decoded; if (argc < 1) { sqlite3_result_error(ctx, "not enough parameters", -1); return; } if (argc > 1) { sqlite3_result_error(ctx, "too many parameters", -1); return; } input_type = sqlite3_value_type(argv[0]); if (input_type != SQLITE_NULL) { input = sqlite3_value_text(argv[0]); } if (input == 0) { sqlite3_result_null(ctx); return; } input_length = strlen_utf8(input); result = sqlite3_malloc(4 * input_length + 1); decoded = sqlite3_malloc(sizeof(int) * input_length); decode_utf8(input, decoded); reverse_string(decoded, result, input_length); sqlite3_free(decoded); sqlite3_result_text(ctx, result, -1, result_string_destructor); }
// Insert the given utf8 string into the rope at the specified position. static ROPE_RESULT rope_insert_at_iter(rope *r, rope_node *e, rope_iter *iter, const uint8_t *str) { // iter.offset contains how far (in characters) into the current element to skip. // Figure out how much that is in bytes. size_t offset_bytes = 0; // The insertion offset into the destination node. size_t offset = iter->s[0].skip_size; if (offset) { assert(offset <= e->nexts[0].skip_size); offset_bytes = count_bytes_in_utf8(e->str, offset); } // We might be able to insert the new data into the current node, depending on // how big it is. We'll count the bytes, and also check that its valid utf8. ssize_t num_inserted_bytes = bytelen_and_check_utf8(str); if (num_inserted_bytes == -1) return ROPE_INVALID_UTF8; // Can we insert into the current node? bool insert_here = e->num_bytes + num_inserted_bytes <= ROPE_NODE_STR_SIZE; // Can we insert into the subsequent node? rope_node *next = NULL; if (!insert_here && offset_bytes == e->num_bytes) { next = e->nexts[0].node; // We can insert into the subsequent node if: // - We can't insert into the current node // - There _is_ a next node to insert into // - The insert would be at the start of the next node // - There's room in the next node if (next && next->num_bytes + num_inserted_bytes <= ROPE_NODE_STR_SIZE) { offset = offset_bytes = 0; for (int i = 0; i < next->height; i++) { iter->s[i].node = next; // tree offset nodes will not be used. } e = next; insert_here = true; } } if (insert_here) { // First move the current bytes later on in the string. if (offset_bytes < e->num_bytes) { memmove(&e->str[offset_bytes + num_inserted_bytes], &e->str[offset_bytes], e->num_bytes - offset_bytes); } // Then copy in the string bytes memcpy(&e->str[offset_bytes], str, num_inserted_bytes); e->num_bytes += num_inserted_bytes; r->num_bytes += num_inserted_bytes; size_t num_inserted_chars = strlen_utf8(str); r->num_chars += num_inserted_chars; // .... aaaand update all the offset amounts. #if ROPE_WCHAR size_t num_inserted_wchars = count_wchars_in_utf8(str, num_inserted_chars); update_offset_list(r, iter, num_inserted_chars, num_inserted_wchars); #else update_offset_list(r, iter, num_inserted_chars); #endif } else { // There isn't room. We'll need to add at least one new node to the rope. // If we're not at the end of the current node, we'll need to remove // the end of the current node's data and reinsert it later. size_t num_end_chars, num_end_bytes = e->num_bytes - offset_bytes; if (num_end_bytes) { // We'll pretend like the character have been deleted from the node, while leaving // the bytes themselves there (for later). e->num_bytes = offset_bytes; num_end_chars = e->nexts[0].skip_size - offset; #if ROPE_WCHAR size_t num_end_wchars = count_wchars_in_utf8(&e->str[offset_bytes], num_end_chars); update_offset_list(r, iter, -num_end_chars, -num_end_wchars); #else update_offset_list(r, iter, -num_end_chars); #endif r->num_chars -= num_end_chars; r->num_bytes -= num_end_bytes; } // Now we insert new nodes containing the new character data. The data must be broken into // pieces of with a maximum size of ROPE_NODE_STR_SIZE. Node boundaries must not occur in the // middle of a utf8 codepoint. size_t str_offset = 0; while (str_offset < num_inserted_bytes) { size_t new_node_bytes = 0; size_t new_node_chars = 0; while (str_offset + new_node_bytes < num_inserted_bytes) { size_t cs = codepoint_size(str[str_offset + new_node_bytes]); if (cs + new_node_bytes > ROPE_NODE_STR_SIZE) { break; } else { new_node_bytes += cs; new_node_chars++; } } insert_at(r, iter, &str[str_offset], new_node_bytes, new_node_chars); str_offset += new_node_bytes; } if (num_end_bytes) { insert_at(r, iter, &e->str[offset_bytes], num_end_bytes, num_end_chars); } } return ROPE_OK; }
// Insert the given utf8 string into the rope at the specified position. void rope_insert(rope *r, size_t pos, const uint8_t *str) { assert(r); assert(str); #ifdef DEBUG _rope_check(r); #endif pos = MIN(pos, r->num_chars); // There's a good chance we'll have to rewrite a bunch of next pointers and a bunch // of offsets. This variable will store pointers to the elements which need to // be changed. rope_node *nodes[UINT8_MAX]; size_t tree_offsets[UINT8_MAX]; // This is the number of characters to skip in the current node. size_t offset; // First we need to search for the node where we'll insert the string. rope_node *e = go_to_node(r, pos, &offset, nodes, tree_offsets); // offset contains how far (in characters) into the current element to skip. // Figure out how much that is in bytes. size_t offset_bytes = 0; if (e && offset) { assert(offset <= e->num_bytes); offset_bytes = count_bytes_in_chars(e->str, offset); } // Maybe we can insert the characters into the current node? size_t num_inserted_bytes = strlen((char *)str); // Can we insert into the current node? bool insert_here = e && e->num_bytes + num_inserted_bytes <= ROPE_NODE_STR_SIZE; // Can we insert into the subsequent node? bool insert_next = false; rope_node *next = NULL; if (!insert_here) { next = e ? e->nexts[0].node : (r->num_chars ? r->heads[0].node : NULL); // We can insert into the subsequent node if: // - We can't insert into the current node // - There _is_ a next node to insert into // - The insert would be at the start of the next node // - There's room in the next node insert_next = next && (e == NULL || offset_bytes == e->num_bytes) && next->num_bytes + num_inserted_bytes <= ROPE_NODE_STR_SIZE; } if (insert_here || insert_next) { if (insert_next) { offset = offset_bytes = 0; for (int i = 0; i < next->height; i++) { nodes[i] = next; // tree offset nodes not used. } e = next; } // First move the current bytes later on in the string. if (offset_bytes < e->num_bytes) { memmove(&e->str[offset_bytes + num_inserted_bytes], &e->str[offset_bytes], e->num_bytes - offset_bytes); } // Then copy in the string bytes memcpy(&e->str[offset_bytes], str, num_inserted_bytes); e->num_bytes += num_inserted_bytes; r->num_bytes += num_inserted_bytes; size_t num_inserted_chars = strlen_utf8(str); r->num_chars += num_inserted_chars; // .... aaaand update all the offset amounts. update_offset_list(r, nodes, num_inserted_chars); } else { // There isn't room. We'll need to add at least one new node to the rope. // If we're not at the end of the current node, we'll need to remove // the end of the current node's data and reinsert it later. size_t num_end_bytes = 0, num_end_chars; if (e) { num_end_bytes = e->num_bytes - offset_bytes; e->num_bytes = offset_bytes; if (num_end_bytes) { // Count out characters. num_end_chars = e->nexts[0].skip_size - offset; update_offset_list(r, nodes, -num_end_chars); r->num_chars -= num_end_chars; r->num_bytes -= num_end_bytes; } } // Now, we insert new node[s] containing the data. The data must // be broken into pieces of with a maximum size of ROPE_NODE_STR_SIZE. // Node boundaries do not occur in the middle of a utf8 codepoint. size_t str_offset = 0; while (str_offset < num_inserted_bytes) { size_t new_node_bytes = 0; size_t new_node_chars = 0; while (str_offset + new_node_bytes < num_inserted_bytes) { size_t cs = codepoint_size(str[str_offset + new_node_bytes]); if (cs + new_node_bytes > ROPE_NODE_STR_SIZE) { break; } else { new_node_bytes += cs; new_node_chars++; } } insert_at(r, pos, &str[str_offset], new_node_bytes, new_node_chars, nodes, tree_offsets); pos += new_node_chars; str_offset += new_node_bytes; } if (num_end_bytes) { insert_at(r, pos, &e->str[offset_bytes], num_end_bytes, num_end_chars, nodes, tree_offsets); } } #ifdef DEBUG _rope_check(r); #endif }
static int strio_size(Value *vret, Value *v, RefNode *node) { RefBytesIO *mb = Value_bytesio(*v); *vret = int32_Value(strlen_utf8(mb->buf.p, mb->buf.size)); return TRUE; }