/** adds or sets a color of a skin. @param skin skin to set the color of. @param wgt widget name (UTF-8 string). @param res resource name (UTF-8 string). @param val resource value. @return non-zero on success, zero on failure. */ int algui_set_skin_color(ALGUI_SKIN *skin, const char *wgt, const char *res, ALLEGRO_COLOR color) { ALLEGRO_USTR *temp; unsigned char red, green, blue, alpha; int result; //convert the color to a string al_unmap_rgba(color, &red, &green, &blue, &alpha); temp = al_ustr_newf("%ui, %ui, %ui, %ui", (unsigned int)red, (unsigned int)green, (unsigned int)blue, (unsigned int)alpha); //set the skin result = algui_set_skin_str(skin, wgt, res, al_cstr(temp)); //free the temp string al_ustr_free(temp); return result; }
/* Output message to ANSI log. */ static void wlog_do_append_native_text_log_ansi(ALLEGRO_NATIVE_DIALOG *textlog) { int index; CHARFORMATA format; memset(&format, 0, sizeof(format)); format.cbSize = sizeof(format); format.dwMask = CFM_COLOR; format.crTextColor = RGB(128, 255, 128); index = GetWindowTextLength(textlog->tl_textview); SendMessageA(textlog->tl_textview, EM_SETSEL, (WPARAM)index, (LPARAM)index); SendMessageA(textlog->tl_textview, EM_SETCHARFORMAT, (WPARAM)SCF_SELECTION, (LPARAM)&format); SendMessageA(textlog->tl_textview, EM_REPLACESEL, 0, (LPARAM)al_cstr(textlog->tl_pending_text)); al_ustr_truncate(textlog->tl_pending_text, 0); textlog->tl_have_pending = false; }
static bool ljoy_detect_device_name(int num, ALLEGRO_USTR *device_name) { char key[80]; const char *value; struct stat stbuf; al_ustr_truncate(device_name, 0); snprintf(key, sizeof(key), "device%d", num); value = al_get_config_value(al_get_system_config(), "joystick", key); if (value) al_ustr_assign_cstr(device_name, value); if (al_ustr_size(device_name) == 0) al_ustr_appendf(device_name, "/dev/input/event%d", num); return (stat(al_cstr(device_name), &stbuf) == 0); }
/* Event callbacks * */ void allua_keyboard_event_callback(lua_State * L, ALLEGRO_EVENT * event) { Set_literal("keycode", event->keyboard.keycode, -3); allua_pushdisplay(L, event->keyboard.display); lua_setfield(L, -2, "display"); if (event->type == ALLEGRO_EVENT_KEY_CHAR) { const char *cstr; ALLEGRO_USTR *us = al_ustr_new(""); al_ustr_append_chr(us, event->keyboard.unichar); cstr = al_cstr(us); lua_pushstring(L, cstr); lua_setfield(L, -2, "string"); Set_literal("unichar", event->keyboard.unichar, -3); Set_literal("modifiers", event->keyboard.modifiers, -3); lua_pushboolean(L, event->keyboard.repeat); lua_setfield(L, -2, "repeated"); } }
/* [gtk thread] */ static gboolean create_native_text_log(gpointer data) { Msg *msg = data; ALLEGRO_NATIVE_DIALOG *textlog = msg->dialog; /* Create a new text log window. */ GtkWidget *top = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(top), 640, 480); gtk_window_set_title(GTK_WINDOW(top), al_cstr(textlog->title)); if (textlog->flags & ALLEGRO_TEXTLOG_NO_CLOSE) { gtk_window_set_deletable(GTK_WINDOW(top), false); } else { g_signal_connect(G_OBJECT(top), "key-press-event", G_CALLBACK(textlog_key_press), textlog); } g_signal_connect(G_OBJECT(top), "delete-event", G_CALLBACK(textlog_delete), textlog); g_signal_connect(G_OBJECT(top), "destroy", G_CALLBACK(dialog_destroy), textlog); GtkWidget *scroll = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(top), scroll); GtkWidget *view = gtk_text_view_new(); gtk_text_view_set_editable(GTK_TEXT_VIEW(view), false); if (textlog->flags & ALLEGRO_TEXTLOG_MONOSPACE) { PangoFontDescription *font_desc; font_desc = pango_font_description_from_string("Monospace"); gtk_widget_modify_font(view, font_desc); pango_font_description_free(font_desc); } gtk_container_add(GTK_CONTAINER(scroll), view); gtk_widget_show(view); gtk_widget_show(scroll); gtk_widget_show(top); textlog->window = top; textlog->tl_textview = view; ASSERT(textlog->async_queue); g_async_queue_push(textlog->async_queue, ACK_OPENED); return FALSE; }
static ALLEGRO_FS_ENTRY *fs_apk_create_entry(const char *path) { ALLEGRO_FS_ENTRY_APK *e; ALLEGRO_USTR *us; e = al_calloc(1, sizeof *e); if (!e) return NULL; e->fs_entry.vtable = &fs_apk_vtable; us = apply_cwd(path); e->path = al_create_path(al_cstr(us)); al_ustr_free(us); if (!e->path) { al_free(e); return NULL; } e->path_cstr = al_path_cstr(e->path, '/'); return &e->fs_entry; }
/* A helper function for al_clone_menu() and al_clone_menu_for_popup(). * Note that only the root menu is created as a "popup" (if popup == TRUE). */ static ALLEGRO_MENU *clone_menu(ALLEGRO_MENU *menu, bool popup) { ALLEGRO_MENU *clone = NULL; size_t i; if (menu) { clone = popup ? al_create_popup_menu() : al_create_menu(); for (i = 0; i < _al_vector_size(&menu->items); ++i) { const ALLEGRO_MENU_ITEM *item = *(ALLEGRO_MENU_ITEM **)_al_vector_ref(&menu->items, i); ALLEGRO_BITMAP *icon = item->icon; if (icon) icon = al_clone_bitmap(icon); al_append_menu_item(clone, item->caption ? al_cstr(item->caption) : NULL, item->id, item->flags, icon, al_clone_menu(item->popup)); } } return clone; }
/* [gtk thread] */ static gboolean create_native_file_dialog(gpointer data) { Msg *msg = data; ALLEGRO_DISPLAY *display = msg->display; ALLEGRO_NATIVE_DIALOG *fd = msg->dialog; GtkWidget *window; /* Create a new file selection widget */ window = gtk_file_selection_new(al_cstr(fd->title)); make_transient(display, window); /* Connect the destroy signal */ g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(dialog_destroy), fd); /* Connect the ok_button */ g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(window)->ok_button), "clicked", G_CALLBACK(filesel_ok), (gpointer) window); /* Connect both buttons to gtk_widget_destroy */ g_signal_connect_swapped(GTK_FILE_SELECTION(window)->ok_button, "clicked", G_CALLBACK(gtk_widget_destroy), window); g_signal_connect_swapped(GTK_FILE_SELECTION(window)->cancel_button, "clicked", G_CALLBACK(gtk_widget_destroy), window); g_object_set_data(G_OBJECT(GTK_FILE_SELECTION(window)->ok_button), "ALLEGRO_NATIVE_DIALOG", fd); if (fd->fc_initial_path) { gtk_file_selection_set_filename(GTK_FILE_SELECTION(window), al_path_cstr(fd->fc_initial_path, '/')); } if (fd->flags & ALLEGRO_FILECHOOSER_MULTIPLE) gtk_file_selection_set_select_multiple(GTK_FILE_SELECTION(window), true); gtk_widget_show(window); return FALSE; }
/* 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); }
/* An ALLEGRO_MENU_INFO structure represents a heirarchy of menus. This function * recursively steps through it and builds the entire menu. */ static ALLEGRO_MENU_INFO *parse_menu_info(ALLEGRO_MENU *parent, ALLEGRO_MENU_INFO *info) { ASSERT(parent); ASSERT(info); /* The end of the menu is marked by a NULL caption and an id of 0. */ while (info->caption || info->id) { if (!info->caption) { /* A separator */ al_append_menu_item(parent, NULL, 0, 0, NULL, NULL); ++info; } else if (strlen(info->caption) > 2 && !strncmp("->", info->caption + strlen(info->caption) - 2, 2)) { /* An item with a sub-menu has a -> marker as part of its caption. * (e.g., "File->"). */ ALLEGRO_MENU *menu = al_create_menu(); if (menu) { /* Strip the -> mark off the end. */ ALLEGRO_USTR *s = al_ustr_new(info->caption); al_ustr_remove_range(s, al_ustr_size(s) - 2, al_ustr_size(s)); al_append_menu_item(parent, al_cstr(s), info->id, 0, NULL, menu); info = parse_menu_info(menu, info + 1); al_ustr_free(s); } } else { /* Just ar regular item */ al_append_menu_item(parent, info->caption, info->id, info->flags, info->icon, NULL); ++info; } } return info + 1; }
/* Function: al_is_path_present */ bool al_is_path_present(const ALLEGRO_PATH *path) { ALLEGRO_USTR *ustr; bool rc; ASSERT(path); ustr = al_ustr_new(""); path_to_ustr(path, ALLEGRO_NATIVE_PATH_SEP, ustr); /* Windows' stat() doesn't like the slash at the end of the path when * the path is pointing to a directory. There are other places which * might require the same fix. */ #ifdef ALLEGRO_WINDOWS if (al_ustr_has_suffix_cstr(ustr, "\\")) { al_ustr_truncate(ustr, al_ustr_size(ustr) - 1); } #endif rc = al_filename_exists(al_cstr(ustr)); al_ustr_free(ustr); return rc; }
/* [gtk thread] */ static gboolean do_append_native_text_log(gpointer data) { ALLEGRO_NATIVE_DIALOG *textlog = data; al_lock_mutex(textlog->tl_text_mutex); GtkTextView *tv = GTK_TEXT_VIEW(textlog->tl_textview); GtkTextBuffer *buffer = gtk_text_view_get_buffer(tv); GtkTextIter iter; GtkTextMark *mark; gtk_text_buffer_get_end_iter(buffer, &iter); gtk_text_buffer_insert(buffer, &iter, al_cstr(textlog->tl_pending_text), -1); mark = gtk_text_buffer_create_mark(buffer, NULL, &iter, FALSE); gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(textlog->tl_textview), mark); gtk_text_buffer_delete_mark(buffer, mark); al_ustr_truncate(textlog->tl_pending_text, 0); textlog->tl_have_pending = false; al_unlock_mutex(textlog->tl_text_mutex); return FALSE; }
//converts a string to color static int _string_to_color(const char *str, ALLEGRO_COLOR *color) { ALLEGRO_USTR *result[4]; unsigned int red, green, blue, alpha; int count, ok = 0; //if the string is null, the result is invalid if (!str) return 0; //split the string by ',' count = _split_string_by_char(str, ',', result, 4); switch (count) { //read red, green, blue case 3: _string_to_uint(al_cstr(result[0]), &red); _string_to_uint(al_cstr(result[1]), &green); _string_to_uint(al_cstr(result[2]), &blue); *color = al_map_rgb(red, green, blue); ok = 1; break; //read red, green, blue, alpha case 4: _string_to_uint(al_cstr(result[0]), &red); _string_to_uint(al_cstr(result[1]), &green); _string_to_uint(al_cstr(result[2]), &blue); _string_to_uint(al_cstr(result[3]), &alpha); *color = al_map_rgba(red, green, blue, alpha); ok = 1; break; } //free the strings _free_string_array(result, count); return ok; }
/* Test al_ustr_set_chr. */ static void t42(void) { ALLEGRO_USTR *us = al_ustr_new("abcdef"); /* Same size (ASCII). */ CHECK(al_ustr_set_chr(us, 1, 'B') == 1); CHECK(0 == strcmp(al_cstr(us), "aBcdef")); CHECK(6 == al_ustr_size(us)); /* Enlarge to 2-bytes. */ CHECK(al_ustr_set_chr(us, 1, U_beta) == 2); CHECK(0 == strcmp(al_cstr(us), "aβcdef")); CHECK(7 == al_ustr_size(us)); /* Enlarge to 3-bytes. */ CHECK(al_ustr_set_chr(us, 5, U_1d08) == 3); CHECK(0 == strcmp(al_cstr(us), "aβcdᴈf")); CHECK(9 == al_ustr_size(us)); /* Reduce to 2-bytes. */ CHECK(al_ustr_set_chr(us, 5, U_schwa) == 2); CHECK(0 == strcmp(al_cstr(us), "aβcdəf")); CHECK(8 == al_ustr_size(us)); /* Set at end of string. */ CHECK(al_ustr_set_chr(us, al_ustr_size(us), U_1ff7) == 3); CHECK(0 == strcmp(al_cstr(us), "aβcdəfῷ")); CHECK(11 == al_ustr_size(us)); /* Set past end of string. */ CHECK(al_ustr_set_chr(us, al_ustr_size(us) + 2, U_2051) == 3); CHECK(0 == memcmp(al_cstr(us), "aβcdəfῷ\0\0⁑", 16)); CHECK(16 == al_ustr_size(us)); /* Set before start of string (not allowed). */ CHECK(al_ustr_set_chr(us, -1, U_2051) == 0); CHECK(16 == al_ustr_size(us)); al_ustr_free(us); }
/* [gtk thread] */ static GtkWidget *build_menu_item(ALLEGRO_MENU_ITEM *aitem) { GtkWidget *gitem; if (!aitem->caption) { gitem = gtk_separator_menu_item_new(); } else { ALLEGRO_USTR *caption = al_ustr_dup(aitem->caption); /* convert & to _ using unprintable chars as placeholders */ al_ustr_find_replace_cstr(caption, 0, "_", "\x01\x02"); al_ustr_find_replace_cstr(caption, 0, "&", "_"); al_ustr_find_replace_cstr(caption, 0, "\x01\x02", "__"); if (aitem->flags & ALLEGRO_MENU_ITEM_CHECKBOX) { gitem = gtk_check_menu_item_new_with_mnemonic(al_cstr(caption)); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gitem), aitem->flags & ALLEGRO_MENU_ITEM_CHECKED); g_signal_connect_swapped (gitem, "toggled", G_CALLBACK(checkbox_on_toggle), (gpointer) aitem); } else { /* always create an image menu item, in case the user ever sets an icon */ gitem = gtk_image_menu_item_new_with_mnemonic(al_cstr(caption)); if (aitem->icon) { const int w = al_get_bitmap_width(aitem->icon), h = al_get_bitmap_height(aitem->icon); const int stride = w * 4; int x, y, i; GdkPixbuf *pixbuf; uint8_t *data = al_malloc(stride * h); if (data) { for (y = 0, i = 0; y < h; ++y) { for (x = 0; x < w; ++x, i += 4) { al_unmap_rgba(al_get_pixel(aitem->icon, x, y), &data[i], &data[i + 1], &data[i + 2], &data[i + 3] ); } } pixbuf = gdk_pixbuf_new_from_data (data, GDK_COLORSPACE_RGB, TRUE, 8, w, h, stride, destroy_pixbuf, NULL); aitem->extra2 = gtk_image_new_from_pixbuf(pixbuf); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(gitem), aitem->extra2); /* Subtract the main reference. the image still holds a reference, so the * pixbuf won't be destroyed until the image itself is. */ g_object_unref(pixbuf); } } } al_ustr_free(caption); gtk_widget_set_sensitive(gitem, !(aitem->flags & ALLEGRO_MENU_ITEM_DISABLED)); aitem->extra1 = gitem; if (aitem->popup) { GtkWidget *gsubmenu = gtk_menu_new(); build_menu(gsubmenu, aitem->popup); aitem->popup->extra1 = gsubmenu; gtk_widget_show(gsubmenu); gtk_menu_item_set_submenu(GTK_MENU_ITEM(gitem), gsubmenu); } else if (aitem->id) { g_signal_connect_swapped (gitem, "activate", G_CALLBACK(menuitem_response), (gpointer) aitem); } } gtk_widget_show(gitem); return gitem; }
void TextEdit::EventOccured( Event* e ) { UString keyname; Control::EventOccured( e ); if( e->Type == EVENT_FORM_INTERACTION ) { if( e->Data.Forms.RaisedBy == this ) { if( e->Data.Forms.EventFlag == FormEventType::GotFocus || e->Data.Forms.EventFlag == FormEventType::MouseClick || e->Data.Forms.EventFlag == FormEventType::KeyDown ) { editting = true; //e->Handled = true; } if( e->Data.Forms.EventFlag == FormEventType::LostFocus ) { editting = false; RaiseEvent( FormEventType::TextEditFinish ); //e->Handled = true; } } else if( e->Data.Forms.EventFlag == FormEventType::MouseClick ) { editting = false; RaiseEvent( FormEventType::TextEditFinish ); } if( e->Data.Forms.EventFlag == FormEventType::KeyPress && editting ) { switch( e->Data.Forms.KeyInfo.KeyCode ) { case ALLEGRO_KEY_BACKSPACE: if( SelectionStart > 0 ) { text.remove(SelectionStart, 1); SelectionStart--; RaiseEvent( FormEventType::TextChanged ); } e->Handled = true; break; case ALLEGRO_KEY_DELETE: if( SelectionStart < text.length() ) { text.remove(SelectionStart+1, 1); RaiseEvent( FormEventType::TextChanged ); } e->Handled = true; break; case ALLEGRO_KEY_LEFT: if( SelectionStart > 0 ) { SelectionStart--; } e->Handled = true; break; case ALLEGRO_KEY_RIGHT: if( SelectionStart < text.length() ) { SelectionStart++; } e->Handled = true; break; case ALLEGRO_KEY_LSHIFT: case ALLEGRO_KEY_RSHIFT: editShift = true; break; case ALLEGRO_KEY_ALTGR: editAltGr = true; break; case ALLEGRO_KEY_HOME: SelectionStart = 0; e->Handled = true; break; case ALLEGRO_KEY_END: SelectionStart = text.length(); e->Handled = true; break; case ALLEGRO_KEY_ENTER: editting = false; RaiseEvent( FormEventType::TextEditFinish ); break; default: ALLEGRO_USTR* convert = al_ustr_new(""); al_ustr_append_chr( convert, e->Data.Forms.KeyInfo.UniChar ); if( convert->slen == 1 && al_cstr(convert)[0] != 0 ) { text.insert( SelectionStart, al_cstr(convert) ); SelectionStart++; RaiseEvent( FormEventType::TextChanged ); } } } if( e->Data.Forms.EventFlag == FormEventType::KeyUp && editting ) { switch( e->Data.Forms.KeyInfo.KeyCode ) { case ALLEGRO_KEY_LSHIFT: case ALLEGRO_KEY_RSHIFT: editShift = false; e->Handled = true; break; case ALLEGRO_KEY_ALTGR: editAltGr = false; e->Handled = true; break; } } } }
static void t2(void) { CHECK(0 == al_ustr_size(al_ustr_empty_string())); CHECK(0 == strcmp(al_cstr(al_ustr_empty_string()), "")); }
/** returns the current filename of a skin. @param skin skin to get the filename of. @return the filename of a skin; a pointer to the internal character buffer (UTF-8 string). */ const char *algui_get_skin_filename(ALGUI_SKIN *skin) { assert(skin); return al_cstr(skin->filename); }
/* parse_path_string: * * Parse a path string according to the following grammar. The last * component, if it is not followed by a directory separator, is interpreted * as the filename component, unless it is "." or "..". * * GRAMMAR * * path ::= "//" c+ "/" nonlast [Windows only] * | c ":" nonlast [Windows only] * | nonlast * * nonlast ::= c* "/" nonlast * | last * * last ::= "." * | ".." * | filename * * filename ::= c* [but not "." and ".."] * * c ::= any character but '/' */ static bool parse_path_string(const ALLEGRO_USTR *str, ALLEGRO_PATH *path) { ALLEGRO_USTR_INFO dot_info; ALLEGRO_USTR_INFO dotdot_info; const ALLEGRO_USTR * dot = al_ref_cstr(&dot_info, "."); const ALLEGRO_USTR * dotdot = al_ref_cstr(&dotdot_info, ".."); ALLEGRO_USTR *piece = al_ustr_new(""); int pos = 0; bool on_windows; /* We compile the drive handling code on non-Windows platforms to prevent * it becoming broken. */ #ifdef ALLEGRO_WINDOWS on_windows = true; #else on_windows = false; #endif if (on_windows) { /* UNC \\server\share name */ if (al_ustr_has_prefix_cstr(str, "//")) { int slash = al_ustr_find_chr(str, 2, '/'); if (slash == -1 || slash == 2) { /* Missing slash or server component is empty. */ goto Error; } al_ustr_assign_substr(path->drive, str, pos, slash); pos = slash + 1; } else { /* Drive letter. */ int colon = al_ustr_offset(str, 1); if (colon > -1 && al_ustr_get(str, colon) == ':') { /* Include the colon in the drive string. */ al_ustr_assign_substr(path->drive, str, 0, colon + 1); pos = colon + 1; } } } for (;;) { int slash = al_ustr_find_chr(str, pos, '/'); if (slash == -1) { /* Last component. */ al_ustr_assign_substr(piece, str, pos, al_ustr_size(str)); if (al_ustr_equal(piece, dot) || al_ustr_equal(piece, dotdot)) { al_append_path_component(path, al_cstr(piece)); } else { /* This might be an empty string, but that's okay. */ al_ustr_assign(path->filename, piece); } break; } /* Non-last component. */ al_ustr_assign_substr(piece, str, pos, slash); al_append_path_component(path, al_cstr(piece)); pos = slash + 1; } al_ustr_free(piece); return true; Error: al_ustr_free(piece); return false; }
/* Function: al_get_path_filename */ const char *al_get_path_filename(const ALLEGRO_PATH *path) { ASSERT(path); return al_cstr(path->filename); }
/* _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 *cwd; /* Prepend current directory */ cwd = al_get_current_directory(); if (cwd) { ALLEGRO_PATH *path = al_create_path_for_directory(cwd); al_free(cwd); al_set_path_filename(path, filename); if (stat(al_path_cstr(path, '/'), &finfo) == 0 && !S_ISDIR(finfo.st_mode)) { return path; } al_destroy_path(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; const ALLEGRO_USTR *sub = al_ref_ustr(&info, us, start_pos, end_pos); ALLEGRO_PATH *path = al_create_path_for_directory(al_cstr(sub)); al_set_path_filename(path, filename); if (stat(al_path_cstr(path, '/'), &finfo) == 0 && !S_ISDIR (finfo.st_mode)) { return path; } al_destroy_path(path); start_pos = next_start_pos; } } return NULL; }
bool _al_show_native_file_dialog(ALLEGRO_DISPLAY *display, ALLEGRO_NATIVE_DIALOG *fd) { OPENFILENAME ofn; ALLEGRO_DISPLAY_WIN *win_display; int flags = 0; bool ret; char buf[4096] = ""; ALLEGRO_USTR *filter_string = NULL; win_display = (ALLEGRO_DISPLAY_WIN *)display; if (fd->flags & ALLEGRO_FILECHOOSER_FOLDER) { return select_folder(win_display, fd); } /* Selecting a file. */ memset(&ofn, 0, sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = (win_display) ? win_display->window : NULL; /* Create filter string. */ if (fd->fc_patterns) { filter_string = create_filter_string(fd->fc_patterns); ofn.lpstrFilter = al_cstr(filter_string); } else { /* List all files by default. */ ofn.lpstrFilter = "All Files\0*.*\0\0"; } ofn.lpstrFile = buf; ofn.nMaxFile = sizeof(buf); if (fd->fc_initial_path) { ofn.lpstrInitialDir = al_path_cstr(fd->fc_initial_path, ALLEGRO_NATIVE_PATH_SEP); } if (fd->title) ofn.lpstrTitle = al_cstr(fd->title); flags |= OFN_NOCHANGEDIR | OFN_EXPLORER; if (fd->flags & ALLEGRO_FILECHOOSER_SAVE) { flags |= OFN_OVERWRITEPROMPT; } else { flags |= (fd->flags & ALLEGRO_FILECHOOSER_FILE_MUST_EXIST) ? OFN_FILEMUSTEXIST : 0; } flags |= (fd->flags & ALLEGRO_FILECHOOSER_MULTIPLE) ? OFN_ALLOWMULTISELECT : 0; flags |= (fd->flags & ALLEGRO_FILECHOOSER_SHOW_HIDDEN) ? 0x10000000 : 0; // NOTE: 0x10000000 is FORCESHOWHIDDEN ofn.Flags = flags; if (flags & OFN_OVERWRITEPROMPT) { ret = GetSaveFileName(&ofn); } else { ret = GetOpenFileName(&ofn); } al_ustr_free(filter_string); if (!ret) { DWORD err = GetLastError(); if (err != ERROR_SUCCESS) { char buf[1000]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, buf, sizeof(buf), NULL); ALLEGRO_ERROR("al_show_native_file_dialog failed: %s\n", buf); } return false; } if (flags & OFN_ALLOWMULTISELECT) { int i; /* Count number of file names in buf. */ fd->fc_path_count = 0; i = skip_nul_terminated_string(buf); while (1) { if (buf[i] == '\0') { fd->fc_path_count++; if (buf[i+1] == '\0') break; } i++; } } else { fd->fc_path_count = 1; } if (fd->fc_path_count == 1) { fd->fc_paths = al_malloc(sizeof(void *)); fd->fc_paths[0] = al_create_path(buf); } else { int i, p; /* If multiple files were selected, the first string in buf is the * directory name, followed by each of the file names terminated by NUL. */ fd->fc_paths = al_malloc(fd->fc_path_count * sizeof(void *)); i = skip_nul_terminated_string(buf); for (p = 0; p < (int)fd->fc_path_count; p++) { fd->fc_paths[p] = al_create_path_for_directory(buf); al_set_path_filename(fd->fc_paths[p], buf+i); i += skip_nul_terminated_string(buf+i); } } return true; }
bool _al_open_native_text_log(ALLEGRO_NATIVE_DIALOG *textlog) { LPCSTR font_name; HWND hWnd; HWND hLog; WNDCLASSA text_log_class; RECT client_rect; HFONT hFont; MSG msg; BOOL ret; al_lock_mutex(textlog->tl_text_mutex); /* Prepare text log class info. */ if (!wlog_class_registered) { memset(&text_log_class, 0, sizeof(text_log_class)); text_log_class.hInstance = (HINSTANCE)GetModuleHandle(NULL); text_log_class.lpszClassName = "Allegro Text Log"; text_log_class.lpfnWndProc = wlog_text_log_callback; text_log_class.hIcon = NULL; text_log_class.hCursor = NULL; text_log_class.lpszMenuName = NULL; text_log_class.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH); if (RegisterClassA(&text_log_class) == 0) { /* Failure, window class is a basis and we do not have one. */ al_unlock_mutex(textlog->tl_text_mutex); return false; } wlog_class_registered++; } /* Load RichEdit control. */ if (!wlog_rich_edit_module) { if ((wlog_rich_edit_module = _al_open_library("msftedit.dll"))) { /* 4.1 and emulation of 3.0, 2.0, 1.0 */ wlog_edit_control = L"RICHEDIT50W"; /*MSFTEDIT_CLASS*/ wlog_unicode = true; } else if ((wlog_rich_edit_module = _al_open_library("riched20.dll"))) { /* 3.0, 2.0 */ wlog_edit_control = L"RichEdit20W"; /*RICHEDIT_CLASS*/ wlog_unicode = true; } else if ((wlog_rich_edit_module = _al_open_library("riched32.dll"))) { /* 1.0 */ wlog_edit_control = L"RichEdit"; /*RICHEDIT_CLASS*/ wlog_unicode = false; } else { wlog_edit_control = L"EDIT"; wlog_unicode = false; } } /* Create text log window. */ hWnd = CreateWindowA("Allegro Text Log", al_cstr(textlog->title), WS_CAPTION | WS_SIZEBOX | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, (HINSTANCE)GetModuleHandle(NULL), textlog); if (!hWnd) { if (wlog_rich_edit_module) { _al_close_library(wlog_rich_edit_module); wlog_rich_edit_module = NULL; } UnregisterClassA("Allegro Text Log", (HINSTANCE)GetModuleHandle(NULL)); al_unlock_mutex(textlog->tl_text_mutex); return false; } /* Get client area of the log window. */ GetClientRect(hWnd, &client_rect); /* Create edit control. */ hLog = CreateWindowW(wlog_edit_control, NULL, WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE | ES_WANTRETURN | ES_AUTOVSCROLL | ES_READONLY, client_rect.left, client_rect.top, client_rect.right - client_rect.left, client_rect.bottom - client_rect.top, hWnd, NULL, (HINSTANCE)GetModuleHandle(NULL), NULL); if (!hLog) { if (wlog_rich_edit_module) { _al_close_library(wlog_rich_edit_module); wlog_rich_edit_module = NULL; } DestroyWindow(hWnd); UnregisterClassA("Allegro Text Log", (HINSTANCE)GetModuleHandle(NULL)); al_unlock_mutex(textlog->tl_text_mutex); return false; } /* Enable double-buffering. */ SetWindowLong(hLog, GWL_EXSTYLE, GetWindowLong(hLog, GWL_EXSTYLE) | 0x02000000L/*WS_EX_COMPOSITED*/); /* Select font name. */ if (textlog->flags & ALLEGRO_TEXTLOG_MONOSPACE) font_name = "Courier New"; else font_name = "Arial"; /* Create font and set font. */ hFont = CreateFont(-11, 0, 0, 0, FW_LIGHT, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_MODERN | FIXED_PITCH, font_name); /* Assign font to the text log. */ if (hFont) { SendMessage(hLog, WM_SETFONT, (WPARAM)hFont, 0); } /* Set background color of RichEdit control. */ if (wlog_rich_edit_module) { SendMessage(hLog, EM_SETBKGNDCOLOR, 0, (LPARAM)RGB(16, 16, 16)); } /* We are ready to show our window. */ ShowWindow(hWnd, SW_NORMAL); /* Save handles for future use. */ textlog->window = hWnd; textlog->tl_textview = hLog; textlog->is_active = true; /* Now notify al_show_native_textlog that the text log is ready. */ textlog->tl_done = true; al_signal_cond(textlog->tl_text_cond); al_unlock_mutex(textlog->tl_text_mutex); /* Process messages. */ while ((ret = GetMessage(&msg, NULL, 0, 0)) != 0) { if (ret != -1 && msg.message != WM_QUIT) { /* Intercept child window key down messages. Needed to track * hit of ESCAPE key while text log have focus. */ if (msg.hwnd != textlog->window && msg.message == WM_KEYDOWN) { PostMessage(textlog->window, WM_KEYDOWN, msg.wParam, msg.lParam); } TranslateMessage(&msg); DispatchMessage(&msg); } else break; } /* Close window. Should be already closed, this is just sanity. */ if (IsWindow(textlog->window)) { DestroyWindow(textlog->window); } /* Release font. We don't want to leave any garbage. */ DeleteObject(hFont); /* Release RichEdit module. */ if (wlog_rich_edit_module) { _al_close_library(wlog_rich_edit_module); wlog_rich_edit_module = NULL; } /* Unregister window class. */ if (--wlog_class_registered == 0) { UnregisterClassA("Allegro Text Log", (HINSTANCE)GetModuleHandle(NULL)); } /* Notify everyone that we're gone. */ al_lock_mutex(textlog->tl_text_mutex); textlog->tl_done = true; al_signal_cond(textlog->tl_text_cond); al_unlock_mutex(textlog->tl_text_mutex); return true; }
/* [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; }
int main(void) { ALLEGRO_DISPLAY *display; ALLEGRO_TIMER *timer; ALLEGRO_EVENT_QUEUE *queue; int redraw = 0, i; bool quit = false; if (!al_init()) { abort_example("Could not initialise Allegro\n"); return 1; } al_init_primitives_addon(); al_install_mouse(); al_init_image_addon(); al_init_font_addon(); al_init_ttf_addon(); srand(time(NULL)); white = al_map_rgba_f(1, 1, 1, 1); display = al_create_display(640, 480); if (!display) { abort_example("Could not create display\n"); return 1; } al_set_window_title(display, "Allegro Logo Generator"); al_install_keyboard(); /* Read logo parameters from logo.ini (if it exists). */ config = al_load_config_file("logo.ini"); if (!config) config = al_create_config(); for (i = 0; param_names[i]; i++) { char const *value = al_get_config_value(config, "logo", param_names[i]); if (value) strncpy(param_values[i], value, sizeof(param_values[i])); } font = al_load_font("data/DejaVuSans.ttf", 12, 0); if (!font) { abort_example("Could not load font\n"); return 1; } timer = al_create_timer(1.0 / 60); queue = al_create_event_queue(); al_register_event_source(queue, al_get_keyboard_event_source()); al_register_event_source(queue, al_get_mouse_event_source()); al_register_event_source(queue, al_get_display_event_source(display)); al_register_event_source(queue, al_get_timer_event_source(timer)); al_start_timer(timer); while (!quit) { ALLEGRO_EVENT event; al_wait_for_event(queue, &event); if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) break; if (event.type == ALLEGRO_EVENT_KEY_CHAR) { if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) { quit = true; } else if (event.keyboard.keycode == ALLEGRO_KEY_ENTER) { if (editing) { regenerate = true; editing = false; } else { cursor = 0; editing = true; } } else if (event.keyboard.keycode == ALLEGRO_KEY_UP) { if (selection > 0) { selection--; cursor = 0; editing = false; } } else if (event.keyboard.keycode == ALLEGRO_KEY_DOWN) { if (param_names[selection + 1]) { selection++; cursor = 0; editing = false; } } else { int c = event.keyboard.unichar; if (editing) { if (c >= 32) { ALLEGRO_USTR *u = al_ustr_new(param_values[selection]); al_ustr_set_chr(u, cursor, c); cursor++; al_ustr_set_chr(u, cursor, 0); strncpy(param_values[selection], al_cstr(u), sizeof param_values[selection]); al_ustr_free(u); } } else { if (c == 'r') randomize(); if (c == 's') save(); } } } if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) { if (event.mouse.button == 1) { mouse_click(event.mouse.x, event.mouse.y); } } if (event.type == ALLEGRO_EVENT_TIMER) redraw++; if (redraw && al_is_event_queue_empty(queue)) { redraw = 0; render(); al_flip_display(); } } /* Write modified parameters back to logo.ini. */ for (i = 0; param_names[i]; i++) { al_set_config_value(config, "logo", param_names[i], param_values[i]); } al_save_config_file("logo.ini", config); al_destroy_config(config); return 0; }
/* Function: al_path_cstr */ const char *al_path_cstr(const ALLEGRO_PATH *path, char delim) { path_to_ustr(path, delim, path->full_string); return al_cstr(path->full_string); }
const char *TextEntry::get_text() { return al_cstr(text); }
/* get_segment_cstr: * Return the i'th directory component of a path as a C string. */ static const char *get_segment_cstr(const ALLEGRO_PATH *path, unsigned i) { return al_cstr(get_segment(path, i)); }
static void ljoy_scan(bool configure) { int fd; ALLEGRO_JOYSTICK_LINUX *joy, **joypp; int num; ALLEGRO_USTR *device_name; unsigned i; /* Clear mark bits. */ for (i = 0; i < _al_vector_size(&joysticks); i++) { joypp = _al_vector_ref(&joysticks, i); joy = *joypp; joy->marked = false; } device_name = al_ustr_new(""); /* This is a big number, but there can be gaps and other unrelated event * device files. Perhaps it would be better to use glob() here. */ for (num = 0; num < 32; num++) { if (!ljoy_detect_device_name(num, device_name)) continue; joy = ljoy_by_device_name(device_name); if (joy) { ALLEGRO_DEBUG("Device %s still exists\n", al_cstr(device_name)); joy->marked = true; continue; } /* Try to open the device. The device must be opened in O_RDWR mode to * allow writing of haptic effects! The haptic driver for linux * reuses the joystick driver's fd. */ fd = open(al_cstr(device_name), O_RDWR|O_NONBLOCK); if (fd == -1) { ALLEGRO_WARN("Failed to open device %s\n", al_cstr(device_name)); continue; } /* The device must have at least one joystick-related axis, and one * joystick-related button. Some devices, such as mouse pads, have ABS_X * and ABS_Y axes like a joystick but not joystick-related buttons. By * checking for both axes and buttons, such devices can be excluded. */ if (!have_joystick_button(fd) || !have_joystick_axis(fd)) { ALLEGRO_DEBUG("Device %s not a joystick\n", al_cstr(device_name)); close(fd); continue; } ALLEGRO_DEBUG("Device %s is new\n", al_cstr(device_name)); joy = ljoy_allocate_structure(); joy->fd = fd; joy->device_name = al_ustr_dup(device_name); joy->config_state = LJOY_STATE_BORN; joy->marked = true; config_needs_merging = true; if (ioctl(fd, EVIOCGNAME(sizeof(joy->name)), joy->name) < 0) strcpy(joy->name, "Unknown"); /* Map Linux input API axis and button numbers to ours, and fill in * information. */ if (!fill_joystick_axes(joy, fd) || !fill_joystick_buttons(joy, fd)) { ALLEGRO_ERROR("fill_joystick_info failed %s\n", al_cstr(device_name)); inactivate_joy(joy); close(fd); continue; } /* Register the joystick with the fdwatch subsystem. */ _al_unix_start_watching_fd(joy->fd, ljoy_process_new_data, joy); } al_ustr_free(device_name); /* Schedule unmarked structures to be inactivated. */ for (i = 0; i < _al_vector_size(&joysticks); i++) { joypp = _al_vector_ref(&joysticks, i); joy = *joypp; if (joy->config_state == LJOY_STATE_ALIVE && !joy->marked) { ALLEGRO_DEBUG("Device %s to be inactivated\n", al_cstr(joy->device_name)); joy->config_state = LJOY_STATE_DYING; config_needs_merging = true; } } /* Generate a configure event if necessary. * Even if we generated one before that the user hasn't responded to, * we don't know if the user received it so always generate it. */ if (config_needs_merging && configure) { ljoy_generate_configure_event(); } }
/* Function: al_get_path_drive */ const char *al_get_path_drive(const ALLEGRO_PATH *path) { ASSERT(path); return al_cstr(path->drive); }