delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin-developers/2001/06/23/10:17:03

Mailing-List: contact cygwin-developers-help AT sourceware DOT cygnus DOT com; run by ezmlm
List-Subscribe: <mailto:cygwin-developers-subscribe AT sources DOT redhat DOT com>
List-Archive: <http://sources.redhat.com/ml/cygwin-developers/>
List-Post: <mailto:cygwin-developers AT sources DOT redhat DOT com>
List-Help: <mailto:cygwin-developers-help AT sources DOT redhat DOT com>, <http://sources.redhat.com/ml/#faqs>
Sender: cygwin-developers-owner AT sources DOT redhat DOT com
Delivered-To: mailing list cygwin-developers AT sources DOT redhat DOT com
Message-ID: <054c01c0fbef$5f600e20$0200a8c0@lifelesswks>
From: "Robert Collins" <robert DOT collins AT itdomain DOT com DOT au>
To: <cygwin-developers AT sources DOT redhat DOT com>, <cygwin-patches AT cygwin DOT com>
References: <04e801c0faa2$f9008260$0200a8c0 AT lifelesswks> <20010621222615 DOT C13746 AT redhat DOT com> <3B3324A7 DOT 49FFC98A AT yahoo DOT com>
Subject: Re: hierarchy in setup (category stuff)
Date: Sun, 24 Jun 2001 00:18:27 +1000
MIME-Version: 1.0
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 5.50.4133.2400
X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4133.2400
X-OriginalArrivalTime: 23 Jun 2001 14:06:55.0381 (UTC) FILETIME=[C2684C50:01C0FBED]

This is a multi-part message in MIME format.

------=_NextPart_000_0549_01C0FC43.305F8A70
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit


----- Original Message -----
From: "Earnie Boyd" <earnie_boyd AT yahoo DOT com>
To: <cygwin-developers AT sources DOT redhat DOT com>
Sent: Friday, June 22, 2001 8:57 PM
Subject: Re: hierarchy in setup (category stuff)


> Christopher Faylor wrote:
> >
> >
> > >4) Should category should uncategorised packages appear as?
> > >"Uncategorised" seems singularly unappealing..
> >
> > Misc?
> >
>
> Optional?
>

I've gone with "Misc". Optional has a implied judgment about the package
value, and I'm aiming for backwards compatability: ash etc should not
_need_ to be categorised for this setup.exe to make sense to the user.

I think that locally found packages (see recent threads on
cygwin AT cygwin DOT com) can be dumped into a new category "local" or
something similar.

I've attached my current sandbox changes. The code _is not finished_. (I
am _looking_ at adding the prev/curr/exp capability to whole categories
as well as the code cleanliness I mention below).

However: Feel free to throw stones at the UI, functionality, look n
feel. I need to know whether this is what folk have anticipated users
will understand.

Code-wise I need to tidy up the classes a little, and doing that will
make the code significantly smaller. The end I am currently targeting is
a large array of lines, with categories having a sub-count of the number
of packages visible and their own array pointer for those packages. That
will allow a slightly better class hierarchy...

anyway, have fun, feedback wanted.

Rob

------=_NextPart_000_0549_01C0FC43.305F8A70
Content-Type: application/octet-stream;
	name="choose.h"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="choose.h"

/*=0A=
 * Copyright (c) 2000, Red Hat, Inc.=0A=
 *=0A=
 *     This program is free software; you can redistribute it and/or =
modify=0A=
 *     it under the terms of the GNU General Public License as published =
by=0A=
 *     the Free Software Foundation; either version 2 of the License, or=0A=
 *     (at your option) any later version.=0A=
 *=0A=
 *     A copy of the GNU General Public License can be found at=0A=
 *     http://www.gnu.org/=0A=
 *=0A=
 * Written by Robert Collins <rbtcollins AT hotmail DOT com>=0A=
 *=0A=
 */=0A=
=0A=
#ifndef _CHOOSE_H_=0A=
#define _CHOOSE_H_=0A=
=0A=
#include "ini.h"=0A=
=0A=
#define CATEGORY_EXPANDED  0=0A=
#define CATEGORY_COLLAPSED 1=0A=
=0A=
=0A=
struct _header=0A=
{=0A=
  char *text;=0A=
  int slen;=0A=
  int width;=0A=
  int x;=0A=
};=0A=
=0A=
class pick_line=0A=
{=0A=
  public:=0A=
    void set_line (Package *_pkg);=0A=
    void set_line (Category *_cat);=0A=
    void paint (HDC hdc, int x, int y, int row, int show_cat);=0A=
    Package *get_pkg (void) { return pkg; };=0A=
    Category *get_category (void) { return cat; };=0A=
    int click (int x);=0A=
  private:=0A=
    Package *pkg;=0A=
    Category *cat;=0A=
};=0A=
=0A=
typedef class _view=0A=
{=0A=
  public:=0A=
    int num_columns;=0A=
    views get_view_mode () { return view_mode; };=0A=
    void set_view_mode(views _mode);=0A=
    struct _header *headers;=0A=
    _view (views mode, HDC dc);=0A=
    char *mode_caption ();=0A=
    void insert_pkg (Package *);=0A=
    void insert_category (Category *, int);=0A=
    void clear_view (void);=0A=
    int click (int row, int x);=0A=
    int current_col;=0A=
    int new_col;=0A=
    int src_col;=0A=
    int cat_col;=0A=
    int pkg_col;=0A=
    int last_col;=0A=
    pick_line * lines;=0A=
    int nlines;=0A=
=0A=
  private:=0A=
    views view_mode;=0A=
    void set_headers (void);=0A=
    void init_headers (HDC dc);=0A=
    void insert_at (int, Package *);=0A=
=0A=
} view;=0A=
=0A=
#endif /* _CHOOSE_H_ */=0A=

------=_NextPart_000_0549_01C0FC43.305F8A70
Content-Type: application/octet-stream;
	name="hierarchy.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="hierarchy.patch"

? .iniparse.y.swp=0A=
? .tar.cc.swp=0A=
? choose.h=0A=
? depends2.patch=0A=
? depends4.patch=0A=
? hierarchy.patch=0A=
? home.patch=0A=
? orcinstall=0A=
? work.patch=0A=
Index: choose.cc=0A=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
RCS file: /cvs/src/src/winsup/cinstall/choose.cc,v=0A=
retrieving revision 2.33=0A=
diff -u -p -r2.33 choose.cc=0A=
--- choose.cc	2001/06/16 18:50:13	2.33=0A=
+++ choose.cc	2001/06/23 14:12:51=0A=
@@ -43,6 +43,7 @@ static char *cvsid =3D "\n%%% $Id: choose.=0A=
 #include "find.h"=0A=
 #include "filemanip.h"=0A=
 #include "mount.h"=0A=
+#include "choose.h"=0A=
 =0A=
 #include "port.h"=0A=
 =0A=
@@ -55,8 +56,6 @@ static char *cvsid =3D "\n%%% $Id: choose.=0A=
 =0A=
 static int initialized =3D 0;=0A=
 =0A=
-static int full_list =3D 0;=0A=
-=0A=
 static int scroll_ulc_x, scroll_ulc_y;=0A=
 =0A=
 static HWND lv, nextbutton, choose_inst_text;=0A=
@@ -66,28 +65,29 @@ static HANDLE sysfont;=0A=
 static int row_height;=0A=
 static HANDLE bm_spin, bm_rtarrow, bm_checkyes, bm_checkno, bm_checkna;=0A=
 static HDC bitmap_dc;=0A=
