bool task_push_decompress( const char *source_file, const char *target_dir, const char *target_file, const char *subdir, const char *valid_ext, retro_task_callback_t cb, void *user_data) { char tmp[PATH_MAX_LENGTH] = {0}; decompress_state_t *s = NULL; retro_task_t *t = NULL; if (string_is_empty(target_dir) || string_is_empty(source_file)) { RARCH_WARN("[decompress] Empty or null source file or" " target directory arguments.\n"); return false; } /* ZIP or APK only */ if (!path_file_exists(source_file) || msg_hash_to_file_type(msg_hash_calculate(path_get_extension(source_file))) != FILE_TYPE_COMPRESSED) { RARCH_WARN("[decompress] File '%s' does not exist or is not a compressed file.\n", source_file); return false; } if (!valid_ext || !valid_ext[0]) valid_ext = NULL; if (task_check_decompress(source_file)) { RARCH_LOG("[decompress] File '%s' already being decompressed.\n", source_file); return false; } RARCH_LOG("[decompress] File '%s.\n", source_file); s = (decompress_state_t*)calloc(1, sizeof(*s)); if (!s) goto error; s->source_file = strdup(source_file); s->target_dir = strdup(target_dir); s->valid_ext = valid_ext ? strdup(valid_ext) : NULL; s->zlib.type = ZLIB_TRANSFER_INIT; t = (retro_task_t*)calloc(1, sizeof(*t)); if (!t) goto error; t->state = s; t->handler = task_decompress_handler; if (!string_is_empty(subdir)) { s->subdir = strdup(subdir); t->handler = task_decompress_handler_subdir; } else if (!string_is_empty(target_file)) { s->target_file = strdup(target_file); t->handler = task_decompress_handler_target_file; } t->callback = cb; t->user_data = user_data; snprintf(tmp, sizeof(tmp), "%s '%s'", msg_hash_to_str(MSG_EXTRACTING), path_basename(source_file)); t->title = strdup(tmp); task_queue_ctl(TASK_QUEUE_CTL_PUSH, t); return true; error: if (s) free(s); return false; }
void task_file_load_handler(retro_task_t *task) { nbio_handle_t *nbio = (nbio_handle_t*)task->state; if (nbio) { switch (nbio->status) { case NBIO_STATUS_INIT: if (nbio && !string_is_empty(nbio->path)) { struct nbio_t *handle = (struct nbio_t*)nbio_open(nbio->path, NBIO_READ); if (handle) { nbio->handle = handle; nbio->status = NBIO_STATUS_TRANSFER; nbio_begin_read(handle); return; } else task_set_cancelled(task, true); } break; case NBIO_STATUS_TRANSFER_PARSE: if (!nbio || task_file_transfer_iterate_parse(nbio) == -1) task_set_cancelled(task, true); nbio->status = NBIO_STATUS_TRANSFER_FINISHED; break; case NBIO_STATUS_TRANSFER: if (!nbio || task_file_transfer_iterate_transfer(nbio) == -1) nbio->status = NBIO_STATUS_TRANSFER_PARSE; break; case NBIO_STATUS_TRANSFER_FINISHED: break; } switch (nbio->type) { case NBIO_TYPE_PNG: case NBIO_TYPE_JPEG: case NBIO_TYPE_TGA: case NBIO_TYPE_BMP: if (!task_image_load_handler(task)) task_set_finished(task, true); break; case NBIO_TYPE_MP3: case NBIO_TYPE_FLAC: case NBIO_TYPE_OGG: case NBIO_TYPE_MOD: case NBIO_TYPE_WAV: if (!task_audio_mixer_load_handler(task)) task_set_finished(task, true); break; case NBIO_TYPE_NONE: default: if (nbio->is_finished) task_set_finished(task, true); break; } } if (task_get_cancelled(task)) { task_set_error(task, strdup("Task canceled.")); task_set_finished(task, true); } }
static void chat_onKey(ToxWindow *self, Tox *m, wint_t key) { ChatContext *ctx = (ChatContext *) self->x; StatusBar *statusbar = (StatusBar *) self->s; struct tm *timeinfo = get_time(); int x, y, y2, x2; getyx(self->window, y, x); getmaxyx(self->window, y2, x2); /* Add printable chars to buffer and print on input space */ #if HAVE_WIDECHAR if (iswprint(key)) { #else if (isprint(key)) { #endif if (ctx->pos < (MAX_STR_SIZE-1)) { mvwaddstr(self->window, y, x, wc_to_char(key)); ctx->line[ctx->pos++] = key; ctx->line[ctx->pos] = L'\0'; } } /* BACKSPACE key: Remove one character from line */ else if (key == 0x107 || key == 0x8 || key == 0x7f) { if (ctx->pos > 0) { ctx->line[--ctx->pos] = L'\0'; if (x == 0) mvwdelch(self->window, y - 1, x2 - 1); else mvwdelch(self->window, y, x - 1); } } /* RETURN key: Execute command or print line */ else if (key == '\n') { uint8_t *line = wcs_to_char(ctx->line); wclear(ctx->linewin); wmove(self->window, y2 - CURS_Y_OFFSET, 0); wclrtobot(self->window); bool close_win = false; if (line[0] == '/') { if (close_win = !strncmp(line, "/close", strlen("/close"))) { int f_num = self->friendnum; delwin(ctx->linewin); delwin(statusbar->topline); del_window(self); disable_chatwin(f_num); } else execute(self, ctx, statusbar, m, line); } else { /* make sure the string has at least non-space character */ if (!string_is_empty(line)) { uint8_t selfname[TOX_MAX_NAME_LENGTH]; tox_getselfname(m, selfname, TOX_MAX_NAME_LENGTH); wattron(ctx->history, COLOR_PAIR(CYAN)); wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); wattroff(ctx->history, COLOR_PAIR(CYAN)); wattron(ctx->history, COLOR_PAIR(GREEN)); wprintw(ctx->history, "%s: ", selfname); wattroff(ctx->history, COLOR_PAIR(GREEN)); wprintw(ctx->history, "%s\n", line); if (!statusbar->is_online || tox_sendmessage(m, self->friendnum, line, strlen(line) + 1) == 0) { wattron(ctx->history, COLOR_PAIR(RED)); wprintw(ctx->history, " * Failed to send message.\n"); wattroff(ctx->history, COLOR_PAIR(RED)); } } } if (close_win) { free(ctx); free(statusbar); } else { ctx->line[0] = L'\0'; ctx->pos = 0; } free(line); } } static void chat_onDraw(ToxWindow *self, Tox *m) { curs_set(1); int x, y; getmaxyx(self->window, y, x); ChatContext *ctx = (ChatContext *) self->x; /* Draw status bar */ StatusBar *statusbar = (StatusBar *) self->s; mvwhline(statusbar->topline, 1, 0, '-', x); wmove(statusbar->topline, 0, 0); /* Draw name, status and note in statusbar */ if (statusbar->is_online) { char *status_text = "Unknown"; int colour = WHITE; TOX_USERSTATUS status = statusbar->status; switch(status) { case TOX_USERSTATUS_NONE: status_text = "Online"; colour = GREEN; break; case TOX_USERSTATUS_AWAY: status_text = "Away"; colour = YELLOW; break; case TOX_USERSTATUS_BUSY: status_text = "Busy"; colour = RED; break; } wattron(statusbar->topline, A_BOLD); wprintw(statusbar->topline, " %s ", self->name); wattroff(statusbar->topline, A_BOLD); wattron(statusbar->topline, COLOR_PAIR(colour) | A_BOLD); wprintw(statusbar->topline, "[%s]", status_text); wattroff(statusbar->topline, COLOR_PAIR(colour) | A_BOLD); } else { wattron(statusbar->topline, A_BOLD); wprintw(statusbar->topline, " %s ", self->name); wattroff(statusbar->topline, A_BOLD); wprintw(statusbar->topline, "[Offline]"); } /* Truncate note if it doesn't fit in statusbar */ uint16_t maxlen = x - getcurx(statusbar->topline) - 5; if (statusbar->statusmsg_len > maxlen) { statusbar->statusmsg[maxlen] = '\0'; statusbar->statusmsg_len = maxlen; } wattron(statusbar->topline, A_BOLD); wprintw(statusbar->topline, " | %s |", statusbar->statusmsg); wattroff(statusbar->topline, A_BOLD); wprintw(statusbar->topline, "\n"); mvwhline(ctx->linewin, 0, 0, '_', x); wrefresh(self->window); }
static void chat_onKey(ToxWindow *self, Messenger *m, wint_t key) { ChatContext *ctx = (ChatContext *) self->x; struct tm *timeinfo = get_time(); int x, y, y2, x2; getyx(self->window, y, x); getmaxyx(self->window, y2, x2); /* Add printable chars to buffer and print on input space */ #if HAVE_WIDECHAR if (iswprint(key)) { #else if (isprint(key)) { #endif if (ctx->pos != sizeof(ctx->line) - 1) { mvwaddstr(self->window, y, x, wc_to_char(key)); ctx->line[ctx->pos++] = key; ctx->line[ctx->pos] = L'\0'; } } /* BACKSPACE key: Remove one character from line */ else if (key == 0x107 || key == 0x8 || key == 0x7f) { if (ctx->pos > 0) { ctx->line[--ctx->pos] = L'\0'; if (x == 0) mvwdelch(self->window, y - 1, x2 - 1); else mvwdelch(self->window, y, x - 1); } } /* RETURN key: Execute command or print line */ else if (key == '\n') { char *line = wcs_to_char(ctx->line); wclear(ctx->linewin); wmove(self->window, y2 - CURS_Y_OFFSET, 0); wclrtobot(self->window); if (line[0] == '/') execute(self, ctx, m, line); else { /* make sure the string has at least non-space character */ if (!string_is_empty(line)) { uint8_t selfname[MAX_NAME_LENGTH]; getself_name(m, selfname, sizeof(selfname)); wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); wattroff(ctx->history, COLOR_PAIR(2)); wattron(ctx->history, COLOR_PAIR(1)); wprintw(ctx->history, "%s: ", selfname); wattroff(ctx->history, COLOR_PAIR(1)); wprintw(ctx->history, "%s\n", line); if (m_sendmessage(m, ctx->friendnum, (uint8_t *) line, strlen(line) + 1) == 0) { wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, " * Failed to send message.\n"); wattroff(ctx->history, COLOR_PAIR(3)); } } } ctx->line[0] = L'\0'; ctx->pos = 0; free(line); } } void execute(ToxWindow *self, ChatContext *ctx, Messenger *m, char *cmd) { if (!strcmp(cmd, "/clear") || !strcmp(cmd, "/c")) { wclear(self->window); wclear(ctx->history); int x, y; getmaxyx(self->window, y, x); (void) x; wmove(self->window, y - CURS_Y_OFFSET, 0); } else if (!strcmp(cmd, "/help") || !strcmp(cmd, "/h")) print_help(ctx); else if (!strcmp(cmd, "/quit") || !strcmp(cmd, "/exit") || !strcmp(cmd, "/q")) { endwin(); exit(0); } else if (!strncmp(cmd, "/me ", strlen("/me "))) { struct tm *timeinfo = get_time(); char *action = strchr(cmd, ' '); if (action == NULL) { wprintw(self->window, "Invalid syntax.\n"); return; } action++; wattron(ctx->history, COLOR_PAIR(2)); wprintw(ctx->history, "[%02d:%02d:%02d] ", timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); wattroff(ctx->history, COLOR_PAIR(2)); uint8_t selfname[MAX_NAME_LENGTH]; int len = getself_name(m, selfname, sizeof(selfname)); char msg[MAX_STR_SIZE - len - 4]; snprintf(msg, sizeof(msg), "* %s %s\n", (uint8_t *) selfname, action); wattron(ctx->history, COLOR_PAIR(5)); wprintw(ctx->history, msg); wattroff(ctx->history, COLOR_PAIR(5)); if (m_sendaction(m, ctx->friendnum, (uint8_t *) msg, strlen(msg) + 1) < 0) { wattron(ctx->history, COLOR_PAIR(3)); wprintw(ctx->history, " * Failed to send action\n"); wattroff(ctx->history, COLOR_PAIR(3)); } } else if (!strncmp(cmd, "/status ", strlen("/status "))) { char *status = strchr(cmd, ' '); char *msg; char *status_text; if (status == NULL) { wprintw(ctx->history, "Invalid syntax.\n"); return; } status++; USERSTATUS status_kind; if (!strncmp(status, "online", strlen("online"))) { status_kind = USERSTATUS_NONE; status_text = "ONLINE"; } else if (!strncmp(status, "away", strlen("away"))) { status_kind = USERSTATUS_AWAY; status_text = "AWAY"; } else if (!strncmp(status, "busy", strlen("busy"))) { status_kind = USERSTATUS_BUSY; status_text = "BUSY"; } else { wprintw(ctx->history, "Invalid status.\n"); return; } msg = strchr(status, ' '); if (msg == NULL) { m_set_userstatus(m, status_kind); wprintw(ctx->history, "Status set to: %s\n", status_text); } else { msg++; m_set_userstatus(m, status_kind); m_set_statusmessage(m, ( uint8_t *) msg, strlen(msg) + 1); wprintw(ctx->history, "Status set to: %s, %s\n", status_text, msg); } } else if (!strncmp(cmd, "/nick ", strlen("/nick "))) { char *nick; nick = strchr(cmd, ' '); if (nick == NULL) { wprintw(ctx->history, "Invalid syntax.\n"); return; } nick++; setname(m, (uint8_t *) nick, strlen(nick) + 1); wprintw(ctx->history, "Nickname set to: %s\n", nick); } else if (!strcmp(cmd, "/myid")) { char id[FRIEND_ADDRESS_SIZE * 2 + 1] = {0}; uint8_t address[FRIEND_ADDRESS_SIZE]; size_t i; getaddress(m, address); for (i = 0; i < FRIEND_ADDRESS_SIZE; i++) { char xx[3]; snprintf(xx, sizeof(xx), "%02X", address[i] & 0xff); strcat(id, xx); } wprintw(ctx->history, "%s\n", id); } else if (strcmp(cmd, "/close") == 0) { int f_num = ctx->friendnum; delwin(ctx->linewin); del_window(self); disable_chatwin(f_num); } else wprintw(ctx->history, "Invalid command.\n"); } static void chat_onDraw(ToxWindow *self, Messenger *m) { curs_set(1); int x, y; getmaxyx(self->window, y, x); (void) y; ChatContext *ctx = (ChatContext *) self->x; mvwhline(ctx->linewin, 0, 0, '_', x); wrefresh(self->window); }
void task_file_load_handler(retro_task_t *task) { nbio_handle_t *nbio = (nbio_handle_t*)task->state; if (nbio) { switch (nbio->status) { case NBIO_STATUS_INIT: if (nbio && !string_is_empty(nbio->path)) { const char *fullpath = nbio->path; struct nbio_t *handle = nbio_open(fullpath, NBIO_READ); if (handle) { nbio->handle = handle; nbio->status = NBIO_STATUS_TRANSFER; if (strstr(fullpath, file_path_str(FILE_PATH_PNG_EXTENSION))) nbio->image_type = IMAGE_TYPE_PNG; else if (strstr(fullpath, file_path_str(FILE_PATH_JPEG_EXTENSION)) || strstr(fullpath, file_path_str(FILE_PATH_JPG_EXTENSION))) nbio->image_type = IMAGE_TYPE_JPEG; else if (strstr(fullpath, file_path_str(FILE_PATH_BMP_EXTENSION))) nbio->image_type = IMAGE_TYPE_BMP; else if (strstr(fullpath, file_path_str(FILE_PATH_TGA_EXTENSION))) nbio->image_type = IMAGE_TYPE_TGA; nbio_begin_read(handle); return; } else task_set_cancelled(task, true); } break; case NBIO_STATUS_TRANSFER_PARSE: if (task_file_transfer_iterate_parse(nbio) == -1) task_set_cancelled(task, true); nbio->status = NBIO_STATUS_TRANSFER_PARSE_FREE; break; case NBIO_STATUS_TRANSFER: if (task_file_transfer_iterate_transfer(nbio) == -1) nbio->status = NBIO_STATUS_TRANSFER_PARSE; break; case NBIO_STATUS_TRANSFER_PARSE_FREE: case NBIO_STATUS_POLL: default: break; } switch (nbio->image_type) { case IMAGE_TYPE_PNG: case IMAGE_TYPE_JPEG: case IMAGE_TYPE_TGA: case IMAGE_TYPE_BMP: if (!task_image_load_handler(task)) task_set_finished(task, true); break; case 0: if (nbio->is_finished) task_set_finished(task, true); break; } } if (task_get_cancelled(task)) { task_set_error(task, strdup("Task canceled.")); task_set_finished(task, true); } }
void fill_pathname_application_special(char *s, size_t len, enum application_special_type type) { switch (type) { case APPLICATION_SPECIAL_DIRECTORY_AUTOCONFIG: { settings_t *settings = config_get_ptr(); fill_pathname_join(s, settings->directory.autoconfig, settings->input.joypad_driver, len); } break; case APPLICATION_SPECIAL_DIRECTORY_CONFIG: { settings_t *settings = config_get_ptr(); /* Try config directory setting first, * fallback to the location of the current configuration file. */ if (!string_is_empty(settings->directory.menu_config)) strlcpy(s, settings->directory.menu_config, len); else if (!path_is_empty(RARCH_PATH_CONFIG)) fill_pathname_basedir(s, path_get(RARCH_PATH_CONFIG), len); } break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH_ICONS: #ifdef HAVE_ZARCH { } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH_FONT: #ifdef HAVE_ZARCH { char s1[PATH_MAX_LENGTH]; s1[0] = '\0'; fill_pathname_application_special(s1, sizeof(s1), APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH); fill_pathname_join(s, s1, "Roboto-Condensed.ttf", len); } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH: #ifdef HAVE_ZARCH { settings_t *settings = config_get_ptr(); fill_pathname_join(s, settings->directory.assets, "zarch", len); } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB_ICONS: #ifdef HAVE_XMB { char s1[PATH_MAX_LENGTH]; char s2[PATH_MAX_LENGTH]; s1[0] = s2[0] = '\0'; fill_pathname_application_special(s1, sizeof(s1), APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB); fill_pathname_join(s2, s1, "png", sizeof(s2)); fill_pathname_slash(s2, sizeof(s2)); strlcpy(s, s2, len); } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB_BG: #ifdef HAVE_XMB { settings_t *settings = config_get_ptr(); if (!string_is_empty(settings->path.menu_wallpaper)) strlcpy(s, settings->path.menu_wallpaper, len); else { char s1[PATH_MAX_LENGTH]; s1[0] = '\0'; fill_pathname_application_special(s1, sizeof(s1), APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB_ICONS); fill_pathname_join(s, s1, file_path_str(FILE_PATH_BACKGROUND_IMAGE), len); } } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB: #ifdef HAVE_XMB { char s1[PATH_MAX_LENGTH]; char s2[PATH_MAX_LENGTH]; settings_t *settings = config_get_ptr(); s1[0] = s2[0] = '\0'; fill_pathname_join( s1, settings->directory.assets, "xmb", sizeof(s1)); fill_pathname_join(s2, s1, xmb_theme_ident(), sizeof(s2)); strlcpy(s, s2, len); } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_MATERIALUI: #ifdef HAVE_MATERIALUI { settings_t *settings = config_get_ptr(); fill_pathname_join( s, settings->directory.assets, "glui", len); } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_MATERIALUI_ICONS: #ifdef HAVE_MATERIALUI { char s1[PATH_MAX_LENGTH]; s1[0] = '\0'; fill_pathname_application_special(s1, sizeof(s1), APPLICATION_SPECIAL_DIRECTORY_ASSETS_MATERIALUI); fill_pathname_slash(s1, sizeof(s1)); strlcpy(s, s1, len); } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_MATERIALUI_FONT: #ifdef HAVE_MATERIALUI { char s1[PATH_MAX_LENGTH]; s1[0] = '\0'; fill_pathname_application_special(s1, sizeof(s1), APPLICATION_SPECIAL_DIRECTORY_ASSETS_MATERIALUI); fill_pathname_join(s, s1, "font.ttf", len); } #endif break; case APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB_FONT: #ifdef HAVE_XMB { settings_t *settings = config_get_ptr(); if (!string_is_empty(settings->menu.xmb.font)) strlcpy(s, settings->menu.xmb.font, len); else { char s1[PATH_MAX_LENGTH]; s1[0] = '\0'; fill_pathname_application_special(s1, sizeof(s1), APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB); fill_pathname_join(s, s1, file_path_str(FILE_PATH_TTF_FONT), len); } } #endif break; case APPLICATION_SPECIAL_NONE: default: break; } }
/** * load_content: * @special : subsystem of content to be loaded. Can be NULL. * content : * * Load content file (for libretro core). * * Returns : true if successful, otherwise false. **/ static bool load_content( struct string_list *temporary_content, struct retro_game_info *info, const struct string_list *content, const struct retro_subsystem_info *special, struct string_list* additional_path_allocs ) { unsigned i; retro_ctx_load_content_info_t load_info; if (!info || !additional_path_allocs) return false; for (i = 0; i < content->size; i++) { int attr = content->elems[i].attr.i; bool need_fullpath = attr & 2; bool require_content = attr & 4; const char *path = content->elems[i].data; if (require_content && string_is_empty(path)) { RARCH_LOG("libretro core requires content, " "but nothing was provided.\n"); return false; } info[i].path = NULL; if (*path) info[i].path = path; if (!need_fullpath && !string_is_empty(path)) { if (!load_content_into_memory(&info[i], i, path)) return false; } else { RARCH_LOG("Content loading skipped. Implementation will" " load it on its own.\n"); #ifdef HAVE_COMPRESSION if (!load_content_from_compressed_archive( temporary_content, &info[i], i, additional_path_allocs, need_fullpath, path)) return false; #endif } } load_info.content = content; load_info.special = special; load_info.info = info; if (!core_load_game(&load_info)) { RARCH_ERR("%s.\n", msg_hash_to_str(MSG_FAILED_TO_LOAD_CONTENT)); return false; } #ifdef HAVE_CHEEVOS if (!special) { const void *load_data = NULL; cheevos_set_cheats(); if (*content->elems[0].data) load_data = info; cheevos_load(load_data); } #endif return true; }
/** * load_content: * @special : subsystem of content to be loaded. Can be NULL. * content : * * Load content file (for libretro core). * * Returns : true if successful, otherwise false. **/ static bool load_content( struct string_list *temporary_content, struct retro_game_info *info, const struct string_list *content, const struct retro_subsystem_info *special ) { unsigned i; retro_ctx_load_content_info_t load_info; struct string_list *additional_path_allocs = string_list_new(); if (!additional_path_allocs) return false; for (i = 0; i < content->size; i++) { int attr = content->elems[i].attr.i; bool need_fullpath = attr & 2; bool require_content = attr & 4; const char *path = content->elems[i].data; if (require_content && string_is_empty(path)) { RARCH_LOG("%s\n", msg_hash_to_str(MSG_ERROR_LIBRETRO_CORE_REQUIRES_CONTENT)); goto error; } info[i].path = NULL; if (!string_is_empty(path)) info[i].path = path; if (!need_fullpath && !string_is_empty(path)) { /* Load the content into memory. */ ssize_t len = 0; if (!load_content_into_memory(i, path, (void**)&info[i].data, &len)) { RARCH_ERR("%s \"%s\".\n", msg_hash_to_str(MSG_COULD_NOT_READ_CONTENT_FILE), path); goto error; } info[i].size = len; } else { RARCH_LOG("%s\n", msg_hash_to_str( MSG_CONTENT_LOADING_SKIPPED_IMPLEMENTATION_WILL_DO_IT)); #ifdef HAVE_COMPRESSION if (!load_content_from_compressed_archive( temporary_content, &info[i], i, additional_path_allocs, need_fullpath, path)) goto error; #endif } } load_info.content = content; load_info.special = special; load_info.info = info; if (!core_load_game(&load_info)) { RARCH_ERR("%s.\n", msg_hash_to_str(MSG_FAILED_TO_LOAD_CONTENT)); goto error; } #ifdef HAVE_CHEEVOS if (!special) { const void *load_data = NULL; cheevos_set_cheats(); if (!string_is_empty(content->elems[0].data)) load_data = info; cheevos_load(load_data); } #endif string_list_free(additional_path_allocs); return true; error: if (additional_path_allocs) string_list_free(additional_path_allocs); return false; }
/** * task_load_content: * * Loads content into currently selected core. * Will also optionally push the content entry to the history playlist. * * Returns: true (1) if successful, otherwise false (0). **/ static bool task_load_content(content_ctx_info_t *content_info, bool launched_from_menu, enum content_mode_load mode) { char name[256]; char msg[256]; name[0] = msg[0] = '\0'; if (launched_from_menu) { #ifdef HAVE_MENU /* redraw menu frame */ menu_display_set_msg_force(true); menu_driver_ctl(RARCH_MENU_CTL_RENDER, NULL); if (!path_is_empty(RARCH_PATH_CONTENT)) fill_pathname_base(name, path_get(RARCH_PATH_CONTENT), sizeof(name)); #endif /** Show loading OSD message */ if (!string_is_empty(path_get(RARCH_PATH_CONTENT))) { snprintf(msg, sizeof(msg), "%s %s ...", msg_hash_to_str(MSG_LOADING), name); runloop_msg_queue_push(msg, 2, 1, true); } } if (!content_load(content_info)) goto error; /* Push entry to top of history playlist */ if (content_is_inited() || content_does_not_need_content()) { char tmp[PATH_MAX_LENGTH]; struct retro_system_info *info = NULL; rarch_system_info_t *system = NULL; tmp[0] = '\0'; runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system); if (system) info = &system->info; #ifdef HAVE_MENU if (launched_from_menu) menu_driver_ctl(RARCH_MENU_CTL_SYSTEM_INFO_GET, &info); #endif strlcpy(tmp, path_get(RARCH_PATH_CONTENT), sizeof(tmp)); if (!launched_from_menu) { /* Path can be relative here. * Ensure we're pushing absolute path. */ if (!string_is_empty(tmp)) path_resolve_realpath(tmp, sizeof(tmp)); } if (info && *tmp) { const char *core_path = NULL; const char *core_name = NULL; playlist_t *playlist_tmp = g_defaults.content_history; switch (path_is_media_type(tmp)) { case RARCH_CONTENT_MOVIE: #ifdef HAVE_FFMPEG playlist_tmp = g_defaults.video_history; core_name = "movieplayer"; core_path = "builtin"; #endif break; case RARCH_CONTENT_MUSIC: #ifdef HAVE_FFMPEG playlist_tmp = g_defaults.music_history; core_name = "musicplayer"; core_path = "builtin"; #endif break; case RARCH_CONTENT_IMAGE: #ifdef HAVE_IMAGEVIEWER playlist_tmp = g_defaults.image_history; core_name = "imageviewer"; core_path = "builtin"; #endif break; default: core_path = path_get(RARCH_PATH_CORE); core_name = info->library_name; break; } if (content_push_to_history_playlist(playlist_tmp, tmp, core_name, core_path)) playlist_write_file(playlist_tmp); } } return true; error: if (launched_from_menu) { if (!path_is_empty(RARCH_PATH_CONTENT) && !string_is_empty(name)) { snprintf(msg, sizeof(msg), "%s %s.\n", msg_hash_to_str(MSG_FAILED_TO_LOAD), name); runloop_msg_queue_push(msg, 2, 90, true); } } return false; }
static void iohidmanager_hid_device_add(void *data, IOReturn result, void* sender, IOHIDDeviceRef device) { int i; IOReturn ret; uint16_t dev_vid, dev_pid; CFArrayRef elements_raw; int count; CFMutableArrayRef elements; CFRange range; bool found_axis[6] = { false, false, false, false, false, false }; apple_input_rec_t *tmp = NULL; apple_input_rec_t *tmpButtons = NULL; apple_input_rec_t *tmpAxes = NULL; iohidmanager_hid_t *hid = (iohidmanager_hid_t*) hid_driver_get_data(); struct iohidmanager_hid_adapter *adapter = (struct iohidmanager_hid_adapter*) calloc(1, sizeof(*adapter)); if (!adapter) return; if (!hid) goto error; adapter->handle = device; ret = IOHIDDeviceOpen(device, kIOHIDOptionsTypeNone); if (ret != kIOReturnSuccess) goto error; /* Move the device's run loop to this thread. */ IOHIDDeviceScheduleWithRunLoop(device, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); IOHIDDeviceRegisterRemovalCallback(device, iohidmanager_hid_device_remove, adapter); #ifndef IOS iohidmanager_hid_device_get_product_string(device, adapter->name, sizeof(adapter->name)); #endif dev_vid = iohidmanager_hid_device_get_vendor_id (device); dev_pid = iohidmanager_hid_device_get_product_id (device); adapter->slot = pad_connection_pad_init(hid->slots, adapter->name, dev_vid, dev_pid, adapter, &iohidmanager_hid); if (adapter->slot == -1) goto error; if (pad_connection_has_interface(hid->slots, adapter->slot)) IOHIDDeviceRegisterInputReportCallback(device, adapter->data + 1, sizeof(adapter->data) - 1, iohidmanager_hid_device_report, adapter); else IOHIDDeviceRegisterInputValueCallback(device, iohidmanager_hid_device_input_callback, adapter); if (string_is_empty(adapter->name)) goto error; /* scan for buttons, axis, hats */ elements_raw = IOHIDDeviceCopyMatchingElements(device, NULL, kIOHIDOptionsTypeNone); count = (int)CFArrayGetCount(elements_raw); elements = CFArrayCreateMutableCopy( kCFAllocatorDefault,(CFIndex)count,elements_raw); range = CFRangeMake(0,count); CFArraySortValues(elements, range, iohidmanager_sort_elements, NULL); for (i = 0; i < count; i++) { IOHIDElementRef element = (IOHIDElementRef)CFArrayGetValueAtIndex(elements, i); if (!element) continue; IOHIDElementType type = IOHIDElementGetType(element); uint32_t page = (uint32_t)IOHIDElementGetUsagePage(element); uint32_t use = (uint32_t)IOHIDElementGetUsage(element); uint32_t cookie = (uint32_t)IOHIDElementGetCookie(element); int detected_button = 0; switch (page) { case kHIDPage_GenericDesktop: switch (type) { case kIOHIDElementTypeCollection: case kIOHIDElementTypeInput_ScanCodes: case kIOHIDElementTypeFeature: case kIOHIDElementTypeInput_Button: case kIOHIDElementTypeOutput: case kIOHIDElementTypeInput_Axis: /* TODO/FIXME */ break; case kIOHIDElementTypeInput_Misc: switch (use) { case kHIDUsage_GD_Hatswitch: { /* as far as I can tell, OSX only reports one Hat */ apple_input_rec_t *hat = (apple_input_rec_t *)malloc(sizeof(apple_input_rec_t)); hat->id = 0; hat->cookie = (IOHIDElementCookie)cookie; hat->next = NULL; adapter->hats = hat; } break; default: { uint32_t i = 0; static const uint32_t axis_use_ids[6] = { 48, 49, 51, 52, 50, 53 }; while (i < 6 && axis_use_ids[i] != use) i++; if (i < 6) { apple_input_rec_t *axis = (apple_input_rec_t *)malloc(sizeof(apple_input_rec_t)); axis->id = i; axis->cookie = (IOHIDElementCookie)cookie; axis->next = NULL; if(iohidmanager_check_for_id(adapter->axes,i)) { /* axis ID already exists, save to tmp for appending later */ if(tmpAxes) iohidmanager_append_record(tmpAxes, axis); else tmpAxes = axis; } else { found_axis[axis->id] = true; if(adapter->axes) iohidmanager_append_record(adapter->axes, axis); else adapter->axes = axis; } } else detected_button = 1; } break; } break; } break; case kHIDPage_Consumer: case kHIDPage_Button: switch (type) { case kIOHIDElementTypeCollection: case kIOHIDElementTypeFeature: case kIOHIDElementTypeInput_ScanCodes: case kIOHIDElementTypeInput_Axis: case kIOHIDElementTypeOutput: /* TODO/FIXME */ break; case kIOHIDElementTypeInput_Misc: case kIOHIDElementTypeInput_Button: detected_button = 1; break; } break; } if (detected_button) { apple_input_rec_t *btn = (apple_input_rec_t *)malloc(sizeof(apple_input_rec_t)); btn->id = (uint32_t)use; btn->cookie = (IOHIDElementCookie)cookie; btn->next = NULL; if(iohidmanager_check_for_id(adapter->buttons,btn->id)) { if(tmpButtons) iohidmanager_append_record_ordered(&tmpButtons, btn); else tmpButtons = btn; } else { if(adapter->buttons) iohidmanager_append_record_ordered(&adapter->buttons, btn); else adapter->buttons = btn; } } } /* take care of buttons/axes with duplicate 'use' values */ for (i = 0; i < 6; i++) { if(found_axis[i] == false && tmpAxes) { apple_input_rec_t *next = tmpAxes->next; tmpAxes->id = i; tmpAxes->next = NULL; iohidmanager_append_record(adapter->axes, tmpAxes); tmpAxes = next; } } tmp = adapter->buttons; if (tmp) { while(tmp->next) tmp = tmp->next; } while(tmpButtons) { apple_input_rec_t *next = tmpButtons->next; tmpButtons->id = tmp->id; tmpButtons->next = NULL; tmp->next = tmpButtons; tmp = tmp->next; tmpButtons = next; } iohidmanager_hid_device_add_autodetect(adapter->slot, adapter->name, iohidmanager_hid.ident, dev_vid, dev_pid); return; error: { apple_input_rec_t *tmp = NULL; while(adapter->hats != NULL) { tmp = adapter->hats; adapter->hats = adapter->hats->next; free(tmp); } while(adapter->axes != NULL) { tmp = adapter->axes; adapter->axes = adapter->axes->next; free(tmp); } while(adapter->buttons != NULL) { tmp = adapter->buttons; adapter->buttons = adapter->buttons->next; free(tmp); } while(tmpAxes != NULL) { tmp = tmpAxes; tmpAxes = tmpAxes->next; free(tmp); } while(tmpButtons != NULL) { tmp = tmpButtons; tmpButtons = tmpButtons->next; free(tmp); } free(adapter); } }
void filebrowser_parse(void *data, unsigned type_data, bool extensions_honored) { size_t i, list_size; struct string_list *str_list = NULL; unsigned items_found = 0; unsigned files_count = 0; unsigned dirs_count = 0; settings_t *settings = config_get_ptr(); menu_displaylist_info_t *info = (menu_displaylist_info_t*)data; enum menu_displaylist_ctl_state type = (enum menu_displaylist_ctl_state) type_data; bool path_is_compressed = path_is_compressed_file(info->path); bool filter_ext = settings->menu.navigation.browser.filter.supported_extensions_enable; if (string_is_equal(info->label, msg_hash_to_str(MENU_ENUM_LABEL_SCAN_FILE))) filter_ext = false; if (extensions_honored) filter_ext = true; if (path_is_compressed) str_list = file_archive_get_file_list(info->path, info->exts); else str_list = dir_list_new(info->path, filter_ext ? info->exts : NULL, true, settings->show_hidden_files, true, false); #ifdef HAVE_LIBRETRODB if (filebrowser_types == FILEBROWSER_SCAN_DIR) menu_entries_prepend(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SCAN_THIS_DIRECTORY), msg_hash_to_str(MENU_ENUM_LABEL_SCAN_THIS_DIRECTORY), MENU_ENUM_LABEL_SCAN_THIS_DIRECTORY, FILE_TYPE_SCAN_DIRECTORY, 0 ,0); #endif if (filebrowser_types == FILEBROWSER_SELECT_DIR) menu_entries_prepend(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_USE_THIS_DIRECTORY), msg_hash_to_str(MENU_ENUM_LABEL_USE_THIS_DIRECTORY), MENU_ENUM_LABEL_USE_THIS_DIRECTORY, FILE_TYPE_USE_DIRECTORY, 0 ,0); if (!str_list) { const char *str = path_is_compressed ? msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UNABLE_TO_READ_COMPRESSED_FILE) : msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DIRECTORY_NOT_FOUND); menu_entries_append_enum(info->list, str, "", MENU_ENUM_LABEL_VALUE_DIRECTORY_NOT_FOUND, 0, 0, 0); goto end; } dir_list_sort(str_list, true); list_size = str_list->size; if (list_size == 0) { string_list_free(str_list); str_list = NULL; } else { for (i = 0; i < list_size; i++) { char label[PATH_MAX_LENGTH]; bool is_dir = false; enum msg_hash_enums enum_idx = MSG_UNKNOWN; enum msg_file_type file_type = FILE_TYPE_NONE; const char *path = str_list->elems[i].data; label[0] = '\0'; switch (str_list->elems[i].attr.i) { case RARCH_DIRECTORY: file_type = FILE_TYPE_DIRECTORY; break; case RARCH_COMPRESSED_ARCHIVE: file_type = FILE_TYPE_CARCHIVE; break; case RARCH_COMPRESSED_FILE_IN_ARCHIVE: file_type = FILE_TYPE_IN_CARCHIVE; break; case RARCH_PLAIN_FILE: default: file_type = (enum msg_file_type)info->type_default; switch (type) { /* in case of deferred_core_list we have to interpret * every archive as an archive to disallow instant loading */ case DISPLAYLIST_CORES_DETECTED: if (path_is_compressed_file(path)) file_type = FILE_TYPE_CARCHIVE; break; default: break; } break; } is_dir = (file_type == FILE_TYPE_DIRECTORY); if (!is_dir) { if (filebrowser_types == FILEBROWSER_SELECT_DIR) continue; if (filebrowser_types == FILEBROWSER_SCAN_DIR) continue; } /* Need to preserve slash first time. */ if (!string_is_empty(info->path) && !path_is_compressed) path = path_basename(path); if (filebrowser_types == FILEBROWSER_SELECT_COLLECTION) { if (is_dir) file_type = FILE_TYPE_DIRECTORY; else file_type = FILE_TYPE_PLAYLIST_COLLECTION; } if (!is_dir && (settings->multimedia.builtin_mediaplayer_enable || settings->multimedia.builtin_imageviewer_enable)) { switch (path_is_media_type(path)) { case RARCH_CONTENT_MOVIE: #ifdef HAVE_FFMPEG if (settings->multimedia.builtin_mediaplayer_enable) file_type = FILE_TYPE_MOVIE; #endif break; case RARCH_CONTENT_MUSIC: #ifdef HAVE_FFMPEG if (settings->multimedia.builtin_mediaplayer_enable) file_type = FILE_TYPE_MUSIC; #endif break; case RARCH_CONTENT_IMAGE: #ifdef HAVE_IMAGEVIEWER if (settings->multimedia.builtin_imageviewer_enable && type != DISPLAYLIST_IMAGES) file_type = FILE_TYPE_IMAGEVIEWER; else file_type = FILE_TYPE_IMAGE; #endif break; default: break; } } switch (file_type) { case FILE_TYPE_PLAIN: #if 0 enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_PLAIN_FILE; #endif files_count++; break; case FILE_TYPE_MOVIE: enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_MOVIE_OPEN; files_count++; break; case FILE_TYPE_MUSIC: enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_MUSIC_OPEN; files_count++; break; case FILE_TYPE_IMAGE: enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_IMAGE; files_count++; break; case FILE_TYPE_IMAGEVIEWER: enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_IMAGE_OPEN_WITH_VIEWER; files_count++; break; case FILE_TYPE_DIRECTORY: enum_idx = MENU_ENUM_LABEL_FILE_BROWSER_DIRECTORY; dirs_count++; break; default: break; } items_found++; menu_entries_append_enum(info->list, path, label, enum_idx, file_type, 0, 0); } } if (str_list && str_list->size > 0) string_list_free(str_list); if (items_found == 0) { menu_entries_append_enum(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_ITEMS), msg_hash_to_str(MENU_ENUM_LABEL_NO_ITEMS), MENU_ENUM_LABEL_NO_ITEMS, MENU_SETTING_NO_ITEM, 0, 0); } /* We don't want to show 'filter by extension' for this. */ if (filebrowser_types == FILEBROWSER_SELECT_DIR) goto end; if (filebrowser_types == FILEBROWSER_SCAN_DIR) goto end; if (!extensions_honored && files_count > 0) menu_entries_prepend(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NAVIGATION_BROWSER_FILTER_SUPPORTED_EXTENSIONS_ENABLE), msg_hash_to_str(MENU_ENUM_LABEL_NAVIGATION_BROWSER_FILTER_SUPPORTED_EXTENSIONS_ENABLE), MENU_ENUM_LABEL_NAVIGATION_BROWSER_FILTER_SUPPORTED_EXTENSIONS_ENABLE, 0, 0 ,0); end: menu_entries_prepend(info->list, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_PARENT_DIRECTORY), info->path, MENU_ENUM_LABEL_PARENT_DIRECTORY, FILE_TYPE_PARENT_DIRECTORY, 0, 0); }
/** * Creates a control from the given XMLNode as a child of the given parent * ContainerControl. * * @param form the WndForm object * @param Parent The parent ContainerControl * @param LookUpTable The parent CallBackTable * @param node The XMLNode that represents the control * @param eDialogStyle The parent's dialog style */ static Window * LoadChild(WndForm &form, ContainerControl &Parent, CallBackTableEntry *LookUpTable, XMLNode node, const DialogStyle eDialogStyle) { Window *window = NULL; // Determine name, coordinates, width, height // and caption of the control const TCHAR* Name = GetName(node); const TCHAR* Caption = GetCaption(node); RECT rc = Parent.GetClientAreaWindow().get_client_rect(); ControlPosition pos = GetPosition(node, rc); if (!pos.no_scaling) pos.x = ScaleWidth(pos.x, eDialogStyle); ControlSize size = GetSize(node, rc, pos); if (!size.no_scaling) size.cx = ScaleWidth(size.cx, eDialogStyle); WindowStyle style; if (!StringToIntDflt(node.getAttribute(_T("Visible")), 1)) style.hide(); if (StringToIntDflt(node.getAttribute(_T("Border")), 0)) style.border(); bool advanced = _tcschr(Caption, _T('*')) != NULL; // PropertyControl (WndProperty) if (_tcscmp(node.getName(), _T("Edit")) == 0) { WndProperty *W; int CaptionWidth; bool ReadOnly; bool MultiLine; // Determine the width of the caption field CaptionWidth = StringToIntDflt(node.getAttribute(_T("CaptionWidth")), 0); if (Layout::ScaleSupported()) CaptionWidth = Layout::Scale(CaptionWidth); CaptionWidth = ScaleWidth(CaptionWidth, eDialogStyle); // Determine whether the control is multiline or readonly MultiLine = StringToIntDflt(node.getAttribute(_T("MultiLine")), 0); ReadOnly = StringToIntDflt(node.getAttribute(_T("ReadOnly")), 0); // Load the event callback properties WndProperty::DataChangeCallback_t DataNotifyCallback = (WndProperty::DataChangeCallback_t) GetCallBack(LookUpTable, node, _T("OnDataNotify")); WindowControl::OnHelpCallback_t OnHelpCallback = (WindowControl::OnHelpCallback_t) GetCallBack(LookUpTable, node, _T("OnHelp")); // Create the Property Control style.control_parent(); EditWindowStyle edit_style; if (ReadOnly) edit_style.read_only(); else edit_style.tab_stop(); if (is_embedded() || Layout::scale_1024 < 2048) /* sunken edge doesn't fit well on the tiny screen of an embedded device */ edit_style.border(); else edit_style.sunken_edge(); if (MultiLine) { edit_style.multiline(); edit_style.vscroll(); } window = W = new WndProperty(Parent, Caption, pos.x, pos.y, size.cx, size.cy, CaptionWidth, style, edit_style, DataNotifyCallback); // Set the fore- and background color LoadColors(*W, node); // Set the help function event callback W->SetOnHelpCallback(OnHelpCallback); // Load the help text W->SetHelpText(StringToStringDflt(node.getAttribute(_T("Help")), _T(""))); // If the control has (at least) one DataField child control if (node.nChildNode(_T("DataField")) > 0){ // -> Load the first DataField control DataField *data_field = LoadDataField(node.getChildNode(_T("DataField"), 0), LookUpTable, eDialogStyle); if (data_field != NULL) // Tell the Property control about the DataField control W->SetDataField(data_field); } // ButtonControl (WndButton) } else if (_tcscmp(node.getName(), _T("Button")) == 0) { // Determine ClickCallback function WndButton::ClickNotifyCallback_t ClickCallback = (WndButton::ClickNotifyCallback_t) GetCallBack(LookUpTable, node, _T("OnClick")); // Create the ButtonControl style.tab_stop(); window = new WndButton(Parent.GetClientAreaWindow(), Caption, pos.x, pos.y, size.cx, size.cy, style, ClickCallback); } else if (_tcscmp(node.getName(), _T("CheckBox")) == 0) { // Determine ClickCallback function CheckBoxControl::ClickNotifyCallback_t ClickCallback = (CheckBoxControl::ClickNotifyCallback_t) GetCallBack(LookUpTable, node, _T("OnClick")); // Create the CheckBoxControl style.tab_stop(); window = new CheckBoxControl(Parent.GetClientAreaWindow(), Caption, pos.x, pos.y, size.cx, size.cy, style, ClickCallback); // SymbolButtonControl (WndSymbolButton) not used yet } else if (_tcscmp(node.getName(), _T("SymbolButton")) == 0) { // Determine ClickCallback function WndButton::ClickNotifyCallback_t ClickCallback = (WndButton::ClickNotifyCallback_t) GetCallBack(LookUpTable, node, _T("OnClick")); // Create the SymbolButtonControl style.tab_stop(); window = new WndSymbolButton(Parent.GetClientAreaWindow(), Caption, pos.x, pos.y, size.cx, size.cy, style, Parent.GetBackColor(), ClickCallback); // PanelControl (WndPanel) } else if (_tcscmp(node.getName(), _T("Panel")) == 0) { // Create the PanelControl style.control_parent(); PanelControl *frame = new PanelControl(Parent, pos.x, pos.y, size.cx, size.cy, style); // Set the fore- and background color LoadColors(*frame, node); window = frame; // Load children controls from the XMLNode LoadChildrenFromXML(form, *frame, LookUpTable, &node, eDialogStyle); // KeyboardControl } else if (_tcscmp(node.getName(), _T("Keyboard")) == 0) { KeyboardControl::OnCharacterCallback_t CharacterCallback = (KeyboardControl::OnCharacterCallback_t) GetCallBack(LookUpTable, node, _T("OnCharacter")); // Create the KeyboardControl KeyboardControl *kb = new KeyboardControl(Parent.GetClientAreaWindow(), pos.x, pos.y, size.cx, size.cy, Parent.GetBackColor(), CharacterCallback, style); window = kb; // DrawControl (WndOwnerDrawFrame) } else if (_tcscmp(node.getName(), _T("Canvas")) == 0) { // Determine DrawCallback function WndOwnerDrawFrame::OnPaintCallback_t PaintCallback = (WndOwnerDrawFrame::OnPaintCallback_t) GetCallBack(LookUpTable, node, _T("OnPaint")); // Create the DrawControl WndOwnerDrawFrame* canvas = new WndOwnerDrawFrame(Parent, pos.x, pos.y, size.cx, size.cy, style, PaintCallback); // Set the fore- and background color LoadColors(*canvas, node); window = canvas; // FrameControl (WndFrame) } else if (_tcscmp(node.getName(), _T("Label")) == 0){ // Create the FrameControl WndFrame* frame = new WndFrame(Parent, pos.x, pos.y, size.cx, size.cy, style); // Set the fore- and background color LoadColors(*frame, node); // Set the caption frame->SetCaption(Caption); window = frame; // ListBoxControl (WndListFrame) } else if (_tcscmp(node.getName(), _T("List")) == 0){ // Determine ItemHeight of the list items unsigned item_height = Layout::Scale(StringToIntDflt(node.getAttribute(_T("ItemHeight")), 18)); // Create the ListBoxControl style.tab_stop(); if (is_embedded() || Layout::scale_1024 < 2048) /* sunken edge doesn't fit well on the tiny screen of an embedded device */ style.border(); else style.sunken_edge(); window = new WndListFrame(Parent.GetClientAreaWindow(), pos.x, pos.y, size.cx, size.cy, style, item_height); // TabControl (Tabbed) } else if (_tcscmp(node.getName(), _T("Tabbed")) == 0) { // Create the TabControl style.control_parent(); TabbedControl *tabbed = new TabbedControl(Parent, pos.x, pos.y, size.cx, size.cy, style); // Set the fore- and background color LoadColors(*tabbed, node); window = tabbed; const unsigned n = node.nChildNode(); for (unsigned i = 0; i < n; ++i) { // Load each child control from the child nodes Window *child = LoadChild(form, *tabbed, LookUpTable, node.getChildNode(i), eDialogStyle); if (child != NULL) tabbed->AddClient(child); continue; } } else if (_tcscmp(node.getName(), _T("Custom")) == 0) { // Create a custom Window object with a callback CreateWindowCallback_t create = (CreateWindowCallback_t)GetCallBack(LookUpTable, node, _T("OnCreate")); if (create == NULL) return NULL; window = create(Parent.GetClientAreaWindow(), pos.x, pos.y, size.cx, size.cy, style); } if (window != NULL) { if (!string_is_empty(Name)) form.AddNamed(Name, window); if (advanced) form.AddAdvanced(window); form.AddDestruct(window); } return window; }
bool runloop_ctl(enum runloop_ctl_state state, void *data) { settings_t *settings = config_get_ptr(); switch (state) { case RUNLOOP_CTL_SHADER_DIR_DEINIT: shader_dir_free(&runloop_shader_dir); break; case RUNLOOP_CTL_SHADER_DIR_INIT: return shader_dir_init(&runloop_shader_dir); case RUNLOOP_CTL_SYSTEM_INFO_INIT: core_get_system_info(&runloop_system.info); if (!runloop_system.info.library_name) runloop_system.info.library_name = msg_hash_to_str(MSG_UNKNOWN); if (!runloop_system.info.library_version) runloop_system.info.library_version = "v0"; video_driver_set_title_buf(); strlcpy(runloop_system.valid_extensions, runloop_system.info.valid_extensions ? runloop_system.info.valid_extensions : DEFAULT_EXT, sizeof(runloop_system.valid_extensions)); break; case RUNLOOP_CTL_GET_CORE_OPTION_SIZE: { unsigned *idx = (unsigned*)data; if (!idx) return false; *idx = core_option_manager_size(runloop_core_options); } break; case RUNLOOP_CTL_HAS_CORE_OPTIONS: return runloop_core_options; case RUNLOOP_CTL_CORE_OPTIONS_LIST_GET: { core_option_manager_t **coreopts = (core_option_manager_t**)data; if (!coreopts) return false; *coreopts = runloop_core_options; } break; case RUNLOOP_CTL_SYSTEM_INFO_GET: { rarch_system_info_t **system = (rarch_system_info_t**)data; if (!system) return false; *system = &runloop_system; } break; case RUNLOOP_CTL_SYSTEM_INFO_FREE: /* No longer valid. */ if (runloop_system.subsystem.data) free(runloop_system.subsystem.data); runloop_system.subsystem.data = NULL; runloop_system.subsystem.size = 0; if (runloop_system.ports.data) free(runloop_system.ports.data); runloop_system.ports.data = NULL; runloop_system.ports.size = 0; if (runloop_system.mmaps.descriptors) free((void *)runloop_system.mmaps.descriptors); runloop_system.mmaps.descriptors = NULL; runloop_system.mmaps.num_descriptors = 0; runloop_key_event = NULL; runloop_frontend_key_event = NULL; audio_driver_unset_callback(); memset(&runloop_system, 0, sizeof(rarch_system_info_t)); break; case RUNLOOP_CTL_SET_FRAME_TIME_LAST: runloop_frame_time_last_enable = true; break; case RUNLOOP_CTL_UNSET_FRAME_TIME_LAST: if (!runloop_ctl(RUNLOOP_CTL_IS_FRAME_TIME_LAST, NULL)) return false; runloop_frame_time_last = 0; runloop_frame_time_last_enable = false; break; case RUNLOOP_CTL_SET_OVERRIDES_ACTIVE: runloop_overrides_active = true; break; case RUNLOOP_CTL_UNSET_OVERRIDES_ACTIVE: runloop_overrides_active = false; break; case RUNLOOP_CTL_IS_OVERRIDES_ACTIVE: return runloop_overrides_active; case RUNLOOP_CTL_SET_GAME_OPTIONS_ACTIVE: runloop_game_options_active = true; break; case RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE: runloop_game_options_active = false; break; case RUNLOOP_CTL_IS_GAME_OPTIONS_ACTIVE: return runloop_game_options_active; case RUNLOOP_CTL_IS_FRAME_TIME_LAST: return runloop_frame_time_last_enable; case RUNLOOP_CTL_SET_FRAME_LIMIT: runloop_set_frame_limit = true; break; case RUNLOOP_CTL_UNSET_FRAME_LIMIT: runloop_set_frame_limit = false; break; case RUNLOOP_CTL_SHOULD_SET_FRAME_LIMIT: return runloop_set_frame_limit; case RUNLOOP_CTL_GET_PERFCNT: { bool **perfcnt = (bool**)data; if (!perfcnt) return false; *perfcnt = &runloop_perfcnt_enable; } break; case RUNLOOP_CTL_SET_PERFCNT_ENABLE: runloop_perfcnt_enable = true; break; case RUNLOOP_CTL_UNSET_PERFCNT_ENABLE: runloop_perfcnt_enable = false; break; case RUNLOOP_CTL_IS_PERFCNT_ENABLE: return runloop_perfcnt_enable; case RUNLOOP_CTL_SET_NONBLOCK_FORCED: runloop_force_nonblock = true; break; case RUNLOOP_CTL_UNSET_NONBLOCK_FORCED: runloop_force_nonblock = false; break; case RUNLOOP_CTL_IS_NONBLOCK_FORCED: return runloop_force_nonblock; case RUNLOOP_CTL_SET_FRAME_TIME: { const struct retro_frame_time_callback *info = (const struct retro_frame_time_callback*)data; #ifdef HAVE_NETPLAY global_t *global = global_get_ptr(); /* retro_run() will be called in very strange and * mysterious ways, have to disable it. */ if (global->netplay.enable) return false; #endif runloop_frame_time = *info; } break; case RUNLOOP_CTL_GET_WINDOWED_SCALE: { unsigned **scale = (unsigned**)data; if (!scale) return false; *scale = (unsigned*)&runloop_pending_windowed_scale; } break; case RUNLOOP_CTL_SET_WINDOWED_SCALE: { unsigned *idx = (unsigned*)data; if (!idx) return false; runloop_pending_windowed_scale = *idx; } break; case RUNLOOP_CTL_SET_LIBRETRO_PATH: { const char *fullpath = (const char*)data; if (!fullpath) return false; strlcpy( settings->path.libretro, fullpath, sizeof(settings->path.libretro)); } break; case RUNLOOP_CTL_CLEAR_CONTENT_PATH: *runloop_fullpath = '\0'; break; case RUNLOOP_CTL_GET_CONTENT_PATH: { char **fullpath = (char**)data; if (!fullpath) return false; *fullpath = (char*)runloop_fullpath; } break; case RUNLOOP_CTL_SET_CONTENT_PATH: { const char *fullpath = (const char*)data; if (!fullpath) return false; strlcpy(runloop_fullpath, fullpath, sizeof(runloop_fullpath)); } break; case RUNLOOP_CTL_FRAME_TIME_FREE: memset(&runloop_frame_time, 0, sizeof(struct retro_frame_time_callback)); runloop_frame_time_last = 0; runloop_max_frames = 0; break; case RUNLOOP_CTL_STATE_FREE: runloop_perfcnt_enable = false; runloop_idle = false; runloop_paused = false; runloop_slowmotion = false; runloop_frame_time_last_enable = false; runloop_set_frame_limit = false; runloop_overrides_active = false; runloop_ctl(RUNLOOP_CTL_FRAME_TIME_FREE, NULL); break; case RUNLOOP_CTL_GLOBAL_FREE: { global_t *global = NULL; command_event(CMD_EVENT_TEMPORARY_CONTENT_DEINIT, NULL); command_event(CMD_EVENT_SUBSYSTEM_FULLPATHS_DEINIT, NULL); command_event(CMD_EVENT_RECORD_DEINIT, NULL); command_event(CMD_EVENT_LOG_FILE_DEINIT, NULL); rarch_ctl(RARCH_CTL_UNSET_BLOCK_CONFIG_READ, NULL); runloop_ctl(RUNLOOP_CTL_CLEAR_CONTENT_PATH, NULL); runloop_overrides_active = false; core_unset_input_descriptors(); global = global_get_ptr(); memset(global, 0, sizeof(struct global)); } break; case RUNLOOP_CTL_CLEAR_STATE: driver_ctl(RARCH_DRIVER_CTL_DEINIT, NULL); runloop_ctl(RUNLOOP_CTL_STATE_FREE, NULL); runloop_ctl(RUNLOOP_CTL_GLOBAL_FREE, NULL); break; case RUNLOOP_CTL_SET_MAX_FRAMES: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; runloop_max_frames = *ptr; } break; case RUNLOOP_CTL_IS_IDLE: return runloop_idle; case RUNLOOP_CTL_SET_IDLE: { bool *ptr = (bool*)data; if (!ptr) return false; runloop_idle = *ptr; } break; case RUNLOOP_CTL_IS_SLOWMOTION: return runloop_slowmotion; case RUNLOOP_CTL_SET_SLOWMOTION: { bool *ptr = (bool*)data; if (!ptr) return false; runloop_slowmotion = *ptr; } break; case RUNLOOP_CTL_SET_PAUSED: { bool *ptr = (bool*)data; if (!ptr) return false; runloop_paused = *ptr; } break; case RUNLOOP_CTL_IS_PAUSED: return runloop_paused; case RUNLOOP_CTL_MSG_QUEUE_PULL: runloop_msg_queue_lock(); { const char **ret = (const char**)data; if (!ret) return false; *ret = msg_queue_pull(runloop_msg_queue); } runloop_msg_queue_unlock(); break; case RUNLOOP_CTL_MSG_QUEUE_FREE: #ifdef HAVE_THREADS slock_free(_runloop_msg_queue_lock); _runloop_msg_queue_lock = NULL; #endif break; case RUNLOOP_CTL_MSG_QUEUE_CLEAR: msg_queue_clear(runloop_msg_queue); break; case RUNLOOP_CTL_MSG_QUEUE_DEINIT: if (!runloop_msg_queue) return true; runloop_msg_queue_lock(); msg_queue_free(runloop_msg_queue); runloop_msg_queue_unlock(); runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_FREE, NULL); runloop_msg_queue = NULL; break; case RUNLOOP_CTL_MSG_QUEUE_INIT: runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_DEINIT, NULL); runloop_msg_queue = msg_queue_new(8); retro_assert(runloop_msg_queue); #ifdef HAVE_THREADS _runloop_msg_queue_lock = slock_new(); retro_assert(_runloop_msg_queue_lock); #endif break; case RUNLOOP_CTL_TASK_INIT: { bool threaded_enable = false; #ifdef HAVE_THREADS threaded_enable = settings->threaded_data_runloop_enable; #endif task_queue_ctl(TASK_QUEUE_CTL_INIT, &threaded_enable); } break; case RUNLOOP_CTL_SET_CORE_SHUTDOWN: runloop_core_shutdown_initiated = true; break; case RUNLOOP_CTL_UNSET_CORE_SHUTDOWN: runloop_core_shutdown_initiated = false; break; case RUNLOOP_CTL_IS_CORE_SHUTDOWN: return runloop_core_shutdown_initiated; case RUNLOOP_CTL_SET_SHUTDOWN: runloop_shutdown_initiated = true; break; case RUNLOOP_CTL_UNSET_SHUTDOWN: runloop_shutdown_initiated = false; break; case RUNLOOP_CTL_IS_SHUTDOWN: return runloop_shutdown_initiated; case RUNLOOP_CTL_SET_EXEC: runloop_exec = true; break; case RUNLOOP_CTL_UNSET_EXEC: runloop_exec = false; break; case RUNLOOP_CTL_IS_EXEC: return runloop_exec; case RUNLOOP_CTL_DATA_DEINIT: task_queue_ctl(TASK_QUEUE_CTL_DEINIT, NULL); break; case RUNLOOP_CTL_IS_CORE_OPTION_UPDATED: if (!runloop_core_options) return false; return core_option_manager_updated(runloop_core_options); case RUNLOOP_CTL_CORE_OPTION_PREV: { unsigned *idx = (unsigned*)data; if (!idx) return false; core_option_manager_prev(runloop_core_options, *idx); if (ui_companion_is_on_foreground()) ui_companion_driver_notify_refresh(); } break; case RUNLOOP_CTL_CORE_OPTION_NEXT: { unsigned *idx = (unsigned*)data; if (!idx) return false; core_option_manager_next(runloop_core_options, *idx); if (ui_companion_is_on_foreground()) ui_companion_driver_notify_refresh(); } break; case RUNLOOP_CTL_CORE_OPTIONS_GET: { struct retro_variable *var = (struct retro_variable*)data; if (!runloop_core_options || !var) return false; RARCH_LOG("Environ GET_VARIABLE %s:\n", var->key); core_option_manager_get(runloop_core_options, var); RARCH_LOG("\t%s\n", var->value ? var->value : "N/A"); } break; case RUNLOOP_CTL_CORE_OPTIONS_INIT: { char *game_options_path = NULL; bool ret = false; char buf[PATH_MAX_LENGTH] = {0}; global_t *global = global_get_ptr(); const char *options_path = settings->path.core_options; const struct retro_variable *vars = (const struct retro_variable*)data; if (!*options_path && *global->path.config) { fill_pathname_resolve_relative(buf, global->path.config, "retroarch-core-options.cfg", sizeof(buf)); options_path = buf; } if (settings->game_specific_options) ret = rarch_game_specific_options(&game_options_path); if(ret) { runloop_ctl(RUNLOOP_CTL_SET_GAME_OPTIONS_ACTIVE, NULL); runloop_core_options = core_option_manager_new(game_options_path, vars); free(game_options_path); } else { runloop_ctl(RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE, NULL); runloop_core_options = core_option_manager_new(options_path, vars); } } break; case RUNLOOP_CTL_CORE_OPTIONS_FREE: if (runloop_core_options) core_option_manager_free(runloop_core_options); runloop_core_options = NULL; break; case RUNLOOP_CTL_CORE_OPTIONS_DEINIT: { global_t *global = global_get_ptr(); if (!runloop_core_options) return false; /* check if game options file was just created and flush to that file instead */ if(global && !string_is_empty(global->path.core_options_path)) { core_option_manager_flush_game_specific(runloop_core_options, global->path.core_options_path); global->path.core_options_path[0] = '\0'; } else core_option_manager_flush(runloop_core_options); if (runloop_ctl(RUNLOOP_CTL_IS_GAME_OPTIONS_ACTIVE, NULL)) runloop_ctl(RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE, NULL); runloop_ctl(RUNLOOP_CTL_CORE_OPTIONS_FREE, NULL); } break; case RUNLOOP_CTL_KEY_EVENT_GET: { retro_keyboard_event_t **key_event = (retro_keyboard_event_t**)data; if (!key_event) return false; *key_event = &runloop_key_event; } break; case RUNLOOP_CTL_FRONTEND_KEY_EVENT_GET: { retro_keyboard_event_t **key_event = (retro_keyboard_event_t**)data; if (!key_event) return false; *key_event = &runloop_frontend_key_event; } break; case RUNLOOP_CTL_NONE: default: break; } return true; }
static int add_adapter(void *data, struct libusb_device *dev) { int rc; struct libusb_device_descriptor desc; const char *device_name = NULL; struct libusb_adapter *old_head = NULL; struct libusb_hid *hid = (struct libusb_hid*)data; struct libusb_adapter *adapter = (struct libusb_adapter*) calloc(1, sizeof(struct libusb_adapter)); if (!adapter) return -1; if (!hid) { free(adapter); RARCH_ERR("Allocation of adapter failed.\n"); return -1; } rc = libusb_get_device_descriptor(dev, &desc); if (rc != LIBUSB_SUCCESS) { RARCH_ERR("Error getting device descriptor.\n"); goto error; } adapter->device = dev; libusb_get_description(adapter->device, adapter); if (adapter->endpoint_in == 0) { RARCH_ERR("Could not find HID config for device.\n"); goto error; } rc = libusb_open (adapter->device, &adapter->handle); if (rc != LIBUSB_SUCCESS) { RARCH_ERR("Error opening device 0x%p (VID/PID: %04x:%04x).\n", (void*)adapter->device, desc.idVendor, desc.idProduct); goto error; } if (desc.iManufacturer) { libusb_get_string_descriptor_ascii(adapter->handle, desc.iManufacturer, adapter->manufacturer_name, sizeof(adapter->manufacturer_name)); #if 0 RARCH_ERR(" Adapter Manufacturer name: %s\n", adapter->manufacturer_name); #endif } if (desc.iProduct) { libusb_get_string_descriptor_ascii(adapter->handle, desc.iProduct, adapter->name, sizeof(adapter->name)); #if 0 RARCH_ERR(" Adapter name: %s\n", adapter->name); #endif } device_name = (const char*)adapter->name; if (string_is_empty((const char*)adapter->name)) goto error; adapter->send_control_lock = slock_new(); adapter->send_control_buffer = fifo_new(4096); if (!adapter->send_control_lock || !adapter->send_control_buffer) { RARCH_ERR("Error creating send control buffer.\n"); goto error; } adapter->slot = pad_connection_pad_init(hid->slots, device_name, desc.idVendor, desc.idProduct, adapter, &libusb_hid_device_send_control); if (adapter->slot == -1) goto error; if (!pad_connection_has_interface(hid->slots, adapter->slot)) { RARCH_ERR(" Interface not found (%s).\n", adapter->name); goto error; } RARCH_LOG("Interface found: [%s].\n", adapter->name); if (libusb_kernel_driver_active(adapter->handle, 0) == 1 && libusb_detach_kernel_driver(adapter->handle, 0)) { RARCH_ERR("Error detaching handle 0x%p from kernel.\n", adapter->handle); goto error; } rc = libusb_claim_interface(adapter->handle, adapter->interface_number); if (rc != LIBUSB_SUCCESS) { RARCH_ERR("Error claiming interface %d .\n", adapter->interface_number); goto error; } RARCH_LOG("Device 0x%p attached (VID/PID: %04x:%04x).\n", adapter->device, desc.idVendor, desc.idProduct); libusb_hid_device_add_autodetect(adapter->slot, device_name, libusb_hid.ident, desc.idVendor, desc.idProduct); adapter->hid = hid; adapter->thread = sthread_create(adapter_thread, adapter); if (!adapter->thread) { RARCH_ERR("Error initializing adapter thread.\n"); goto error; } old_head = adapters.next; adapters.next = adapter; adapter->next = old_head; return 0; error: if (adapter->thread) sthread_join(adapter->thread); if (adapter->send_control_lock) slock_free(adapter->send_control_lock); if (adapter->send_control_buffer) fifo_free(adapter->send_control_buffer); if (adapter) free(adapter); return -1; }
/** * video_shader_resolve_parameters: * @conf : Preset file to read from. * @shader : Shader passes handle. * * Resolves all shader parameters belonging to shaders. * * Returns: true (1) if successful, otherwise false (0). **/ bool video_shader_resolve_parameters(config_file_t *conf, struct video_shader *shader) { unsigned i; struct video_shader_parameter *param = &shader->parameters[0]; shader->num_parameters = 0; /* Find all parameters in our shaders. */ for (i = 0; i < shader->passes; i++) { intfstream_t *file = NULL; size_t line_size = 4096 * sizeof(char); char *line = NULL; const char *path = shader->pass[i].source.path; if (string_is_empty(path)) continue; #if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS) /* First try to use the more robust slang * implementation to support #includes. */ /* FIXME: The check for slang can be removed * if it's sufficiently tested for * GLSL/Cg as well, it should be the same implementation. */ if (string_is_equal(path_get_extension(path), "slang") && slang_preprocess_parse_parameters(path, shader)) continue; /* If that doesn't work, fallback to the old path. * Ideally, we'd get rid of this path sooner or later. */ #endif file = intfstream_open_file(path, RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); if (!file) continue; line = (char*)malloc(4096 * sizeof(char)); line[0] = '\0'; /* even though the pass is set in the loop too, not all passes have parameters */ param->pass = i; while (shader->num_parameters < ARRAY_SIZE(shader->parameters) && intfstream_gets(file, line, line_size)) { int ret = sscanf(line, "#pragma parameter %63s \"%63[^\"]\" %f %f %f %f", param->id, param->desc, ¶m->initial, ¶m->minimum, ¶m->maximum, ¶m->step); if (ret < 5) continue; param->id[63] = '\0'; param->desc[63] = '\0'; if (ret == 5) param->step = 0.1f * (param->maximum - param->minimum); param->pass = i; RARCH_LOG("Found #pragma parameter %s (%s) %f %f %f %f in pass %d\n", param->desc, param->id, param->initial, param->minimum, param->maximum, param->step, param->pass); param->current = param->initial; shader->num_parameters++; param++; } free(line); intfstream_close(file); free(file); } if (conf && !video_shader_resolve_current_parameters(conf, shader)) return false; return true; }
/** * playlist_push: * @playlist : Playlist handle. * @path : Path of new playlist entry. * @core_path : Core path of new playlist entry. * @core_name : Core name of new playlist entry. * * Push entry to top of playlist. **/ bool playlist_push(playlist_t *playlist, const char *path, const char *label, const char *core_path, const char *core_name, const char *crc32, const char *db_name) { size_t i; if (string_is_empty(core_path) || string_is_empty(core_name)) { if (string_is_empty(core_name) && !string_is_empty(core_path)) { static char base_path[255] = {0}; fill_pathname_base_noext(base_path, core_path, sizeof(base_path)); core_name = base_path; RARCH_LOG("core_name is now: %s\n", core_name); } RARCH_LOG("core_name: %s.\n", string_is_empty(core_name) ? "N/A" : core_name); RARCH_LOG("core_path: %s.\n", string_is_empty(core_path) ? "N/A" : core_path); if (string_is_empty(core_path) || string_is_empty(core_name)) { RARCH_ERR("cannot push NULL or empty core name into the playlist.\n"); return false; } } if (string_is_empty(path)) path = NULL; if (!playlist) return false; for (i = 0; i < playlist->size; i++) { struct playlist_entry tmp; bool equal_path = (!path && !playlist->entries[i].path) || (path && playlist->entries[i].path && string_is_equal(path,playlist->entries[i].path)); /* Core name can have changed while still being the same core. * Differentiate based on the core path only. */ if (!equal_path) continue; if (!string_is_equal(playlist->entries[i].core_path, core_path)) continue; /* If top entry, we don't want to push a new entry since * the top and the entry to be pushed are the same. */ if (i == 0) return false; /* Seen it before, bump to top. */ tmp = playlist->entries[i]; memmove(playlist->entries + 1, playlist->entries, i * sizeof(struct playlist_entry)); playlist->entries[0] = tmp; return true; } if (playlist->size == playlist->cap) { struct playlist_entry *entry = &playlist->entries[playlist->cap - 1]; if (entry) playlist_free_entry(entry); playlist->size--; } memmove(playlist->entries + 1, playlist->entries, (playlist->cap - 1) * sizeof(struct playlist_entry)); playlist->entries[0].path = NULL; playlist->entries[0].label = NULL; playlist->entries[0].core_path = NULL; playlist->entries[0].core_name = NULL; playlist->entries[0].db_name = NULL; playlist->entries[0].crc32 = NULL; if (!string_is_empty(path)) playlist->entries[0].path = strdup(path); if (!string_is_empty(label)) playlist->entries[0].label = strdup(label); if (!string_is_empty(core_path)) playlist->entries[0].core_path = strdup(core_path); if (!string_is_empty(core_name)) playlist->entries[0].core_name = strdup(core_name); if (!string_is_empty(db_name)) playlist->entries[0].db_name = strdup(db_name); if (!string_is_empty(crc32)) playlist->entries[0].crc32 = strdup(crc32); playlist->size++; return true; }
void draw_atext(Canvas *canvas, Quark *q) { VPoint anchor; AText *at = atext_get_data(q); TextFrame *tf; view bbox; if (!at || string_is_empty(at->s)) { return; } if (Apoint2Vpoint(q, &at->ap, &anchor) != RETURN_SUCCESS) { return; } anchor.x += at->offset.x; anchor.y += at->offset.y; setclipping(canvas, FALSE); tf = &at->frame; drawtext(canvas, &anchor, &at->text_props, tf, at->s, &bbox); at->bb = bbox; if ((tf->line.pen.pattern || tf->fillpen.pattern) && at->arrow_flag && tf->line.style) { VPoint vp1, vp2; vp2.x = anchor.x - at->offset.x; vp2.y = anchor.y - at->offset.y; switch (tf->decor) { case FRAME_DECOR_LINE: if (vp2.x < bbox.xv1) { vp1.x = bbox.xv1; } else if (vp2.x > bbox.xv2) { vp1.x = bbox.xv2; } else { vp1.x = vp2.x; } vp1.y = bbox.yv1; break; case FRAME_DECOR_OVAL: if (vp2.x < bbox.xv1) { vp1.x = bbox.xv1; } else if (vp2.x > bbox.xv2) { vp1.x = bbox.xv2; } else { vp1.x = (bbox.xv1 + bbox.xv2)/2; } if (vp2.y < bbox.yv1) { vp1.y = bbox.yv1; } else if (vp2.y > bbox.yv2) { vp1.y = bbox.yv2; } else { vp1.y = (bbox.yv1 + bbox.yv2)/2; } break; default: if (vp2.x < bbox.xv1) { vp1.x = bbox.xv1; } else if (vp2.x > bbox.xv2) { vp1.x = bbox.xv2; } else { vp1.x = vp2.x; } if (vp2.y < bbox.yv1) { vp1.y = bbox.yv1; } else if (vp2.y > bbox.yv2) { vp1.y = bbox.yv2; } else { vp1.y = vp2.y; } } setline(canvas, &tf->line); DrawLine(canvas, &vp1, &vp2); draw_arrowhead(canvas, &vp1, &vp2, &at->arrow, &tf->line.pen, &tf->line.pen); } }
bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data) { static struct retro_system_info menu_driver_system; static bool menu_driver_pending_quick_menu = false; static bool menu_driver_pending_action = false; static bool menu_driver_prevent_populate = false; static bool menu_driver_load_no_content = false; static bool menu_driver_alive = false; static bool menu_driver_data_own = false; static bool menu_driver_pending_quit = false; static bool menu_driver_pending_shutdown = false; static content_playlist_t *menu_driver_playlist = NULL; static struct video_shader *menu_driver_shader = NULL; static menu_handle_t *menu_driver_data = NULL; static const menu_ctx_driver_t *menu_driver_ctx = NULL; static void *menu_userdata = NULL; settings_t *settings = config_get_ptr(); switch (state) { case RARCH_MENU_CTL_IS_PENDING_ACTION: if (!menu_driver_pending_action) return false; menu_driver_ctl(RARCH_MENU_CTL_UNSET_PENDING_ACTION, NULL); break; case RARCH_MENU_CTL_SET_PENDING_ACTION: menu_driver_pending_action = true; break; case RARCH_MENU_CTL_UNSET_PENDING_ACTION: menu_driver_pending_action = false; break; case RARCH_MENU_CTL_DRIVER_DATA_GET: { menu_handle_t **driver_data = (menu_handle_t**)data; if (!driver_data) return false; *driver_data = menu_driver_data; } break; case RARCH_MENU_CTL_IS_PENDING_QUICK_MENU: return menu_driver_pending_quick_menu; case RARCH_MENU_CTL_SET_PENDING_QUICK_MENU: menu_driver_pending_quick_menu = true; break; case RARCH_MENU_CTL_UNSET_PENDING_QUICK_MENU: menu_driver_pending_quick_menu = false; break; case RARCH_MENU_CTL_IS_PENDING_QUIT: return menu_driver_pending_quit; case RARCH_MENU_CTL_SET_PENDING_QUIT: menu_driver_pending_quit = true; break; case RARCH_MENU_CTL_UNSET_PENDING_QUIT: menu_driver_pending_quit = false; break; case RARCH_MENU_CTL_IS_PENDING_SHUTDOWN: return menu_driver_pending_shutdown; case RARCH_MENU_CTL_SET_PENDING_SHUTDOWN: menu_driver_pending_shutdown = true; break; case RARCH_MENU_CTL_UNSET_PENDING_SHUTDOWN: menu_driver_pending_shutdown = false; break; case RARCH_MENU_CTL_DESTROY: menu_driver_pending_quick_menu = false; menu_driver_pending_action = false; menu_driver_pending_quit = false; menu_driver_pending_shutdown = false; menu_driver_prevent_populate = false; menu_driver_load_no_content = false; menu_driver_alive = false; menu_driver_data_own = false; menu_driver_ctx = NULL; menu_userdata = NULL; break; case RARCH_MENU_CTL_PLAYLIST_FREE: if (menu_driver_playlist) content_playlist_free(menu_driver_playlist); menu_driver_playlist = NULL; break; case RARCH_MENU_CTL_FIND_DRIVER: { int i; driver_ctx_info_t drv; settings_t *settings = config_get_ptr(); drv.label = "menu_driver"; drv.s = settings->menu.driver; driver_ctl(RARCH_DRIVER_CTL_FIND_INDEX, &drv); i = drv.len; if (i >= 0) menu_driver_ctx = (const menu_ctx_driver_t*) menu_driver_find_handle(i); else { unsigned d; RARCH_WARN("Couldn't find any menu driver named \"%s\"\n", settings->menu.driver); RARCH_LOG_OUTPUT("Available menu drivers are:\n"); for (d = 0; menu_driver_find_handle(d); d++) RARCH_LOG_OUTPUT("\t%s\n", menu_driver_find_ident(d)); RARCH_WARN("Going to default to first menu driver...\n"); menu_driver_ctx = (const menu_ctx_driver_t*) menu_driver_find_handle(0); if (!menu_driver_ctx) { retro_fail(1, "find_menu_driver()"); return false; } } } break; case RARCH_MENU_CTL_PLAYLIST_INIT: { const char *path = (const char*)data; if (string_is_empty(path)) return false; menu_driver_playlist = content_playlist_init(path, COLLECTION_SIZE); } break; case RARCH_MENU_CTL_PLAYLIST_GET: { content_playlist_t **playlist = (content_playlist_t**)data; if (!playlist) return false; *playlist = menu_driver_playlist; } break; case RARCH_MENU_CTL_SYSTEM_INFO_GET: { struct retro_system_info **system = (struct retro_system_info**)data; if (!system) return false; *system = &menu_driver_system; } break; case RARCH_MENU_CTL_SYSTEM_INFO_DEINIT: #ifdef HAVE_DYNAMIC libretro_free_system_info(&menu_driver_system); memset(&menu_driver_system, 0, sizeof(struct retro_system_info)); #endif break; case RARCH_MENU_CTL_RENDER_MESSAGEBOX: if (menu_driver_ctx->render_messagebox) menu_driver_ctx->render_messagebox(menu_userdata, menu_driver_data->menu_state.msg); break; case RARCH_MENU_CTL_BLIT_RENDER: if (menu_driver_ctx->render) menu_driver_ctx->render(menu_userdata); break; case RARCH_MENU_CTL_RENDER: if (!menu_driver_data) return false; if (BIT64_GET(menu_driver_data->state, MENU_STATE_RENDER_FRAMEBUFFER) != BIT64_GET(menu_driver_data->state, MENU_STATE_RENDER_MESSAGEBOX)) BIT64_SET(menu_driver_data->state, MENU_STATE_RENDER_FRAMEBUFFER); if (BIT64_GET(menu_driver_data->state, MENU_STATE_RENDER_FRAMEBUFFER)) menu_display_ctl(MENU_DISPLAY_CTL_SET_FRAMEBUFFER_DIRTY_FLAG, NULL); if (BIT64_GET(menu_driver_data->state, MENU_STATE_RENDER_MESSAGEBOX) && !string_is_empty(menu_driver_data->menu_state.msg)) { menu_driver_ctl(RARCH_MENU_CTL_RENDER_MESSAGEBOX, NULL); if (ui_companion_is_on_foreground()) { const ui_companion_driver_t *ui = ui_companion_get_ptr(); if (ui->render_messagebox) ui->render_messagebox(menu_driver_data->menu_state.msg); } } if (BIT64_GET(menu_driver_data->state, MENU_STATE_BLIT)) { menu_animation_ctl(MENU_ANIMATION_CTL_UPDATE_TIME, NULL); menu_driver_ctl(RARCH_MENU_CTL_BLIT_RENDER, NULL); } if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL) && !runloop_ctl(RUNLOOP_CTL_IS_IDLE, NULL)) menu_display_ctl(MENU_DISPLAY_CTL_LIBRETRO, NULL); menu_driver_ctl(RARCH_MENU_CTL_SET_TEXTURE, NULL); menu_driver_data->state = 0; break; case RARCH_MENU_CTL_SHADER_DEINIT: #ifdef HAVE_SHADER_MANAGER if (menu_driver_shader) free(menu_driver_shader); menu_driver_shader = NULL; #endif break; case RARCH_MENU_CTL_SHADER_INIT: #ifdef HAVE_SHADER_MANAGER menu_driver_shader = (struct video_shader*) calloc(1, sizeof(struct video_shader)); if (!menu_driver_shader) return false; #endif break; case RARCH_MENU_CTL_SHADER_GET: { struct video_shader **shader = (struct video_shader**)data; if (!shader) return false; *shader = menu_driver_shader; } break; case RARCH_MENU_CTL_FRAME: if (!menu_driver_alive) return false; if (menu_driver_ctx->frame) menu_driver_ctx->frame(menu_userdata); break; case RARCH_MENU_CTL_SET_PREVENT_POPULATE: menu_driver_prevent_populate = true; break; case RARCH_MENU_CTL_UNSET_PREVENT_POPULATE: menu_driver_prevent_populate = false; break; case RARCH_MENU_CTL_IS_PREVENT_POPULATE: return menu_driver_prevent_populate; case RARCH_MENU_CTL_SET_TOGGLE: menu_driver_toggle(true); break; case RARCH_MENU_CTL_UNSET_TOGGLE: menu_driver_toggle(false); break; case RARCH_MENU_CTL_SET_ALIVE: menu_driver_alive = true; break; case RARCH_MENU_CTL_UNSET_ALIVE: menu_driver_alive = false; break; case RARCH_MENU_CTL_IS_ALIVE: return menu_driver_alive; case RARCH_MENU_CTL_SET_OWN_DRIVER: menu_driver_data_own = true; break; case RARCH_MENU_CTL_UNSET_OWN_DRIVER: if (!content_ctl(CONTENT_CTL_IS_INITED, NULL)) return false; menu_driver_data_own = false; break; case RARCH_MENU_CTL_SET_TEXTURE: if (menu_driver_ctx->set_texture) menu_driver_ctx->set_texture(); break; case RARCH_MENU_CTL_IS_SET_TEXTURE: if (!menu_driver_ctx) return false; return menu_driver_ctx->set_texture; case RARCH_MENU_CTL_OWNS_DRIVER: return menu_driver_data_own; case RARCH_MENU_CTL_DEINIT: menu_driver_ctl(RARCH_MENU_CTL_CONTEXT_DESTROY, NULL); if (menu_driver_ctl(RARCH_MENU_CTL_OWNS_DRIVER, NULL)) return true; if (menu_driver_data) { menu_driver_ctl(RARCH_MENU_CTL_PLAYLIST_FREE, NULL); menu_shader_free(menu_driver_data); menu_input_ctl(MENU_INPUT_CTL_DEINIT, NULL); menu_navigation_ctl(MENU_NAVIGATION_CTL_DEINIT, NULL); if (menu_driver_ctx && menu_driver_ctx->free) menu_driver_ctx->free(menu_userdata); if (menu_userdata) free(menu_userdata); menu_userdata = NULL; menu_driver_ctl(RARCH_MENU_CTL_SYSTEM_INFO_DEINIT, NULL); menu_display_ctl(MENU_DISPLAY_CTL_DEINIT, NULL); menu_entries_ctl(MENU_ENTRIES_CTL_DEINIT, NULL); event_cmd_ctl(EVENT_CMD_HISTORY_DEINIT, NULL); core_info_ctl(CORE_INFO_CTL_LIST_DEINIT, NULL); core_info_ctl(CORE_INFO_CTL_CURRENT_CORE_FREE, NULL); free(menu_driver_data); } menu_driver_data = NULL; break; case RARCH_MENU_CTL_INIT: if (menu_driver_data) return true; menu_driver_data = (menu_handle_t*) menu_driver_ctx->init(&menu_userdata); if (!menu_driver_data || !menu_init(menu_driver_data)) { retro_fail(1, "init_menu()"); return false; } strlcpy(settings->menu.driver, menu_driver_ctx->ident, sizeof(settings->menu.driver)); if (menu_driver_ctx->lists_init) { if (!menu_driver_ctx->lists_init(menu_driver_data)) { retro_fail(1, "init_menu()"); return false; } } break; case RARCH_MENU_CTL_LOAD_NO_CONTENT_GET: { bool **ptr = (bool**)data; if (!ptr) return false; *ptr = (bool*)&menu_driver_load_no_content; } break; case RARCH_MENU_CTL_HAS_LOAD_NO_CONTENT: return menu_driver_load_no_content; case RARCH_MENU_CTL_SET_LOAD_NO_CONTENT: menu_driver_load_no_content = true; break; case RARCH_MENU_CTL_UNSET_LOAD_NO_CONTENT: menu_driver_load_no_content = false; break; case RARCH_MENU_CTL_NAVIGATION_INCREMENT: if (menu_driver_ctx->navigation_increment) menu_driver_ctx->navigation_increment(menu_userdata); break; case RARCH_MENU_CTL_NAVIGATION_DECREMENT: if (menu_driver_ctx->navigation_decrement) menu_driver_ctx->navigation_decrement(menu_userdata); break; case RARCH_MENU_CTL_NAVIGATION_SET: { bool *scroll = (bool*)data; if (!scroll) return false; if (menu_driver_ctx->navigation_set) menu_driver_ctx->navigation_set(menu_userdata, *scroll); } break; case RARCH_MENU_CTL_NAVIGATION_SET_LAST: if (menu_driver_ctx->navigation_set_last) menu_driver_ctx->navigation_set_last(menu_userdata); break; case RARCH_MENU_CTL_NAVIGATION_ASCEND_ALPHABET: { size_t *ptr_out = (size_t*)data; if (!ptr_out) return false; if (menu_driver_ctx->navigation_ascend_alphabet) menu_driver_ctx->navigation_ascend_alphabet( menu_userdata, ptr_out); } case RARCH_MENU_CTL_NAVIGATION_DESCEND_ALPHABET: { size_t *ptr_out = (size_t*)data; if (!ptr_out) return false; if (menu_driver_ctx->navigation_descend_alphabet) menu_driver_ctx->navigation_descend_alphabet( menu_userdata, ptr_out); } break; case RARCH_MENU_CTL_NAVIGATION_CLEAR: { bool *pending_push = (bool*)data; if (!pending_push) return false; if (menu_driver_ctx->navigation_clear) menu_driver_ctx->navigation_clear( menu_userdata, pending_push); } break; case RARCH_MENU_CTL_POPULATE_ENTRIES: { menu_displaylist_info_t *info = (menu_displaylist_info_t*)data; if (!info) return false; if (menu_driver_ctx->populate_entries) menu_driver_ctx->populate_entries( menu_userdata, info->path, info->label, info->type); } break; case RARCH_MENU_CTL_LIST_GET_ENTRY: { menu_ctx_list_t *list = (menu_ctx_list_t*)data; if (!menu_driver_ctx || !menu_driver_ctx->list_get_entry) { list->entry = NULL; return false; } list->entry = menu_driver_ctx->list_get_entry(menu_userdata, list->type, list->idx); } break; case RARCH_MENU_CTL_LIST_GET_SIZE: { menu_ctx_list_t *list = (menu_ctx_list_t*)data; if (!menu_driver_ctx || !menu_driver_ctx->list_get_size) { list->size = 0; return false; } list->size = menu_driver_ctx->list_get_size(menu_userdata, list->type); } break; case RARCH_MENU_CTL_LIST_GET_SELECTION: { menu_ctx_list_t *list = (menu_ctx_list_t*)data; if (!menu_driver_ctx || !menu_driver_ctx->list_get_selection) { list->selection = 0; return false; } list->selection = menu_driver_ctx->list_get_selection(menu_userdata); } break; case RARCH_MENU_CTL_LIST_FREE: { menu_ctx_list_t *list = (menu_ctx_list_t*)data; if (menu_driver_ctx) { if (menu_driver_ctx->list_free) menu_driver_ctx->list_free(list->list, list->idx, list->list_size); } if (list->list) { file_list_free_userdata (list->list, list->idx); file_list_free_actiondata(list->list, list->idx); } } break; case RARCH_MENU_CTL_LIST_PUSH: { menu_ctx_displaylist_t *disp_list = (menu_ctx_displaylist_t*)data; if (menu_driver_ctx->list_push) if (menu_driver_ctx->list_push(menu_driver_data, menu_userdata, disp_list->info, disp_list->type) == 0) return true; } return false; case RARCH_MENU_CTL_LIST_CLEAR: { file_list_t *list = (file_list_t*)data; if (!list) return false; if (menu_driver_ctx->list_clear) menu_driver_ctx->list_clear(list); } break; case RARCH_MENU_CTL_TOGGLE: { bool *latch = (bool*)data; if (!latch) return false; if (menu_driver_ctx->toggle) menu_driver_ctx->toggle(menu_userdata, *latch); } break; case RARCH_MENU_CTL_REFRESH: { #if 0 bool refresh = false; menu_entries_ctl(MENU_ENTRIES_CTL_LIST_DEINIT, NULL); menu_entries_ctl(MENU_ENTRIES_CTL_SETTINGS_DEINIT, NULL); menu_entries_ctl(MENU_ENTRIES_CTL_INIT, NULL); menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh); #endif } break; case RARCH_MENU_CTL_CONTEXT_RESET: if (!menu_driver_ctx || !menu_driver_ctx->context_reset) return false; menu_driver_ctx->context_reset(menu_userdata); break; case RARCH_MENU_CTL_CONTEXT_DESTROY: if (!menu_driver_ctx || !menu_driver_ctx->context_destroy) return false; menu_driver_ctx->context_destroy(menu_userdata); break; case RARCH_MENU_CTL_SHADER_MANAGER_INIT: menu_shader_manager_init(menu_driver_data); break; case RARCH_MENU_CTL_LIST_SET_SELECTION: { file_list_t *list = (file_list_t*)data; if (!list) return false; if (!menu_driver_ctx || !menu_driver_ctx->list_set_selection) return false; menu_driver_ctx->list_set_selection(menu_userdata, list); } break; case RARCH_MENU_CTL_LIST_CACHE: { menu_ctx_list_t *list = (menu_ctx_list_t*)data; if (!list || !menu_driver_ctx || !menu_driver_ctx->list_cache) return false; menu_driver_ctx->list_cache(menu_userdata, list->type, list->action); } break; case RARCH_MENU_CTL_LIST_INSERT: { menu_ctx_list_t *list = (menu_ctx_list_t*)data; if (!list || !menu_driver_ctx || !menu_driver_ctx->list_insert) return false; menu_driver_ctx->list_insert(menu_userdata, list->list, list->path, list->label, list->idx); } break; case RARCH_MENU_CTL_LOAD_IMAGE: { menu_ctx_load_image_t *load_image_info = (menu_ctx_load_image_t*)data; if (!menu_driver_ctx || !menu_driver_ctx->load_image) return false; return menu_driver_ctx->load_image(menu_userdata, load_image_info->data, load_image_info->type); } case RARCH_MENU_CTL_ITERATE: { bool retcode = false; menu_ctx_iterate_t *iterate = (menu_ctx_iterate_t*)data; if (menu_driver_ctl(RARCH_MENU_CTL_IS_PENDING_QUICK_MENU, NULL)) { bool msg_force = true; menu_driver_ctl(RARCH_MENU_CTL_UNSET_PENDING_QUICK_MENU, NULL); menu_entries_flush_stack(NULL, MENU_SETTINGS); menu_display_ctl(MENU_DISPLAY_CTL_SET_MSG_FORCE, &msg_force); generic_action_ok_displaylist_push("", "", 0, 0, 0, ACTION_OK_DL_CONTENT_SETTINGS); if (menu_driver_ctl(RARCH_MENU_CTL_IS_PENDING_QUIT, NULL)) { menu_driver_ctl(RARCH_MENU_CTL_UNSET_PENDING_QUIT, NULL); return false; } return true; } if (menu_driver_ctl(RARCH_MENU_CTL_IS_PENDING_QUIT, NULL)) { menu_driver_ctl(RARCH_MENU_CTL_UNSET_PENDING_QUIT, NULL); return false; } if (menu_driver_ctl(RARCH_MENU_CTL_IS_PENDING_SHUTDOWN, NULL)) { menu_driver_ctl(RARCH_MENU_CTL_UNSET_PENDING_SHUTDOWN, NULL); if (!event_cmd_ctl(EVENT_CMD_QUIT, NULL)) return false; return true; } if (!menu_driver_ctx || !menu_driver_ctx->iterate) return false; if (menu_driver_ctl(RARCH_MENU_CTL_IS_PENDING_ACTION, &retcode)) { iterate->action = pending_iter.action; pending_iter.action = MENU_ACTION_NOOP; } if (menu_driver_ctx->iterate(menu_driver_data, menu_userdata, iterate->action) == -1) return false; } break; case RARCH_MENU_CTL_ENVIRONMENT: { menu_ctx_environment_t *menu_environ = (menu_ctx_environment_t*)data; if (menu_driver_ctx->environ_cb) { if (menu_driver_ctx->environ_cb(menu_environ->type, menu_environ->data, menu_userdata) == 0) return true; } } return false; case RARCH_MENU_CTL_POINTER_TAP: { menu_ctx_pointer_t *point = (menu_ctx_pointer_t*)data; if (!menu_driver_ctx || !menu_driver_ctx->pointer_tap) { point->retcode = 0; return false; } point->retcode = menu_driver_ctx->pointer_tap(menu_userdata, point->x, point->y, point->ptr, point->cbs, point->entry, point->action); } break; case RARCH_MENU_CTL_BIND_INIT: { menu_ctx_bind_t *bind = (menu_ctx_bind_t*)data; if (!menu_driver_ctx || !menu_driver_ctx->bind_init) { bind->retcode = 0; return false; } bind->retcode = menu_driver_ctx->bind_init( bind->cbs, bind->path, bind->label, bind->type, bind->idx, bind->elem0, bind->elem1, bind->label_hash, bind->menu_label_hash); } break; default: case RARCH_MENU_CTL_NONE: break; } return true; }
static bool load_content_from_compressed_archive( struct string_list *temporary_content, struct retro_game_info *info, unsigned i, struct string_list* additional_path_allocs, bool need_fullpath, const char *path) { union string_list_elem_attr attributes; char new_path[PATH_MAX_LENGTH]; char new_basedir[PATH_MAX_LENGTH]; ssize_t new_path_len = 0; bool ret = false; settings_t *settings = config_get_ptr(); rarch_system_info_t *sys_info= NULL; runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &sys_info); if (sys_info && sys_info->info.block_extract) return true; if (!need_fullpath || !path_contains_compressed_file(path)) return true; RARCH_LOG("Compressed file in case of need_fullpath." " Now extracting to temporary directory.\n"); strlcpy(new_basedir, settings->directory.cache, sizeof(new_basedir)); if (string_is_empty(new_basedir) || !path_is_directory(new_basedir)) { RARCH_WARN("Tried extracting to cache directory, but " "cache directory was not set or found. " "Setting cache directory to directory " "derived by basename...\n"); fill_pathname_basedir(new_basedir, path, sizeof(new_basedir)); } attributes.i = 0; fill_pathname_join(new_path, new_basedir, path_basename(path), sizeof(new_path)); ret = content_file_compressed_read(path, NULL, new_path, &new_path_len); if (!ret || new_path_len < 0) { RARCH_ERR("%s \"%s\".\n", msg_hash_to_str(MSG_COULD_NOT_READ_CONTENT_FILE), path); return false; } RARCH_LOG("New path is: [%s]\n", new_path); string_list_append(additional_path_allocs, new_path, attributes); info[i].path = additional_path_allocs->elems[additional_path_allocs->size -1 ].data; if (!string_list_append(temporary_content, new_path, attributes)) return false; return true; }
void fill_pathname_abbreviate_special(char *out_path, const char *in_path, size_t size) { #if !defined(RARCH_CONSOLE) unsigned i; const char *candidates[3]; const char *notations[3]; char *application_dir = (char*)malloc(PATH_MAX_LENGTH * sizeof(char)); const char *home = getenv("HOME"); application_dir[0] = '\0'; /* application_dir could be zero-string. Safeguard against this. * * Keep application dir in front of home, moving app dir to a * new location inside home would break otherwise. */ /* ugly hack - use application_dir pointer * before filling it in. C89 reasons */ candidates[0] = application_dir; candidates[1] = home; candidates[2] = NULL; notations [0] = ":"; notations [1] = "~"; notations [2] = NULL; fill_pathname_application_path(application_dir, PATH_MAX_LENGTH * sizeof(char)); path_basedir_wrapper(application_dir); for (i = 0; candidates[i]; i++) { if (!string_is_empty(candidates[i]) && strstr(in_path, candidates[i]) == in_path) { size_t src_size = strlcpy(out_path, notations[i], size); retro_assert(src_size < size); out_path += src_size; size -= src_size; in_path += strlen(candidates[i]); if (!path_char_is_slash(*in_path)) { retro_assert(strlcpy(out_path, path_default_slash(), size) < size); out_path++; size--; } break; /* Don't allow more abbrevs to take place. */ } } free(application_dir); #endif retro_assert(strlcpy(out_path, in_path, size) < size); }
static bool content_load_wrapper( content_ctx_info_t *content_info, bool launched_from_menu) { char name[PATH_MAX_LENGTH]; char msg[PATH_MAX_LENGTH]; char *fullpath = NULL; runloop_ctl(RUNLOOP_CTL_GET_CONTENT_PATH, &fullpath); #ifdef HAVE_MENU if (launched_from_menu) { /* redraw menu frame */ menu_display_set_msg_force(true); menu_driver_ctl(RARCH_MENU_CTL_RENDER, NULL); fill_pathname_base(name, fullpath, sizeof(name)); } #endif if (!content_load(content_info)) goto error; if (launched_from_menu) { /** Show loading OSD message */ if (*fullpath) { snprintf(msg, sizeof(msg), "INFO - Loading %s ...", name); runloop_msg_queue_push(msg, 1, 1, false); } } /* Push entry to top of history playlist */ if (content_is_inited() || content_does_not_need_content()) { char tmp[PATH_MAX_LENGTH]; struct retro_system_info *info = NULL; rarch_system_info_t *system = NULL; runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system); if (system) info = &system->info; #ifdef HAVE_MENU if (launched_from_menu) menu_driver_ctl(RARCH_MENU_CTL_SYSTEM_INFO_GET, &info); #endif strlcpy(tmp, fullpath, sizeof(tmp)); if (!launched_from_menu) { /* Path can be relative here. * Ensure we're pushing absolute path. */ if (*tmp) path_resolve_realpath(tmp, sizeof(tmp)); } if (info && *tmp) { content_push_to_history_playlist( true, tmp, info); playlist_write_file(g_defaults.history); } } return true; error: if (launched_from_menu) { if (!string_is_empty(fullpath) && !string_is_empty(name)) { snprintf(msg, sizeof(msg), "Failed to load %s.\n", name); runloop_msg_queue_push(msg, 1, 90, false); } } return false; }
void *rarch_task_push_http_transfer(const char *url, const char *type, retro_task_callback_t cb, void *user_data) { char tmp[PATH_MAX_LENGTH]; task_finder_data_t find_data; struct http_connection_t *conn = NULL; retro_task_t *t = NULL; http_handle_t *http = NULL; if (string_is_empty(url)) return NULL; find_data.func = rarch_task_http_finder; find_data.userdata = (void*)url; /* Concurrent download of the same file is not allowed */ if (task_queue_ctl(TASK_QUEUE_CTL_FIND, &find_data)) { RARCH_LOG("[http] '%s'' is already being downloaded.\n", url); return NULL; } conn = net_http_connection_new(url); if (!conn) return NULL; http = (http_handle_t*)calloc(1, sizeof(*http)); if (!http) goto error; http->connection.handle = conn; http->connection.cb = &cb_http_conn_default; if (type) strlcpy(http->connection.elem1, type, sizeof(http->connection.elem1)); strlcpy(http->connection.url, url, sizeof(http->connection.url)); http->status = HTTP_STATUS_CONNECTION_TRANSFER; t = (retro_task_t*)calloc(1, sizeof(*t)); if (!t) goto error; t->handler = rarch_task_http_transfer_handler; t->state = http; t->callback = cb; t->user_data = user_data; t->progress = -1; snprintf(tmp, sizeof(tmp), "%s '%s'", msg_hash_to_str(MSG_DOWNLOADING), path_basename(url)); t->title = strdup(tmp); task_queue_ctl(TASK_QUEUE_CTL_PUSH, t); return t; error: if (conn) net_http_connection_free(conn); if (http) free(http); return NULL; }
static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) { ChatContext *ctx = self->chatwin; int x, y, y2, x2; getyx(self->window, y, x); getmaxyx(self->window, y2, x2); if (x2 <= 0) return; /* ignore non-menu related input if active */ if (self->help->active) { help_onKey(self, key); return; } if (ltr) { /* char is printable */ input_new_char(self, key, x, y, x2, y2); return; } if (line_info_onKey(self, key)) return; input_handle(self, key, x, y, x2, y2); if (key == '\t') { /* TAB key: auto-completes command */ if (ctx->len > 1 && ctx->line[0] == '/') { int diff = -1; if (wcsncmp(ctx->line, L"/avatar \"", wcslen(L"/avatar \"")) == 0) diff = dir_match(self, m, ctx->line, L"/avatar"); else if (wcsncmp(ctx->line, L"/status ", wcslen(L"/status ")) == 0){ const char status_cmd_list[3][8] = { {"online"}, {"away"}, {"busy"}, }; diff = complete_line(self, status_cmd_list, 3, 8); } else diff = complete_line(self, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE); if (diff != -1) { if (x + diff > x2 - 1) { int wlen = MAX(0, wcswidth(ctx->line, sizeof(ctx->line) / sizeof(wchar_t))); ctx->start = wlen < x2 ? 0 : wlen - x2 + 1; } } else { sound_notify(self, notif_error, 0, NULL); } } else { sound_notify(self, notif_error, 0, NULL); } } else if (key == '\n') { rm_trailing_spaces_buf(ctx); char line[MAX_STR_SIZE] = {0}; if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) memset(&line, 0, sizeof(line)); if (!string_is_empty(line)) add_line_to_hist(ctx); line_info_add(self, NULL, NULL, NULL, PROMPT, 0, 0, "%s", line); execute(ctx->history, self, m, line, GLOBAL_COMMAND_MODE); wclear(ctx->linewin); wmove(self->window, y2 - CURS_Y_OFFSET, 0); reset_buf(ctx); } }
static int zarch_zui_render_lay_root_load(zui_t *zui, struct zui_tabbed *tabbed) { char parent_dir[PATH_MAX_LENGTH] = {0}; settings_t *settings = config_get_ptr(); core_info_list_t *list = NULL; if (zarch_zui_tab(zui, tabbed, "Load", 1)) { unsigned cwd_offset; if (!zui->load_cwd) zui->load_cwd = strdup(settings->directory.menu_content); if (!zui->load_dlist) { core_info_t *core_info = NULL; core_info_get_current_core(&core_info); zui->load_dlist = dir_list_new(zui->load_cwd, core_info->supported_extensions, true, true, false, true); dir_list_sort(zui->load_dlist, true); zui->load_dlist_first = 0; } cwd_offset = MIN(strlen(zui->load_cwd), 60); zarch_zui_draw_text(zui, ZUI_FG_NORMAL, 15, tabbed->tabline_size + 5 + 41, &zui->load_cwd[strlen(zui->load_cwd) - cwd_offset]); if (zarch_zui_button(zui, zui->width - 290 - 129, tabbed->tabline_size + 5, "Home")) zarch_zui_render_lay_root_load_free(zui); if (zui->load_dlist) { fill_pathname_parent_dir(parent_dir, zui->load_cwd, sizeof(parent_dir)); if (!string_is_empty(parent_dir) && zarch_zui_list_item(zui, tabbed, 0, tabbed->tabline_size + 73, " ..", 0, NULL, false /* TODO/FIXME */)) { zarch_zui_render_lay_root_load_set_new_path(zui, parent_dir); } else { static int gamepad_index = 0; unsigned size = zui->load_dlist->size; unsigned i, j = 1; unsigned skip = 0; for (i = 0; i < size; ++i) { const char *basename = path_basename(zui->load_dlist->elems[i].data); if (basename[0] != '.') break; skip++; } if (zarch_zui_gamepad_input(zui, &gamepad_index, &zui->load_dlist_first, skip)) zui->load_dlist_first = gamepad_index; for (i = skip + zui->load_dlist_first; i < size; ++i) { char label[PATH_MAX_LENGTH] = {0}; const char *path = NULL; const char *basename = NULL; if (j > 10) break; path = zui->load_dlist->elems[i].data; basename = path_basename(path); *label = 0; strncat(label, " ", sizeof(label)-1); strncat(label, basename, sizeof(label)-1); if (path_is_directory(path)) strncat(label, "/", sizeof(label)-1); if (zarch_zui_list_item(zui, tabbed, 0, tabbed->tabline_size + 73 + j * ZUI_ITEM_SIZE_PX, label, i, NULL, gamepad_index == (signed)(i-skip))) { if (path_is_directory(path)) { zarch_zui_render_lay_root_load_set_new_path(zui, path); break; } zui->pick_cores = NULL; zui->pick_supported = 0; strlcpy(zui->pick_content, path, sizeof(zui->pick_content)); core_info_get_list(&list); core_info_list_get_supported_cores(list, path, &zui->pick_cores, &zui->pick_supported); zarch_layout = LAY_PICK_CORE; break; } j++; } } } } else if (zui->load_dlist) { dir_list_free(zui->load_dlist); zui->load_dlist = NULL; } return 0; }
static void frontend_ps3_get_environment_settings(int *argc, char *argv[], void *args, void *params_data) { #ifndef IS_SALAMANDER bool original_verbose = verbosity_is_enabled(); verbosity_enable(); #endif (void)args; #ifndef IS_SALAMANDER #if defined(HAVE_LOGGER) logger_init(); #elif defined(HAVE_FILE_LOGGER) retro_main_log_file_init("/retroarch-log.txt"); #endif #endif int ret; unsigned int get_type; unsigned int get_attributes; CellGameContentSize size; char dirName[CELL_GAME_DIRNAME_SIZE] = {0}; #ifdef HAVE_MULTIMAN /* not launched from external launcher, set default path */ // second param is multiMAN SELF file if(path_file_exists(argv[2]) && *argc > 1 && (!strcmp(argv[2], EMULATOR_CONTENT_DIR))) { multiman_detected = true; RARCH_LOG("Started from multiMAN, auto-game start enabled.\n"); } else #endif #ifndef IS_SALAMANDER if (*argc > 1 && !string_is_empty(argv[1])) { static char path[PATH_MAX_LENGTH]; *path = '\0'; struct rarch_main_wrap *args = (struct rarch_main_wrap*)params_data; if (args) { strlcpy(path, argv[1], sizeof(path)); args->touched = true; args->no_content = false; args->verbose = false; args->config_path = NULL; args->sram_path = NULL; args->state_path = NULL; args->content_path = path; args->libretro_path = NULL; RARCH_LOG("argv[0]: %s\n", argv[0]); RARCH_LOG("argv[1]: %s\n", argv[1]); RARCH_LOG("argv[2]: %s\n", argv[2]); RARCH_LOG("Auto-start game %s.\n", argv[1]); } } else RARCH_WARN("Started from Salamander, auto-game start disabled.\n"); #endif memset(&size, 0x00, sizeof(CellGameContentSize)); ret = cellGameBootCheck(&get_type, &get_attributes, &size, dirName); if(ret < 0) { RARCH_ERR("cellGameBootCheck() Error: 0x%x.\n", ret); } else { char content_info_path[PATH_MAX_LENGTH] = {0}; RARCH_LOG("cellGameBootCheck() OK.\n"); RARCH_LOG("Directory name: [%s].\n", dirName); RARCH_LOG(" HDD Free Size (in KB) = [%d] Size (in KB) = [%d] System Size (in KB) = [%d].\n", size.hddFreeSizeKB, size.sizeKB, size.sysSizeKB); switch(get_type) { case CELL_GAME_GAMETYPE_DISC: RARCH_LOG("RetroArch was launched on Optical Disc Drive.\n"); break; case CELL_GAME_GAMETYPE_HDD: RARCH_LOG("RetroArch was launched on HDD.\n"); break; } if((get_attributes & CELL_GAME_ATTRIBUTE_APP_HOME) == CELL_GAME_ATTRIBUTE_APP_HOME) RARCH_LOG("RetroArch was launched from host machine (APP_HOME).\n"); ret = cellGameContentPermit(content_info_path, g_defaults.dir.port); #ifdef HAVE_MULTIMAN if (multiman_detected) { fill_pathname_join(content_info_path, "/dev_hdd0/game/", EMULATOR_CONTENT_DIR, sizeof(content_info_path)); fill_pathname_join(g_defaults.dir.port, content_info_path, "USRDIR", sizeof(g_defaults.dir.port)); } #endif if(ret < 0) RARCH_ERR("cellGameContentPermit() Error: 0x%x\n", ret); else { RARCH_LOG("cellGameContentPermit() OK.\n"); RARCH_LOG("content_info_path : [%s].\n", content_info_path); RARCH_LOG("usrDirPath : [%s].\n", g_defaults.dir.port); } fill_pathname_join(g_defaults.dir.core, g_defaults.dir.port, "cores", sizeof(g_defaults.dir.core)); fill_pathname_join(g_defaults.dir.core_info, g_defaults.dir.port, "cores", sizeof(g_defaults.dir.core_info)); fill_pathname_join(g_defaults.dir.savestate, g_defaults.dir.core, "savestates", sizeof(g_defaults.dir.savestate)); fill_pathname_join(g_defaults.dir.sram, g_defaults.dir.core, "savefiles", sizeof(g_defaults.dir.sram)); fill_pathname_join(g_defaults.dir.system, g_defaults.dir.core, "system", sizeof(g_defaults.dir.system)); fill_pathname_join(g_defaults.dir.shader, g_defaults.dir.core, "shaders_cg", sizeof(g_defaults.dir.shader)); fill_pathname_join(g_defaults.path.config, g_defaults.dir.port, "retroarch.cfg", sizeof(g_defaults.path.config)); fill_pathname_join(g_defaults.dir.overlay, g_defaults.dir.core, "overlays", sizeof(g_defaults.dir.overlay)); fill_pathname_join(g_defaults.dir.assets, g_defaults.dir.core, "assets", sizeof(g_defaults.dir.assets)); fill_pathname_join(g_defaults.dir.cursor, g_defaults.dir.core, "database/cursors", sizeof(g_defaults.dir.cursor)); fill_pathname_join(g_defaults.dir.database, g_defaults.dir.core, "database/rdb", sizeof(g_defaults.dir.database)); fill_pathname_join(g_defaults.dir.playlist, g_defaults.dir.core, "playlists", sizeof(g_defaults.dir.playlist)); } #ifndef IS_SALAMANDER if (original_verbose) verbosity_enable(); else verbosity_disable(); #endif }
static bool vita2d_gfx_frame(void *data, const void *frame, unsigned width, unsigned height, uint64_t frame_count, unsigned pitch, const char *msg) { void *tex_p; vita_video_t *vita = (vita_video_t *)data; (void)frame; (void)width; (void)height; (void)pitch; (void)msg; if (frame) { unsigned i, j; unsigned int stride; if ((width != vita->width || height != vita->height) && vita->texture) { vita2d_free_texture(vita->texture); vita->texture = NULL; } if (!vita->texture) { RARCH_LOG("Creating texture: %ix%i\n", width, height); vita->width = width; vita->height = height; vita->texture = vita2d_create_empty_texture_format(width, height, vita->format); vita2d_texture_set_filters(vita->texture,vita->tex_filter,vita->tex_filter); } tex_p = vita2d_texture_get_datap(vita->texture); stride = vita2d_texture_get_stride(vita->texture); if (vita->format == SCE_GXM_TEXTURE_FORMAT_X8U8U8U8_1RGB) { stride /= 4; pitch /= 4; uint32_t *tex32 = tex_p; const uint32_t *frame32 = frame; for (i = 0; i < height; i++) for (j = 0; j < width; j++) tex32[j + i*stride] = frame32[j + i*pitch]; } else { stride /= 2; pitch /= 2; uint16_t *tex16 = tex_p; const uint16_t *frame16 = frame; for (i = 0; i < height; i++) for (j = 0; j < width; j++) tex16[j + i*stride] = frame16[j + i*pitch]; } } if (vita->should_resize) vita2d_gfx_update_viewport(vita); vita2d_start_drawing(); vita2d_clear_screen(); if (vita->texture) { if (vita->fullscreen) vita2d_draw_texture_scale(vita->texture, 0, 0, PSP_FB_WIDTH / (float)vita->width, PSP_FB_HEIGHT / (float)vita->height); else { const float radian = 90 * 0.0174532925f; const float rad = vita->rotation * radian; float scalex = vita->vp.width / (float)vita->width; float scaley = vita->vp.height / (float)vita->height; vita2d_draw_texture_scale_rotate(vita->texture, vita->vp.x, vita->vp.y, scalex, scaley, rad); } } #ifdef HAVE_OVERLAY if (vita->overlay_enable) vita2d_render_overlay(vita); #endif if (vita->menu.active && vita->menu.texture) { if (vita->fullscreen) vita2d_draw_texture_scale(vita->menu.texture, 0, 0, PSP_FB_WIDTH / (float)vita->menu.width, PSP_FB_HEIGHT / (float)vita->menu.height); else { if (vita->menu.width > vita->menu.height) { float scale = PSP_FB_HEIGHT / (float)vita->menu.height; float w = vita->menu.width * scale; vita2d_draw_texture_scale(vita->menu.texture, PSP_FB_WIDTH / 2.0f - w/2.0f, 0.0f, scale, scale); } else { float scale = PSP_FB_WIDTH / (float)vita->menu.width; float h = vita->menu.height * scale; vita2d_draw_texture_scale(vita->menu.texture, 0.0f, PSP_FB_HEIGHT / 2.0f - h/2.0f, scale, scale); } } } if(!string_is_empty(msg)) font_driver_render_msg(NULL, msg, NULL); vita2d_end_drawing(); vita2d_swap_buffers(); return true; }
void path_set_redirect(void) { char new_savefile_dir[PATH_MAX_LENGTH]; char new_savestate_dir[PATH_MAX_LENGTH]; uint32_t library_name_hash = 0; bool check_library_name_hash = false; rarch_system_info_t *info = NULL; global_t *global = global_get_ptr(); const char *old_savefile_dir = dir_get(RARCH_DIR_SAVEFILE); const char *old_savestate_dir = dir_get(RARCH_DIR_SAVESTATE); new_savefile_dir[0] = new_savestate_dir[0] = '\0'; runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &info); if (info && info->info.library_name && !string_is_empty(info->info.library_name)) library_name_hash = msg_hash_calculate(info->info.library_name); /* Initialize current save directories * with the values from the config. */ strlcpy(new_savefile_dir, old_savefile_dir, sizeof(new_savefile_dir)); strlcpy(new_savestate_dir, old_savestate_dir, sizeof(new_savestate_dir)); check_library_name_hash = (library_name_hash != 0); #ifdef HAVE_MENU check_library_name_hash = check_library_name_hash && (library_name_hash != MENU_VALUE_NO_CORE); #endif if (check_library_name_hash) { settings_t *settings = config_get_ptr(); /* per-core saves: append the library_name to the save location */ if ( settings->sort_savefiles_enable && !string_is_empty(old_savefile_dir)) { fill_pathname_join( new_savefile_dir, old_savefile_dir, info->info.library_name, sizeof(new_savefile_dir)); /* If path doesn't exist, try to create it, * if everything fails revert to the original path. */ if(!path_is_directory(new_savefile_dir) && !string_is_empty(new_savefile_dir)) { path_mkdir(new_savefile_dir); if(!path_is_directory(new_savefile_dir)) { RARCH_LOG("%s %s\n", msg_hash_to_str(MSG_REVERTING_SAVEFILE_DIRECTORY_TO), old_savefile_dir); strlcpy(new_savefile_dir, old_savefile_dir, sizeof(new_savefile_dir)); } } } /* per-core states: append the library_name to the save location */ if (settings->sort_savestates_enable && !string_is_empty(old_savestate_dir)) { fill_pathname_join( new_savestate_dir, old_savestate_dir, info->info.library_name, sizeof(new_savestate_dir)); /* If path doesn't exist, try to create it. * If everything fails, revert to the original path. */ if(!path_is_directory(new_savestate_dir) && !string_is_empty(new_savestate_dir)) { path_mkdir(new_savestate_dir); if(!path_is_directory(new_savestate_dir)) { RARCH_LOG("%s %s\n", msg_hash_to_str(MSG_REVERTING_SAVESTATE_DIRECTORY_TO), old_savestate_dir); strlcpy(new_savestate_dir, old_savestate_dir, sizeof(new_savestate_dir)); } } } } /* Set savefile directory if empty based on content directory */ if (string_is_empty(new_savefile_dir)) { strlcpy(new_savefile_dir, path_main_basename, sizeof(new_savefile_dir)); path_basedir(new_savefile_dir); } if (global) { if(path_is_directory(new_savefile_dir)) strlcpy(global->name.savefile, new_savefile_dir, sizeof(global->name.savefile)); if(path_is_directory(new_savestate_dir)) strlcpy(global->name.savestate, new_savestate_dir, sizeof(global->name.savestate)); if (path_is_directory(global->name.savefile)) { fill_pathname_dir(global->name.savefile, path_main_basename, file_path_str(FILE_PATH_SRM_EXTENSION), sizeof(global->name.savefile)); RARCH_LOG("%s \"%s\".\n", msg_hash_to_str(MSG_REDIRECTING_SAVEFILE_TO), global->name.savefile); } if (path_is_directory(global->name.savestate)) { fill_pathname_dir(global->name.savestate, path_main_basename, file_path_str(FILE_PATH_STATE_EXTENSION), sizeof(global->name.savestate)); RARCH_LOG("%s \"%s\".\n", msg_hash_to_str(MSG_REDIRECTING_SAVESTATE_TO), global->name.savestate); } if (path_is_directory(global->name.cheatfile)) { fill_pathname_dir(global->name.cheatfile, path_main_basename, file_path_str(FILE_PATH_STATE_EXTENSION), sizeof(global->name.cheatfile)); RARCH_LOG("%s \"%s\".\n", msg_hash_to_str(MSG_REDIRECTING_CHEATFILE_TO), global->name.cheatfile); } } dir_set(RARCH_DIR_CURRENT_SAVEFILE, new_savefile_dir); dir_set(RARCH_DIR_CURRENT_SAVESTATE, new_savestate_dir); }
enum rarch_shader_type video_shader_get_type_from_ext( const char *ext, bool *is_preset) { enum gfx_ctx_api api = video_context_driver_get_api(); if (string_is_empty(ext)) return RARCH_SHADER_NONE; if (strlen(ext) > 1 && ext[0] == '.') ext++; *is_preset = false; if ( string_is_equal_case_insensitive(ext, "cg") ) { switch (api) { case GFX_CTX_DIRECT3D9_API: return RARCH_SHADER_CG; case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: { struct retro_hw_render_callback *hwr = video_driver_get_hw_context(); if (hwr) { switch (hwr->context_type) { case RETRO_HW_CONTEXT_OPENGLES2: case RETRO_HW_CONTEXT_OPENGL_CORE: case RETRO_HW_CONTEXT_OPENGLES3: return RARCH_SHADER_NONE; default: break; } } } return RARCH_SHADER_CG; default: break; } } if ( string_is_equal_case_insensitive(ext, "cgp") ) { *is_preset = true; switch (api) { case GFX_CTX_DIRECT3D9_API: return RARCH_SHADER_CG; case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: { struct retro_hw_render_callback *hwr = video_driver_get_hw_context(); if (hwr) { switch (hwr->context_type) { case RETRO_HW_CONTEXT_OPENGLES2: case RETRO_HW_CONTEXT_OPENGL_CORE: case RETRO_HW_CONTEXT_OPENGLES3: return RARCH_SHADER_NONE; default: break; } } } return RARCH_SHADER_CG; default: break; } } if ( string_is_equal_case_insensitive(ext, "glsl") ) { switch (api) { case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: return RARCH_SHADER_GLSL; default: break; } } if ( string_is_equal_case_insensitive(ext, "glslp") ) { *is_preset = true; switch (api) { case GFX_CTX_OPENGL_API: case GFX_CTX_OPENGL_ES_API: return RARCH_SHADER_GLSL; default: break; } } if ( string_is_equal_case_insensitive(ext, "slang") ) { switch (api) { case GFX_CTX_DIRECT3D10_API: case GFX_CTX_DIRECT3D11_API: case GFX_CTX_DIRECT3D12_API: case GFX_CTX_GX2_API: case GFX_CTX_VULKAN_API: case GFX_CTX_METAL_API: return RARCH_SHADER_SLANG; default: break; } } if ( string_is_equal_case_insensitive(ext, "slangp") ) { *is_preset = true; switch (api) { case GFX_CTX_DIRECT3D10_API: case GFX_CTX_DIRECT3D11_API: case GFX_CTX_DIRECT3D12_API: case GFX_CTX_GX2_API: case GFX_CTX_VULKAN_API: case GFX_CTX_METAL_API: return RARCH_SHADER_SLANG; default: break; } } return RARCH_SHADER_NONE; }
/** * rarch_environment_cb: * @cmd : Identifier of command. * @data : Pointer to data. * * Environment callback function implementation. * * Returns: true (1) if environment callback command could * be performed, otherwise false (0). **/ bool rarch_environment_cb(unsigned cmd, void *data) { unsigned p; settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); rarch_system_info_t *system = NULL; runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system); if (ignore_environment_cb) return false; switch (cmd) { case RETRO_ENVIRONMENT_GET_OVERSCAN: *(bool*)data = !settings->video.crop_overscan; RARCH_LOG("Environ GET_OVERSCAN: %u\n", (unsigned)!settings->video.crop_overscan); break; case RETRO_ENVIRONMENT_GET_CAN_DUPE: *(bool*)data = true; RARCH_LOG("Environ GET_CAN_DUPE: true\n"); break; case RETRO_ENVIRONMENT_GET_VARIABLE: { if (!runloop_ctl(RUNLOOP_CTL_CORE_OPTIONS_GET, data)) { struct retro_variable *var = (struct retro_variable*)data; if (var) { RARCH_LOG("Environ GET_VARIABLE %s: not implemented.\n", var->key); var->value = NULL; } } break; } case RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE: *(bool*)data = runloop_ctl(RUNLOOP_CTL_IS_CORE_OPTION_UPDATED, NULL); break; case RETRO_ENVIRONMENT_SET_VARIABLES: { RARCH_LOG("Environ SET_VARIABLES.\n"); runloop_ctl(RUNLOOP_CTL_CORE_OPTIONS_DEINIT, NULL); runloop_ctl(RUNLOOP_CTL_CORE_OPTIONS_INIT, data); break; } case RETRO_ENVIRONMENT_SET_MESSAGE: { const struct retro_message *msg = (const struct retro_message*)data; RARCH_LOG("Environ SET_MESSAGE: %s\n", msg->msg); runloop_msg_queue_push(msg->msg, 1, msg->frames, true); break; } case RETRO_ENVIRONMENT_SET_ROTATION: { unsigned rotation = *(const unsigned*)data; RARCH_LOG("Environ SET_ROTATION: %u\n", rotation); if (!settings->video.allow_rotate) break; system->rotation = rotation; if (!video_driver_set_rotation(rotation)) return false; break; } case RETRO_ENVIRONMENT_SHUTDOWN: RARCH_LOG("Environ SHUTDOWN.\n"); runloop_ctl(RUNLOOP_CTL_SET_SHUTDOWN, NULL); runloop_ctl(RUNLOOP_CTL_SET_CORE_SHUTDOWN, NULL); break; case RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL: system->performance_level = *(const unsigned*)data; RARCH_LOG("Environ PERFORMANCE_LEVEL: %u.\n", system->performance_level); break; case RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY: if (string_is_empty(settings->system_directory)) { char *fullpath = NULL; runloop_ctl(RUNLOOP_CTL_GET_CONTENT_PATH, &fullpath); RARCH_WARN("SYSTEM DIR is empty, assume CONTENT DIR %s\n", fullpath); fill_pathname_basedir(global->dir.systemdir, fullpath, sizeof(global->dir.systemdir)); *(const char**)data = global->dir.systemdir; RARCH_LOG("Environ SYSTEM_DIRECTORY: \"%s\".\n", global->dir.systemdir); } else { *(const char**)data = settings->system_directory; RARCH_LOG("Environ SYSTEM_DIRECTORY: \"%s\".\n", settings->system_directory); } break; case RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY: *(const char**)data = rarch_get_current_savefile_dir(); break; case RETRO_ENVIRONMENT_GET_USERNAME: *(const char**)data = *settings->username ? settings->username : NULL; RARCH_LOG("Environ GET_USERNAME: \"%s\".\n", settings->username); break; case RETRO_ENVIRONMENT_GET_LANGUAGE: *(unsigned *)data = settings->user_language; RARCH_LOG("Environ GET_LANGUAGE: \"%u\".\n", settings->user_language); break; case RETRO_ENVIRONMENT_SET_PIXEL_FORMAT: { enum retro_pixel_format pix_fmt = *(const enum retro_pixel_format*)data; switch (pix_fmt) { case RETRO_PIXEL_FORMAT_0RGB1555: RARCH_LOG("Environ SET_PIXEL_FORMAT: 0RGB1555.\n"); break; case RETRO_PIXEL_FORMAT_RGB565: RARCH_LOG("Environ SET_PIXEL_FORMAT: RGB565.\n"); break; case RETRO_PIXEL_FORMAT_XRGB8888: RARCH_LOG("Environ SET_PIXEL_FORMAT: XRGB8888.\n"); break; default: return false; } video_driver_set_pixel_format(pix_fmt); break; } case RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS: { unsigned retro_id, retro_port; const struct retro_input_descriptor *desc = NULL; static const char *libretro_btn_desc[] = { "B (bottom)", "Y (left)", "Select", "Start", "D-Pad Up", "D-Pad Down", "D-Pad Left", "D-Pad Right", "A (right)", "X (up)", "L", "R", "L2", "R2", "L3", "R3", }; memset(system->input_desc_btn, 0, sizeof(system->input_desc_btn)); desc = (const struct retro_input_descriptor*)data; for (; desc->description; desc++) { retro_port = desc->port; retro_id = desc->id; if (desc->port >= MAX_USERS) continue; /* Ignore all others for now. */ if (desc->device != RETRO_DEVICE_JOYPAD && desc->device != RETRO_DEVICE_ANALOG) continue; if (desc->id >= RARCH_FIRST_CUSTOM_BIND) continue; if (desc->device == RETRO_DEVICE_ANALOG) { switch (retro_id) { case RETRO_DEVICE_ID_ANALOG_X: switch (desc->index) { case RETRO_DEVICE_INDEX_ANALOG_LEFT: system->input_desc_btn[retro_port][RARCH_ANALOG_LEFT_X_PLUS] = desc->description; system->input_desc_btn[retro_port][RARCH_ANALOG_LEFT_X_MINUS] = desc->description; break; case RETRO_DEVICE_INDEX_ANALOG_RIGHT: system->input_desc_btn[retro_port][RARCH_ANALOG_RIGHT_X_PLUS] = desc->description; system->input_desc_btn[retro_port][RARCH_ANALOG_RIGHT_X_MINUS] = desc->description; break; } break; case RETRO_DEVICE_ID_ANALOG_Y: switch (desc->index) { case RETRO_DEVICE_INDEX_ANALOG_LEFT: system->input_desc_btn[retro_port][RARCH_ANALOG_LEFT_Y_PLUS] = desc->description; system->input_desc_btn[retro_port][RARCH_ANALOG_LEFT_Y_MINUS] = desc->description; break; case RETRO_DEVICE_INDEX_ANALOG_RIGHT: system->input_desc_btn[retro_port][RARCH_ANALOG_RIGHT_Y_PLUS] = desc->description; system->input_desc_btn[retro_port][RARCH_ANALOG_RIGHT_Y_MINUS] = desc->description; break; } break; } } else system->input_desc_btn[retro_port][retro_id] = desc->description; } RARCH_LOG("Environ SET_INPUT_DESCRIPTORS:\n"); for (p = 0; p < settings->input.max_users; p++) { for (retro_id = 0; retro_id < RARCH_FIRST_CUSTOM_BIND; retro_id++) { const char *description = system->input_desc_btn[p][retro_id]; if (!description) continue; RARCH_LOG("\tRetroPad, User %u, Button \"%s\" => \"%s\"\n", p + 1, libretro_btn_desc[retro_id], description); } } global->has_set.input_descriptors = true; break; } case RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK: { retro_keyboard_event_t *key_event = NULL; const struct retro_keyboard_callback *info = (const struct retro_keyboard_callback*)data; runloop_ctl(RUNLOOP_CTL_KEY_EVENT_GET, &key_event); if (!key_event) return false; RARCH_LOG("Environ SET_KEYBOARD_CALLBACK.\n"); *key_event = info->callback; global->frontend_key_event = *key_event; break; } case RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE: RARCH_LOG("Environ SET_DISK_CONTROL_INTERFACE.\n"); system->disk_control = *(const struct retro_disk_control_callback*)data; break; case RETRO_ENVIRONMENT_SET_HW_RENDER: case RETRO_ENVIRONMENT_SET_HW_RENDER | RETRO_ENVIRONMENT_EXPERIMENTAL: { struct retro_hw_render_callback *hw_render = video_driver_callback(); struct retro_hw_render_callback *cb = (struct retro_hw_render_callback*)data; RARCH_LOG("Environ SET_HW_RENDER.\n"); switch (cb->context_type) { case RETRO_HW_CONTEXT_NONE: RARCH_LOG("Requesting no HW context.\n"); break; #if defined(HAVE_OPENGLES2) case RETRO_HW_CONTEXT_OPENGLES2: #if defined(HAVE_OPENGLES3) case RETRO_HW_CONTEXT_OPENGLES3: #endif RARCH_LOG("Requesting OpenGLES%u context.\n", cb->context_type == RETRO_HW_CONTEXT_OPENGLES2 ? 2 : 3); break; #if defined(HAVE_OPENGLES3) case RETRO_HW_CONTEXT_OPENGLES_VERSION: RARCH_LOG("Requesting OpenGLES%u.%u context.\n", cb->version_major, cb->version_minor); break; #endif case RETRO_HW_CONTEXT_OPENGL: case RETRO_HW_CONTEXT_OPENGL_CORE: RARCH_ERR("Requesting OpenGL context, but RetroArch is compiled against OpenGLES2. Cannot use HW context.\n"); return false; #elif defined(HAVE_OPENGL) case RETRO_HW_CONTEXT_OPENGLES2: case RETRO_HW_CONTEXT_OPENGLES3: RARCH_ERR("Requesting OpenGLES%u context, but RetroArch is compiled against OpenGL. Cannot use HW context.\n", cb->context_type == RETRO_HW_CONTEXT_OPENGLES2 ? 2 : 3); return false; case RETRO_HW_CONTEXT_OPENGLES_VERSION: RARCH_ERR("Requesting OpenGLES%u.%u context, but RetroArch is compiled against OpenGL. Cannot use HW context.\n", cb->version_major, cb->version_minor); return false; case RETRO_HW_CONTEXT_OPENGL: RARCH_LOG("Requesting OpenGL context.\n"); break; case RETRO_HW_CONTEXT_OPENGL_CORE: RARCH_LOG("Requesting core OpenGL context (%u.%u).\n", cb->version_major, cb->version_minor); break; #endif default: RARCH_LOG("Requesting unknown context.\n"); return false; } cb->get_current_framebuffer = video_driver_get_current_framebuffer; cb->get_proc_address = video_driver_get_proc_address; if (cmd & RETRO_ENVIRONMENT_EXPERIMENTAL) /* Old ABI. Don't copy garbage. */ memcpy(hw_render, cb, offsetof(struct retro_hw_render_callback, stencil)); else memcpy(hw_render, cb, sizeof(*cb)); break; } case RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME: { bool state = *(const bool*)data; RARCH_LOG("Environ SET_SUPPORT_NO_GAME: %s.\n", state ? "yes" : "no"); system->no_content = state; break; } case RETRO_ENVIRONMENT_GET_LIBRETRO_PATH: { const char **path = (const char**)data; #ifdef HAVE_DYNAMIC *path = settings->libretro; #else *path = NULL; #endif break; } /* FIXME - PS3 audio driver needs to be fixed so that threaded * audio works correctly (audio is already on a thread for PS3 * audio driver so that's probably the problem) */ #if defined(HAVE_THREADS) && !defined(__CELLOS_LV2__) case RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK: { const struct retro_audio_callback *info = (const struct retro_audio_callback*)data; RARCH_LOG("Environ SET_AUDIO_CALLBACK.\n"); if (recording_driver_get_data_ptr()) /* A/V sync is a must. */ return false; #ifdef HAVE_NETPLAY if (global->netplay.enable) return false; #endif audio_driver_set_callback(info); break; } #endif case RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK: { const struct retro_frame_time_callback *info = (const struct retro_frame_time_callback*)data; RARCH_LOG("Environ SET_FRAME_TIME_CALLBACK.\n"); #ifdef HAVE_NETPLAY /* retro_run() will be called in very strange and * mysterious ways, have to disable it. */ if (global->netplay.enable) return false; #endif system->frame_time = *info; break; } case RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE: { struct retro_rumble_interface *iface = (struct retro_rumble_interface*)data; RARCH_LOG("Environ GET_RUMBLE_INTERFACE.\n"); iface->set_rumble_state = input_driver_set_rumble_state; break; } case RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES: { uint64_t *mask = (uint64_t*)data; RARCH_LOG("Environ GET_INPUT_DEVICE_CAPABILITIES.\n"); if (input_driver_ctl(RARCH_INPUT_CTL_HAS_CAPABILITIES, NULL)) *mask = input_driver_get_capabilities(); else return false; break; } case RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE: { struct retro_sensor_interface *iface = (struct retro_sensor_interface*)data; RARCH_LOG("Environ GET_SENSOR_INTERFACE.\n"); iface->set_sensor_state = input_sensor_set_state; iface->get_sensor_input = input_sensor_get_input; break; } case RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE: { struct retro_camera_callback *cb = (struct retro_camera_callback*)data; RARCH_LOG("Environ GET_CAMERA_INTERFACE.\n"); cb->start = driver_camera_start; cb->stop = driver_camera_stop; system->camera_callback = *cb; if (cb->caps != 0) camera_driver_ctl(RARCH_CAMERA_CTL_SET_ACTIVE, NULL); else camera_driver_ctl(RARCH_CAMERA_CTL_UNSET_ACTIVE, NULL); break; } case RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE: { struct retro_location_callback *cb = (struct retro_location_callback*)data; RARCH_LOG("Environ GET_LOCATION_INTERFACE.\n"); cb->start = driver_location_start; cb->stop = driver_location_stop; cb->get_position = driver_location_get_position; cb->set_interval = driver_location_set_interval; system->location_callback = *cb; location_driver_ctl(RARCH_LOCATION_CTL_UNSET_ACTIVE, NULL); break; } case RETRO_ENVIRONMENT_GET_LOG_INTERFACE: { struct retro_log_callback *cb = (struct retro_log_callback*)data; RARCH_LOG("Environ GET_LOG_INTERFACE.\n"); cb->log = rarch_log_libretro; break; } case RETRO_ENVIRONMENT_GET_PERF_INTERFACE: { struct retro_perf_callback *cb = (struct retro_perf_callback*)data; RARCH_LOG("Environ GET_PERF_INTERFACE.\n"); cb->get_time_usec = retro_get_time_usec; cb->get_cpu_features = retro_get_cpu_features; cb->get_perf_counter = retro_get_perf_counter; cb->perf_register = retro_perf_register; /* libretro specific path. */ cb->perf_start = retro_perf_start; cb->perf_stop = retro_perf_stop; cb->perf_log = retro_perf_log; /* libretro specific path. */ break; } case RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY: { const char **dir = (const char**)data; *dir = *settings->core_assets_directory ? settings->core_assets_directory : NULL; RARCH_LOG("Environ CORE_ASSETS_DIRECTORY: \"%s\".\n", settings->core_assets_directory); break; } case RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO: { RARCH_LOG("Environ SET_SYSTEM_AV_INFO.\n"); return driver_ctl(RARCH_DRIVER_CTL_UPDATE_SYSTEM_AV_INFO, (void**)&data); } case RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO: { unsigned i, j; const struct retro_subsystem_info *info = (const struct retro_subsystem_info*)data; RARCH_LOG("Environ SET_SUBSYSTEM_INFO.\n"); for (i = 0; info[i].ident; i++) { RARCH_LOG("Special game type: %s\n", info[i].desc); RARCH_LOG(" Ident: %s\n", info[i].ident); RARCH_LOG(" ID: %u\n", info[i].id); RARCH_LOG(" Content:\n"); for (j = 0; j < info[i].num_roms; j++) { RARCH_LOG(" %s (%s)\n", info[i].roms[j].desc, info[i].roms[j].required ? "required" : "optional"); } } free(system->special); system->special = (struct retro_subsystem_info*) calloc(i, sizeof(*system->special)); if (!system->special) return false; memcpy(system->special, info, i * sizeof(*system->special)); system->num_special = i; break; } case RETRO_ENVIRONMENT_SET_CONTROLLER_INFO: { unsigned i, j; const struct retro_controller_info *info = (const struct retro_controller_info*)data; RARCH_LOG("Environ SET_CONTROLLER_INFO.\n"); for (i = 0; info[i].types; i++) { RARCH_LOG("Controller port: %u\n", i + 1); for (j = 0; j < info[i].num_types; j++) RARCH_LOG(" %s (ID: %u)\n", info[i].types[j].desc, info[i].types[j].id); } free(system->ports); system->ports = (struct retro_controller_info*) calloc(i, sizeof(*system->ports)); if (!system->ports) return false; memcpy(system->ports, info, i * sizeof(*system->ports)); system->num_ports = i; break; } case RETRO_ENVIRONMENT_SET_GEOMETRY: { struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); const struct retro_game_geometry *in_geom = (const struct retro_game_geometry*)data; struct retro_game_geometry *geom = av_info ? (struct retro_game_geometry*)&av_info->geometry : NULL; if (!geom) return false; RARCH_LOG("Environ SET_GEOMETRY.\n"); /* Can potentially be called every frame, * don't do anything unless required. */ if (geom->base_width != in_geom->base_width || geom->base_height != in_geom->base_height || geom->aspect_ratio != in_geom->aspect_ratio) { geom->base_width = in_geom->base_width; geom->base_height = in_geom->base_height; geom->aspect_ratio = in_geom->aspect_ratio; RARCH_LOG("SET_GEOMETRY: %ux%u, aspect: %.3f.\n", geom->base_width, geom->base_height, geom->aspect_ratio); /* Forces recomputation of aspect ratios if * using core-dependent aspect ratios. */ event_command(EVENT_CMD_VIDEO_SET_ASPECT_RATIO); /* TODO: Figure out what to do, if anything, with recording. */ } break; } case RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER: return video_driver_get_current_software_framebuffer((struct retro_framebuffer*)data); /* Private extensions for internal use, not part of libretro API. */ case RETRO_ENVIRONMENT_SET_LIBRETRO_PATH: RARCH_LOG("Environ (Private) SET_LIBRETRO_PATH.\n"); if (!path_file_exists((const char*)data)) return false; runloop_ctl(RUNLOOP_CTL_SET_LIBRETRO_PATH, data); break; case RETRO_ENVIRONMENT_EXEC: case RETRO_ENVIRONMENT_EXEC_ESCAPE: { char *fullpath = NULL; runloop_ctl(RUNLOOP_CTL_GET_CONTENT_PATH, &fullpath); if (fullpath != data) { runloop_ctl(RUNLOOP_CTL_CLEAR_CONTENT_PATH, NULL); if (data) runloop_ctl(RUNLOOP_CTL_SET_CONTENT_PATH, data); } #if defined(RARCH_CONSOLE) frontend_driver_set_fork(true, true, false); #elif defined(HAVE_DYNAMIC) rarch_ctl(RARCH_CTL_LOAD_CONTENT, NULL); #endif if (cmd == RETRO_ENVIRONMENT_EXEC_ESCAPE) { RARCH_LOG("Environ (Private) EXEC_ESCAPE.\n"); runloop_ctl(RUNLOOP_CTL_SET_EXEC, NULL); } else RARCH_LOG("Environ (Private) EXEC.\n"); } break; default: RARCH_LOG("Environ UNSUPPORTED (#%u).\n", cmd); return false; } return true; }
static void prompt_onKey(ToxWindow *self, Tox *m, wint_t key, bool ltr) { ChatContext *ctx = self->chatwin; int x, y, y2, x2; getyx(ctx->history, y, x); getmaxyx(ctx->history, y2, x2); if (ltr) { if (ctx->len < (MAX_STR_SIZE - 1)) { add_char_to_buf(ctx, key); } } else { /* if (!ltr) */ /* BACKSPACE key: Remove one character from line */ if (key == 0x107 || key == 0x8 || key == 0x7f) { if (ctx->pos > 0) { del_char_buf_bck(ctx); wmove(ctx->history, y, x - 1); /* not necessary but fixes a display glitch */ } else { beep(); } } else if (key == KEY_DC) { /* DEL key: Remove character at pos */ if (ctx->pos != ctx->len) { del_char_buf_frnt(ctx); } else { beep(); } } else if (key == T_KEY_DISCARD) { /* CTRL-U: Delete entire line behind pos */ if (ctx->pos > 0) { wmove(ctx->history, ctx->orig_y, X_OFST); wclrtobot(ctx->history); discard_buf(ctx); } else { beep(); } } else if (key == T_KEY_KILL) { /* CTRL-K: Delete entire line in front of pos */ if (ctx->len != ctx->pos) kill_buf(ctx); else beep(); } else if (key == KEY_HOME || key == T_KEY_C_A) { /* HOME/C-a key: Move cursor to start of line */ if (ctx->pos != 0) ctx->pos = 0; } else if (key == KEY_END || key == T_KEY_C_E) { /* END/C-e key: move cursor to end of line */ if (ctx->pos != ctx->len) ctx->pos = ctx->len; } else if (key == KEY_LEFT) { if (ctx->pos > 0) --ctx->pos; else beep(); } else if (key == KEY_RIGHT) { if (ctx->pos < ctx->len) ++ctx->pos; else beep(); } else if (key == KEY_UP) { /* fetches previous item in history */ wmove(ctx->history, ctx->orig_y, X_OFST); fetch_hist_item(ctx, MOVE_UP); /* adjust line y origin appropriately when window scrolls down */ if (ctx->at_bottom && ctx->len >= x2 - X_OFST) { int px2 = ctx->len >= x2 ? x2 : x2 - X_OFST; int p_ofst = px2 != x2 ? 0 : X_OFST; if (px2 <= 0) return; int k = ctx->orig_y + ((ctx->len + p_ofst) / px2); if (k >= y2) { --ctx->orig_y; } } } else if (key == KEY_DOWN) { /* fetches next item in history */ wmove(ctx->history, ctx->orig_y, X_OFST); fetch_hist_item(ctx, MOVE_DOWN); } else if (key == '\t') { /* TAB key: completes command */ if (ctx->len > 1 && ctx->line[0] == '/') { if (complete_line(ctx, glob_cmd_list, AC_NUM_GLOB_COMMANDS, MAX_CMDNAME_SIZE) == -1) beep(); } else { beep(); } } /* RETURN key: execute command */ else if (key == '\n') { rm_trailing_spaces_buf(ctx); wprintw(ctx->history, "\n"); uint8_t line[MAX_STR_SIZE] = {0}; if (wcs_to_mbs_buf(line, ctx->line, MAX_STR_SIZE) == -1) memset(&line, 0, sizeof(line)); if (!string_is_empty(line)) add_line_to_hist(ctx); line_info_add(self, NULL, NULL, NULL, line, PROMPT, 0, 0); execute(ctx->history, self, m, line, GLOBAL_COMMAND_MODE); reset_buf(ctx); } } }