/* Test that we can make strings which reference (parts of) other strings. */ static void t5(void) { ALLEGRO_USTR *us1; const ALLEGRO_USTR *us2; ALLEGRO_USTR_INFO us2_info; us1 = al_ustr_new("aábdðeéfghiíjklmnoóprstuúvxyýþæö"); us2 = al_ref_ustr(&us2_info, us1, 36, 36 + 4); CHECK(0 == memcmp(al_cstr(us2), "þæ", al_ustr_size(us2))); /* Start pos underflow */ us2 = al_ref_ustr(&us2_info, us1, -10, 7); CHECK(0 == memcmp(al_cstr(us2), "aábdð", al_ustr_size(us2))); /* End pos overflow */ us2 = al_ref_ustr(&us2_info, us1, 36, INT_MAX); CHECK(0 == memcmp(al_cstr(us2), "þæö", al_ustr_size(us2))); /* Start > end */ us2 = al_ref_ustr(&us2_info, us1, 36 + 4, 36); CHECK(0 == al_ustr_size(us2)); al_ustr_free(us1); }
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); } } }
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++; } }
//return the new start int wz_find_eol(ALLEGRO_USTR* text, ALLEGRO_FONT* font, float max_width, int start, int* end) { int a, b; int first = 1; int last = 0; a = start; while(1) { ALLEGRO_USTR_INFO info; ALLEGRO_USTR* token; float len; /* Find the end of current token */ b = al_ustr_find_set_cstr(text, a, "\t\n "); if(b == -1) //found nothing { b = al_ustr_size(text); //this is the last whole word last = 1; } /* Check to see if the token fits */ token = al_ref_ustr(&info, text, start, b); len = al_get_ustr_width(font, token); if (len < max_width || first) { if(last) { *end = b + 1; return -1; } } else //we return the last num { *end = a - 1; return a; } /* Check what character we found */ { int character = al_ustr_get(text, b); if(character == '\n') { *end = b; return b + 1; } } a = b + 1; first = 0; } }
/* [gtk thread] */ static gboolean create_native_message_box(gpointer data) { Msg *msg = data; ALLEGRO_DISPLAY *display = msg->display; ALLEGRO_NATIVE_DIALOG *fd = msg->dialog; GtkWidget *window; /* Create a new file selection widget */ GtkMessageType type = GTK_MESSAGE_INFO; GtkButtonsType buttons = GTK_BUTTONS_OK; if (fd->flags & ALLEGRO_MESSAGEBOX_YES_NO) type = GTK_MESSAGE_QUESTION; if (fd->flags & ALLEGRO_MESSAGEBOX_QUESTION) type = GTK_MESSAGE_QUESTION; if (fd->flags & ALLEGRO_MESSAGEBOX_WARN) type = GTK_MESSAGE_WARNING; if (fd->flags & ALLEGRO_MESSAGEBOX_ERROR) type = GTK_MESSAGE_ERROR; if (fd->flags & ALLEGRO_MESSAGEBOX_YES_NO) buttons = GTK_BUTTONS_YES_NO; if (fd->flags & ALLEGRO_MESSAGEBOX_OK_CANCEL) buttons = GTK_BUTTONS_OK_CANCEL; if (fd->mb_buttons) buttons = GTK_BUTTONS_NONE; window = gtk_message_dialog_new(NULL, 0, type, buttons, "%s", al_cstr(fd->mb_heading)); gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(window), "%s", al_cstr(fd->mb_text)); make_transient(display, window); if (fd->mb_buttons) { int i = 1; int pos = 0; while (1) { int next = al_ustr_find_chr(fd->mb_buttons, pos, '|'); int pos2 = next; if (next == -1) pos2 = al_ustr_size(fd->mb_buttons); ALLEGRO_USTR_INFO info; const ALLEGRO_USTR *button_text; button_text = al_ref_ustr(&info, fd->mb_buttons, pos, pos2); pos = pos2 + 1; char buffer[256]; al_ustr_to_buffer(button_text, buffer, sizeof buffer); gtk_dialog_add_button(GTK_DIALOG(window), buffer, i++); if (next == -1) break; } } gtk_window_set_title(GTK_WINDOW(window), al_cstr(fd->title)); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(dialog_destroy), fd); g_signal_connect(G_OBJECT(window), "response", G_CALLBACK(msgbox_response), fd); g_signal_connect_swapped(G_OBJECT(window), "response", G_CALLBACK(gtk_widget_destroy), window); gtk_widget_show(window); return FALSE; }
/* _find_executable_file: * Helper function: searches path and current directory for executable. * Returns 1 on succes, 0 on failure. */ static ALLEGRO_PATH *_find_executable_file(const char *filename) { char *env; /* If filename has an explicit path, search current directory */ if (strchr(filename, '/')) { if (filename[0] == '/') { /* Full path; done */ return al_create_path(filename); } else { struct stat finfo; char pathname[1024]; /* Prepend current directory */ ALLEGRO_PATH *path = al_get_current_directory(); al_append_path_component(path, filename); if ((stat(pathname, &finfo)==0) && (!S_ISDIR (finfo.st_mode))) { return path; } } } /* If filename has no explicit path, but we do have $PATH, search * there */ else if ((env = getenv("PATH"))) { struct stat finfo; ALLEGRO_USTR *us = al_ustr_new(env); int start_pos = 0; while (start_pos >= 0) { int next_start_pos = al_ustr_find_chr(us, start_pos + 1, ':'); int end_pos = next_start_pos; if (next_start_pos < 0) end_pos = al_ustr_size(us); ALLEGRO_USTR_INFO info; ALLEGRO_USTR *sub = al_ref_ustr(&info, us, start_pos, end_pos); ALLEGRO_PATH *path = al_create_path_for_directory(al_cstr(sub)); al_append_path_component(path, filename); if (stat(al_path_cstr(path, '/'), &finfo) == 0 && !S_ISDIR (finfo.st_mode)) { return path; } start_pos = next_start_pos; } } return NULL; }
/* Function: wz_draw_multi_text Draws multiple lines of text, wrapping it as necessary */ void wz_draw_multi_text(float x, float y, float w, float h, int halign, int valign, ALLEGRO_COLOR color, ALLEGRO_FONT* font, ALLEGRO_USTR* text) { float cur_y = y; float text_height = al_get_font_line_height(font); float total_height = 0; if (valign == WZ_ALIGN_BOTTOM || valign == WZ_ALIGN_CENTRE) { int ret = 0; do { int start = ret; int end; ret = wz_find_eol(text, font, w, start, &end); total_height += text_height; } while (ret > 0); } if (valign == WZ_ALIGN_BOTTOM) { cur_y = y + h - total_height; } else if (valign == WZ_ALIGN_CENTRE) { cur_y = y + (h - total_height) / 2; } { int ret = 0; do { int start = ret; int end; ret = wz_find_eol(text, font, w, start, &end); { ALLEGRO_USTR_INFO info; ALLEGRO_USTR* token = al_ref_ustr(&info, text, start, end); wz_draw_single_text(x, cur_y, w, h, halign, WZ_ALIGN_TOP, color, font, token); } cur_y += text_height; } while (ret > 0); } }
/* Test al_ustr_append with aliased strings. */ static void t9(void) { ALLEGRO_USTR *us1; ALLEGRO_USTR_INFO us2_info; const ALLEGRO_USTR *us2; /* Append a string to itself. */ us1 = al_ustr_new("aábdðeéfghiíjklm"); CHECK(al_ustr_append(us1, us1)); CHECK(0 == strcmp(al_cstr(us1), "aábdðeéfghiíjklmaábdðeéfghiíjklm")); al_ustr_free(us1); /* Append a substring of a string to itself. */ us1 = al_ustr_new("aábdðeéfghiíjklm"); us2 = al_ref_ustr(&us2_info, us1, 5, 5 + 11); /* ð...í */ CHECK(al_ustr_append(us1, us2)); CHECK(0 == strcmp(al_cstr(us1), "aábdðeéfghiíjklmðeéfghií")); al_ustr_free(us1); }
/* 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; }
/* 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; }