OWLNext    7.0
Borland's Object Windows Library for the modern age
Loading...
Searching...
No Matches
filename.cpp
Go to the documentation of this file.
1//----------------------------------------------------------------------------
2// ObjectWindows
3// Copyright (c) 1995, 1996 by Borland International, All Rights Reserved
4//
5/// \file
6/// TFileName class implementation.
7//----------------------------------------------------------------------------
8#include <owl/pch.h>
9#include <owl/filename.h>
10#include <owl/private/memory.h>
11#include <owl/commdial.h>
12
13
14namespace owl {
15
16
17#define WIN95_LONGFILENAME_MAX 260
18
19 static tchar serverNamePrefix[] = _T("\\\\");
20 const int serverNamePrefixLen = sizeof serverNamePrefix / sizeof(tchar) - 1;
21// static tchar devTerminator[] = "\\/:";
22 static tchar ldevTerminatorCh = _T(':');
23 static tchar ldevTerminatorStr[] = _T(":");
24#if defined(UNIX)
25 static tchar dirSeparator[] = _T("/");
26// static tchar dirSeparatorCh = _T('/');
27 static tchar dirSeparatorStr[] = _T("/");
28#else
29 static tchar dirSeparator[] = _T("\\/");
30// static tchar dirSeparatorCh = _T('\\');
31 static tchar dirSeparatorStr[] = _T("\\");
32#endif //if UNIX
33 static tchar extSeparatorCh = _T('.');
34 static tchar extSeparatorStr[] = _T(".");
35
36
37//
38// Some Win32 APIs that are available under Win16 via DOS calls
39//
40
41//
42// overloaded functions to perform string scanning
43//
44static const tchar* fn_strend(const tchar* str)
45{
46 while (*str)
47 str++;
48 return str;
49}
50
51static const tchar* fn_find(const tchar* start, const tchar* end, int match)
52{
53 while (start != end && *start != match)
54 start++;
55 return start;
56}
57
58static const tchar* fn_find(const tchar* start, const tchar* end, const tchar* set)
59{
60 const tchar* setend = set + ::_tcslen(set);
61 while (start != end && fn_find(set, setend, *start) == setend)
62 start++;
63 return start;
64}
65
66static const tchar* fn_findl(const tchar* start, const tchar* end, int match)
67{
68 while (start != end && *start != match)
69 start--;
70 return start;
71}
72
73static const tchar* fn_findl(const tchar* start, const tchar* end, const tchar* set)
74{
75 const tchar* setend = set + ::_tcslen(set);
76 while (start != end && fn_find(set, setend, *start) == setend)
77 start--;
78 return start;
79}
80
81static const tchar* fn_skipstr(const tchar* start, const tchar* end,
82 const tchar* skip)
83{
84 while (start != end && *skip && *start == *skip)
85 start++, skip++;
86
87 return start;
88
89/*
90// TODO: Verify this does not break anything -jhh
91 if ((start[0] == '\\') && (start[1] == '\\'))
92 return &start[2];
93 else
94 return start;
95//jhh while (*skip && *start == *skip && start != end)
96//jhh start++, skip++;
97
98//jhh
99//jhh return start;
100*/
101}
102
103//-----
104// Low level helper functions for parsing filename parts
105//
106
107//
108//
109//
110static
111tstring __formServer(const tchar* serverName)
112{
113 if (!serverName)
114 return serverName;
115
116 const tchar* serverNameEnd = fn_strend(serverName);
117
118 if (_tcsncmp(serverName, serverNamePrefix, serverNamePrefixLen) == 0)
119 serverName += serverNamePrefixLen; // skip "\\"
120
121 const tchar* ds = fn_find(serverName, serverNameEnd, dirSeparator);
122 return tstring(serverName, 0, static_cast<int>(ds - serverName));
123}
124
125//
126//
127//
128static
129tstring __formDevice(const tchar* deviceName, bool isUNC)
130{
131 if (!deviceName)
132 return deviceName;
133
134 const tchar* deviceNameEnd = fn_strend(deviceName);
135
136
137 if (isUNC)
138 deviceNameEnd = fn_find(deviceName, deviceNameEnd, dirSeparator);
139 else
140 deviceNameEnd = fn_find(deviceName, deviceNameEnd, ldevTerminatorCh);
141
142 return tstring(deviceName, 0, static_cast<int>(deviceNameEnd - deviceName));
143}
144
145//
146// Return a well formed path from any kind of filename part. A lone name
147// is assumed to be just the path
148//
149static
150tstring __formPath(const tchar* path)
151{
152 if (!path)
153 return path;
154
155 const tchar* pathEnd = fn_strend(path);
156
157 // Find the start of the path, skipping logical device or server+share
158 //
159 const tchar* dvs = fn_find(path, pathEnd, ldevTerminatorCh);
160 if (dvs < pathEnd) {
161 path = dvs + 1; // skip logical device
162 }
163
164 return tstring(path, 0, static_cast<int>(pathEnd - path));
165}
166
167
168//
169// Return a well formed file from any kind of filename part. A lone name
170// is assumed to be just the file
171//
172// "dir.x\file.ext" -> "file"
173// "dir.x\" -> ""
174// "file" -> "file"
175//
176static
177tstring __formFile(const tchar* file)
178{
179 if (!file)
180 return file;
181
182 const tchar* fileEnd = fn_strend(file);
183
184 const tchar* ds = fn_findl(fileEnd-1, file-1, dirSeparator);
185 if (ds >= file)
186 file = ds + 1;
187
188 const tchar* es = fn_findl(fileEnd-1, file-1, extSeparatorCh);
189 if (es >= file)
190 fileEnd = es;
191
192 return tstring(file, 0, static_cast<int>(fileEnd - file));
193}
194
195//
196// Return a well formed extension from any kind of filename part. A lone name
197// is assumed to be just the extension and a '.' is prepended
198//
199// "dir.x\file.ext" -> ".ext"
200// "dir.x\" -> "."
201// "ext" -> ".ext"
202//
203static
204tstring __formExt(const tchar* ext)
205{
206 if (!ext)
207 return ext; // or extSeparatorCh?
208
209 const tchar* extEnd = fn_strend(ext);
210
211 const tchar* ds = fn_findl(extEnd-1, ext-1, dirSeparator);
212 if (ds >= ext)
213 ext = ds + 1;
214
215 const tchar* es = fn_findl(extEnd-1, ext-1, extSeparatorCh);
216 if (es >= ext)
217 return es;
218
219 return tstring(extSeparatorStr) + ext;
220}
221
222//
223/// Constructs an empty filename.
224//
228
229//
230/// Constructs a filename from another filename.
231//
233:
234 Unc(src.Unc),
235 ServerStr(src.ServerStr),
236 DeviceStr(src.DeviceStr),
237 PathStr(src.PathStr),
238 FileStr(src.FileStr),
239 ExtStr(src.ExtStr)
240{
242}
243
244//
245/// Constructs a filename from its parts. Use 0 to skip any of the parameters.
246/// The form is:
247/// \code
248/// filename := [[servername]devicename][path][file[ext]]
249/// \endcode
250/// where:
251/// \code
252/// servername := \\multiname\ //
253/// devicename := name(: | \ | :\‍)
254/// sharename := name
255/// logicaldevice := name
256///
257/// path := multiname\[...]
258/// file := multiname
259/// ext := [.[name]]
260///
261/// name := (filecharset)[...]
262/// multiname := (filecharset | .)[...]
263/// \endcode
266{
267 ServerStr = __formServer(serverName);
268
269 Unc = serverName != nullptr;
270
271 DeviceStr = __formDevice(deviceName, Unc);
272 PathStr += __formPath(path);
273 FileStr += __formFile(file);
274 ExtStr += __formExt(ext);
276}
277
278
279//
280/// Parses the freeform string into the filename parts.
281//
282void
284{
285 const tchar* nextp;
286 const tchar* freeformEnd = fn_strend(freeform);
287
288 if (*freeform == '\0')
289 {
290 Unc = false;
291 ServerStr = _T("");
292 DeviceStr = _T("");
293 ExtStr = _T("");
294 PathStr = _T("");
295 FileStr = _T("");
297 return;
298 }
299 // Parse from the left, the server name and device if UNC "\\", or the
300 // logical device name if one.
301 //
302 nextp = fn_skipstr(freeform, freeformEnd, serverNamePrefix);
304 Unc = true;
305 freeform = nextp; // skip "\\"
306 nextp = fn_find(freeform, freeformEnd, dirSeparator);
307 ServerStr = tstring(freeform, 0, static_cast<int>(nextp-freeform));
308 freeform = nextp + 1; // skip past "\"
309
310 nextp = fn_find(freeform, freeformEnd, dirSeparator);
311 DeviceStr = tstring(freeform, 0, static_cast<int>(nextp-freeform));
312 freeform = nextp + 1; // skip past "\"
313 }
314 else {
315 Unc = false;
316 ServerStr = _T("");
317
318 nextp = fn_find(freeform, freeformEnd, ldevTerminatorCh);
319 if (nextp != freeformEnd) {
320 DeviceStr = tstring(freeform, 0, static_cast<int>(nextp-freeform));
321 freeform = nextp + 1; // skip past "\/:"
322 }
323 else
324 DeviceStr = _T("");
325 }
326
327 if (!pathOnly){
328 // Parse the extension and filename from the right.
329 //
330 nextp = fn_findl(freeformEnd-1, freeform-1, extSeparatorCh);
331 //DLN freeform is just before first char in string, so boundschecker will
332 // report an erroneous error here
333 const tchar* dirp = fn_findl(freeformEnd-1, freeform-1, dirSeparator);
334
335 if (nextp > dirp) {
336 ExtStr = tstring(nextp, 0, static_cast<int>(freeformEnd-nextp));
338 }
339 else
340 ExtStr = _T("");
341
342 FileStr = tstring(dirp+1, 0, static_cast<int>(freeformEnd - (dirp+1)));
344 }
345 else{
346 FileStr = _T("");
347 ExtStr = _T("");
348 }
349
350 // What is left is the path
351 //
352 if (freeformEnd > freeform)
353 PathStr = tstring(freeform, 0, static_cast<int>(freeformEnd-freeform));
354 else
355 PathStr = _T("");
357}
358
359//
360/// Construct a filename given the full path in any form
361//
366
367
368//
369/// Construct a filename given the full path in any form
370//
375
376
377//
378/// Construct a filename representing a special file or directory. The parameter
379/// type can be specified from TSpecialType.
380/// \todo Looks like not all the types are implemented or work correctly. Need to research
381///
382//
384{
385 switch (type) {
386 case TempFile:
387 case TempDir: {
388 int tmpLen = ::GetTempPath(0,nullptr);
392 if (type == TempDir) {
393 //_tcscat(tmpPath,dirSeparatorStr); // !BUG: Writes past EOB. Also, path already has trailing backslash. [VH]
394 Parse(tmpPath,true);
395 }
396 else {
398 ::GetTempFileName(static_cast<tchar*>(tmpPath), _T("TFN"), 0, tmpFile);
399 Parse(static_cast<tchar*>(tmpFile));
400 }
401 }
402 break;
403 case CurrentDir: {
406 _tcscat(static_cast<tchar*>(buffer), dirSeparatorStr);
407 Parse((tchar*)buffer,true);
408 }
409 break;
410 case HomeDir: {
413 _tcscat(static_cast<tchar*>(buffer),dirSeparatorStr);
414 Parse(static_cast<tchar*>(buffer),true);
415 }
416 break;
417 case BootDir:{
418 LPCTSTR path = _tgetenv(_T("wonbootdir"));
419 if(path)
420 Parse(path,true);
421 break;
422 }
423 case MachineDir:
424 // !Y.B ??????????????
425 case SharedDir:
426 // !Y.B ??????????????
427 break;
428 case SysDir: {
431 _tcscat(tmp,dirSeparatorStr);
432 Parse(tmp,true);
433 }
434 break;
435 case ComputerName: {
438 ::GetComputerName(tmp, &size);
439
440 Parse(tmp);
441 }
442 break;
443 }
444}
445
446
447//
448/// Assigns new filename or freeform to this name.
449//
452{
453 Unc = src.Unc;
454 ServerStr = src.ServerStr;
455 DeviceStr = src.DeviceStr;
456 PathStr = src.PathStr;
457 FileStr = src.FileStr;
458 ExtStr = src.ExtStr;
460 return *this;
461}
462
463
464//
465//
466//
467
468
469// JJH this function is not used
470//static void
471//ForceFullPath(string& canonical)
472//{
473// if (canonical != "")
474// {
475// tchar buffer[WIN95_LONGFILENAME_MAX];
476// ::GetFullPathName(canonical.c_str(), WIN95_LONGFILENAME_MAX, buffer, 0);
477// canonical = buffer;
478// }
479//}
480
481
483{
484 return const_cast<tchar*>(CanonicalStr());
485}
486
487//
488// Reassemble the filename parts into a canonical form & expand any relative
489// dirs
490//
491
492//string TFileName::Canonical(bool forceUNC) const
494{
495// if (forceUNC)
496// {
497// strcpy(NameBuffer,serverNamePrefix);
498// strcat(NameBuffer,DeviceStr);
499// strcat(NameBuffer, dirSeparatorStr);
500// strcat(NameBuffer,PathStr);
501// strcat(NameBuffer,dirSeparatorStr);
502// strcat(NameBuffer,FileStr);
503// strcat(NameBuffer,ExtStr);
504// else
505 GetParts(Server|Device|Path|File|Ext); //fills NameBuffer
506
507 if (_tcscmp(NameBuffer,_T(""))) //if file name is not blank
508 { // use it to get official file name
512 }
513 else
515// return NameBuffer;
516}
517
518/// Return normal fully qualified path string. Convert a possibly logical drive based
519/// name to a UNC name if indicated.
521{
522 return FullCanonicalName;
523}
524
526{
527 return const_cast<tchar*>(GetParts(File));
528}
529
531{
532 return const_cast<tchar*>(GetParts(File|Ext));
533}
534
536{
537 return const_cast<tchar*>(GetParts(Server|Device|Path|File)); //fills NameBuffer
538}
539
540
541
542//
543/// Returns the short file path. Convert a possibly logical drive based name to a
544/// UNC name if indicated.
545//
546const tchar*
555
556
557//
558/// The Title member function uses system conventions to get a human-readable
559/// rendering of the filename appropriate for use in titles.
560/// \note Returns null string for directory names or malformed names. For
561/// directories, try Canonical() instead.
562//
564{
567 if (GetFileTitle(canonical.c_str(), tmp, COUNTOF(tmp)) == 0)
569 else
570 NameBuffer[0] = _T('\0');
571 return static_cast<tchar*>(NameBuffer);
572}
573
574
575//
576// input filemame.ext
577// output file...
578//
579static tstring& trimmStr(tstring& s, uint len)
580{
581 if(s.length() < len)
582 return s;
583 s.erase(len-3);
584 s += _T("...");
585 return s;
586}
587
588//
589// input ProgrammFiles\Common File\New Files\Short
590// output ProgrammFiles\...\Short
591//
592static tstring& trimPath(tstring& s, uint len)
593{
594 if(s.length() < len)
595 return s;
596
597 const tchar* addPath = _T("\\...");
598 // find ?
599 // 1. get last path path1\path2\path3 -> \path3
600 tstring subpath = s;
601 const auto pos = subpath.find_last_of(dirSeparatorStr);
602 if (pos == subpath.npos || len <= 5)
603 {
604 s = addPath;
605 return s;
606 }
607
608 tstring lastpath = subpath.substr(pos);
609 subpath.erase(pos);
610
611 // calculate minimum path length include "\\..."
612 int length = static_cast<int>(len - 4 - lastpath.length());
613 while(length < 0 && lastpath.length() > 0){
614 lastpath = lastpath.substr(1); //Remove the first character
615 length = static_cast<int>(len - 4 - lastpath.length());
616 }
617 uint iteration = 0;
618
619 // while remainig string greater then our length
620 while(static_cast<int>(subpath.length()) > length && subpath.length() > 0){
621 const auto pos = subpath.find_last_of(dirSeparatorStr);
622 if (pos != subpath.npos)
623 subpath.erase(pos);
624 else
625 subpath = _T("");
626
627 iteration++;
628 }
629
630 // if was only one path1 -> lastpath => path1, and subpath => 0
631 if(iteration){
632 s = subpath;
633 s += addPath;
634 s += lastpath;
635 }
636 else if(s.length() > len){
637 s = subpath;
638 s += addPath;
639 }
640
641 return s;
642}
643//
644static tstring getAttempt(const TFileName& This, const tstring& name,
645 int index)
646{
647 uint parts[] = {
651 };
652 tstring attempt = This.GetParts(parts[index]);
653 if(!attempt.empty()){
654 tchar lastCh = attempt.c_str()[attempt.length()-1];
655 if(lastCh != _T('\\') && lastCh != _T('/'))
656 attempt += dirSeparatorStr;
657 }
658 attempt += name;
659 return attempt;
660}
661//
662/// Obtains a human-readable form of the filename. The name length is at most maxLen
663/// characters.
664/// \code
665/// lpszCanon = C:\MYAPP\DEBUGS\C\TESWIN.C
666///
667/// maxLen b Result
668/// ------ - ---------
669/// 1-3 F <empty>
670/// 4 F T...
671/// 5 F TE...
672/// 6 F TES...
673/// 7 F TESW...
674/// 4- 7 T TESWIN.C
675/// 8-14 x TESWIN.C
676/// 15-16 x C:\...\TESWIN.C
677/// 17-23 x C:\MYAPP\...\TESWIN.C
678/// 24-25 x C:\MYAPP\...\C\TESWIN.C
679/// 26+ x C:\MYAPP\DEBUGS\C\TESWIN.C
680/// \endcode
681//
683{
684 if (maxLen <= 3)
685 return _T("");
686
687 const uint n = static_cast<uint>(maxLen);
688 tstring fname = Title();
689 tstring attempt = getAttempt(*this, fname, 0); // full path
690
691 // If maxLen is not enough to hold the full path name, then trim.
692 // If maxLen is enough to hold at least the basename, and enough
693 // to hold at least server/device and "...\", trim the path,
694 // otherwise trim (or keep) only the basename.
695
696 if (n < attempt.length())
697 {
698 const tstring dname = getAttempt(*this, fname, 1); // server-device/name
699 if (n > dname.length() + 3)
700 {
701 tstring p = PathStr;
702 trimPath(p, n - static_cast<int>(dname.length()));
703 if (p.length() > 0 && p[p.length() - 1] != dirSeparatorStr[0])
704 p += dirSeparatorStr;
706 }
707 else
708 {
709 attempt = keepName ? fname : trimmStr(fname, n);
710 }
711 }
712
713 CHECK(attempt.length() < _MAX_PATH - 1);
714 _tcscpy(NameBuffer,attempt.c_str());
715 return NameBuffer;
716}
717
718
719//
720/// Determines whether a filename is valid.
721//
722bool
724{
726 ofs.cBytes = sizeof ofs;
728 return ::OpenFile(_W2A(CanonicalStr()), &ofs, OF_PARSE) != -1;
729}
730
731//
732/// Determines whether the device, directory, or file exists.
733//
734bool
736{
737#if 0
739 ofs.cBytes = sizeof ofs;
741 return ::OpenFile(_W2A(Canonical().c_str()), &ofs, OF_EXIST) != -1;
742#else
743 HANDLE h;
744 {
747 ::FindClose(h);
748 }
749 return (h != INVALID_HANDLE_VALUE);
750#endif
751}
752
753
754//
755/// Reassembles any logical subset of filename parts. More than one part can be
756/// checked for by bitwise oring in the parameter p. See TFileName::TPart.
757//
758const tchar*
760{
761 *NameBuffer = 0; //JRB This crashes GWANGI
762
763
764 if (Unc)
765 {
766 if (p & Server)
767 {
768 _tcscat(NameBuffer,serverNamePrefix);
770 if (p & Device)
771 _tcscat(NameBuffer,dirSeparatorStr);
772 }
773 if ((p & Device) && DeviceStr.length() > 0) {
774 _tcscat(NameBuffer, DeviceStr.c_str());
775 if ((p & Path) || (p & File))
776 _tcscat(NameBuffer, dirSeparatorStr);
777 }
778 }
779 else
780 {
781 if ((p & Device) && DeviceStr.length() > 0) {
782 _tcscat(NameBuffer, DeviceStr.c_str());
783 _tcscat(NameBuffer, ldevTerminatorStr);
784 if ((p & Path) && PathStr.length() == 0) {
785 _tcscat(NameBuffer, dirSeparatorStr);
786 }
787 }
788 }
789
790 if ((p & Path) && PathStr.length() > 0)
791 {
792 _tcscat(NameBuffer,PathStr.c_str());
793 _tcscat(NameBuffer, dirSeparatorStr);
794 }
795
796 if ((p & File) && FileStr.length() > 0)
797 _tcscat(NameBuffer, FileStr.c_str());
798
799 if ((p & Ext) && ExtStr.length() > 0)
800 _tcscat(NameBuffer, ExtStr.c_str());
801 return (tchar*)NameBuffer;
802
803}
804
805//
806/// Returns true if any of the parts specified by p are used. More than one part can
807/// be checked for by bitwise oring in the parameter p. See TFileName::TPart.
808//
809bool
811{
812 bool has = false;
813 if (p & Server)
814 has |= (ServerStr.length() > 0);
815 if (p & Device)
816 has |= (DeviceStr.length() > 0);
817 if (p & Path)
818 has |= (PathStr.length() > 0);
819 if (p & File)
820 has |= (FileStr.length() > 0);
821 if (p & Ext)
822 has |= (ExtStr.length() > 0);
823 return has;
824}
825
826//
827/// Replaces the specified filename parts with parts extracted from partStr. More
828/// than one part can be checked for by bitwise oring in the parameter p. See TFileName::TPart.
829//
832{
833 if (p & Server)
835 if (p & Device)
837 if (p & Path)
839 if (p & File)
841 if (p & Ext)
842 ExtStr = partStr;
844 return *this;
845}
846
847
848//
849/// Replaces the specified parts in this with the parts from source. More than one
850/// part can be merged by bitwise oring in the parameter p. See TFileName::TPart.
851//
854{
855 // Walk thru bits & SetPart(p) from source.GetParts(p)
856 //
857 if (p & Server)
858 ServerStr = source.ServerStr;//source.GetParts(Server);
859 if (p & Device)
860 DeviceStr = source.DeviceStr;//source.GetParts(Device);
861 if (p & Path)
862 PathStr = source.PathStr;//source.GetParts(Path);
863 if (p & File)
864 FileStr = source.FileStr;//source.GetParts(File);
865 if (p & Ext)
866 ExtStr = source.ExtStr;//source.GetParts(Ext);
867
868 FormCanonicalName(); // BUGFIX: FullCanonicalName wasn't updated! (VH, 2005-07-26)
869 return *this;
870}
871
872//
873/// Removes the specified filename parts from this set of parts. More than one part
874/// can be checked for by bitwise oring in the parameter p. See TFileName::TPart.
875//
878{
879 if (p & Server)
880 ServerStr = _T("");
881 if (p & Device)
882 DeviceStr = _T("");
883 if (p & Path)
884 PathStr = _T("");
885 if (p & File)
886 FileStr = _T("");
887 if (p & Ext)
888 ExtStr = _T("");
889
890 FormCanonicalName(); // BUGFIX: FullCanonicalName wasn't updated! (VH, 2005-07-26)
891 return *this;
892}
893
894//
895/// Deletes this file associated with this name if possible; otherwise attempts to
896/// delete the directory associated with this name (which must be empty).
897//
898bool
900{
903 return false;
904 return true;
905}
906
907//
908/// Move (rename) the file associated with this filename, and change this name to
909/// the new name.
910///
911/// Under WinNT how is used to specifie how the file is to be copied:
912/// - ReplaceExisting = 1
913/// - CopyAllowed = 2
914/// - DelayUntilReboot = 4
915//
916bool
918{
919 bool retval = ::MoveFileEx(CanonicalStr(), newName.CanonicalStr(), how);
920
921 if(retval){
922 *this = newName;
923 return true;
924 }
925
926 return false;
927}
928
929//
930/// Copy the file associated with this filename to a new file. If failIfExists is
931/// true, the copy will not take place if a file newName already exists.
932//
933bool
935{
936 return ::CopyFile(CanonicalStr(), newName.CanonicalStr(), failIfExists) != FALSE;
937}
938
939//
940/// Creates the directory associated with this filename.
941///
942/// Returns a non-zero value on success. Call LastError for extended information.
943//
944int
946{
947 return ::CreateDirectory(CanonicalStr(), 0) != FALSE; //LPSECURITY_ATTRIBUTES
948}
949
950//
951/// Changes the current directory to the directory associated with this filename.
952///
953/// Returns a non-zero value on success. Call LastError for extended information.
954//
955int
957{
958 return ::SetCurrentDirectory(CanonicalStr()) != FALSE;
959}
960
963{
964 if (_tcschr(dirSeparator, subdir[0]) == nullptr) // The subdir does not begin with the separator
965 PathStr += dirSeparatorStr;
966
967 PathStr += subdir;
968
969 if (_tcschr(dirSeparator, PathStr[PathStr.length() - 1]) != nullptr) // The resultring string ends with the separator
970 PathStr = PathStr.substr(0, PathStr.length() - 1);
971
973 return *this;
974}
975
976
977///////////////////////
978// struct __TFindFileStr
979// ~~~~~~ ~~~~~~~~~~~~~~
980//
981/// \cond
982struct __TFindFileStr{
983 HANDLE Handle;
984 WIN32_FIND_DATA Data;
986};
987/// \endcond
988
990void __MakeDosTime(const TTime& ctm, uint16& fdm, uint16& ftm);
993static
994void __FillFileStr( __TFindFileStr& data, TFileStatus& status);
995
996
997static
998void __FillFileStr( __TFindFileStr& data, TFileStatus& status)
999{
1000 ::_tcscpy(status.fullName, data.Data.cFileName);
1001 status.attribute = __sys2Atr(data.Data.dwFileAttributes);
1002 status.createTime = TTime(TFileTime(data.Data.ftCreationTime));
1003 status.modifyTime = TTime(TFileTime(data.Data.ftLastWriteTime));
1004 status.accessTime = TTime(TFileTime(data.Data.ftLastAccessTime));
1005 status.size = data.Data.nFileSizeLow;
1006}
1007
1008
1009//
1010/// Get the file status struct for the item associated with this filename.
1011//
1013{
1016 findData.Handle = ::FindFirstFile(fileName.c_str(), &findData.Data);
1017 if(findData.Handle == INVALID_HANDLE_VALUE)
1018 return false;
1019
1020 __FillFileStr(findData, status);
1021 ::_tcscpy(status.fullName, fileName.c_str());
1022
1023
1024 ::FindClose(findData.Handle);
1025
1026 return true;
1027}
1028
1029
1030//
1031/// Fills the status structure for the file associated with this filename with
1032/// information from status.
1033//
1035{
1037 {
1039 if(!File.IsOpen())
1040 return false;
1041 if(!File.Length(status.size))
1042 return false;
1046
1047 // will work only for TDiskFileHandle
1050 return false;
1051 }
1052 uint attr = __attr2Sys(status.attribute);
1053 if(!::SetFileAttributes(fileName.c_str(), attr))
1054 {
1055# pragma warn -ccc
1056 WARN(1, "TFile::SetStatus() error ::SetFileAttributes(), line: " << __LINE__);
1057# pragma warn .ccc
1058 return false;
1059 }
1060
1061 return true;
1062}
1063
1064//
1065//
1066/// Under Win32 a WIN32_FIND_DATA structure (the Data member) is allocated and
1067/// intialized. If a file is not found the Done member is set true; otherwise the
1068/// data structure is filled in.
1069///
1070/// wildName may contain wild card characters and a path.
1071//
1073:
1074 Done(false)
1075{
1077 Data = data;
1078 tchar* p = const_cast<tchar*>(_tcsrchr(wildName.c_str(),_T('\\')));
1079 if(p){
1080 tchar c = *p;
1081 *p = _T('\0');
1082 data->Direct = tstring(wildName.c_str()) + _T("\\");
1083 *p = c;
1084 }
1085
1086 data->Handle = ::FindFirstFile(wildName.c_str(), &data->Data);
1087 if(data->Handle != INVALID_HANDLE_VALUE){
1088 __FillFileStr( *data, Status);
1089 }
1090 else
1091 Done = true;
1092}
1093//------------------------------------------------------------------------------
1094/// Deletes the find file Data structure.
1096{
1097 if (Data && (static_cast<__TFindFileStr*>(Data))->Handle != INVALID_HANDLE_VALUE)
1098 ::FindClose((static_cast<__TFindFileStr*>(Data))->Handle);
1099
1100 delete static_cast<__TFindFileStr*>(Data);
1101}
1102//------------------------------------------------------------------------------
1103/// Attempts to find the next file. Returns a true if found, false otherwise.
1104//
1106{
1107 __TFindFileStr& data = *static_cast<__TFindFileStr*>(findData);
1108 if (!::FindNextFile(data.Handle, &data.Data))
1109 return false;
1110
1111 __FillFileStr(data, status);
1112 return true;
1113}
1114
1115//==============================================================================
1116
1117} // OWL namespace
1118
#define CHECK(condition)
Definition checks.h:239
#define WARN(condition, message)
Definition checks.h:273
The TFile class encapsulates standard file characteristics and operations.
Definition file.h:120
@ WriteOnly
Definition file.h:131
@ OpenExisting
Opens the file. The function fails if the file does not exist.
Definition file.h:151
@ PermExclusive
Definition file.h:141
The TFileName class constructs filenames.
Definition filename.h:37
bool Exists() const
Determines whether the device, directory, or file exists.
Definition filename.cpp:735
TFileName()
Constructs an empty filename.
Definition filename.cpp:225
const tchar * Title() const
The Title member function uses system conventions to get a human-readable rendering of the filename a...
Definition filename.cpp:563
const tchar * CanonicalStr(bool forceUNC=false) const
Definition filename.h:252
tstring DeviceStr
Holds the device filename part.
Definition filename.h:45
TFileName & StripParts(uint p)
Removes the specified filename parts from this set of parts.
Definition filename.cpp:877
tchar NameBuffer[_MAX_PATH]
Definition filename.h:57
void FormCanonicalName()
Definition filename.cpp:493
tchar * GetFullFileNameNoExt()
Definition filename.cpp:535
TFileName & MergeParts(uint p, const TFileName &source)
Replaces the specified parts in this with the parts from source.
Definition filename.cpp:853
@ Device
Logical device or sharename.
Definition filename.h:127
@ Path
Directory path to the file.
Definition filename.h:128
@ Ext
Extension.
Definition filename.h:130
@ File
Filename part without the extension.
Definition filename.h:129
@ Server
Server name.
Definition filename.h:126
tchar * GetNameAndExt() const
Definition filename.cpp:530
tstring ServerStr
Holds the server filename part.
Definition filename.h:42
const tstring & Canonical(bool forceUNC=false) const
Return normal fully qualified path string.
Definition filename.cpp:520
void Parse(LPCTSTR freeform, bool pathOnly=false)
Parses the freeform string into the filename parts.
Definition filename.cpp:283
int CreateDir() const
Creates the directory associated with this filename.
Definition filename.cpp:945
TFileName & SetPart(uint p, const tstring &partStr)
Replaces the specified filename parts with parts extracted from partStr.
Definition filename.cpp:831
int GetStatus(TFileStatus &status) const
Get the file status struct for the item associated with this filename.
int ChangeDir() const
Changes the current directory to the directory associated with this filename.
Definition filename.cpp:956
tstring ExtStr
Holds the extension filename part.
Definition filename.h:54
const tchar * Squeezed(int maxLen, bool keepName=true) const
Obtains a human-readable form of the filename.
Definition filename.cpp:682
bool Unc
true if UNC naming convention in use; false otherwise.
Definition filename.h:60
const tchar * GetParts(uint p) const
Reassembles any logical subset of filename parts.
Definition filename.cpp:759
const tchar * ShortName(bool forceUNC=false) const
Returns the short file path.
Definition filename.cpp:547
tchar * GetNameNoExt()
Definition filename.cpp:525
bool IsValid() const
Determines whether a filename is valid.
Definition filename.cpp:723
bool Move(const TFileName &newName, uint32 how=CopyAllowed)
Move (rename) the file associated with this filename, and change this name to the new name.
Definition filename.cpp:917
TFileName & operator=(const TFileName &src)
Assigns new filename or freeform to this name.
Definition filename.cpp:451
bool Copy(const TFileName &newName, bool failIfExists) const
Copy the file associated with this filename to a new file.
Definition filename.cpp:934
tstring FileStr
Holds the file filename part (no extension).
Definition filename.h:51
tchar * GetFullFileName()
Definition filename.cpp:482
tstring PathStr
Holds the path filename part.
Definition filename.h:48
TSpecialType
Construct a filename representing a special file or directory.
Definition filename.h:91
@ SysDir
Location of system files (LDID_SYS)
Definition filename.h:99
@ MachineDir
(LDID_MACHINE) currently not implemented?
Definition filename.h:96
@ SharedDir
Shared home directory for OS (LDID_SHARED) currently not implemented?
Definition filename.h:98
@ BootDir
Root dir of boot device (LDID_BOOT)
Definition filename.h:95
@ TempDir
Location of temporary files.
Definition filename.h:93
@ CurrentDir
Current working directory if any.
Definition filename.h:94
@ HomeDir
Home directory for OS (LDID_WIN)
Definition filename.h:97
@ TempFile
A temporary filename.
Definition filename.h:92
bool HasParts(uint p) const
Returns true if any of the parts specified by p are used.
Definition filename.cpp:810
tstring FullCanonicalName
Definition filename.h:56
int SetStatus(const TFileStatus &status)
Fills the status structure for the file associated with this filename with information from status.
TFileName & AddSubDir(const tstring &subdir)
Definition filename.cpp:962
bool Remove() const
Deletes this file associated with this name if possible; otherwise attempts to delete the directory a...
Definition filename.cpp:899
TFileStatus Status
Status of last attempt to find a file. See TFileStatus structure.
Definition filename.h:215
virtual ~TFileNameIterator()
Deletes the find file Data structure.
void * Data
Under Win32 a pointer to a WIN32_FIND_DATA structure.
Definition filename.h:212
virtual bool FindNext(TFileStatus &status, void *findData)
all work do here -> must fill TFileStatus structure return true on success
bool Done
Set false in the constructor.
Definition filename.h:209
TFileTime is a class derived from the structure FILETIME.
Definition wsyscls.h:362
Definition of Common Dialog abstract base class.
#define _tcscmp
Definition cygwin.h:75
#define _tcscat
Definition cygwin.h:83
#define _tcscpy
Definition cygwin.h:79
#define _MAX_PATH
Definition cygwin.h:97
#define _tcsncmp
Definition cygwin.h:78
#define _tcslen
Definition cygwin.h:74
#define _T(x)
Definition cygwin.h:51
#define _tcschr
Definition cygwin.h:85
#define _tcsrchr
Definition cygwin.h:86
#define WIN95_LONGFILENAME_MAX
Definition filename.cpp:17
Reliable platform independent header for common memory and string functions.
#define _W2A(lpw)
Definition memory.h:219
#define _USES_CONVERSION
Definition memory.h:217
Object Windows Library (OWLNext Core)
Definition animctrl.h:22
void __MakeDosTime(const TTime &time, uint16 &fdate, uint16 &ftime)
uint __sys2Atr(uint32 attrib)
Definition file.cpp:312
unsigned long uint32
Definition number.h:34
char tchar
Definition defs.h:77
TTime __MakeTTime(uint16 fdate, uint16 ftime)
unsigned short uint16
Definition number.h:33
std::string tstring
Definition defs.h:79
unsigned int uint
Definition number.h:25
const int serverNamePrefixLen
Definition filename.cpp:20
uint __attr2Sys(uint attrib)
Definition file.cpp:331
#define COUNTOF(s)
Array element count Important: Only use this with an argument of array type.
Definition defs.h:376
#define TYPESAFE_DOWNCAST(object, toClass)
Definition defs.h:269
uint32 size
Definition file.h:39
tchar fullName[_MAX_PATH]
Definition file.h:41
uint attribute
Definition file.h:40
TTime modifyTime
Definition file.h:37
TTime createTime
Definition file.h:36
TTime accessTime
Definition file.h:38