2 #include "nuklear_internal.h" 
   13    int first_char, length; 
 
   20    float baseline_y_delta;
 
   28 NK_INTERN 
void nk_textedit_makeundo_delete(
struct nk_text_edit*, 
int, 
int);
 
   29 NK_INTERN 
void nk_textedit_makeundo_insert(
struct nk_text_edit*, 
int, 
int);
 
   30 NK_INTERN 
void nk_textedit_makeundo_replace(
struct nk_text_edit*, 
int, 
int, 
int);
 
   31 #define NK_TEXT_HAS_SELECTION(s)   ((s)->select_start != (s)->select_end) 
   34 nk_textedit_get_width(
const struct nk_text_edit *edit, 
int line_start, 
int char_id,
 
   39     const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len);
 
   40     return font->
width(font->userdata, font->
height, str, len);
 
   44     int line_start_id, 
float row_height, 
const struct nk_user_font *font)
 
   49     const char *remaining;
 
   50     int len = nk_str_len_char(&edit->string);
 
   51     const char *end = nk_str_get_const(&edit->string) + len;
 
   52     const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l);
 
   53     const struct nk_vec2 size = nk_text_calculate_text_bounds(font,
 
   54         text, (
int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE);
 
   58     r->baseline_y_delta = size.y;
 
   61     r->num_chars = glyphs;
 
   64 nk_textedit_locate_coord(
struct nk_text_edit *edit, 
float x, 
float y,
 
   68     int n = edit->string.len;
 
   69     float base_y = 0, prev_x;
 
   78         nk_textedit_layout_row(&r, edit, i, row_height, font);
 
   82         if (i==0 && y < base_y + r.ymin)
 
   85         if (y < base_y + r.ymax)
 
   89         base_y += r.baseline_y_delta;
 
  105         for (i=0; i < r.num_chars; ++i) {
 
  106             float w = nk_textedit_get_width(edit, k, i, font);
 
  119     if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == 
'\n')
 
  120         return i+r.num_chars-1;
 
  121     else return i+r.num_chars;
 
  124 nk_textedit_click(
struct nk_text_edit *state, 
float x, 
float y,
 
  129     state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height);
 
  130     state->select_start = state->cursor;
 
  131     state->select_end = state->cursor;
 
  132     state->has_preferred_x = 0;
 
  135 nk_textedit_drag(
struct nk_text_edit *state, 
float x, 
float y,
 
  140     int p = nk_textedit_locate_coord(state, x, y, font, row_height);
 
  141     if (state->select_start == state->select_end)
 
  142         state->select_start = state->cursor;
 
  143     state->cursor = state->select_end = p;
 
  147     int n, 
int single_line, 
const struct nk_user_font *font, 
float row_height)
 
  153     int z = state->string.len;
 
  160         nk_textedit_layout_row(&r, state, 0, row_height, font);
 
  162             find->first_char = 0;
 
  168                 nk_textedit_layout_row(&r, state, i, row_height, font);
 
  171             find->first_char = i;
 
  172             find->length = r.num_chars;
 
  176         find->height = r.ymax - r.ymin;
 
  177         find->prev_first = prev_start;
 
  185         nk_textedit_layout_row(&r, state, i, row_height, font);
 
  186         if (n < i + r.num_chars) 
break;
 
  189         find->y += r.baseline_y_delta;
 
  192     find->first_char = first = i;
 
  193     find->length = r.num_chars;
 
  194     find->height = r.ymax - r.ymin;
 
  195     find->prev_first = prev_start;
 
  199     for (i=0; first+i < n; ++i)
 
  200         find->x += nk_textedit_get_width(state, first, i, font);
 
  206     int n = state->string.len;
 
  207     if (NK_TEXT_HAS_SELECTION(state)) {
 
  208         if (state->select_start > n) state->select_start = n;
 
  209         if (state->select_end   > n) state->select_end = n;
 
  211         if (state->select_start == state->select_end)
 
  212             state->cursor = state->select_start;
 
  214     if (state->cursor > n) state->cursor = n;
 
  217 nk_textedit_delete(
struct nk_text_edit *state, 
int where, 
int len)
 
  220     nk_textedit_makeundo_delete(state, where, len);
 
  221     nk_str_delete_runes(&state->string, where, len);
 
  222     state->has_preferred_x = 0;
 
  225 nk_textedit_delete_selection(
struct nk_text_edit *state)
 
  228     nk_textedit_clamp(state);
 
  229     if (NK_TEXT_HAS_SELECTION(state)) {
 
  230         if (state->select_start < state->select_end) {
 
  231             nk_textedit_delete(state, state->select_start,
 
  232                 state->select_end - state->select_start);
 
  233             state->select_end = state->cursor = state->select_start;
 
  235             nk_textedit_delete(state, state->select_end,
 
  236                 state->select_start - state->select_end);
 
  237             state->select_start = state->cursor = state->select_end;
 
  239         state->has_preferred_x = 0;
 
  246     if (state->select_end < state->select_start) {
 
  247         int temp = state->select_end;
 
  248         state->select_end = state->select_start;
 
  249         state->select_start = temp;
 
  256     if (NK_TEXT_HAS_SELECTION(state)) {
 
  257         nk_textedit_sortselection(state);
 
  258         state->cursor = state->select_start;
 
  259         state->select_end = state->select_start;
 
  260         state->has_preferred_x = 0;
 
  267     if (NK_TEXT_HAS_SELECTION(state)) {
 
  268         nk_textedit_sortselection(state);
 
  269         nk_textedit_clamp(state);
 
  270         state->cursor = state->select_end;
 
  271         state->select_start = state->select_end;
 
  272         state->has_preferred_x = 0;
 
  276 nk_is_word_boundary( 
struct nk_text_edit *state, 
int idx)
 
  280     if (idx <= 0) 
return 1;
 
  281     if (!nk_str_at_rune(&state->string, idx, &c, &len)) 
return 1;
 
  282     return (c == 
' ' || c == 
'\t' ||c == 0x3000 || c == 
',' || c == 
';' ||
 
  283             c == 
'(' || c == 
')' || c == 
'{' || c == 
'}' || c == 
'[' || c == 
']' ||
 
  287 nk_textedit_move_to_word_previous(
struct nk_text_edit *state)
 
  289    int c = state->cursor - 1;
 
  290    while( c >= 0 && !nk_is_word_boundary(state, c))
 
  299 nk_textedit_move_to_word_next(
struct nk_text_edit *state)
 
  301    const int len = state->string.len;
 
  302    int c = state->cursor+1;
 
  303    while( c < len && !nk_is_word_boundary(state, c))
 
  312 nk_textedit_prep_selection_at_cursor(
struct nk_text_edit *state)
 
  315     if (!NK_TEXT_HAS_SELECTION(state))
 
  316         state->select_start = state->select_end = state->cursor;
 
  317     else state->cursor = state->select_end;
 
  323     if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
 
  325     if (NK_TEXT_HAS_SELECTION(state)) {
 
  326         nk_textedit_delete_selection(state); 
 
  327         state->has_preferred_x = 0;
 
  333 nk_textedit_paste(
struct nk_text_edit *state, 
char const *ctext, 
int len)
 
  337     const char *text = (
const char *) ctext;
 
  338     if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 
return 0;
 
  341     nk_textedit_clamp(state);
 
  342     nk_textedit_delete_selection(state);
 
  345     glyphs = nk_utf_len(ctext, len);
 
  346     if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) {
 
  347         nk_textedit_makeundo_insert(state, state->cursor, glyphs);
 
  348         state->cursor += len;
 
  349         state->has_preferred_x = 0;
 
  353     if (state->undo.undo_point)
 
  354         --state->undo.undo_point;
 
  358 nk_textedit_text(
struct nk_text_edit *state, 
const char *text, 
int total_len)
 
  366     if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) 
return;
 
  368     glyph_len = nk_utf_decode(text, &unicode, total_len);
 
  369     while ((text_len < total_len) && glyph_len)
 
  372         if (unicode == 127) 
goto next;
 
  374         if (unicode == 
'\n' && state->single_line) 
goto next;
 
  376         if (state->filter && !state->filter(state, unicode)) 
goto next;
 
  378         if (!NK_TEXT_HAS_SELECTION(state) &&
 
  379             state->cursor < state->string.len)
 
  381             if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) {
 
  382                 nk_textedit_makeundo_replace(state, state->cursor, 1, 1);
 
  383                 nk_str_delete_runes(&state->string, state->cursor, 1);
 
  385             if (nk_str_insert_text_utf8(&state->string, state->cursor,
 
  389                 state->has_preferred_x = 0;
 
  392             nk_textedit_delete_selection(state); 
 
  393             if (nk_str_insert_text_utf8(&state->string, state->cursor,
 
  396                 nk_textedit_makeundo_insert(state, state->cursor, 1);
 
  397                 state->cursor = NK_MIN(state->cursor + 1, state->string.len);
 
  398                 state->has_preferred_x = 0;
 
  402         text_len += glyph_len;
 
  403         glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len);
 
  407 nk_textedit_key(
struct nk_text_edit *state, 
enum nk_keys key, 
int shift_mod,
 
  423     case NK_KEY_TEXT_UNDO:
 
  424          nk_textedit_undo(state);
 
  425          state->has_preferred_x = 0;
 
  428     case NK_KEY_TEXT_REDO:
 
  429         nk_textedit_redo(state);
 
  430         state->has_preferred_x = 0;
 
  433     case NK_KEY_TEXT_SELECT_ALL:
 
  434         nk_textedit_select_all(state);
 
  435         state->has_preferred_x = 0;
 
  438     case NK_KEY_TEXT_INSERT_MODE:
 
  439         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
 
  440             state->mode = NK_TEXT_EDIT_MODE_INSERT;
 
  442     case NK_KEY_TEXT_REPLACE_MODE:
 
  443         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
 
  444             state->mode = NK_TEXT_EDIT_MODE_REPLACE;
 
  446     case NK_KEY_TEXT_RESET_MODE:
 
  447         if (state->mode == NK_TEXT_EDIT_MODE_INSERT ||
 
  448             state->mode == NK_TEXT_EDIT_MODE_REPLACE)
 
  449             state->mode = NK_TEXT_EDIT_MODE_VIEW;
 
  454             nk_textedit_clamp(state);
 
  455             nk_textedit_prep_selection_at_cursor(state);
 
  457             if (state->select_end > 0)
 
  459             state->cursor = state->select_end;
 
  460             state->has_preferred_x = 0;
 
  464             if (NK_TEXT_HAS_SELECTION(state))
 
  465                 nk_textedit_move_to_first(state);
 
  466             else if (state->cursor > 0)
 
  468             state->has_preferred_x = 0;
 
  473             nk_textedit_prep_selection_at_cursor(state);
 
  476             nk_textedit_clamp(state);
 
  477             state->cursor = state->select_end;
 
  478             state->has_preferred_x = 0;
 
  482             if (NK_TEXT_HAS_SELECTION(state))
 
  483                 nk_textedit_move_to_last(state);
 
  484             else ++state->cursor;
 
  485             nk_textedit_clamp(state);
 
  486             state->has_preferred_x = 0;
 
  489     case NK_KEY_TEXT_WORD_LEFT:
 
  491             if( !NK_TEXT_HAS_SELECTION( state ) )
 
  492             nk_textedit_prep_selection_at_cursor(state);
 
  493             state->cursor = nk_textedit_move_to_word_previous(state);
 
  494             state->select_end = state->cursor;
 
  495             nk_textedit_clamp(state );
 
  497             if (NK_TEXT_HAS_SELECTION(state))
 
  498                 nk_textedit_move_to_first(state);
 
  500                 state->cursor = nk_textedit_move_to_word_previous(state);
 
  501                 nk_textedit_clamp(state );
 
  505     case NK_KEY_TEXT_WORD_RIGHT:
 
  507             if( !NK_TEXT_HAS_SELECTION( state ) )
 
  508                 nk_textedit_prep_selection_at_cursor(state);
 
  509             state->cursor = nk_textedit_move_to_word_next(state);
 
  510             state->select_end = state->cursor;
 
  511             nk_textedit_clamp(state);
 
  513             if (NK_TEXT_HAS_SELECTION(state))
 
  514                 nk_textedit_move_to_last(state);
 
  516                 state->cursor = nk_textedit_move_to_word_next(state);
 
  517                 nk_textedit_clamp(state );
 
  524         int i, sel = shift_mod;
 
  526         if (state->single_line) {
 
  533             nk_textedit_prep_selection_at_cursor(state);
 
  534         else if (NK_TEXT_HAS_SELECTION(state))
 
  535             nk_textedit_move_to_last(state);
 
  538         nk_textedit_clamp(state);
 
  539         nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
 
  546             float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
 
  547             int start = find.first_char + find.length;
 
  549             state->cursor = start;
 
  550             nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
 
  553             for (i=0; i < row.num_chars && x < row.x1; ++i) {
 
  554                 float dx = nk_textedit_get_width(state, start, i, font);
 
  560             nk_textedit_clamp(state);
 
  562             state->has_preferred_x = 1;
 
  563             state->preferred_x = goal_x;
 
  565                 state->select_end = state->cursor;
 
  572         int i, sel = shift_mod;
 
  574         if (state->single_line) {
 
  581             nk_textedit_prep_selection_at_cursor(state);
 
  582         else if (NK_TEXT_HAS_SELECTION(state))
 
  583             nk_textedit_move_to_first(state);
 
  586          nk_textedit_clamp(state);
 
  587          nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
 
  591          if (find.prev_first != find.first_char) {
 
  594             float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
 
  596             state->cursor = find.prev_first;
 
  597             nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
 
  600             for (i=0; i < row.num_chars && x < row.x1; ++i) {
 
  601                 float dx = nk_textedit_get_width(state, find.prev_first, i, font);
 
  607             nk_textedit_clamp(state);
 
  609             state->has_preferred_x = 1;
 
  610             state->preferred_x = goal_x;
 
  611             if (sel) state->select_end = state->cursor;
 
  616         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
 
  618         if (NK_TEXT_HAS_SELECTION(state))
 
  619             nk_textedit_delete_selection(state);
 
  621             int n = state->string.len;
 
  622             if (state->cursor < n)
 
  623                 nk_textedit_delete(state, state->cursor, 1);
 
  625          state->has_preferred_x = 0;
 
  628     case NK_KEY_BACKSPACE:
 
  629         if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
 
  631         if (NK_TEXT_HAS_SELECTION(state))
 
  632             nk_textedit_delete_selection(state);
 
  634             nk_textedit_clamp(state);
 
  635             if (state->cursor > 0) {
 
  636                 nk_textedit_delete(state, state->cursor-1, 1);
 
  640          state->has_preferred_x = 0;
 
  643     case NK_KEY_TEXT_START:
 
  645             nk_textedit_prep_selection_at_cursor(state);
 
  646             state->cursor = state->select_end = 0;
 
  647             state->has_preferred_x = 0;
 
  649             state->cursor = state->select_start = state->select_end = 0;
 
  650             state->has_preferred_x = 0;
 
  654     case NK_KEY_TEXT_END:
 
  656             nk_textedit_prep_selection_at_cursor(state);
 
  657             state->cursor = state->select_end = state->string.len;
 
  658             state->has_preferred_x = 0;
 
  660             state->cursor = state->string.len;
 
  661             state->select_start = state->select_end = 0;
 
  662             state->has_preferred_x = 0;
 
  666     case NK_KEY_TEXT_LINE_START: {
 
  669            nk_textedit_clamp(state);
 
  670             nk_textedit_prep_selection_at_cursor(state);
 
  671             if (state->string.len && state->cursor == state->string.len)
 
  673             nk_textedit_find_charpos(&find, state,state->cursor, state->single_line,
 
  675             state->cursor = state->select_end = find.first_char;
 
  676             state->has_preferred_x = 0;
 
  679             if (state->string.len && state->cursor == state->string.len)
 
  681             nk_textedit_clamp(state);
 
  682             nk_textedit_move_to_first(state);
 
  683             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
 
  685             state->cursor = find.first_char;
 
  686             state->has_preferred_x = 0;
 
  690     case NK_KEY_TEXT_LINE_END: {
 
  693             nk_textedit_clamp(state);
 
  694             nk_textedit_prep_selection_at_cursor(state);
 
  695             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
 
  697             state->has_preferred_x = 0;
 
  698             state->cursor = find.first_char + find.length;
 
  699             if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == 
'\n')
 
  701             state->select_end = state->cursor;
 
  704             nk_textedit_clamp(state);
 
  705             nk_textedit_move_to_first(state);
 
  706             nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
 
  709             state->has_preferred_x = 0;
 
  710             state->cursor = find.first_char + find.length;
 
  711             if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == 
'\n')
 
  719     state->redo_point = NK_TEXTEDIT_UNDOSTATECOUNT;
 
  720     state->redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT;
 
  726     if (state->undo_point > 0) {
 
  728         if (state->undo_rec[0].char_storage >= 0) {
 
  729             int n = state->undo_rec[0].insert_length, i;
 
  731             state->undo_char_point = (short)(state->undo_char_point - n);
 
  732             NK_MEMCPY(state->undo_char, state->undo_char + n,
 
  733                 (nk_size)state->undo_char_point*
sizeof(nk_rune));
 
  734             for (i=0; i < state->undo_point; ++i) {
 
  735                 if (state->undo_rec[i].char_storage >= 0)
 
  736                 state->undo_rec[i].char_storage = (short)
 
  737                     (state->undo_rec[i].char_storage - n);
 
  741         NK_MEMCPY(state->undo_rec, state->undo_rec+1,
 
  742             (nk_size)((nk_size)state->undo_point * 
sizeof(state->undo_rec[0])));
 
  753     int k = NK_TEXTEDIT_UNDOSTATECOUNT-1;
 
  754     if (state->redo_point <= k) {
 
  756         if (state->undo_rec[k].char_storage >= 0) {
 
  757             int n = state->undo_rec[k].insert_length, i;
 
  759             state->redo_char_point = (short)(state->redo_char_point + n);
 
  760             num = (nk_size)(NK_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point);
 
  761             NK_MEMCPY(state->undo_char + state->redo_char_point,
 
  762                 state->undo_char + state->redo_char_point-n, num * 
sizeof(
char));
 
  763             for (i = state->redo_point; i < k; ++i) {
 
  764                 if (state->undo_rec[i].char_storage >= 0) {
 
  765                     state->undo_rec[i].char_storage = (short)
 
  766                         (state->undo_rec[i].char_storage + n);
 
  771         num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point);
 
  772         if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1,
 
  773             state->undo_rec + state->redo_point, num * 
sizeof(state->undo_rec[0]));
 
  780     nk_textedit_flush_redo(state);
 
  784     if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
 
  785         nk_textedit_discard_undo(state);
 
  789     if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) {
 
  790         state->undo_point = 0;
 
  791         state->undo_char_point = 0;
 
  797     while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT)
 
  798         nk_textedit_discard_undo(state);
 
  799     return &state->undo_rec[state->undo_point++];
 
  803     int insert_len, 
int delete_len)
 
  810     r->insert_length = (short) insert_len;
 
  811     r->delete_length = (short) delete_len;
 
  813     if (insert_len == 0) {
 
  814         r->char_storage = -1;
 
  817         r->char_storage = state->undo_char_point;
 
  818         state->undo_char_point = (short)(state->undo_char_point +  insert_len);
 
  819         return &state->undo_char[r->char_storage];
 
  827     if (s->undo_point == 0)
 
  831     u = s->undo_rec[s->undo_point-1];
 
  832     r = &s->undo_rec[s->redo_point-1];
 
  833     r->char_storage = -1;
 
  835     r->insert_length = u.delete_length;
 
  836     r->delete_length = u.insert_length;
 
  849         if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) {
 
  852             r->insert_length = 0;
 
  856             while (s->undo_char_point + u.delete_length > s->redo_char_point) {
 
  858                 nk_textedit_discard_redo(s);
 
  860                 if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
 
  864             r = &s->undo_rec[s->redo_point-1];
 
  865             r->char_storage = (short)(s->redo_char_point - u.delete_length);
 
  866             s->redo_char_point = (short)(s->redo_char_point -  u.delete_length);
 
  869             for (i=0; i < u.delete_length; ++i)
 
  870                 s->undo_char[r->char_storage + i] =
 
  871                     nk_str_rune_at(&state->string, u.where + i);
 
  874         nk_str_delete_runes(&state->string, u.where, u.delete_length);
 
  878     if (u.insert_length) {
 
  880         nk_str_insert_text_runes(&state->string, u.where,
 
  881             &s->undo_char[u.char_storage], u.insert_length);
 
  882         s->undo_char_point = (short)(s->undo_char_point - u.insert_length);
 
  884     state->cursor = (short)(u.where + u.insert_length);
 
  894     if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
 
  898     u = &s->undo_rec[s->undo_point];
 
  899     r = s->undo_rec[s->redo_point];
 
  903     u->delete_length = r.insert_length;
 
  904     u->insert_length = r.delete_length;
 
  906     u->char_storage = -1;
 
  908     if (r.delete_length) {
 
  911         if (s->undo_char_point + u->insert_length > s->redo_char_point) {
 
  912             u->insert_length = 0;
 
  913             u->delete_length = 0;
 
  916             u->char_storage = s->undo_char_point;
 
  917             s->undo_char_point = (short)(s->undo_char_point + u->insert_length);
 
  920             for (i=0; i < u->insert_length; ++i) {
 
  921                 s->undo_char[u->char_storage + i] =
 
  922                     nk_str_rune_at(&state->string, u->where + i);
 
  925         nk_str_delete_runes(&state->string, r.where, r.delete_length);
 
  928     if (r.insert_length) {
 
  930         nk_str_insert_text_runes(&state->string, r.where,
 
  931             &s->undo_char[r.char_storage], r.insert_length);
 
  933     state->cursor = r.where + r.insert_length;
 
  939 nk_textedit_makeundo_insert(
struct nk_text_edit *state, 
int where, 
int length)
 
  941     nk_textedit_createundo(&state->undo, where, 0, length);
 
  944 nk_textedit_makeundo_delete(
struct nk_text_edit *state, 
int where, 
int length)
 
  947     nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0);
 
  949         for (i=0; i < length; ++i)
 
  950             p[i] = nk_str_rune_at(&state->string, where+i);
 
  954 nk_textedit_makeundo_replace(
struct nk_text_edit *state, 
int where,
 
  955     int old_length, 
int new_length)
 
  958     nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length);
 
  960         for (i=0; i < old_length; ++i)
 
  961             p[i] = nk_str_rune_at(&state->string, where+i);
 
  965 nk_textedit_clear_state(
struct nk_text_edit *state, 
enum nk_text_edit_type type,
 
  966     nk_plugin_filter filter)
 
  969    state->undo.undo_point = 0;
 
  970    state->undo.undo_char_point = 0;
 
  971    state->undo.redo_point = NK_TEXTEDIT_UNDOSTATECOUNT;
 
  972    state->undo.redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT;
 
  973    state->select_end = state->select_start = 0;
 
  975    state->has_preferred_x = 0;
 
  976    state->preferred_x = 0;
 
  977    state->cursor_at_end_of_line = 0;
 
  978    state->initialized = 1;
 
  979    state->single_line = (
unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE);
 
  980    state->mode = NK_TEXT_EDIT_MODE_VIEW;
 
  981    state->filter = filter;
 
  982    state->scrollbar = 
nk_vec2(0,0);
 
  985 nk_textedit_init_fixed(
struct nk_text_edit *state, 
void *memory, nk_size size)
 
  989     if (!state || !memory || !size) 
return;
 
  991     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
 
  992     nk_str_init_fixed(&state->string, memory, size);
 
  999     if (!state || !alloc) 
return;
 
 1001     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
 
 1002     nk_str_init(&state->string, alloc, size);
 
 1004 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 
 1011     nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
 
 1012     nk_str_init_default(&state->string);
 
 1019     state->select_start = 0;
 
 1020     state->select_end = state->string.len;
 
 1027     nk_str_free(&state->string);
 
main API and documentation file
 
NK_API void nk_textedit_init(struct nk_text_edit *, const struct nk_allocator *, nk_size size)
text editor
 
nk_text_width_f width
!< max height of the font
 
float height
!< user provided font handle