void input_context::display_help() { inp_mngr.set_timeout(-1); // Shamelessly stolen from help.cpp WINDOW *w_help = newwin(FULL_SCREEN_HEIGHT - 2, FULL_SCREEN_WIDTH - 2, 1 + (int)((TERMY > FULL_SCREEN_HEIGHT) ? (TERMY - FULL_SCREEN_HEIGHT) / 2 : 0), 1 + (int)((TERMX > FULL_SCREEN_WIDTH) ? (TERMX - FULL_SCREEN_WIDTH) / 2 : 0)); // has the user changed something? bool changed = false; // keybindings before the user changed anything. input_manager::t_action_contexts old_action_contexts(inp_mngr.action_contexts); // current status: adding/removing/showing keybindings enum { s_remove, s_add, s_add_global, s_show } status = s_show; // copy of registered_actions, but without the ANY_INPUT and COORDINATE, which should not be shown std::vector<std::string> org_registered_actions(registered_actions); std::vector<std::string>::iterator any_input = std::find(org_registered_actions.begin(), org_registered_actions.end(), ANY_INPUT); if (any_input != org_registered_actions.end()) { org_registered_actions.erase(any_input); } std::vector<std::string>::iterator coordinate = std::find(org_registered_actions.begin(), org_registered_actions.end(), COORDINATE); if (coordinate != org_registered_actions.end()) { org_registered_actions.erase(coordinate); } // colors of the keybindings static const nc_color global_key = c_ltgray; static const nc_color local_key = c_ltgreen; static const nc_color unbound_key = c_ltred; // (vertical) scroll offset size_t scroll_offset = 0; // height of the area usable for display of keybindings, excludes headers & borders const size_t display_height = FULL_SCREEN_HEIGHT - 9 - 2; // -2 for the border // width of the legend const size_t legwidth = FULL_SCREEN_WIDTH - 4 - 2; // keybindings help std::ostringstream legend; legend << "<color_" << string_from_color(unbound_key) << ">" << _("Unbound keys") << "</color>\n"; legend << "<color_" << string_from_color(local_key) << ">" << _("Keybinding active only on this screen") << "</color>\n"; legend << "<color_" << string_from_color(global_key) << ">" << _("Keybinding active globally") << "</color>\n"; legend << _("Press - to remove keybinding\nPress + to add local keybinding\nPress = to add global keybinding\n"); input_context ctxt("HELP_KEYBINDINGS"); ctxt.register_action("UP", _("Scroll up")); ctxt.register_action("DOWN", _("Scroll down")); ctxt.register_action("PAGE_DOWN"); ctxt.register_action("PAGE_UP"); ctxt.register_action("REMOVE"); ctxt.register_action("ADD_LOCAL"); ctxt.register_action("ADD_GLOBAL"); ctxt.register_action("QUIT"); ctxt.register_action("ANY_INPUT"); if (category != "HELP_KEYBINDINGS") { // avoiding inception! ctxt.register_action("HELP_KEYBINDINGS"); } std::string hotkeys = ctxt.get_available_single_char_hotkeys(display_help_hotkeys); while(true) { werase(w_help); draw_border(w_help); draw_scrollbar(w_help, scroll_offset, display_height, org_registered_actions.size() - display_height, 8); mvwprintz(w_help, 0, (FULL_SCREEN_WIDTH - utf8_width(_("Keybindings"))) / 2 - 1, c_ltred, " %s ", _("Keybindings")); fold_and_print(w_help, 1, 2, legwidth, c_white, legend.str()); for (size_t i = 0; i + scroll_offset < org_registered_actions.size() && i < display_height; i++) { const std::string &action_id = org_registered_actions[i + scroll_offset]; bool overwrite_default; const action_attributes &attributes = inp_mngr.get_action_attributes(action_id, category, &overwrite_default); char invlet; if (i < hotkeys.size()) { invlet = hotkeys[i]; } else { invlet = ' '; } if (status == s_add_global && overwrite_default) { // We're trying to add a global, but this action has a local // defined, so gray out the invlet. mvwprintz(w_help, i + 8, 2, c_dkgray, "%c ", invlet); } else if (status == s_add || status == s_add_global) { mvwprintz(w_help, i + 8, 2, c_blue, "%c ", invlet); } else if (status == s_remove) { mvwprintz(w_help, i + 8, 2, c_blue, "%c ", invlet); } else { mvwprintz(w_help, i + 8, 2, c_blue, " "); } nc_color col; if (attributes.input_events.empty()) { col = unbound_key; } else if (overwrite_default) { col = local_key; } else { col = global_key; } mvwprintz(w_help, i + 8, 4, col, "%s: ", get_action_name(action_id).c_str()); mvwprintz(w_help, i + 8, 52, col, "%s", get_desc(action_id).c_str()); } wrefresh(w_help); refresh(); // In addition to the modifiable hotkeys, we also check for hardcoded // keys, e.g. '+', '-', '=', in order to prevent the user from // entering an unrecoverable state. const std::string action = ctxt.handle_input(); const long raw_input_char = ctxt.get_raw_input().get_first_input(); if (action == "ADD_LOCAL" || raw_input_char == '+') { status = s_add; } else if (action == "ADD_GLOBAL" || raw_input_char == '=') { status = s_add_global; } else if (action == "REMOVE" || raw_input_char == '-') { status = s_remove; } else if (action == "ANY_INPUT") { const size_t hotkey_index = hotkeys.find_first_of(raw_input_char); if (status == s_show || hotkey_index == std::string::npos ) { continue; } const size_t action_index = hotkey_index + scroll_offset; if( action_index >= org_registered_actions.size() ) { continue; } const std::string &action_id = org_registered_actions[action_index]; // Check if this entry is local or global. bool is_local = false; inp_mngr.get_action_attributes(action_id, category, &is_local); const std::string name = get_action_name(action_id); if (status == s_remove && (!OPTIONS["QUERY_KEYBIND_REMOVAL"] || query_yn(_("Clear keys for %s?"), name.c_str()))) { // If it's global, reset the global actions. std::string category_to_access = category; if (!is_local) { category_to_access = default_context_id; } inp_mngr.remove_input_for_action(action_id, category_to_access); changed = true; } else if (status == s_add_global && is_local) { // Disallow adding global actions to an action that already has a local defined. popup(_("There are already local keybindings defined for this action, please remove them first.")); } else if (status == s_add || status == s_add_global) { const long newbind = popup_getkey(_("New key for %s:"), name.c_str()); const input_event new_event(newbind, CATA_INPUT_KEYBOARD); const std::string conflicts = get_conflicts(new_event); const bool has_conflicts = !conflicts.empty(); bool resolve_conflicts = false; if (has_conflicts) { resolve_conflicts = query_yn( _("This key conflicts with %s. Remove this key from the conflicting command(s), and continue?"), conflicts.c_str()); } if (!has_conflicts || resolve_conflicts) { if (resolve_conflicts) { clear_conflicting_keybindings(new_event); } // We might be adding a local or global action. std::string category_to_access = category; if (status == s_add_global) { category_to_access = default_context_id; } inp_mngr.add_input_for_action(action_id, category_to_access, new_event); changed = true; } } status = s_show; } else if (action == "DOWN") { if (scroll_offset < org_registered_actions.size() - display_height) { scroll_offset++; } } else if (action == "UP") { if (scroll_offset > 0) { scroll_offset--; } } else if (action == "PAGE_DOWN") { if( scroll_offset + display_height < org_registered_actions.size() ) { scroll_offset += std::min(display_height, org_registered_actions.size() - display_height - scroll_offset); } else if( org_registered_actions.size() > display_height ) { scroll_offset = 0; } } else if( action == "PAGE_UP" ) { if( scroll_offset >= display_height ) { scroll_offset -= display_height; } else if( scroll_offset > 0 ) { scroll_offset = 0; } else if( org_registered_actions.size() > display_height ) { scroll_offset = org_registered_actions.size() - display_height; } } else if (action == "QUIT") { if (status != s_show) { status = s_show; } else { break; } } else if (action == "HELP_KEYBINDINGS") { // update available hotkeys in case they've changed hotkeys = ctxt.get_available_single_char_hotkeys(display_help_hotkeys); } } if (changed && query_yn(_("Save changes?"))) { try { inp_mngr.save(); } catch(std::exception &err) { popup(_("saving keybindings failed: %s"), err.what()); } catch(std::string &err) { popup(_("saving keybindings failed: %s"), err.c_str()); } } else if(changed) { inp_mngr.action_contexts.swap(old_action_contexts); } werase(w_help); wrefresh(w_help); delwin(w_help); }
static void verify_package (Package *pkg) { GSList *requires = NULL; GSList *conflicts = NULL; GSList *system_directories = NULL; GSList *iter; GSList *requires_iter; GSList *conflicts_iter; GSList *system_dir_iter = NULL; int count; gchar *c_include_path; /* Be sure we have the required fields */ if (pkg->key == NULL) { fprintf (stderr, "Internal pkg-config error, package with no key, please file a bug report\n"); exit (1); } if (pkg->name == NULL) { verbose_error ("Package '%s' has no Name: field\n", pkg->key); exit (1); } if (pkg->version == NULL) { verbose_error ("Package '%s' has no Version: field\n", pkg->key); exit (1); } if (pkg->description == NULL) { verbose_error ("Package '%s' has no Description: field\n", pkg->key); exit (1); } /* Make sure we have the right version for all requirements */ iter = pkg->requires_private; while (iter != NULL) { Package *req = iter->data; RequiredVersion *ver = NULL; if (pkg->required_versions) ver = g_hash_table_lookup (pkg->required_versions, req->key); if (ver) { if (!version_test (ver->comparison, req->version, ver->version)) { verbose_error ("Package '%s' requires '%s %s %s' but version of %s is %s\n", pkg->name, req->key, comparison_to_str (ver->comparison), ver->version, req->name, req->version); if (req->url) verbose_error ("You may find new versions of %s at %s\n", req->name, req->url); exit (1); } } iter = g_slist_next (iter); } /* Make sure we didn't drag in any conflicts via Requires * (inefficient algorithm, who cares) */ recursive_fill_list (pkg, get_requires_private, &requires); conflicts = get_conflicts (pkg); requires_iter = requires; while (requires_iter != NULL) { Package *req = requires_iter->data; conflicts_iter = conflicts; while (conflicts_iter != NULL) { RequiredVersion *ver = conflicts_iter->data; if (version_test (ver->comparison, req->version, ver->version)) { verbose_error ("Version %s of %s creates a conflict.\n" "(%s %s %s conflicts with %s %s)\n", req->version, req->name, ver->name, comparison_to_str (ver->comparison), ver->version ? ver->version : "(any)", ver->owner->name, ver->owner->version); exit (1); } conflicts_iter = g_slist_next (conflicts_iter); } requires_iter = g_slist_next (requires_iter); } g_slist_free (requires); /* We make a list of system directories that gcc expects so we can remove * them. */ #ifndef G_OS_WIN32 system_directories = g_slist_append (NULL, g_strdup ("/usr/include")); #endif c_include_path = g_getenv ("C_INCLUDE_PATH"); if (c_include_path != NULL) { system_directories = add_env_variable_to_list (system_directories, c_include_path); } c_include_path = g_getenv ("CPLUS_INCLUDE_PATH"); if (c_include_path != NULL) { system_directories = add_env_variable_to_list (system_directories, c_include_path); } count = 0; iter = pkg->I_cflags; while (iter != NULL) { gint offset = 0; /* we put things in canonical -I/usr/include (vs. -I /usr/include) format, * but if someone changes it later we may as well be robust */ if (((strncmp (iter->data, "-I", 2) == 0) && (offset = 2))|| ((strncmp (iter->data, "-I ", 3) == 0) && (offset = 3))) { if (offset == 0) { iter = iter->next; continue; } system_dir_iter = system_directories; while (system_dir_iter != NULL) { if (strcmp (system_dir_iter->data, ((char*)iter->data) + offset) == 0) { debug_spew ("Package %s has %s in Cflags\n", pkg->name, (gchar *)iter->data); if (g_getenv ("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS") == NULL) { debug_spew ("Removing %s from cflags for %s\n", iter->data, pkg->key); ++count; iter->data = NULL; break; } } system_dir_iter = system_dir_iter->next; } } iter = iter->next; } while (count) { pkg->I_cflags = g_slist_remove (pkg->I_cflags, NULL); --count; } g_slist_foreach (system_directories, (GFunc) g_free, NULL); g_slist_free (system_directories); #ifdef PREFER_LIB64 #define SYSTEM_LIBDIR "/usr/lib64" #else #define SYSTEM_LIBDIR "/usr/lib" #endif count = 0; iter = pkg->L_libs; while (iter != NULL) { if (strcmp (iter->data, "-L" SYSTEM_LIBDIR) == 0 || strcmp (iter->data, "-L " SYSTEM_LIBDIR) == 0) { debug_spew ("Package %s has -L" SYSTEM_LIBDIR " in Libs\n", pkg->name); if (g_getenv ("PKG_CONFIG_ALLOW_SYSTEM_LIBS") == NULL) { iter->data = NULL; ++count; debug_spew ("Removing -L" SYSTEM_LIBDIR " from libs for %s\n", pkg->key); } } iter = iter->next; } #undef SYSTEM_LIBDIR while (count) { pkg->L_libs = g_slist_remove (pkg->L_libs, NULL); --count; } }