2#include "nuklear_internal.h"
17nk_filter_ascii(
const struct nk_text_edit *box, nk_rune unicode)
20 if (unicode > 128)
return nk_false;
24nk_filter_float(
const struct nk_text_edit *box, nk_rune unicode)
27 if ((unicode <
'0' || unicode >
'9') && unicode !=
'.' && unicode !=
'-')
32nk_filter_decimal(
const struct nk_text_edit *box, nk_rune unicode)
35 if ((unicode <
'0' || unicode >
'9') && unicode !=
'-')
40nk_filter_hex(
const struct nk_text_edit *box, nk_rune unicode)
43 if ((unicode <
'0' || unicode >
'9') &&
44 (unicode <
'a' || unicode >
'f') &&
45 (unicode <
'A' || unicode >
'F'))
50nk_filter_oct(
const struct nk_text_edit *box, nk_rune unicode)
53 if (unicode <
'0' || unicode >
'7')
58nk_filter_binary(
const struct nk_text_edit *box, nk_rune unicode)
61 if (unicode !=
'0' && unicode !=
'1')
74 float x_offset,
const char *text,
int byte_len,
float row_height,
76 struct nk_color foreground, nk_bool is_selected)
81 if (!text || !byte_len || !out || !style)
return;
88 const char *line = text;
89 float line_offset = 0;
94 txt.background = background;
95 txt.text = foreground;
97 foreground = nk_rgb_factor(foreground, style->color_factor);
98 background = nk_rgb_factor(background, style->color_factor);
100 glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len);
101 if (!glyph_len)
return;
102 while ((text_len < byte_len) && glyph_len)
104 if (unicode ==
'\n') {
107 label.y = pos_y + line_offset;
108 label.h = row_height;
109 label.w = line_width;
116 nk_widget_text(out, label, line, (
int)((text + text_len) - line),
117 &txt, NK_TEXT_CENTERED, font);
122 line = text + text_len;
123 line_offset += row_height;
124 glyph_len = nk_utf_decode(text + text_len, &unicode, (
int)(byte_len-text_len));
127 if (unicode ==
'\r') {
129 glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
132 glyph_width = font->
width(font->userdata, font->
height, text+text_len, glyph_len);
133 line_width += (float)glyph_width;
134 text_len += glyph_len;
135 glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
138 if (line_width > 0) {
141 label.y = pos_y + line_offset;
142 label.h = row_height;
143 label.w = line_width;
150 nk_widget_text(out, label, line, (
int)((text + text_len) - line),
151 &txt, NK_TEXT_LEFT, font);
156 struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter,
166 char cursor_follow = 0;
173 if (!state || !out || !style)
177 area.x = bounds.x + style->padding.x + style->border;
178 area.y = bounds.y + style->padding.y + style->border;
179 area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border);
180 area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border);
181 if (flags & NK_EDIT_MULTILINE)
182 area.w = NK_MAX(0, area.w - style->scrollbar_size.x);
183 row_height = (flags & NK_EDIT_MULTILINE)? font->
height + style->row_padding: area.h;
186 old_clip = out->clip;
187 nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h);
190 prev_state = (char)edit->active;
191 if (in && in->mouse.buttons[NK_BUTTON_LEFT].clicked && in->mouse.buttons[NK_BUTTON_LEFT].down) {
192 edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y,
193 bounds.x, bounds.y, bounds.w, bounds.h);
197 if (!prev_state && edit->active) {
198 const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ?
199 NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE;
201 struct nk_vec2 oldscrollbar = edit->scrollbar;
202 nk_textedit_clear_state(edit, type, filter);
203 edit->scrollbar = oldscrollbar;
204 if (flags & NK_EDIT_AUTO_SELECT)
205 select_all = nk_true;
206 if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) {
207 edit->cursor = edit->string.len;
210 }
else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW;
211 if (flags & NK_EDIT_READ_ONLY)
212 edit->mode = NK_TEXT_EDIT_MODE_VIEW;
213 else if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
214 edit->mode = NK_TEXT_EDIT_MODE_INSERT;
217 if (prev_state != edit->active)
221 if (edit->active && in)
223 int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down;
224 const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x;
225 const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y;
228 is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area);
230 nk_textedit_select_all(edit);
231 }
else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
232 in->mouse.buttons[NK_BUTTON_LEFT].clicked) {
233 nk_textedit_click(edit, mouse_x, mouse_y, font, row_height);
234 }
else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
235 (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) {
236 nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height);
237 cursor_follow = nk_true;
238 }
else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked &&
239 in->mouse.buttons[NK_BUTTON_RIGHT].down) {
240 nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height);
241 nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height);
242 cursor_follow = nk_true;
246 int old_mode = edit->mode;
247 for (i = 0; i < NK_KEY_MAX; ++i) {
248 if (i == NK_KEY_ENTER || i == NK_KEY_TAB)
continue;
249 if (nk_input_is_key_pressed(in, (
enum nk_keys)i)) {
250 nk_textedit_key(edit, (
enum nk_keys)i, shift_mod, font, row_height);
251 cursor_follow = nk_true;
254 if (old_mode != edit->mode) {
255 in->keyboard.text_len = 0;
259 edit->filter = filter;
260 if (in->keyboard.text_len) {
261 nk_textedit_text(edit, in->keyboard.text, in->keyboard.text_len);
262 cursor_follow = nk_true;
263 in->keyboard.text_len = 0;
267 if (nk_input_is_key_pressed(in, NK_KEY_ENTER)) {
268 cursor_follow = nk_true;
269 if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod)
270 nk_textedit_text(edit,
"\n", 1);
271 else if (flags & NK_EDIT_SIG_ENTER)
273 else nk_textedit_text(edit,
"\n", 1);
277 {
int copy= nk_input_is_key_pressed(in, NK_KEY_COPY);
278 int cut = nk_input_is_key_pressed(in, NK_KEY_CUT);
279 if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD))
284 int b = edit->select_start;
285 int e = edit->select_end;
287 int begin = NK_MIN(b, e);
288 int end = NK_MAX(b, e);
289 text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len);
291 edit->clip.copy(edit->clip.userdata, text, end - begin);
292 if (cut && !(flags & NK_EDIT_READ_ONLY)){
293 nk_textedit_cut(edit);
294 cursor_follow = nk_true;
299 {
int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE);
300 if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) {
301 edit->clip.paste(edit->clip.userdata, edit);
302 cursor_follow = nk_true;
306 {
int tab = nk_input_is_key_pressed(in, NK_KEY_TAB);
307 if (tab && (flags & NK_EDIT_ALLOW_TAB)) {
308 nk_textedit_text(edit,
" ", 4);
309 cursor_follow = nk_true;
316 else nk_widget_state_reset(state);
322 {
const char *text = nk_str_get_const(&edit->string);
323 int len = nk_str_len_char(&edit->string);
328 background = &style->active;
330 background = &style->hover;
331 else background = &style->normal;
334 switch(background->type) {
335 case NK_STYLE_ITEM_IMAGE:
336 nk_draw_image(out, bounds, &background->data.image, nk_rgb_factor(nk_white, style->color_factor));
338 case NK_STYLE_ITEM_NINE_SLICE:
339 nk_draw_nine_slice(out, bounds, &background->data.slice, nk_rgb_factor(nk_white, style->color_factor));
341 case NK_STYLE_ITEM_COLOR:
342 nk_fill_rect(out, bounds, style->rounding, nk_rgb_factor(background->data.color, style->color_factor));
343 nk_stroke_rect(out, bounds, style->rounding, style->border, nk_rgb_factor(style->border_color, style->color_factor));
348 area.w = NK_MAX(0, area.w - style->cursor_size);
355 const char *cursor_ptr = 0;
356 const char *select_begin_ptr = 0;
357 const char *select_end_ptr = 0;
364 int selection_begin = NK_MIN(edit->select_start, edit->select_end);
365 int selection_end = NK_MAX(edit->select_start, edit->select_end);
368 float line_width = 0.0f;
379 glyph_len = nk_utf_decode(text, &unicode, len);
380 glyph_width = font->
width(font->userdata, font->
height, text, glyph_len);
384 while ((text_len < len) && glyph_len)
387 if (!cursor_ptr && glyphs == edit->cursor)
392 const char *remaining;
395 cursor_pos.y = (float)(total_lines-1) * row_height;
396 row_size = nk_text_calculate_text_bounds(font, text+row_begin,
397 text_len-row_begin, row_height, &remaining,
398 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
399 cursor_pos.x = row_size.x;
400 cursor_ptr = text + text_len;
404 if (!select_begin_ptr && edit->select_start != edit->select_end &&
405 glyphs == selection_begin)
410 const char *remaining;
413 selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height;
414 row_size = nk_text_calculate_text_bounds(font, text+row_begin,
415 text_len-row_begin, row_height, &remaining,
416 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
417 selection_offset_start.x = row_size.x;
418 select_begin_ptr = text + text_len;
422 if (!select_end_ptr && edit->select_start != edit->select_end &&
423 glyphs == selection_end)
428 const char *remaining;
431 selection_offset_end.y = (float)(total_lines-1) * row_height;
432 row_size = nk_text_calculate_text_bounds(font, text+row_begin,
433 text_len-row_begin, row_height, &remaining,
434 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
435 selection_offset_end.x = row_size.x;
436 select_end_ptr = text + text_len;
438 if (unicode ==
'\n') {
439 text_size.x = NK_MAX(text_size.x, line_width);
444 row_begin = text_len;
445 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
446 glyph_width = font->
width(font->userdata, font->
height, text+text_len, glyph_len);
451 text_len += glyph_len;
452 line_width += (float)glyph_width;
454 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
455 glyph_width = font->
width(font->userdata, font->
height,
456 text+text_len, glyph_len);
459 text_size.y = (float)total_lines * row_height;
462 if (!cursor_ptr && edit->cursor == edit->string.len) {
463 cursor_pos.x = line_width;
464 cursor_pos.y = text_size.y - row_height;
472 if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) {
474 const float scroll_increment = area.w * 0.25f;
475 if (cursor_pos.x < edit->scrollbar.x)
476 edit->scrollbar.x = (float)(
int)NK_MAX(0.0f, cursor_pos.x - scroll_increment);
477 if (cursor_pos.x >= edit->scrollbar.x + area.w)
478 edit->scrollbar.x = (float)(
int)NK_MAX(0.0f, cursor_pos.x - area.w + scroll_increment);
479 }
else edit->scrollbar.x = 0;
481 if (flags & NK_EDIT_MULTILINE) {
485 if (cursor_pos.y < edit->scrollbar.y)
486 edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y);
487 if (cursor_pos.y > edit->scrollbar.y + area.h - row_height)
488 edit->scrollbar.y = edit->scrollbar.y + row_height;
489 }
else edit->scrollbar.y = 0;
493 if (flags & NK_EDIT_MULTILINE)
503 scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x;
504 scroll.w = style->scrollbar_size.x;
506 scroll_offset = edit->scrollbar.y;
507 scroll_step = scroll.h * 0.10f;
508 scroll_inc = scroll.h * 0.01f;
509 scroll_target = text_size.y;
510 edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, is_hovered,
511 scroll_offset, scroll_target, scroll_step, scroll_inc,
512 &style->scrollbar, in, font);
514 if (is_hovered && in->mouse.scroll_delta.y) {
515 in->mouse.scroll_delta.y = 0;
523 struct nk_color sel_background_color;
528 nk_push_scissor(out, clip);
532 background = &style->active;
533 text_color = style->text_active;
534 sel_text_color = style->selected_text_hover;
535 sel_background_color = style->selected_hover;
536 cursor_color = style->cursor_hover;
537 cursor_text_color = style->cursor_text_hover;
539 background = &style->hover;
540 text_color = style->text_hover;
541 sel_text_color = style->selected_text_hover;
542 sel_background_color = style->selected_hover;
543 cursor_text_color = style->cursor_text_hover;
544 cursor_color = style->cursor_hover;
546 background = &style->normal;
547 text_color = style->text_normal;
548 sel_text_color = style->selected_text_normal;
549 sel_background_color = style->selected_normal;
550 cursor_color = style->cursor_normal;
551 cursor_text_color = style->cursor_text_normal;
553 if (background->type == NK_STYLE_ITEM_IMAGE)
554 background_color = nk_rgba(0,0,0,0);
556 background_color = background->data.color;
558 cursor_color = nk_rgb_factor(cursor_color, style->color_factor);
559 cursor_text_color = nk_rgb_factor(cursor_text_color, style->color_factor);
561 if (edit->select_start == edit->select_end) {
563 const char *begin = nk_str_get_const(&edit->string);
564 int l = nk_str_len_char(&edit->string);
565 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
566 area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
567 background_color, text_color, nk_false);
570 if (edit->select_start != edit->select_end && selection_begin > 0){
572 const char *begin = nk_str_get_const(&edit->string);
573 NK_ASSERT(select_begin_ptr);
574 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
575 area.y - edit->scrollbar.y, 0, begin, (
int)(select_begin_ptr - begin),
576 row_height, font, background_color, text_color, nk_false);
578 if (edit->select_start != edit->select_end) {
580 NK_ASSERT(select_begin_ptr);
581 if (!select_end_ptr) {
582 const char *begin = nk_str_get_const(&edit->string);
583 select_end_ptr = begin + nk_str_len_char(&edit->string);
585 nk_edit_draw_text(out, style,
586 area.x - edit->scrollbar.x,
587 area.y + selection_offset_start.y - edit->scrollbar.y,
588 selection_offset_start.x,
589 select_begin_ptr, (
int)(select_end_ptr - select_begin_ptr),
590 row_height, font, sel_background_color, sel_text_color, nk_true);
592 if ((edit->select_start != edit->select_end &&
593 selection_end < edit->
string.len))
596 const char *begin = select_end_ptr;
597 const char *end = nk_str_get_const(&edit->string) +
598 nk_str_len_char(&edit->string);
599 NK_ASSERT(select_end_ptr);
600 nk_edit_draw_text(out, style,
601 area.x - edit->scrollbar.x,
602 area.y + selection_offset_end.y - edit->scrollbar.y,
603 selection_offset_end.x,
604 begin, (
int)(end - begin), row_height, font,
605 background_color, text_color, nk_true);
610 if (edit->select_start == edit->select_end)
612 if (edit->cursor >= nk_str_len(&edit->string) ||
613 (cursor_ptr && *cursor_ptr ==
'\n')) {
616 cursor.w = style->cursor_size;
618 cursor.x = area.x + cursor_pos.x - edit->scrollbar.x;
619 cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f;
620 cursor.y -= edit->scrollbar.y;
629 NK_ASSERT(cursor_ptr);
630 glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4);
632 label.x = area.x + cursor_pos.x - edit->scrollbar.x;
633 label.y = area.y + cursor_pos.y - edit->scrollbar.y;
634 label.w = font->
width(font->userdata, font->
height, cursor_ptr, glyph_len);
635 label.h = row_height;
638 txt.background = cursor_color;;
639 txt.text = cursor_text_color;
641 nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font);
646 int l = nk_str_len_char(&edit->string);
647 const char *begin = nk_str_get_const(&edit->string);
652 nk_push_scissor(out, clip);
654 background = &style->active;
655 text_color = style->text_active;
657 background = &style->hover;
658 text_color = style->text_hover;
660 background = &style->normal;
661 text_color = style->text_normal;
663 if (background->type == NK_STYLE_ITEM_IMAGE)
664 background_color = nk_rgba(0,0,0,0);
666 background_color = background->data.color;
668 background_color = nk_rgb_factor(background_color, style->color_factor);
669 text_color = nk_rgb_factor(text_color, style->color_factor);
671 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
672 area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
673 background_color, text_color, nk_false);
675 nk_push_scissor(out, old_clip);}
679nk_edit_focus(
struct nk_context *ctx, nk_flags flags)
685 NK_ASSERT(ctx->current);
686 if (!ctx || !ctx->current)
return;
689 hash = win->edit.seq;
690 win->edit.active = nk_true;
691 win->edit.name = hash;
692 if (flags & NK_EDIT_ALWAYS_INSERT_MODE)
693 win->edit.mode = NK_TEXT_EDIT_MODE_INSERT;
700 NK_ASSERT(ctx->current);
701 if (!ctx || !ctx->current)
return;
704 win->edit.active = nk_false;
708nk_edit_string(
struct nk_context *ctx, nk_flags flags,
709 char *memory,
int *len,
int max, nk_plugin_filter filter)
719 if (!ctx || !memory || !len)
724 hash = win->edit.seq;
726 nk_textedit_clear_state(&ctx->
text_edit, (flags & NK_EDIT_MULTILINE)?
727 NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE, filter);
729 if (win->edit.active && hash == win->edit.name) {
730 if (flags & NK_EDIT_NO_CURSOR)
731 edit->cursor = nk_utf_len(memory, *len);
732 else edit->cursor = win->edit.cursor;
733 if (!(flags & NK_EDIT_SELECTABLE)) {
734 edit->select_start = win->edit.cursor;
735 edit->select_end = win->edit.cursor;
737 edit->select_start = win->edit.sel_start;
738 edit->select_end = win->edit.sel_end;
740 edit->mode = win->edit.mode;
741 edit->scrollbar.x = (float)win->edit.scrollbar.x;
742 edit->scrollbar.y = (float)win->edit.scrollbar.y;
743 edit->active = nk_true;
744 }
else edit->active = nk_false;
746 max = NK_MAX(1, max);
747 *len = NK_MIN(*len, max-1);
748 nk_str_init_fixed(&edit->string, memory, (nk_size)max);
749 edit->string.buffer.
allocated = (nk_size)*len;
750 edit->string.len = nk_utf_len(memory, *len);
751 state = nk_edit_buffer(ctx, flags, edit, filter);
752 *len = (int)edit->string.buffer.
allocated;
755 win->edit.cursor = edit->cursor;
756 win->edit.sel_start = edit->select_start;
757 win->edit.sel_end = edit->select_end;
758 win->edit.mode = edit->mode;
759 win->edit.scrollbar.x = (nk_uint)edit->scrollbar.x;
760 win->edit.scrollbar.y = (nk_uint)edit->scrollbar.y;
764nk_edit_buffer(
struct nk_context *ctx, nk_flags flags,
774 nk_flags ret_flags = 0;
775 unsigned char prev_state;
781 NK_ASSERT(ctx->current);
782 NK_ASSERT(ctx->current->layout);
783 if (!ctx || !ctx->current || !ctx->current->layout)
788 state = nk_widget(&bounds, ctx);
789 if (!state)
return state;
791 flags |= NK_EDIT_READ_ONLY;
795 hash = win->edit.seq++;
796 if (win->edit.active && hash == win->edit.name) {
797 if (flags & NK_EDIT_NO_CURSOR)
798 edit->cursor = edit->string.len;
799 if (!(flags & NK_EDIT_SELECTABLE)) {
800 edit->select_start = edit->cursor;
801 edit->select_end = edit->cursor;
803 if (flags & NK_EDIT_CLIPBOARD)
804 edit->clip = ctx->clip;
805 edit->active = (
unsigned char)win->edit.active;
806 }
else edit->active = nk_false;
807 edit->mode = win->edit.mode;
810 prev_state = (
unsigned char)edit->active;
811 in = (flags & NK_EDIT_READ_ONLY) ? 0: in;
812 ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags,
813 filter, edit, &style->edit, in, style->font);
816 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_TEXT];
817 if (edit->active && prev_state != edit->active) {
819 win->edit.active = nk_true;
820 win->edit.name = hash;
821 }
else if (prev_state && !edit->active) {
823 win->edit.active = nk_false;
827nk_edit_string_zero_terminated(
struct nk_context *ctx, nk_flags flags,
828 char *buffer,
int max, nk_plugin_filter filter)
831 int len = nk_strlen(buffer);
832 result = nk_edit_string(ctx, flags, buffer, &len, max, filter);
833 buffer[NK_MIN(NK_MAX(max-1,0), len)] =
'\0';
main API and documentation file
@ NK_WINDOW_ROM
sets window widgets into a read only mode and does not allow input changes
NK_API void nk_draw_image(struct nk_command_buffer *, struct nk_rect, const struct nk_image *, struct nk_color)
misc
NK_API void nk_fill_rect(struct nk_command_buffer *, struct nk_rect, float rounding, struct nk_color)
filled shades
NK_API nk_bool nk_filter_default(const struct nk_text_edit *, nk_rune unicode)
filter function
@ NK_WIDGET_STATE_ACTIVED
!< widget is being hovered
@ NK_WIDGET_STATE_HOVER
!< widget has been hovered on the current frame
@ NK_WIDGET_STATE_ACTIVE
!< widget is being hovered
@ NK_WIDGET_STATE_HOVERED
!< widget is from this frame on not hovered anymore
@ NK_WIDGET_DISABLED
The widget is manually disabled and acts like NK_WIDGET_ROM.
@ NK_EDIT_INACTIVE
!< edit widget is currently being modified
@ NK_EDIT_DEACTIVATED
!< edit widget went from state inactive to state active
@ NK_EDIT_COMMITED
!< edit widget went from state active to state inactive
@ NK_EDIT_ACTIVATED
!< edit widget is not active and is not being modified
nk_size allocated
!< growing factor for dynamic memory management
struct nk_text_edit text_edit
text editor objects are quite big because of an internal undo/redo stack.
nk_text_width_f width
!< max height of the font
float height
!< user provided font handle