]> cygwin.com Git - cygwin-apps/setup.git/blob - choose.cc
* choose.cc (set_action): Only clear srcpicked when moving to next state.
[cygwin-apps/setup.git] / 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 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
47 #include "port.h"
48
49 #define HMARGIN 10
50 #define ROW_MARGIN 5
51 #define ICON_MARGIN 4
52 #define NEW_COL_SIZE_SLOP (ICON_MARGIN + 11)
53
54 #define CHECK_SIZE 11
55
56 static int initialized = 0;
57
58 static int full_list = 0;
59
60 static int scroll_ulc_x, scroll_ulc_y;
61
62 static HWND lv, nextbutton, choose_inst_text;
63 static TEXTMETRIC tm;
64 static int header_height;
65 static HANDLE sysfont;
66 static int row_height;
67 static HANDLE bm_spin, bm_rtarrow, bm_checkyes, bm_checkno, bm_checkna;
68 static HDC bitmap_dc;
69
70 static struct
71 {
72 char *text;
73 int slen;
74 int width;
75 int x;
76 }
77 headers[] = {
78 { "Current", 7, 0, 0 },
79 #define CURRENT_COL 0
80 { "New", 3, 0, 0 },
81 #define NEW_COL 1
82 { "Src?", 4, 0, 0 },
83 #define SRC_COL 2
84 { "Package", 7, 0, 0 },
85 #define PACKAGE_COL 3
86 { 0, 0, 0, 0 }
87 };
88 #define NUM_COLUMNS (sizeof (headers) / (sizeof (headers[0])) - 1)
89
90 int *package_indexes, nindexes;
91
92 static bool
93 isinstalled (Package *pkg, int trust)
94 {
95 return pkg->installed && pkg->info[trust].version &&
96 strcmp (pkg->installed->version, pkg->info[trust].version) == 0;
97 }
98
99 /* Set the next action given a current action. */
100 static void
101 set_action (Package *pkg, bool preinc)
102 {
103 if (!pkg->action || preinc)
104 {
105 ((int) pkg->action)++;
106 pkg->srcpicked = 0;
107 }
108
109 /* Exercise the action state machine. */
110 for (;; ((int) pkg->action)++)
111 switch (pkg->action)
112 {
113 case ACTION_ERROR:
114 case ACTION_UNKNOWN:
115 pkg->action = (actions) (ACTION_CURR - 1);
116 break;
117 case ACTION_LAST:
118 pkg->action = ACTION_PREV;
119 /* fall through intentionally */
120 case ACTION_PREV:
121 case ACTION_CURR:
122 case ACTION_TEST:
123 /* Try to find the next best action. We may not have all of
124 prev, curr, or test but we should have at least one of those. */
125 Info *inf;
126 inf = pkg->info + pkg->action;
127 if (inf->version && inf->install_exists)
128 {
129 if (isinstalled (pkg, pkg->action))
130 (int) pkg->action += ACTION_SAME;
131 return;
132 }
133 break;
134 /* ACTION_SAME_* are used when the installed version is the same
135 as the given action. */
136 case ACTION_SAME_CURR:
137 case ACTION_SAME_TEST:
138 if (!preinc) /* Previously set to this value */
139 return;
140 (int) pkg->action -= ACTION_SAME + 1; /* revert to ACTION_CURR, etc. */
141 break;
142 case ACTION_SAME_PREV:
143 if (!preinc) /* Previously set to this value */
144 return;
145 pkg->action = ACTION_UNINSTALL;
146 /* Fall through intentionally */
147 case ACTION_UNINSTALL:
148 if (pkg->installed)
149 return;
150 break;
151 case ACTION_REDO:
152 if (pkg->installed && pkg->info[pkg->installed_ix].install_exists)
153 {
154 pkg->trust = pkg->installed_ix;
155 return;
156 }
157 break;
158 case ACTION_SRC_ONLY:
159 if (pkg->info[pkg->trust].source_exists)
160 {
161 pkg->srcpicked = 1;
162 return;
163 }
164 break;
165 case ACTION_SAME_LAST:
166 pkg->action = ACTION_SKIP;
167 /* Fall through intentionally */
168 case ACTION_SKIP:
169 if (!pkg->installed || !pkg->info[pkg->installed_ix].install_exists)
170 return;
171 break;
172 default:
173 log (0, "should never get here %d\n", pkg->action);
174 }
175 }
176
177 /* Return an appropriate caption given the current action. */
178 const char *
179 choose_caption (Package *pkg)
180 {
181 set_action (pkg, 0);
182 switch (pkg->action)
183 {
184 case ACTION_PREV:
185 case ACTION_CURR:
186 case ACTION_TEST:
187 pkg->trust = (trusts) pkg->action;
188 return pkg->info[pkg->trust].version;
189 case ACTION_SAME_PREV:
190 case ACTION_SAME_CURR:
191 case ACTION_SAME_TEST:
192 return "Keep";
193 case ACTION_UNINSTALL:
194 return "Uninstall";
195 case ACTION_REDO:
196 return source == IDC_SOURCE_DOWNLOAD ? "Retrieve" : "Reinstall";
197 case ACTION_SRC_ONLY:
198 if (pkg->installed && pkg->installed->source_exists)
199 return "Redo Source";
200 else
201 return "Source";
202 case ACTION_SKIP:
203 return "Skip";
204 }
205 return "???";
206 }
207
208 static void
209 paint (HWND hwnd)
210 {
211 HDC hdc;
212 PAINTSTRUCT ps;
213 int x, y, i, j, ii;
214
215 hdc = BeginPaint (hwnd, &ps);
216
217 SelectObject (hdc, sysfont);
218 SetBkColor (hdc, GetSysColor (COLOR_WINDOW));
219
220 RECT cr;
221 GetClientRect (hwnd, &cr);
222
223 POINT p;
224
225 x = cr.left - scroll_ulc_x;
226 y = cr.top - scroll_ulc_y + header_height;
227
228
229 for (i = 0; headers[i].text; i++)
230 {
231 TextOut (hdc, x + headers[i].x, 3, headers[i].text, headers[i].slen);
232 MoveToEx (hdc, x + headers[i].x, header_height-3, &p);
233 LineTo (hdc, x + headers[i].x + headers[i].width, header_height-3);
234 }
235
236 IntersectClipRect (hdc, cr.left, cr.top + header_height, cr.right, cr.bottom);
237
238 for (ii = 0; ii < nindexes; ii++)
239 {
240 i = package_indexes[ii];
241 Package *pkg = package + i;
242 int r = y + ii * row_height;
243 int by = r + tm.tmHeight - 11;
244 if (pkg->installed)
245 {
246 TextOut (hdc, x + headers[CURRENT_COL].x, r,
247 pkg->installed->version, strlen (pkg->installed->version));
248 SelectObject (bitmap_dc, bm_rtarrow);
249 BitBlt (hdc, x + headers[CURRENT_COL].x + headers[0].width + ICON_MARGIN/2 + HMARGIN/2, by,
250 11, 11, bitmap_dc, 0, 0, SRCCOPY);
251 }
252
253 const char *s = choose_caption (pkg);
254 TextOut (hdc, x + headers[NEW_COL].x + NEW_COL_SIZE_SLOP, r,
255 s, strlen (s));
256 SelectObject (bitmap_dc, bm_spin);
257 BitBlt (hdc, x + headers[NEW_COL].x, by, 11, 11,
258 bitmap_dc, 0, 0, SRCCOPY);
259
260 HANDLE check_bm;
261 if (pkg->srcpicked)
262 check_bm = bm_checkyes;
263 else
264 check_bm = bm_checkno;
265
266 SelectObject (bitmap_dc, check_bm);
267 BitBlt (hdc, x + headers[SRC_COL].x, by, 11, 11,
268 bitmap_dc, 0, 0, SRCCOPY);
269
270 if (package[i].sdesc)
271 s = package[i].sdesc;
272 else
273 s = package[i].name;
274 TextOut (hdc, x + headers[PACKAGE_COL].x, r, s, strlen (s));
275 }
276
277 if (nindexes == 0)
278 {
279 static char *msg = "Nothing to Install/Update";
280 if (source == IDC_SOURCE_DOWNLOAD)
281 msg = "Nothing to Download";
282 TextOut (hdc, HMARGIN, header_height, msg, strlen (msg));
283 }
284
285 EndPaint (hwnd, &ps);
286 }
287
288 static void
289 scroll_common (HWND hwnd, int which, int *var, int code)
290 {
291 int v = *var;
292
293 SCROLLINFO si;
294 si.cbSize = sizeof (si);
295 si.fMask = SIF_ALL;
296 GetScrollInfo (hwnd, which, &si);
297
298 switch (code)
299 {
300 case SB_THUMBTRACK:
301 si.nPos = si.nTrackPos;
302 break;
303 case SB_THUMBPOSITION:
304 break;
305 case SB_BOTTOM:
306 si.nPos = si.nMax;
307 break;
308 case SB_TOP:
309 si.nPos = 0;
310 break;
311 case SB_LINEDOWN:
312 si.nPos += row_height;
313 break;
314 case SB_LINEUP:
315 si.nPos -= row_height;
316 break;
317 case SB_PAGEDOWN:
318 si.nPos += si.nPage * 9/10;
319 break;
320 case SB_PAGEUP:
321 si.nPos -= si.nPage * 9/10;
322 break;
323 }
324
325 if ((int)si.nPos < 0)
326 si.nPos = 0;
327 if (si.nPos + si.nPage > si.nMax)
328 si.nPos = si.nMax - si.nPage;
329
330 si.fMask = SIF_POS;
331 SetScrollInfo (hwnd, which, &si, TRUE);
332
333 int ox = scroll_ulc_x;
334 int oy = scroll_ulc_y;
335 *var = si.nPos;
336
337 RECT cr, sr;
338 GetClientRect (hwnd, &cr);
339 sr = cr;
340 sr.top += header_height;
341 ScrollWindow (hwnd, ox - scroll_ulc_x, oy - scroll_ulc_y, &sr, &sr);
342 sr.bottom = sr.top;
343 sr.top = cr.top;
344 ScrollWindow (hwnd, ox - scroll_ulc_x, 0, &sr, &sr);
345 }
346
347 static LRESULT CALLBACK
348 list_vscroll (HWND hwnd, HWND hctl, UINT code, int pos)
349 {
350 scroll_common (hwnd, SB_VERT, &scroll_ulc_y, code);
351 }
352
353 static LRESULT CALLBACK
354 list_hscroll (HWND hwnd, HWND hctl, UINT code, int pos)
355 {
356 scroll_common (hwnd, SB_HORZ, &scroll_ulc_x, code);
357 }
358
359 static LRESULT CALLBACK
360 list_click (HWND hwnd, BOOL dblclk, int x, int y, UINT hitCode)
361 {
362 int r;
363
364 if (nindexes == 0)
365 return 0;
366
367 if (y < header_height)
368 return 0;
369 x += scroll_ulc_x;
370 y += scroll_ulc_y - header_height;
371
372 r = (y + ROW_MARGIN/2) / row_height;
373
374 if (r < 0 || r >= nindexes)
375 return 0;
376
377 Package *pkg = package + package_indexes[r];
378
379 if (x >= headers[NEW_COL].x - (HMARGIN / 2) && x <= headers[NEW_COL + 1].x - HMARGIN/2)
380 set_action (pkg, 1);
381
382 if (pkg->info[pkg->trust].source_exists &&
383 x >= headers[SRC_COL].x - HMARGIN/2 && x <= headers[SRC_COL + 1].x - HMARGIN/2)
384 pkg->srcpicked ^= 1;
385
386 RECT rect;
387 rect.left = headers[NEW_COL].x - scroll_ulc_x;
388 rect.right = headers[SRC_COL + 1].x - scroll_ulc_x;
389 rect.top = header_height + r * row_height - scroll_ulc_y;
390 rect.bottom = rect.top + row_height;
391 InvalidateRect (hwnd, &rect, TRUE);
392 }
393
394 static LRESULT CALLBACK
395 listview_proc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
396 {
397 switch (message)
398 {
399 case WM_HSCROLL:
400 return HANDLE_WM_HSCROLL (hwnd, wParam, lParam, list_hscroll);
401 case WM_VSCROLL:
402 return HANDLE_WM_VSCROLL (hwnd, wParam, lParam, list_vscroll);
403 case WM_LBUTTONDOWN:
404 return HANDLE_WM_LBUTTONDOWN (hwnd, wParam, lParam, list_click);
405 case WM_PAINT:
406 paint (hwnd);
407 return 0;
408 default:
409 return DefWindowProc (hwnd, message, wParam, lParam);
410 }
411 }
412
413 static void
414 register_windows (HINSTANCE hinst)
415 {
416 WNDCLASSEX wcex;
417 static int done = 0;
418
419 if (done)
420 return;
421 done = 1;
422
423 memset (&wcex, 0, sizeof (wcex));
424 wcex.cbSize = sizeof (WNDCLASSEX);
425 wcex.style = CS_HREDRAW | CS_VREDRAW;
426 wcex.lpfnWndProc = listview_proc;
427 wcex.hInstance = hinst;
428 wcex.hIcon = LoadIcon (0, IDI_APPLICATION);
429 wcex.hCursor = LoadCursor (0, IDC_ARROW);
430 wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
431 wcex.lpszClassName = "listview";
432
433 RegisterClassEx (&wcex);
434 }
435
436 static void
437 note_width (HDC dc, char *string, int addend, int column)
438 {
439 if (!string)
440 return;
441 SIZE s;
442 GetTextExtentPoint32 (dc, string, strlen (string), &s);
443 if (headers[column].width < s.cx + addend)
444 headers[column].width = s.cx + addend;
445 }
446
447 static int
448 check_existence (Info *inf, int check_src)
449 {
450 if (source == IDC_SOURCE_NETINST)
451 return 1;
452 if (source == IDC_SOURCE_CWD)
453 return 0; /* should have already been determined */
454 if (check_src)
455 return (inf->source && _access (inf->source, 0) == 0) ? -1 : 1;
456 else
457 return (inf->install && _access (inf->install, 0) == 0) ? -1 : 1;
458 return 0;
459 }
460
461 /* Iterate over the package list, setting the "existence" flags
462 for the source or binary. */
463 static void
464 set_existence ()
465 {
466 for (Package *pkg = package; pkg->name; pkg++)
467 if (!pkg->exclude)
468 {
469 int exists = 0;
470 for (Info *inf = pkg->infoscan; inf < pkg->infoend; inf++)
471 {
472 if (inf->install_exists)
473 exists = 1;
474 else
475 exists |= inf->install_exists = check_existence (inf, 0);
476 if (inf->source_exists)
477 exists = 1;
478 else
479 exists |= inf->source_exists = check_existence (inf, 1);
480 }
481 if (!exists)
482 pkg->exclude = EXCLUDE_NOT_FOUND;
483 }
484 }
485
486 static void
487 default_trust (HWND h, trusts trust)
488 {
489 int i, t, c;
490
491 for (Package *pkg = package; pkg->name; pkg++)
492 {
493 pkg->action = (actions) trust;
494 set_action (pkg, 0);
495 }
496 RECT r;
497 GetClientRect (h, &r);
498 InvalidateRect (h, &r, TRUE);
499 if (nextbutton)
500 SetFocus (nextbutton);
501 }
502
503 static void
504 set_full_list (HWND h, int isfull)
505 {
506 int i;
507 full_list = isfull;
508
509 if (package_indexes == 0)
510 package_indexes = (int *) malloc (npackages * sizeof (int));
511
512 nindexes = 0;
513 for (Package *pkg = package; pkg->name; pkg++)
514 if (!pkg->exclude)
515 {
516 set_action (pkg, 0);
517 if (isfull || !is_full_action (pkg))
518 package_indexes[nindexes++] = pkg - package;
519 }
520
521 RECT r;
522 GetClientRect (h, &r);
523 SCROLLINFO si;
524 memset (&si, 0, sizeof (si));
525 si.cbSize = sizeof (si);
526 si.fMask = SIF_ALL;
527 si.nMin = 0;
528 si.nMax = headers[2].x + headers[2].width + HMARGIN;
529 si.nPage = r.right;
530 SetScrollInfo (h, SB_HORZ, &si, TRUE);
531
532 si.nMax = nindexes * row_height;
533 si.nPage = r.bottom - header_height;
534 SetScrollInfo (h, SB_VERT, &si, TRUE);
535
536 scroll_ulc_x = scroll_ulc_y = 0;
537
538 InvalidateRect (h, &r, TRUE);
539
540 if (nextbutton)
541 SetFocus (nextbutton);
542 }
543
544 static void
545 create_listview (HWND dlg, RECT *r)
546 {
547 int i, t;
548 lv = CreateWindowEx (WS_EX_CLIENTEDGE,
549 "listview",
550 "listviewwindow",
551 WS_CHILD | WS_HSCROLL | WS_VSCROLL | WS_VISIBLE,
552 r->left, r->top,
553 r->right-r->left + 1, r->bottom-r->top + 1,
554 dlg,
555 (HMENU) MAKEINTRESOURCE(IDC_CHOOSE_LIST),
556 hinstance,
557 0);
558 ShowWindow (lv, SW_SHOW);
559
560 for (i = 0; headers[i].text; i++)
561 headers[i].width = 0;
562
563 HDC dc = GetDC (lv);
564 sysfont = GetStockObject (DEFAULT_GUI_FONT);
565 SelectObject (dc, sysfont);
566 GetTextMetrics (dc, &tm);
567 header_height = tm.tmHeight + 5 + 3;
568
569 bitmap_dc = CreateCompatibleDC (dc);
570
571 row_height = (tm.tmHeight + tm.tmExternalLeading + ROW_MARGIN);
572 int irh = tm.tmExternalLeading + tm.tmDescent + 11 + ROW_MARGIN;
573 if (row_height < irh)
574 row_height = irh;
575
576 for (i = 0; headers[i].text; i++)
577 note_width (dc, headers[i].text, 0, i);
578 for (Package *pkg = package; pkg->name; pkg++)
579 {
580 if (pkg->installed)
581 {
582 note_width (dc, pkg->installed->version, 0, CURRENT_COL);
583 note_width (dc, pkg->installed->version, NEW_COL_SIZE_SLOP, NEW_COL);
584 }
585 for (Info *inf = pkg->infoscan; inf < pkg->infoend; inf++)
586 note_width (dc, inf->version, NEW_COL_SIZE_SLOP, NEW_COL);
587 note_width (dc, pkg->name, 0, PACKAGE_COL);
588 note_width (dc, pkg->sdesc, 0, PACKAGE_COL);
589 }
590 note_width (dc, "keep", NEW_COL_SIZE_SLOP, NEW_COL);
591 note_width (dc, "uninstall", NEW_COL_SIZE_SLOP, NEW_COL);
592
593 headers[CURRENT_COL].x = HMARGIN/2;
594 headers[NEW_COL].x = headers[CURRENT_COL].x + headers[CURRENT_COL].width + NEW_COL_SIZE_SLOP + HMARGIN;
595 headers[SRC_COL].x = headers[NEW_COL].x + headers[NEW_COL].width + HMARGIN;
596 headers[PACKAGE_COL].x = headers[SRC_COL].x + headers[SRC_COL].width + HMARGIN;
597
598 default_trust (lv, TRUST_CURR);
599 set_full_list (lv, full_list);
600 static int ta[] = { IDC_CHOOSE_CURR, 0 };
601 rbset (dlg, ta, IDC_CHOOSE_CURR);
602
603 ReleaseDC (lv, dc);
604 }
605
606 static BOOL
607 dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
608 {
609 switch (id)
610 {
611 case IDC_CHOOSE_PREV:
612 default_trust (lv, TRUST_PREV);
613 set_full_list (lv, full_list);
614 break;
615 case IDC_CHOOSE_CURR:
616 default_trust (lv, TRUST_CURR);
617 set_full_list (lv, full_list);
618 break;
619 case IDC_CHOOSE_EXP:
620 default_trust (lv, TRUST_TEST);
621 set_full_list (lv, full_list);
622 break;
623 case IDC_CHOOSE_FULLPART:
624 set_full_list (lv, !full_list);
625 break;
626
627 case IDOK:
628 if (source == IDC_SOURCE_CWD)
629 NEXT (IDD_S_INSTALL);
630 else
631 NEXT (IDD_S_DOWNLOAD);
632 break;
633
634 case IDC_BACK:
635 initialized = 0;
636 if (source == IDC_SOURCE_CWD)
637 NEXT (IDD_ROOT);
638 else
639 NEXT (IDD_SITE);
640 break;
641
642 case IDCANCEL:
643 NEXT (0);
644 break;
645 }
646 }
647
648 static void
649 GetParentRect (HWND parent, HWND child, RECT *r)
650 {
651 POINT p;
652 GetWindowRect (child, r);
653 p.x = r->left;
654 p.y = r->top;
655 ScreenToClient (parent, &p);
656 r->left = p.x;
657 r->top = p.y;
658 p.x = r->right;
659 p.y = r->bottom;
660 ScreenToClient (parent, &p);
661 r->right = p.x;
662 r->bottom = p.y;
663 }
664
665 static BOOL CALLBACK
666 dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
667 {
668 int i, j;
669 HWND frame;
670 RECT r;
671 switch (message)
672 {
673 case WM_INITDIALOG:
674 nextbutton = GetDlgItem (h, IDOK);
675 frame = GetDlgItem (h, IDC_LISTVIEW_POS);
676 choose_inst_text = GetDlgItem(h,IDC_CHOOSE_INST_TEXT);
677 if (source == IDC_SOURCE_DOWNLOAD)
678 SetWindowText (choose_inst_text, "Select packages to download ");
679 else
680 SetWindowText (choose_inst_text, "Select packages to install ");
681 GetParentRect (h, frame, &r);
682 r.top += 2;
683 r.bottom -= 2;
684 create_listview (h, &r);
685 #if 0
686 load_dialog (h);
687 #endif
688 return FALSE;
689 case WM_COMMAND:
690 return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
691 }
692 return FALSE;
693 }
694
695 char *
696 base (const char *s)
697 {
698 if (!s)
699 return 0;
700 const char *rv = s;
701 while (*s)
702 {
703 if ((*s == '/' || *s == ':' || *s == '\\') && s[1])
704 rv = s + 1;
705 s++;
706 }
707 return (char *) rv;
708 }
709
710 int
711 find_tar_ext (const char *path)
712 {
713 char *p = strchr (path, '\0') - 7;
714 if (p <= path)
715 return 0;
716 if (*p == '.')
717 {
718 if (strcmp (p, ".tar.gz") != 0)
719 return 0;
720 }
721 else if (--p <= path || strcmp (p, ".tar.bz2") != 0)
722 return 0;
723
724 return p - path;
725 }
726
727 /* Parse a filename into package, version, and extension components. */
728 int
729 parse_filename (const char *in_fn, fileparse& f)
730 {
731 char *p, *ver;
732 char fn[strlen (in_fn) + 1];
733
734 strcpy (fn, in_fn);
735 int n = find_tar_ext (fn);
736
737 if (!n)
738 return 0;
739
740 strcpy (f.tail, fn + n);
741 fn[n] = '\0';
742 f.pkg[0] = f.what[0] = '\0';
743 p = base (fn);
744 for (ver = p; *ver; ver++)
745 if (*ver == '-' || *ver == '_')
746 if (isdigit (ver[1]))
747 {
748 *ver++ = 0;
749 strcpy (f.pkg, p);
750 break;
751 }
752 else if (strcasecmp (ver, "-src") == 0 ||
753 strcasecmp (ver, "-patch") == 0)
754 {
755 *ver++ = 0;
756 strcpy (f.pkg, p);
757 strcpy (f.what, strlwr (ver));
758 strcpy (f.pkgtar, p);
759 strcat (f.pkgtar, f.tail);
760 ver = strchr (ver, '\0');
761 break;
762 }
763
764 if (!f.pkg[0])
765 strcpy (f.pkg, p);
766
767 if (!f.what[0])
768 {
769 p = strchr (ver, '\0');
770 strcpy (f.pkgtar, in_fn);
771 if ((p -= 4) >= ver && strcasecmp (p, "-src") == 0)
772 {
773 strcpy (f.what, "src");
774 *p = '\0';
775 p = f.pkgtar + (p - fn) + 4;
776 memcpy (p - 4, p, strlen (p));
777 }
778 else if ((p -= 2) >= ver && strcasecmp (p, "-patch") == 0)
779 {
780 strcpy (f.what, "patch");
781 *p = '\0';
782 p = f.pkgtar + (p - fn) + 6;
783 memcpy (p - 6, p, strlen (p));
784 }
785 }
786
787 strcpy (f.ver, *ver ? ver : "0.0");
788 return 1;
789 }
790
791 /* Return a pointer to a package given the name. */
792 Package *
793 getpkgbyname (const char *pkgname)
794 {
795 for (Package *pkg = package; pkg->name; pkg++)
796 if (strcasecmp (pkg->name, pkgname) == 0)
797 return pkg;
798
799 return NULL;
800 }
801
802 static void
803 scan2 (char *path, unsigned int size)
804 {
805 Package *pkg;
806 fileparse f;
807
808 if (!parse_filename (path, f))
809 return;
810
811 if (f.what[0] != '\0' && f.what[0] != 's')
812 return;
813
814 pkg = getpkgbyname (f.pkg);
815 if (pkg == NULL)
816 return;
817
818 Info *hole = NULL;
819 for (Info *inf = pkg->infoscan; inf < pkg->infoend; inf++)
820 if (!inf->version)
821 hole = inf;
822 else if (strcmp (f.ver, inf->version) == 0)
823 {
824 if (f.what[0] == 's')
825 inf->source_exists = -1;
826 else
827 inf->install_exists = -1;
828 return;
829 }
830
831 /* FIXME: This is really not the right way to do this. We should check
832 the version number of the "found" tar file and put it in the test slot
833 if it is newer than curr, the curr slot if it is newer than prev, etc. */
834 if (hole)
835 {
836 hole->version = strdup (f.ver);
837 hole->install = strdup (f.pkgtar);
838 if (!hole->source && f.what[0] == 's')
839 {
840 hole->source = strdup (path);
841 hole->source_exists = -1;
842 hole->source_size = size;
843 }
844 else
845 {
846 hole->install = strdup (path);
847 hole->install_exists = -1;
848 hole->install_size = size;
849 }
850 }
851 }
852
853 static void
854 scan_downloaded_files ()
855 {
856 find (".", scan2);
857 }
858
859 _Info::_Info (const char *_install, const char *_version, int _install_size,
860 const char *_source, int _source_size)
861 {
862 memset (this, 0, sizeof (*this));
863 install = strdup (_install);
864 version = strdup (_version);
865 install_size = _install_size;
866 if (_source)
867 {
868 source = strdup (_source);
869 source_size = _source_size;
870 }
871 }
872
873 static void
874 read_installed_db ()
875 {
876 int i;
877 if (!get_root_dir ())
878 return;
879
880 char line[1000], pkgname[1000], inst[1000], src[1000];
881 int instsz, srcsz;
882
883 FILE *db = fopen (cygpath ("/etc/setup/installed.db", 0), "rt");
884 if (!db)
885 return;
886
887 while (fgets (line, 1000, db))
888 {
889 int parseable;
890 src[0] = 0;
891 srcsz = 0;
892 sscanf (line, "%s %s %d %s %d", pkgname, inst, &instsz, src, &srcsz);
893
894 Package *pkg = getpkgbyname (pkgname);
895 fileparse f;
896 parseable = parse_filename (inst, f);
897
898 if (pkg == NULL)
899 {
900 if (!parseable)
901 continue;
902 pkg = new_package (pkgname);
903 pkg->info[TRUST_CURR].version = strdup (f.ver);
904 pkg->info[TRUST_CURR].install = strdup (inst);
905 pkg->info[TRUST_CURR].install_size = instsz;
906 if (src && srcsz)
907 {
908 pkg->info[TRUST_CURR].source = strdup (src);
909 pkg->info[TRUST_CURR].source_size = srcsz;
910 }
911 pkg->installed_ix = TRUST_CURR;
912 /* Exists on local system but not on download system */
913 pkg->exclude = EXCLUDE_NOT_FOUND;
914 }
915
916 pkg->installed = new Info (inst, f.ver, instsz);
917
918 if (!pkg->installed_ix)
919 for (trusts t = TRUST_PREV; t < NTRUST; ((int) t)++)
920 if (pkg->info[t].install && strcmp (f.ver, pkg->info[t].version) == 0)
921 {
922 pkg->installed_ix = t;
923 break;
924 }
925 }
926 fclose (db);
927 }
928
929 int
930 package_sort (const void *va, const void *vb)
931 {
932 Package *a = (Package *)va;
933 Package *b = (Package *)vb;
934 return strcmp (a->name, b->name);
935 }
936
937 void
938 do_choose (HINSTANCE h)
939 {
940 int rv;
941
942 nextbutton = 0;
943 bm_spin = LoadImage (h, MAKEINTRESOURCE (IDB_SPIN), IMAGE_BITMAP, 0, 0, 0);
944 bm_rtarrow = LoadImage (h, MAKEINTRESOURCE (IDB_RTARROW), IMAGE_BITMAP, 0, 0, 0);
945
946 bm_checkyes = LoadImage (h, MAKEINTRESOURCE (IDB_CHECK_YES), IMAGE_BITMAP, 0, 0, 0);
947 bm_checkno = LoadImage (h, MAKEINTRESOURCE (IDB_CHECK_NO), IMAGE_BITMAP, 0, 0, 0);
948 bm_checkna = LoadImage (h, MAKEINTRESOURCE (IDB_CHECK_NA), IMAGE_BITMAP, 0, 0, 0);
949
950 register_windows (h);
951
952 if (source == IDC_SOURCE_DOWNLOAD || source == IDC_SOURCE_CWD)
953 scan_downloaded_files ();
954
955 read_installed_db ();
956 set_existence ();
957
958 qsort (package, npackages, sizeof (package[0]), package_sort);
959
960 rv = DialogBox (h, MAKEINTRESOURCE (IDD_CHOOSE), 0, dialog_proc);
961 if (rv == -1)
962 fatal (IDS_DIALOG_FAILED);
963
964 log (LOG_BABBLE, "Chooser results...");
965 for (Package *pkg = package; pkg->name; pkg++)
966 {
967 static char *infos[] = {"nada", "prev", "curr", "test"};
968 const char *trust = ((pkg->trust == TRUST_PREV) ? "prev"
969 : (pkg->trust == TRUST_CURR) ? "curr"
970 : (pkg->trust == TRUST_TEST) ? "test"
971 : "unknown");
972 const char *action = choose_caption (pkg);
973 const char *installed = ((pkg->installed_ix == -1) ? "none"
974 : (pkg->installed_ix == TRUST_PREV) ? "prev"
975 : (pkg->installed_ix == TRUST_CURR) ? "curr"
976 : (pkg->installed_ix == TRUST_TEST) ? "test"
977 : "unknown");
978 const char *excluded = (pkg->exclude ? "yes" : "no");
979
980 log (LOG_BABBLE, "[%s] action=%s trust=%s installed=%s excluded=%s src?=%s",
981 pkg->name, action, trust, installed,
982 excluded, pkg->srcpicked ? "yes" : "no");
983 for (int t = 1; t < NTRUST; t++)
984 {
985 if (pkg->info[t].install)
986 log (LOG_BABBLE, " [%s] ver=%s\r\n"
987 " inst=%s %d exists=%s\r\n"
988 " src=%s %d exists=%s",
989 infos[t],
990 pkg->info[t].version ?: "(none)",
991 pkg->info[t].install ?: "(none)",
992 pkg->info[t].install_size,
993 (pkg->info[t].install_exists) ? "yes":"no",
994 pkg->info[t].source ?: "(none)",
995 pkg->info[t].source_size,
996 (pkg->info[t].source_exists == 1) ? "yes" : "no");
997 }
998 }
999 }
This page took 0.080049 seconds and 5 git commands to generate.