1 static bool AnyMessageDisplayed=false; // For console -idn switch.
2
3 // Purely user interface function. Gets and returns user input.
uiAskReplace(wchar * Name,size_t MaxNameSize,int64 FileSize,RarTime * FileTime,uint Flags)4 UIASKREP_RESULT uiAskReplace(wchar *Name,size_t MaxNameSize,int64 FileSize,RarTime *FileTime,uint Flags)
5 {
6 wchar SizeText1[20],DateStr1[50],SizeText2[20],DateStr2[50];
7
8 FindData ExistingFD;
9 memset(&ExistingFD,0,sizeof(ExistingFD)); // In case find fails.
10 FindFile::FastFind(Name,&ExistingFD);
11 itoa(ExistingFD.Size,SizeText1,ASIZE(SizeText1));
12 ExistingFD.mtime.GetText(DateStr1,ASIZE(DateStr1),false);
13
14 if (FileSize==INT64NDF || FileTime==NULL)
15 {
16 eprintf(L"\n");
17 eprintf(St(MAskOverwrite),Name);
18 }
19 else
20 {
21 itoa(FileSize,SizeText2,ASIZE(SizeText2));
22 FileTime->GetText(DateStr2,ASIZE(DateStr2),false);
23 if ((Flags & UIASKREP_F_EXCHSRCDEST)==0)
24 eprintf(St(MAskReplace),Name,SizeText1,DateStr1,SizeText2,DateStr2);
25 else
26 eprintf(St(MAskReplace),Name,SizeText2,DateStr2,SizeText1,DateStr1);
27 }
28
29 bool AllowRename=(Flags & UIASKREP_F_NORENAME)==0;
30 int Choice=0;
31 do
32 {
33 Choice=Ask(St(AllowRename ? MYesNoAllRenQ : MYesNoAllQ));
34 } while (Choice==0); // 0 means invalid input.
35 switch(Choice)
36 {
37 case 1:
38 return UIASKREP_R_REPLACE;
39 case 2:
40 return UIASKREP_R_SKIP;
41 case 3:
42 return UIASKREP_R_REPLACEALL;
43 case 4:
44 return UIASKREP_R_SKIPALL;
45 }
46 if (AllowRename && Choice==5)
47 {
48 mprintf(St(MAskNewName));
49 if (getwstr(Name,MaxNameSize))
50 return UIASKREP_R_RENAME;
51 else
52 return UIASKREP_R_SKIP; // Process fwgets failure as if user answered 'No'.
53 }
54 return UIASKREP_R_CANCEL;
55 }
56
57
58
59
uiStartArchiveExtract(bool Extract,const wchar * ArcName)60 void uiStartArchiveExtract(bool Extract,const wchar *ArcName)
61 {
62 mprintf(St(Extract ? MExtracting : MExtrTest), ArcName);
63 }
64
65
uiStartFileExtract(const wchar * FileName,bool Extract,bool Test,bool Skip)66 bool uiStartFileExtract(const wchar *FileName,bool Extract,bool Test,bool Skip)
67 {
68 return true;
69 }
70
71
uiExtractProgress(int64 CurFileSize,int64 TotalFileSize,int64 CurSize,int64 TotalSize)72 void uiExtractProgress(int64 CurFileSize,int64 TotalFileSize,int64 CurSize,int64 TotalSize)
73 {
74 int CurPercent=ToPercent(CurSize,TotalSize);
75 mprintf(L"\b\b\b\b%3d%%",CurPercent);
76 }
77
78
uiProcessProgress(const char * Command,int64 CurSize,int64 TotalSize)79 void uiProcessProgress(const char *Command,int64 CurSize,int64 TotalSize)
80 {
81 int CurPercent=ToPercent(CurSize,TotalSize);
82 mprintf(L"\b\b\b\b%3d%%",CurPercent);
83 }
84
85
Msg()86 void uiMsgStore::Msg()
87 {
88 // When creating volumes, AnyMessageDisplayed must be reset for UIEVENT_NEWARCHIVE,
89 // so it ignores this and all earlier messages like UIEVENT_PROTECTEND
90 // and UIEVENT_PROTECTEND, because they precede "Creating archive" message
91 // and do not interfere with -idn and file names. If we do not ignore them,
92 // uiEolAfterMsg() in uiStartFileAddit() can cause unneeded carriage return
93 // in archiving percent after creating a new volume with -v -idn (and -rr
94 // for UIEVENT_PROTECT*) switches. AnyMessageDisplayed is set for messages
95 // after UIEVENT_NEWARCHIVE, so archiving percent with -idn is moved to
96 // next line and does not delete their last characters.
97 // Similarly we ignore UIEVENT_RRTESTINGEND for volumes, because it is issued
98 // before "Testing archive" and would add an excessive \n otherwise.
99 AnyMessageDisplayed=(Code!=UIEVENT_NEWARCHIVE && Code!=UIEVENT_RRTESTINGEND);
100
101 switch(Code)
102 {
103 case UIERROR_SYSERRMSG:
104 case UIERROR_GENERALERRMSG:
105 Log(NULL,L"\n%ls",Str[0]);
106 break;
107 case UIERROR_CHECKSUM:
108 Log(Str[0],St(MCRCFailed),Str[1]);
109 break;
110 case UIERROR_CHECKSUMENC:
111 Log(Str[0],St(MEncrBadCRC),Str[1]);
112 break;
113 case UIERROR_CHECKSUMPACKED:
114 Log(Str[0],St(MDataBadCRC),Str[1],Str[0]);
115 break;
116 case UIERROR_BADPSW:
117 Log(Str[0],St(MWrongFilePassword),Str[1]);
118 break;
119 case UIWAIT_BADPSW:
120 Log(Str[0],St(MWrongPassword));
121 break;
122 case UIERROR_MEMORY:
123 mprintf(L"\n");
124 Log(NULL,St(MErrOutMem));
125 break;
126 case UIERROR_FILEOPEN:
127 Log(Str[0],St(MCannotOpen),Str[1]);
128 break;
129 case UIERROR_FILECREATE:
130 Log(Str[0],St(MCannotCreate),Str[1]);
131 break;
132 case UIERROR_FILECLOSE:
133 Log(NULL,St(MErrFClose),Str[0]);
134 break;
135 case UIERROR_FILESEEK:
136 Log(NULL,St(MErrSeek),Str[0]);
137 break;
138 case UIERROR_FILEREAD:
139 mprintf(L"\n");
140 Log(Str[0],St(MErrRead),Str[1]);
141 break;
142 case UIERROR_FILEWRITE:
143 Log(Str[0],St(MErrWrite),Str[1]);
144 break;
145 #ifndef SFX_MODULE
146 case UIERROR_FILEDELETE:
147 Log(Str[0],St(MCannotDelete),Str[1]);
148 break;
149 case UIERROR_RECYCLEFAILED:
150 Log(Str[0],St(MRecycleFailed));
151 break;
152 case UIERROR_FILERENAME:
153 Log(Str[0],St(MErrRename),Str[1],Str[2]);
154 break;
155 #endif
156 case UIERROR_FILEATTR:
157 Log(Str[0],St(MErrChangeAttr),Str[1]);
158 break;
159 case UIERROR_FILECOPY:
160 Log(Str[0],St(MCopyError),Str[1],Str[2]);
161 break;
162 case UIERROR_FILECOPYHINT:
163 Log(Str[0],St(MCopyErrorHint));
164 mprintf(L" "); // For progress percent.
165 break;
166 case UIERROR_DIRCREATE:
167 Log(Str[0],St(MExtrErrMkDir),Str[1]);
168 break;
169 case UIERROR_SLINKCREATE:
170 Log(Str[0],St(MErrCreateLnkS),Str[1]);
171 break;
172 case UIERROR_HLINKCREATE:
173 Log(NULL,St(MErrCreateLnkH),Str[0]);
174 break;
175 case UIERROR_NOLINKTARGET:
176 Log(NULL,St(MErrLnkTarget));
177 mprintf(L" "); // For progress percent.
178 break;
179 case UIERROR_NEEDADMIN:
180 Log(NULL,St(MNeedAdmin));
181 break;
182 case UIERROR_ARCBROKEN:
183 Log(Str[0],St(MErrBrokenArc));
184 break;
185 case UIERROR_HEADERBROKEN:
186 Log(Str[0],St(MHeaderBroken));
187 break;
188 case UIERROR_MHEADERBROKEN:
189 Log(Str[0],St(MMainHeaderBroken));
190 break;
191 case UIERROR_FHEADERBROKEN:
192 Log(Str[0],St(MLogFileHead),Str[1]);
193 break;
194 case UIERROR_SUBHEADERBROKEN:
195 Log(Str[0],St(MSubHeadCorrupt));
196 break;
197 case UIERROR_SUBHEADERUNKNOWN:
198 Log(Str[0],St(MSubHeadUnknown));
199 break;
200 case UIERROR_SUBHEADERDATABROKEN:
201 Log(Str[0],St(MSubHeadDataCRC),Str[1]);
202 break;
203 case UIERROR_RRDAMAGED:
204 Log(Str[0],St(MRRDamaged));
205 break;
206 case UIERROR_UNKNOWNMETHOD:
207 Log(Str[0],St(MUnknownMeth),Str[1]);
208 break;
209 case UIERROR_UNKNOWNENCMETHOD:
210 {
211 wchar Msg[256];
212 swprintf(Msg,ASIZE(Msg),St(MUnkEncMethod),Str[1]);
213 Log(Str[0],L"%s: %s",Msg,Str[2]);
214 }
215 break;
216 #ifndef SFX_MODULE
217 case UIERROR_RENAMING:
218 Log(Str[0],St(MRenaming),Str[1],Str[2]);
219 break;
220 case UIERROR_NEWERRAR:
221 Log(Str[0],St(MNewerRAR));
222 break;
223 #endif
224 case UIERROR_RECVOLDIFFSETS:
225 Log(NULL,St(MRecVolDiffSets),Str[0],Str[1]);
226 break;
227 case UIERROR_RECVOLALLEXIST:
228 mprintf(St(MRecVolAllExist));
229 break;
230 case UIERROR_RECONSTRUCTING:
231 mprintf(St(MReconstructing));
232 break;
233 case UIERROR_RECVOLCANNOTFIX:
234 mprintf(St(MRecVolCannotFix));
235 break;
236 case UIERROR_UNEXPEOF:
237 Log(Str[0],St(MLogUnexpEOF));
238 break;
239 case UIERROR_BADARCHIVE:
240 Log(Str[0],St(MBadArc),Str[0]);
241 break;
242 case UIERROR_CMTBROKEN:
243 Log(Str[0],St(MLogCommBrk));
244 break;
245 case UIERROR_INVALIDNAME:
246 Log(Str[0],St(MInvalidName),Str[1]);
247 mprintf(L"\n"); // Needed when called from CmdExtract::ExtractCurrentFile.
248 break;
249 #ifndef SFX_MODULE
250 case UIERROR_NEWRARFORMAT:
251 Log(Str[0],St(MNewRarFormat));
252 break;
253 #endif
254 case UIERROR_NOFILESTOEXTRACT:
255 mprintf(St(MExtrNoFiles));
256 break;
257 case UIERROR_MISSINGVOL:
258 Log(Str[0],St(MAbsNextVol),Str[0]);
259 break;
260 #ifndef SFX_MODULE
261 case UIERROR_NEEDPREVVOL:
262 Log(Str[0],St(MUnpCannotMerge),Str[1]);
263 break;
264 case UIERROR_UNKNOWNEXTRA:
265 Log(Str[0],St(MUnknownExtra),Str[1]);
266 break;
267 case UIERROR_CORRUPTEXTRA:
268 Log(Str[0],St(MCorruptExtra),Str[1],Str[2]);
269 break;
270 #endif
271 #if !defined(SFX_MODULE) && defined(_WIN_ALL)
272 case UIERROR_NTFSREQUIRED:
273 Log(NULL,St(MNTFSRequired),Str[0]);
274 break;
275 #endif
276 #if !defined(SFX_MODULE) && defined(_WIN_ALL)
277 case UIERROR_ACLBROKEN:
278 Log(Str[0],St(MACLBroken),Str[1]);
279 break;
280 case UIERROR_ACLUNKNOWN:
281 Log(Str[0],St(MACLUnknown),Str[1]);
282 break;
283 case UIERROR_ACLSET:
284 Log(Str[0],St(MACLSetError),Str[1]);
285 break;
286 case UIERROR_STREAMBROKEN:
287 Log(Str[0],St(MStreamBroken),Str[1]);
288 break;
289 case UIERROR_STREAMUNKNOWN:
290 Log(Str[0],St(MStreamUnknown),Str[1]);
291 break;
292 #endif
293 case UIERROR_INCOMPATSWITCH:
294 mprintf(St(MIncompatSwitch),Str[0],Num[0]);
295 break;
296 case UIERROR_PATHTOOLONG:
297 Log(NULL,L"\n%ls%ls%ls",Str[0],Str[1],Str[2]);
298 Log(NULL,St(MPathTooLong));
299 break;
300 #ifndef SFX_MODULE
301 case UIERROR_DIRSCAN:
302 Log(NULL,St(MScanError),Str[0]);
303 break;
304 #endif
305 case UIERROR_UOWNERBROKEN:
306 Log(Str[0],St(MOwnersBroken),Str[1]);
307 break;
308 case UIERROR_UOWNERGETOWNERID:
309 Log(Str[0],St(MErrGetOwnerID),Str[1]);
310 break;
311 case UIERROR_UOWNERGETGROUPID:
312 Log(Str[0],St(MErrGetGroupID),Str[1]);
313 break;
314 case UIERROR_UOWNERSET:
315 Log(Str[0],St(MSetOwnersError),Str[1]);
316 break;
317 case UIERROR_ULINKREAD:
318 Log(NULL,St(MErrLnkRead),Str[0]);
319 break;
320 case UIERROR_ULINKEXIST:
321 Log(NULL,St(MSymLinkExists),Str[0]);
322 break;
323 case UIERROR_READERRTRUNCATED:
324 Log(NULL,St(MErrReadTrunc),Str[0]);
325 break;
326 case UIERROR_READERRCOUNT:
327 Log(NULL,St(MErrReadCount),Num[0]);
328 break;
329 case UIERROR_DIRNAMEEXISTS:
330 Log(NULL,St(MDirNameExists));
331 break;
332
333 #ifndef SFX_MODULE
334 case UIMSG_STRING:
335 mprintf(L"\n%s",Str[0]);
336 break;
337 #endif
338 case UIMSG_CORRECTINGNAME:
339 Log(Str[0],St(MCorrectingName));
340 break;
341 case UIMSG_BADARCHIVE:
342 mprintf(St(MBadArc),Str[0]);
343 break;
344 case UIMSG_CREATING:
345 mprintf(St(MCreating),Str[0]);
346 break;
347 case UIMSG_RENAMING:
348 mprintf(St(MRenaming),Str[0],Str[1]);
349 break;
350 case UIMSG_RECVOLCALCCHECKSUM:
351 mprintf(St(MCalcCRCAllVol));
352 break;
353 case UIMSG_RECVOLFOUND:
354 mprintf(St(MRecVolFound),Num[0]);
355 break;
356 case UIMSG_RECVOLMISSING:
357 mprintf(St(MRecVolMissing),Num[0]);
358 break;
359 case UIMSG_MISSINGVOL:
360 mprintf(St(MAbsNextVol),Str[0]);
361 break;
362 case UIMSG_RECONSTRUCTING:
363 mprintf(St(MReconstructing));
364 break;
365 case UIMSG_CHECKSUM:
366 mprintf(St(MCRCFailed),Str[0]);
367 break;
368 case UIMSG_FAT32SIZE:
369 mprintf(St(MFAT32Size));
370 mprintf(L" "); // For progress percent.
371 break;
372
373
374
375 case UIEVENT_RRTESTINGSTART:
376 mprintf(L"%s ",St(MTestingRR));
377 break;
378 }
379 }
380
381
uiGetPassword(UIPASSWORD_TYPE Type,const wchar * FileName,SecPassword * Password)382 bool uiGetPassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password)
383 {
384 // Unlike GUI we cannot provide Cancel button here, so we use the empty
385 // password to abort. Otherwise user not knowing a password would need to
386 // press Ctrl+C multiple times to quit from infinite password request loop.
387 return GetConsolePassword(Type,FileName,Password) && Password->IsSet();
388 }
389
390
uiIsGlobalPasswordSet()391 bool uiIsGlobalPasswordSet()
392 {
393 return false;
394 }
395
396
uiAlarm(UIALARM_TYPE Type)397 void uiAlarm(UIALARM_TYPE Type)
398 {
399 if (uiSoundNotify==SOUND_NOTIFY_ON)
400 {
401 static clock_t LastTime=-10; // Negative to always beep first time.
402 if ((MonoClock()-LastTime)/CLOCKS_PER_SEC>5)
403 {
404 #ifdef _WIN_ALL
405 MessageBeep(-1);
406 #else
407 putwchar('\007');
408 #endif
409 LastTime=MonoClock();
410 }
411 }
412 }
413
414
415
416
uiAskNextVolume(wchar * VolName,size_t MaxSize)417 bool uiAskNextVolume(wchar *VolName,size_t MaxSize)
418 {
419 eprintf(St(MAskNextVol),VolName);
420 return Ask(St(MContinueQuit))!=2;
421 }
422
423
uiAskRepeatRead(const wchar * FileName,bool & Ignore,bool & All,bool & Retry,bool & Quit)424 void uiAskRepeatRead(const wchar *FileName,bool &Ignore,bool &All,bool &Retry,bool &Quit)
425 {
426 eprintf(St(MErrReadInfo));
427 int Code=Ask(St(MIgnoreAllRetryQuit));
428
429 Ignore=(Code==1);
430 All=(Code==2);
431 Quit=(Code==4);
432 Retry=!Ignore && !All && !Quit; // Default also for invalid input, not just for 'Retry'.
433 }
434
435
uiAskRepeatWrite(const wchar * FileName,bool DiskFull)436 bool uiAskRepeatWrite(const wchar *FileName,bool DiskFull)
437 {
438 mprintf(L"\n");
439 Log(NULL,St(DiskFull ? MNotEnoughDisk:MErrWrite),FileName);
440 return Ask(St(MRetryAbort))==1;
441 }
442
443
444 #ifndef SFX_MODULE
uiGetMonthName(int Month)445 const wchar *uiGetMonthName(int Month)
446 {
447 static MSGID MonthID[12]={
448 MMonthJan,MMonthFeb,MMonthMar,MMonthApr,MMonthMay,MMonthJun,
449 MMonthJul,MMonthAug,MMonthSep,MMonthOct,MMonthNov,MMonthDec
450 };
451 return St(MonthID[Month]);
452 }
453 #endif
454
455
uiEolAfterMsg()456 void uiEolAfterMsg()
457 {
458 if (AnyMessageDisplayed)
459 {
460 // Avoid deleting several last characters of any previous error message
461 // with percentage indicator in -idn mode.
462 AnyMessageDisplayed=false;
463 mprintf(L"\n");
464 }
465 }
466