/* Test al_ustr_length. */ static void t27(void) { ALLEGRO_USTR *us = al_ustr_new("aþ€\xf4\x8f\xbf\xbf"); CHECK(0 == al_ustr_length(al_ustr_empty_string())); CHECK(4 == al_ustr_length(us)); al_ustr_free(us); }
bool InputField::Input(ALLEGRO_EVENT &ev, float &scalex, float &scaley) { int unichar = 0; detectingbutton->Input(ev, scalex, scaley); if(detectingbutton->is_button_clicked() == true && detectingbutton->is_mouse_in_it() == false && ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN && ev.mouse.button == 1) { detectingbutton->unclick(); } else if(detectingbutton->is_button_clicked() == true) { if(ev.type == ALLEGRO_EVENT_KEY_CHAR && (ev.keyboard.keycode == ALLEGRO_KEY_BACKSPACE || ev.keyboard.keycode == ALLEGRO_KEY_ENTER)) { switch(ev.keyboard.keycode) { case ALLEGRO_KEY_BACKSPACE : if(al_ustr_length(al_text) > 0) { al_ustr_remove_chr(al_text, al_ustr_length(al_text)-1); } break; case ALLEGRO_KEY_ENTER : detectingbutton->unclick(); break; } } else if(ev.type == ALLEGRO_EVENT_KEY_CHAR) { if(lenght_limit == true && (int)text.size() >= max_lenght) { return true; } unichar = ev.keyboard.unichar; if(unichar >= 32) { al_ustr_append_chr(al_text, unichar); } } } text = al_cstr_dup(al_text); text_width = al_get_text_width(font, text.c_str()) + 7; return true; }
/* Function: al_create_path_for_directory */ ALLEGRO_PATH *al_create_path_for_directory(const char *str) { ALLEGRO_PATH *path = al_create_path(str); if (al_ustr_length(path->filename)) { ALLEGRO_USTR *last = path->filename; path->filename = al_ustr_new(""); al_append_path_component(path, al_cstr(last)); al_ustr_free(last); } return path; }
void wz_def_draw_editbox(struct WZ_THEME* theme, float x, float y, float w, float h, int cursor_pos, ALLEGRO_USTR* text, int style) { WZ_DEF_THEME* thm = (WZ_DEF_THEME*)theme; int len = wz_get_text_pos(thm->font, text, w - 4); int cx,cy,cw,ch; int len2 = al_ustr_length(text); int offset; ALLEGRO_USTR_INFO info; ALLEGRO_USTR* token; ALLEGRO_COLOR border_col; ALLEGRO_COLOR text_col; len = len + 1 > len2 ? len2 : len + 1; offset = al_ustr_offset(text, len); token = al_ref_ustr(&info, text, 0, offset); border_col = thm->color1; text_col = thm->color2; if (style & WZ_STYLE_FOCUSED) { border_col = wz_scale_color(thm->color1, 1.5); } if (style & WZ_STYLE_DISABLED) { border_col = wz_scale_color(thm->color1, 0.5); text_col = wz_scale_color(thm->color2, 0.5); } wz_draw_3d_rectangle(x, y, x + w, y + h, 1, border_col, true); al_get_clipping_rectangle(&cx, &cy, &cw, &ch); al_set_clipping_rectangle(x + 2, y + 2, w - 4, h - 4); wz_draw_single_text(x + 2, y + 2, w - 4, h - 4, WZ_ALIGN_LEFT, WZ_ALIGN_CENTRE, text_col, thm->font, token); al_set_clipping_rectangle(cx, cy, cw, ch); if (style & WZ_STYLE_FOCUSED) { if (((int)(al_get_time() / 0.5f)) % 2 == 0) { float len; float halfheight; offset = al_ustr_offset(text, cursor_pos); token = al_ref_ustr(&info, text, 0, offset); len = al_get_ustr_width(thm->font, token); halfheight = al_get_font_line_height(thm->font) / 2.0f; al_draw_line(x + 2 + len, y + 2 + h / 2 - halfheight, x + 2 + len, y + 2 + h / 2 + halfheight, text_col, 1); } } }
/* Function: al_ustr_offset */ int al_ustr_offset(const ALLEGRO_USTR *us, int index) { int pos = 0; if (index < 0) index += al_ustr_length(us); while (index-- > 0) { if (!al_ustr_next(us, &pos)) return pos; } return pos; }
void wz_snap_editbox(WZ_EDITBOX* box) { WZ_WIDGET* wgt = (WZ_WIDGET*)box; ALLEGRO_FONT* font = wgt->theme->get_font(wgt->theme, 0); int len = al_ustr_length(box->text); int size = al_ustr_size(box->text); int scroll_offset = al_ustr_offset(box->text, box->scroll_pos); int cursor_offset; ALLEGRO_USTR_INFO info; ALLEGRO_USTR* text = al_ref_ustr(&info, box->text, scroll_offset, size); int max_rel_cursor_pos = wz_get_text_pos(font, text, wgt->w); if (box->cursor_pos < box->scroll_pos) { box->scroll_pos = box->cursor_pos; } if (box->cursor_pos > box->scroll_pos + max_rel_cursor_pos) { box->scroll_pos = box->cursor_pos - max_rel_cursor_pos; } if (box->cursor_pos > 0 && box->cursor_pos - box->scroll_pos < 1) { box->scroll_pos--; } if (box->cursor_pos > len) { box->cursor_pos = len; } if (box->cursor_pos < 0) { box->cursor_pos = 0; } scroll_offset = al_ustr_offset(box->text, box->scroll_pos); cursor_offset = al_ustr_offset(box->text, box->cursor_pos); text = al_ref_ustr(&info, box->text, scroll_offset, cursor_offset); if (al_get_ustr_width(font, text) > wgt->w) { box->scroll_pos++; } }
/* Function: wz_get_text_pos Parameters: text - the text you want to search x - the length you want to match Returns: The character position such that the text length of the string up to that character is as close as possible to the passed length. */ int wz_get_text_pos(ALLEGRO_FONT* font, ALLEGRO_USTR* text, float x) { int ii = 0; int len = al_ustr_length(text); float width = al_get_ustr_width(font, text); if(x > width) { return len + 1; } if(x < 0) { return 0; } else { float old_diff = x; float diff; ALLEGRO_USTR_INFO info; for(ii = 0; ii <= len; ii++) { int offset = al_ustr_offset(text, ii); const ALLEGRO_USTR* str = al_ref_ustr(&info, text, 0, offset); diff = fabs(x - al_get_ustr_width(font, str)); if(diff > old_diff) { return ii - 1; } old_diff = diff; } } return ii - 1; }
/* Test UTF-16 conversion. */ static void t50(void) { ALLEGRO_USTR *us; char utf8[] = "⅛-note: 𝅘𝅥𝅮, domino: 🁡"; uint16_t *utf16; size_t s; uint16_t little[8]; /* Only native byte order supported right now, so have to specify * elements as uint16_t and not as char. */ uint16_t utf16_ref[] = { 0x215b, 0x002d, 0x006e, 0x006f, 0x0074, 0x0065, 0x003a, 0x0020, 0xd834, 0xdd60, 0x002c, 0x0020, 0x0064, 0x006f, 0x006d, 0x0069, 0x006e, 0x006f, 0x003a, 0x0020, 0xd83c, 0xdc61, 0x0000}; uint16_t truncated[] = { 0x215b, 0x002d, 0x006e, 0x006f, 0x0074, 0x0065, 0x003a, 0x0000}; us = al_ustr_new_from_utf16(utf16_ref); CHECK(20 == al_ustr_length(us)); CHECK(0 == strcmp(utf8, al_cstr(us))); al_ustr_free(us); us = al_ustr_new(utf8); s = al_ustr_size_utf16(us); CHECK(46 == s); utf16 = malloc(s); al_ustr_encode_utf16(us, utf16, s); CHECK(0 == memcmp(utf16, utf16_ref, s)); free(utf16); s = al_ustr_encode_utf16(us, little, sizeof little); CHECK(16 == s); CHECK(0 == memcmp(truncated, little, s)); al_ustr_free(us); }
/* Print some text with a shadow. */ static void print(int x, int y, bool vertical, char const *format, ...) { va_list list; char message[1024]; ALLEGRO_COLOR color; int h; int j; va_start(list, format); vsnprintf(message, sizeof message, format, list); va_end(list); al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA); h = al_get_font_line_height(ex.myfont); for (j = 0; j < 2; j++) { if (j == 0) color = al_map_rgb(0, 0, 0); else color = al_map_rgb(255, 255, 255); if (vertical) { int i; ALLEGRO_USTR_INFO ui; const ALLEGRO_USTR *us = al_ref_cstr(&ui, message); for (i = 0; i < (int)al_ustr_length(us); i++) { ALLEGRO_USTR_INFO letter; al_draw_ustr(ex.myfont, color, x + 1 - j, y + 1 - j + h * i, 0, al_ref_ustr(&letter, us, al_ustr_offset(us, i), al_ustr_offset(us, i + 1))); } } else { al_draw_text(ex.myfont, color, x + 1 - j, y + 1 - j, 0, message); } } }
/* Title: Edit Box Section: Internal Function: wz_editbox_proc See also: <wz_widget_proc> */ int wz_editbox_proc(WZ_WIDGET* wgt, ALLEGRO_EVENT* event) { int ret = 1; WZ_EDITBOX* box = (WZ_EDITBOX*)wgt; switch (event->type) { case WZ_DRAW: { if (wgt->flags & WZ_STATE_HIDDEN) { ret = 0; } else { int size = al_ustr_size(box->text); int scroll_offset = al_ustr_offset(box->text, box->scroll_pos); ALLEGRO_USTR_INFO info; ALLEGRO_USTR* text = al_ref_ustr(&info, box->text, scroll_offset, size); int pos = box->cursor_pos - box->scroll_pos; int flags = 0; if(wgt->flags & WZ_STATE_DISABLED) flags = WZ_STYLE_DISABLED; else if(wgt->flags & WZ_STATE_HAS_FOCUS) flags = WZ_STYLE_FOCUSED; wgt->theme->draw_editbox(wgt->theme, wgt->local_x, wgt->local_y, wgt->w, wgt->h, pos, text, flags); } break; } case ALLEGRO_EVENT_MOUSE_BUTTON_DOWN: { if (wgt->flags & WZ_STATE_DISABLED) { ret = 0; } else if (event->mouse.button == 1 && wz_widget_rect_test(wgt, event->mouse.x, event->mouse.y)) { int len = al_ustr_length(box->text); ALLEGRO_USTR_INFO info; ALLEGRO_USTR* text = al_ref_ustr(&info, box->text, box->scroll_pos, len - 1); ALLEGRO_FONT* font = wgt->theme->get_font(wgt->theme, 0); wz_ask_parent_for_focus(wgt); box->cursor_pos = wz_get_text_pos(font, text, event->mouse.x - wgt->x) + box->scroll_pos; } else ret = 0; break; } #if (ALLEGRO_SUB_VERSION > 0) case ALLEGRO_EVENT_TOUCH_BEGIN: { if (wgt->flags & WZ_STATE_DISABLED) { ret = 0; } else if (wz_widget_rect_test(wgt, event->touch.x, event->touch.y)) { int len = al_ustr_length(box->text); ALLEGRO_USTR_INFO info; ALLEGRO_USTR* text = al_ref_ustr(&info, box->text, box->scroll_pos, len - 1); ALLEGRO_FONT* font = wgt->theme->get_font(wgt->theme, 0); wz_ask_parent_for_focus(wgt); box->cursor_pos = wz_get_text_pos(font, text, event->touch.x - wgt->x) + box->scroll_pos; } else ret = 0; break; } #endif case WZ_HANDLE_SHORTCUT: { wz_ask_parent_for_focus(wgt); break; } case WZ_DESTROY: { if(box->own) al_ustr_free(box->text); ret = 0; break; } case ALLEGRO_EVENT_KEY_CHAR: { int len; if(wgt->flags & WZ_STATE_DISABLED || !(wgt->flags & WZ_STATE_HAS_FOCUS)) { ret = 0; break; } else if(event->keyboard.modifiers & ALLEGRO_KEYMOD_CTRL || event->keyboard.modifiers & ALLEGRO_KEYMOD_ALT) { ret = 0; } len = al_ustr_length(box->text); if((int)(event->keyboard.unichar) > 31 && (int)(event->keyboard.unichar) != 127) { al_ustr_insert_chr(box->text, al_ustr_offset(box->text, box->cursor_pos), event->keyboard.unichar); box->cursor_pos++; } else { switch (event->keyboard.keycode) { case ALLEGRO_KEY_BACKSPACE: { if (len > 0 && box->cursor_pos > 0) { al_ustr_remove_chr(box->text, al_ustr_offset(box->text, box->cursor_pos - 1)); box->cursor_pos--; } break; } case ALLEGRO_KEY_DELETE: { if (len > 0 && box->cursor_pos < len) { al_ustr_remove_chr(box->text, al_ustr_offset(box->text, box->cursor_pos)); } break; } case ALLEGRO_KEY_LEFT: { if (box->cursor_pos > 0) { box->cursor_pos--; } else ret = 0; break; } case ALLEGRO_KEY_RIGHT: { if (box->cursor_pos < len) { box->cursor_pos++; } else ret = 0; break; } case ALLEGRO_KEY_HOME: { box->cursor_pos = 0; break; } case ALLEGRO_KEY_END: { len = al_ustr_length(box->text); box->cursor_pos = len; break; } case ALLEGRO_KEY_ENTER: { wz_trigger(wgt); break; } default: ret = 0; } } wz_snap_editbox(box); break; } case WZ_SET_CURSOR_POS: { box->cursor_pos = event->user.data3; wz_snap_editbox(box); } case WZ_SET_TEXT: { if(box->own) { al_ustr_assign(box->text, (ALLEGRO_USTR*)event->user.data3); } else box->text = (ALLEGRO_USTR*)event->user.data3; wz_snap_editbox(box); break; } case WZ_TRIGGER: { ALLEGRO_EVENT ev; wz_craft_event(&ev, WZ_TEXT_CHANGED, wgt, 0); al_emit_user_event(wgt->source, &ev, 0); break; } case ALLEGRO_EVENT_MOUSE_AXES: { if (wgt->flags & WZ_STATE_DISABLED) { ret = 0; } if (wz_widget_rect_test(wgt, event->mouse.x, event->mouse.y)) { wz_ask_parent_for_focus(wgt); } return wz_widget_proc(wgt, event); break; } default: ret = 0; } if (ret == 0) ret = wz_widget_proc(wgt, event); return ret; }
static void render(void) { ALLEGRO_COLOR white = al_map_rgba_f(1, 1, 1, 1); ALLEGRO_COLOR black = al_map_rgba_f(0, 0, 0, 1); ALLEGRO_COLOR red = al_map_rgba_f(1, 0, 0, 1); ALLEGRO_COLOR green = al_map_rgba_f(0, 0.5, 0, 1); ALLEGRO_COLOR blue = al_map_rgba_f(0.1, 0.2, 1, 1); ALLEGRO_COLOR purple = al_map_rgba_f(0.3, 0.1, 0.2, 1); int x, y, w, h, as, de, xpos, ypos; unsigned int index; int target_w, target_h; ALLEGRO_USTR_INFO info, sub_info; const ALLEGRO_USTR *u; ALLEGRO_USTR *tulip = al_ustr_new("Tulip"); ALLEGRO_USTR *dimension_text = al_ustr_new("Tulip"); ALLEGRO_USTR *vertical_text = al_ustr_new("Rose."); al_clear_to_color(white); al_hold_bitmap_drawing(true); al_draw_textf(ex.f1, black, 50, 20, 0, "Tulip (kerning)"); al_draw_textf(ex.f2, black, 50, 80, 0, "Tulip (no kerning)"); x = 50; y = 140; for (index = 0; index < al_ustr_length(dimension_text); index ++) { int cp = ustr_at(dimension_text, index); int bbx, bby, bbw, bbh; al_get_glyph_dimensions(ex.f2, cp, &bbx, &bby, &bbw, &bbh); al_draw_rectangle(x + bbx + 0.5, y + bby + 0.5, x + bbx + bbw - 0.5, y + bby + bbh - 0.5, blue, 1); al_draw_rectangle(x + 0.5, y + 0.5, x + bbx + bbw - 0.5, y + bby + bbh - 0.5, green, 1); al_draw_glyph(ex.f2, purple, x, y, cp); x += al_get_glyph_advance(ex.f2, cp, ALLEGRO_NO_KERNING); } al_draw_line(50.5, y+0.5, x+0.5, y+0.5, red, 1); al_draw_textf(ex.f2, black, x + 10, y, 0, "(dimensions)"); al_draw_textf(ex.f3, black, 50, 200, 0, "This font has a size of 12 pixels, " "the one above has 48 pixels."); al_hold_bitmap_drawing(false); al_hold_bitmap_drawing(true); al_draw_textf(ex.f3, red, 50, 220, 0, "The color can simply be changed.🐊← fallback glyph"); al_hold_bitmap_drawing(false); al_hold_bitmap_drawing(true); al_draw_textf(ex.f3, green, 50, 240, 0, "Some unicode symbols:"); al_draw_textf(ex.f3, green, 50, 260, 0, "%s", get_string("symbols1")); al_draw_textf(ex.f3, green, 50, 280, 0, "%s", get_string("symbols2")); al_draw_textf(ex.f3, green, 50, 300, 0, "%s", get_string("symbols3")); #define OFF(x) al_ustr_offset(u, x) #define SUB(x, y) al_ref_ustr(&sub_info, u, OFF(x), OFF(y)) u = al_ref_cstr(&info, get_string("substr1")); al_draw_ustr(ex.f3, green, 50, 320, 0, SUB(0, 6)); u = al_ref_cstr(&info, get_string("substr2")); al_draw_ustr(ex.f3, green, 50, 340, 0, SUB(7, 11)); u = al_ref_cstr(&info, get_string("substr3")); al_draw_ustr(ex.f3, green, 50, 360, 0, SUB(4, 11)); u = al_ref_cstr(&info, get_string("substr4")); al_draw_ustr(ex.f3, green, 50, 380, 0, SUB(0, 11)); al_draw_textf(ex.f5, black, 50, 395, 0, "forced monochrome"); /* Glyph rendering tests. */ al_draw_textf(ex.f3, red, 50, 410, 0, "Glyph adv Tu: %d, draw: ", al_get_glyph_advance(ex.f3, 'T', 'u')); x = 50; y = 425; for (index = 0; index < al_ustr_length(tulip); index ++) { int cp = ustr_at(tulip, index); /* Use al_get_glyph_advance for the stride, with no kerning. */ al_draw_glyph(ex.f3, red, x, y, cp); x += al_get_glyph_advance(ex.f3, cp, ALLEGRO_NO_KERNING); } x = 50; y = 440; /* First draw a red string using al_draw_text, that should be hidden * completely by the same text drawing in green per glyph * using al_draw_glyph and al_get_glyph_advance below. */ al_draw_ustr(ex.f3, red, x, y, 0, tulip); for (index = 0; index < al_ustr_length(tulip); index ++) { int cp = ustr_at(tulip, index); int ncp = (index < (al_ustr_length(tulip) - 1)) ? ustr_at(tulip, index + 1) : ALLEGRO_NO_KERNING; /* Use al_get_glyph_advance for the stride and apply kerning. */ al_draw_glyph(ex.f3, green, x, y, cp); x += al_get_glyph_advance(ex.f3, cp, ncp); } x = 50; y = 466; al_draw_ustr(ex.f3, red, x, y, 0, tulip); for (index = 0; index < al_ustr_length(tulip); index ++) { int cp = ustr_at(tulip, index); int bbx, bby, bbw, bbh; al_get_glyph_dimensions(ex.f3, cp, &bbx, &bby, &bbw, &bbh); al_draw_glyph(ex.f3, blue, x, y, cp); x += bbx + bbw; } x = 10; y = 30; for (index = 0; index < al_ustr_length(vertical_text); index ++) { int bbx, bby, bbw, bbh; int cp = ustr_at(vertical_text, index); /* Use al_get_glyph_dimensions for the height to apply. */ al_get_glyph_dimensions(ex.f3, cp, &bbx, &bby, &bbw, &bbh); al_draw_glyph(ex.f3, green, x, y, cp); y += bby; y += bbh; } x = 30; y = 30; for (index = 0; index < al_ustr_length(vertical_text); index ++) { int bbx, bby, bbw, bbh; int cp = ustr_at(vertical_text, index); /* Use al_get_glyph_dimensions for the height to apply, here bby is * omited for the wrong result. */ al_get_glyph_dimensions(ex.f3, cp, &bbx, &bby, &bbw, &bbh); al_draw_glyph(ex.f3, red, x, y, cp); y += bbh; } al_hold_bitmap_drawing(false); target_w = al_get_bitmap_width(al_get_target_bitmap()); target_h = al_get_bitmap_height(al_get_target_bitmap()); xpos = target_w - 10; ypos = target_h - 10; al_get_text_dimensions(ex.f4, "Allegro", &x, &y, &w, &h); as = al_get_font_ascent(ex.f4); de = al_get_font_descent(ex.f4); xpos -= w; ypos -= h; x += xpos; y += ypos; al_draw_rectangle(x, y, x + w - 0.5, y + h - 0.5, black, 0); al_draw_line(x+0.5, y + as + 0.5, x + w - 0.5, y + as + 0.5, black, 0); al_draw_line(x + 0.5, y + as + de + 0.5, x + w - 0.5, y + as + de + 0.5, black, 0); al_hold_bitmap_drawing(true); al_draw_textf(ex.f4, blue, xpos, ypos, 0, "Allegro"); al_hold_bitmap_drawing(false); al_hold_bitmap_drawing(true); al_draw_textf(ex.f3, black, target_w, 0, ALLEGRO_ALIGN_RIGHT, "%.1f FPS", ex.fps); al_draw_textf(ex.f3, black, 0, 0, 0, "%s: %d unicode ranges", font_file, ex.ranges_count); al_hold_bitmap_drawing(false); }