? category.patch
? depends2.patch
? depends4.patch
? depends5.patch
? depends6.patch
Index: choose.cc
===================================================================
RCS file: /cvs/src/src/winsup/cinstall/choose.cc,v
retrieving revision 2.25
diff -u -p -r2.25 choose.cc
--- choose.cc	2001/06/14 03:38:45	2.25
+++ choose.cc	2001/06/14 05:47:20
@@ -81,14 +81,20 @@ headers[] = {
 #define NEW_COL 1
   { "Src?", 4, 0, 0 },
 #define SRC_COL 2
+  { "Category", 8, 0, 0 },
+#define CATEGORY_COL 3
   { "Package", 7, 0, 0 },
-#define PACKAGE_COL 3
+#define PACKAGE_COL 4
   { 0, 0, 0, 0 }
 };
 #define NUM_COLUMNS (sizeof (headers) / (sizeof (headers[0])) - 1)
 
 int *package_indexes, nindexes;
 
+static int add_required(Package *pkg);
+static void set_full_list (HWND h, int isfull);
+
+
 static bool
 isinstalled (Package *pkg, int trust)
 {
@@ -159,6 +165,87 @@ set_action (Package *pkg, bool preinc)
       }
 }
 
+static int
+add_required (Package *pkg)
+{
+  Dependency *dp;
+  Package *required;
+  int c;
+  int changed = 0;
+  dp = pkg->required;
+  switch (pkg->action)
+    {
+    case ACTION_UNINSTALL:
+    case ACTION_ERROR:
+    case ACTION_UNKNOWN:
+    case ACTION_SRC_ONLY:
+    case ACTION_SKIP:
+      return 0;
+    default:
+      break;
+    }
+  while (dp)
+    {
+      if ((required = getpkgbyname(dp->package)) == NULL)
+        {
+          dp=dp->next;
+          continue;
+        }
+      switch (required->action)
+        {
+	case ACTION_PREV:
+	case ACTION_CURR:
+	case ACTION_TEST:
+	case ACTION_LAST:
+	case ACTION_SAME_CURR:
+	case ACTION_SAME_TEST:
+	case ACTION_SAME_PREV:
+	case ACTION_REDO:
+	case ACTION_SAME_LAST:
+	  /* we are installing a user selected version */
+	  break;
+	
+	case ACTION_UNINSTALL:
+	  /* it's already installed - leave it */
+	  required->action = ACTION_SKIP;
+	  break;
+	case ACTION_ERROR:
+	case ACTION_UNKNOWN:
+	case ACTION_SRC_ONLY:
+	case ACTION_SKIP:
+	  /* the current install will fail */
+	  required->action = ACTION_PREV; /* this find prev, then curr, then test. */
+	  set_action(required, 0);	  /* we need a find_best that gets installed, */
+	  changed++;			  /* then current, then prev, then test */
+	  /* we should insert the package in alphabetical order */
+	  if (package_indexes) 
+	    {
+	      int n=0;
+	      while (n < nindexes)
+	        {
+		  if (package_indexes[n] > required-package)
+		    {
+		      memmove (&package_indexes[n + 1], &package_indexes[n], (nindexes - n) * sizeof (package_indexes[n]));
+		      package_indexes[n] = required - package;
+		      nindexes++;
+		      n=nindexes;	
+		    }
+		  else if (package_indexes[n] == required-package)
+		    n=nindexes;
+		  n++;
+		}
+	    }
+//	  package_indexes[nindexes++] = required - package;
+	  break;
+	default:
+	  log (0, "should never get here %d\n", required->action);
+	}
+      changed += add_required (required);
+      dp=dp->next;
+    }
+  return changed;
+}
+
 /* Return an appropriate caption given the current action. */
 const char *
 choose_caption (Package *pkg)
@@ -252,6 +339,9 @@ paint (HWND hwnd)
       BitBlt (hdc, x + headers[SRC_COL].x, by, 11, 11,
 	      bitmap_dc, 0, 0, SRCCOPY);
 
+      if (package[i].category)
+       TextOut (hdc, x + headers[CATEGORY_COL].x, r, package[i].category, strlen (package[i].category));
+
       if (package[i].sdesc)
 	s = package[i].sdesc;
       else
