? category.patch
? depends.patch
Index: choose.cc
===================================================================
RCS file: /cvs/src/src/winsup/cinstall/choose.cc,v
retrieving revision 2.23
diff -u -p -r2.23 choose.cc
--- choose.cc	2001/05/27 19:43:52	2.23
+++ choose.cc	2001/06/13 06:31:13
@@ -87,14 +87,19 @@ 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(int p);
+static void set_full_list (HWND h, int isfull);
+
 struct ExtraPackageInfo
   {
     char *installed_file;	/* filename of previous "install" file */
@@ -188,6 +193,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].name)
 	TextOut (hdc, x + headers[PACKAGE_COL].x, r, package[i].name, strlen (package[i].name));
     }
@@ -278,6 +286,7 @@ static LRESULT CALLBACK
 list_click (HWND hwnd, BOOL dblclk, int x, int y, UINT hitCode)
 {
   int r;
+  int refresh;
 
   if (nindexes == 0)
     return 0;
@@ -305,6 +314,8 @@ list_click (HWND hwnd, BOOL dblclk, int 
 	extra[p].pick++;
       if (extra[p].chooser[extra[p].pick].caption == 0)
 	extra[p].pick = 0;
+      /* Add any packages that are needed by this package */
+      refresh = add_required(p);
     }
 
   if (x >= headers[SRC_COL].x - HMARGIN/2 && x <= headers[SRC_COL + 1].x - HMARGIN/2)
@@ -312,13 +323,34 @@ list_click (HWND hwnd, BOOL dblclk, int 
       if (extra[p].chooser[extra[p].pick].src_avail)
 	package[p].srcaction ^= (SRCACTION_NO^SRCACTION_YES);
     }
+
+  if (refresh)
+    { 
+      RECT r;
+      GetClientRect (lv, &r);
+      SCROLLINFO si;
+      memset (&si, 0, sizeof (si));
+      si.cbSize = sizeof (si);
+      si.fMask = SIF_ALL;
+      si.nMin = 0;
+
+      si.nMax = nindexes * row_height;
+      si.nPage = r.bottom - header_height;
+      SetScrollInfo (lv, SB_VERT, &si, TRUE);
+
+      scroll_ulc_x = scroll_ulc_y = 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);
+      InvalidateRect (lv, &r, TRUE);
+    }
+  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
@@ -432,7 +464,7 @@ set_existence ()
 }
 
 static int
-best_trust (int p, int trust)
+best_trust (int p, int trust, int ignore_categories)
 {
   int t;
   t = trust;
@@ -440,12 +472,97 @@ best_trust (int p, int trust)
       ((package[p].info[t].install_exists && source == IDC_SOURCE_CWD) ||
        (package[p].info[t].install_exists == 0 &&
 	source == IDC_SOURCE_DOWNLOAD) || source == IDC_SOURCE_NETINST))
-    return t;
+    {
+      if (!ignore_categories && package[p].category 
+	&& strcasecmp(package[p].category, "Required"))
+        return TRUST_NONE;
+      else
+	return t;
+    }
   if (extra[p].installed_file && extra[p].installed_ver == package[p].info[t].version)
     return TRUST_KEEP;
   return TRUST_NONE;
 }
 
