]> cygwin.com Git - cygwin-apps/setup.git/blob - choose.cc
e10ec14123ded21524b363a4e35354d5b5e080b6
[cygwin-apps/setup.git] / choose.cc
1 /*
2 * Copyright (c) 2000, 2001 Red Hat, Inc.
3 *
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.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by DJ Delorie <dj@cygnus.com>
13 *
14 */
15
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
26 default. */
27
28 static char *cvsid = "\n%%% $Id$\n";
29
30 #include "win32.h"
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <io.h>
34 #include <ctype.h>
35
36 #include "dialog.h"
37 #include "resource.h"
38 #include "state.h"
39 #include "ini.h"
40 #include "concat.h"
41 #include "msg.h"
42 #include "log.h"
43 #include "find.h"
44 #include "filemanip.h"
45 #include "mount.h"
46 #include "choose.h"
47
48 #include "port.h"
49
50 #define HMARGIN 10
51 #define ROW_MARGIN 5
52 #define ICON_MARGIN 4
53 #define NEW_COL_SIZE_SLOP (ICON_MARGIN + 11)
54
55 #define CHECK_SIZE 11
56
57 static int initialized = 0;
58
59 static int scroll_ulc_x, scroll_ulc_y;
60
61 static HWND lv, nextbutton, choose_inst_text;
62 static TEXTMETRIC tm;
63 static int header_height;
64 static HANDLE sysfont;
65 static int row_height;
66 static HANDLE bm_spin, bm_rtarrow, bm_checkyes, bm_checkno, bm_checkna;
67 static HDC bitmap_dc;
68 static view *chooser = NULL;
69 static trusts deftrust = TRUST_UNKNOWN;
70
71 static struct _header pkg_headers[] = {
72 { "Current", 7, 0, 0 },
73 { "New", 3, 0, 0 },
74 { "Src?", 4, 0, 0 },
75 { "Category", 8, 0, 0 },
76 { "Package", 7, 0, 0 },
77 { 0, 0, 0, 0 }
78 };
79
80 static struct _header cat_headers[] = {
81 { "Category", 8, 0, 0 },
82 { "Current", 7, 0, 0 },
83 { "New", 3, 0, 0 },
84 { "Src?", 4, 0, 0 },
85 { "Package", 7, 0, 0 },
86 { 0, 0, 0, 0 }
87 };
88
89 static int add_required(Package *pkg);
90 static void set_view_mode (HWND h, views mode);
91
92 static bool
93 isinstalled (Package *pkg, int trust)
94 {
95 if (source == IDC_SOURCE_DOWNLOAD)
96 return pkg->info[trust].install_exists < 0;
97 else
98 return pkg->installed && pkg->info[trust].version &&
99 strcasecmp (pkg->installed->version, pkg->info[trust].version) == 0;
100 }
101
102 /* Set the next action given a current action. */
103 static void
104 set_action (Package *pkg, bool preinc)
105 {
106 if (!pkg->action || preinc)
107 {
108 ((int) pkg->action)++;
109 pkg->srcpicked = 0;
110 }
111
112 /* Exercise the action state machine. */
113 for (;; ((int) pkg->action)++)
114 switch (pkg->action)
115 {
116 case ACTION_ERROR:
117 case ACTION_UNKNOWN:
118 pkg->action = (actions) (ACTION_CURR - 1);
119 break;
120 case ACTION_LAST:
121 pkg->action = ACTION_PREV;
122 /* fall through intentionally */
123 case ACTION_PREV:
124 case ACTION_CURR:
125 case ACTION_TEST:
126 /* Try to find the next best action. We may not have all of
127 prev, curr, or test but we should have at least one of those. */
128 Info *inf;
129 inf = pkg->info + pkg->action;
130 if (inf->version && inf->install_exists)
131 {
132 if (isinstalled (pkg, pkg->action))
133 (int) pkg->action += ACTION_SAME;
134 return;
135 }
136 break;
137 /* ACTION_SAME_* are used when the installed version is the same
138 as the given action. */
139 case ACTION_SAME_CURR:
140 case ACTION_SAME_TEST:
141 if (!preinc) /* Previously set to this value */
142 return;
143 (int) pkg->action -= ACTION_SAME + 1; /* revert to ACTION_CURR, etc. */
144 break;
145 case ACTION_SAME_PREV:
146 if (!preinc) /* Previously set to this value */
147 return;
148 pkg->action = ACTION_UNINSTALL;
149 /* Fall through intentionally */
150 case ACTION_UNINSTALL:
151 if (source != IDC_SOURCE_DOWNLOAD && pkg->installed)
152 return;
153 break;
154 case ACTION_REDO:
155 {
156 if (isinstalled (pkg, deftrust))
157 {
158 pkg->trust = deftrust;
159 return;
160 }
161 }
162 break;
163 case ACTION_SRC_ONLY:
164 {
165 if (pkg->info[deftrust].source_exists)
166 {
167 pkg->trust = deftrust;
168 pkg->srcpicked = 1;
169 return;
170 }
171 }
172 break;
173 case ACTION_SAME_LAST:
174 pkg->action = ACTION_SKIP;
175 /* Fall through intentionally */
176 case ACTION_SKIP:
177 if ((source == IDC_SOURCE_DOWNLOAD) || !pkg->installed
178 || pkg->trust != pkg->installed_ix)
179 return;
180 break;
181 default:
182 log (0, "should never get here %d\n", pkg->action);
183 }
184 }
185
186 static int
187 add_required (Package *pkg)
188 {
189 Dependency *dp;
190 Package *required;
191 int c;
192 int changed = 0;
193 dp = pkg->required;
194 switch (pkg->action)
195 {
196 case ACTION_UNINSTALL:
197 case ACTION_ERROR:
198 case ACTION_UNKNOWN:
199 case ACTION_SRC_ONLY:
200 case ACTION_SKIP:
201 return 0;
202 default:
203 break;
204 }
205 while (dp)
206 {
207 if ((required = getpkgbyname(dp->package)) == NULL)
208 {
209 dp=dp->next;
210 continue;
211 }
212 switch (required->action)
213 {
214 case ACTION_PREV:
215 case ACTION_CURR:
216 case ACTION_TEST:
217 case ACTION_LAST:
218 case ACTION_SAME_CURR:
219 case ACTION_SAME_TEST:
220 case ACTION_SAME_PREV:
221 case ACTION_REDO:
222 case ACTION_SAME_LAST:
223 /* we are installing a user selected version */
224 break;
225
226 case ACTION_UNINSTALL:
227 /* it's already installed - leave it */
228 required->action = (actions) required->installed_ix;
229 break;
230 case ACTION_ERROR:
231 case ACTION_UNKNOWN:
232 case ACTION_SRC_ONLY:
233 case ACTION_SKIP:
234 /* the current install will fail */
235 required->action = ACTION_UNKNOWN; /* this find prev, then curr, then test. */
236 set_action(required, 0); /* we need a find_best that gets installed, */
237 changed++; /* then current, then prev, then test */
238 chooser->insert_pkg (required);
239 break;
240 default:
241 log (0, "invalid state %d\n", required->action);
242 }
243 changed += add_required (required);
244 dp=dp->next;
245 }
246 return changed;
247 }
248
249 /* Return an appropriate caption given the current action. */
250 const char *
251 choose_caption (Package *pkg)
252 {
253 set_action (pkg, 0);
254 switch (pkg->action)
255 {
256 case ACTION_PREV:
257 case ACTION_CURR:
258 case ACTION_TEST:
259 pkg->trust = (trusts) pkg->action;
260 return pkg->info[pkg->trust].version;
261 case ACTION_SAME_PREV:
262 case ACTION_SAME_CURR:
263 case ACTION_SAME_TEST:
264 return "Keep";
265 case ACTION_UNINSTALL:
266 return "Uninstall";
267 case ACTION_REDO:
268 return source == IDC_SOURCE_DOWNLOAD ? "Retrieve" : "Reinstall";
269 case ACTION_SRC_ONLY:
270 if (pkg->installed && pkg->installed->source_exists)
271 return "Redo Source";
272 else
273 return "Source";
274 case ACTION_SKIP:
275 return "Skip";
276 }
277 return "???";
278 }
279
280 static void
281 paint (HWND hwnd)
282 {
283 HDC hdc;
284 PAINTSTRUCT ps;
285 int x, y, i, j, ii;
286
287 hdc = BeginPaint (hwnd, &ps);
288
289 SelectObject (hdc, sysfont);
290 SetBkColor (hdc, GetSysColor (COLOR_WINDOW));
291 SetTextColor (hdc, GetSysColor (COLOR_WINDOWTEXT));
292
293 RECT cr;
294 GetClientRect (hwnd, &cr);
295
296 POINT p;
297
298 x = cr.left - scroll_ulc_x;
299 y = cr.top - scroll_ulc_y + header_height;
300
301
302 for (i = 0; i <= chooser->last_col ; i++)
303 {
304 TextOut (hdc, x + chooser->headers[i].x, 3, chooser->headers[i].text,
305 chooser->headers[i].slen);
306 MoveToEx (hdc, x + chooser->headers[i].x, header_height-3, &p);
307 LineTo (hdc, x + chooser->headers[i].x + chooser->headers[i].width,
308 header_height-3);
309 }
310
311 IntersectClipRect (hdc, cr.left, cr.top + header_height, cr.right, cr.bottom);
312
313 for (ii = 0; ii < chooser->nlines; ii++)
314 chooser->lines[ii].paint (hdc, x, y, ii,
315 (chooser->get_view_mode () == VIEW_CATEGORY) ? 0 : 1);
316
317 if (chooser->nlines == 0)
318 {
319 static char *msg = "Nothing to Install/Update";
320 if (source == IDC_SOURCE_DOWNLOAD)
321 msg = "Nothing to Download";
322 TextOut (hdc, HMARGIN, header_height, msg, strlen (msg));
323 }
324
325 EndPaint (hwnd, &ps);
326 }
327
328 static void
329 scroll_common (HWND hwnd, int which, int *var, int code)
330 {
331 int v = *var;
332
333 SCROLLINFO si;
334 si.cbSize = sizeof (si);
335 si.fMask = SIF_ALL;
336 GetScrollInfo (hwnd, which, &si);
337
338 switch (code)
339 {
340 case SB_THUMBTRACK:
341 si.nPos = si.nTrackPos;
342 break;
343 case SB_THUMBPOSITION:
344 break;
345 case SB_BOTTOM:
346 si.nPos = si.nMax;
347 break;
348 case SB_TOP:
349 si.nPos = 0;
350 break;
351 case SB_LINEDOWN:
352 si.nPos += row_height;
353 break;
354 case SB_LINEUP:
355 si.nPos -= row_height;
356 break;
357 case SB_PAGEDOWN:
358 si.nPos += si.nPage * 9/10;
359 break;
360 case SB_PAGEUP:
361 si.nPos -= si.nPage * 9/10;
362 break;
363 }
364
365 if ((int)si.nPos < 0)
366 si.nPos = 0;
367 if (si.nPos + si.nPage > si.nMax)
368 si.nPos = si.nMax - si.nPage;
369
370 si.fMask = SIF_POS;
371 SetScrollInfo (hwnd, which, &si, TRUE);
372
373 int ox = scroll_ulc_x;
374 int oy = scroll_ulc_y;
375 *var = si.nPos;
376
377 RECT cr, sr;
378 GetClientRect (hwnd, &cr);
379 sr = cr;
380 sr.top += header_height;
381 ScrollWindow (hwnd, ox - scroll_ulc_x, oy - scroll_ulc_y, &sr, &sr);
382 sr.bottom = sr.top;
383 sr.top = cr.top;
384 ScrollWindow (hwnd, ox - scroll_ulc_x, 0, &sr, &sr);
385 }
386
387 static LRESULT CALLBACK
388 list_vscroll (HWND hwnd, HWND hctl, UINT code, int pos)
389 {
390 scroll_common (hwnd, SB_VERT, &scroll_ulc_y, code);
391 }
392
393 static LRESULT CALLBACK
394 list_hscroll (HWND hwnd, HWND hctl, UINT code, int pos)
395 {
396 scroll_common (hwnd, SB_HORZ, &scroll_ulc_x, code);
397 }
398
399 static LRESULT CALLBACK
400 list_click (HWND hwnd, BOOL dblclk, int x, int y, UINT hitCode)
401 {
402 int r,refresh;
403
404 if (chooser->nlines == 0)
405 return 0;
406
407 if (y < header_height)
408 return 0;
409 x += scroll_ulc_x;
410 y += scroll_ulc_y - header_height;
411
412 r = (y + ROW_MARGIN/2) / row_height;
413
414 if (r < 0 || r >= chooser->nlines)
415 return 0;
416
417 refresh = chooser->click (r, x);
418
419 if (refresh)
420 {
421 RECT r;
422 GetClientRect (lv, &r);
423 SCROLLINFO si;
424 memset (&si, 0, sizeof (si));
425 si.cbSize = sizeof (si);
426 si.fMask = SIF_ALL; /* SIF_RANGE was giving strange behaviour */
427 si.nMin = 0;
428
429 si.nMax = chooser->nlines * row_height;
430 si.nPage = r.bottom - header_height;
431 si.nPos = scroll_ulc_y;
432 SetScrollInfo (lv, SB_VERT, &si, TRUE);
433
434 InvalidateRect (lv, &r, TRUE);
435
436 }
437 else
438 {
439 RECT rect;
440 rect.left = chooser->headers[chooser->new_col].x - scroll_ulc_x;
441 rect.right = chooser->headers[chooser->src_col + 1].x - scroll_ulc_x;
442 rect.top = header_height + r * row_height - scroll_ulc_y;
443 rect.bottom = rect.top + row_height;
444 InvalidateRect (hwnd, &rect, TRUE);
445 }
446 }
447
448 static LRESULT CALLBACK
449 listview_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
450 {
451 switch (message)
452 {
453 case WM_HSCROLL:
454 return HANDLE_WM_HSCROLL (hwnd, wParam, lParam, list_hscroll);
455 case WM_VSCROLL:
456 return HANDLE_WM_VSCROLL (hwnd, wParam, lParam, list_vscroll);
457 case WM_LBUTTONDOWN:
458 return HANDLE_WM_LBUTTONDOWN (hwnd, wParam, lParam, list_click);
459 case WM_PAINT:
460 paint (hwnd);
461 return 0;
462 default:
463 return DefWindowProc (hwnd, message, wParam, lParam);
464 }
465 }
466
467 static void
468 register_windows (HINSTANCE hinst)
469 {
470 WNDCLASSEX wcex;
471 static int done = 0;
472
473 if (done)
474 return;
475 done = 1;
476
477 memset (&wcex, 0, sizeof (wcex));
478 wcex.cbSize = sizeof (WNDCLASSEX);
479 wcex.style = CS_HREDRAW | CS_VREDRAW;
480 wcex.lpfnWndProc = listview_proc;
481 wcex.hInstance = hinst;
482 wcex.hIcon = LoadIcon (0, IDI_APPLICATION);
483 wcex.hCursor = LoadCursor (0, IDC_ARROW);
484 wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
485 wcex.lpszClassName = "listview";
486
487 RegisterClassEx (&wcex);
488 }
489
490 static void
491 note_width (struct _header *hdrs, HDC dc, char *string, int addend, int column)
492 {
493 if (!string)
494 return;
495 SIZE s;
496 GetTextExtentPoint32 (dc, string, strlen (string), &s);
497 if (hdrs[column].width < s.cx + addend)
498 hdrs[column].width = s.cx + addend;
499 }
500
501 static int
502 check_existence (Info *inf, int check_src)
503 {
504 if (source == IDC_SOURCE_NETINST)
505 return 1;
506 if (source == IDC_SOURCE_CWD)
507 return 0; /* should have already been determined */
508 if (check_src)
509 return (inf->source && _access (inf->source, 0) == 0) ? -1 : 1;
510 else
511 return (inf->install && _access (inf->install, 0) == 0) ? -1 : 1;
512 return 0;
513 }
514
515 /* Iterate over the package list, setting the "existence" flags
516 for the source or binary. */
517 static void
518 set_existence ()
519 {
520 for (Package *pkg = package; pkg->name; pkg++)
521 if (!pkg->exclude)
522 {
523 int exists = 0;
524 for (Info *inf = pkg->infoscan; inf < pkg->infoend; inf++)
525 {
526 if (inf->install_exists)
527 exists = 1;
528 else
529 exists |= inf->install_exists = check_existence (inf, 0);
530 if (inf->source_exists)
531 exists = 1;
532 else
533 exists |= inf->source_exists = check_existence (inf, 1);
534 }
535 if (source != IDC_SOURCE_DOWNLOAD && !exists)
536 pkg->exclude = EXCLUDE_NOT_FOUND;
537 }
538 }
539
540 static void
541 fill_missing_category ()
542 {
543 for (Package *pkg = package; pkg->name; pkg++)
544 if (!pkg->exclude && !pkg->category)
545 add_category (pkg, register_category ("Misc"));
546 }
547
548 static actions
549 keep_or_skip (Package *pkg)
550 {
551 if (pkg->installed)
552 return (actions) pkg->installed_ix;
553 return ACTION_SKIP;
554 }
555
556 static void
557 default_trust (HWND h, trusts trust)
558 {
559 int i, t, c;
560
561 deftrust = trust;
562 for (Package *pkg = package; pkg->name; pkg++)
563 if (!pkg->exclude)
564 {
565 pkg->action = (actions) trust;
566 if (pkg->category && !(getpackagecategorybyname (pkg, "Required") ||
567 getpackagecategorybyname (pkg, "Misc")))
568 pkg->action = keep_or_skip (pkg);
569 set_action (pkg, 0);
570 }
571 RECT r;
572 GetClientRect (h, &r);
573 InvalidateRect (h, &r, TRUE);
574 if (nextbutton)
575 SetFocus (nextbutton);
576 }
577
578 void
579 pick_line::set_line (Package *_pkg)
580 {
581 pkg = _pkg;
582 cat = NULL;
583 }
584
585 void
586 pick_line::set_line (Category *_cat)
587 {
588 cat = _cat;
589 pkg = NULL;
590 }
591
592 void
593 pick_line::paint (HDC hdc, int x, int y, int row, int show_cat)
594 {
595 int r = y + row * row_height;
596 int by = r + tm.tmHeight - 11;
597 if (pkg)
598 {
599 if (pkg->installed)
600 {
601 TextOut (hdc, x + chooser->headers[chooser->current_col].x, r,
602 pkg->installed->version, strlen (pkg->installed->version));
603 SelectObject (bitmap_dc, bm_rtarrow);
604 BitBlt (hdc, x + chooser->headers[chooser->current_col].x
605 + chooser->headers[0].width + ICON_MARGIN / 2
606 + HMARGIN / 2,
607 by, 11, 11, bitmap_dc, 0, 0, SRCCOPY);
608 }
609
610 const char *s = choose_caption (pkg);
611 TextOut (hdc, x + chooser->headers[chooser->new_col].x
612 + NEW_COL_SIZE_SLOP, r, s, strlen (s));
613 SelectObject (bitmap_dc, bm_spin);
614 BitBlt (hdc, x + chooser->headers[chooser->new_col].x, by, 11, 11,
615 bitmap_dc, 0, 0, SRCCOPY);
616
617 HANDLE check_bm;
618 if (!pkg->info[pkg->trust].source_exists
619 || (pkg->action != ACTION_REDO && pkg->action != (actions) pkg->trust))
620 check_bm = bm_checkna;
621 else if (pkg->srcpicked)
622 check_bm = bm_checkyes;
623 else
624 check_bm = bm_checkno;
625
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);
629
630 /* shows "first" category - do we want to show any? */
631 if (pkg->category && show_cat)
632 TextOut (hdc, x + chooser->headers[chooser->cat_col].x, r,
633 pkg->category->name, strlen (pkg->category->name));
634
635 if (pkg->sdesc)
636 s = pkg->sdesc;
637 else
638 s = pkg->name;
639 TextOut (hdc, x + chooser->headers[chooser->pkg_col].x, r, s, strlen (s));
640 }
641 else if (cat)
642 TextOut (hdc, x + chooser->headers[chooser->cat_col].x, r, cat->name,
643 strlen (cat->name));
644 }
645
646 int
647 pick_line::click (int x)
648 {
649 if (pkg)
650 {
651 if (pkg->info[pkg->trust].source_exists
652 && x >= chooser->headers[chooser->src_col].x - HMARGIN/2
653 && x <= chooser->headers[chooser->src_col + 1].x - HMARGIN/2)
654 pkg->srcpicked ^= 1;
655
656 if (x >= chooser->headers[chooser->new_col].x - (HMARGIN / 2)
657 && x <= chooser->headers[chooser->new_col + 1].x - HMARGIN/2)
658 {
659 set_action (pkg, 1);
660 /* Add any packages that are needed by this package */
661 return add_required (pkg);
662 }
663 }
664 else if (cat)
665 {
666 /* handle the catalog being clicked ... does this belong up a level.. ? */
667 }
668
669 return 0;
670 }
671
672 _view::_view (views _mode, HDC dc)
673 {
674 lines = NULL;
675 nlines = 0;
676 view_mode = VIEW_PACKAGE;
677 set_headers ();
678 init_headers (dc);
679 view_mode = VIEW_CATEGORY;
680 set_headers ();
681 init_headers (dc);
682
683 view_mode = _mode;
684 set_headers ();
685 }
686
687 void
688 _view::set_view_mode (views _mode)
689 {
690 if (_mode == NVIEW)
691 view_mode = VIEW_PACKAGE_FULL;
692 else
693 view_mode = _mode;
694 set_headers ();
695 }
696
697 char *
698 _view::mode_caption ()
699 {
700 switch (view_mode)
701 {
702 case VIEW_UNKNOWN: return "";
703 case VIEW_PACKAGE_FULL: return "Full";
704 case VIEW_PACKAGE: return "Partial";
705 case VIEW_CATEGORY: return "Category";
706 default: return "";
707 }
708 }
709
710 void
711 _view::set_headers (void)
712 {
713 switch (view_mode)
714 {
715 case VIEW_UNKNOWN:
716 return;
717 case VIEW_PACKAGE_FULL:
718 case VIEW_PACKAGE:
719 headers = pkg_headers;
720 current_col = 0;
721 new_col = 1;
722 src_col = 2;
723 cat_col = 3;
724 pkg_col = 4;
725 last_col = 4;
726 break;
727 case VIEW_CATEGORY:
728 headers = cat_headers;
729 current_col = 1;
730 new_col = 2;
731 src_col = 3;
732 cat_col = 0;
733 pkg_col = 4;
734 last_col = 4;
735 default:
736 return;
737 }
738 }
739
740 void
741 _view::init_headers (HDC dc)
742 {
743 int i;
744
745 for (i = 0; headers[i].text; i++)
746 headers[i].width = 0;
747
748 for (i = 0; headers[i].text; i++)
749 note_width (headers, dc, headers[i].text, 0, i);
750 for (Package *pkg = package; pkg->name; pkg++)
751 {
752 if (pkg->installed)
753 {
754 note_width (headers, dc, pkg->installed->version, 0, current_col);
755 note_width (headers, dc, pkg->installed->version, NEW_COL_SIZE_SLOP,
756 new_col);
757 }
758 for (Info *inf = pkg->infoscan; inf < pkg->infoend; inf++)
759 note_width (headers, dc, inf->version, NEW_COL_SIZE_SLOP, new_col);
760 for (Category *cat = pkg->category; cat ; cat = cat->next)
761 note_width (headers, dc, cat->name, 0, cat_col);
762 note_width (headers, dc, pkg->name, 0, pkg_col);
763 note_width (headers, dc, pkg->sdesc, 0, pkg_col);
764 }
765 note_width (headers, dc, "keep", NEW_COL_SIZE_SLOP, new_col);
766 note_width (headers, dc, "uninstall", NEW_COL_SIZE_SLOP, new_col);
767
768 headers[0].x = HMARGIN/2;
769 for (i = 1; i <= last_col ; i++)
770 headers[i].x = headers[i-1].x + headers[i-1].width + ((i == new_col) ?
771 NEW_COL_SIZE_SLOP : 0) + HMARGIN;
772 }
773
774 void
775 _view::insert_pkg (Package *pkg)
776 {
777 pick_line line;
778 if (pkg->exclude)
779 return;
780 line.set_line (pkg);
781 if (view_mode != VIEW_CATEGORY)
782 {
783 if (lines == NULL)
784 {
785 lines = (pick_line *) calloc (npackages + ncategories,
786 sizeof (pick_line));
787 nlines = 0;
788 insert_at (0, line);
789 }
790 else
791 insert_under (0, line);
792 }
793 else
794 {
795 // assert (lines); /* protect against a coding change in future */
796 for (Category *cat = pkg->category; cat; cat = cat->next)
797 {
798 /* insert the package under this category in the list. If this category is not
799 visible, add it */
800 int n=0;
801 while (n < nlines)
802 {
803 /* this should be a generic call to list_sort_cmp */
804 if (lines[n].get_category ()
805 && cat->name == lines[n].get_category ()->name)
806 insert_under (n, line);
807 n++;
808 }
809 if (n == nlines)
810 {
811 /* the category wasn't visible - insert at the end */
812 insert_category (cat, CATEGORY_COLLAPSED);
813 insert_pkg (pkg);
814 }
815 }
816 }
817 }
818
819 void
820 _view::insert_category (Category *cat, int collapsed)
821 {
822 pick_line line;
823 line.set_line (cat);
824 if (lines == NULL)
825 {
826 lines = (pick_line *) malloc ((npackages + ncategories) * sizeof (pick_line));
827 memset (lines, '\0', (npackages + ncategories) * sizeof (pick_line) );
828 nlines = 0;
829 insert_at (0, line);
830 if (!collapsed)
831 for (CategoryPackage *catpkg = cat->packages; catpkg; catpkg = catpkg->next)
832 insert_pkg (getpkgbyname (catpkg->pkgname));
833 }
834 else
835 {
836 int n=0;
837 while (n < nlines)
838 {
839 /* this should be a generic call to list_sort_cmp */
840 if (lines[n].get_category ()
841 && strcasecmp (cat->name, lines[n].get_category ()->name) < 0)
842 {
843 insert_at (n, line);
844 if (!collapsed)
845 for (CategoryPackage *catpkg = cat->packages; catpkg; catpkg = catpkg->next)
846 insert_pkg (getpkgbyname (catpkg->pkgname));
847 n = nlines;
848 }
849 else if (lines[n].get_category () == cat)
850 n = nlines;
851 n++;
852
853 }
854 if (n == nlines)
855 {
856 /* insert at the end */
857 insert_at (n, line);
858 if (!collapsed)
859 for (CategoryPackage *catpkg = cat->packages; catpkg; catpkg = catpkg->next)
860 insert_pkg (getpkgbyname (catpkg->pkgname));
861 }
862 }
863 }
864
865 /* insert a new line at line n */
866 void
867 _view::insert_at (int n, pick_line line)
868 {
869 if (n < 0 || n > nlines)
870 return;
871 memmove (&lines[n + 1], &lines[n], (nlines - n) * sizeof (pick_line));
872 lines[n] = line;
873 nlines++;
874 }
875
876 /* insert a new line in the chooser, at the next depth in from linen */
877 void
878 _view::insert_under (int linen, pick_line line)
879 {
880 int n;
881 /* special case - empty view */
882 if (nlines == 0)
883 {
884 insert_at (0, line);
885 return;
886 }
887 /* part 1 - find the appropriate bucket beginning */
888 if (lines[linen].get_category ())
889 {
890 n = linen + 1;
891 }
892 else if (lines[linen].get_pkg ())
893 {
894 n = linen;
895 /* walk up to the beginning of the bucket */
896 while (n > 0 && lines[n - 1].get_pkg ())
897 n--;
898 }
899 /* part 2 - insert in sorted order in the bucket */
900 while (n < nlines)
901 {
902 if (lines[n].get_category () || (lines[n].get_pkg ()
903 && strcasecmp (line.get_pkg ()->name, lines[n].get_pkg ()->name) < 0))
904 {
905 insert_at (n, line);
906 n = nlines;
907 }
908 else if (lines[n].get_pkg () == line.get_pkg ())
909 {
910 n = nlines;
911 }
912 n++;
913 }
914 if (n == nlines)
915 {
916 /* insert at the end of this bucket */
917 insert_at (n, line);
918 }
919 }
920
921 void
922 _view::clear_view (void)
923 {
924 nlines = 0;
925 }
926
927 static views
928 viewsplusplus(views theview)
929 {
930 switch (theview)
931 {
932 case VIEW_UNKNOWN: return VIEW_PACKAGE_FULL;
933 case VIEW_PACKAGE_FULL: return VIEW_PACKAGE;
934 case VIEW_PACKAGE: return VIEW_CATEGORY;
935 case VIEW_CATEGORY: return NVIEW;
936 default: return VIEW_UNKNOWN;
937 }
938 }
939
940 int
941 _view::click (int row, int x)
942 {
943 if (row > nlines)
944 return 0;
945 if (lines[row].get_pkg ())
946 return lines[row].click (x);
947 else
948 {
949 /* if we are the last line or the next line is a category too, expand */
950 if (row == (nlines -1) || lines[row + 1].get_category ())
951 {
952 int count = nlines;
953 for (CategoryPackage *catpkg = lines[row].get_category ()->packages; catpkg; catpkg = catpkg->next)
954 {
955 Package * pkg = getpkgbyname (catpkg->pkgname);
956 int n = row + 1;
957 pick_line line;
958 line.set_line (pkg);
959 /* this is a nasty hack. It will go away when the hierarchy is coded */
960 while (n < nlines)
961 {
962 if (lines[n].get_category () || (lines[n].get_pkg ()
963 && strcasecmp (pkg->name, lines[n].get_pkg ()->name) < 0))
964 {
965 insert_at (n, line);
966 n = nlines;
967 }
968 else if (lines[n].get_pkg () == pkg)
969 {
970 n = nlines;
971 }
972 n++;
973 }
974 if (n == nlines)
975 {
976 /* insert at the end of this category */
977 insert_at (n, line);
978 n=nlines + 1;
979 }
980 }
981 return nlines - count;
982 }
983 else
984 /* contract */
985 {
986 int count = 0, n = row + 1;
987 while (n < nlines &! lines[n].get_category ())
988 {
989 memmove (&lines[n], &lines[n + 1], (nlines - n) * sizeof (pick_line));
990 nlines--;
991 count++;
992 }
993 return count;
994 }
995 }
996 }
997
998
999 static void
1000 set_view_mode (HWND h, views mode)
1001 {
1002 int i;
1003 chooser->set_view_mode (mode);
1004
1005 chooser->clear_view ();
1006 for (Package *pkg = package; pkg->name; pkg++)
1007 if (!pkg->exclude)
1008 set_action (pkg, 0);
1009
1010 switch (chooser->get_view_mode ())
1011 {
1012 case VIEW_PACKAGE:
1013 for (Package *pkg = package; pkg->name; pkg++)
1014 if (!pkg->exclude && !is_full_action (pkg))
1015 chooser->insert_pkg (pkg);
1016 break;
1017 case VIEW_PACKAGE_FULL:
1018 for (Package *pkg = package; pkg->name; pkg++)
1019 if (!pkg->exclude)
1020 chooser->insert_pkg (pkg);
1021 break;
1022 case VIEW_CATEGORY:
1023 /* start collapsed. TODO: make this a chooser flag */
1024 for (Category *cat = category; cat; cat = cat->next)
1025 chooser->insert_category (cat, CATEGORY_COLLAPSED);
1026 break;
1027 default:
1028 break;
1029 }
1030
1031 RECT r;
1032 GetClientRect (h, &r);
1033 SCROLLINFO si;
1034 memset (&si, 0, sizeof (si));
1035 si.cbSize = sizeof (si);
1036 si.fMask = SIF_ALL;
1037 si.nMin = 0;
1038 si.nMax = chooser->headers[chooser->last_col].x + chooser->headers[chooser->last_col].width + HMARGIN;
1039 si.nPage = r.right;
1040 SetScrollInfo (h, SB_HORZ, &si, TRUE);
1041
1042 si.nMax = chooser->nlines * row_height;
1043 si.nPage = r.bottom - header_height;
1044 SetScrollInfo (h, SB_VERT, &si, TRUE);
1045
1046 scroll_ulc_x = scroll_ulc_y = 0;
1047
1048 InvalidateRect (h, &r, TRUE);
1049
1050 if (nextbutton)
1051 SetFocus (nextbutton);
1052 }
1053
1054 static void
1055 create_listview (HWND dlg, RECT *r)
1056 {
1057 int i, t;
1058 lv = CreateWindowEx (WS_EX_CLIENTEDGE,
1059 "listview",
1060 "listviewwindow",
1061 WS_CHILD | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE,
1062 r->left, r->top,
1063 r->right-r->left + 1, r->bottom-r->top + 1,
1064 dlg,
1065 (HMENU) MAKEINTRESOURCE(IDC_CHOOSE_LIST),
1066 hinstance,
1067 0);
1068 ShowWindow (lv, SW_SHOW);
1069 HDC dc = GetDC (lv);
1070 sysfont = GetStockObject (DEFAULT_GUI_FONT);
1071 SelectObject (dc, sysfont);
1072 GetTextMetrics (dc, &tm);
1073 header_height = tm.tmHeight + 5 + 3;
1074
1075 bitmap_dc = CreateCompatibleDC (dc);
1076
1077 row_height = (tm.tmHeight + tm.tmExternalLeading + ROW_MARGIN);
1078 int irh = tm.tmExternalLeading + tm.tmDescent + 11 + ROW_MARGIN;
1079 if (row_height < irh)
1080 row_height = irh;
1081
1082 chooser = new (view) (VIEW_CATEGORY, dc);
1083
1084 default_trust (lv, TRUST_CURR);
1085 set_view_mode (lv, VIEW_CATEGORY);
1086 if (!SetDlgItemText (dlg, IDC_CHOOSE_VIEWCAPTION, chooser->mode_caption()))
1087 log (LOG_BABBLE, "Failed to set View button caption %d", GetLastError() );
1088 for (Package *foo = package; foo->name; foo++)
1089 add_required(foo);
1090 static int ta[] = { IDC_CHOOSE_CURR, 0 };
1091 rbset (dlg, ta, IDC_CHOOSE_CURR);
1092
1093 ReleaseDC (lv, dc);
1094 }
1095
1096 static BOOL
1097 dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
1098 {
1099 switch (id)
1100 {
1101 case IDC_CHOOSE_PREV:
1102 default_trust (lv, TRUST_PREV);
1103 for (Package *foo = package; foo->name; foo++)
1104 add_required(foo);
1105 set_view_mode (lv, chooser->get_view_mode ());
1106 break;
1107 case IDC_CHOOSE_CURR:
1108 default_trust (lv, TRUST_CURR);
1109 for (Package *foo = package; foo->name; foo++)
1110 add_required(foo);
1111 set_view_mode (lv, chooser->get_view_mode ());
1112 break;
1113 case IDC_CHOOSE_EXP:
1114 default_trust (lv, TRUST_TEST);
1115 for (Package *foo = package; foo->name; foo++)
1116 add_required(foo);
1117 set_view_mode (lv, chooser->get_view_mode ());
1118 break;
1119 case IDC_CHOOSE_VIEW:
1120 set_view_mode (lv, viewsplusplus (chooser->get_view_mode ()));
1121 if (!SetDlgItemText (h, IDC_CHOOSE_VIEWCAPTION, chooser->mode_caption()))
1122 log (LOG_BABBLE, "Failed to set View button caption %d", GetLastError() );
1123 break;
1124
1125 case IDOK:
1126 if (source == IDC_SOURCE_CWD)
1127 NEXT (IDD_S_INSTALL);
1128 else
1129 NEXT (IDD_S_DOWNLOAD);
1130 break;
1131
1132 case IDC_BACK:
1133 initialized = 0;
1134 if (source == IDC_SOURCE_CWD)
1135 NEXT (IDD_ROOT);
1136 else
1137 NEXT (IDD_SITE);
1138 break;
1139
1140 case IDCANCEL:
1141 NEXT (0);
1142 break;
1143 }
1144 }
1145
1146 static void
1147 GetParentRect (HWND parent, HWND child, RECT *r)
1148 {
1149 POINT p;
1150 GetWindowRect (child, r);
1151 p.x = r->left;
1152 p.y = r->top;
1153 ScreenToClient (parent, &p);
1154 r->left = p.x;
1155 r->top = p.y;
1156 p.x = r->right;
1157 p.y = r->bottom;
1158 ScreenToClient (parent, &p);
1159 r->right = p.x;
1160 r->bottom = p.y;
1161 }
1162
1163 static BOOL CALLBACK
1164 dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
1165 {
1166 int i, j;
1167 HWND frame;
1168 RECT r;
1169 switch (message)
1170 {
1171 case WM_INITDIALOG:
1172 nextbutton = GetDlgItem (h, IDOK);
1173 frame = GetDlgItem (h, IDC_LISTVIEW_POS);
1174 choose_inst_text = GetDlgItem(h,IDC_CHOOSE_INST_TEXT);
1175 if (source == IDC_SOURCE_DOWNLOAD)
1176 SetWindowText (choose_inst_text, "Select packages to download ");
1177 else
1178 SetWindowText (choose_inst_text, "Select packages to install ");
1179 GetParentRect (h, frame, &r);
1180 r.top += 2;
1181 r.bottom -= 2;
1182 create_listview (h, &r);
1183 #if 0
1184 load_dialog (h);
1185 #endif
1186 return FALSE;
1187 case WM_COMMAND:
1188 return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
1189 }
1190 return FALSE;
1191 }
1192
1193 char *
1194 base (const char *s)
1195 {
1196 if (!s)
1197 return 0;
1198 const char *rv = s;
1199 while (*s)
1200 {
1201 if ((*s == '/' || *s == ':' || *s == '\\') && s[1])
1202 rv = s + 1;
1203 s++;
1204 }
1205 return (char *) rv;
1206 }
1207
1208 int
1209 find_tar_ext (const char *path)
1210 {
1211 char *p = strchr (path, '\0') - 7;
1212 if (p <= path)
1213 return 0;
1214 if (*p == '.')
1215 {
1216 if (strcmp (p, ".tar.gz") != 0)
1217 return 0;
1218 }
1219 else if (--p <= path || strcmp (p, ".tar.bz2") != 0)
1220 return 0;
1221
1222 return p - path;
1223 }
1224
1225 /* Parse a filename into package, version, and extension components. */
1226 int
1227 parse_filename (const char *in_fn, fileparse& f)
1228 {
1229 char *p, *ver;
1230 char fn[strlen (in_fn) + 1];
1231
1232 strcpy (fn, in_fn);
1233 int n = find_tar_ext (fn);
1234
1235 if (!n)
1236 return 0;
1237
1238 strcpy (f.tail, fn + n);
1239 fn[n] = '\0';
1240 f.pkg[0] = f.what[0] = '\0';
1241 p = base (fn);
1242 for (ver = p; *ver; ver++)
1243 if (*ver == '-' || *ver == '_')
1244 if (isdigit (ver[1]))
1245 {
1246 *ver++ = 0;
1247 strcpy (f.pkg, p);
1248 break;
1249 }
1250 else if (strcasecmp (ver, "-src") == 0 ||
1251 strcasecmp (ver, "-patch") == 0)
1252 {
1253 *ver++ = 0;
1254 strcpy (f.pkg, p);
1255 strcpy (f.what, strlwr (ver));
1256 strcpy (f.pkgtar, p);
1257 strcat (f.pkgtar, f.tail);
1258 ver = strchr (ver, '\0');
1259 break;
1260 }
1261
1262 if (!f.pkg[0])
1263 strcpy (f.pkg, p);
1264
1265 if (!f.what[0])
1266 {
1267 p = strchr (ver, '\0');
1268 strcpy (f.pkgtar, in_fn);
1269 if ((p -= 4) >= ver && strcasecmp (p, "-src") == 0)
1270 {
1271 strcpy (f.what, "src");
1272 *p = '\0';
1273 p = f.pkgtar + (p - fn) + 4;
1274 memcpy (p - 4, p, strlen (p));
1275 }
1276 else if ((p -= 2) >= ver && strcasecmp (p, "-patch") == 0)
1277 {
1278 strcpy (f.what, "patch");
1279 *p = '\0';
1280 p = f.pkgtar + (p - fn) + 6;
1281 memcpy (p - 6, p, strlen (p));
1282 }
1283 }
1284
1285 strcpy (f.ver, *ver ? ver : "0.0");
1286 return 1;
1287 }
1288
1289 /* Return a pointer to a package given the name. */
1290 Package *
1291 getpkgbyname (const char *pkgname)
1292 {
1293 for (Package *pkg = package; pkg->name; pkg++)
1294 if (strcasecmp (pkg->name, pkgname) == 0)
1295 return pkg;
1296
1297 return NULL;
1298 }
1299
1300 /* Return a pointer to a category given the name. */
1301 Category *
1302 getcategorybyname (const char *categoryname)
1303 {
1304 for (Category *cat = category; cat; cat=cat->next)
1305 if (strcasecmp (cat->name, categoryname) == 0)
1306 return cat;
1307
1308 return NULL;
1309 }
1310
1311 /* Return a pointer to a category of a given package given the name. */
1312 Category *
1313 getpackagecategorybyname (Package *pkg, const char *categoryname)
1314 {
1315 for (Category *cat = pkg->category; cat; cat = cat->next)
1316 if (strcasecmp (cat->name, categoryname) == 0)
1317 return cat;
1318
1319 return NULL;
1320 }
1321
1322 /* Find out where to put existing tar file in local directory in
1323 known package array. */
1324 static void
1325 scan2 (char *path, unsigned int size)
1326 {
1327 Package *pkg;
1328 fileparse f;
1329
1330 if (!parse_filename (path, f))
1331 return;
1332
1333 if (f.what[0] != '\0' && f.what[0] != 's')
1334 return;
1335
1336 pkg = getpkgbyname (f.pkg);
1337 if (pkg == NULL)
1338 return;
1339
1340 /* Scan existing package list looking for a match between a known
1341 package from setup.ini and a tar archive on disk.
1342 While scanning, keep track of appropriate "holes" in the trust
1343 table where a tar file could be put if no known entry
1344 exists.
1345
1346 So, if setup.ini knows that ash-20010425-1.tar.gz is the current
1347 version and there is an ash-20010426-1.tar.gz in the current directory,
1348 the 20010426 version will be placed in the "test" slot, assuming that
1349 there is no test version listed in setup.ini. */
1350
1351 Info *hole = NULL;
1352 Info *maybe_hole = NULL;
1353 int cmp = 0;
1354 for (Info *inf = pkg->infoscan; inf < pkg->infoend; inf++)
1355 if (!inf->version || inf->derived)
1356 {
1357 if (cmp > 0)
1358 hole = inf;
1359 else if (cmp == 0)
1360 maybe_hole = inf;
1361 }
1362 else if ((cmp = strcasecmp (f.ver, inf->version)) == 0)
1363 {
1364 if (f.what[0] == 's')
1365 inf->source_exists = -1;
1366 else
1367 inf->install_exists = -1;
1368 return;
1369 }
1370 else if (!hole && maybe_hole && cmp < 0)
1371 hole = maybe_hole;
1372 else
1373 maybe_hole = NULL;
1374
1375 /* If maybe_hole != NULL, then we should be sitting at the "test"
1376 trust entry. Use that if there was nothing at all in the
1377 known package list. */
1378 if (!hole && maybe_hole)
1379 hole = maybe_hole;
1380
1381 /* If !hole, we didn't find this version in the known packages array
1382 and there was no place to put it. */
1383 if (!hole)
1384 return;
1385
1386 /* The derived flag is set when we place info about a file in a slot
1387 iff there was nothing known about the file in the known package
1388 array. We try to put the highest numbered versions in the "empty"
1389 slots. */
1390 if (hole->derived)
1391 {
1392 cmp = strcasecmp (f.ver, hole->version) < 0;
1393 if (cmp < 0)
1394 return;
1395
1396 if (cmp > 0)
1397 {
1398 free (hole->version);
1399 if (hole->source)
1400 free (hole->source);
1401 else
1402 free (hole->install);
1403 }
1404 }
1405
1406 /* Fill in the "hole", setting a flag that we derived this location
1407 from context rather than from setup.ini. */
1408 hole->derived = 1;
1409 hole->version = strdup (f.ver);
1410 if (!hole->source && f.what[0] == 's')
1411 {
1412 hole->source = strdup (path);
1413 hole->source_exists = -1;
1414 hole->source_size = size;
1415 }
1416 else
1417 {
1418 hole->install = strdup (path);
1419 hole->install_exists = -1;
1420 hole->install_size = size;
1421 }
1422 }
1423
1424 static void
1425 scan_downloaded_files ()
1426 {
1427 find (".", scan2);
1428 }
1429
1430 _Info::_Info (const char *_install, const char *_version, int _install_size,
1431 const char *_source, int _source_size)
1432 {
1433 memset (this, 0, sizeof (*this));
1434 install = strdup (_install);
1435 version = strdup (_version);
1436 install_size = _install_size;
1437 if (_source)
1438 {
1439 source = strdup (_source);
1440 source_size = _source_size;
1441 }
1442 }
1443
1444 static void
1445 read_installed_db ()
1446 {
1447 int i;
1448 if (!get_root_dir ())
1449 return;
1450
1451 char line[1000], pkgname[1000], inst[1000], src[1000];
1452 int instsz, srcsz;
1453
1454 FILE *db = fopen (cygpath ("/etc/setup/installed.db", 0), "rt");
1455 if (!db)
1456 return;
1457
1458 while (fgets (line, 1000, db))
1459 {
1460 int parseable;
1461 src[0] = 0;
1462 srcsz = 0;
1463 sscanf (line, "%s %s %d %s %d", pkgname, inst, &instsz, src, &srcsz);
1464
1465 Package *pkg = getpkgbyname (pkgname);
1466 fileparse f;
1467 parseable = parse_filename (inst, f);
1468
1469 if (pkg == NULL)
1470 {
1471 if (!parseable)
1472 continue;
1473 pkg = new_package (pkgname);
1474 pkg->info[TRUST_CURR].version = strdup (f.ver);
1475 pkg->info[TRUST_CURR].install = strdup (inst);
1476 pkg->info[TRUST_CURR].install_size = instsz;
1477 if (src && srcsz)
1478 {
1479 pkg->info[TRUST_CURR].source = strdup (src);
1480 pkg->info[TRUST_CURR].source_size = srcsz;
1481 }
1482 pkg->installed_ix = TRUST_CURR;
1483 /* Exists on local system but not on download system */
1484 pkg->exclude = EXCLUDE_NOT_FOUND;
1485 }
1486
1487 pkg->installed = new Info (inst, f.ver, instsz);
1488
1489 if (!pkg->installed_ix)
1490 for (trusts t = TRUST_PREV; t < NTRUST; ((int) t)++)
1491 if (pkg->info[t].install && strcmp (f.ver, pkg->info[t].version) == 0)
1492 {
1493 pkg->installed_ix = t;
1494 break;
1495 }
1496 }
1497 fclose (db);
1498 }
1499
1500 int
1501 package_sort (const void *va, const void *vb)
1502 {
1503 Package *a = (Package *)va;
1504 Package *b = (Package *)vb;
1505 return strcasecmp (a->name, b->name);
1506 }
1507
1508 void
1509 do_choose (HINSTANCE h)
1510 {
1511 int rv;
1512
1513 nextbutton = 0;
1514 bm_spin = LoadImage (h, MAKEINTRESOURCE (IDB_SPIN), IMAGE_BITMAP, 0, 0, 0);
1515 bm_rtarrow = LoadImage (h, MAKEINTRESOURCE (IDB_RTARROW), IMAGE_BITMAP,
1516 0, 0, 0);
1517
1518 bm_checkyes = LoadImage (h, MAKEINTRESOURCE (IDB_CHECK_YES), IMAGE_BITMAP,
1519 0, 0, 0);
1520 bm_checkno = LoadImage (h, MAKEINTRESOURCE (IDB_CHECK_NO), IMAGE_BITMAP,
1521 0, 0, 0);
1522 bm_checkna = LoadImage (h, MAKEINTRESOURCE (IDB_CHECK_NA), IMAGE_BITMAP,
1523 0, 0, 0);
1524
1525 register_windows (h);
1526
1527 if (source == IDC_SOURCE_DOWNLOAD || source == IDC_SOURCE_CWD)
1528 scan_downloaded_files ();
1529
1530 read_installed_db ();
1531 set_existence ();
1532 fill_missing_category ();
1533
1534 qsort (package, npackages, sizeof (package[0]), package_sort);
1535
1536 rv = DialogBox (h, MAKEINTRESOURCE (IDD_CHOOSE), 0, dialog_proc);
1537 if (rv == -1)
1538 fatal (IDS_DIALOG_FAILED);
1539
1540 log (LOG_BABBLE, "Chooser results...");
1541 for (Package *pkg = package; pkg->name; pkg++)
1542 {
1543 static char *infos[] = {"nada", "prev", "curr", "test"};
1544 const char *trust = ((pkg->trust == TRUST_PREV) ? "prev"
1545 : (pkg->trust == TRUST_CURR) ? "curr"
1546 : (pkg->trust == TRUST_TEST) ? "test"
1547 : "unknown");
1548 const char *action = choose_caption (pkg);
1549 const char *installed = ((pkg->installed_ix == -1) ? "none"
1550 : (pkg->installed_ix == TRUST_PREV) ? "prev"
1551 : (pkg->installed_ix == TRUST_CURR) ? "curr"
1552 : (pkg->installed_ix == TRUST_TEST) ? "test"
1553 : "unknown");
1554 const char *excluded = (pkg->exclude ? "yes" : "no");
1555
1556 log (LOG_BABBLE, "[%s] action=%s trust=%s installed=%s excluded=%s"
1557 " src?=%s",
1558 pkg->name, action, trust, installed, excluded,
1559 pkg->srcpicked ? "yes" : "no");
1560 if (pkg->category)
1561 {
1562 /* List categories the package belongs to */
1563 char *categories = "";
1564 int categories_len = 0;
1565 Category *cp;
1566 for (cp = pkg->category; cp; cp = cp->next)
1567 if (cp->name)
1568 categories_len += strlen (cp->name) + 2;
1569
1570 if (categories_len > 0)
1571 {
1572 categories = (char *) malloc (categories_len);
1573 strcpy(categories, pkg->category->name);
1574 for (cp = pkg->category->next; cp; cp = cp->next)
1575 if (cp->name)
1576 {
1577 strcat (categories, ", ");
1578 strcat (categories, cp->name);
1579 }
1580 log (LOG_BABBLE, " categories=%s", categories);
1581 free (categories);
1582 }
1583 }
1584 if (pkg->required)
1585 {
1586 /* List other packages this package depends on */
1587 char *requires = "";
1588 int requires_len = 0;
1589 Dependency *dp;
1590 for (dp = pkg->required; dp; dp = dp->next)
1591 if (dp->package)
1592 requires_len += strlen (dp->package) + 2;
1593
1594 if (requires_len > 0)
1595 {
1596 requires = (char *) malloc (requires_len);
1597 strcpy(requires, pkg->required->package);
1598 for (dp = pkg->required->next; dp; dp = dp->next)
1599 if (dp->package)
1600 {
1601 strcat (requires, ", ");
1602 strcat (requires, dp->package);
1603 }
1604 log (LOG_BABBLE, " requires=%s", requires);
1605 free (requires);
1606 }
1607 }
1608
1609 for (int t = 1; t < NTRUST; t++)
1610 {
1611 if (pkg->info[t].install)
1612 log (LOG_BABBLE, " [%s] ver=%s\n"
1613 " inst=%s %d exists=%s\n"
1614 " src=%s %d exists=%s",
1615 infos[t],
1616 pkg->info[t].version ?: "(none)",
1617 pkg->info[t].install ?: "(none)",
1618 pkg->info[t].install_size,
1619 (pkg->info[t].install_exists) ? "yes" : "no",
1620 pkg->info[t].source ?: "(none)",
1621 pkg->info[t].source_size,
1622 (pkg->info[t].source_exists) ? "yes" : "no");
1623 }
1624 }
1625 }
This page took 0.183326 seconds and 4 git commands to generate.