Ver código fonte

Add configurable colours to dselect

Wichert Akkerman 25 anos atrás
pai
commit
7af774a7a0
7 arquivos alterados com 282 adições e 32 exclusões
  1. 9 0
      ChangeLog
  2. 1 0
      debian/changelog
  3. 2 1
      dselect/basecmds.cc
  4. 27 16
      dselect/baselist.cc
  5. 59 0
      dselect/dselect.8
  6. 26 1
      dselect/dselect.h
  7. 158 14
      dselect/main.cc

+ 9 - 0
ChangeLog

@@ -1,3 +1,12 @@
+Mon Jul 16 01:50:58 CEST 2001 Wichert Akkerman <wakkerma@debian.org>
+
+  * Merge a reworked version of a patch from Joey Hess
+    + dselect/dselect.8: Document new colour options
+    + dselect/basecmds.cc: properly draw the background using helpscreen_attr
+    + dselect/baselist.cc: change drawing code to use new changeable colours
+    + dselect/dselect.h: Add all the colour structures
+    + dselect/main.cc: Parse --colour options
+
 Mon Jul 16 00:01:24 CEST 2001 Wichert Akkerman <wakkerma@debian.org>
 
   * dselect/baselist.cc: include unistd.h which is needed to get the

+ 1 - 0
debian/changelog

@@ -19,6 +19,7 @@ dpkg (1.10) unstable; urgency=low
   * Split dselect into its own package. dpkg Pre-Depends on it
     to make sure no weird things happen during an upgrade but this
     will allow us to make dselect option at some point in the future.
+  * Make colours in dselect user-configurable. Closes: Bug#103994
 
  -- Wichert Akkerman <wakkerma@debian.org>  UNRELEASED
 

+ 2 - 1
dselect/basecmds.cc

