source: trunk/dll/uudecode.c@ 907

Last change on this file since 907 was 907, checked in by Steven Levine, 18 years ago

Avoid out of memory traps in Compare Directories
Rework Compare Directories progress display for 2 second update rate
Start refactoring to reduce dependence on fm3dll.h
Add timer services (IsITimerExpired etc.)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.3 KB
Line 
1
2/***********************************************************************
3
4 $Id: uudecode.c 907 2008-01-06 07:26:17Z stevenhl $
5
6 uudecode
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2005, 2008 Steven H. Levine
10
11 06 Jun 05 SHL Indent -i2
12 06 Jun 05 SHL Drop unused code
13 17 Jul 06 SHL Use Runtime_Error
14 29 Jul 06 SHL Use xfgets
15 01 Sep 06 SHL Back to fgets for now - avoid excess error messages
16 22 Mar 07 GKY Use QWL_USER
17 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
18
19***********************************************************************/
20
21#include <stdlib.h>
22#include <string.h>
23#include <share.h>
24
25#define INCL_DOS
26#define INCL_WIN
27#define INCL_LONGLONG // dircnrs.h
28
29#include "fm3dlg.h"
30#include "fm3str.h"
31#include "makelist.h" // AddToList
32#include "errutil.h" // Dos_Error...
33#include "strutil.h" // GetPString
34#include "fm3dll.h"
35
36static PSZ pszSrcFile = __FILE__;
37
38/* prototypes */
39static BOOL decode(FILE * in, FILE * out);
40static void outdec(char *p, FILE * f, int n);
41
42/* single character decode */
43#define DEC(c) (((c) - ' ') & 077)
44
45int UUD(char *filename, CHAR * dest)
46{
47 FILE *in, *out;
48 int mode, ret = 0;
49 char buf[80];
50 char fakedest[CCHMAXPATH];
51
52 if (!dest)
53 dest = fakedest;
54 in = _fsopen(filename, "r", SH_DENYWR);
55 if (!in) {
56 saymsg(MB_CANCEL,
57 HWND_DESKTOP,
58 GetPString(IDS_ERRORTEXT),
59 GetPString(IDS_COMPCANTOPENTEXT), filename);
60 return ret;
61 }
62
63 /* search for header line */
64 for (;;) {
65 if (!fgets(buf, sizeof(buf), in)) {
66 fclose(in);
67 saymsg(MB_CANCEL,
68 HWND_DESKTOP,
69 GetPString(IDS_ERRORTEXT),
70 GetPString(IDS_UUDNOBEGINTEXT), filename);
71 return ret;
72 }
73 if (!strncmp(buf, "begin ", 6))
74 break;
75 } // for
76 *dest = 0;
77 sscanf(buf, "begin %o %259s", &mode, dest);
78 dest[CCHMAXPATH - 1] = 0;
79 {
80 /* place dest in same directory as filename by default... */
81 char build[CCHMAXPATH], *p;
82
83 strcpy(build, filename);
84 p = strrchr(build, '\\');
85 if (p) {
86 p++;
87 *p = 0;
88 }
89 else
90 strcat(build, "\\");
91 strncat(build, dest, CCHMAXPATH - strlen(dest));
92 strcpy(dest, build);
93 }
94
95 if (!export_filename(HWND_DESKTOP, dest, FALSE)) {
96 fclose(in);
97 return ret;
98 }
99
100 /* create output file */
101 out = _fsopen(dest, "ab+", SH_DENYWR);
102 if (!out) {
103 fclose(in);
104 saymsg(MB_CANCEL,
105 HWND_DESKTOP,
106 GetPString(IDS_ERRORTEXT),
107 GetPString(IDS_UUDCANTOPENFORTEXT), dest, filename);
108 return ret;
109 }
110
111 ret = 1;
112 decode(in, out);
113
114 xfgets(buf, sizeof(buf), in, pszSrcFile, __LINE__);
115
116 fclose(in);
117 fclose(out);
118 return ret;
119}
120
121/*
122 * copy from in to out, decoding as you go along.
123 */
124static BOOL decode(FILE * in, FILE * out)
125{
126 char buf[80];
127 char *bp;
128 int n;
129
130 for (;;) {
131 /* for each input line */
132 if (!xfgets(buf, sizeof(buf), in, pszSrcFile, __LINE__))
133 return FALSE;
134 n = DEC(buf[0]);
135 if (n <= 0)
136 break;
137 bp = &buf[1];
138 while (n > 0) {
139 outdec(bp, out, n);
140 bp += 4;
141 n -= 3;
142 }
143 }
144 return TRUE;
145}
146
147/*
148 * output a group of 3 bytes (4 input characters).
149 * the input chars are pointed to by p, they are to
150 * be output to file f. n is used to tell us not to
151 * output all of them at the end of the file.
152 */
153static void outdec(char *p, FILE * f, int n)
154{
155 INT c1, c2, c3;
156
157 c1 = DEC(*p) << 2 | (UINT) DEC(p[1]) >> 4;
158 c2 = DEC(p[1]) << 4 | (UINT) DEC(p[2]) >> 2;
159 c3 = DEC(p[2]) << 6 | DEC(p[3]);
160 if (n >= 1)
161 putc(c1, f);
162 if (n >= 2)
163 putc(c2, f);
164 if (n >= 3)
165 putc(c3, f);
166}
167
168MRESULT EXPENTRY MergeDlgProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
169{
170 WORKER *wk;
171
172 switch (msg) {
173 case WM_INITDLG:
174 if (mp2) {
175 WinSetWindowPtr(hwnd, QWL_USER, mp2);
176 wk = (WORKER *) mp2;
177 if (wk->li && wk->li->list && wk->li->list[0]) {
178 WinSendDlgItemMsg(hwnd, MRG_TARGETNAME, EM_SETTEXTLIMIT,
179 MPFROM2SHORT(CCHMAXPATH, 0), MPVOID);
180 PostMsg(hwnd, UM_UNDO, MPVOID, MPVOID);
181 }
182 else
183 WinDismissDlg(hwnd, 0);
184 }
185 else
186 WinDismissDlg(hwnd, 0);
187 break;
188
189 case UM_UNDO:
190 WinSendDlgItemMsg(hwnd, MRG_LISTBOX, LM_DELETEALL, MPVOID, MPVOID);
191 wk = WinQueryWindowPtr(hwnd, QWL_USER);
192 if (wk) {
193 INT x, numfiles = 0;
194 SHORT start;
195 CHAR *p;
196
197 WinSetDlgItemText(hwnd, MRG_TARGETNAME, wk->li->targetpath);
198 start = 0;
199 p = strrchr(wk->li->targetpath, '\\');
200 if (p)
201 start = (p + 1) - wk->li->targetpath;
202 WinSendDlgItemMsg(hwnd, MRG_TARGETNAME, EM_SETSEL,
203 MPFROM2SHORT(start, CCHMAXPATH), MPVOID);
204 for (x = 0; wk->li->list[x]; x++) {
205 if (IsFile(wk->li->list[x]) == 1) {
206 numfiles++;
207 WinSendDlgItemMsg(hwnd, MRG_LISTBOX, LM_INSERTITEM,
208 MPFROM2SHORT(LIT_END, 0),
209 MPFROMP(wk->li->list[x]));
210 }
211 }
212 WinCheckButton(hwnd, MRG_BINARY, (wk->li->type == IDM_MERGEBINARY));
213 if (!numfiles) {
214 saymsg(MB_CANCEL | MB_ICONEXCLAMATION,
215 hwnd,
216 GetPString(IDS_SILLYERRORTEXT),
217 GetPString(IDS_MERGEWASTETEXT));
218 WinDismissDlg(hwnd, 0);
219 }
220 }
221 return 0;
222
223 case WM_CONTROL:
224 switch (SHORT1FROMMP(mp1)) {
225 case MRG_LISTBOX:
226 switch (SHORT2FROMMP(mp1)) {
227 case LN_ENTER:
228 {
229 SHORT x;
230 CHAR szBuffer[CCHMAXPATH];
231
232 x = (SHORT) WinSendDlgItemMsg(hwnd, MRG_LISTBOX, LM_QUERYSELECTION,
233 MPFROMSHORT(LIT_FIRST), MPVOID);
234 if (x >= 0) {
235 *szBuffer = 0;
236 WinSendDlgItemMsg(hwnd, MRG_LISTBOX, LM_QUERYITEMTEXT,
237 MPFROM2SHORT(x, CCHMAXPATH), MPFROMP(szBuffer));
238 if (*szBuffer)
239 QuickEdit(hwnd, szBuffer);
240 }
241 }
242 break;
243 }
244 break;
245 }
246 break;
247
248 case WM_ADJUSTWINDOWPOS:
249 PostMsg(hwnd, UM_SETDIR, MPVOID, MPVOID);
250 break;
251
252 case UM_SETDIR:
253 PaintRecessedWindow(WinWindowFromID(hwnd, MRG_HELP), (HPS) 0, FALSE,
254 TRUE);
255 return 0;
256
257 case WM_COMMAND:
258 switch (SHORT1FROMMP(mp1)) {
259 case IDM_UNDO:
260 PostMsg(hwnd, UM_UNDO, MPVOID, MPVOID);
261 break;
262
263 case MRG_CHANGETARGET:
264 wk = WinQueryWindowPtr(hwnd, QWL_USER);
265 if (wk) {
266 CHAR filename[CCHMAXPATH];
267
268 strcpy(filename, wk->li->targetpath);
269 if (export_filename(HWND_DESKTOP, filename, FALSE) && *filename) {
270 strcpy(wk->li->targetpath, filename);
271 WinSetDlgItemText(hwnd, MRG_TARGETNAME, wk->li->targetpath);
272 }
273 }
274 break;
275
276 case MRG_REMOVE:
277 {
278 SHORT x;
279
280 x = (SHORT) WinSendDlgItemMsg(hwnd, MRG_LISTBOX, LM_QUERYSELECTION,
281 MPFROMSHORT(LIT_FIRST), MPVOID);
282 if (x >= 0)
283 WinSendDlgItemMsg(hwnd, MRG_LISTBOX, LM_DELETEITEM,
284 MPFROMSHORT(x), MPVOID);
285 }
286 break;
287
288 case MRG_BOTTOM:
289 case MRG_TOP:
290 {
291 SHORT x;
292 CHAR szBuffer[CCHMAXPATH];
293
294 x = (SHORT) WinSendDlgItemMsg(hwnd, MRG_LISTBOX, LM_QUERYSELECTION,
295 MPFROMSHORT(LIT_FIRST), MPVOID);
296 if (x >= 0) {
297 *szBuffer = 0;
298 WinSendDlgItemMsg(hwnd, MRG_LISTBOX, LM_QUERYITEMTEXT,
299 MPFROM2SHORT(x, CCHMAXPATH), MPFROMP(szBuffer));
300 if (*szBuffer) {
301 WinSendDlgItemMsg(hwnd, MRG_LISTBOX, LM_DELETEITEM,
302 MPFROMSHORT(x), MPVOID);
303 if (SHORT1FROMMP(mp1) == MRG_TOP)
304 WinSendDlgItemMsg(hwnd, MRG_LISTBOX, LM_INSERTITEM,
305 MPFROM2SHORT(0, 0), MPFROMP(szBuffer));
306 else
307 WinSendDlgItemMsg(hwnd, MRG_LISTBOX, LM_INSERTITEM,
308 MPFROM2SHORT(LIT_END, 0), MPFROMP(szBuffer));
309 }
310 }
311 }
312 break;
313
314 case DID_CANCEL:
315 WinDismissDlg(hwnd, 0);
316 break;
317
318 case IDM_HELP:
319 if (hwndHelp)
320 WinSendMsg(hwndHelp, HM_DISPLAY_HELP,
321 MPFROM2SHORT(HELP_MERGE, 0), MPFROMSHORT(HM_RESOURCEID));
322 break;
323
324 case DID_OK:
325 wk = WinQueryWindowPtr(hwnd, QWL_USER);
326 if (wk) {
327 BOOL append, binary;
328 CHAR **list = NULL, **test, szBuffer[CCHMAXPATH];
329 UINT numfiles = 0, numalloc = 0;
330 INT error;
331 SHORT x, y;
332
333 *szBuffer = 0;
334 WinQueryDlgItemText(hwnd, MRG_TARGETNAME, CCHMAXPATH, szBuffer);
335 if (!*szBuffer) {
336 DosBeep(50, 100);
337 WinSetFocus(HWND_DESKTOP, WinWindowFromID(hwnd, MRG_TARGETNAME));
338 break;
339 }
340 if (DosQueryPathInfo(szBuffer,
341 FIL_QUERYFULLNAME,
342 wk->li->targetpath, CCHMAXPATH)) {
343 DosBeep(50, 100);
344 WinSetFocus(HWND_DESKTOP, WinWindowFromID(hwnd, MRG_TARGETNAME));
345 break;
346 }
347 WinSetDlgItemText(hwnd, MRG_TARGETNAME, szBuffer);
348 append = WinQueryButtonCheckstate(hwnd, MRG_APPEND);
349 binary = WinQueryButtonCheckstate(hwnd, MRG_BINARY);
350 wk->li->type = (append && binary) ? IDM_MERGEBINARYAPPEND :
351 (append) ? IDM_MERGETEXTAPPEND :
352 (binary) ? IDM_MERGEBINARY : IDM_MERGETEXT;
353 x = (SHORT) WinSendDlgItemMsg(hwnd,
354 MRG_LISTBOX,
355 LM_QUERYITEMCOUNT, MPVOID, MPVOID);
356 for (y = 0; y < x; y++) {
357 *szBuffer = 0;
358 WinSendDlgItemMsg(hwnd,
359 MRG_LISTBOX,
360 LM_QUERYITEMTEXT,
361 MPFROM2SHORT(y, CCHMAXPATH), MPFROMP(szBuffer));
362 if (*szBuffer) {
363 error = AddToList(szBuffer, &list, &numfiles, &numalloc);
364 if (error) {
365 Runtime_Error(pszSrcFile, __LINE__, "AddToList");
366 break;
367 }
368 }
369 }
370 if (numfiles && list && numfiles + 1 < numalloc) {
371 test =
372 xrealloc(list, sizeof(CHAR *) * (numfiles + 1), pszSrcFile,
373 __LINE__);
374 if (test)
375 list = test;
376 }
377 if (!list || !list[0]) {
378 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
379 break;
380 }
381 else {
382 FreeList(wk->li->list);
383 wk->li->list = list;
384 }
385 }
386 WinDismissDlg(hwnd, 1);
387 break;
388 } // switch WM_COMMAND mp1
389 return 0;
390 } // switch msg
391 return WinDefDlgProc(hwnd, msg, mp1, mp2);
392}
393
394#pragma alloc_text(UUD,UUD,decode,outdec)
395#pragma alloc_text(MERGE,MergeDlgProc)
Note: See TracBrowser for help on using the repository browser.