/* Function: al_ustr_set_chr */ size_t al_ustr_set_chr(ALLEGRO_USTR *us, int start_pos, int32_t c) { int32_t oldc; size_t oldw; size_t neww; int rc; oldc = al_ustr_get(us, start_pos); if (oldc == -2) return 0; oldw = al_utf8_width(oldc); neww = al_utf8_width(c); if (neww == 0) return 0; if (oldw > neww) rc = _al_bdelete(us, start_pos, oldw - neww); else if (neww > oldw) rc = _al_binsertch(us, start_pos, neww - oldw, '\0'); else rc = _AL_BSTR_OK; if (rc == _AL_BSTR_OK) return al_utf8_encode(_al_bdataofs(us, start_pos), c); else return 0; }
/* Test al_utf8_width. */ static void t17(void) { CHECK(al_utf8_width(0x000000) == 1); CHECK(al_utf8_width(0x00007f) == 1); CHECK(al_utf8_width(0x000080) == 2); CHECK(al_utf8_width(0x0007ff) == 2); CHECK(al_utf8_width(0x000800) == 3); CHECK(al_utf8_width(0x00ffff) == 3); CHECK(al_utf8_width(0x010000) == 4); CHECK(al_utf8_width(0x10ffff) == 4); /* These are illegal. */ CHECK(al_utf8_width(0x110000) == 0); CHECK(al_utf8_width(0xffffff) == 0); }
//splits a string by a character static int _split_string_by_char(const char *str, int ch, ALLEGRO_USTR *result[], int result_len) { //start from the string beginning int pos = 0, next_pos; //count of sub-strings found int count = 0; //temp allegro string ALLEGRO_USTR_INFO temp_info; ALLEGRO_USTR *temp = al_ref_cstr(&temp_info, str); //iterate until the end of string for(;;) { //find the character next_pos = al_ustr_find_chr(temp, pos, ch); //if not found, end if (next_pos == -1) break; //add a string; if no more strings can be added, return if (!_add_substring(temp, pos, next_pos, result, result_len, &count)) goto END; //continue after the character pos = next_pos + al_utf8_width(ch); } //set the remainder of the string to be the last string in the array _add_substring(temp, pos, al_ustr_size(temp), result, result_len, &count); END: return count; }
//returns the filepath of a resource static ALLEGRO_USTR *_get_resource_filepath(const ALLEGRO_USTR *skin_filepath, const char *resource_filename) { ALLEGRO_USTR *result; int pos, end_pos; ALLEGRO_USTR *temp; ALLEGRO_USTR_INFO temp_info; //duplicate the resource filepath in order to replace '\' by '/' result = al_ustr_dup(skin_filepath); //replace '\' with '/' al_ustr_find_replace_cstr(result, 0, "\\", "/"); //find the end of the string end_pos = al_ustr_size(result); //find the last occurrence of '/' pos = al_ustr_rfind_chr(result, end_pos, '/'); //find the position after the '/' pos += al_utf8_width('/'); //the replace function needs a ustr temp = al_ref_cstr(&temp_info, resource_filename); //replace the string after the '/' with the resource filename al_ustr_replace_range(result, pos, end_pos, temp); return result; }
/* Function: al_ustr_find_set */ int al_ustr_find_set(const ALLEGRO_USTR *us, int start_pos, const ALLEGRO_USTR *accept) { int rc; int32_t c, d; int pos; int set_pos; /* Fast path for ASCII characters. */ if (all_ascii(accept)) { rc = _al_binchr(us, start_pos, accept); return (rc == _AL_BSTR_ERR) ? -1 : rc; } /* Non-ASCII. */ pos = 0; while ((c = al_ustr_get(us, pos)) != -1) { if (c == -2) { /* Invalid byte sequence. */ pos++; continue; } set_pos = 0; while ((d = al_ustr_get_next(accept, &set_pos)) != -1) { if (c == d) return pos; } pos += al_utf8_width(c); } return -1; }
/* Function: al_ustr_remove_chr */ bool al_ustr_remove_chr(ALLEGRO_USTR *us, int pos) { int32_t c; size_t w; c = al_ustr_get(us, pos); if (c < 0) return false; w = al_utf8_width(c); return _al_bdelete(us, pos, w) == _AL_BSTR_OK; }
/* Function: al_ustr_insert_chr */ size_t al_ustr_insert_chr(ALLEGRO_USTR *us, int pos, int32_t c) { uint32_t uc = c; size_t sz; if (uc < 128) { return (_al_binsertch(us, pos, 1, uc) == _AL_BSTR_OK) ? 1 : 0; } sz = al_utf8_width(c); if (_al_binsertch(us, pos, sz, '\0') == _AL_BSTR_OK) { return al_utf8_encode(_al_bdataofs(us, pos), c); } return 0; }
/* Function: al_ustr_get_next */ int32_t al_ustr_get_next(const ALLEGRO_USTR *us, int *pos) { int32_t c = al_ustr_get(us, *pos); if (c >= 0) { (*pos) += al_utf8_width(c); return c; } if (c == -1) { /* Past end. */ return c; } /* Some invalid byte sequence. */ al_ustr_next(us, pos); return c; }
void TextEntry::on_key_down(const ALLEGRO_KEYBOARD_EVENT & event) { if (is_disabled()) return; switch (event.keycode) { case ALLEGRO_KEY_LEFT: al_ustr_prev(text, &cursor_pos); break; case ALLEGRO_KEY_RIGHT: al_ustr_next(text, &cursor_pos); break; case ALLEGRO_KEY_HOME: cursor_pos = 0; break; case ALLEGRO_KEY_END: cursor_pos = al_ustr_size(text); break; case ALLEGRO_KEY_DELETE: al_ustr_remove_chr(text, cursor_pos); break; case ALLEGRO_KEY_BACKSPACE: if (al_ustr_prev(text, &cursor_pos)) al_ustr_remove_chr(text, cursor_pos); break; default: if (event.unichar >= ' ') { al_ustr_insert_chr(text, cursor_pos, event.unichar); cursor_pos += al_utf8_width(event.unichar); } break; } maybe_scroll(); dialog->request_draw(); }
int init_bitmaps(Board *b){ // will load bitmaps from folders named 0, 1,..., 7 // inside the folder "icons", each containing 8 square bitmaps int i,j, k=0; char pathname[1000]; ALLEGRO_PATH *path; ALLEGRO_BITMAP *dispbuf = al_get_target_bitmap(); al_set_target_bitmap(NULL); // this is a workaround for android -- try removing later #ifdef ALLEGRO_ANDROID al_android_set_apk_file_interface(); #endif al_set_target_bitmap(dispbuf); for(i=0;i<b->h+1;i++){ for(j=0;j<b->n; j++){ al_utf8_encode(symbol_char[i][j], BF_CODEPOINT_START+ j + i*b->n); symbol_char[i][j][al_utf8_width(BF_CODEPOINT_START+ j + i*b->n)] = '\0'; } } // create buttons // xxx todo: improve these default_font = al_load_font(DEFAULT_FONT_FILE, 16, 0); if(!default_font) errlog("Error loading default font"); b->info_text_bmp = NULL; b->info_panel.bmp = NULL; // if this fails, buttons will be created anyway at update_bitmaps b->button_bmp[0] = al_load_bitmap("buttons/light-bulb.png"); b->button_bmp[1] = al_load_bitmap("buttons/question.png"); b->button_bmp[2] = al_load_bitmap("buttons/gear.png"); b->button_bmp[3] = al_load_bitmap("buttons/undo.png"); if(b->type_of_tiles == 2) return init_bitmaps_classic(b); if(b->type_of_tiles == 1){ // use bitmaps #ifndef ALLEGRO_ANDROID path = al_get_standard_path(ALLEGRO_RESOURCES_PATH); al_path_cstr(path, '/'); #else path = al_create_path(""); #endif for(j=0; j<b->h; j++){ for(k=0; k<b->n; k++){ snprintf(pathname, 999, "%sicons/%d/%d.png", al_path_cstr(path, '/'), j, k); basic_bmp[j][k] = al_load_bitmap(pathname); if(!basic_bmp[j][k]){ errlog("Error loading %s.", pathname); unload_basic_bmps(b, j,k-1); al_destroy_path(path); return -1; } } } al_destroy_path(path); } // create symbols (alternatively we could load these from files!)) symbol_bmp[SYM_FORBIDDEN] = al_create_bitmap(256, 256); symbol_bmp[SYM_SWAPPABLE] = al_create_bitmap(3*256 + 2*b->clue_unit_space, 256); symbol_bmp[SYM_ONE_SIDE] = al_create_bitmap(256, 256); symbol_bmp[SYM_ONLY_ONE] = al_create_bitmap(256, 3*256); if( (!symbol_bmp[SYM_FORBIDDEN]) || (!symbol_bmp[SYM_SWAPPABLE]) || (!symbol_bmp[SYM_ONE_SIDE]) || !symbol_bmp[SYM_ONLY_ONE]){ fprintf(stderr, "Error creating bitmap.\n"); return -1; } al_set_target_bitmap(symbol_bmp[SYM_FORBIDDEN]); al_clear_to_color(NULL_COLOR); al_draw_line(1, 1, 254, 254, al_map_rgba_f(1,0,0,0.5),4); al_draw_line(1, 254, 254, 1, al_map_rgba_f(1,0,0,0.5),4); al_set_target_bitmap(symbol_bmp[SYM_SWAPPABLE]); al_clear_to_color(NULL_COLOR); al_draw_line(256*0.7,256*0.9, 256*(3-0.7),256*0.9, al_map_rgba_f(1,0,0,0.5), 2); al_draw_filled_triangle(256*0.5,256*0.9, 256*0.7,256, 256*0.7, 256*0.8, al_map_rgba_f(1,0,0,0.35)); al_set_target_bitmap(symbol_bmp[SYM_ONE_SIDE]); al_clear_to_color(NULL_COLOR); al_draw_filled_circle(256/2, 256/2, 0.03*256, WHITE_COLOR); al_draw_filled_circle(256/2 - 0.2*256, 256/2, 0.03*256, WHITE_COLOR); al_draw_filled_circle(256/2 + 0.2*256, 256/2, 0.03*256, WHITE_COLOR); al_set_target_bitmap(symbol_bmp[SYM_ONLY_ONE]); al_clear_to_color(NULL_COLOR); al_draw_filled_triangle(256*0.3, 256, 256*0.7, 256, 256*0.5, 256*0.7, al_map_rgba_f(1,0,0,0.5)); al_draw_filled_triangle(256*0.3, 256, 256*0.7, 256, 256*0.5, 256*1.3, al_map_rgba_f(1,0,0,0.5)); al_draw_line(256*0.5, 256*0.8, 256*0.5, 256*1.2, WHITE_COLOR, 3); al_set_target_bitmap(dispbuf); return 0; }
/* [nd_gtk thread] */ static gboolean create_gtk_file_dialog(gpointer data) { GTK_FILE_DIALOG_MESSAGE *msg = data; ALLEGRO_DISPLAY *display = msg->display; ALLEGRO_NATIVE_DIALOG *fd = msg->dialog; bool save = fd->flags & ALLEGRO_FILECHOOSER_SAVE; gint result; GtkWidget *window; window = gtk_file_chooser_dialog_new(al_cstr(fd->title), NULL, save ? GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, save ? GTK_STOCK_SAVE : GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); _al_gtk_make_transient(display, window); if (fd->fc_initial_path) { gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(window), al_path_cstr(fd->fc_initial_path, ALLEGRO_NATIVE_PATH_SEP)); } if (fd->flags & ALLEGRO_FILECHOOSER_MULTIPLE) gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(window), true); /* FIXME: Move all this filter parsing stuff into a common file. */ if (al_ustr_size(fd->fc_patterns) > 0) { GtkFileFilter* filter = gtk_file_filter_new(); int start = 0; int end = 0; bool is_mime_type = false; while (true) { int32_t c = al_ustr_get(fd->fc_patterns, end); if (c < 0 || c == ';') { if (end - start > 0) { ALLEGRO_USTR* pattern = al_ustr_dup_substr(fd->fc_patterns, start, end); if (is_mime_type) { gtk_file_filter_add_mime_type(filter, al_cstr(pattern)); } else { gtk_file_filter_add_pattern(filter, al_cstr(pattern)); } al_ustr_free(pattern); } start = end + 1; is_mime_type = false; } if (c == '/') is_mime_type = true; if (c < 0) break; end += al_utf8_width(c); } gtk_file_filter_set_name(filter, "All supported files"); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(window), filter); } result = gtk_dialog_run(GTK_DIALOG(window)); if (result == GTK_RESPONSE_ACCEPT) { GSList* filenames = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(window)); int i; GSList* iter; fd->fc_path_count = g_slist_length(filenames); fd->fc_paths = al_malloc(fd->fc_path_count * sizeof(void *)); for (i = 0, iter = filenames; i < (int)fd->fc_path_count; i++, iter = g_slist_next(iter)) { fd->fc_paths[i] = al_create_path((const char*)iter->data); g_free(iter->data); } g_slist_free(filenames); } gtk_widget_destroy(window); ASSERT(fd->async_queue); g_async_queue_push(fd->async_queue, ACK_CLOSED); return FALSE; }