static int dialog_create (pinentry_t pinentry, dialog_t dialog) { int err = 0; int size_y; int size_x; int y; int x; int ypos; int xpos; int description_x = 0; int error_x = 0; CH *description = NULL; CH *error = NULL; CH *prompt = NULL; dialog->pinentry = pinentry; #define COPY_OUT(what) \ do \ if (pinentry->what) \ { \ what = utf8_to_local (pinentry->lc_ctype, pinentry->what); \ if (!what) \ { \ err = 1; \ pinentry->specific_err = ASSUAN_Locale_Problem; \ goto out; \ } \ } \ while (0) COPY_OUT (description); COPY_OUT (error); COPY_OUT (prompt); /* There is no pinentry->default_notok. Map it to pinentry->notok. */ #define default_notok notok #define MAKE_BUTTON(which,default) \ do \ { \ char *new = NULL; \ if (pinentry->default_##which || pinentry->which) \ { \ int len; \ char *msg; \ int i, j; \ \ msg = pinentry->which; \ if (! msg) \ msg = pinentry->default_##which; \ len = strlen (msg); \ \ new = malloc (len + 3); \ if (!new) \ { \ err = 1; \ pinentry->specific_err = ASSUAN_Out_Of_Core; \ goto out; \ } \ \ new[0] = '<'; \ for (i = 0, j = 1; i < len; i ++, j ++) \ { \ if (msg[i] == '_') \ { \ i ++; \ if (msg[i] == 0) \ /* _ at end of string. */ \ break; \ } \ new[j] = msg[i]; \ } \ \ new[j] = '>'; \ new[j + 1] = 0; \ } \ dialog->which = pinentry_utf8_to_local (pinentry->lc_ctype, \ new ? new : default); \ if (!dialog->which) \ { \ err = 1; \ pinentry->specific_err = ASSUAN_Locale_Problem; \ goto out; \ } \ } \ while (0) MAKE_BUTTON (ok, STRING_OK); if (!pinentry->one_button) MAKE_BUTTON (cancel, STRING_CANCEL); else dialog->cancel = NULL; if (!pinentry->one_button && pinentry->notok) MAKE_BUTTON (notok, STRING_NOTOK); else dialog->notok = NULL; getmaxyx (stdscr, size_y, size_x); /* Check if all required lines fit on the screen. */ y = 1; /* Top frame. */ if (description) { CH *start = description; int len = 0; do { collect_line (size_x - 4, &start, &len); if (len > description_x) description_x = len; y++; } while (start[len - 1]); y++; } if (pinentry->pin) { if (error) { CH *p = error; int err_x = 0; while (*p) { if (*(p++) == '\n') { if (err_x > error_x) error_x = err_x; y++; err_x = 0; } else err_x++; } if (err_x > error_x) error_x = err_x; y += 2; /* Error message. */ } y += 2; /* Pin entry field. */ } y += 2; /* OK/Cancel and bottom frame. */ if (y > size_y) { err = 1; pinentry->specific_err = ASSUAN_Too_Short; goto out; } /* Check if all required columns fit on the screen. */ x = 0; if (description) { int new_x = description_x; if (new_x > size_x - 4) new_x = size_x - 4; if (new_x > x) x = new_x; } if (pinentry->pin) { #define MIN_PINENTRY_LENGTH 40 int new_x; if (error) { new_x = error_x; if (new_x > size_x - 4) new_x = size_x - 4; if (new_x > x) x = new_x; } new_x = MIN_PINENTRY_LENGTH; if (prompt) { new_x += STRLEN (prompt) + 1; /* One space after prompt. */ } if (new_x > size_x - 4) new_x = size_x - 4; if (new_x > x) x = new_x; } /* We position the buttons after the first, second and third fourth of the width. Account for rounding. */ if (x < 3 * strlen (dialog->ok)) x = 3 * strlen (dialog->ok); if (dialog->cancel) if (x < 3 * strlen (dialog->cancel)) x = 3 * strlen (dialog->cancel); if (dialog->notok) if (x < 3 * strlen (dialog->notok)) x = 3 * strlen (dialog->notok); /* Add the frame. */ x += 4; if (x > size_x) { err = 1; pinentry->specific_err = ASSUAN_Too_Short; goto out; } dialog->pos = DIALOG_POS_NONE; dialog->pin_max = pinentry->pin_len; dialog->pin_loc = 0; dialog->pin_len = 0; ypos = (size_y - y) / 2; xpos = (size_x - x) / 2; move (ypos, xpos); addch (ACS_ULCORNER); hline (0, x - 2); move (ypos, xpos + x - 1); addch (ACS_URCORNER); move (ypos + 1, xpos + x - 1); vline (0, y - 2); move (ypos + y - 1, xpos); addch (ACS_LLCORNER); hline (0, x - 2); move (ypos + y - 1, xpos + x - 1); addch (ACS_LRCORNER); ypos++; if (description) { CH *start = description; int len = 0; do { int i; move (ypos, xpos); addch (ACS_VLINE); addch (' '); collect_line (size_x - 4, &start, &len); for (i = 0; i < len - 1; i++) { ADDCH (start[i]); } if (start[len - 1] != NULLCH && start[len - 1] != NLCH) ADDCH (start[len - 1]); ypos++; } while (start[len - 1]); move (ypos, xpos); addch (ACS_VLINE); ypos++; } if (pinentry->pin) { int i; if (error) { CH *p = error; i = 0; while (*p) { move (ypos, xpos); addch (ACS_VLINE); addch (' '); if (USE_COLORS && pinentry->color_so != PINENTRY_COLOR_NONE) { attroff (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0)); attron (COLOR_PAIR (2) | (pinentry->color_so_bright ? A_BOLD : 0)); } else standout (); for (;*p && *p != NLCH; p++) if (i < x - 4) { i++; ADDCH (*p); } if (USE_COLORS && pinentry->color_so != PINENTRY_COLOR_NONE) { attroff (COLOR_PAIR (2) | (pinentry->color_so_bright ? A_BOLD : 0)); attron (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0)); } else standend (); if (*p == '\n') p++; i = 0; ypos++; } move (ypos, xpos); addch (ACS_VLINE); ypos++; } move (ypos, xpos); addch (ACS_VLINE); addch (' '); dialog->pin_y = ypos; dialog->pin_x = xpos + 2; dialog->pin_size = x - 4; if (prompt) { CH *p = prompt; i = STRLEN (prompt); if (i > x - 4 - MIN_PINENTRY_LENGTH) i = x - 4 - MIN_PINENTRY_LENGTH; dialog->pin_x += i + 1; dialog->pin_size -= i + 1; while (i-- > 0) { ADDCH (*(p++)); } addch (' '); } for (i = 0; i < dialog->pin_size; i++) addch ('_'); ypos++; move (ypos, xpos); addch (ACS_VLINE); ypos++; } move (ypos, xpos); addch (ACS_VLINE); if (dialog->cancel || dialog->notok) { dialog->ok_y = ypos; /* Calculating the left edge of the left button, rounding down. */ dialog->ok_x = xpos + 2 + ((x - 4) / 3 - strlen (dialog->ok)) / 2; move (dialog->ok_y, dialog->ok_x); addstr (dialog->ok); if (! pinentry->pin && dialog->notok) { dialog->notok_y = ypos; /* Calculating the left edge of the middle button, rounding up. */ dialog->notok_x = xpos + x / 2 - strlen (dialog->notok) / 2; move (dialog->notok_y, dialog->notok_x); addstr (dialog->notok); } if (dialog->cancel) { dialog->cancel_y = ypos; /* Calculating the left edge of the right button, rounding up. */ dialog->cancel_x = xpos + x - 2 - ((x - 4) / 3 + strlen (dialog->cancel)) / 2; move (dialog->cancel_y, dialog->cancel_x); addstr (dialog->cancel); } } else { dialog->ok_y = ypos; /* Calculating the left edge of the OK button, rounding down. */ dialog->ok_x = xpos + x / 2 - strlen (dialog->ok) / 2; move (dialog->ok_y, dialog->ok_x); addstr (dialog->ok); } out: if (description) free (description); if (error) free (error); if (prompt) free (prompt); return err; }
static int dialog_create (pinentry_t pinentry, dialog_t dialog) { int err = 0; int size_y; int size_x; int y; int x; int ypos; int xpos; int description_x = 0; int error_x = 0; char *description = NULL; char *error = NULL; char *prompt = NULL; #define COPY_OUT(what) \ do \ if (pinentry->what) \ { \ what = pinentry_utf8_to_local (pinentry->lc_ctype, \ pinentry->what); \ if (!what) \ { \ err = 1; \ goto out; \ } \ } \ while (0) COPY_OUT (description); COPY_OUT (error); COPY_OUT (prompt); #define MAKE_BUTTON(which,default) \ do \ { \ char *new = NULL; \ if (pinentry->which) \ { \ int len = strlen (pinentry->which); \ new = malloc (len + 3); \ if (!new) \ { \ err = 1; \ goto out; \ } \ new[0] = '<'; \ memcpy (&new[1], pinentry->which, len); \ new[len + 1] = '>'; \ new[len + 2] = '\0'; \ } \ dialog->which = pinentry_utf8_to_local (pinentry->lc_ctype, \ new ? new : default); \ if (!dialog->which) \ { \ err = 1; \ goto out; \ } \ } \ while (0) MAKE_BUTTON (ok, STRING_OK); if (!pinentry->one_button) MAKE_BUTTON (cancel, STRING_CANCEL); else dialog->cancel = NULL; getmaxyx (stdscr, size_y, size_x); /* Check if all required lines fit on the screen. */ y = 1; /* Top frame. */ if (description) { char *start = description; int len = 0; do { collect_line (size_x - 4, &start, &len); if (len > description_x) description_x = len; y++; } while (start[len - 1]); y++; } if (pinentry->pin) { if (error) { char *p = error; int err_x = 0; while (*p) { if (*(p++) == '\n') { if (err_x > error_x) error_x = err_x; y++; err_x = 0; } else err_x++; } if (err_x > error_x) error_x = err_x; y += 2; /* Error message. */ } y += 2; /* Pin entry field. */ } y += 2; /* OK/Cancel and bottom frame. */ if (y > size_y) { err = 1; goto out; } /* Check if all required columns fit on the screen. */ x = 0; if (description) { int new_x = description_x; if (new_x > size_x - 4) new_x = size_x - 4; if (new_x > x) x = new_x; } if (pinentry->pin) { #define MIN_PINENTRY_LENGTH 40 int new_x; if (error) { new_x = error_x; if (new_x > size_x - 4) new_x = size_x - 4; if (new_x > x) x = new_x; } new_x = MIN_PINENTRY_LENGTH; if (prompt) new_x += strlen (prompt) + 1; /* One space after prompt. */ if (new_x > size_x - 4) new_x = size_x - 4; if (new_x > x) x = new_x; } /* We position the buttons after the first and second third of the width. Account for rounding. */ if (x < 2 * strlen (dialog->ok)) x = 2 * strlen (dialog->ok); if (dialog->cancel) if (x < 2 * strlen (dialog->cancel)) x = 2 * strlen (dialog->cancel); /* Add the frame. */ x += 4; if (x > size_x) { err = 1; goto out; } dialog->pos = DIALOG_POS_NONE; dialog->pin = pinentry->pin; dialog->pin_max = pinentry->pin_len; dialog->pin_loc = 0; dialog->pin_len = 0; ypos = (size_y - y) / 2; xpos = (size_x - x) / 2; move (ypos, xpos); addch (ACS_ULCORNER); hline (0, x - 2); move (ypos, xpos + x - 1); addch (ACS_URCORNER); move (ypos + 1, xpos + x - 1); vline (0, y - 2); move (ypos + y - 1, xpos); addch (ACS_LLCORNER); hline (0, x - 2); move (ypos + y - 1, xpos + x - 1); addch (ACS_LRCORNER); ypos++; if (description) { char *start = description; int len = 0; do { int i; move (ypos, xpos); addch (ACS_VLINE); addch (' '); collect_line (size_x - 4, &start, &len); for (i = 0; i < len - 1; i++) addch ((unsigned char) start[i]); if (start[len - 1] && start[len - 1] != '\n') addch ((unsigned char) start[len - 1]); ypos++; } while (start[len - 1]); move (ypos, xpos); addch (ACS_VLINE); ypos++; } if (pinentry->pin) { int i; if (error) { char *p = error; i = 0; while (*p) { move (ypos, xpos); addch (ACS_VLINE); addch (' '); if (USE_COLORS && pinentry->color_so != PINENTRY_COLOR_NONE) { attroff (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0)); attron (COLOR_PAIR (2) | (pinentry->color_so_bright ? A_BOLD : 0)); } else standout (); for (;*p && *p != '\n'; p++) if (i < x - 4) { i++; addch ((unsigned char) *p); } if (USE_COLORS && pinentry->color_so != PINENTRY_COLOR_NONE) { attroff (COLOR_PAIR (2) | (pinentry->color_so_bright ? A_BOLD : 0)); attron (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0)); } else standend (); if (*p == '\n') p++; i = 0; ypos++; } move (ypos, xpos); addch (ACS_VLINE); ypos++; } move (ypos, xpos); addch (ACS_VLINE); addch (' '); dialog->pin_y = ypos; dialog->pin_x = xpos + 2; dialog->pin_size = x - 4; if (prompt) { char *p = prompt; i = strlen (prompt); if (i > x - 4 - MIN_PINENTRY_LENGTH) i = x - 4 - MIN_PINENTRY_LENGTH; dialog->pin_x += i + 1; dialog->pin_size -= i + 1; while (i-- > 0) addch ((unsigned char) *(p++)); addch (' '); } for (i = 0; i < dialog->pin_size; i++) addch ('_'); ypos++; move (ypos, xpos); addch (ACS_VLINE); ypos++; } move (ypos, xpos); addch (ACS_VLINE); if (dialog->cancel) { dialog->ok_y = ypos; /* Calculating the left edge of the left button, rounding down. */ dialog->ok_x = xpos + 2 + ((x - 4) / 2 - strlen (dialog->ok)) / 2; move (dialog->ok_y, dialog->ok_x); addstr (dialog->ok); dialog->cancel_y = ypos; /* Calculating the left edge of the right button, rounding up. */ dialog->cancel_x = xpos + x - 2 - ((x - 4) / 2 + strlen (dialog->cancel)) / 2; move (dialog->cancel_y, dialog->cancel_x); addstr (dialog->cancel); } else { dialog->ok_y = ypos; /* Calculating the left edge of the OK button, rounding down. */ dialog->ok_x = xpos + x / 2 - strlen (dialog->ok) / 2; move (dialog->ok_y, dialog->ok_x); addstr (dialog->ok); } out: if (description) free (description); if (error) free (error); if (prompt) free (prompt); return err; }