2007-05-10 Marcus Brinkmann <marcus@g10code.de>
authorMarcus Brinkmann <mb@g10code.com>
Thu, 10 May 2007 17:37:07 +0000 (17:37 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Thu, 10 May 2007 17:37:07 +0000 (17:37 +0000)
* pinentry/pinentry.h (pinentry_color_t): New type.
(struct pinentry): New members COLOR_FG, COLOR_FG_BRIGHT,
COLOR_BG, COLOR_SO.
* pinentry/pinentry.c (pinentry_parse_opts): Support new option --colors.
(parse_color): New function.
* pinentry/pinentry-curses.c (USE_COLORS): New macro.
(pinentry_color): New static variable.
(dialog_create): Redo color management.

ChangeLog
NEWS
README
pinentry/pinentry-curses.c
pinentry/pinentry.c
pinentry/pinentry.h

index 996f342..5845fe6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2007-05-10  Marcus Brinkmann  <marcus@g10code.de>
 
+       * pinentry/pinentry.h (pinentry_color_t): New type.
+       (struct pinentry): New members COLOR_FG, COLOR_FG_BRIGHT,
+       COLOR_BG, COLOR_SO.
+       * pinentry/pinentry.c (pinentry_parse_opts): Support new option --colors.
+       (parse_color): New function.
+       * pinentry/pinentry-curses.c (USE_COLORS): New macro.
+       (pinentry_color): New static variable.
+       (dialog_create): Redo color management.
+
        * pinentry/pinentry-curses.c (dialog_create): Re-add calculation
        of cancel button position.  Adjust calculation of OK button
        position if it is the only one used.
diff --git a/NEWS b/NEWS
index 484798c..55af1d8 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,9 @@ Noteworthy changes in version 0.7.3
  * New Assuan option touch-file to set a file which will be touched
    after ncurses does not need the display anymore.
 
+ * New option --colors=FG,BG,SO to set the colors for the curses
+   pinentry.
+
 
 Noteworthy changes in version 0.7.2 (2005-01-27)
 ------------------------------------------------
diff --git a/README b/README
index 684c453..bf100b8 100644 (file)
--- a/README
+++ b/README
@@ -40,3 +40,29 @@ Some of the code is taken from Robert Bihlmeyer's Quintuple-Agent.
 For security reasons, all internationalization has been removed.  The
 client is expected to tell the PIN entry the text strings to be
 displayed.
+
+
+Curses Pinentry
+---------------
+
+The curses pinentry supports colors if the terminal does.  The colors
+can be specified by the --colors=FG,BG,SO option, which sets the
+foreground, background and standout colors respectively.  The standout
+color is used for error messages.  Colors can be named by any of
+"black", "red", "green", "yellow", "blue", "magenta", "cyan" and
+"white".  The foreground and standout color can be prefixed by
+"bright-", "bright", "bold-" and "bold", and any of these prefixes has
+the same effect of making the color bolder or brighter.  Two special
+color names are defined as well: "default" chooses the default color,
+and "none" disables use of colors.  The name "none" is only meaningful
+for the standout color and in this case a reversed effect is used for
+error messages.  For the other colors, disabling colors means the same
+as using the defaults.  The default colors are as follows:
+
+       Foreground:     Terminal default
+       Background:     Terminal default
+       Standout:       Bright red
+
+Note that color support is limited by the capabilities of the display
+terminal.  Some color combinations can be very difficult to read, and
+please know that colors are perceived differently by different people.
index d376e3d..ace02ba 100644 (file)
 #define STRING_OK "<OK>"
 #define STRING_CANCEL "<Cancel>"
 
+#define USE_COLORS             (has_colors () && COLOR_PAIRS >= 2)
+static short pinentry_color[] = { -1, -1, COLOR_BLACK, COLOR_RED,
+                                 COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE,
+                                 COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE };
 static int init_screen;
 
 typedef enum
@@ -352,8 +356,11 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
              move (ypos, xpos);
              addch (ACS_VLINE);
              addch (' ');
-             if (has_colors () && COLOR_PAIRS >= 1)
-               attron (COLOR_PAIR(1) | A_BOLD);
+             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++)
@@ -362,8 +369,11 @@ dialog_create (pinentry_t pinentry, dialog_t dialog)
                    i++;
                    addch ((unsigned char) *p);
                  }
-             if (has_colors () && COLOR_PAIRS >= 1)
-               attroff (COLOR_PAIR(1) | A_BOLD);
+             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')
@@ -610,15 +620,29 @@ dialog_run (pinentry_t pinentry, const char *tty_name, const char *tty_type)
   nonl ();             /* Tell curses not to do NL->CR/NL on output.  */
   cbreak ();           /* Take input chars one at a time, no wait for \n.  */
   noecho ();           /* Don't echo input - in color.  */