+static int
+find_package (const char *name)
+{
+  int i;
+  for (i=0; i < npackages; i++)
+    {
+      if (!strcasecmp(name, package[i].name))
+	return i;
+    }
+  return -1;
+}
+
+static int 
+add_required (int p)
+{
+  Dependency *dp;
+  int i;
+  int c;
+  int changed = 0;
+  dp = package[p].required;
+  switch (extra[p].chooser[extra[p].pick].trust)
+    {
+    case TRUST_UNINSTALL:
+    case TRUST_NONE:
+    case TRUST_SRC_ONLY:
+      return 0;
+    default:
+      break;
+    }
+  while (dp)
+    {
+      if ((i = find_package(dp->package)) == -1)
+	{
+	  dp=dp->next;
+	  continue;
+	}
+      switch (extra[i].chooser[extra[i].pick].trust)
+        {
+        case TRUST_PREV:
+        case TRUST_CURR:
+        case TRUST_TEST:
+        case TRUST_REDO:
+	case TRUST_KEEP:
+          break;
+
+        case TRUST_UNINSTALL:
+	  package[i].trust = TRUST_KEEP;
+          break;
+
+	case TRUST_NONE:
+	  package_indexes[nindexes++] = i;
+        case TRUST_SRC_ONLY:
+          if (! extra[i].which_is_installed >= 0)
+	    {
+	      /* prefer the current version, then prev, then experimental */
+              package[i].trust = best_trust (i, TRUST_CURR, 1);
+	      if (package[i].trust != TRUST_CURR)
+	        {
+	          package[i].trust = best_trust (i, TRUST_PREV, 1);
+		  if (package[i].trust != TRUST_PREV)
+		    package[i].trust = best_trust (i, TRUST_TEST, 1);
+	        }
+	    }
+	  else
+ 	    package[i].trust = TRUST_KEEP;
+	  changed++;
+          break;
+
+	default:
+	  break;
+	}
+      for (c = 0; c < extra[i].npick; c++)
+	if (package[i].trust == extra[i].chooser[c].trust)
+	  extra[i].pick = c;
+      dp=dp->next;
+    }
+  return changed;
+}
+
 static void
 default_trust (HWND h, int trust)
 {
@@ -453,7 +570,7 @@ default_trust (HWND h, int trust)
 
   for (i = 0; i < npackages; i++)
     {
-      t = best_trust (i, trust);
+      t = best_trust (i, trust, 0);
       extra[i].pick = 1;
       package[i].trust = t;
       for (c = 0; c < extra[i].npick; c++)
@@ -640,6 +757,7 @@ create_listview (HWND dlg, RECT *r)
       for (t = 0; t < NTRUST; t++)
 	note_width (dc, package[i].info[t].version, NEW_COL_SIZE_SLOP, NEW_COL);
       note_width (dc, package[i].name, 0, PACKAGE_COL);
+      note_width (dc, package[i].category, 0, CATEGORY_COL);
       note_width (dc, package[i].sdesc, 0, PACKAGE_COL);
     }
   note_width (dc, "keep", NEW_COL_SIZE_SLOP, NEW_COL);
@@ -648,10 +766,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 (i = 0; i < npackages; i++)
+    add_required(i);
   static int ta[] = { IDC_CHOOSE_CURR, 0 };
   rbset (dlg, ta, IDC_CHOOSE_CURR);
 
@@ -661,18 +782,25 @@ create_listview (HWND dlg, RECT *r)
 static BOOL
 dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
 {
+  int i;
   switch (id)
     {
     case IDC_CHOOSE_PREV:
       default_trust (lv, TRUST_PREV);
+      for (i = 0; i < npackages; i++)
+        add_required(i);
       set_full_list (lv, full_list);
       break;
     case IDC_CHOOSE_CURR:
       default_trust (lv, TRUST_CURR);
+      for (i = 0; i < npackages; i++)
+        add_required(i);
       set_full_list (lv, full_list);
       break;
     case IDC_CHOOSE_EXP:
       default_trust (lv, TRUST_TEST);
+      for (i = 0; i < npackages; i++)
+        add_required(i);
       set_full_list (lv, full_list);
       break;
     case IDC_CHOOSE_FULLPART:
@@ -1096,9 +1224,11 @@ do_choose (HINSTANCE h)
 			       : "unknown");
       const char *partial_list = ((extra[i].in_partial_list == 1) ? "yes" : "no");
 
-      log (LOG_BABBLE, "[%s] action=%s trust=%s installed=%s partial_list=%s src?=%s",
+      log (LOG_BABBLE, "[%s] action=%s trust=%s installed=%s partial_list=%s src?=%s"
+	   " category=%s",
 	   package[i].name, action, trust, installed,
-	   partial_list, package[i].srcaction == SRCACTION_NO ? "no" : "yes");
+	   partial_list, package[i].srcaction == SRCACTION_NO ? "no" : "yes", 
+	   package[i].category);
       for (int t = 0; t < NTRUST; t++)
 	{
 	  if (package[i].info[t].install)
Index: ini.h
===================================================================
RCS file: /cvs/src/src/winsup/cinstall/ini.h,v
retrieving revision 2.7
diff -u -p -r2.7 ini.h
--- ini.h	2001/05/27 07:05:09	2.7
+++ ini.h	2001/06/13 06:31:13
@@ -52,14 +52,23 @@ typedef struct
   int partial_list_display;/* display this version in partial list */
 } 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" */
   int action;	/* ACTION_* - only NEW and UPGRADE get installed */
   int srcaction;/* SRCACTION_ */
   int trust;	/* TRUST_* (selects among info[] below) */
+  Dependency *required; /* the packages required for this package to work */
 
   Info info[NTRUST + 1]; /* +1 for TRUST_UNKNOWN */
 } Package;
@@ -73,6 +82,7 @@ extern "C" {
 
 Package *new_package (char *name);
 void	ini_init (char *string);
+void    new_requirement(Package *package, char *dependson);
 
 #define pi (package[i].info[package[i].trust])
 
Index: inilex.l
===================================================================
RCS file: /cvs/src/src/winsup/cinstall/inilex.l,v
retrieving revision 2.2
diff -u -p -r2.2 inilex.l
--- inilex.l	2001/05/30 01:38:41	2.2
+++ inilex.l	2001/06/13 06:31:13
@@ -47,6 +47,8 @@ STR	[a-zA-Z0-9_./+-]+
 "setup-timestamp:"	return SETUP_TIMESTAMP;
 "setup-version:"	return SETUP_VERSION;
 "version:"		return VERSION;
+"category:"		return CATEGORY;
+"requires:"		return REQUIRES;
 "install:"		return INSTALL;
 "source:"		return SOURCE;
 "sdesc:"		return SDESC;
Index: iniparse.y
===================================================================
RCS file: /cvs/src/src/winsup/cinstall/iniparse.y,v
retrieving revision 2.6
diff -u -p -r2.6 iniparse.y
--- iniparse.y	2001/05/27 19:43:52	2.6
+++ iniparse.y	2001/06/13 06:31:13
@@ -43,7 +43,7 @@ extern int yylineno;
 %}
 
 %token STRING
-%token SETUP_TIMESTAMP SETUP_VERSION VERSION INSTALL SOURCE SDESC LDESC
+%token SETUP_TIMESTAMP SETUP_VERSION VERSION INSTALL SOURCE SDESC LDESC CATEGORY REQUIRES
 %token T_PREV T_CURR T_TEST T_UNKNOWN
 
 %%
@@ -81,6 +81,7 @@ lines
 
 simple_line
  : VERSION STRING		{ cpt->version = $2; }
+ | CATEGORY STRING		{ cp->category = $2; }
  | SDESC STRING			{ cp->sdesc = $2; }
  | LDESC STRING			{ cp->ldesc = $2; }
  | INSTALL STRING STRING	{ cpt->install = $2;
@@ -98,6 +99,7 @@ simple_line
  | T_CURR			{ trust = TRUST_CURR; }
  | T_TEST			{ trust = TRUST_TEST; }
  | T_UNKNOWN			{ trust = TRUST_UNKNOWN; }
+ | REQUIRES requires
  | /* empty */
  | error '\n' { yylineno --;
 		yyerror ("unrecognized line in package %s (do you have the latest setup?)", cp->name);
@@ -105,6 +107,10 @@ simple_line
 	      }
  ;
 
+requires
+ : STRING { new_requirement(cp, $1); } requires
+ | STRING { new_requirement(cp, $1); }
+ ;
 %%
 
 Package *package = 0;
@@ -133,4 +139,16 @@ new_package (char *name)
   trust = TRUST_CURR;
 
   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;
 }
