ask_user_id (int mode, int full, KBNODE keyblock)
{
    char *answer;
    char *aname, *acomment, *amail, *uid;

    if ( !mode )
      {
        /* TRANSLATORS: This is the new string telling the user what
           gpg is now going to do (i.e. ask for the parts of the user
           ID).  Note that if you do not translate this string, a
           different string will be used, which might still have
           a correct translation.  */
	const char *s1 =
          N_("\n"
             "GnuPG needs to construct a user ID to identify your key.\n"
             "\n");
        const char *s2 = _(s1);

        if (!strcmp (s1, s2))
          {
            /* There is no translation for the string thus we to use
               the old info text.  gettext has no way to tell whether
               a translation is actually available, thus we need to
               to compare again. */
            /* TRANSLATORS: This string is in general not anymore used
               but you should keep your existing translation.  In case
               the new string is not translated this old string will
               be used. */
            const char *s3 = N_("\n"
"You need a user ID to identify your key; "
                                        "the software constructs the user ID\n"
"from the Real Name, Comment and Email Address in this form:\n"
"    \"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>\"\n\n");
            const char *s4 = _(s3);
            if (strcmp (s3, s4))
              s2 = s3; /* A translation exists - use it. */
          }
        tty_printf ("%s", s2) ;
      }
    uid = aname = acomment = amail = NULL;
    for(;;) {
	char *p;
	int fail=0;

	if( !aname ) {
	    for(;;) {
		xfree(aname);
		aname = cpr_get("keygen.name",_("Real name: "));
		trim_spaces(aname);
		cpr_kill_prompt();

		if( opt.allow_freeform_uid )
		    break;

		if( strpbrk( aname, "<>" ) )
		    tty_printf(_("Invalid character in name\n"));
		else if( digitp(aname) )
		    tty_printf(_("Name may not start with a digit\n"));
		else if( strlen(aname) < 5 )
		    tty_printf(_("Name must be at least 5 characters long\n"));
		else
		    break;
	    }
	}
	if( !amail ) {
	    for(;;) {
		xfree(amail);
		amail = cpr_get("keygen.email",_("Email address: "));
		trim_spaces(amail);
		cpr_kill_prompt();
		if( !*amail || opt.allow_freeform_uid )
		    break;   /* no email address is okay */
		else if ( !is_valid_mailbox (amail) )
                    tty_printf(_("Not a valid email address\n"));
		else
		    break;
	    }
	}
	if (!acomment) {
          if (full) {
	    for(;;) {
		xfree(acomment);
		acomment = cpr_get("keygen.comment",_("Comment: "));
		trim_spaces(acomment);
		cpr_kill_prompt();
		if( !*acomment )
		    break;   /* no comment is okay */
		else if( strpbrk( acomment, "()" ) )
		    tty_printf(_("Invalid character in comment\n"));
		else
		    break;
	    }
          }
          else {
            xfree (acomment);
            acomment = xstrdup ("");
          }
	}


	xfree(uid);
	uid = p = xmalloc(strlen(aname)+strlen(amail)+strlen(acomment)+12+10);
	p = stpcpy(p, aname );
	if( *acomment )
	    p = stpcpy(stpcpy(stpcpy(p," ("), acomment),")");
	if( *amail )
	    p = stpcpy(stpcpy(stpcpy(p," <"), amail),">");

	/* Append a warning if the RNG is switched into fake mode.  */
        if ( random_is_faked ()  )
          strcpy(p, " (insecure!)" );

	/* print a note in case that UTF8 mapping has to be done */
	for(p=uid; *p; p++ ) {
	    if( *p & 0x80 ) {
		tty_printf(_("You are using the '%s' character set.\n"),
			   get_native_charset() );
		break;
	    }
	}

	tty_printf(_("You selected this USER-ID:\n    \"%s\"\n\n"), uid);

	if( !*amail && !opt.allow_freeform_uid
	    && (strchr( aname, '@' ) || strchr( acomment, '@'))) {
	    fail = 1;
            tty_printf(_("Please don't put the email address "
                         "into the real name or the comment\n") );
	}

        if (!fail && keyblock)
          {
            PKT_user_id *uidpkt = uid_from_string (uid);
            KBNODE node;

            for (node=keyblock; node && !fail; node=node->next)
              if (!is_deleted_kbnode (node)
                  && node->pkt->pkttype == PKT_USER_ID
                  && !cmp_user_ids (uidpkt, node->pkt->pkt.user_id))
		fail = 1;
            if (fail)
              tty_printf (_("Such a user ID already exists on this key!\n"));
            free_user_id (uidpkt);
          }

	for(;;) {
            /* TRANSLATORS: These are the allowed answers in
               lower and uppercase.  Below you will find the matching
               string which should be translated accordingly and the
               letter changed to match the one in the answer string.

                 n = Change name
                 c = Change comment
                 e = Change email
                 o = Okay (ready, continue)
                 q = Quit
             */
	    const char *ansstr = _("NnCcEeOoQq");

	    if( strlen(ansstr) != 10 )
		BUG();
	    if( cpr_enabled() ) {
                answer = xstrdup (ansstr + (fail?8:6));
		answer[1] = 0;
	    }
            else if (full) {
		answer = cpr_get("keygen.userid.cmd", fail?
		  _("Change (N)ame, (C)omment, (E)mail or (Q)uit? ") :
		  _("Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? "));
		cpr_kill_prompt();
            }
            else {
		answer = cpr_get("keygen.userid.cmd", fail?
		  _("Change (N)ame, (E)mail, or (Q)uit? ") :
		  _("Change (N)ame, (E)mail, or (O)kay/(Q)uit? "));
		cpr_kill_prompt();
	    }
	    if( strlen(answer) > 1 )
		;
	    else if( *answer == ansstr[0] || *answer == ansstr[1] ) {
		xfree(aname); aname = NULL;
		break;
	    }
	    else if( *answer == ansstr[2] || *answer == ansstr[3] ) {
		xfree(acomment); acomment = NULL;
		break;
	    }
	    else if( *answer == ansstr[4] || *answer == ansstr[5] ) {
		xfree(amail); amail = NULL;
		break;
	    }
	    else if( *answer == ansstr[6] || *answer == ansstr[7] ) {
		if( fail ) {
		    tty_printf(_("Please correct the error first\n"));
		}
		else {
		    xfree(aname); aname = NULL;
		    xfree(acomment); acomment = NULL;
		    xfree(amail); amail = NULL;
		    break;
		}
	    }
	    else if( *answer == ansstr[8] || *answer == ansstr[9] ) {
		xfree(aname); aname = NULL;
		xfree(acomment); acomment = NULL;
		xfree(amail); amail = NULL;
		xfree(uid); uid = NULL;
		break;
	    }
	    xfree(answer);
	}
	xfree(answer);
	if (!amail && !acomment)
	    break;
	xfree(uid); uid = NULL;
    }
    if( uid ) {
	char *p = native_to_utf8( uid );
	xfree( uid );
	uid = p;
    }
    return uid;
}