+static view *chooser =3D NULL;=0A=
+=0A=
+static struct _header pkg_headers[] =3D {=0A=
+  { "Current", 7, 0, 0 },=0A=
+  { "New", 3, 0, 0 },=0A=
+  { "Src?", 4, 0, 0 },=0A=
+  { "Category", 8, 0, 0 },=0A=
+  { "Package", 7, 0, 0 },=0A=
+  { 0, 0, 0, 0 }=0A=
+};=0A=
 =0A=
-static struct=0A=
-  {=0A=
-    char *text;=0A=
-    int slen;=0A=
-    int width;=0A=
-    int x;=0A=
-  }=0A=
-headers[] =3D {=0A=
+static struct _header cat_headers[] =3D {=0A=
+  { "Category", 8, 0, 0 },=0A=
   { "Current", 7, 0, 0 },=0A=
-#define CURRENT_COL 0=0A=
   { "New", 3, 0, 0 },=0A=
-#define NEW_COL 1=0A=
   { "Src?", 4, 0, 0 },=0A=
-#define SRC_COL 2=0A=
   { "Package", 7, 0, 0 },=0A=
-#define PACKAGE_COL 3=0A=
   { 0, 0, 0, 0 }=0A=
 };=0A=
-#define NUM_COLUMNS (sizeof (headers) / (sizeof (headers[0])) - 1)=0A=
+=0A=
+static int add_required(Package *pkg);=0A=
+static void set_view_mode (HWND h, views mode);=0A=
 =0A=
-int *package_indexes, nindexes;=0A=
 =0A=
 static bool=0A=
 isinstalled (Package *pkg, int trust)=0A=
@@ -165,6 +165,69 @@ set_action (Package *pkg, bool preinc)=0A=
       }=0A=
 }=0A=
 =0A=
+static int=0A=
+add_required (Package *pkg)=0A=
+{=0A=
+  Dependency *dp;=0A=
+  Package *required;=0A=
+  int c;=0A=
+  int changed =3D 0;=0A=
+  dp =3D pkg->required;=0A=
+  switch (pkg->action)=0A=
+    {=0A=
+    case ACTION_UNINSTALL:=0A=
+    case ACTION_ERROR:=0A=
+    case ACTION_UNKNOWN:=0A=
+    case ACTION_SRC_ONLY:=0A=
+    case ACTION_SKIP:=0A=
+      return 0;=0A=
+    default:=0A=
+      break;=0A=
+    }=0A=
+  while (dp)=0A=
+    {=0A=
+      if ((required =3D getpkgbyname(dp->package)) =3D=3D NULL)=0A=
+        {=0A=
+          dp=3Ddp->next;=0A=
+          continue;=0A=
+        }=0A=
+      switch (required->action)=0A=
+        {=0A=
+	case ACTION_PREV:=0A=
+	case ACTION_CURR:=0A=
+	case ACTION_TEST:=0A=
+	case ACTION_LAST:=0A=
+	case ACTION_SAME_CURR:=0A=
+	case ACTION_SAME_TEST:=0A=
+	case ACTION_SAME_PREV:=0A=
+	case ACTION_REDO:=0A=
+	case ACTION_SAME_LAST:=0A=
+	  /* we are installing a user selected version */=0A=
+	  break;=0A=
+	=0A=
+	case ACTION_UNINSTALL:=0A=
+	  /* it's already installed - leave it */=0A=
+	  required->action =3D ACTION_SKIP;=0A=
+	  break;=0A=
+	case ACTION_ERROR:=0A=
+	case ACTION_UNKNOWN:=0A=
+	case ACTION_SRC_ONLY:=0A=
+	case ACTION_SKIP:=0A=
+	  /* the current install will fail */=0A=
+	  required->action =3D ACTION_PREV; /* this find prev, then curr, then =
test. */=0A=
+	  set_action(required, 0);	  /* we need a find_best that gets =
installed, */=0A=
+	  changed++;			  /* then current, then prev, then test */=0A=
+	  chooser->insert_pkg (required);=0A=
+	  break;=0A=
+	default:=0A=
+	  log (0, "should never get here %d\n", required->action);=0A=
+	}=0A=
+      changed +=3D add_required (required);=0A=
+      dp=3Ddp->next;=0A=
+    }=0A=
+  return changed;=0A=
+}=0A=
+=0A=
 /* Return an appropriate caption given the current action. */=0A=
 const char *=0A=
 choose_caption (Package *pkg)=0A=
@@ -217,55 +280,19 @@ paint (HWND hwnd)=0A=
   y =3D cr.top - scroll_ulc_y + header_height;=0A=
 =0A=
 =0A=
