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