@@ -344,7 +434,7 @@ list_hscroll (HWND hwnd, HWND hctl, UINT
 static LRESULT CALLBACK
 list_click (HWND hwnd, BOOL dblclk, int x, int y, UINT hitCode)
 {
-  int r;
+  int r,refresh;
 
   if (nindexes == 0)
     return 0;
@@ -364,15 +454,38 @@ list_click (HWND hwnd, BOOL dblclk, int 
   if (x >= headers[NEW_COL].x - (HMARGIN / 2) && x <= headers[NEW_COL + 1].x - HMARGIN/2)
     set_action (pkg, 1);
 
+  /* Add any packages that are needed by this package */
+  refresh = add_required(pkg);
+
   if (x >= headers[SRC_COL].x - HMARGIN/2 && x <= headers[SRC_COL + 1].x - HMARGIN/2)
     pkg->srcpicked ^= 1;
+
+  if (refresh)
+    {
+      RECT r;
+      GetClientRect (lv, &r);
+      SCROLLINFO si;
+      memset (&si, 0, sizeof (si));
+      si.cbSize = sizeof (si);
+      si.fMask = SIF_RANGE;
+      si.nMin = 0;
 
-  RECT rect;
-  rect.left = headers[NEW_COL].x - scroll_ulc_x;
-  rect.right = headers[SRC_COL + 1].x - scroll_ulc_x;
-  rect.top = header_height + r * row_height - scroll_ulc_y;
-  rect.bottom = rect.top + row_height;
-  InvalidateRect (hwnd, &rect, TRUE);
+      si.nMax = nindexes * row_height;
+      SetScrollInfo (lv, SB_VERT, &si, FALSE);
+
+      InvalidateRect (lv, &r, TRUE);
+
+//      scroll_ulc_x = scroll_ulc_y = 0;
+    }
+  else
+    {
+      RECT rect;
+      rect.left = headers[NEW_COL].x - scroll_ulc_x;
+      rect.right = headers[SRC_COL + 1].x - scroll_ulc_x;
+      rect.top = header_height + r * row_height - scroll_ulc_y;
+      rect.bottom = rect.top + row_height;
+      InvalidateRect (hwnd, &rect, TRUE);
+    }
 }
 
 static LRESULT CALLBACK
@@ -476,6 +589,8 @@ default_trust (HWND h, trusts trust)
   for (Package *pkg = package; pkg->name; pkg++)
     {
       pkg->action = (actions) trust;
+      if (pkg->category && strcasecmp(pkg->category, "Required"))
+	pkg->action = ACTION_SKIP;
       set_action (pkg, 0);
     }
   RECT r;
@@ -569,6 +684,7 @@ create_listview (HWND dlg, RECT *r)
 	}
       for (t = 1; t < NTRUST; t++)
 	note_width (dc, pkg->info[t].version, NEW_COL_SIZE_SLOP, NEW_COL);
+      note_width (dc, pkg->category, 0, CATEGORY_COL);
       note_width (dc, pkg->name, 0, PACKAGE_COL);
       note_width (dc, pkg->sdesc, 0, PACKAGE_COL);
     }
@@ -578,10 +694,13 @@ create_listview (HWND dlg, RECT *r)
   headers[CURRENT_COL].x = HMARGIN/2;
   headers[NEW_COL].x = headers[CURRENT_COL].x + headers[CURRENT_COL].width + NEW_COL_SIZE_SLOP + HMARGIN;
   headers[SRC_COL].x = headers[NEW_COL].x + headers[NEW_COL].width + HMARGIN;
-  headers[PACKAGE_COL].x = headers[SRC_COL].x + headers[SRC_COL].width + HMARGIN;
+  headers[CATEGORY_COL].x = headers[SRC_COL].x + headers[SRC_COL].width + HMARGIN;
+  headers[PACKAGE_COL].x = headers[CATEGORY_COL].x + headers[CATEGORY_COL].width + HMARGIN;
 
   default_trust (lv, TRUST_CURR);
   set_full_list (lv, full_list);
+  for (Package *foo = package; foo->name; foo++)
+    add_required(foo);
   static int ta[] = { IDC_CHOOSE_CURR, 0 };
   rbset (dlg, ta, IDC_CHOOSE_CURR);
 