@@ -119,12 +119,13 @@ void baselist::displayhelp(const struct helpmenuentry *helpmenu, int key) {
   int maxx, maxy, i, y, x, nextkey;
   
   getmaxyx(stdscr,maxy,maxx);
+  wbkgdset(stdscr, ' ' | helpscreen_attr);
   clearok(stdscr,TRUE);
   for (;;) {
     werase(stdscr);
     for (hme= helpmenu; hme->key && hme->key != key; hme++);
     if (hme->key) {
-      attrset(list_attr);
+      attrset(helpscreen_attr);
       mvaddstr(1,0, gettext(hme->msg->text));
       attrset(title_attr);
       mvaddstr(0,0, _("Help: "));

+ 27 - 16
dselect/baselist.cc

@@ -115,19 +115,28 @@ void baselist::startdisplay() {
   clear(); wnoutrefresh(stdscr);
 
   // find attributes
-  if (has_colors() && start_color()==OK && COLOR_PAIRS >= 3) {
-    if (init_pair(1,COLOR_WHITE,COLOR_BLACK) != OK ||
-        init_pair(2,COLOR_WHITE,COLOR_RED) != OK ||
-        init_pair(3,COLOR_WHITE,COLOR_BLUE) != OK)
-      ohshite(_("failed to allocate colour pairs"));
-    list_attr= COLOR_PAIR(1);
-    listsel_attr= list_attr|A_REVERSE;
-    title_attr= COLOR_PAIR(2);
-    thisstate_attr= COLOR_PAIR(3);
-    selstate_attr= list_attr|A_BOLD;
-    selstatesel_attr= listsel_attr|A_BOLD;
-    colheads_attr= COLOR_PAIR(3);
+  if (has_colors() && start_color()==OK && COLOR_PAIRS >= numscreenparts) {
+    int i;
+    printf("allocing\n");
+    for (i = 1; i < numscreenparts; i++) {
+       if (init_pair(i, color[i].fore, color[i].back) != OK)
+         ohshite(_("failed to allocate colour pair"));
+    }
+    /* TODO: should use an array of attr's, indexed by attr name. Oh well. */
+    list_attr=		COLOR_PAIR(list)	| color[list].attr;
+    listsel_attr= 	COLOR_PAIR(listsel)	| color[listsel].attr;
+    title_attr=		COLOR_PAIR(title)	| color[title].attr;
+    thisstate_attr=	COLOR_PAIR(thisstate)	| color[thisstate].attr;
+    selstate_attr=	COLOR_PAIR(selstate)	| color[selstate].attr;
+    selstatesel_attr= 	COLOR_PAIR(selstatesel)	| color[selstatesel].attr;
+    colheads_attr=	COLOR_PAIR(colheads)	| color[colheads].attr;
+    query_attr=		COLOR_PAIR(query)	| color[query].attr;
+    info_attr=		COLOR_PAIR(info)	| color[info].attr;
+    info_headattr=	COLOR_PAIR(info_head)	| color[info_head].attr;
+    whatinfo_attr=	COLOR_PAIR(whatinfo)	| color[whatinfo].attr;
+    helpscreen_attr=	COLOR_PAIR(helpscreen)	| color[helpscreen].attr;
   } else {
+    /* User defined attributes for B&W mode are not currently supported. */
     title_attr= A_REVERSE;
     thisstate_attr= A_STANDOUT;
     list_attr= 0;
@@ -135,11 +144,11 @@ void baselist::startdisplay() {
     selstate_attr= A_BOLD;
     selstatesel_attr= A_STANDOUT;
     colheads_attr= A_BOLD;
+    query_attr= title_attr;
+    info_attr= list_attr;
+    info_headattr= A_BOLD;
+    whatinfo_attr= thisstate_attr;
   }
-  query_attr= title_attr;
-  info_attr= list_attr;
-  info_headattr= A_BOLD;
-  whatinfo_attr= thisstate_attr;
 
   // set up windows and pads, based on screen size
   getmaxyx(stdscr,ymax,xmax);
@@ -172,9 +181,11 @@ void baselist::startdisplay() {
   infopad= newpad(MAX_DISPLAY_INFO, total_width);
   if (!infopad) ohshite(_("failed to create info pad"));
   wattrset(infopad,info_attr);
+  wbkgdset(infopad, ' ' | info_attr);
 
   querywin= newwin(1,xmax,ymax-1,0);
   if (!querywin) ohshite(_("failed to create query window"));
+  wbkgdset(querywin, ' ' | query_attr);
 
   if (cursorline >= topofscreen + list_height) topofscreen= cursorline;
   if (topofscreen > nitems - list_height) topofscreen= nitems - list_height;

+ 59 - 0
dselect/dselect.8

@@ -5,6 +5,7 @@ dselect \- Debian package management frontend
 .B dselect
 [\-\-admindir <directory>] [\-\-help] [\-\-version] [\-\-licence | \-\-license]
 [\-\-expert] [\-\-debug | \-D <file>] [\fI<action>\fP]
+[\-\-colour | \-\-color screenpart:[foreground],[background][:attr[+attr+..]]]
 .SH DESCRIPTION
 .B dselect
 is the primary user interface for managing packages on a Debian system.
@@ -51,6 +52,64 @@ Turn on debugging. Debugging information is sent to \fI<file>\fP.
 Turns on expert mode, i.e. doesn't display possibly annoying help 
 messages.
 .TP
+.TP
+.B --colour | --color screenpart:[foreground],[background][:attr[+attr+..]]
+Configures screen colors. This works only if your display supports colors.
+This option may be used multiple times (and is best used in
+\fIdselect.cfg\fP). Each use changes the color (and optionally, other
+attributes) of one part of the screen.
+The parts of the screen (from top to bottom) are:
+.RS
+.TP
+.B title
+The screen title.
+.TP
+.B listhead
+The header line above the list of packages.
+.TP
+.B list
+The scrolling list of packages (and also some help text).
+.TP
+.B listsel
+The selected item in the list.
+.TP
+.B pkgstate
+In the list of packages, the text indicating the current state of each
+package.
+.TP
+.B pkgstatesel
+In the list of packages, the text indicating the current state of the
+currently selected package.
+.TP
+.B infohead
+The header line that displays the state of the currently selected package.
+.TP
+.B infodesc
+The package's short description.
+.TP
+.B info
+Used to display package info such as the package's description.
+.TP
+.B infofoot
+The last line of the screen when selecting packages.
+.TP
+.B query
+Used to display query lines
+.TP
+.B helpscreen
+Color of help screens.
+.RE
+.P
+After the part of the screen comes a colon and the color specification. You
+can specify either the foreground color, the background color, or both,
+overriding the compiled-in colors. Use standard curses color names.
+.P
+Optionally, after the color specification is another colon, and an
+attribute specification. This is a list of one or more attributes,
+separated by plus ("+") characters. Available attributes include (not all
+of these will work on all terminals): normal, standout, underline, reverse,
+blink, bright, dim, bold
+.P
 .B --help
 Print a brief help text and exit successfully.
 .TP

+ 26 - 1
dselect/dselect.h

@@ -47,7 +47,8 @@ protected:
   int info_headattr, whatinfo_attr;
   int thisstate_attr, query_attr;
   int selstate_attr, selstatesel_attr;
-  
+  int helpscreen_attr;
+
   int total_width;
   
   // (n)curses stuff
@@ -142,6 +143,30 @@ extern const char *admindir;
 extern FILE *debug;
 extern int expertmode;
 
+enum screenparts {
+       background,
+       list,
+       listsel,
+       title,
+       thisstate,
+       selstate,
+       selstatesel,
+       colheads,
+       query,
+       info,
+       info_head,
+       whatinfo,
+       helpscreen,
+       numscreenparts,
+};
+
+struct colordata {
+       int fore;
+       int back;
+       int attr;
+};
+extern colordata color[];
+
 /* Evil recommends flag variable. */
 extern int manual_install;
 

+ 158 - 14
dselect/main.cc

@@ -56,10 +56,75 @@ const char printforhelp[]= N_("Type dselect --help for help.");
 modstatdb_rw readwrite;
 const char *admindir= ADMINDIR;
 FILE *debug;
-int expertmode = 0;
+int expertmode= 0;
 
 static keybindings packagelistbindings(packagelist_kinterps,packagelist_korgbindings);
 
+struct table_t {
+  const char *name;
+  const int num;
+};
+
+static const struct table_t colourtable[]= {
+  {"black",	COLOR_BLACK	},
+  {"red",	COLOR_RED	},
+  {"green",	COLOR_GREEN	},
+  {"yellow",	COLOR_YELLOW	},
+  {"blue",	COLOR_BLUE	},
+  {"magenta",	COLOR_MAGENTA	},
+  {"cyan",	COLOR_CYAN	},
+  {"white",	COLOR_WHITE	},
+  {NULL, 0},
+};
+
+static const struct table_t attrtable[]= {
+  {"normal",	A_NORMAL	},
+  {"standout",	A_STANDOUT	},
+  {"underline",	A_UNDERLINE	},
+  {"reverse",	A_REVERSE	},
+  {"blink",	A_BLINK		},
+  {"bright",	A_BLINK		}, // on some terminals
+  {"dim",	A_DIM		},
+  {"bold",	A_BOLD		},
+  {NULL, 0},
+};
+
+/* A slightly confusing mapping from dselect's internal names to
+ * the user-visible names.*/
+static const struct table_t screenparttable[]= {
+  {"list",		list		},
+  {"listsel",		listsel		},
+  {"title",		title		},
+  {"infohead",		thisstate	},
+  {"pkgstate",		selstate	},
+  {"pkgstatesel",	selstatesel	},
+  {"listhead",		colheads	},
+  {"query",		query		},
+  {"info",		info		},
+  {"infodesc",		info_head	},
+  {"infofoot",		whatinfo	},
+  {"helpscreen",	helpscreen	},
+  {NULL, 0},
+};
+
+/* Historical (patriotic?) colours. */
+struct colordata color[]= {
+  /* fore      back            attr */
+  {COLOR_WHITE,        COLOR_BLACK,    0			}, // default, not used
+  {COLOR_WHITE,        COLOR_BLACK,    0			}, // list
+  {COLOR_WHITE,        COLOR_BLACK,    A_REVERSE		}, // listsel
+  {COLOR_WHITE,        COLOR_RED,      0			}, // title
+  {COLOR_WHITE,        COLOR_BLUE,     0			}, // thisstate
+  {COLOR_WHITE,        COLOR_BLACK,    A_BOLD			}, // selstate
+  {COLOR_WHITE,        COLOR_BLACK,    A_REVERSE | A_BOLD	}, // selstatesel
+  {COLOR_WHITE,        COLOR_BLUE,     0			}, // colheads
+  {COLOR_WHITE,        COLOR_RED,      0			}, // query
+  {COLOR_WHITE,        COLOR_BLACK,    0			}, // info
+  {COLOR_WHITE,        COLOR_BLACK,    A_BOLD			}, // info_head
+  {COLOR_WHITE,        COLOR_BLUE,     0			}, // whatinfo
+  {COLOR_WHITE,        COLOR_BLACK,    0			}, // help
+};
+
 struct menuentry {
   const char *command;
   const char *key;
@@ -98,13 +163,30 @@ static void printversion(void) {
 }
 
 static void usage(void) {
+  int i;
   if (!fputs(
      _("Usage: dselect [options]\n"
        "       dselect [options] action ...\n"
        "Options:  --admindir <directory>  (default is /var/lib/dpkg)\n"
        "          --help  --version  --licence  --expert  --debug <file> | -D<file>\n"
-       "Actions:  access update select install config remove quit menu\n"),
+       "          --colour screenpart:[foreground],[background][:attr[+attr+..]]\n"
+       "Actions:  access update select install config remove quit\n"),
        stdout)) werr("stdout");
+
+  printf(_("Screenparts:\n"));
+  for (i=0; screenparttable[i].name; i++)
+    printf("  %s", screenparttable[i].name);
+  if (!fputs("\n", stdout)) werr("stdout");
+
+  printf(_("Colours:\n"));
+  for (i=0; colourtable[i].name; i++)
+    printf("  %s", colourtable[i].name);
+  if (!fputs("\n", stdout)) werr("stdout");
+
+  printf(_("Attributes:\n"));
+  for (i=0; attrtable[i].name; i++)
+    printf("  %s", attrtable[i].name);
+  if (!fputs("\n", stdout)) werr("stdout");
 }
 
 /* These are called by C code, so need to have C calling convention */
@@ -126,20 +208,82 @@ extern "C" {
   }
 
   static void setexpert(const struct cmdinfo*, const char *v) {
-    expertmode = 1;
+    expertmode= 1;
+  }
+
+  int findintable(const struct table_t *table, const char *item, const char *tablename) {
+    int i;
+
+    for (i= 0;  item && (table[i].name!=NULL); i++)
+      if (strcasecmp(item, table[i].name) == 0)
+        return table[i].num;
+
+    ohshit(_("Invalid %s `%s'\n"), tablename, item);
+  }
+
+  /*
+   *  The string's format is:
+   *    screenpart:[forecolor][,backcolor][:[<attr>, ...]
+   *  Examples: --color title:black,cyan:bright+underline
+   *            --color list:red,yellow
+   *            --color colheads:,green:bright
+   *            --color selstate::reverse  // doesn't work FIXME
+   */
+  static void setcolor(const struct cmdinfo*, const char *string) {
+    char *s= (char *) malloc((strlen(string) + 1) * sizeof(char));
+    char *colours, *attributes, *attrib, *colourname;
+    int screenpart, aval;
+
+    strcpy(s, string); // strtok modifies strings, keep string const
+    screenpart= findintable(screenparttable, strtok(s, ":"), _("screen part"));
+    colours= strtok(NULL, ":");
+    attributes= strtok(NULL, ":");
+
+    if ((colours == NULL || ! strlen(colours)) &&
+        (attributes == NULL || ! strlen(attributes))) {
+       ohshit(_("Null color specificaton\n"));
+    }
+
+    if (colours != NULL && strlen(colours)) {
+      colourname= strtok(colours, ",");
+      if (colourname != NULL && strlen(colourname)) {
+        // normalize attributes to prevent confusion
+        color[screenpart].attr= A_NORMAL;
+       color[screenpart].fore=findintable(colourtable, colourname, _("color"));
+      }
+      colourname= strtok(NULL, ",");
+      if (colourname != NULL && strlen(colourname)) {
+        color[screenpart].attr= A_NORMAL;
+        color[screenpart].back=findintable(colourtable, colourname, _("color"));
+      }
+    }
+
+    if (attributes != NULL && strlen(attributes)) {
+      for (attrib= strtok(attributes, "+");
+           attrib != NULL && strlen(attrib);
+          attrib= strtok(NULL, "+")) {
+               aval=findintable(attrtable, attrib, _("color attribute"));
+               if (aval == A_NORMAL) // set to normal
+                       color[screenpart].attr= aval;
+               else // add to existing attribs
+                       color[screenpart].attr= color[screenpart].attr | aval;
+      }
+    }
   }
 
 } /* End of extern "C" */
 
 static const struct cmdinfo cmdinfos[]= {
-  { "admindir",   0,   1,  0,  &admindir,  0                      },
-  { "debug",     'D',  1,  0,  0,          setdebug               },
-  { "expert",    'E',  0,  0,  0,          setexpert              },
-  { "help",      'h',  0,  0,  0,          helponly               },
-  { "version",    0,   0,  0,  0,          versiononly            },
-  { "licence",    0,   0,  0,  0,          showcopyright          }, /* UK spelling */
-  { "license",    0,   0,  0,  0,          showcopyright          }, /* US spelling */
-  {  0,           0,   0,  0,  0,          0                      }
+  { "admindir",     0,   1,  0,  &admindir,  0               },
+  { "debug",       'D',  1,  0,  0,          setdebug        },
+  { "expert",      'E',  0,  0,  0,          setexpert       },
+  { "help",        'h',  0,  0,  0,          helponly        },
+  { "version",      0,   0,  0,  0,          versiononly     },
+  { "licence",      0,   0,  0,  0,          showcopyright   }, /* UK spelling */
+  { "license",      0,   0,  0,  0,          showcopyright   }, /* US spelling */
+  { "color",        0,   1,  0,  0,          setcolor        }, /* US spelling */
+  { "colour",       0,   1,  0,  0,          setcolor        }, /* UK spelling */
+  { 0,              0,   0,  0,  0,          0               }
 };
 
 static int cursesareon= 0;
@@ -244,11 +388,11 @@ int refreshmenu(void) {
   sprintf(buf,gettext(copyrightstring),DPKG_VERSION_ARCH);
   addstr(buf);
 
-  l = strlen(admindir);
-  lockfile = new char[l+sizeof(LOCKFILE)+2];
+  l= strlen(admindir);
+  lockfile= new char[l+sizeof(LOCKFILE)+2];
   strcpy(lockfile,admindir);
   strcpy(lockfile+l, "/" LOCKFILE);
-  lockfd = open(lockfile, O_RDWR|O_CREAT|O_TRUNC, 0660);
+  lockfd= open(lockfile, O_RDWR|O_CREAT|O_TRUNC, 0660);
   if (errno == EACCES || errno == EPERM)
     addstr(_("\n\n"
              "Read-only access: only preview of selections is available!"));