(U-00020E60): Use `->denotational' and `->subsumptive'.
[chise/xemacs-chise.git.1] / netinstall / geturl.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 act as a pretty interface to
17    netio.cc.  We add a progress dialog and some convenience functions
18    (like collect to string or file */
19
20 #include "win32.h"
21 #include "commctrl.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <errno.h>
26
27 #include "dialog.h"
28 #include "geturl.h"
29 #include "resource.h"
30 #include "netio.h"
31 #include "msg.h"
32 #include "log.h"
33
34 static int is_showing = 0;
35 static HWND gw_dialog = 0;
36 static HWND gw_url = 0;
37 static HWND gw_rate = 0;
38 static HWND gw_progress = 0;
39 static HANDLE init_event;
40 static int max_bytes = 0;
41
42 static BOOL
43 dialog_cmd (HWND h, int id, HWND hwndctl, UINT code)
44 {
45   switch (id)
46     {
47     case IDCANCEL:
48       exit_setup (0);
49     }
50   return FALSE;
51 }
52
53 static BOOL CALLBACK
54 dialog_proc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
55 {
56   switch (message)
57     {
58     case WM_INITDIALOG:
59       gw_dialog = h;
60       gw_url = GetDlgItem (h, IDC_DLS_URL);
61       gw_rate = GetDlgItem (h, IDC_DLS_RATE);
62       gw_progress = GetDlgItem (h, IDC_DLS_PROGRESS);
63       SetEvent (init_event);
64       return FALSE;
65     case WM_COMMAND:
66       return HANDLE_WM_COMMAND (h, wParam, lParam, dialog_cmd);
67     }
68   return FALSE;
69 }
70
71 static DWORD WINAPI
72 dialog (void *)
73 {
74   MSG m;
75   HWND lgw_dialog = CreateDialog (hinstance, MAKEINTRESOURCE (IDD_DLSTATUS),
76                                    0, dialog_proc);
77   ShowWindow (lgw_dialog, SW_SHOWNORMAL);
78   UpdateWindow (lgw_dialog);
79   while (GetMessage (&m, 0, 0, 0) > 0) {
80     TranslateMessage (&m);
81     DispatchMessage (&m);
82   }
83   return FALSE;
84 }
85
86 static DWORD start_tics;
87
88 static void
89 init_dialog (char *url, int length)
90 {
91   if (gw_dialog == 0)
92     {
93       DWORD tid;
94       HANDLE thread;
95       init_event = CreateEvent (0, 0, 0, 0);
96       thread = CreateThread (0, 0, dialog, 0, 0, &tid);
97       WaitForSingleObject (init_event, 1000);
98       CloseHandle (init_event);
99       SendMessage (gw_progress, PBM_SETRANGE, 0, MAKELPARAM (0, 100));
100       is_showing = 0;
101     }
102   char *sl=url, *cp;
103   for (cp=url; *cp; cp++)
104     if (*cp == '/' || *cp == '\\' || *cp == ':')
105       sl = cp+1;
106   max_bytes = length;
107   SetWindowText (gw_url, sl);
108   SetWindowText (gw_rate, "Connecting...");
109   SendMessage (gw_progress, PBM_SETPOS, (WPARAM) 0, 0);
110   ShowWindow (gw_progress, (length > 0) ? SW_SHOW : SW_HIDE);
111   ShowWindow (gw_dialog, SW_SHOWNORMAL);
112   if (!is_showing)
113     {
114       SetForegroundWindow (gw_dialog);
115       is_showing = 1;
116     }
117   start_tics = GetTickCount ();
118 }
119
120
121 static void
122 progress (int bytes)
123 {
124   static char buf[100];
125   int kbps;
126   static DWORD last_tics = 0;
127   DWORD tics = GetTickCount ();
128   if (tics == start_tics) // to prevent division by zero
129     return;
130   if (tics < last_tics + 200) // to prevent flickering updates
131     return;
132   last_tics = tics;
133
134   kbps = bytes / (tics - start_tics);
135   ShowWindow (gw_progress, (max_bytes > 0) ? SW_SHOW : SW_HIDE);
136   if (max_bytes > 100)
137     {
138       int perc = bytes / (max_bytes / 100);
139       SendMessage (gw_progress, PBM_SETPOS, (WPARAM) perc, 0);
140       sprintf (buf, "%3d %%  (%dk/%dk)  %d kb/s\n",
141                perc, bytes/1000, max_bytes/1000, kbps);
142     }
143   else
144     sprintf (buf, "%d  %d kb/s\n", bytes, kbps);
145
146   SetWindowText (gw_rate, buf);
147 }
148
149 struct GUBuf {
150   GUBuf *next;
151   int count;
152   char buf[2000];
153 };
154
155 char *
156 get_url_to_string (char *_url)
157 {
158   log (LOG_BABBLE, "get_url_to_string %s", _url);
159   init_dialog (_url, 0);
160   NetIO *n = NetIO::open (_url);
161   if (!n || !n->ok ())
162     {
163       delete n;
164       log (LOG_BABBLE, "get_url_to_string failed!");
165       return 0;
166     }
167
168   if (n->file_size)
169     max_bytes = n->file_size;
170
171   GUBuf *bufs = 0;
172   GUBuf **nextp = &bufs;
173   int total_bytes = 1; /* for the NUL */
174   progress (0);
175   while (1)
176     {
177       GUBuf *b = new GUBuf;
178       *nextp = b;
179       b->next = 0;
180       nextp = &(b->next);
181
182       b->count = n->read (b->buf, sizeof (b->buf));
183       if (b->count <= 0)
184         break;
185       total_bytes += b->count;
186       progress (total_bytes);
187     }
188
189   char *rv = (char *) malloc (total_bytes);
190   char *rvp = rv;
191   while (bufs && bufs->count > 0)
192     {
193       GUBuf *tmp = bufs->next;
194       memcpy (rvp, bufs->buf, bufs->count);
195       rvp += bufs->count;
196       delete bufs;
197       bufs = tmp;
198     }
199   *rvp = 0;
200
201   if (n)
202     delete n;
203
204   return rv;
205 }
206
207 int
208 get_url_to_file (char *_url, char *_filename, int expected_length)
209 {
210   log (LOG_BABBLE, "get_url_to_file %s %s", _url, _filename);
211   init_dialog (_url, expected_length);
212
213   remove (_filename); /* but ignore errors */
214
215   NetIO *n = NetIO::open (_url);
216   if (!n || !n->ok ())
217     {
218       delete n;
219       log (LOG_BABBLE, "get_url_to_file failed!");
220       return 1;
221     }
222
223   FILE *f = fopen (_filename, "wb");
224   if (!f)
225     {
226       char *err = strerror (errno);
227       if (!err)
228         err = "(unknown error)";
229       fatal (IDS_ERR_OPEN_WRITE, _filename, err);
230     }
231
232   if (n->file_size)
233     max_bytes = n->file_size;
234
235   int total_bytes = 0;
236   progress (0);
237   while (1)
238     {
239       char buf[8192];
240       int count;
241       count = n->read (buf, sizeof (buf));
242       if (count <= 0)
243         break;
244       fwrite (buf, 1, count, f);
245       total_bytes += count;
246       progress (total_bytes);
247     }
248
249   fclose (f);
250
251   if (n)
252     delete n;
253
254   return 0;
255 }
256
257 void
258 dismiss_url_status_dialog ()
259 {
260   ShowWindow (gw_dialog, SW_HIDE);
261   is_showing = 0;
262 }