123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665 |
- /* Magic comment for runcprotoall: @generate_cproto@ */
- #include "monolog.h"
- #include "zori.h"
- #include "zori_widget.h"
- #include "zori_caption.h"
- #include "zori_longtext.h"
- #include "zori_page.h"
- #include <math.h>
- #define ZORI_LONGTEXT_LINE_POS_MAX 99999
- #define ZORI_LONGTEXT_ANIMATION_CYCLE_TIME 4.0
- #define ZORI_LONGTEXT_PAUSE_MARKER_DAMPER 2.0
- #define ZORI_LONGTEXT_PAUSE_MARKER_SCALE 0.75
- #define ZORI_LONGTEXT_DEFAULT_DELAY 0.2
- struct zori_longtext * zori_widget_to_longtext(struct zori_widget * widget) {
- if (!zori_widget_is_type(widget, ZORI_WIDGET_TYPE_LONGTEXT)) return NULL;
- return ZORI_CONTAINER_OF(widget, struct zori_longtext, widget);
- }
- static bool
- zori_longtext_calculate_lines_aid(int line_num, const zori_string *line, void * extra) {
- struct zori_longtext * longtext = extra;
- longtext->state.total = line_num + 1;
- return true;
- }
- /** Calculates the amount of lines needed for the longtext as per al_do_multiline_text
- * The value is set in longtext->state.total and returned;
- */
- int zori_longtext_calculate_lines(struct zori_longtext * longtext) {
- double width = longtext->widget.inner.size.x;
- longtext->state.total = 0;
- al_do_multiline_ustr(zori_widget_font(&longtext->widget), width,
- longtext->text, zori_longtext_calculate_lines_aid, longtext);
- return longtext->state.total;
- }
- struct zori_longtext *
- zori_longtext_set(struct zori_longtext * longtext, const zori_string * text) {
- if (longtext) {
- if (longtext->text) {
- ustr_free(longtext->text);
- longtext->text = NULL;
- longtext->state.total = 0;
- }
- if (text) {
- longtext->text = ustr_dup(text);
- if (!longtext->text) {
- longtext->state.total = 0;
- LOG_ERROR("Out of memory in longtext setup.\n");
- return NULL;
- } else {
- zori_longtext_calculate_lines(longtext);
- LOG_DEBUG("Longtext lines: %d\n", longtext->state.total);
- }
- }
- }
- return longtext;
- }
- struct zori_longtext *
- zori_longtext_set_cstr(struct zori_longtext * longtext, const char * cstr) {
- const USTR * ustr;
- USTR_INFO info;
- if (!cstr) cstr = "EMPTY!!!";
- ustr = ustr_refcstr(&info, cstr);
- return zori_longtext_set(longtext, ustr);
- }
- struct zori_longtext *
- zori_longtext_init_cstr(struct zori_longtext * longtext, const char * cstr) {
- longtext->text = NULL;
- return zori_longtext_set_cstr(longtext, cstr);
- }
- void zori_longtext_done(struct zori_longtext * longtext) {
- zori_longtext_set(longtext, NULL);
- }
- /** Gets the number of lines in one page. Always returns at least 1. */
- int zori_longtext_page_lines(struct zori_longtext * longtext) {
- if (!longtext) return 1;
- if (longtext->settings.lines > 1) {
- return longtext->settings.lines;
- }
- return 1;
- }
- /** Sets the number of lines in one page. Sets at least 1. */
- int zori_longtext_page_lines_(struct zori_longtext * longtext, int pl) {
- if (!longtext) return -1;
- if (pl < 1) {
- pl = 1;
- }
- longtext->settings.lines = pl;
- return longtext->settings.lines;
- }
- /** Gets the current text page for a longtext. Page 0 is the first page, etc.*/
- int zori_longtext_page(struct zori_longtext * longtext) {
- int pl = 1;
- if (!longtext) return -2;
- return longtext->state.page;
- }
- /** Gets the last page number (inclusive) for a longtext or negative on error. */
- int zori_longtext_last_page(struct zori_longtext * longtext) {
- int pl = 1;
- if (!longtext) return -2;
- pl = zori_longtext_page_lines(longtext);
- return longtext->state.total / pl;
- }
- /** Advances long text to the given page. Automatically unpauses as well. */
- int zori_longtext_page_(struct zori_longtext * longtext, int page) {
- int pl = 1;
- int line = 1;
- if (!longtext) return -2;
- if (!longtext) return -2;
- if (page < 0) return -3;
- pl = zori_longtext_page_lines(longtext);
- line = page * pl;
- /* Check for page overflow. */
- LOG_NOTE("Selecting page nr %d, line nr %d, limit of %d", page, line, longtext->state.total);
-
- if (line >= longtext->state.total) {
- LOG_WARNING("Cannot select page nr %d, line nr %d, more than limit of %d",
- page, line, longtext->state.total);
- return -5;
- }
-
- longtext->state.paused = false;
- longtext->state.line = line;
- longtext->state.page = page;
- /* Negative delay is instant display. */
- if (longtext->settings.delay < 0) {
- longtext->state.position = ZORI_LONGTEXT_LINE_POS_MAX;
- } else {
- longtext->state.position = 0;
- }
- return page;
- }
- /* Returns TRUE if the longtext node is at the end of the text to display,
- * false if not (more text to display) */
- int zori_longtext_at_end(struct zori_longtext * longtext) {
- if (!longtext) return FALSE;
- return ((longtext->state.line >= longtext->state.total)
- /* && (longtext->state.position >= ZORI_LONGTEXT_LINE_POS_MAX) */);
- }
- /* This function is the helper callback that implements
- * updating scrolled/partial text for Longtexts.
- */
- static bool
- zori_longtext_update_custom_partial_text(int line_num, const zori_text *line, void * extra) {
- struct zori_longtext * longtext = extra;
- int last_line = line_num;
- int start_line = longtext->state.page * longtext->settings.lines;
- int stop_line = (longtext->state.page + 1) * longtext->settings.lines;
- int line_length = al_ustr_length(line);
-
- /* Don't draw lines before start but keep on drawing (for later lines) */
- if (line_num < start_line) return true;
- /* Don't draw lines after stop, but keep calculating to get correct amount of lines */
- if (line_num >= stop_line) return true;
- /* Reveal letter by letter on last line */
- if (line_num == longtext->state.line) {
- /* Advance the position automatically if not paused. */
- if (!longtext->state.paused) {
- if (longtext->settings.flags & ZORI_LONGTEXT_SETTING_FLAG_SHOW_LETTERS) {
- al_ustr_next(line, &longtext->state.position);
- } else {
- int next_word = al_ustr_find_set_cstr(line, longtext->state.position + 1, " \t\r\n");
- if (next_word > 0) {
- longtext->state.position = next_word;
- } else if (longtext->state.position < (line_length -1)) { /* skip almost to the end of the line. */
- longtext->state.position = line_length;
- } else { /* Advance, to end of line. */
- al_ustr_next(line, &longtext->state.position);
- }
- }
- }
- /* Reached eol, advance to next line. */
- if (longtext->state.position >= line_length) {
- int pl = zori_longtext_page_lines(longtext);
- /* Is if the text window is full, pause, otherwise show the next line. */
- if (longtext->state.line >= (stop_line-1)) {
- longtext->state.paused = true;
- } else {
- longtext->state.line++;
- longtext->state.position = 0;
- }
- }
- }
- return true;
- }
- /* Rerurns whether or no t the end of a page is reached on a longtext */
- int zori_longtext_end_of_page(struct zori_longtext * longtext) {
- int limit;
- if (zori_longtext_at_end(longtext)) return TRUE;
- limit = (longtext->state.page + 1) * longtext->settings.lines;
- return (longtext->state.line >= limit);
- }
- /* Updates the longtext, enables scrolling and per character display. */
- void zori_longtext_update_longtext(struct zori_longtext * longtext, double dt) {
- float width = longtext->widget.inner.size.x;
- zori_text * text = longtext->text;
-
- if (!text) {
- LOG_WARNING("Attempted to update a NULL longtext.");
- return;
- }
-
- longtext->state.anitime += dt;
- if (longtext->state.anitime > ZORI_LONGTEXT_ANIMATION_CYCLE_TIME) {
- longtext->state.anitime = 0;
- }
-
- /* Delay advance of characters somewhat if requested. */
- if (longtext->settings.delay > 0.0) {
- longtext->state.wait += dt;
- if (longtext->state.wait < longtext->settings.delay) return;
- longtext->state.wait = 0;
- }
-
- al_do_multiline_ustr(zori_widget_font(&longtext->widget), width,
- text, zori_longtext_update_custom_partial_text, longtext);
-
- /* pause if the last line of the page is reached, and prevent overflow. */
- if (zori_longtext_end_of_page(longtext)) {
- longtext->state.paused = TRUE;
- longtext->state.position = ZORI_LONGTEXT_LINE_POS_MAX;
- }
-
- }
- /* Calculates the x and y position where to draw text, taking alignment and
- * margin into consideration. */
- static BeVec
- zori_longtext_calculate_text_position(struct zori_longtext * longtext) {
- BeVec result;
- int flags = longtext->widget.style.text.flags;
- result.x = longtext->widget.inner.at.x;
- result.y = longtext->widget.inner.at.y;
- if (flags & ALLEGRO_ALIGN_CENTER) {
- result.x += longtext->widget.inner.size.x / 2;
- } else if (flags & ALLEGRO_ALIGN_RIGHT) {
- result.x += longtext->widget.inner.size.x;
- }
- return result;
- }
- /* Draws the longtext, if it has a single line.. */
- void zori_longtext_draw_text(struct zori_longtext * longtext) {
- zori_font * font;
- int flags;
- BeVec pos = zori_longtext_calculate_text_position(longtext);
- font = zori_widget_font(&longtext->widget);
- flags = longtext->widget.style.text.flags | ALLEGRO_ALIGN_INTEGER;
- zori_color shadow = longtext->widget.style.back.color;
- zori_color fore = longtext->widget.style.text.color;
-
- /* Draw the text twice, once offset in bg color to produce a shadow,
- and once normally with foreground color. */
- al_draw_ustr(font, shadow, pos.x + 1, pos.y + 1,
- flags, longtext->text);
- al_draw_ustr(font, fore, pos.x, pos.y,
- flags, longtext->text);
- }
- /**
- * Draws the paused marker if needed.
- */
- static void zori_longtext_draw_paused_marker(const struct zori_longtext * longtext) {
- struct zori_root * root = zori_get_root();
- int line_skip;
- float x, y, x1, y1, x2, y2, x3, y3, sp, ms;
-
- if (!longtext->state.paused) return;
-
- line_skip = (longtext->state.page + 1 * longtext->settings.lines);
- x = longtext->widget.inner.at.x ;
- y = longtext->widget.inner.at.y ;
- sp = longtext->settings.spacing;
- y += line_skip * sp;
- ms = sp * ZORI_LONGTEXT_PAUSE_MARKER_SCALE;
-
- /* Animate marker by varying its y position */
- y -= sin(longtext->state.anitime * ALLEGRO_PI) * ms / ZORI_LONGTEXT_PAUSE_MARKER_DAMPER;
-
- if (root->style.icons.paused) {
- al_draw_bitmap(root->style.icons.paused, x, y, 0);
- } else {
- y2 = y + ms;
- x2 = x + longtext->widget.inner.size.x;
- x1 = x2 - ms;
- y1 = y2;
- x3 = x2 - ms / 2.0;
- y3 = y2 + ms;
- al_draw_filled_triangle(x1, y1, x2, y2, x3, y3, longtext->widget.style.text.color);
- }
- }
- /* This function is the helper callback that implements the actual drawing
- * for zori_longtext_draw_partial_text.
- */
- static bool zori_longtext_draw_custom_partial_text(int line_num, const zori_text *line,
- void *extra) {
- float x, y;
- struct zori_longtext * longtext = extra;
- ALLEGRO_USTR_INFO info;
- const ALLEGRO_USTR * subline;
- int real_length, flags;
- ALLEGRO_FONT * font;
- BeVec pos;
- int sublength = al_ustr_length(line);
- int last_line = line_num;
- int start_line = longtext->state.page * longtext->settings.lines;
- int stop_line = longtext->state.line + 1;
- if (stop_line >= longtext->state.total) {
- stop_line = longtext->state.total;
- }
-
- font = zori_widget_font(&longtext->widget);
- flags = longtext->widget.style.text.flags | ALLEGRO_ALIGN_INTEGER;
- pos = zori_longtext_calculate_text_position(longtext);
-
-
- /* Don't draw lines before start but keep on drawing (for later lines) */
- if (line_num < start_line) return true;
- /* Don't draw lines after stop, drawing is done */
- if (line_num >= stop_line) return false;
-
- real_length = sublength;
-
- /* Reveal letter by letter on currently active line */
- if (line_num == (longtext->state.line)) {
- real_length = (longtext->state.position < sublength) ? longtext->state.position : sublength;
- }
-
-
- x = pos.x;
- y = pos.y + (longtext->settings.spacing * (line_num - start_line));
-
- /* calculate position of subline */
- subline = al_ref_ustr(&info, line, 0, al_ustr_offset(line, real_length));
-
- if (flags & ALLEGRO_ALIGN_CENTER) {
- /* x -= al_get_ustr_width(font, subline) / 2; */
- } else if (flags & ALLEGRO_ALIGN_RIGHT) {
- x -= al_get_ustr_width(font, subline);
- }
-
-
-
- // real_size = size;
-
- zori_color shadow = longtext->widget.style.back.color;
- zori_color fore = longtext->widget.style.text.color;
-
- al_draw_ustr(font, shadow, x + 1, y + 1, flags, subline);
- al_draw_ustr(font, fore, x, y, flags, subline);
-
- return true;
- }
- /* Allows to draw a multi line text partially, from line_start up to
- * line_stop. Draws scrolling text from a prefilled struct. */
- void zori_longtext_draw_partial_text(struct zori_longtext * longtext) {
- float width = longtext->widget.inner.size.x - 20;
- zori_font * font = zori_widget_font(&longtext->widget);
-
- if (!longtext->text) {
- LOG_WARNING("Trying to draw a NULL longtext.");
- return;
- }
-
- al_do_multiline_ustr(font, width,
- longtext->text, zori_longtext_draw_custom_partial_text, longtext);
- }
- void zori_draw_longtext(struct zori_longtext * longtext) {
- zori_widget_draw_background(&longtext->widget);
- zori_longtext_draw_partial_text(longtext);
- zori_longtext_draw_paused_marker(longtext);
- }
- /** Sets the last line to display for a long text */
- zori_id zori_set_line_stop(zori_id index, int stop) {
- return ZORI_ID_EINVAL;
- }
- /** Sets the first line to display for a long text */
- zori_id zori_line_start_(zori_id index, int start) {
- return ZORI_ID_EINVAL;
- }
- /** Sets display delay between individual characters for a long text */
- int zori_delay_(zori_id index, double delay) {
- struct zori_widget * widget = zori_get_widget(index);
- struct zori_longtext * longtext = zori_widget_to_longtext(widget);
- if (!longtext) return ZORI_ID_EINVAL;
- longtext->settings.delay = delay;
- return index;
- }
- /** Gets the last line to display for a long text or negative on error*/
- int zori_line_stop(int index) {
- return ZORI_ID_EINVAL;
- }
- /** Gets the first line to display for a long text */
- int zori_line_start(int index) {
- return ZORI_ID_EINVAL;
- }
- /** Gets display delay between individual characters for a long text */
- double zori_delay(int index) {
- struct zori_widget * widget = zori_get_widget(index);
- struct zori_longtext * longtext = zori_widget_to_longtext(widget);
- if (!longtext) return ZORI_ID_EINVAL;
- return longtext->settings.delay;
- }
- /** Sets amount of shown lines per page for a long text */
- int zori_page_lines_(zori_id index, int lines) {
- struct zori_widget * widget = zori_get_widget(index);
- struct zori_longtext * longtext = zori_widget_to_longtext(widget);
- if (!longtext) return ZORI_ID_EINVAL;
- zori_longtext_page_lines_(longtext, lines);
- return index;
- }
- /** Gets amount of lines for a "page" of long text */
- int zori_page_lines(int index) {
- struct zori_widget * widget = zori_get_widget(index);
- struct zori_longtext * longtext = zori_widget_to_longtext(widget);
- if (!longtext) return ZORI_ID_EINVAL;
- return zori_longtext_page_lines(longtext);
- }
- /** Sets paused state of long text */
- int zori_paused_(zori_id index, int paused) {
- struct zori_widget * widget = zori_get_widget(index);
- struct zori_longtext * longtext = zori_widget_to_longtext(widget);
- if (!longtext) return ZORI_ID_EINVAL;
- longtext->state.paused = paused;
- return index;
- }
- /** Gets paused state of long text */
- int zori_paused(zori_id index) {
- struct zori_widget * widget = zori_get_widget(index);
- struct zori_longtext * longtext = zori_widget_to_longtext(widget);
- if (!longtext) return 0;
- return longtext->state.paused;
- }
- /** Gets the current text page for a longtext. */
- int zori_page(zori_id index) {
- struct zori_widget * widget = zori_get_widget(index);
- struct zori_longtext * longtext = zori_widget_to_longtext(widget);
- if (!longtext) return ZORI_ID_EINVAL;
- return zori_longtext_page(longtext);
- }
- /** Gets the number of the last text page for a longtext. */
- int zori_last_page(zori_id index) {
- struct zori_widget * widget = zori_get_widget(index);
- struct zori_longtext * longtext = zori_widget_to_longtext(widget);
- if (!longtext) return ZORI_ID_EINVAL;
- return zori_longtext_last_page(longtext);
- }
- /** Returns nonzero if the long text is at the end of it's display. */
- int zori_at_end(zori_id index) {
- struct zori_widget * widget = zori_get_widget(index);
- struct zori_longtext * longtext = zori_widget_to_longtext(widget);
- if (!longtext) return ZORI_ID_EINVAL;
- return zori_longtext_at_end(longtext);
- }
- /** Advances long text to the given page. Automatically unpauses as well. */
- int zori_page_(zori_id index, int page) {
- struct zori_widget * widget = zori_get_widget(index);
- struct zori_longtext * longtext = zori_widget_to_longtext(widget);
- return zori_longtext_page_(longtext, page);
- }
- /** Advances long text to the next page. Automatically unpauses as well. */
- int zori_next_page(zori_id index) {
- int page = zori_page(index);
- if (page < 0) return page;
- return zori_page_(index, page + 1);
- }
- /** Advances long text to the previous page. Automatically unpauses as well. */
- int zori_previous_page(int index) {
- int page = zori_page(index);
- if (page < 0) return page;
- return zori_page_(index, page - 1);
- }
- /** Handles an update event and pass it on. */
- int zori_longtext_on_update(union zori_event * event) {
- struct zori_widget * widget = event->any.widget;
- struct zori_longtext * longtext = zori_widget_to_longtext(widget);
- zori_longtext_update_longtext(longtext, event->update.dt);
- return ZORI_HANDLE_PASS;
- }
- /** Handles a mouse axis event and pass it on. */
- int zori_longtext_on_mouse_axes(union zori_event * event) {
- struct zori_widget * widget = event->any.widget;
- struct zori_longtext * longtext = zori_widget_to_longtext(widget);
- float x = event->sys.ev->mouse.x;
- float y = event->sys.ev->mouse.y;
- if (zori_xy_inside_widget_p(widget, x, y)) {
- zori_widget_hover_(widget, TRUE);
- } else {
- zori_widget_hover_(widget, FALSE);
- }
-
- return ZORI_HANDLE_PASS;
- }
- /** Handles a mouse click event and pass it on. */
- int zori_longtext_on_mouse_click(union zori_event * event) {
- struct zori_widget * widget = event->any.widget;
- struct zori_longtext * longtext = zori_widget_to_longtext(widget);
- float x = event->sys.ev->mouse.x;
- float y = event->sys.ev->mouse.y;
- int b = event->sys.ev->mouse.button;
- if (zori_xy_inside_widget_p(widget, x, y)) {
- struct zori_widget * page = zori_widget_get_parent_of_type(widget, ZORI_WIDGET_TYPE_PAGE);
- widget->result.ready = widget->id;
- widget->result.value.string = longtext->text;
- LOG_NOTE("Longtext %d clicked: %d, result %d.\n", widget->id, widget->result);
- LOG_NOTE("Longtext visible %d.\n", zori_widget_visible(widget));
- LOG_NOTE("UI page visible %d.\n", zori_widget_visible(page));
- LOG_NOTE("Longtext page visible %d.\n", zori_longtext_page(longtext));
-
- longtext->state.paused = 0;
-
- if (1==b) {
- if (zori_longtext_at_end(longtext)) {
- zori_widget_set_closed_result(&longtext->widget, longtext->state.total);
- } else {
- zori_longtext_page_(longtext, zori_longtext_page(longtext) + 1);
- }
- } else if (2==b) {
- zori_longtext_page_(longtext, 0);
- }
- return zori_widget_raise_action_event(widget);
- }
- return ZORI_HANDLE_PASS;
- }
- int zori_longtext_on_draw(union zori_event * event) {
- struct zori_widget * widget = event->any.widget;
- struct zori_longtext * longtext = zori_widget_to_longtext(widget);
- zori_draw_longtext(longtext);
- return ZORI_HANDLE_PASS;
- }
- struct zori_handler zori_longtext_handlers[] = {
- { ZORI_SYSTEM_EVENT_MOUSE_BUTTON_DOWN , zori_longtext_on_mouse_click , NULL },
- { ZORI_SYSTEM_EVENT_MOUSE_AXES , zori_longtext_on_mouse_axes , NULL },
- { ZORI_EVENT_DRAW , zori_longtext_on_draw , NULL },
- { ZORI_EVENT_UPDATE , zori_longtext_on_update , NULL },
- { -1, NULL, NULL }
- };
- struct zori_longtext *
- zori_longtext_init(struct zori_longtext * longtext, const char * text) {
- if (longtext) {
- int lh = 8;
- zori_longtext_set_cstr(longtext, text);
- zori_longtext_page_(longtext, 0);
- lh = zori_font_lineheight(longtext->widget.style.text.font);
- zori_longtext_page_lines_(longtext, lh / longtext->widget.inner.size.y);
- longtext->settings.delay = ZORI_LONGTEXT_DEFAULT_DELAY;
- longtext->state.line = 0;
- longtext->state.page = 0;
- longtext->state.position = 0;
- longtext->state.paused = 0;
- longtext->state.anitime = 0.0;
- longtext->settings.lines = 2;
-
- /* XXX It's a hack that this ends up here... */
- if (longtext->settings.spacing < 1.0) {
- longtext->settings.spacing = lh;
- }
- }
- return longtext;
- }
- struct zori_longtext * zori_longtext_new(zori_id id, zori_id parent_id,
- zori_box * box, const char * text) {
- struct zori_longtext * longtext = NULL;
- longtext = calloc(1, sizeof(*longtext));
- if (!longtext) return NULL;
- zori_widget_initall(&longtext->widget, ZORI_WIDGET_TYPE_LONGTEXT, id, zori_get_widget(parent_id),
- box, NULL, ZORI_ARRAY_AND_AMOUNT(zori_longtext_handlers));
- if (!zori_longtext_init(longtext, text)) {
- free(longtext);
- longtext = NULL;
- }
- zori_widget_hover_(&longtext->widget, 0);
- zori_widget_live_(&longtext->widget, 1);
-
- return longtext;
- }
- zori_id zori_new_longtext(zori_id id, zori_id parent, zori_box * box, const char * text) {
- struct zori_longtext * longtext = zori_longtext_new(id, parent, box, text);
- if (!longtext) return ZORI_ID_ENOMEM;
- return longtext->widget.id;
- }
|