Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
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;
    }
}