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