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