(U-00020E60): Use `->denotational' and `->subsumptive'.
[chise/xemacs-chise.git.1] / netinstall / choose.cc
1 /*
2  * Copyright (c) 2000, 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 #include "win32.h"
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32
33 #include "dialog.h"
34 #include "resource.h"
35 #include "state.h"
36 #include "ini.h"
37 #include "concat.h"
38 #include "msg.h"
39 #include "log.h"
40 #include "find.h"
41 #include "reginfo.h"
42
43 #define HMARGIN         10
44 #define ROW_MARGIN      5
45 #define ICON_MARGIN     4
46
47 #define CHECK_SIZE      11
48
49 #define TRUST_KEEP      101
50 #define TRUST_UNINSTALL 102
51 #define TRUST_NONE      103
52
53 static int initialized = 0;
54
55 static int full_list = 0;
56
57 static int scroll_ulc_x, scroll_ulc_y;
58
59 static HWND lv, nextbutton;
60 static TEXTMETRIC tm;
61 static int header_height;
62 static HANDLE sysfont;
63 static int row_height;
64 static HANDLE bm_spin, bm_rtarrow, bm_checkyes, bm_checkno, bm_checkna;
65 static HDC bitmap_dc;
66
67 static struct {
68   char *text;
69   int slen;
70   int width;
71   int x;
72 } headers[] = {
73   { "Current", 7, 0, 0 },
74 #define CURRENT_COL 0
75   { "New", 3, 0, 0 },
76 #define NEW_COL 1
77   { "Src?", 4, 0, 0 },
78 #define SRC_COL 2
79   { "Package", 7, 0, 0 },
80 #define PACKAGE_COL 3
81   { 0, 0, 0, 0 }
82 };
83 #define NUM_COLUMNS (sizeof(headers)/(sizeof(headers[0]))-1)
84
85 int *package_indexes, nindexes;
86
87 struct ExtraPackageInfo {
88   char *installed_file; /* filename of previous "install" file */
89   char *installed_ver;  /* version part */
90   int   installed_size; /* ditto, size. */
91
92   int in_partial_list;
93   int pick;
94   int npick;
95   int which_is_installed; /* == TRUST* or -1 */
96
97   struct {
98     int src_avail;
99     int trust;          /* may be keep or uninstall */
100     char *caption;      /* ==0 at EOL */
101   } chooser[NTRUST+3];  /* one extra for NULL above */
102 };
103
104 static ExtraPackageInfo *extra;
105
106 static void
107 paint (HWND hwnd)
108 {
109   HDC hdc;
110   PAINTSTRUCT ps;
111   int x, y, i, ii;
112
113   hdc = BeginPaint (hwnd, &ps);
114
115   SelectObject (hdc, sysfont);
116
117   RECT cr;
118   GetClientRect (hwnd, &cr);
119
120   POINT p;
121
122   x = cr.left - scroll_ulc_x;
123   y = cr.top - scroll_ulc_y + header_height;
124
125
126   for (i=0; headers[i].text; i++)
127     {
128       TextOut (hdc, x+headers[i].x, 3, headers[i].text, headers[i].slen);
129       MoveToEx (hdc, x+headers[i].x, header_height-3, &p);
130       LineTo (hdc, x+headers[i].x+headers[i].width, header_height-3);
131     }
132
133   IntersectClipRect (hdc, cr.left, cr.top+header_height, cr.right, cr.bottom);
134
135   for (ii=0; ii<nindexes; ii++)
136     {
137       i = package_indexes[ii];
138       int r = y + ii * row_height;
139       int by = r + tm.tmHeight - 11;
140       if (extra[i].installed_ver && extra[i].installed_ver[0])
141         {
142           TextOut (hdc, x+headers[CURRENT_COL].x, r,
143                    extra[i].installed_ver, strlen (extra[i].installed_ver));
144           SelectObject (bitmap_dc, bm_rtarrow);
145           BitBlt (hdc, x+headers[CURRENT_COL].x+headers[0].width+ICON_MARGIN/2+HMARGIN/2, by,
146                   11, 11, bitmap_dc, 0, 0, SRCCOPY);
147         }
148
149       char *s = extra[i].chooser[extra[i].pick].caption;
150       if (s)
151         {
152           TextOut (hdc, x+headers[NEW_COL].x + 11 + ICON_MARGIN, r,
153                    s, strlen (s));
154           if (extra[i].npick > 1)
155             {
156               SelectObject (bitmap_dc, bm_spin);
157               BitBlt (hdc, x+headers[NEW_COL].x, by, 11, 11,
158                       bitmap_dc, 0, 0, SRCCOPY);
159             }
160         }
161
162       HANDLE check_bm = bm_checkna;
163       if (extra[i].chooser[extra[i].pick].src_avail)
164         {
165           if (package[i].srcaction == SRCACTION_NO)
166             check_bm = bm_checkno;
167           else if (package[i].srcaction == SRCACTION_YES)
168             check_bm = bm_checkyes;
169         }
170       SelectObject (bitmap_dc, check_bm);
171       BitBlt (hdc, x+headers[SRC_COL].x, by, 11, 11,
172               bitmap_dc, 0, 0, SRCCOPY);
173
174       if (package[i].name)
175         TextOut (hdc, x+headers[PACKAGE_COL].x, r, package[i].name, strlen(package[i].name));
176     }
177
178   if (nindexes == 0)
179     {
180       static char *m = "Nothing to Install/Update";
181       TextOut (hdc, HMARGIN, header_height, m, strlen (m));
182     }
183   
184   EndPaint (hwnd, &ps);
185 }
186
187 static void
188 scroll_common (HWND hwnd, int which, int *var, int code)
189 {
190   SCROLLINFO si;
191   si.cbSize = sizeof (si);
192   si.fMask = SIF_ALL;
193   GetScrollInfo (hwnd, which, &si);
194
195   switch (code)
196     {
197     case SB_THUMBTRACK:
198       si.nPos = si.nTrackPos;
199       break;
200     case SB_THUMBPOSITION:
201       break;
202     case SB_BOTTOM:
203       si.nPos = si.nMax;
204       break;
205     case SB_TOP:
206       si.nPos = 0;
207       break;
208     case SB_LINEDOWN:
209       si.nPos += row_height;
210       break;
211     case SB_LINEUP:
212       si.nPos -= row_height;
213       break;
214     case SB_PAGEDOWN:
215       si.nPos += si.nPage * 9/10;
216       break;
217     case SB_PAGEUP:
218       si.nPos -= si.nPage * 9/10;
219       break;
220     }
221
222   if ((int)si.nPos < 0)
223     si.nPos = 0;
224   if ((int)(si.nPos + si.nPage) > si.nMax)
225     si.nPos = si.nMax - si.nPage;
226
227   si.fMask = SIF_POS;
228   SetScrollInfo (hwnd, which, &si, TRUE);
229
230   int ox = scroll_ulc_x;
231   int oy = scroll_ulc_y;
232   *var = si.nPos;
233
234   RECT cr, sr;
235   GetClientRect (hwnd, &cr);
236   sr = cr;
237   sr.top += header_height;
238   ScrollWindow (hwnd, ox - scroll_ulc_x, oy - scroll_ulc_y, &sr, &sr);
239   sr.bottom = sr.top;
240   sr.top = cr.top;
241   ScrollWindow (hwnd, ox - scroll_ulc_x, 0, &sr, &sr);
242 }
243
244 static LRESULT CALLBACK
245 list_vscroll (HWND hwnd, HWND hctl, UINT code, int pos)
246 {
247   scroll_common (hwnd, SB_VERT, &scroll_ulc_y, code);
248   return FALSE;
249 }
250
251 static LRESULT CALLBACK
252 list_hscroll (HWND hwnd, HWND hctl, UINT code, int pos)
253 {
254   scroll_common (hwnd, SB_HORZ, &scroll_ulc_x, code);
255   return FALSE;
256 }
257
258 static LRESULT CALLBACK
259 list_click (HWND hwnd, BOOL dblclk, int x, int y, UINT hitCode)
260 {
261   int r;
262
263   if (nindexes == 0)
264     return 0;
265
266   if (y < header_height)
267     return 0;
268   x += scroll_ulc_x;
269   y += scroll_ulc_y - header_height;
270
271   r = (y + ROW_MARGIN/2) / row_height;
272
273   if (r < 0 || r >= npackages)
274     return 0;
275
276   int p = package_indexes[r];
277
278   if (x >= headers[NEW_COL].x - HMARGIN/2 && x <= headers[NEW_COL+1].x - HMARGIN/2)
279     {
280       extra[p].pick ++;
281       if (extra[p].chooser[extra[p].pick].caption == 0)
282         extra[p].pick = 0;
283     }
284
285   if (x >= headers[SRC_COL].x - HMARGIN/2 && x <= headers[SRC_COL+1].x - HMARGIN/2)
286     {
287       if (extra[p].chooser[extra[p].pick].src_avail)
288         package[p].srcaction ^= (SRCACTION_NO^SRCACTION_YES);
289     }
290
291   RECT rect;
292   rect.left = headers[NEW_COL].x - scroll_ulc_x;
293   rect.right = headers[SRC_COL+1].x - scroll_ulc_x;
294   rect.top = header_height + r * row_height - scroll_ulc_y;
295   rect.bottom = rect.top + row_height;
296   InvalidateRect (hwnd, &rect, TRUE);
297   return FALSE;
298 }
299
300 static LRESULT CALLBACK
301 listview_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
302 {
303   switch (message) {
304   case WM_HSCROLL:
305     return HANDLE_WM_HSCROLL (hwnd, wParam, lParam, list_hscroll);
306   case WM_VSCROLL:
307     return HANDLE_WM_VSCROLL (hwnd, wParam, lParam, list_vscroll);
308   case WM_LBUTTONDOWN:
309     return HANDLE_WM_LBUTTONDOWN (hwnd, wParam, lParam, list_click);
310   case WM_PAINT:
311     paint (hwnd);
312     return 0;
313   default:
314     return DefWindowProc (hwnd, message, wParam, lParam);
315   }
316 }
317
318 static void
319 register_windows (HINSTANCE hinst)
320 {
321   WNDCLASSEX wcex;
322   static int done = 0;
323
324   if (done)
325     return;
326   done = 1;
327
328   memset (&wcex, 0, sizeof (wcex));
329   wcex.cbSize = sizeof (WNDCLASSEX);
330   wcex.style = CS_HREDRAW | CS_VREDRAW;
331   wcex.lpfnWndProc = listview_proc;
332   wcex.hInstance = hinst;
333   wcex.hIcon = LoadIcon (0, IDI_APPLICATION);
334   wcex.hCursor = LoadCursor (0, IDC_ARROW);
335   wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
336   wcex.lpszClassName = "listview";
337
338   RegisterClassEx (&wcex);
339 }
340
341 static void
342 note_width (HDC dc, char *string, int addend, int column)
343 {
344   if (!string)
345     return;
346   SIZE s;
347   GetTextExtentPoint32 (dc, string, strlen (string), &s);
348   if (headers[column].width < s.cx + addend)
349     headers[column].width = s.cx + addend;
350 }
351
352 static int
353 best_trust (int p, int trust)
354 {
355   int t;
356   for (t=trust; t>=0; t--)
357     if (package[p].info[t].install)
358       return t;
359   for (t=trust+1; t<=NTRUST; t++)
360     if (package[p].info[t].install)
361       return t;
362   if (extra[p].installed_file)
363     return TRUST_KEEP;
364   return TRUST_NONE;
365 }
366
367 static void
368 default_trust (HWND h, int trust)
369 {
370   int i, t, c;
371
372   for (i=0; i<npackages; i++)
373     {
374       t = best_trust (i, trust);
375       extra[i].pick = 1;
376       for (c=0; c<extra[i].npick; c++)
377         if (t == extra[i].chooser[c].trust)
378           extra[i].pick = c;
379       if (install_type == IDC_INSTALL_NATIVE 
380           && package[i].type == TY_CYGWIN
381           ||
382           install_type == IDC_INSTALL_CYGWIN 
383           && package[i].type == TY_NATIVE)
384         extra[i].pick = extra[i].npick -1;
385     }
386   RECT r;
387   GetClientRect (h, &r);
388   InvalidateRect (h, &r, TRUE);
389   if (nextbutton)
390     SetFocus (nextbutton);
391 }
392
393 static void
394 set_full_list (HWND h, int isfull)
395 {
396   int i, j;
397   full_list = isfull;
398   if (package_indexes == 0)
399     package_indexes = (int *) malloc (npackages * sizeof (int));
400   for (i=j=0; i<npackages; i++)
401     {
402       if (isfull || extra[i].in_partial_list)
403         package_indexes[j++] = i;
404     }
405   nindexes = j;
406
407   RECT r;
408   GetClientRect (h, &r);
409   SCROLLINFO si;
410   memset (&si, 0, sizeof (si));
411   si.cbSize = sizeof (si);
412   si.fMask = SIF_ALL;
413   si.nMin = 0;
414   si.nMax = headers[2].x + headers[2].width + HMARGIN;
415   si.nPage = r.right;
416   SetScrollInfo (h, SB_HORZ, &si, TRUE);
417
418   si.nMax = nindexes * row_height;
419   si.nPage = r.bottom - header_height;
420   SetScrollInfo (h, SB_VERT, &si, TRUE);
421
422   scroll_ulc_x = scroll_ulc_y = 0;
423
424   InvalidateRect (h, &r, TRUE);
425
426   if (nextbutton)
427     SetFocus (nextbutton);
428 }
429
430 static void
431 build_labels ()
432 {
433   int i;
434   for (i=0; i<npackages; i++)
435     {
436       int c = 0, t;
437
438 #define C extra[i].chooser[c]
439       if (extra[i].installed_ver)
440         {
441           C.caption = "Uninstall";
442           C.trust = TRUST_UNINSTALL;
443           c++;
444           C.caption = "Keep";
445           C.trust = TRUST_KEEP;
446           c++;
447         }
448
449       for (t=TRUST_PREV; t<NTRUST; t++)
450         if (package[i].info[t].install)
451           if (t != extra[i].which_is_installed)
452             {
453               C.caption = package[i].info[t].version;
454               if (C.caption == 0 || C.caption[0] == 0)
455                 C.caption = "0.0";
456               C.trust = t;
457               if (package[i].info[t].source)
458                 C.src_avail = 1;
459               c++;
460               /* we intentionally skip TRUST_PREV */
461               if (t != TRUST_PREV || !extra[i].installed_ver)
462                 extra[i].in_partial_list = 1;
463
464             }
465
466       if (c == 0)
467         {
468           C.caption = "N/A";
469           C.trust = TRUST_NONE;
470           c++;
471         }
472
473       if (! extra[i].installed_file)
474         {
475           C.caption = "Skip";
476           C.trust = TRUST_NONE;
477           c++;
478         }
479
480       C.caption = 0;
481       extra[i].npick = c;
482 #undef C
483     }
484 }
485
486 static void
487 create_listview (HWND dlg, RECT *r)
488 {
489   int i, t;
490   lv = CreateWindowEx (WS_EX_CLIENTEDGE,
491                        "listview",
492                        "listviewwindow",
493                        WS_CHILD | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE,
494                        r->left, r->top,
495                        r->right-r->left+1, r->bottom-r->top+1,
496                        dlg,
497                        NULL, // ??? MAKEINTRESOURCE(IDC_CHOOSE_LIST),
498                        hinstance,
499                        0);
500   ShowWindow (lv, SW_SHOW);
501
502   for (i=0; headers[i].text; i++)
503     headers[i].width = 0;
504
505   HDC dc = GetDC (lv);
506   sysfont = GetStockObject (DEFAULT_GUI_FONT);
507   SelectObject (dc, sysfont);
508   GetTextMetrics (dc, &tm);
509   header_height = tm.tmHeight + 5 + 3;
510
511   bitmap_dc = CreateCompatibleDC (dc);
512
513   row_height = (tm.tmHeight + tm.tmExternalLeading + ROW_MARGIN);
514   int irh = tm.tmExternalLeading + tm.tmDescent + 11 + ROW_MARGIN;
515   if (row_height < irh)
516     row_height = irh;
517
518   for (i=0; headers[i].text; i++)
519     note_width (dc, headers[i].text, 0, i);
520   for (i=0; i<npackages; i++)
521     {
522       note_width (dc, extra[i].installed_ver, 0, CURRENT_COL);
523       note_width (dc, extra[i].installed_ver, 11+ICON_MARGIN, NEW_COL);
524       for (t=0; t<NTRUST; t++)
525         note_width (dc, package[i].info[t].version, 11+ICON_MARGIN, NEW_COL);
526       note_width (dc, package[i].name, 0, PACKAGE_COL);
527       note_width (dc, package[i].sdesc, 0, PACKAGE_COL);
528     }
529   note_width (dc, "keep", 11+ICON_MARGIN, NEW_COL);
530   note_width (dc, "uninstall", 11+ICON_MARGIN, NEW_COL);
531
532   headers[CURRENT_COL].x = HMARGIN/2;
533   headers[NEW_COL].x = (headers[CURRENT_COL].x + headers[CURRENT_COL].width
534                         + HMARGIN + 11 + ICON_MARGIN);
535   headers[SRC_COL].x = headers[NEW_COL].x + headers[NEW_COL].width + HMARGIN;
536   headers[PACKAGE_COL].x = headers[SRC_COL].x + headers[SRC_COL].width + HMARGIN;
537
538   set_full_list (lv, full_list);
539   default_trust (lv, TRUST_CURR);
540
541   ReleaseDC (lv, dc);
542 }
543
544 static BOOL
545 dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
546 {
547   switch (id)
548     {
549
550     case IDC_CHOOSE_PREV:
551       default_trust (lv, TRUST_PREV);
552       break;
553     case IDC_CHOOSE_CURR:
554       default_trust (lv, TRUST_CURR);
555       break;
556     case IDC_CHOOSE_EXP:
557       default_trust (lv, TRUST_TEST);
558       break;
559     case IDC_CHOOSE_FULLPART:
560       set_full_list (lv, !full_list);
561       break;
562
563     case IDOK:
564       if (source == IDC_SOURCE_CWD)
565         NEXT (IDD_S_INSTALL);
566       else
567         NEXT (IDD_S_DOWNLOAD);
568       break;
569
570     case IDC_BACK:
571       initialized = 0;
572       if (source == IDC_SOURCE_CWD)
573         NEXT (IDD_ROOT);
574       else
575         NEXT (IDD_SITE);
576       break;
577
578     case IDCANCEL:
579       NEXT (0);
580       break;
581     }
582   return FALSE;
583 }
584
585 static void
586 GetParentRect (HWND parent, HWND child, RECT *r)
587 {
588   POINT p;
589   GetWindowRect (child, r);
590   p.x = r->left;
591   p.y = r->top;
592   ScreenToClient (parent, &p);
593   r->left = p.x;
594   r->top = p.y;
595   p.x = r->right;
596   p.y = r->bottom;
597   ScreenToClient (parent, &p);
598   r->right = p.x;
599   r->bottom = p.y;
600 }
601
602 static BOOL CALLBACK
603 dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
604 {
605   HWND frame;
606   RECT r;
607   switch (message)
608     {
609     case WM_INITDIALOG:
610       nextbutton = GetDlgItem (h, IDOK);
611       frame = GetDlgItem (h, IDC_LISTVIEW_POS);
612       GetParentRect (h, frame, &r);
613       r.top += 2;
614       r.bottom -= 2;
615       create_listview (h, &r);
616 #if 0
617       load_dialog (h);
618 #endif
619       return FALSE;
620     case WM_COMMAND:
621       return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
622     }
623   return FALSE;
624 }
625
626 char *
627 base (char *s)
628 {
629   if (!s)
630     return 0;
631   char *rv = s;
632   while (*s)
633     {
634       if ((*s == '/' || *s == ':' || *s == '\\') && s[1])
635         rv = s+1;
636       s++;
637     }
638   return rv;
639 }
640
641 static void
642 scan2 (char *path, unsigned int size)
643 {
644   int i, t;
645   for (i=0; i<npackages; i++)
646     for (t=0; t<NTRUST; t++)
647       if (package[i].info[t].install
648           && strcmp (base (package[i].info[t].install), base (path)) == 0
649           && package[i].info[t].install_size == (int)size)
650         {
651           extra[i].installed_file = package[i].info[t].install;
652           extra[i].installed_size = size;
653           extra[i].which_is_installed = t;
654           extra[i].installed_ver = package[i].info[t].version;
655           if (!extra[i].installed_ver)
656             extra[i].installed_ver = "0";
657         }
658 }
659
660 static void
661 scan_downloaded_files ()
662 {
663   find (".", scan2);
664 }
665
666 static void
667 read_installed_db ()
668 {
669   int i;
670   if (!root_dir)
671     return;
672
673   char line[1000], pkg[1000], inst[1000], src[1000];
674   int instsz, srcsz;
675
676   FILE *db = fopen (concat (root_dir, XEMACS_SETUP_DIR, "installed.db", 0), "rt");
677   if (!db)
678     return;
679
680   while (fgets (line, 1000, db))
681     {
682       src[0] = 0;
683       srcsz = 0;
684       sscanf (line, "%s %s %d %s %d", pkg, inst, &instsz, src, &srcsz);
685
686       for (i=0; i<npackages; i++)
687         if (strcmp (package[i].name, pkg) == 0)
688           {
689             int t;
690             extra[i].installed_file = inst;
691             extra[i].installed_size = instsz;
692
693             for (t=0; t<NTRUST; t++)
694               if (package[i].info[t].install
695                   && strcmp (base (package[i].info[t].install), base (inst)) == 0)
696                 {
697                   extra[i].which_is_installed = t;
698                   extra[i].installed_ver = package[i].info[t].version;
699                   break;
700                 }
701
702             if (extra[i].installed_ver == 0) /* still */
703               {
704                 char *v, *d;
705                 for (v=base (inst); *v; v++)
706                   if (*v == '-' && isdigit(v[1]))
707                     {
708                       v++;
709                       break;
710                     }
711                 if (!v)
712                   v = inst;
713                 for (d=v; *d; d++)
714                   if (strncmp (d, ".tar", 4) == 0
715                       || strncmp (d, "-pkg", 4) == 0)
716                     {
717                       *d = 0;
718                       break;
719                     }
720                 if (v[0])
721                   extra[i].installed_ver = strdup (v);
722                 else
723                   extra[i].installed_ver = "0";
724               }
725             break;
726           }
727     }
728   fclose (db);
729 }
730
731 int CDECL
732 package_sort (const void *va, const void *vb)
733 {
734   Package *a = (Package *)va;
735   Package *b = (Package *)vb;
736   return strcmp (a->name, b->name);
737 }
738
739 void
740 do_choose (HINSTANCE h)
741 {
742   int rv, i;
743
744   qsort (package, npackages, sizeof (package[0]), package_sort);
745
746   nextbutton = 0;
747   bm_spin = LoadImage (h, MAKEINTRESOURCE (IDB_SPIN), IMAGE_BITMAP, 0, 0, 0);
748   bm_rtarrow = LoadImage (h, MAKEINTRESOURCE (IDB_RTARROW), IMAGE_BITMAP, 0, 0, 0);
749
750   bm_checkyes = LoadImage (h, MAKEINTRESOURCE (IDB_CHECK_YES), IMAGE_BITMAP, 0, 0, 0);
751   bm_checkno = LoadImage (h, MAKEINTRESOURCE (IDB_CHECK_NO), IMAGE_BITMAP, 0, 0, 0);
752   bm_checkna = LoadImage (h, MAKEINTRESOURCE (IDB_CHECK_NA), IMAGE_BITMAP, 0, 0, 0);
753
754   extra = (ExtraPackageInfo *) malloc (npackages * sizeof (ExtraPackageInfo));
755   memset (extra, 0, npackages * sizeof (ExtraPackageInfo));
756   for (i=0; i<npackages; i++)
757     extra[i].which_is_installed = -1;
758
759   register_windows (h);
760
761   if (source == IDC_SOURCE_DOWNLOAD)
762     scan_downloaded_files ();
763   else
764     read_installed_db ();
765   build_labels ();
766
767   rv = DialogBox (h, MAKEINTRESOURCE (IDD_CHOOSE), 0, dialog_proc);
768   if (rv == -1)
769     fatal (IDS_DIALOG_FAILED);
770
771   for (i=0; i<npackages; i++)
772     {
773       switch (extra[i].chooser[extra[i].pick].trust)
774         {
775         case TRUST_PREV:
776         case TRUST_CURR:
777         case TRUST_TEST:
778           if (extra[i].installed_file)
779             package[i].action = ACTION_UPGRADE;
780           else
781             package[i].action = ACTION_NEW;
782           package[i].trust = extra[i].chooser[extra[i].pick].trust;
783           // pick up the actual core package to install
784           if (package[i].type == TY_CYGWIN || package[i].type == TY_NATIVE
785               && xemacs_package == 0)
786             xemacs_package = &package[i];
787           break;
788
789         case TRUST_UNINSTALL:
790           package[i].action = ACTION_UNINSTALL;
791           break;
792
793         case TRUST_KEEP:
794         case TRUST_NONE:
795         default:
796           package[i].action = ACTION_SAME;
797           break;
798         }
799     }
800
801   log (LOG_BABBLE, "Chooser results...");
802   for (i=0; i<npackages; i++)
803     {
804       static char *infos[] = {"prev", "curr", "test"};
805       const char *trust = ((package[i].trust == TRUST_PREV) ? "prev"
806                            : (package[i].trust == TRUST_CURR) ? "curr"
807                            : (package[i].trust == TRUST_TEST) ? "test"
808                            : "unknown");
809       const char *action = ((package[i].action == ACTION_UNKNOWN) ? "unknown"
810                             : (package[i].action == ACTION_SAME) ? "same"
811                             : (package[i].action == ACTION_NEW) ? "new"
812                             : (package[i].action == ACTION_UPGRADE) ? "upgrade"
813                             : (package[i].action == ACTION_UNINSTALL) ? "uninstall"
814                             : (package[i].action == ACTION_ERROR) ? "error"
815                             : "unknown");
816
817       log (LOG_BABBLE, "[%s] action=%s trust=%s src? %s", package[i].name, action, trust,
818            package[i].srcaction == SRCACTION_NO ? "no" : "yes");
819       for (int t=0; t<NTRUST; t++)
820         {
821           if (package[i].info[t].install)
822             log (LOG_BABBLE, "[%s] ver %s inst %s %d src %s %d",
823                  infos[t],
824                  package[i].info[t].version ? package[i].info[t].version : "(none)",
825                  package[i].info[t].install ? package[i].info[t].install : "(none)",
826                  package[i].info[t].install_size,
827                  package[i].info[t].source ? package[i].info[t].source : "(none)",
828                  package[i].info[t].source_size);
829         }
830     }
831 }