-  for (i =3D 0; headers[i].text; i++)=0A=
+  for (i =3D 0; i <=3D chooser->last_col ; i++)=0A=
     {=0A=
-      TextOut (hdc, x + headers[i].x, 3, headers[i].text, =
headers[i].slen);=0A=
-      MoveToEx (hdc, x + headers[i].x, header_height-3, &p);=0A=
-      LineTo (hdc, x + headers[i].x + headers[i].width, =
header_height-3);=0A=
+      TextOut (hdc, x + chooser->headers[i].x, 3, =
chooser->headers[i].text, chooser->headers[i].slen);=0A=
+      MoveToEx (hdc, x + chooser->headers[i].x, header_height-3, &p);=0A=
+      LineTo (hdc, x + chooser->headers[i].x + =
chooser->headers[i].width, header_height-3);=0A=
     }=0A=
 =0A=
   IntersectClipRect (hdc, cr.left, cr.top + header_height, cr.right, =
cr.bottom);=0A=
-=0A=
-  for (ii =3D 0; ii < nindexes; ii++)=0A=
-    {=0A=
-      i =3D package_indexes[ii];=0A=
-      Package *pkg =3D package + i;=0A=
-      int r =3D y + ii * row_height;=0A=
-      int by =3D r + tm.tmHeight - 11;=0A=
-      if (pkg->installed)=0A=
-	{=0A=
-	  TextOut (hdc, x + headers[CURRENT_COL].x, r,=0A=
-		   pkg->installed->version, strlen (pkg->installed->version));=0A=
-	  SelectObject (bitmap_dc, bm_rtarrow);=0A=
-	  BitBlt (hdc, x + headers[CURRENT_COL].x + headers[0].width + =
ICON_MARGIN/2 + HMARGIN/2, by,=0A=
-		  11, 11, bitmap_dc, 0, 0, SRCCOPY);=0A=
-	}=0A=
-=0A=
-      const char *s =3D choose_caption (pkg);=0A=
-      TextOut (hdc, x + headers[NEW_COL].x + NEW_COL_SIZE_SLOP, r,=0A=
-	       s, strlen (s));=0A=
-      SelectObject (bitmap_dc, bm_spin);=0A=
-      BitBlt (hdc, x + headers[NEW_COL].x, by, 11, 11,=0A=
-	      bitmap_dc, 0, 0, SRCCOPY);=0A=
 =0A=
-      HANDLE check_bm;=0A=
-      if (pkg->srcpicked)=0A=
-	check_bm =3D bm_checkyes;=0A=
-      else=0A=
-	check_bm =3D bm_checkno;=0A=
-=0A=
-      SelectObject (bitmap_dc, check_bm);=0A=
-      BitBlt (hdc, x + headers[SRC_COL].x, by, 11, 11,=0A=
-	      bitmap_dc, 0, 0, SRCCOPY);=0A=
+  for (ii =3D 0; ii < chooser->nlines; ii++)=0A=
+      chooser->lines[ii].paint (hdc, x, y, ii, (chooser->get_view_mode =
() =3D=3D VIEW_CATEGORY) ? 0 : 1);=0A=
 =0A=
-      if (package[i].sdesc)=0A=
-	s =3D package[i].sdesc;=0A=
-      else=0A=
-	s =3D package[i].name;=0A=
-      TextOut (hdc, x + headers[PACKAGE_COL].x, r, s, strlen (s));=0A=
-    }=0A=
-=0A=
-  if (nindexes =3D=3D 0)=0A=
+  if (chooser->nlines =3D=3D 0)=0A=
     {=0A=
       static char *msg =3D "Nothing to Install/Update";=0A=
       if (source =3D=3D IDC_SOURCE_DOWNLOAD)=0A=
@@ -350,9 +377,9 @@ list_hscroll (HWND hwnd, HWND hctl, UINT=0A=
 static LRESULT CALLBACK=0A=
 list_click (HWND hwnd, BOOL dblclk, int x, int y, UINT hitCode)=0A=
 {=0A=
-  int r;=0A=
+  int r,refresh;=0A=
 =0A=
-  if (nindexes =3D=3D 0)=0A=
+  if (chooser->nlines =3D=3D 0)=0A=
     return 0;=0A=
 =0A=
   if (y < header_height)=0A=
@@ -362,23 +389,38 @@ list_click (HWND hwnd, BOOL dblclk, int =0A=
 =0A=
   r =3D (y + ROW_MARGIN/2) / row_height;=0A=
 =0A=
-  if (r < 0 || r >=3D nindexes)=0A=
+  if (r < 0 || r >=3D chooser->nlines)=0A=
     return 0;=0A=
-=0A=
-  Package *pkg =3D package + package_indexes[r];=0A=
 =0A=
-  if (x >=3D headers[NEW_COL].x - (HMARGIN / 2) && x <=3D =
headers[NEW_COL + 1].x - HMARGIN/2)=0A=
-    set_action (pkg, 1);=0A=
+  refresh =3D chooser->click (r, x);=0A=
+ =0A=
+  if (refresh)=0A=
+    {=0A=
+      RECT r;=0A=
+      GetClientRect (lv, &r);=0A=
+      SCROLLINFO si;=0A=
+      memset (&si, 0, sizeof (si));=0A=
+      si.cbSize =3D sizeof (si);=0A=
+      si.fMask =3D SIF_ALL; /* SIF_RANGE was giving strange behaviour */=0A=
+      si.nMin =3D 0;=0A=
+=0A=
+      si.nMax =3D chooser->nlines * row_height;=0A=
+      si.nPage =3D r.bottom - header_height;=0A=
+      si.nPos =3D scroll_ulc_y;=0A=
+      SetScrollInfo (lv, SB_VERT, &si, TRUE);=0A=
 =0A=
-  if (x >=3D headers[SRC_COL].x - HMARGIN/2 && x <=3D headers[SRC_COL + =
1].x - HMARGIN/2)=0A=
-    pkg->srcpicked ^=3D 1;=0A=
+      InvalidateRect (lv, &r, TRUE);=0A=
 =0A=
-  RECT rect;=0A=
-  rect.left =3D headers[NEW_COL].x - scroll_ulc_x;=0A=
-  rect.right =3D headers[SRC_COL + 1].x - scroll_ulc_x;=0A=
-  rect.top =3D header_height + r * row_height - scroll_ulc_y;=0A=
-  rect.bottom =3D rect.top + row_height;=0A=
-  InvalidateRect (hwnd, &rect, TRUE);=0A=
+    }=0A=
+  else=0A=
+    {=0A=
+      RECT rect;=0A=
+      rect.left =3D chooser->headers[chooser->new_col].x - scroll_ulc_x;=0A=
+      rect.right =3D chooser->headers[chooser->src_col + 1].x - =
scroll_ulc_x;=0A=
+      rect.top =3D header_height + r * row_height - scroll_ulc_y;=0A=
+      rect.bottom =3D rect.top + row_height;=0A=
+      InvalidateRect (hwnd, &rect, TRUE);=0A=
+    }=0A=
 }=0A=
 =0A=
 static LRESULT CALLBACK=0A=
@@ -424,14 +466,14 @@ register_windows (HINSTANCE hinst)=0A=
 }=0A=
 =0A=
 static void=0A=
-note_width (HDC dc, char *string, int addend, int column)=0A=
+note_width (struct _header *hdrs, HDC dc, char *string, int addend, int =
column)=0A=
 {=0A=
   if (!string)=0A=
     return;=0A=
   SIZE s;=0A=
   GetTextExtentPoint32 (dc, string, strlen (string), &s);=0A=
-  if (headers[column].width < s.cx + addend)=0A=
-    headers[column].width =3D s.cx + addend;=0A=
+  if (hdrs[column].width < s.cx + addend)=0A=
+    hdrs[column].width =3D s.cx + addend;=0A=
 }=0A=
 =0A=
 static int=0A=
@@ -474,6 +516,14 @@ set_existence ()=0A=
 }=0A=
 =0A=
 static void=0A=
+fill_missing_category ()=0A=
+{=0A=
+  for (Package *pkg =3D package; pkg->name; pkg++)=0A=
+    if (!pkg->category)=0A=
+      add_category (pkg, register_category ("Misc"));=0A=
+}=0A=
+=0A=
+static void=0A=
 default_trust (HWND h, trusts trust)=0A=
 {=0A=
   int i, t, c;=0A=
@@ -481,6 +531,9 @@ default_trust (HWND h, trusts trust)=0A=
   for (Package *pkg =3D package; pkg->name; pkg++)=0A=
     {=0A=
       pkg->action =3D (actions) trust;=0A=
+      if (pkg->category && !(getpackagecategorybyname (pkg, "Required") =
||=0A=
+			     getpackagecategorybyname (pkg, "Misc")))=0A=
+	pkg->action =3D ACTION_SKIP;=0A=
       set_action (pkg, 0);=0A=
     }=0A=
   RECT r;=0A=
@@ -490,24 +543,462 @@ default_trust (HWND h, trusts trust)=0A=
     SetFocus (nextbutton);=0A=
 }=0A=
 =0A=
-static void=0A=
-set_full_list (HWND h, int isfull)=0A=
+void=0A=
+pick_line::set_line (Package *_pkg)=0A=
+{=0A=
+  pkg =3D _pkg;=0A=
+  cat =3D NULL;=0A=
+}=0A=
+=0A=
+void=0A=
+pick_line::set_line (Category *_cat)=0A=
 {=0A=
+  cat =3D _cat;=0A=
+  pkg =3D NULL;=0A=
+}=0A=
+=0A=
+void=0A=
+pick_line::paint (HDC hdc, int x, int y, int row, int show_cat)=0A=
+{=0A=
+  int r =3D y + row * row_height;=0A=
+  int by =3D r + tm.tmHeight - 11;=0A=
+  if (pkg)=0A=
+    {=0A=
+      if (pkg->installed)=0A=
+        {=0A=
+          TextOut (hdc, x + chooser->headers[chooser->current_col].x, r,=0A=
+                   pkg->installed->version, strlen =
(pkg->installed->version));=0A=
+          SelectObject (bitmap_dc, bm_rtarrow);=0A=
+          BitBlt (hdc, x + chooser->headers[chooser->current_col].x + =
chooser->headers[0].width + ICON_MARGIN/2 + HMARGIN/2, by,=0A=
+                  11, 11, bitmap_dc, 0, 0, SRCCOPY);=0A=
+        }=0A=
+=0A=
+      const char *s =3D choose_caption (pkg);=0A=
+      TextOut (hdc, x + chooser->headers[chooser->new_col].x + =
NEW_COL_SIZE_SLOP, r,=0A=
+               s, strlen (s));=0A=
+      SelectObject (bitmap_dc, bm_spin);=0A=
+      BitBlt (hdc, x + chooser->headers[chooser->new_col].x, by, 11, 11,=0A=
+              bitmap_dc, 0, 0, SRCCOPY);=0A=
+=0A=
+      HANDLE check_bm;=0A=
+      if (pkg->srcpicked)=0A=
+        check_bm =3D bm_checkyes;=0A=
+      else=0A=
+        check_bm =3D bm_checkno;=0A=
+=0A=
+      SelectObject (bitmap_dc, check_bm);=0A=
+      BitBlt (hdc, x + chooser->headers[chooser->src_col].x, by, 11, 11,=0A=
+              bitmap_dc, 0, 0, SRCCOPY);=0A=
+=0A=
+	/* shows "first" category - do we want to show any? */=0A=
+      if (pkg->category && show_cat)=0A=
+       TextOut (hdc, x + chooser->headers[chooser->cat_col].x, r, =
pkg->category->name, strlen (pkg->category->name));=0A=
+=0A=
+      if (pkg->sdesc)=0A=
+        s =3D pkg->sdesc;=0A=
+      else=0A=
+        s =3D pkg->name;=0A=
+      TextOut (hdc, x + chooser->headers[chooser->pkg_col].x, r, s, =
strlen (s));=0A=
+    }=0A=
+  else if (cat)=0A=
+    {=0A=
+      TextOut (hdc, x + chooser->headers[chooser->cat_col].x, r, =
cat->name, strlen (cat->name));=0A=
+    }=0A=
+}=0A=
+=0A=
+int=0A=
+pick_line::click (int x)=0A=
+{=0A=
+  if (pkg)=0A=
+    {=0A=
+      if (x >=3D chooser->headers[chooser->src_col].x - HMARGIN/2 && x =
<=3D chooser->headers[chooser->src_col + 1].x - HMARGIN/2)=0A=
+      pkg->srcpicked ^=3D 1;=0A=
+=0A=
+    if (x >=3D chooser->headers[chooser->new_col].x - (HMARGIN / 2) && =
x <=3D chooser->headers[chooser->new_col + 1].x - HMARGIN/2)=0A=
+      {=0A=
+        set_action (pkg, 1);=0A=
+        /* Add any packages that are needed by this package */=0A=
+        return add_required  (pkg);=0A=
+      }=0A=
+    }=0A=
+  else if (cat)=0A=
+    {=0A=
+      /* handle the catalog being clicked ... does this belong up a =
level.. ? */=0A=
+    }=0A=
+  =0A=
+  return 0;=0A=
+}=0A=
+=0A=
+_view::_view (views _mode, HDC dc)=0A=
+{=0A=
+  lines =3D NULL;=0A=
+  nlines =3D 0;=0A=
+  view_mode =3D VIEW_PACKAGE;=0A=
+  set_headers ();=0A=
+  init_headers (dc);=0A=
+  view_mode =3D VIEW_CATEGORY;=0A=
+  set_headers ();=0A=
+  init_headers (dc);=0A=
+=0A=
+  view_mode =3D _mode;=0A=
+  set_headers ();=0A=
+}=0A=
+=0A=
+void=0A=
+_view::set_view_mode (views _mode)=0A=
+{=0A=
+  if (_mode =3D=3D NVIEW)=0A=
+      view_mode =3D VIEW_PACKAGE_FULL;=0A=
+  else=0A=
+    view_mode =3D _mode;=0A=
+  set_headers ();=0A=
+}=0A=
+=0A=
+char *=0A=
+_view::mode_caption ()=0A=
+{=0A=
+  switch (view_mode)=0A=
+    {=0A=
+    case VIEW_UNKNOWN:      return "";=0A=
+    case VIEW_PACKAGE_FULL: return "Full";=0A=
+    case VIEW_PACKAGE:      return "Partial";=0A=
+    case VIEW_CATEGORY:     return "Category";=0A=
+    default:                return "";=0A=
+    }=0A=
+}=0A=
+=0A=
+void=0A=
+_view::set_headers (void)=0A=
+{=0A=
+  switch (view_mode)=0A=
+    {=0A=
+    case VIEW_UNKNOWN:=0A=
+      return;=0A=
+    case VIEW_PACKAGE_FULL: =0A=
+    case VIEW_PACKAGE:      =0A=
+      headers =3D pkg_headers;=0A=
+      current_col =3D 0;=0A=
+      new_col =3D 1;=0A=
+      src_col =3D 2;=0A=
+      cat_col =3D 3;=0A=
+      pkg_col =3D 4;=0A=
+      last_col =3D 4;=0A=
+      break;=0A=
+    case VIEW_CATEGORY:=0A=
+      headers =3D cat_headers;=0A=
+      current_col =3D 1;=0A=
+      new_col =3D 2;=0A=
+      src_col =3D 3;=0A=
+      cat_col =3D 0;=0A=
+      pkg_col =3D 4;=0A=
+      last_col =3D 4;=0A=
+    default:=0A=
+      return;=0A=
+    }=0A=
+}=0A=
+=0A=
+void=0A=
+_view::init_headers (HDC dc)=0A=
+{=0A=
   int i;=0A=
-  full_list =3D isfull;=0A=
 =0A=
-  if (package_indexes =3D=3D 0)=0A=
-    package_indexes =3D (int *) malloc (npackages * sizeof (int));=0A=
+  for (i =3D 0; headers[i].text; i++)=0A=
+    headers[i].width =3D 0;=0A=
 =0A=
-  nindexes =3D 0;=0A=
+  for (i =3D 0; headers[i].text; i++)=0A=
+    note_width (headers, dc, headers[i].text, 0, i);=0A=
   for (Package *pkg =3D package; pkg->name; pkg++)=0A=
+    {=0A=
+      if (pkg->installed)=0A=
+        {=0A=
+          note_width (headers, dc, pkg->installed->version, 0, =
current_col);=0A=
+          note_width (headers, dc, pkg->installed->version, =
NEW_COL_SIZE_SLOP, new_col);=0A=
+        }=0A=
+      for (Info *inf =3D pkg->infoscan; inf < pkg->infoend; inf++)=0A=
+        note_width (headers, dc, inf->version, NEW_COL_SIZE_SLOP, =
new_col);=0A=
+      for (Category *cat =3D pkg->category; cat ; cat =3D cat->next)=0A=
+	note_width (headers, dc, cat->name, 0, cat_col);=0A=
+      note_width (headers, dc, pkg->name, 0, pkg_col);=0A=
+      note_width (headers, dc, pkg->sdesc, 0, pkg_col);=0A=
+    }=0A=
+  note_width (headers, dc, "keep", NEW_COL_SIZE_SLOP, new_col);=0A=
+  note_width (headers, dc, "uninstall", NEW_COL_SIZE_SLOP, new_col);=0A=
+=0A=
+  headers[0].x =3D HMARGIN/2;=0A=
+  for (i =3D 1; i <=3D last_col ; i++)=0A=
+    headers[i].x =3D headers[i-1].x + headers[i-1].width + ((i =3D=3D =
new_col) ? NEW_COL_SIZE_SLOP : 0) + HMARGIN;=0A=
+;=0A=
+}=0A=
+=0A=
+void=0A=
+_view::insert_pkg (Package *pkg)=0A=
+{=0A=
+  if (view_mode !=3D VIEW_CATEGORY)=0A=
+    {=0A=
+      if (lines =3D=3D NULL)=0A=
+        {=0A=
+          lines =3D (pick_line *) malloc ((npackages + ncategories) * =
sizeof (pick_line));=0A=
+          memset (lines, '\0', (npackages + ncategories) * sizeof =
(pick_line) );=0A=
+          nlines =3D 1;=0A=
+          lines[0].set_line (pkg);=0A=
+        }=0A=
+      else=0A=
+        {=0A=
+          int n=3D0;=0A=
+          while (n < nlines)=0A=
+            {=0A=
+              /* this should be a generic call to list_sort_cmp */=0A=
+              if (lines[n].get_pkg () =0A=
+  	          && strcasecmp (pkg->name, lines[n].get_pkg ()->name) < 0)=0A=
+                {=0A=
+                  memmove (&lines[n + 1], &lines[n], (nlines - n) * =
sizeof (pick_line));=0A=
+                  lines[n].set_line (pkg);=0A=
+                  nlines++;=0A=
+                  n =3D nlines;=0A=
+                }=0A=
+              else if (lines[n].get_pkg () =3D=3D pkg)=0A=
+	        {=0A=
+                  n =3D nlines - 1;=0A=
+                }=0A=
+	      n++;=0A=
+          =0A=
+            }=0A=
+          if (n =3D=3D nlines)=0A=
+	    {=0A=
+   	      /* insert at the end */=0A=
+	      lines[n].set_line (pkg);=0A=
+ 	      nlines++;=0A=
+	    }=0A=
+        }=0A=
+    }=0A=
+  else=0A=
+    {=0A=
+//      assert (lines); /* protect against a coding change in future */=0A=
+      for (Category *cat =3D pkg->category; cat; cat =3D cat->next)=0A=
+	{=0A=
+	  /* insert the package under this category in the list. If this =
category is not=0A=
+	     visible, add it */=0A=
+	  int n=3D0;=0A=
+	  while (n < nlines)=0A=
+	    {=0A=
+	      /* this should be a generic call to list_sort_cmp */=0A=
+	      if (lines[n].get_category ()=0A=
+		  && cat->name =3D=3D lines[n].get_category ()->name)=0A=
+		{=0A=
+		/* insert under this category */=0A=
+		  n++;=0A=
+		  while (n < nlines &! lines[n].get_category ())=0A=
+		    {=0A=
+		      if (lines[n].get_pkg ()=0A=
+			  && strcasecmp (pkg->name, lines[n].get_pkg ()->name) < 0)=0A=
+			{=0A=
+			  memmove (&lines[n + 1], &lines[n], (nlines - n) * sizeof =
(pick_line));=0A=
+			  lines[n].set_line (pkg);=0A=
+			  nlines++;=0A=
+			  n =3D nlines;=0A=
+			}=0A=
+	      	     else if (lines[n].get_pkg () =3D=3D pkg)=0A=
+			{=0A=
+			  n =3D nlines;=0A=
+			}=0A=
+		    else if (lines[n].get_category ())=0A=
+			{=0A=
+			  memmove (&lines[n + 1], &lines[n], (nlines - n) * sizeof =
(pick_line));=0A=
+			  lines[n].set_line (pkg);=0A=
+			  nlines++;=0A=
+			  n =3D nlines;=0A=
+			}=0A=
+		      n++;=0A=
+		    }=0A=
+		  if (n =3D=3D nlines)=0A=
+		    {=0A=
+		      /* insert at the end of this category */=0A=
+		      lines[n].set_line (pkg);=0A=
+		      nlines++;=0A=
+		      n=3Dnlines + 1;=0A=
+		    }=0A=
+		}=0A=
+	      n++;=0A=
+	    }=0A=
+	  if (n =3D=3D nlines)=0A=
+	    {=0A=
+	      /* the category wasn't visible - insert at the end */=0A=
+	      insert_category (cat, CATEGORY_COLLAPSED);=0A=
+	      insert_pkg (pkg);=0A=
+	    }=0A=
+	}=0A=
+    }=0A=
+}=0A=
+=0A=
+void=0A=
+_view::insert_category (Category *cat, int collapsed)=0A=
+{=0A=
+  if (lines =3D=3D NULL)=0A=
+    {=0A=
+      lines =3D (pick_line *) malloc ((npackages + ncategories) * =
sizeof (pick_line));=0A=
+      memset (lines, '\0', (npackages + ncategories) * sizeof =
(pick_line) );=0A=
+      nlines =3D 1;=0A=
+      lines[0].set_line (cat);=0A=
+      if (!collapsed)=0A=
+	for (CategoryPackage *catpkg =3D cat->packages; catpkg; catpkg =3D =
catpkg->next)=0A=
+	  insert_pkg (getpkgbyname (catpkg->pkg));=0A=
+    }=0A=
+  else=0A=
+    {=0A=
+      int n=3D0;=0A=
+      while (n < nlines)=0A=
+        {=0A=
+          /* this should be a generic call to list_sort_cmp */=0A=
+          if (lines[n].get_category ()=0A=
+              && strcasecmp (cat->name, lines[n].get_category ()->name) =
< 0)=0A=
+            {=0A=
+              memmove (&lines[n + 1], &lines[n], (nlines - n) * sizeof =
(pick_line));=0A=
+              lines[n].set_line (cat);=0A=
+              nlines++;=0A=
+	      if (!collapsed)=0A=
+		for (CategoryPackage *catpkg =3D cat->packages; catpkg; catpkg =3D =
catpkg->next)=0A=
+		  insert_pkg (getpkgbyname (catpkg->pkg));=0A=
+              n =3D nlines;=0A=
+            }=0A=
+          else if (lines[n].get_category () =3D=3D cat)=0A=
+            {=0A=
+              n =3D nlines - 1;=0A=
+            }=0A=
+          n++;=0A=
+=0A=
+        }=0A=
+      if (n =3D=3D nlines)=0A=
+        {=0A=
+          /* insert at the end */=0A=
+          lines[n].set_line (cat);=0A=
+          nlines++;=0A=
+	  if (!collapsed)=0A=
+	    for (CategoryPackage *catpkg =3D cat->packages; catpkg; catpkg =3D =
catpkg->next)=0A=
+	      insert_pkg (getpkgbyname (catpkg->pkg));=0A=
+        }=0A=
+    }=0A=
+}=0A=
+=0A=
+void=0A=
+_view::clear_view (void)=0A=
+{=0A=
+  nlines =3D 0;=0A=
+}=0A=
+=0A=
+static views=0A=
+viewsplusplus(views theview)=0A=
+{=0A=
+  switch (theview)=0A=
+    {=0A=
+    case VIEW_UNKNOWN:      return VIEW_PACKAGE_FULL;=0A=
+    case VIEW_PACKAGE_FULL: return VIEW_PACKAGE;=0A=
+    case VIEW_PACKAGE:      return VIEW_CATEGORY;=0A=
+    case VIEW_CATEGORY:     return NVIEW;=0A=
+    default:                return VIEW_UNKNOWN;=0A=
+    }=0A=
+}=0A=
+=0A=
+int=0A=
+_view::click (int row, int x)=0A=
+{=0A=
+  if (row > nlines)=0A=
+    return 0;=0A=
+  if (lines[row].get_pkg ())=0A=
+    return lines[row].click (x);=0A=
+  else=0A=
+    {=0A=
+      /* if we are the last line or the next line is a category too, =
expand */=0A=
+      if (row =3D=3D (nlines -1) || lines[row + 1].get_category ())=0A=
+	{=0A=
+	  int count =3D nlines;=0A=
+	  for (CategoryPackage *catpkg =3D lines[row].get_category =
()->packages; catpkg; catpkg =3D catpkg->next)=0A=
+	    {=0A=
+	      Package * pkg =3D getpkgbyname (catpkg->pkg);=0A=
+	      int n =3D row + 1;=0A=
+	      /* this is a nasty hack. It will go away when the hierarchy is =
coded */=0A=
+	      while (n < nlines)=0A=
+	        {=0A=
+		  if (lines[n].get_pkg ()=0A=
+		      && strcasecmp (pkg->name, lines[n].get_pkg ()->name) < 0)=0A=
+		    {=0A=
+		      memmove (&lines[n + 1], &lines[n], (nlines - n) * sizeof =
(pick_line));=0A=
+		      lines[n].set_line (pkg);=0A=
+		      nlines++;=0A=
+		      n =3D nlines;=0A=
+		    }=0A=
+		  else if (lines[n].get_pkg () =3D=3D pkg)=0A=
+		    {=0A=
+		      n =3D nlines;=0A=
+		    }=0A=
+		  else if (lines[n].get_category ())=0A=
+		    {=0A=
+		      memmove (&lines[n + 1], &lines[n], (nlines - n) * sizeof =
(pick_line));=0A=
+		      lines[n].set_line (pkg);=0A=
+		      nlines++;=0A=
+		      n =3D nlines;=0A=
+		    }=0A=
+		  n++;=0A=
+		}=0A=
+	      if (n =3D=3D nlines)=0A=
+		{=0A=
+		  /* insert at the end of this category */=0A=
+		  lines[n].set_line (pkg);=0A=
+		  nlines++;=0A=
+		  n=3Dnlines + 1;=0A=
+		}=0A=
+	    }=0A=
+	  return nlines - count;=0A=
+	}=0A=
+      else=0A=
+	/* contract */=0A=
+	{=0A=
+	  int count =3D 0, n =3D row + 1;=0A=
+	  while (n < nlines &! lines[n].get_category ())=0A=
+	    {=0A=
+	      memmove (&lines[n], &lines[n + 1], (nlines - n) * sizeof =
(pick_line));=0A=
+	      nlines--;=0A=
+	      count++;=0A=
+	    }=0A=
+	  return count;=0A=
+	}=0A=
+    }=0A=
+}=0A=
+=0A=
+=0A=
+static void=0A=
+set_view_mode (HWND h, views mode)=0A=
+{=0A=
+  int i;=0A=
+  chooser->set_view_mode (mode);=0A=
+=0A=
+  chooser->clear_view ();=0A=
+  for (Package *pkg =3D package; pkg->name; pkg++)=0A=
     if (!pkg->exclude)=0A=
       {=0A=
-	set_action (pkg, 0);=0A=
-	if ((isfull || is_download_action (pkg)))=0A=
-	  package_indexes[nindexes++] =3D pkg - package;=0A=
+        set_action (pkg, 0);=0A=
       }=0A=
 =0A=
+  switch (chooser->get_view_mode ())=0A=
+    {=0A=
+    case VIEW_PACKAGE:=0A=
+      for (Package *pkg =3D package; pkg->name; pkg++)=0A=
+	if (!pkg->exclude && is_download_action (pkg)) =0A=
+	  chooser->insert_pkg (pkg); =0A=
+      break;=0A=
+    case VIEW_PACKAGE_FULL:=0A=
+      for (Package *pkg =3D package; pkg->name; pkg++)=0A=
+	if (!pkg->exclude) =0A=
+	  chooser->insert_pkg (pkg); =0A=
+      break;=0A=
+    case VIEW_CATEGORY:=0A=
+      /* start collapsed. TODO: make this a chooser flag */=0A=
+      for (Category *cat =3D category; cat; cat =3D cat->next)=0A=
+	chooser->insert_category (cat, CATEGORY_COLLAPSED);=0A=
+      break;=0A=
+    default:=0A=
+      break;=0A=
+    }=0A=
+=0A=
   RECT r;=0A=
   GetClientRect (h, &r);=0A=
   SCROLLINFO si;=0A=
@@ -515,11 +1006,11 @@ set_full_list (HWND h, int isfull)=0A=
   si.cbSize =3D sizeof (si);=0A=
   si.fMask =3D SIF_ALL;=0A=
   si.nMin =3D 0;=0A=
-  si.nMax =3D headers[2].x + headers[2].width + HMARGIN;=0A=
+  si.nMax =3D chooser->headers[chooser->last_col].x + =
chooser->headers[chooser->last_col].width + HMARGIN;=0A=
   si.nPage =3D r.right;=0A=
   SetScrollInfo (h, SB_HORZ, &si, TRUE);=0A=
 =0A=
-  si.nMax =3D nindexes * row_height;=0A=
+  si.nMax =3D chooser->nlines * row_height;=0A=
   si.nPage =3D r.bottom - header_height;=0A=
   SetScrollInfo (h, SB_VERT, &si, TRUE);=0A=
 =0A=
@@ -546,10 +1037,6 @@ create_listview (HWND dlg, RECT *r)=0A=
 		       hinstance,=0A=
 		       0);=0A=
   ShowWindow (lv, SW_SHOW);=0A=
-=0A=
-  for (i =3D 0; headers[i].text; i++)=0A=
-    headers[i].width =3D 0;=0A=
-=0A=
   HDC dc =3D GetDC (lv);=0A=
   sysfont =3D GetStockObject (DEFAULT_GUI_FONT);=0A=
   SelectObject (dc, sysfont);=0A=
@@ -563,30 +1050,14 @@ create_listview (HWND dlg, RECT *r)=0A=
   if (row_height < irh)=0A=
     row_height =3D irh;=0A=
 =0A=
-  for (i =3D 0; headers[i].text; i++)=0A=
-    note_width (dc, headers[i].text, 0, i);=0A=
-  for (Package *pkg =3D package; pkg->name; pkg++)=0A=
-    {=0A=
-      if (pkg->installed)=0A=
-	{=0A=
-	  note_width (dc, pkg->installed->version, 0, CURRENT_COL);=0A=
-	  note_width (dc, pkg->installed->version, NEW_COL_SIZE_SLOP, NEW_COL);=0A=
-	}=0A=
-      for (Info *inf =3D pkg->infoscan; inf < pkg->infoend; inf++)=0A=
-	note_width (dc, inf->version, NEW_COL_SIZE_SLOP, NEW_COL);=0A=
-      note_width (dc, pkg->name, 0, PACKAGE_COL);=0A=
-      note_width (dc, pkg->sdesc, 0, PACKAGE_COL);=0A=
-    }=0A=
-  note_width (dc, "keep", NEW_COL_SIZE_SLOP, NEW_COL);=0A=
-  note_width (dc, "uninstall", NEW_COL_SIZE_SLOP, NEW_COL);=0A=
-=0A=
-  headers[CURRENT_COL].x =3D HMARGIN/2;=0A=
-  headers[NEW_COL].x =3D headers[CURRENT_COL].x + =
headers[CURRENT_COL].width + NEW_COL_SIZE_SLOP + HMARGIN;=0A=
-  headers[SRC_COL].x =3D headers[NEW_COL].x + headers[NEW_COL].width + =
HMARGIN;=0A=
-  headers[PACKAGE_COL].x =3D headers[SRC_COL].x + =
headers[SRC_COL].width + HMARGIN;=0A=
+  chooser =3D new (view) (VIEW_PACKAGE, dc);=0A=
 =0A=
   default_trust (lv, TRUST_CURR);=0A=
-  set_full_list (lv, full_list);=0A=
+  set_view_mode (lv, VIEW_PACKAGE);=0A=
+  if (!SetDlgItemText (dlg, IDC_CHOOSE_VIEWCAPTION, =
chooser->mode_caption()))=0A=
+    log (LOG_BABBLE, "Failed to set View button caption %d", =
GetLastError() );=0A=
+  for (Package *foo =3D package; foo->name; foo++)=0A=
+    add_required(foo);=0A=
   static int ta[] =3D { IDC_CHOOSE_CURR, 0 };=0A=
   rbset (dlg, ta, IDC_CHOOSE_CURR);=0A=
 =0A=
@@ -600,18 +1071,26 @@ dialog_cmd (HWND h, int id, HWND hwndctl=0A=
     {=0A=
     case IDC_CHOOSE_PREV:=0A=
       default_trust (lv, TRUST_PREV);=0A=
-      set_full_list (lv, full_list);=0A=
+      for (Package *foo =3D package; foo->name; foo++)=0A=
+        add_required(foo);=0A=
+      set_view_mode (lv, chooser->get_view_mode ());=0A=
       break;=0A=
     case IDC_CHOOSE_CURR:=0A=
       default_trust (lv, TRUST_CURR);=0A=
-      set_full_list (lv, full_list);=0A=
+      for (Package *foo =3D package; foo->name; foo++)=0A=
+        add_required(foo);=0A=
+      set_view_mode (lv, chooser->get_view_mode ());=0A=
       break;=0A=
     case IDC_CHOOSE_EXP:=0A=
       default_trust (lv, TRUST_TEST);=0A=
-      set_full_list (lv, full_list);=0A=
+      for (Package *foo =3D package; foo->name; foo++)=0A=
+        add_required(foo);=0A=
+      set_view_mode (lv, chooser->get_view_mode ());=0A=
       break;=0A=
-    case IDC_CHOOSE_FULLPART:=0A=
-      set_full_list (lv, !full_list);=0A=
+    case IDC_CHOOSE_VIEW:=0A=
+      set_view_mode (lv, viewsplusplus (chooser->get_view_mode ()));=0A=
+      if (!SetDlgItemText (h, IDC_CHOOSE_VIEWCAPTION, =
chooser->mode_caption()))=0A=
+	log (LOG_BABBLE, "Failed to set View button caption %d", =
GetLastError() );=0A=
       break;=0A=
 =0A=
     case IDOK:=0A=
@@ -789,6 +1268,28 @@ getpkgbyname (const char *pkgname)=0A=
   return NULL;=0A=
 }=0A=
 =0A=
+/* Return a pointer to a category given the name. */=0A=
+Category *=0A=
+getcategorybyname (const char *categoryname)=0A=
+{=0A=
+  for (Category *cat =3D category; cat; cat=3Dcat->next)=0A=
+    if (strcasecmp (cat->name, categoryname) =3D=3D 0)=0A=
+      return cat;=0A=
+=0A=
+  return NULL;=0A=
+}=0A=
+=0A=
+/* Return a pointer to a category of a given package given the name. */=0A=
+Category *=0A=
+getpackagecategorybyname (Package *pkg, const char *categoryname)=0A=
+{=0A=
+  for (Category *cat =3D pkg->category; cat; cat =3D cat->next)=0A=
+    if (strcasecmp (cat->name, categoryname) =3D=3D 0)=0A=
+      return cat;=0A=
+=0A=
+  return NULL;=0A=
+}=0A=
+=0A=
 static void=0A=
 scan2 (char *path, unsigned int size)=0A=
 {=0A=
@@ -921,7 +1422,7 @@ package_sort (const void *va, const void=0A=
 {=0A=
   Package *a =3D (Package *)va;=0A=
   Package *b =3D (Package *)vb;=0A=
-  return strcmp (a->name, b->name);=0A=
+  return strcasecmp (a->name, b->name);=0A=
 }=0A=
 =0A=
 void=0A=
@@ -944,6 +1445,7 @@ do_choose (HINSTANCE h)=0A=
 =0A=
   read_installed_db ();=0A=
   set_existence ();=0A=
+  fill_missing_category ();=0A=
 =0A=
   qsort (package, npackages, sizeof (package[0]), package_sort);=0A=
 =0A=
@@ -967,9 +1469,10 @@ do_choose (HINSTANCE h)=0A=
 			       : "unknown");=0A=
       const char *excluded =3D (pkg->exclude ? "yes" : "no");=0A=
 =0A=
-      log (LOG_BABBLE, "[%s] action=3D%s trust=3D%s installed=3D%s =
excluded=3D%s src?=3D%s",=0A=
+      log (LOG_BABBLE, "[%s] action=3D%s trust=3D%s installed=3D%s =
excluded=3D%s src?=3D%s"=0A=
+	   "category=3D%s",=0A=
 	   pkg->name, action, trust, installed,=0A=
-	   excluded, pkg->srcpicked ? "yes" : "no");=0A=
+	   excluded, pkg->srcpicked ? "yes" : "no", pkg->category);=0A=
       for (int t =3D 1; t < NTRUST; t++)=0A=
 	{=0A=
 	  if (pkg->info[t].install)=0A=
Index: ini.h=0A=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
RCS file: /cvs/src/src/winsup/cinstall/ini.h,v=0A=
retrieving revision 2.12=0A=
diff -u -p -r2.12 ini.h=0A=
--- ini.h	2001/06/18 00:43:57	2.12=0A=
+++ ini.h	2001/06/23 14:12:51=0A=
@@ -13,6 +13,9 @@=0A=
  *=0A=
  */=0A=
 =0A=
+#ifndef _INI_H_=0A=
+#define _INI_H_=0A=
+=0A=
 /* When setup.ini is parsed, the information is stored according to=0A=
    the declarations here.  ini.cc (via inilex and iniparse)=0A=
    initializes these structures.  choose.cc sets the action and trust=0A=
@@ -62,6 +65,15 @@ typedef enum=0A=
   EXCLUDE_NOT_FOUND=0A=
 } excludes;=0A=
 =0A=
+typedef enum =0A=
+{=0A=
+  VIEW_UNKNOWN,=0A=
+  VIEW_PACKAGE_FULL,=0A=
+  VIEW_PACKAGE,=0A=
+  VIEW_CATEGORY,=0A=
+  NVIEW=0A=
+} views;=0A=
+=0A=
 #define is_download_action(pkg) \=0A=
   ((pkg)->action =3D=3D ACTION_PREV || \=0A=
    (pkg)->action =3D=3D ACTION_CURR || \=0A=
@@ -97,6 +109,19 @@ typedef struct _Info=0A=
 #endif=0A=
 } Info;			/* +1 for TRUST_UNKNOWN */=0A=
 =0A=
+typedef struct _CategoryPackage=0A=
+{=0A=
+  struct _CategoryPackage *next;  /* The next package pointer in the =
list */=0A=
+  char *pkg;			  /* This should be Package *, but the packages can =
move*/=0A=
+} CategoryPackage;=0A=
+=0A=
+typedef struct _Category=0A=
+{=0A=
+  struct _Category *next; /* the next category in the list */=0A=
+  char *name;		  /* the category */=0A=
+  CategoryPackage *packages; /* the packages in this category */=0A=
+} Category;=0A=
+=0A=
 typedef struct _Dependency=0A=
 {=0A=
   struct _Dependency *next; /* the next package in this dependency list =
*/=0A=
@@ -108,7 +133,7 @@ typedef struct=0A=
   char *name;		/* package name, like "cygwin" */=0A=
   char *sdesc;		/* short description (replaces "name" if provided) */=0A=
   char *ldesc;		/* long description (multi-line) */=0A=
-  char *category; /* the category the package belongs to, like =
"required" or "XFree86" */=0A=
+  Category *category;   /* the categories the package belongs to */ =0A=
   Dependency *required; /* the packages required for this package to =
work */=0A=
   actions action;	/* A range of states applicable to this package */=0A=
   trusts trust;		/* Selects among info[] below, a subset of action */=0A=
@@ -129,6 +154,8 @@ typedef struct=0A=
 =0A=
 extern Package *package;=0A=
 extern int npackages;=0A=
+extern Category *category;=0A=
+extern int ncategories;=0A=
 =0A=
 #ifdef __cplusplus=0A=
 extern "C" {=0A=
@@ -138,7 +165,13 @@ Package *new_package (char *name);=0A=
 void	ini_init (char *string);=0A=
 Package *getpkgbyname (const char *pkgname);=0A=
 void    new_requirement (Package *package, char *dependson);=0A=
+Category *getcategorybyname (const char *categoryname);=0A=
+Category *getpackagecategorybyname (Package *pkg, const char =
*categoryname); =0A=
+Category *register_category (char *name);=0A=
+void    add_category (Package *package, Category *cat);=0A=
 =0A=
 #ifdef __cplusplus=0A=
 }=0A=
 #endif=0A=
+=0A=
+#endif /* _INI_H_ */=0A=
Index: iniparse.y=0A=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
RCS file: /cvs/src/src/winsup/cinstall/iniparse.y,v=0A=
retrieving revision 2.9=0A=
diff -u -p -r2.9 iniparse.y=0A=
--- iniparse.y	2001/06/15 04:05:31	2.9=0A=
+++ iniparse.y	2001/06/23 14:12:51=0A=
@@ -86,7 +86,8 @@ simple_line=0A=
  : VERSION STRING		{ cpt->version =3D $2; }=0A=
  | SDESC STRING			{ cp->sdesc =3D $2; }=0A=
  | LDESC STRING			{ cp->ldesc =3D $2; }=0A=
- | CATEGORY STRING		{ cp->category =3D $2; }=0A=
+ | CATEGORY STRING		{ add_category (cp, register_category ($2));=0A=
+                                }=0A=
  | REQUIRES requires=0A=
  | INSTALL STRING STRING	{ cpt->install =3D $2;=0A=
 				  cpt->install_size =3D atoi($3);=0A=
@@ -121,11 +122,13 @@ requires=0A=
 Package *package =3D NULL;=0A=
 int npackages =3D 0;=0A=
 static int maxpackages =3D 0;=0A=
+Category *category =3D NULL;=0A=
+int ncategories =3D 0;=0A=
 =0A=
 Package *=0A=
 new_package (char *name)=0A=
 {=0A=
-  if (package =3D=3D 0)=0A=
+  if (package =3D=3D NULL)=0A=
     maxpackages =3D npackages =3D 0;=0A=
   if (npackages >=3D maxpackages)=0A=
     {=0A=
@@ -149,7 +152,7 @@ new_package (char *name)=0A=
 }=0A=
 =0A=
 void=0A=
-new_requirement(Package *package, char *dependson)=0A=
+new_requirement (Package *package, char *dependson)=0A=
 {=0A=
   Dependency *dp;=0A=
   if (!dependson)=0A=
@@ -158,4 +161,58 @@ new_requirement(Package *package, char *=0A=
   dp->next =3D cp->required;=0A=
   dp->package =3D dependson;=0A=
   cp->required =3D dp;=0A=
+}=0A=
+=0A=
+Category *=0A=
+register_category (char *name)=0A=
+{=0A=
+  Category *tempcat;=0A=
+  if (category =3D=3D NULL)=0A=
+    ncategories =3D 0;=0A=
+  tempcat =3D getcategorybyname (name);=0A=
+  if (!tempcat)=0A=
+    {=0A=
+      Category *sortcat =3D category;=0A=
+      tempcat =3D new (Category);=0A=
+      memset (tempcat, '\0', sizeof (Category));=0A=
+      tempcat->name =3D strdup (name);=0A=
+      if (!sortcat || strcasecmp(sortcat->name, name) > 0)=0A=
+	{=0A=
+	  tempcat->next =3D category;=0A=
+	  category =3D tempcat;=0A=
+	}=0A=
+      else=0A=
+	{=0A=
+	  while (sortcat->next && =0A=
+		 strcasecmp(sortcat->next->name, tempcat->name) < 0)=0A=
+	    {=0A=
+	      tempcat->next =3D sortcat->next;=0A=
+	      sortcat->next =3D tempcat;=0A=
+	    }=0A=
+	}=0A=
+      ncategories++;=0A=
+    }=0A=
+  return tempcat;=0A=
+}=0A=
+=0A=
+void=0A=
+add_category (Package *package, Category *cat)=0A=
+{=0A=
+  /* add a new record for the package list */=0A=
+  /* TODO: alpabetical inserts ? */=0A=
+  Category *tempcat;=0A=
+  CategoryPackage *templink;=0A=
+  tempcat =3D new (Category);=0A=
+  memset (tempcat, '\0', sizeof (Category));=0A=
+  tempcat->next =3D package->category;=0A=
+  tempcat->name =3D cat->name;=0A=
+  package->category =3D tempcat;=0A=
+=0A=
+  templink =3D new (CategoryPackage);=0A=
+  templink->next =3D cat->packages;=0A=
+  templink->pkg =3D package->name;=0A=
+  cat->packages =3D templink;=0A=
+ =0A=
+  /* hack to ensure we allocate enough space */=0A=
+  ncategories++; =0A=
 }=0A=
Index: res.rc=0A=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
RCS file: /cvs/src/src/winsup/cinstall/res.rc,v=0A=
retrieving revision 2.20=0A=
diff -u -p -r2.20 res.rc=0A=
--- res.rc	2001/05/28 08:31:02	2.20=0A=
+++ res.rc	2001/06/23 14:12:51=0A=
@@ -240,7 +240,8 @@ BEGIN=0A=
     CONTROL         "SPIN",IDC_STATIC,"Static",SS_BITMAP,55,170,15,13=0A=
     LTEXT           "=3D click to choose action, (p) =3D previous =
version, (x) =3D experimental",=0A=
                     IDC_STATIC,65,170,220,8=0A=
-    PUSHBUTTON      "Full/Part",IDC_CHOOSE_FULLPART,283,5,35,10=0A=
+    PUSHBUTTON      "View",IDC_CHOOSE_VIEW,278,5,20,10=0A=
+    LTEXT           "",   IDC_CHOOSE_VIEWCAPTION, 300,5,30,10=0A=
     CONTROL         "E&xp",IDC_CHOOSE_EXP,"Button",BS_AUTORADIOBUTTON | =0A=
                     WS_GROUP,248,5,25,10=0A=
     CONTROL         =
"&Curr",IDC_CHOOSE_CURR,"Button",BS_AUTORADIOBUTTON,222,=0A=
Index: resource.h=0A=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
RCS file: /cvs/src/src/winsup/cinstall/resource.h,v=0A=
retrieving revision 2.11=0A=
diff -u -p -r2.11 resource.h=0A=
--- resource.h	2001/05/28 08:31:02	2.11=0A=
+++ resource.h	2001/06/23 14:12:51=0A=
@@ -84,7 +84,7 @@=0A=
 #define IDC_NET_PASSWD                  1031=0A=
 #define IDC_VERSION                     1033=0A=
 #define IDC_LISTVIEW_POS                1034=0A=
-#define IDC_CHOOSE_FULLPART             1035=0A=
+#define IDC_CHOOSE_VIEW                 1035=0A=
 #define IDC_CHOOSE_EXP                  1036=0A=
 #define IDC_CHOOSE_CURR                 1037=0A=
 #define IDC_CHOOSE_PREV                 1038=0A=
@@ -100,6 +100,7 @@=0A=
 #define IDC_DLS_PPROGRESS_TEXT          1048=0A=
 #define IDC_DLS_IPROGRESS_TEXT          1049=0A=
 #define IDC_CHOOSE_INST_TEXT      1050=0A=
+#define IDC_CHOOSE_VIEWCAPTION          1051=0A=
 #define IDC_STATIC                      -1=0A=
 =0A=
 // Next default values for new objects=0A=
@@ -110,7 +111,7 @@=0A=
 #define _APS_3D_CONTROLS                     1=0A=
 #define _APS_NEXT_RESOURCE_VALUE        127=0A=
 #define _APS_NEXT_COMMAND_VALUE         40003=0A=
-#define _APS_NEXT_CONTROL_VALUE         1051=0A=
+#define _APS_NEXT_CONTROL_VALUE         1052=0A=
 #define _APS_NEXT_SYMED_VALUE           101=0A=
 #endif=0A=
 #endif=0A=

------=_NextPart_000_0549_01C0FC43.305F8A70--

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019