OWLNext    7.0
Borland's Object Windows Library for the modern age
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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