-  refresh ();
 
   if (has_colors ())
     {
       start_color ();
+      use_default_colors ();
 
-      if (COLOR_PAIRS >= 1)
-       init_pair (1, COLOR_RED, COLOR_BLACK);
+      if (pinentry->color_so == PINENTRY_COLOR_DEFAULT)
+       {
+         pinentry->color_so = PINENTRY_COLOR_RED;
+         pinentry->color_so_bright = 1;
+       }
+      if (COLOR_PAIRS >= 2)
+       {
+         init_pair (1, pinentry_color[pinentry->color_fg],
+                    pinentry_color[pinentry->color_bg]);
+         init_pair (2, pinentry_color[pinentry->color_so],
+                    pinentry_color[pinentry->color_bg]);
+
+         bkgd (COLOR_PAIR (1));
+         attron (COLOR_PAIR (1) | (pinentry->color_fg_bright ? A_BOLD : 0));
+       }
     }
+  refresh ();
 
   /* XXX */
   if (dialog_create (pinentry, &diag))
index 78e8fe5..a993a27 100644 (file)
@@ -68,7 +68,12 @@ struct pinentry pinentry =
     NULL,       /* Touch file.  */
     0,         /* Result.  */
     0,          /* Locale error flag. */
-    0           /* One-button flag.  */
+    0,          /* One-button flag.  */
+    PINENTRY_COLOR_DEFAULT,
+    0,
+    PINENTRY_COLOR_DEFAULT,
+    PINENTRY_COLOR_DEFAULT,
+    0
   };
 
 \f
@@ -290,6 +295,56 @@ usage (void)
 }
 
 
+char *
+parse_color (char *arg, pinentry_color_t *color_p, int *bright_p)
+{
+  static struct
+  {
+    const char *name;
+    pinentry_color_t color;
+  } colors[] = { { "none", PINENTRY_COLOR_NONE },
+                { "default", PINENTRY_COLOR_DEFAULT },
+                { "black", PINENTRY_COLOR_BLACK },
+                { "red", PINENTRY_COLOR_RED },
+                { "green", PINENTRY_COLOR_GREEN },
+                { "yellow", PINENTRY_COLOR_YELLOW },
+                { "blue", PINENTRY_COLOR_BLUE },
+                { "magenta", PINENTRY_COLOR_MAGENTA },
+                { "cyan", PINENTRY_COLOR_CYAN },
+                { "white", PINENTRY_COLOR_WHITE } };
+
+  int i;
+  char *new_arg;
+  pinentry_color_t color = PINENTRY_COLOR_DEFAULT;
+
+  if (!arg)
+    return NULL;
+
+  new_arg = strchr (arg, ',');
+  if (new_arg)
+    new_arg++;
+
+  if (bright_p)
+    {
+      const char *bname[] = { "bright-", "bright", "bold-", "bold" };
+
+      *bright_p = 0;
+      for (i = 0; i < sizeof (bname) / sizeof (bname[0]); i++)
+       if (!strncasecmp (arg, bname[i], strlen (bname[i])))
+         {
+           *bright_p = 1;
+           arg += strlen (bname[i]);
+         }
+    }
+
+  for (i = 0; i < sizeof (colors) / sizeof (colors[0]); i++)
+    if (!strncasecmp (arg, colors[i].name, strlen (colors[i].name)))
+      color = colors[i].color;
+
+  *color_p = color;
+  return new_arg;
+}
+
 /* Parse the command line options.  Returns 1 if user should print
    version and exit.  Can exit the program if only help output is
    requested.  */
@@ -309,6 +364,7 @@ pinentry_parse_opts (int argc, char *argv[])
      { "enhanced", no_argument,          0, 'e' },
      { "no-global-grab", no_argument,    0, 'g' },
      { "parent-wid", required_argument,  0, 'W' },
+     { "colors", required_argument,     0, 'c' },
      { "help", no_argument,              0, 'h' },
      { "version", no_argument, &opt_version, 1 },
      { NULL, 0, NULL, 0 }};
@@ -380,6 +436,14 @@ pinentry_parse_opts (int argc, char *argv[])
          /* FIXME: Add some error handling.  Use strtol.  */
          break;
 
+       case 'c':
+         optarg = parse_color (optarg, &pinentry.color_fg,
+                               &pinentry.color_fg_bright);
+         optarg = parse_color (optarg, &pinentry.color_bg, NULL);
+         optarg = parse_color (optarg, &pinentry.color_so,
+                               &pinentry.color_so_bright);
+         break;
+
         default:
           fprintf (stderr, "%s: oops: option not handled\n", this_pgmname);
          break;
index b85aa5b..fec9b4b 100644 (file)
@@ -28,6 +28,13 @@ extern "C" {
 #endif
 #endif
 
+typedef enum {
+  PINENTRY_COLOR_NONE, PINENTRY_COLOR_DEFAULT,
+  PINENTRY_COLOR_BLACK, PINENTRY_COLOR_RED,
+  PINENTRY_COLOR_GREEN, PINENTRY_COLOR_YELLOW,
+  PINENTRY_COLOR_BLUE, PINENTRY_COLOR_MAGENTA,
+  PINENTRY_COLOR_CYAN, PINENTRY_COLOR_WHITE
+} pinentry_color_t;
 
 struct pinentry
 {
@@ -84,6 +91,12 @@ struct pinentry
      dismiss button is required. */
   int one_button;
 
+  /* For the curses pinentry, the color of error messages.  */
+  pinentry_color_t color_fg;
+  int color_fg_bright;
+  pinentry_color_t color_bg;
+  pinentry_color_t color_so;
+  int color_so_bright;
 };
 typedef struct pinentry *pinentry_t;