@@ -595,14 +714,20 @@ dialog_cmd (HWND h, int id, HWND hwndctl
     {
     case IDC_CHOOSE_PREV:
       default_trust (lv, TRUST_PREV);
+      for (Package *foo = package; foo->name; foo++)
+        add_required(foo);
       set_full_list (lv, full_list);
       break;
     case IDC_CHOOSE_CURR:
       default_trust (lv, TRUST_CURR);
+      for (Package *foo = package; foo->name; foo++)
+        add_required(foo);
       set_full_list (lv, full_list);
       break;
     case IDC_CHOOSE_EXP:
       default_trust (lv, TRUST_TEST);
+      for (Package *foo = package; foo->name; foo++)
+        add_required(foo);
       set_full_list (lv, full_list);
       break;
     case IDC_CHOOSE_FULLPART:
@@ -777,9 +902,13 @@ parse_filename (const char *in_fn, filep
 Package *
 getpkgbyname (const char *pkgname)
 {
-  for (int i = 0; i < npackages; i++)
-    if (strcasecmp (package[i].name, pkgname) == 0)
-      return package + i;
+
+  for (Package *pkg = package; pkg->name; pkg++)
+    if (strcasecmp (pkg->name, pkgname) == 0)
+      return pkg;
+//  for (int i = 0; i < npackages; i++)
+//    if (strcasecmp (package[i].name, pkgname) == 0)
+//      return package + i;
 
   return NULL;
 }
@@ -942,9 +1071,10 @@ do_choose (HINSTANCE h)
 			       : "unknown");
       const char *excluded = (pkg->exclude ? "yes" : "no");
 
-      log (LOG_BABBLE, "[%s] action=%s trust=%s installed=%s excluded=%s src?=%s",
+      log (LOG_BABBLE, "[%s] action=%s trust=%s installed=%s excluded=%s src?=%s"
+	   "category=%s",
 	   pkg->name, action, trust, installed,
-	   excluded, pkg->srcpicked ? "yes" : "no");
+	   excluded, pkg->srcpicked ? "yes" : "no", pkg->category);
       for (int t = 1; t < NTRUST; t++)
 	{
 	  if (pkg->info[t].install)
Index: ini.h
===================================================================
RCS file: /cvs/src/src/winsup/cinstall/ini.h,v
retrieving revision 2.8
diff -u -p -r2.8 ini.h
--- ini.h	2001/06/13 16:11:01	2.8
+++ ini.h	2001/06/14 05:47:20
@@ -90,11 +90,20 @@ typedef struct
   int source_exists;	/* source file exists on disk */
 } Info;			/* +1 for TRUST_UNKNOWN */
 
+typedef struct Dependency_t Dependency;
+struct Dependency_t
+{
+  Dependency *next; /* the next package in this dependency list */
+  char *package;    /* the name of the package that is depended on */
+};                  /* Dependencies can be used for recommended/required/related... */
+
 typedef struct
 {
   char *name;		/* package name, like "cygwin" */
   char *sdesc;		/* short description (replaces "name" if provided) */
   char *ldesc;		/* long description (multi-line) */
+  char *category; /* the category the package belongs to, like "required" or "XFree86" */
+  Dependency *required; /* the packages required for this package to work */
   actions action;	/* ACTION_* - only NEW and UPGRADE get installed */
   trusts trust;		/* TRUST_* (selects among info[] below) */
   int srcpicked;	/* SRCACTION_ */
@@ -116,6 +125,7 @@ extern "C" {
 Package *new_package (char *name);
 void	ini_init (char *string);
 Package *getpkgbyname (const char *pkgname);
+void    new_requirement(Package *package, char *dependson);
 
 #ifdef __cplusplus
 }
Index: inilex.l
===================================================================
RCS file: /cvs/src/src/winsup/cinstall/inilex.l,v
retrieving revision 2.3
diff -u -p -r2.3 inilex.l
--- inilex.l	2001/06/13 16:11:01	2.3
+++ inilex.l	2001/06/14 05:47:20
@@ -52,6 +52,9 @@ STR	[a-zA-Z0-9_./+-]+
 "sdesc:"		return SDESC;
 "ldesc:"		return LDESC;
 
+"category:"		return CATEGORY;
+"requires:"		return REQUIRES;
+
 "apath:"		return APATH;
 "ppath:"		return PPATH;
 
Index: iniparse.y
===================================================================
RCS file: /cvs/src/src/winsup/cinstall/iniparse.y,v
retrieving revision 2.7
diff -u -p -r2.7 iniparse.y
--- iniparse.y	2001/06/13 16:11:01	2.7
+++ iniparse.y	2001/06/14 05:47:20
@@ -45,6 +45,7 @@ extern int yylineno;
 
 %token STRING
 %token SETUP_TIMESTAMP SETUP_VERSION VERSION INSTALL SOURCE SDESC LDESC
+%token CATEGORY REQUIRES
 %token APATH PPATH INCLUDE_SETUP EXCLUDE_PACKAGE DOWNLOAD_URL
 %token T_PREV T_CURR T_TEST T_UNKNOWN
 
@@ -85,6 +86,8 @@ simple_line
  : VERSION STRING		{ cpt->version = $2; }
  | SDESC STRING			{ cp->sdesc = $2; }
  | LDESC STRING			{ cp->ldesc = $2; }
+ | CATEGORY STRING		{ cp->category = $2; }
+ | REQUIRES requires
  | INSTALL STRING STRING	{ cpt->install = $2;
 				  cpt->install_size = atoi($3);
 				  if (!cpt->version)
@@ -108,6 +111,11 @@ simple_line
 	      }
  ;
 
+requires
+ : STRING			{ new_requirement(cp, $1); } requires
+ | STRING			{ new_requirement(cp, $1); }
+ ;
+
 %%
 
 Package *package = NULL;
@@ -138,4 +146,16 @@ new_package (char *name)
     }
 
   return cp;
+}
+
+void
+new_requirement(Package *package, char *dependson)
+{
+  Dependency *dp;
+  if (!dependson)
+    return;
+  dp = (Dependency *) malloc (sizeof (Dependency));
+  dp->next = cp->required;
+  dp->package = dependson;
+  cp->required = dp;
 }
