]>
cygwin.com Git - cygwin-apps/setup.git/blob - choose.cc
2 * Copyright (c) 2000, 2001 Red Hat, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * A copy of the GNU General Public License can be found at
12 * Written by DJ Delorie <dj@cygnus.com>
16 /* The purpose of this file is to let the user choose which packages
17 to install, and which versions of the package when more than one
18 version is provided. The "trust" level serves as an indication as
19 to which version should be the default choice. At the moment, all
20 we do is compare with previously installed packages to skip any
21 that are already installed (by setting the action to ACTION_SAME).
22 While the "trust" stuff is supported, it's not really implemented
23 yet. We always prefer the "current" option. In the future, this
24 file might have a user dialog added to let the user choose to not
25 install packages, or to install packages that aren't installed by
29 static const char *cvsid
=
47 #include "filemanip.h"
48 #include "io_stream.h"
51 #include "category_list.h"
53 #include "package_db.h"
54 #include "package_meta.h"
55 #include "package_version.h"
59 #define alloca __builtin_alloca
64 #define NEW_COL_SIZE_SLOP (ICON_MARGIN + 11)
68 static int initialized
= 0;
70 static int scroll_ulc_x
, scroll_ulc_y
;
72 static HWND lv
, nextbutton
, choose_inst_text
;
74 static int header_height
;
75 static HANDLE sysfont
;
76 static int row_height
;
77 static HANDLE bm_spin
, bm_rtarrow
, bm_checkyes
, bm_checkno
, bm_checkna
;
79 static view
*chooser
= NULL
;
80 static trusts deftrust
= TRUST_UNKNOWN
;
82 static struct _header pkg_headers
[] = {
86 {"Category", 8, 0, 0},
91 static struct _header cat_headers
[] = {
92 {"Category", 8, 0, 0},
100 static int add_required (packagemeta
& pkg
, size_t depth
=0);
101 static void set_view_mode (HWND h
, views mode
);
103 #define pkgtrustp(pkg,t) (packageversion *)(t==TRUST_PREV ? pkg->prev : t == TRUST_CURR ? pkg->curr : pkg->exp)
105 /* Set the next action given a current action. */
107 set_action (packagemeta
* pkg
)
109 /* actions are the following:
111 for install modes (from net/local)
114 install the source for this version
115 and a boolean flag - force install to allow reinstallation, or bypassing requirements
117 install the source for the current version.
119 to uninstall a package, the desired version is set to NULL;
121 for mirroring modes (download only)
123 download this version
124 download source for this version
126 these are represented by the following:
127 the desired pointer in the packagemetadata indicated which version we are operating on.
128 if we are operating on the installed version, reinstall is a valid option.
129 for the selected version, forceinstall means Do an install no matter what, and
130 srcpicked means download the source.
132 The default action for any installed package is to install the 'curr version'
133 if it is not already installed.
135 The default action for any non-installed package is to do nothing.
137 To achieve a no-op, set desired==installed, and if (installed) set forceinstall=0 and
140 Iteration through versions should follow the following rules:
141 selected radio button (prev/curr/test) (show as reinstall if that is the
142 current version) ->source only (only if the package is installed) ->oldest version....skip version of radio button...
143 newest version->uninstall->no-op->selected radio button.
145 If any state cannot be set (ie because (say) no prev entry exists for a package
146 simply progress to the next option.
150 /* We were set to uninstall the package */
151 if (!pkg
->desired
&& pkg
->installed
)
153 /* No-op - keep whatever we've got */
154 pkg
->desired
= pkg
->installed
;
157 pkg
->desired
->binpicked
= 0;
158 pkg
->desired
->srcpicked
= 0;
162 else if (pkg
->desired
== pkg
->installed
164 || !(pkg
->installed
->binpicked
|| pkg
->installed
->srcpicked
)))
165 /* Install the default trust version - this is a 'reinstall' for installed
170 pkg
->desired
= pkgtrustp (pkg
, deftrust
);
173 pkg
->desired
->binpicked
= 1;
177 /* are we currently on the radio button selection and installed */
178 if (pkg
->desired
== pkgtrustp (pkg
, deftrust
) && pkg
->installed
&&
179 (!pkg
->desired
|| pkg
->desired
->binpicked
))
181 /* FIXME: is source available */
182 /* source only this file */
183 pkg
->desired
= pkg
->installed
;
184 pkg
->desired
->binpicked
= 0;
185 pkg
->desired
->srcpicked
= 1;
188 /* are we currently on source only or on the radio button but not installed */
189 else if ((pkg
->desired
== pkg
->installed
&& pkg
->installed
190 && pkg
->installed
->srcpicked
) ||
191 pkg
->desired
== pkgtrustp (pkg
, deftrust
))
193 /* move onto the loop through versions */
194 pkg
->desired
= pkg
->versions
.getnth (1);
195 if (pkg
->desired
== pkgtrustp (pkg
, deftrust
))
197 pkg
->versions
.number () > 1 ? pkg
->versions
.getnth (2) : NULL
;
200 pkg
->desired
->binpicked
= 1;
201 pkg
->desired
->srcpicked
= 0;
207 /* preserve the src tick box */
208 int source
= pkg
->desired
->srcpicked
;
209 /* bump the version selected, skipping the radio button trust along the way */
212 n
<= pkg
->versions
.number ()
213 && pkg
->desired
!= pkg
->versions
.getnth (n
); n
++);
214 /* n points at pkg->desired */
216 if (n
<= pkg
->versions
.number ())
218 if (pkgtrustp (pkg
, deftrust
) == pkg
->versions
.getnth (n
))
220 if (n
<= pkg
->versions
.number ())
222 pkg
->desired
= pkg
->versions
.getnth (n
);
223 pkg
->desired
->srcpicked
= source
;
227 /* went past the end - uninstall the package */
233 add_required (packagemeta
& pkg
, size_t depth
= 0)
236 packagemeta
*required
;
239 || (pkg
.desired
!= pkg
.installed
&& !pkg
.desired
->binpicked
))
240 /* uninstall || source only */
243 dp
= pkg
.desired
->required
;
245 /* cheap test for too much recursion */
246 if (depth
> db
.npackages ())
250 if ((required
= db
.getpackagebyname (dp
->package
)) == NULL
)
256 if (!required
->desired
)
258 /* it's set to uninstall */
259 set_action (required
);
261 else if (required
->desired
!= required
->installed
262 && !required
->desired
->binpicked
)
264 /* it's set to change to a different version source only */
265 required
->desired
->binpicked
= 1;
267 /* does this requirement have requirements? */
268 changed
+= add_required (*required
, depth
+ 1);
274 /* Return an appropriate caption given the current action. */
276 choose_caption (packagemeta
* pkg
)
278 if (!pkg
->desired
&& pkg
->installed
)
280 else if (!pkg
->desired
)
282 else if (pkg
->desired
== pkg
->installed
&& pkg
->desired
->binpicked
)
283 return source
== IDC_SOURCE_DOWNLOAD
? "Retrieve" : "Reinstall";
284 else if (pkg
->desired
== pkg
->installed
&& pkg
->desired
->srcpicked
)
285 /* FIXME: Redo source should come up if the tarball is already present locally */
287 else if (pkg
->desired
== pkg
->installed
) /* and neither src nor bin */
290 return pkg
->desired
->Canonical_version ();
300 hdc
= BeginPaint (hwnd
, &ps
);
302 SelectObject (hdc
, sysfont
);
303 SetBkColor (hdc
, GetSysColor (COLOR_WINDOW
));
304 SetTextColor (hdc
, GetSysColor (COLOR_WINDOWTEXT
));
307 GetClientRect (hwnd
, &cr
);
311 x
= cr
.left
- scroll_ulc_x
;
312 y
= cr
.top
- scroll_ulc_y
+ header_height
;
315 for (i
= 0; i
<= chooser
->last_col
; i
++)
317 TextOut (hdc
, x
+ chooser
->headers
[i
].x
, 3, chooser
->headers
[i
].text
,
318 chooser
->headers
[i
].slen
);
319 MoveToEx (hdc
, x
+ chooser
->headers
[i
].x
, header_height
- 3, &p
);
320 LineTo (hdc
, x
+ chooser
->headers
[i
].x
+ chooser
->headers
[i
].width
,
324 IntersectClipRect (hdc
, cr
.left
, cr
.top
+ header_height
, cr
.right
,
327 for (ii
= 0; ii
< chooser
->nlines
; ii
++)
328 chooser
->lines
[ii
].paint (hdc
, x
, y
, ii
,
329 (chooser
->get_view_mode () ==
330 VIEW_CATEGORY
) ? 0 : 1);
332 if (chooser
->nlines
== 0)
334 static const char *msg
= "Nothing to Install/Update";
335 if (source
== IDC_SOURCE_DOWNLOAD
)
336 msg
= "Nothing to Download";
337 TextOut (hdc
, HMARGIN
, header_height
, msg
, strlen (msg
));
340 EndPaint (hwnd
, &ps
);
344 scroll_common (HWND hwnd
, int which
, int *var
, int code
)
347 si
.cbSize
= sizeof (si
);
349 GetScrollInfo (hwnd
, which
, &si
);
354 si
.nPos
= si
.nTrackPos
;
356 case SB_THUMBPOSITION
:
365 si
.nPos
+= row_height
;
368 si
.nPos
-= row_height
;
371 si
.nPos
+= si
.nPage
* 9 / 10;
374 si
.nPos
-= si
.nPage
* 9 / 10;
378 if ((int) si
.nPos
< 0)
380 if (si
.nPos
+ si
.nPage
> (unsigned int) si
.nMax
)
381 si
.nPos
= si
.nMax
- si
.nPage
;
384 SetScrollInfo (hwnd
, which
, &si
, TRUE
);
386 int ox
= scroll_ulc_x
;
387 int oy
= scroll_ulc_y
;
391 GetClientRect (hwnd
, &cr
);
393 sr
.top
+= header_height
;
394 ScrollWindow (hwnd
, ox
- scroll_ulc_x
, oy
- scroll_ulc_y
, &sr
, &sr
);
397 ScrollWindow (hwnd
, ox
- scroll_ulc_x
, 0, &sr
, &sr
);
400 static LRESULT CALLBACK
401 list_vscroll (HWND hwnd
, HWND hctl
, UINT code
, int pos
)
403 scroll_common (hwnd
, SB_VERT
, &scroll_ulc_y
, code
);
407 static LRESULT CALLBACK
408 list_hscroll (HWND hwnd
, HWND hctl
, UINT code
, int pos
)
410 scroll_common (hwnd
, SB_HORZ
, &scroll_ulc_x
, code
);
414 static LRESULT CALLBACK
415 list_click (HWND hwnd
, BOOL dblclk
, int x
, int y
, UINT hitCode
)
419 if (chooser
->nlines
== 0)
422 if (y
< header_height
)
425 y
+= scroll_ulc_y
- header_height
;
427 row
= (y
+ ROW_MARGIN
/ 2) / row_height
;
429 if (row
< 0 || row
>= chooser
->nlines
)
432 refresh
= chooser
->click (row
, x
);
437 GetClientRect (lv
, &r
);
439 memset (&si
, 0, sizeof (si
));
440 si
.cbSize
= sizeof (si
);
441 si
.fMask
= SIF_ALL
; /* SIF_RANGE was giving strange behaviour */
444 si
.nMax
= chooser
->nlines
* row_height
;
445 si
.nPage
= r
.bottom
- header_height
;
447 /* if we are under the minimum display count ,
448 * set the offset to 0
450 if ((unsigned int) si
.nMax
<= si
.nPage
)
452 si
.nPos
= scroll_ulc_y
;
454 SetScrollInfo (lv
, SB_VERT
, &si
, TRUE
);
456 InvalidateRect (lv
, &r
, TRUE
);
462 rect
.left
= chooser
->headers
[chooser
->new_col
].x
- scroll_ulc_x
;
463 rect
.right
= chooser
->headers
[chooser
->src_col
+ 1].x
- scroll_ulc_x
;
464 rect
.top
= header_height
+ row
* row_height
- scroll_ulc_y
;
465 rect
.bottom
= rect
.top
+ row_height
;
466 InvalidateRect (hwnd
, &rect
, TRUE
);
471 static LRESULT CALLBACK
472 listview_proc (HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
477 return HANDLE_WM_HSCROLL (hwnd
, wParam
, lParam
, list_hscroll
);
479 return HANDLE_WM_VSCROLL (hwnd
, wParam
, lParam
, list_vscroll
);
481 return HANDLE_WM_LBUTTONDOWN (hwnd
, wParam
, lParam
, list_click
);
486 return DefWindowProc (hwnd
, message
, wParam
, lParam
);
491 register_windows (HINSTANCE hinst
)
500 memset (&wcex
, 0, sizeof (wcex
));
501 wcex
.cbSize
= sizeof (WNDCLASSEX
);
502 wcex
.style
= CS_HREDRAW
| CS_VREDRAW
;
503 wcex
.lpfnWndProc
= listview_proc
;
504 wcex
.hInstance
= hinst
;
505 wcex
.hIcon
= LoadIcon (0, IDI_APPLICATION
);
506 wcex
.hCursor
= LoadCursor (0, IDC_ARROW
);
507 wcex
.hbrBackground
= (HBRUSH
) (COLOR_WINDOW
+ 1);
508 wcex
.lpszClassName
= "listview";
510 RegisterClassEx (&wcex
);
514 note_width (struct _header
*hdrs
, HDC dc
, const char *string
, int addend
,
520 GetTextExtentPoint32 (dc
, string
, strlen (string
), &s
);
521 if (hdrs
[column
].width
< s
.cx
+ addend
)
522 hdrs
[column
].width
= s
.cx
+ addend
;
529 iterate through the package list, and delete packages that are
531 * have no mirror site
532 and then do the same for categories with no packages.
537 fill_missing_category ()
540 for (packagemeta
* pkg
= db
.getfirstpackage (); pkg
;
541 pkg
= db
.getnextpackage ())
542 if (!pkg
->Categories ().categories ())
543 pkg
->add_category (db
.categories
.register_category ("Misc"));
547 default_trust (HWND h
, trusts trust
)
551 for (packagemeta
* pkg
= db
.getfirstpackage (); pkg
;
552 pkg
= db
.getnextpackage ())
554 if (pkg
->installed
|| pkg
->Categories ().getcategorybyname ("Base")
555 || pkg
->Categories ().getcategorybyname ("Misc"))
557 pkg
->desired
= pkgtrustp (pkg
, trust
);
560 pkg
->desired
->binpicked
=
561 pkg
->desired
== pkg
->installed
? 0 : 1;
562 pkg
->desired
->srcpicked
= 0;
569 GetClientRect (h
, &r
);
570 InvalidateRect (h
, &r
, TRUE
);
572 SetFocus (nextbutton
);
576 pick_line::set_line (packagemeta
* _pkg
)
583 pick_line::set_line (Category
* _cat
)
590 pick_line::paint (HDC hdc
, int x
, int y
, int row
, int show_cat
)
592 int r
= y
+ row
* row_height
;
593 int by
= r
+ tm
.tmHeight
- 11;
598 TextOut (hdc
, x
+ chooser
->headers
[chooser
->current_col
].x
, r
,
599 pkg
->installed
->Canonical_version (),
600 strlen (pkg
->installed
->Canonical_version ()));
601 SelectObject (bitmap_dc
, bm_rtarrow
);
602 BitBlt (hdc
, x
+ chooser
->headers
[chooser
->current_col
].x
603 + chooser
->headers
[0].width
+ ICON_MARGIN
/ 2
604 + HMARGIN
/ 2, by
, 11, 11, bitmap_dc
, 0, 0, SRCCOPY
);
607 const char *s
= choose_caption (pkg
);
608 TextOut (hdc
, x
+ chooser
->headers
[chooser
->new_col
].x
609 + NEW_COL_SIZE_SLOP
, r
, s
, strlen (s
));
610 SelectObject (bitmap_dc
, bm_spin
);
611 BitBlt (hdc
, x
+ chooser
->headers
[chooser
->new_col
].x
, by
, 11, 11,
612 bitmap_dc
, 0, 0, SRCCOPY
);
615 if ( /* uninstall */ !pkg
->desired
||
616 /* source only */ (!pkg
->desired
->binpicked
617 && pkg
->desired
->srcpicked
) ||
618 /* when no source mirror available */
619 !pkg
->desired
->src
.sites
.number ())
620 check_bm
= bm_checkna
;
621 else if (pkg
->desired
->srcpicked
)
622 check_bm
= bm_checkyes
;
624 check_bm
= bm_checkno
;
626 SelectObject (bitmap_dc
, check_bm
);
627 BitBlt (hdc
, x
+ chooser
->headers
[chooser
->src_col
].x
, by
, 11, 11,
628 bitmap_dc
, 0, 0, SRCCOPY
);
630 /* shows "first" category - do we want to show any? */
631 if (pkg
->Categories ().getfirstcategory () && show_cat
)
632 TextOut (hdc
, x
+ chooser
->headers
[chooser
->cat_col
].x
, r
,
633 pkg
->Categories ().getfirstcategory ()->name
,
634 strlen (pkg
->Categories ().getfirstcategory ()->name
));
640 static char buf
[512];
641 strcpy (buf
, pkg
->name
);
643 strcat (buf
, pkg
->SDesc ());
646 TextOut (hdc
, x
+ chooser
->headers
[chooser
->pkg_col
].x
, r
, s
,
650 TextOut (hdc
, x
+ chooser
->headers
[chooser
->cat_col
].x
, r
, cat
->name
,
655 pick_line::click (int x
)
659 if (pkg
->desired
&& pkg
->desired
->src
.sites
.number ()
660 && x
>= chooser
->headers
[chooser
->src_col
].x
- HMARGIN
/ 2
661 && x
<= chooser
->headers
[chooser
->src_col
+ 1].x
- HMARGIN
/ 2)
662 pkg
->desired
->srcpicked
^= 1;
664 if (x
>= chooser
->headers
[chooser
->new_col
].x
- (HMARGIN
/ 2)
665 && x
<= chooser
->headers
[chooser
->new_col
+ 1].x
- HMARGIN
/ 2)
668 /* Add any packages that are needed by this package */
669 return add_required (*pkg
);
674 /* handle the catalog being clicked ... does this belong up a level.. ? */
680 _view::_view (views _mode
, HDC dc
)
684 view_mode
= VIEW_PACKAGE
;
687 view_mode
= VIEW_CATEGORY
;
696 _view::set_view_mode (views _mode
)
699 view_mode
= VIEW_PACKAGE_FULL
;
706 _view::mode_caption ()
712 case VIEW_PACKAGE_FULL
:
724 _view::set_headers (void)
730 case VIEW_PACKAGE_FULL
:
732 headers
= pkg_headers
;
741 headers
= cat_headers
;
754 _view::init_headers (HDC dc
)
758 for (i
= 0; headers
[i
].text
; i
++)
759 headers
[i
].width
= 0;
761 for (i
= 0; headers
[i
].text
; i
++)
762 note_width (headers
, dc
, headers
[i
].text
, 0, i
);
764 for (packagemeta
* pkg
= db
.getfirstpackage (); pkg
;
765 pkg
= db
.getnextpackage ())
769 note_width (headers
, dc
, pkg
->installed
->Canonical_version (), 0,
771 note_width (headers
, dc
, pkg
->installed
->Canonical_version (),
772 NEW_COL_SIZE_SLOP
, new_col
);
774 for (size_t n
= 1; n
<= pkg
->versions
.number (); n
++)
775 note_width (headers
, dc
,
776 pkg
->versions
.getnth (n
)->Canonical_version (),
777 NEW_COL_SIZE_SLOP
, new_col
);
778 for (Category
* cat
= db
.categories
.getfirstcategory (); cat
;
780 note_width (headers
, dc
, cat
->name
, 0, cat_col
);
782 note_width (headers
, dc
, pkg
->name
, 0, pkg_col
);
785 static char buf
[512];
786 strcpy (buf
, pkg
->name
);
788 strcat (buf
, pkg
->SDesc ());
789 note_width (headers
, dc
, buf
, 0, pkg_col
);
792 note_width (headers
, dc
, "keep", NEW_COL_SIZE_SLOP
, new_col
);
793 note_width (headers
, dc
, "uninstall", NEW_COL_SIZE_SLOP
, new_col
);
795 headers
[0].x
= HMARGIN
/ 2;
796 for (i
= 1; i
<= last_col
; i
++)
797 headers
[i
].x
= headers
[i
- 1].x
+ headers
[i
- 1].width
+ ((i
== new_col
) ?
803 _view::insert_pkg (packagemeta
& pkg
)
806 line
.set_line (&pkg
);
808 if (view_mode
!= VIEW_CATEGORY
)
813 (pick_line
*) calloc (db
.npackages () +
814 db
.categories
.categories (),
820 insert_under (0, line
);
824 // assert (lines); /* protect against a coding change in future */
825 for (Category
* cat
= pkg
.Categories ().getfirstcategory (); cat
;
828 /* insert the package under this category in the list. If this category is not
833 /* this should be a generic call to list_sort_cmp */
834 if (lines
[n
].get_category ()
835 && cat
->name
== lines
[n
].get_category ()->name
)
837 insert_under (n
, line
);
844 /* the category wasn't visible - insert at the end */
845 insert_category (cat
, CATEGORY_COLLAPSED
);
853 _view::insert_category (Category
* cat
, int collapsed
)
861 (pick_line
*) malloc ((db
.npackages () + db
.categories
.categories ())
862 * sizeof (pick_line
));
865 db
.categories
.categories ()) * sizeof (pick_line
));
869 for (CategoryPackage
* catpkg
= cat
->packages
; catpkg
;
870 catpkg
= catpkg
->next
)
871 insert_pkg (catpkg
->pkg
);
878 /* this should be a generic call to list_sort_cmp */
879 if (lines
[n
].get_category ()
880 && strcasecmp (cat
->name
, lines
[n
].get_category ()->name
) < 0)
884 for (CategoryPackage
* catpkg
= cat
->packages
; catpkg
;
885 catpkg
= catpkg
->next
)
886 insert_pkg (catpkg
->pkg
);
889 else if (lines
[n
].get_category () == cat
)
896 /* insert at the end */
899 for (CategoryPackage
* catpkg
= cat
->packages
; catpkg
;
900 catpkg
= catpkg
->next
)
901 insert_pkg (catpkg
->pkg
);
906 /* insert a new line at line n */
908 _view::insert_at (int n
, pick_line line
)
910 if (n
< 0 || n
> nlines
)
912 memmove (&lines
[n
+ 1], &lines
[n
], (nlines
- n
) * sizeof (pick_line
));
917 /* insert a new line in the chooser, at the next depth in from linen */
919 _view::insert_under (int linen
, pick_line line
)
922 /* special case - empty view */
928 /* perhaps these two are equivalent. FIXME: check for potential insert_under (0,.. calls */
929 else if (linen
> nlines
)
931 insert_at (nlines
, line
);
934 /* part 1 - find the appropriate bucket beginning */
935 if (lines
[linen
].get_category ())
939 else if (lines
[linen
].get_pkg ())
942 /* walk up to the beginning of the bucket */
943 while (n
> 0 && lines
[n
- 1].get_pkg ())
948 /* nlines != 0 and lines[linen] is not a category or a package! */
951 /* part 2 - insert in sorted order in the bucket */
954 if (lines
[n
].get_category () || (lines
[n
].get_pkg ()
955 && strcasecmp (line
.get_pkg ()->name
,
957 get_pkg ()->name
) < 0))
962 else if (lines
[n
].get_pkg () == line
.get_pkg ())
970 /* insert at the end of this bucket */
976 _view::clear_view (void)
982 viewsplusplus (views theview
)
987 return VIEW_PACKAGE_FULL
;
988 case VIEW_PACKAGE_FULL
:
991 return VIEW_CATEGORY
;
1000 _view::click (int row
, int x
)
1004 if (lines
[row
].get_pkg ())
1005 return lines
[row
].click (x
);
1008 /* if we are the last line or the next line is a category too, expand */
1009 if (row
== (nlines
- 1) || lines
[row
+ 1].get_category ())
1012 for (CategoryPackage
* catpkg
=
1013 lines
[row
].get_category ()->packages
; catpkg
;
1014 catpkg
= catpkg
->next
)
1016 packagemeta
& pkg
= catpkg
->pkg
;
1019 line
.set_line (&pkg
);
1020 /* this is a nasty hack. It will go away when the hierarchy is coded */
1023 if (lines
[n
].get_category () || (lines
[n
].get_pkg ()
1024 && strcasecmp (pkg
.name
,
1030 insert_at (n
, line
);
1033 else if (lines
[n
].get_pkg () == &pkg
)
1041 /* insert at the end of this category */
1042 insert_at (n
, line
);
1046 return nlines
- count
;
1051 int count
= 0, n
= row
+ 1;
1052 while (n
< nlines
& !lines
[n
].get_category ())
1054 memmove (&lines
[n
], &lines
[n
+ 1],
1055 (nlines
- n
) * sizeof (pick_line
));
1066 set_view_mode (HWND h
, views mode
)
1068 chooser
->set_view_mode (mode
);
1070 chooser
->clear_view ();
1072 switch (chooser
->get_view_mode ())
1075 for (packagemeta
* pkg
= db
.getfirstpackage (); pkg
;
1076 pkg
= db
.getnextpackage ())
1077 if ((!pkg
->desired
&& pkg
->installed
) || (pkg
->desired
&& (pkg
->desired
->srcpicked
1078 || pkg
->desired
->binpicked
)))
1079 chooser
->insert_pkg (*pkg
);
1081 case VIEW_PACKAGE_FULL
:
1082 for (packagemeta
* pkg
= db
.getfirstpackage (); pkg
;
1083 pkg
= db
.getnextpackage ())
1084 chooser
->insert_pkg (*pkg
);
1087 /* start collapsed. TODO: make this a chooser flag */
1088 for (Category
* cat
= db
.categories
.getfirstcategory (); cat
;
1090 chooser
->insert_category (cat
, CATEGORY_COLLAPSED
);
1097 GetClientRect (h
, &r
);
1099 memset (&si
, 0, sizeof (si
));
1100 si
.cbSize
= sizeof (si
);
1104 chooser
->headers
[chooser
->last_col
].x
+
1105 chooser
->headers
[chooser
->last_col
].width
+ HMARGIN
;
1107 SetScrollInfo (h
, SB_HORZ
, &si
, TRUE
);
1109 si
.nMax
= chooser
->nlines
* row_height
;
1110 si
.nPage
= r
.bottom
- header_height
;
1111 SetScrollInfo (h
, SB_VERT
, &si
, TRUE
);
1113 scroll_ulc_x
= scroll_ulc_y
= 0;
1115 InvalidateRect (h
, &r
, TRUE
);
1118 SetFocus (nextbutton
);
1122 create_listview (HWND dlg
, RECT
* r
)
1124 lv
= CreateWindowEx (WS_EX_CLIENTEDGE
,
1127 WS_CHILD
| WS_HSCROLL
| WS_VSCROLL
| WS_VISIBLE
,
1129 r
->right
- r
->left
+ 1, r
->bottom
- r
->top
+ 1,
1131 (HMENU
) MAKEINTRESOURCE (IDC_CHOOSE_LIST
),
1133 ShowWindow (lv
, SW_SHOW
);
1134 HDC dc
= GetDC (lv
);
1135 sysfont
= GetStockObject (DEFAULT_GUI_FONT
);
1136 SelectObject (dc
, sysfont
);
1137 GetTextMetrics (dc
, &tm
);
1138 header_height
= tm
.tmHeight
+ 5 + 3;
1140 bitmap_dc
= CreateCompatibleDC (dc
);
1142 row_height
= (tm
.tmHeight
+ tm
.tmExternalLeading
+ ROW_MARGIN
);
1143 int irh
= tm
.tmExternalLeading
+ tm
.tmDescent
+ 11 + ROW_MARGIN
;
1144 if (row_height
< irh
)
1147 chooser
= new (view
) (VIEW_CATEGORY
, dc
);
1149 default_trust (lv
, TRUST_CURR
);
1150 set_view_mode (lv
, VIEW_CATEGORY
);
1151 if (!SetDlgItemText (dlg
, IDC_CHOOSE_VIEWCAPTION
, chooser
->mode_caption ()))
1152 log (LOG_BABBLE
, "Failed to set View button caption %ld",
1155 for (packagemeta
* pkg
= db
.getfirstpackage (); pkg
;
1156 pkg
= db
.getnextpackage ())
1157 add_required (*pkg
);
1158 /* FIXME: do we need to init the desired fields ? */
1159 static int ta
[] = { IDC_CHOOSE_CURR
, 0 };
1160 rbset (dlg
, ta
, IDC_CHOOSE_CURR
);
1166 dialog_cmd (HWND h
, int id
, HWND hwndctl
, UINT code
)
1171 case IDC_CHOOSE_PREV
:
1172 default_trust (lv
, TRUST_PREV
);
1173 for (packagemeta
* pkg
= db
.getfirstpackage (); pkg
;
1174 pkg
= db
.getnextpackage ())
1175 add_required (*pkg
);
1176 set_view_mode (lv
, chooser
->get_view_mode ());
1178 case IDC_CHOOSE_CURR
:
1179 default_trust (lv
, TRUST_CURR
);
1180 for (packagemeta
* pkg
= db
.getfirstpackage (); pkg
;
1181 pkg
= db
.getnextpackage ())
1182 add_required (*pkg
);
1183 set_view_mode (lv
, chooser
->get_view_mode ());
1185 case IDC_CHOOSE_EXP
:
1186 default_trust (lv
, TRUST_TEST
);
1187 for (packagemeta
* pkg
= db
.getfirstpackage (); pkg
;
1188 pkg
= db
.getnextpackage ())
1189 add_required (*pkg
);
1190 set_view_mode (lv
, chooser
->get_view_mode ());
1192 case IDC_CHOOSE_VIEW
:
1193 set_view_mode (lv
, viewsplusplus (chooser
->get_view_mode ()));
1195 (h
, IDC_CHOOSE_VIEWCAPTION
, chooser
->mode_caption ()))
1196 log (LOG_BABBLE
, "Failed to set View button caption %ld",
1201 if (source
== IDC_SOURCE_CWD
)
1202 NEXT (IDD_S_INSTALL
);
1204 NEXT (IDD_S_DOWNLOAD
);
1209 if (source
== IDC_SOURCE_CWD
)
1210 NEXT (IDD_LOCAL_DIR
);
1223 GetParentRect (HWND parent
, HWND child
, RECT
* r
)
1226 GetWindowRect (child
, r
);
1229 ScreenToClient (parent
, &p
);
1234 ScreenToClient (parent
, &p
);
1239 static BOOL CALLBACK
1240 dialog_proc (HWND h
, UINT message
, WPARAM wParam
, LPARAM lParam
)
1247 nextbutton
= GetDlgItem (h
, IDOK
);
1248 frame
= GetDlgItem (h
, IDC_LISTVIEW_POS
);
1249 choose_inst_text
= GetDlgItem (h
, IDC_CHOOSE_INST_TEXT
);
1250 if (source
== IDC_SOURCE_DOWNLOAD
)
1251 SetWindowText (choose_inst_text
, "Select packages to download ");
1253 SetWindowText (choose_inst_text
, "Select packages to install ");
1254 GetParentRect (h
, frame
, &r
);
1257 create_listview (h
, &r
);
1263 return HANDLE_WM_COMMAND (h
, wParam
, lParam
, dialog_cmd
);
1269 base (const char *s
)
1276 if ((*s
== '/' || *s
== ':' || *s
== '\\') && s
[1])
1284 find_tar_ext (const char *path
)
1286 char *end
= strchr (path
, '\0');
1287 /* check in longest first order */
1288 char *ext
= strstr (path
, ".tar.bz2");
1290 return (end
- ext
) == 8 ? ext
- path
: 0;
1291 if ((ext
= strstr (path
, ".tar.gz")));
1292 return (end
- ext
) == 7 ? ext
- path
: 0;
1293 if ((ext
= strstr (path
, ".tar")));
1294 return (end
- ext
) == 4 ? ext
- path
: 0;
1297 /* Parse a filename into package, version, and extension components. */
1299 parse_filename (const char *in_fn
, fileparse
& f
)
1302 char fn
[strlen (in_fn
) + 1];
1305 int n
= find_tar_ext (fn
);
1310 strcpy (f
.tail
, fn
+ n
);
1312 f
.pkg
[0] = f
.what
[0] = '\0';
1314 for (ver
= p
; *ver
; ver
++)
1315 if (*ver
== '-' || *ver
== '_')
1316 if (isdigit (ver
[1]))
1322 else if (strcasecmp (ver
, "-src") == 0 ||
1323 strcasecmp (ver
, "-patch") == 0)
1327 strcpy (f
.what
, strlwr (ver
));
1328 strcpy (f
.pkgtar
, p
);
1329 strcat (f
.pkgtar
, f
.tail
);
1330 ver
= strchr (ver
, '\0');
1340 p
= strchr (ver
, '\0');
1341 strcpy (f
.pkgtar
, in_fn
);
1342 if ((p
-= 4) >= ver
&& strcasecmp (p
, "-src") == 0)
1344 else if ((p
-= 2) >= ver
&& strcasecmp (p
, "-patch") == 0)
1350 strcpy (f
.what
, p
+ 1);
1352 p
= f
.pkgtar
+ (p
- fn
) + n
;
1353 memmove (p
- n
, p
, strlen (p
));
1357 strcpy (f
.ver
, *ver
? ver
: "0.0");
1361 /* Find out where to put existing tar file in local directory in
1362 known package array. */
1364 scan2 (char *path
, unsigned int size
)
1369 if (!parse_filename (path
, f
))
1372 if (f
.what
[0] != '\0' && f
.what
[0] != 's')
1376 pkg
= db
.getpackagebyname (f
.pkg
);
1380 /* Scan existing package list looking for a match between a known
1381 package and a tar archive on disk.
1382 While scanning, keep track of appropriate "holes" in the trust
1383 table where a tar file could be put if no known entry
1386 We have 4 specific insertion points and one generic point.
1387 The generic point is in versioned order in the package version array.
1388 The specific points are
1394 if the version number matches a version in the db,
1395 we simply add this as a mirror source to that version.
1396 If it matches no version, we add a new version to the db.
1398 Lastly if the version number does not matche one of installed/prev/current/exp
1399 AND we had to create a new version entry
1400 we apply the following heuristic:
1401 if there is no exp, we link this in exp.
1402 If there is an exp and this is higher, we link this in exp, and
1403 if there is no curr, bump what was in exp to curr. If there was a curr, we leave it be.
1404 if this is lower than exp, and there is no curr, link as curr. If there is a curr, leave it be.
1405 If this is lower than curr, and there is no prev, link as prev, if there is a prev, leave it be.
1407 Whilst this logic is potentially wrong from time to time, it guarantees that
1408 setup.ini defined stability won't be altered unintentially. An alternative is to
1409 mark setup.ini defined prev/curr/exp packages as such, when this algorithm, can
1412 So, if setup.ini knows that ash-20010425-1.tar.gz is the current
1413 version and there is an ash-20010426-1.tar.gz in the current directory,
1414 the 20010426 version will be placed in the "test" slot, assuming that
1415 there is no test version listed in setup.ini. */
1418 for (size_t n
= 1; n
<= pkg
->versions
.number (); n
++)
1420 if (!strcasecmp (f
.ver
, pkg
->versions
.getnth (n
)->Canonical_version ()))
1422 /* FIXME: Add a mirror entry */
1428 /* FIXME: Add a new version */
1430 /* And now the hole finder */
1433 pkg
->exp
= thenewver
;
1434 else if (strcasecmp (f
.ver
, pkg
->versions
[n
]->Canonicalversion ()) < 0)
1437 pkg
->curr
= thenewver
;
1438 else if (strcasecmp (f
.ver
, pkg
->versions
[n
]->Canonicalversion ()) <
1442 pkg
->prev
= thenewver
;
1449 scan_downloaded_files ()
1454 _Info::_Info (const char *_install
, const char *_version
, int _install_size
,
1455 const char *_source
, int _source_size
)
1457 memset (this, 0, sizeof (*this));
1458 install
= strdup (_install
);
1459 version
= strdup (_version
);
1460 install_size
= _install_size
;
1463 source
= strdup (_source
);
1464 source_size
= _source_size
;
1469 package_sort (const void *va
, const void *vb
)
1471 packagemeta
*a
= (packagemeta
*) va
;
1472 packagemeta
*b
= (packagemeta
*) vb
;
1473 return strcasecmp (a
->name
, b
->name
);
1477 do_choose (HINSTANCE h
)
1482 bm_spin
= LoadImage (h
, MAKEINTRESOURCE (IDB_SPIN
), IMAGE_BITMAP
, 0, 0, 0);
1483 bm_rtarrow
= LoadImage (h
, MAKEINTRESOURCE (IDB_RTARROW
), IMAGE_BITMAP
,
1486 bm_checkyes
= LoadImage (h
, MAKEINTRESOURCE (IDB_CHECK_YES
), IMAGE_BITMAP
,
1488 bm_checkno
= LoadImage (h
, MAKEINTRESOURCE (IDB_CHECK_NO
), IMAGE_BITMAP
,
1490 bm_checkna
= LoadImage (h
, MAKEINTRESOURCE (IDB_CHECK_NA
), IMAGE_BITMAP
,
1493 register_windows (h
);
1495 if (source
== IDC_SOURCE_DOWNLOAD
|| source
== IDC_SOURCE_CWD
)
1496 scan_downloaded_files ();
1499 fill_missing_category ();
1501 rv
= DialogBox (h
, MAKEINTRESOURCE (IDD_CHOOSE
), 0, dialog_proc
);
1503 fatal (IDS_DIALOG_FAILED
);
1505 log (LOG_BABBLE
, "Chooser results...");
1507 for (packagemeta
* pkg
= db
.getfirstpackage (); pkg
;
1508 pkg
= db
.getnextpackage ())
1510 // static const char *infos[] = { "nada", "prev", "curr", "test" };
1511 const char *trust
= ((pkg
->desired
== pkg
->prev
) ? "prev"
1512 : (pkg
->desired
== pkg
->curr
) ? "curr"
1513 : (pkg
->desired
== pkg
->exp
) ? "test" : "unknown");
1514 const char *action
= choose_caption (pkg
);
1515 const char *installed
=
1516 pkg
->installed
? pkg
->installed
->Canonical_version () : "none";
1518 log (LOG_BABBLE
, "[%s] action=%s trust=%s installed=%s"
1520 pkg
->name
, action
, trust
, installed
,
1521 pkg
->desired
&& pkg
->desired
->srcpicked
? "yes" : "no");
1522 if (pkg
->Categories ().categories ())
1524 /* List categories the package belongs to */
1525 int categories_len
= 0;
1527 for (cp
= pkg
->Categories ().getfirstcategory (); cp
; cp
= cp
->next
)
1529 categories_len
+= strlen (cp
->name
) + 2;
1531 if (categories_len
> 0)
1533 char *categories
= (char *) malloc (categories_len
);
1535 pkg
->Categories ().getfirstcategory ()->name
);
1536 for (cp
= pkg
->Categories ().getfirstcategory ()->next
; cp
;
1540 strcat (categories
, ", ");
1541 strcat (categories
, cp
->name
);
1543 log (LOG_BABBLE
, " categories=%s", categories
);
1547 if (pkg
->desired
&& pkg
->desired
->required
)
1549 /* List other packages this package depends on */
1550 int requires_len
= 0;
1552 for (dp
= pkg
->desired
->required
; dp
; dp
= dp
->next
)
1554 requires_len
+= strlen (dp
->package
) + 2;
1556 if (requires_len
> 0)
1558 char *requires
= (char *) malloc (requires_len
);
1559 strcpy (requires
, pkg
->desired
->required
->package
);
1560 for (dp
= pkg
->desired
->required
->next
; dp
; dp
= dp
->next
)
1563 strcat (requires
, ", ");
1564 strcat (requires
, dp
->package
);
1566 log (LOG_BABBLE
, " requires=%s", requires
);
1572 /* FIXME: Reinstate this code, but spit out all mirror sites */
1574 for (int t
= 1; t
< NTRUST
; t
++)
1576 if (pkg
->info
[t
].install
)
1577 log (LOG_BABBLE
, " [%s] ver=%s\n"
1578 " inst=%s %d exists=%s\n"
1579 " src=%s %d exists=%s",
1581 pkg
->info
[t
].version
? : "(none)",
1582 pkg
->info
[t
].install
? : "(none)",
1583 pkg
->info
[t
].install_size
,
1584 (pkg
->info
[t
].install_exists
) ? "yes" : "no",
1585 pkg
->info
[t
].source
? : "(none)",
1586 pkg
->info
[t
].source_size
,
1587 (pkg
->info
[t
].source_exists
) ? "yes" : "no");
This page took 0.197163 seconds and 5 git commands to generate.