ask_algo (ctrl_t ctrl, int addmode, int *r_subkey_algo, unsigned int *r_usage,
          char **r_keygrip)
{
  char *keygrip = NULL;
  char *answer = NULL;
  int algo;
  int dummy_algo;

  if (!r_subkey_algo)
    r_subkey_algo = &dummy_algo;

  tty_printf (_("Please select what kind of key you want:\n"));

#if GPG_USE_RSA
  if (!addmode)
    tty_printf (_("   (%d) RSA and RSA (default)\n"), 1 );
#endif

  if (!addmode)
    tty_printf (_("   (%d) DSA and Elgamal\n"), 2 );

  tty_printf (_("   (%d) DSA (sign only)\n"), 3 );
#if GPG_USE_RSA
  tty_printf (_("   (%d) RSA (sign only)\n"), 4 );
#endif

  if (addmode)
    {
      tty_printf (_("   (%d) Elgamal (encrypt only)\n"), 5 );
#if GPG_USE_RSA
      tty_printf (_("   (%d) RSA (encrypt only)\n"), 6 );
#endif
    }
  if (opt.expert)
    {
      tty_printf (_("   (%d) DSA (set your own capabilities)\n"), 7 );
#if GPG_USE_RSA
      tty_printf (_("   (%d) RSA (set your own capabilities)\n"), 8 );
#endif
    }

#if GPG_USE_ECDSA || GPG_USE_ECDH || GPG_USE_EDDSA
  if (opt.expert && !addmode)
    tty_printf (_("   (%d) ECC and ECC\n"), 9 );
  if (opt.expert)
    tty_printf (_("  (%d) ECC (sign only)\n"), 10 );
  if (opt.expert)
    tty_printf (_("  (%d) ECC (set your own capabilities)\n"), 11 );
  if (opt.expert && addmode)
    tty_printf (_("  (%d) ECC (encrypt only)\n"), 12 );
#endif

  if (opt.expert && r_keygrip)
    tty_printf (_("  (%d) Existing key\n"), 13 );

  for (;;)
    {
      *r_usage = 0;
      *r_subkey_algo = 0;
      xfree (answer);
      answer = cpr_get ("keygen.algo", _("Your selection? "));
      cpr_kill_prompt ();
      algo = *answer? atoi (answer) : 1;
      if ((algo == 1 || !strcmp (answer, "rsa+rsa")) && !addmode)
        {
          algo = PUBKEY_ALGO_RSA;
          *r_subkey_algo = PUBKEY_ALGO_RSA;
          break;
	}
      else if ((algo == 2 || !strcmp (answer, "dsa+elg")) && !addmode)
        {
          algo = PUBKEY_ALGO_DSA;
          *r_subkey_algo = PUBKEY_ALGO_ELGAMAL_E;
          break;
	}
      else if (algo == 3 || !strcmp (answer, "dsa"))
        {
          algo = PUBKEY_ALGO_DSA;
          *r_usage = PUBKEY_USAGE_SIG;
          break;
	}
      else if (algo == 4 || !strcmp (answer, "rsa/s"))
        {
          algo = PUBKEY_ALGO_RSA;
          *r_usage = PUBKEY_USAGE_SIG;
          break;
	}
      else if ((algo == 5 || !strcmp (answer, "elg")) && addmode)
        {
          algo = PUBKEY_ALGO_ELGAMAL_E;
          *r_usage = PUBKEY_USAGE_ENC;
          break;
	}
      else if ((algo == 6 || !strcmp (answer, "rsa/e")) && addmode)
        {
          algo = PUBKEY_ALGO_RSA;
          *r_usage = PUBKEY_USAGE_ENC;
          break;
	}
      else if ((algo == 7 || !strcmp (answer, "dsa/*")) && opt.expert)
        {
          algo = PUBKEY_ALGO_DSA;
          *r_usage = ask_key_flags (algo, addmode);
          break;
	}
      else if ((algo == 8 || !strcmp (answer, "rsa/*")) && opt.expert)
        {
          algo = PUBKEY_ALGO_RSA;
          *r_usage = ask_key_flags (algo, addmode);
          break;
	}
      else if ((algo == 9 || !strcmp (answer, "ecc+ecc"))
               && opt.expert && !addmode)
        {
          algo = PUBKEY_ALGO_ECDSA;
          *r_subkey_algo = PUBKEY_ALGO_ECDH;
          break;
	}
      else if ((algo == 10 || !strcmp (answer, "ecc/s")) && opt.expert)
        {
          algo = PUBKEY_ALGO_ECDSA;
          *r_usage = PUBKEY_USAGE_SIG;
          break;
	}
      else if ((algo == 11 || !strcmp (answer, "ecc/*")) && opt.expert)
        {
          algo = PUBKEY_ALGO_ECDSA;
          *r_usage = ask_key_flags (algo, addmode);
          break;
	}
      else if ((algo == 12 || !strcmp (answer, "ecc/e"))
               && opt.expert && addmode)
        {
          algo = PUBKEY_ALGO_ECDH;
          *r_usage = PUBKEY_USAGE_ENC;
          break;
	}
      else if ((algo == 13 || !strcmp (answer, "keygrip"))
               && opt.expert && r_keygrip)
        {
          for (;;)
            {
              xfree (answer);
              answer = tty_get (_("Enter the keygrip: "));
              tty_kill_prompt ();
              trim_spaces (answer);
              if (!*answer)
                {
                  xfree (answer);
                  answer = NULL;
                  continue;
                }

              if (strlen (answer) != 40 &&
                       !(answer[0] == '&' && strlen (answer+1) == 40))
                tty_printf
                  (_("Not a valid keygrip (expecting 40 hex digits)\n"));
              else if (!(algo = check_keygrip (ctrl, answer)) )
                tty_printf (_("No key with this keygrip\n"));
              else
                break; /* Okay.  */
            }
          xfree (keygrip);
          keygrip = answer;
          answer = NULL;
          *r_usage = ask_key_flags (algo, addmode);
          break;
	}
      else
        tty_printf (_("Invalid selection.\n"));

    }

  xfree(answer);
  if (r_keygrip)
    *r_keygrip = keygrip;
  return algo;
}