FileSel.cpp

Zbigniew Rebacz, 02/04/2014 04:34 PM

Download (47.4 KB)

 
1
#include <CtrlLib/CtrlLib.h>
2

    
3
NAMESPACE_UPP
4

    
5
#ifdef GUI_WIN
6
void AvoidPaintingCheck__();
7

    
8
Image ProcessSHIcon(const SHFILEINFO& info)
9
{
10
        AvoidPaintingCheck__();
11
        Color c = White();
12
        Image m[2];
13
        for(int i = 0; i < 2; i++) {
14
                ICONINFO iconinfo;
15
                if(!info.hIcon || !GetIconInfo(info.hIcon, &iconinfo))
16
                        return Image();
17
                BITMAP bm;
18
                ::GetObject((HGDIOBJ)iconinfo.hbmMask, sizeof(BITMAP), (LPVOID)&bm);
19
                Size sz(bm.bmWidth, bm.bmHeight);
20
                ImageDraw iw(sz);
21
                iw.DrawRect(sz, c);
22
                ::DrawIconEx(iw.GetHandle(), 0, 0, info.hIcon, 0, 0, 0, NULL, DI_NORMAL|DI_COMPAT);
23
                ::DeleteObject(iconinfo.hbmColor);
24
                ::DeleteObject(iconinfo.hbmMask);
25
                c = Black();
26
                m[i] = iw;
27
        }
28
        ::DestroyIcon(info.hIcon);
29
        return RecreateAlpha(m[0], m[1]);
30
}
31

    
32
struct FileIconMaker : ImageMaker {
33
        String file;
34
        bool   exe;
35
        bool   dir;
36
        bool   large;
37

    
38
        virtual String Key() const {
39
                return file + (exe ? "1" : "0") + (dir ? "1" : "0");
40
        }
41

    
42
        virtual Image Make() const {
43
                SHFILEINFO info;
44
                AvoidPaintingCheck__();
45
                SHGetFileInfo(ToSystemCharset(file), dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL,
46
                              &info, sizeof(info),
47
                              SHGFI_ICON|(large ? SHGFI_LARGEICON : SHGFI_SMALLICON)|(exe ? 0 : SHGFI_USEFILEATTRIBUTES));
48
                return ProcessSHIcon(info);
49
        }
50
};
51

    
52

    
53
Image GetFileIcon(const char *path, bool dir, bool force, bool large, bool quick = false)
54
{
55
        FileIconMaker m;
56
        String ext = GetFileExt(path);
57
        m.exe = false;
58
        m.dir = false;
59
        m.file = path;
60
        m.large = large;
61
        if(force)
62
                m.exe = true;
63
        else
64
        if(dir) {
65
                m.dir = true;
66
                m.exe = true;
67
        }
68
        else
69
        if(ext == ".exe")
70
                m.exe = true;
71
        else
72
                m.file = "x." + ext;
73
        if(quick) {
74
                m.exe = false;
75
                m.file = "x." + ext;
76
        }
77
        return MakeImage(m);
78
}
79

    
80
#define GETFILEICON_DEFINED
81

    
82
#endif
83

    
84
#if defined(PLATFORM_X11) && !defined(flagNOGTK)
85

    
86
Image GtkThemeIcon(const char *name, bool large);
87

    
88
Image GnomeImage(const char *s, bool large = false)
89
{
90
        return GtkThemeIcon(String("gnome-") + s, large);
91
}
92

    
93
Image SystemImage(const char *s, bool large = false)
94
{
95
        return GtkThemeIcon(s, large);
96
}
97

    
98
struct ExtToMime {
99
        Index<String> major;
100
        Index<String> minor;
101
        VectorMap<String, dword> map;
102

    
103
        void Load(const char *file);
104
        void Refresh();
105
        bool GetMime(const String& ext, String& maj, String& min);
106
};
107

    
108
void ExtToMime::Load(const char *fn)
109
{
110
        FileIn in(fn);
111
        if(in)
112
                while(!in.IsEof()) {
113
                        String ln = TrimLeft(TrimRight(in.GetLine()));
114
                        if(ln[0] != '#') {
115
                                int q = ln.Find(':');
116
                                if(q >= 0) {
117
                                        String h = ln.Mid(0, q);
118
                                        int w = h.Find('/');
119
                                        if(w >= 0) {
120
                                                int x = ln.Find("*.", q);
121
                                                if(x >= 0) {
122
                                                        String ext = ln.Mid(x + 2);
123
                                                        if(ext.GetCount() && map.Find(ext) < 0)
124
                                                                map.Add(ext, MAKELONG(minor.FindAdd(h.Mid(w + 1)), major.FindAdd(h.Mid(0, w))));
125
                                                }
126
                                        }
127
                                }
128
                        }
129
                }
130
}
131

    
132
void ExtToMime::Refresh()
133
{
134
        major.Clear();
135
        minor.Clear();
136
        map.Clear();
137
        Load("/usr/local/share/mime/globs");
138
        Load("/usr/share/mime/globs");
139
}
140

    
141
bool ExtToMime::GetMime(const String& ext, String& maj, String& min)
142
{
143
        ONCELOCK {
144
                Refresh();
145
        }
146
        int q = map.Find(ext);
147
        if(q < 0)
148
                return false;
149
        dword x = map[q];
150
        maj = major[HIWORD(x)];
151
        min = minor[LOWORD(x)];
152
        return true;
153
}
154

    
155
struct FileExtMaker : ImageMaker {
156
        String ext;
157
        bool   large;
158

    
159
        virtual String Key() const {
160
                return ext;
161
        }
162

    
163
        virtual Image Make() const {
164
                String major;
165
                String minor;
166
                if(!Single<ExtToMime>().GetMime(ext, major, minor))
167
                        return Null;
168
                Image img = SystemImage(major + '-' + minor, large);
169
                return IsNull(img) ? SystemImage(major) : img;
170
        }
171
};
172

    
173
Image PosixGetDriveImage(String dir, bool large)
174
{
175
        static bool init = false;
176
        static Image cdrom;
177
        static Image lcdrom;
178
        static Image harddisk;
179
        static Image lharddisk;
180
        static Image floppy;
181
        static Image lfloppy;
182
        static Image computer;
183
        static Image lcomputer;
184
        
185
        if (!init) {
186
                bool KDE = Environment().Get("KDE_FULL_SESSION", String()) == "true";
187
                if (KDE) {
188
                        cdrom     = SystemImage("media-optical");
189
                        lcdrom    = SystemImage("media-optical", true);
190
                        harddisk  = SystemImage("drive-harddisk");
191
                        lharddisk = SystemImage("drive-harddisk", true);
192
                        floppy    = SystemImage("media-floppy");
193
                        lfloppy   = SystemImage("media-floppy", true);
194
                        computer  = SystemImage("computer");
195
                        lcomputer = SystemImage("computer", true);
196
                }
197
                else {
198
                        cdrom     = GnomeImage("dev-cdrom");
199
                        lcdrom    = GnomeImage("dev-cdrom", true);
200
                        harddisk  = GnomeImage("dev-harddisk");
201
                        lharddisk = GnomeImage("dev-harddisk", true);
202
                        floppy    = GnomeImage("dev-floppy");
203
                        lfloppy   = GnomeImage("dev-floppy", true);
204
                        computer  = GnomeImage("dev-computer");
205
                        lcomputer = GnomeImage("dev-computer", true);
206
                }
207
                
208
                init = true;
209
        }
210
        if(dir.GetCount() == 0 || dir == "/") {
211
                Image m = large ? lcomputer : computer;
212
                return IsNull(m) ? CtrlImg::Computer() : m;
213
        }
214
        if(dir.Find("cdrom") == 0 || dir.Find("cdrecorder") == 0) {
215
                Image m = large ? lcdrom : cdrom;
216
                return IsNull(m) ? CtrlImg::CdRom() : m;
217
        }
218
        if(dir.Find("floppy") == 0 || dir.Find("zip") == 0) {
219
                Image m = large ? lfloppy : floppy;
220
                return IsNull(m) ? CtrlImg::Diskette() : m;
221
        }
222
        Image m = large ? lharddisk : harddisk;
223
        return IsNull(m) ? CtrlImg::Hd() : m;
224
}
225

    
226
Image GetFileIcon(const String& folder, const String& filename, bool isdir, bool isexe, bool large)
227
{
228
        static bool init = false;
229
        static bool KDE  = Environment().Get("KDE_FULL_SESSION", String()) == "true";
230
        
231
        static Image file;
232
        static Image lfile;
233
        static Image dir;
234
        static Image ldir;
235
        static Image exe;
236
        static Image lexe;
237
        static Image home;
238
        static Image lhome;
239
        static Image desktop;
240
        static Image ldesktop;
241
        static Image music;
242
        static Image lmusic;
243
        static Image pictures;
244
        static Image lpictures;
245
        static Image video;
246
        static Image lvideo;
247
        static Image documents;
248
        static Image ldocuments;
249
        static Image download;
250
        static Image ldownload;
251
        static Image help;
252
        static Image lhelp;
253
        static Image translation;
254
        static Image ltranslation;
255
        static Image layout;
256
        static Image llayout;
257
        
258
        static Image fileImage;
259
        static Image fileMusic  = SystemImage("audio-x-generic");
260
        static Image fileScript = SystemImage("text-x-script");
261
        
262
        if (!init) {
263
                if (KDE) {
264
                        file         = SystemImage("text-plain");
265
                        lfile        = SystemImage("text-plain", true);
266
                        dir          = SystemImage("folder");
267
                        ldir         = SystemImage("folder", true);
268
                        exe          = SystemImage("application-x-executable");
269
                        lexe         = SystemImage("application-x-executable", true);
270
                        home         = SystemImage("user-home");
271
                        lhome        = SystemImage("user-home", true);
272
                        desktop      = SystemImage("user-desktop");
273
                        ldesktop     = SystemImage("user-desktop", true);
274
                        music        = SystemImage("folder-sound");
275
                        lmusic       = SystemImage("folder-sound", true);
276
                        pictures     = SystemImage("folder-image");
277
                        lpictures    = SystemImage("folder-image", true);
278
                        video        = SystemImage("folder-video");
279
                        lvideo       = SystemImage("folder-video", true);
280
                        documents    = SystemImage("folder-documents");
281
                        ldocuments   = SystemImage("folder-documents", true);
282
                        download     = SystemImage("folder-downloads");
283
                        ldownload    = SystemImage("folder-downloads", true);
284
                        help         = SystemImage("help-contents");
285
                        lhelp        = SystemImage("help-contents", true);
286
                        translation  = SystemImage("applications-education-language");
287
                        ltranslation = SystemImage("applications-education-language", true);
288
                        layout       = SystemImage("applications-development");
289
                        llayout      = SystemImage("applications-development", true);
290
                        
291
                        fileImage    = SystemImage("application-x-egon");
292
                } 
293
                else {
294
                        file         = GnomeImage("fs-regular");
295
                        lfile        = GnomeImage("fs-regular", true);
296
                        dir          = GnomeImage("fs-directory");
297
                        ldir         = GnomeImage("fs-directory", true);
298
                        exe          = GnomeImage("fs-executable");
299
                        lexe         = GnomeImage("fs-executable", true);
300
                        home         = GnomeImage("fs-home");
301
                        lhome        = GnomeImage("fs-home", true);
302
                        desktop      = GnomeImage("fs-desktop");
303
                        ldesktop     = GnomeImage("fs-desktop", true);
304
                        music        = SystemImage("folder-music");
305
                        lmusic       = SystemImage("folder-music", true);
306
                        pictures     = SystemImage("folder-pictures");
307
                        lpictures    = SystemImage("folder-pictures", true);
308
                        video        = SystemImage("folder-video");
309
                        lvideo       = SystemImage("folder-video", true);
310
                        documents    = SystemImage("folder-documents");
311
                        ldocuments   = SystemImage("folder-documents", true);
312
                        download     = SystemImage("folder-downloads");
313
                        ldownload    = SystemImage("folder-downloads", true);
314
                        help         = SystemImage("help");
315
                        lhelp        = SystemImage("help", true);
316
                        translation  = SystemImage("preferences-desktop-locale");
317
                        ltranslation = SystemImage("preferences-desktop-locale", true);
318
                        layout       = SystemImage("applications-development");
319
                        llayout      = SystemImage("applications-development", true);                        
320

    
321
                        fileImage    = SystemImage("image-x-generic");
322
                }
323
                
324
                init = true;
325
        }
326
        if (filename == "Help Topics")
327
                return large ? lhelp : help; 
328
        if(isdir) {
329
                Image img = dir;
330
                if(AppendFileName(folder, filename) == GetHomeDirectory())
331
                        return large ? lhome : home;
332
                else
333
                if(AppendFileName(folder, filename) ==  GetDesktopFolder ()) 
334
                        return large ? ldesktop : desktop;
335
                else
336
                if(AppendFileName(folder, filename) == GetMusicFolder ())
337
                        return large ? lmusic : music;
338
                else
339
                if(AppendFileName(folder, filename) == GetPicturesFolder())
340
                        return large ? lpictures : pictures;
341
                else
342
                if(AppendFileName(folder, filename) == GetVideoFolder())
343
                        return large ? lvideo : video;
344
                else
345
                if(AppendFileName(folder, filename) == GetDocumentsFolder())
346
                        return large ? ldocuments : documents;
347
                else
348
                if(AppendFileName(folder, filename) == GetDownloadFolder())
349
                        return large ? ldownload : download;
350
                else
351
                if(folder == "/media" || filename.GetCount() == 0)
352
                        return PosixGetDriveImage(filename, large);
353
                return dir;
354
        }
355
        FileExtMaker m;
356
        m.ext = GetFileExt(filename);
357
        for (int i = 1; i < m.ext.GetCount(); ++i)
358
                m.ext.Set (i, ToLower(m.ext[i]));
359
        
360
        // Fixing format problems
361
        if (m.ext == ".gz") m.ext = ".tar.gz";
362
        
363
        // Ultimate++ - files extensions
364
        if (m.ext == ".t" || m.ext == ".lng") return large ? ltranslation : translation;
365
        if (m.ext == ".lay") return large ? llayout : layout;
366
        if (m.ext == ".iml") return fileImage;
367
        if (m.ext == ".usc") return fileScript;
368
        
369
        // Binary - files extensions (It seems that KDE has problem with multimedia MIME icons handling)
370
        if (KDE) {
371
                if (m.ext == ".bmp" || m.ext == ".dib" ||
372
                    m.ext == ".gif" ||
373
                    m.ext == ".jpg" || m.ext == ".jpeg" || m.ext == ".jpe" ||
374
                    m.ext == ".png" ||
375
                    m.ext == ".tif" || m.ext == ".tiff" ||
376
                    m.ext == ".svg" ||
377
                    m.ext == ".ico" ||
378
                    m.ext == ".xcf")
379
                    return fileImage;
380
                if (m.ext == ".aac" || m.ext == ".ogg" || m.ext == ".mp3")  return fileMusic;
381
        }
382

    
383
        Image img;
384
        if(m.ext.GetCount()) {
385
                m.ext = m.ext.Mid(1);
386
                m.large = large;
387
                img = MakeImage(m);
388
                isexe = false;
389
        }
390
        return IsNull(img) ? isexe ? (large ? lexe : exe) : (large ? lfile : file) : img;
391
}
392

    
393
#define GETFILEICON_DEFINED
394

    
395
#endif
396

    
397
#ifndef GETFILEICON_DEFINED
398
Image PosixGetDriveImage(String dir, bool)
399
{
400
        if(dir.GetCount() == 0 || dir == "/")
401
                return CtrlImg::Computer();
402
        if(dir.Find("cdrom") == 0 || dir.Find("cdrecorder") == 0)
403
                return CtrlImg::CdRom();
404
        if(dir.Find("floppy") == 0 || dir.Find("zip") == 0)
405
                return CtrlImg::Diskette();
406
        return CtrlImg::Hd();
407
}
408

    
409
#ifdef PLATFORM_WIN32
410
Image GetFileIcon(const String& folder, bool, bool, bool, bool = false)
411
{
412
        return CtrlImg::File();
413
}
414
#else
415
Image GetFileIcon(const String& folder, const String& filename, bool isdir, bool isexe, bool = false)
416
{
417
        return isdir ? CtrlImg::Dir() : CtrlImg::File();
418
}
419

    
420
#endif
421
#endif
422

    
423
Image NativePathIcon0(const char *path, bool folder, bool large)
424
{
425
#if defined(PLATFORM_WIN32)
426
        if (folder)
427
                return GetFileIcon(path, true, true, large);
428
        else
429
                return GetFileIcon(path, false, false, large);
430
#endif
431
#ifdef PLATFORM_POSIX
432
        String p = path;
433
        bool isdrive = folder && ((p == "/media") || (p == "/mnt"));
434
        FindFile ff(path);
435
        return isdrive ? PosixGetDriveImage(GetFileName(path), large)
436
                                   : GetFileIcon(path, GetFileName(path), folder, ff.GetMode() & 0111, large);
437
#endif
438
}
439

    
440
Image NativePathIcon(const char *path, bool folder)
441
{
442
        return NativePathIcon0(path, folder, false);
443
}
444

    
445
Image NativePathIcon(const char *path)
446
{
447
        FindFile ff(path);
448
        return NativePathIcon(path, ff.IsFolder());
449
}
450

    
451
Image NativePathLargeIcon(const char *path, bool folder)
452
{
453
        return NativePathIcon0(path, folder, true);
454
}
455

    
456
Image NativePathLargeIcon(const char *path)
457
{
458
        FindFile ff(path);
459
        return NativePathLargeIcon(path, ff.IsFolder());
460
}
461

    
462
bool MatchSearch(const String& filename, const String& search)
463
{
464
        return search.GetCount() ? Filter(filename, CharFilterDefaultToUpperAscii).Find(search) >= 0 : true;
465
}
466

    
467
bool Load(FileList& list, const String& dir, const char *patterns, bool dirs,
468
          Callback3<bool, const String&, Image&> WhenIcon, FileSystemInfo& filesystem,
469
          const String& search, bool hidden, bool hiddenfiles, bool lazyicons)
470
{
471
        if(dir.IsEmpty()) {
472
                Array<FileSystemInfo::FileInfo> root = filesystem.Find(Null);
473
                for(int i = 0; i < root.GetCount(); i++)
474
                        if(MatchSearch(root[i].filename, search))
475
                                list.Add(root[i].filename,
476
                        #ifdef PLATFORM_WIN32
477
                                        GetFileIcon(root[i].filename, false, true, false),
478
                        #else
479
                                        GetDriveImage(root[i].root_style),
480
                        #endif
481
                                        StdFont().Bold(), SColorText, true, -1, Null, SColorDisabled,
482
                        #ifdef PLATFORM_WIN32
483
                                        Nvl(root[i].root_desc, String(" ") + t_("Local Disk")),
484
                        #else
485
                                        root[i].root_desc,
486
                        #endif
487
                                        StdFont()
488
                                );
489
                #ifdef PLATFORM_WIN32
490
                        list.Add(t_("Network"), CtrlImg::Network(), StdFont().Bold(), SColorText,
491
                                 true, -1, Null, SColorDisabled, Null, StdFont());
492
                #endif
493
        }
494
        else {
495
                Array<FileSystemInfo::FileInfo> ffi =
496
                        filesystem.Find(AppendFileName(dir, filesystem.IsWin32() ? "*.*" : "*"));
497
                if(ffi.IsEmpty())
498
                        return false;
499
        #ifdef PLATFORM_POSIX
500
                bool isdrive = dir == "/media" || dir == "/mnt";
501
        #endif
502
                for(int t = 0; t < ffi.GetCount(); t++) {
503
                        const FileSystemInfo::FileInfo& fi = ffi[t];
504
                        bool nd = dirs && !fi.is_directory;
505
                        bool show = hidden;
506
                        if(!show && filesystem.IsWin32() ? !fi.is_hidden : fi.filename[0] != '.')
507
                                show = true;
508
                        if(!show && hiddenfiles && fi.is_file)
509
                                show = true;
510
                        if(fi.filename != "." && fi.filename != ".." != 0 &&
511
                           (fi.is_directory || PatternMatchMulti(patterns, fi.filename)) &&
512
                           MatchSearch(fi.filename, search) && show) {
513
                                Image img;
514
                        #ifdef PLATFORM_X11
515
                                img = isdrive ? PosixGetDriveImage(fi.filename, false)
516
                                              : GetFileIcon(dir, fi.filename, fi.is_directory, fi.unix_mode & 0111, false);
517
                        #endif
518
                        #ifdef GUI_WIN
519
                                img = GetFileIcon(AppendFileName(dir, fi.filename), fi.is_directory, false, false, lazyicons);
520
                        #endif
521
                                if(IsNull(img))
522
                                        img = fi.is_directory ? CtrlImg::Dir() : CtrlImg::File();
523
                                WhenIcon(fi.is_directory, fi.filename, img);
524
                                list.Add(fi.filename, fi.is_hidden ? Contrast(img, 200) : img,
525
                                                 StdFont().Bold(fi.is_directory),
526
                                                 nd ? SColorDisabled : fi.is_hidden ? Blend(SColorText, Gray, 200) : SColorText, fi.is_directory,
527
                                                 fi.is_directory ? -1 : fi.length,
528
                                                 Null, nd ? SColorDisabled
529
                                                          : fi.is_directory ? SColorText
530
                                                                            : fi.is_hidden ? Blend(SColorMark, Gray, 200)
531
                                                                                           : SColorMark,
532
                                         Null, Null, Null, Null,
533
#ifdef PLATFORM_WIN32
534
                         false,
535
#else
536
                                                 fi.unix_mode & 0111,
537
#endif
538
                                         fi.is_hidden
539
                                );
540
                        }
541
                }
542
        }
543
        return true;
544
}
545

    
546
#ifdef GUI_WIN
547
static AuxMutex   sExeMutex;
548
static char       sExePath[1025];
549
static bool       sExeRunning;
550
static SHFILEINFO sExeInfo;
551

    
552
static auxthread_t auxthread__ sExeIconThread(void *)
553
{
554
        SHFILEINFO info;
555
        char path[1025];
556
        sExeMutex.Enter();
557
        strncpy(path, sExePath, 1024);
558
        sExeMutex.Leave();
559
        AvoidPaintingCheck__();
560
        SHGetFileInfo(sExePath, FILE_ATTRIBUTE_NORMAL, &info, sizeof(info), SHGFI_ICON|SHGFI_SMALLICON);
561
        sExeMutex.Enter();
562
        memcpy(&sExeInfo, &info, sizeof(info));
563
        sExeRunning = false;
564
        sExeMutex.Leave();
565
        return 0;
566
}
567

    
568
void LazyFileIcons::Done(Image img)
569
{
570
        if(pos >= ndx.GetCount())
571
                return;
572
        int ii = ndx[pos];
573
        if(ii < 0 || ii >= list->GetCount())
574
                return;
575
        const FileList::File& f = list->Get(ii);
576
        WhenIcon(false, f.name, img);
577
        if(f.hidden)
578
                img = Contrast(img, 200);
579
        list->SetIcon(ii, img);
580
        pos++;
581
}
582

    
583
String LazyFileIcons::Path()
584
{
585
        if(pos >= ndx.GetCount())
586
                return Null;
587
        int ii = ndx[pos];
588
        if(ii < 0 || ii >= list->GetCount())
589
                return Null;
590
        const FileList::File& f = list->Get(ii);
591
        return ToSystemCharset(AppendFileName(dir, f.name));
592
}
593

    
594
void LazyFileIcons::Do()
595
{
596
        int start = msecs();
597
        for(;;) {
598
                for(;;) {
599
                        SHFILEINFO info;
600
                        bool done = false;
601
                        String path = Path();
602
                        if(IsNull(path))
603
                                return;
604
                        sExeMutex.Enter();
605
                        bool running = sExeRunning;
606
                        if(!running) {
607
                                done = path == sExePath;
608
                                memcpy(&info, &sExeInfo, sizeof(info));
609
                                *sExePath = '\0';
610
                                memset(&sExeInfo, 0, sizeof(sExeInfo));
611
                        }
612
                        sExeMutex.Leave();
613
                        Image img = ProcessSHIcon(info);
614
                        if(done)
615
                                Done(img);
616
                        if(!running)
617
                                break;
618
                        Sleep(0);
619
                        if(msecs(start) > 10 || Ctrl::IsWaitingEvent()) {
620
                                Restart(0);
621
                                return;
622
                        }
623
                }
624

    
625
                String path = Path();
626
                if(IsNull(path))
627
                        return;
628
                sExeMutex.Enter();
629
                strncpy(sExePath, ~path, 1024);
630
                sExeRunning = true;
631
                StartAuxThread(sExeIconThread, NULL);
632
                sExeMutex.Leave();
633
        }
634
}
635

    
636
void LazyFileIcons::ReOrder()
637
{ // gather .exe files; sort based on length so that small .exe get resolved first
638
        ndx.Clear();
639
        Vector<int> len;
640
        for(int i = 0; i < list->GetCount(); i++) {
641
                const FileList::File& f = list->Get(i);
642
                if(ToLower(GetFileExt(f.name)) == ".exe" && !f.isdir) {
643
                        ndx.Add(i);
644
                        len.Add((int)min((int64)INT_MAX, f.length));
645
                }
646
        }
647
        IndexSort(len, ndx);
648
        Restart(0);
649
}
650

    
651
void LazyFileIcons::Start(FileList& list_, const String& dir_, Callback3<bool, const String&, Image&> WhenIcon_)
652
{
653
        list = &list_;
654
        dir = dir_;
655
        WhenIcon = WhenIcon_;
656
        pos = 0;
657
        ReOrder();
658
}
659
#endif
660

    
661
class FileListSortName : public FileList::Order {
662
public:
663
        virtual bool operator()(const FileList::File& a, const FileList::File& b) const {
664
                if(a.isdir != b.isdir)
665
                        return a.isdir;
666
                if(a.name == "..")
667
                        return b.name != "..";
668
                if(b.name == "..")
669
                        return false;
670
                return stricmp(a.name, b.name) < 0;
671
        }
672
};
673

    
674
void SortByName(FileList& list)
675
{
676
        list.Sort(FileListSortName());
677
}
678

    
679
class FileListSortExt : public FileList::Order {
680
public:
681
        virtual bool operator()(const FileList::File& a, const FileList::File& b) const {
682
                if(a.isdir != b.isdir)
683
                        return a.isdir;
684
                if(a.name == "..")
685
                        return b.name != "..";
686
                if(b.name == "..")
687
                        return false;
688
                const char *ae = strrchr(a.name, '.');
689
                const char *be = strrchr(b.name, '.');
690
                int q;
691
                if(ae == NULL || be == NULL) {
692
                        if(ae) return false;
693
                        if(be) return true;
694
                        q = 0;
695
                }
696
                else
697
                        q = stricmp(ae, be);
698
                return (q ? q : stricmp(a.name, b.name)) < 0;
699
        }
700
};
701

    
702
void SortByExt(FileList& list)
703
{
704
        list.Sort(FileListSortExt());
705
}
706

    
707
String FileSel::GetDir() {
708
        String s = ~dir;
709
        if(s.IsEmpty()) return basedir;
710
        if(basedir.IsEmpty()) return s;
711
        return AppendFileName(basedir, s);
712
}
713

    
714
void FileSel::SetDir(const String& _dir) {
715
#ifdef PLATFORM_WIN32
716
        netstack.Clear();
717
        netnode.Clear();
718
#endif
719
        dir <<= _dir;
720
        Load();
721
        Update();
722
}
723

    
724
String FileSel::FilePath(const String& fn) {
725
        return AppendFileName(GetDir(), fn);
726
}
727

    
728
Image GetDriveImage(char drive_style)
729
{
730
        switch(drive_style)
731
        {
732
        case FileSystemInfo::ROOT_NO_ROOT_DIR: return Null;
733
        case FileSystemInfo::ROOT_COMPUTER:  return CtrlImg::Computer();
734
        case FileSystemInfo::ROOT_REMOVABLE: return CtrlImg::Diskette();
735
        case FileSystemInfo::ROOT_CDROM:     return CtrlImg::CdRom();
736
        default:                             return CtrlImg::Hd();
737
        }
738
}
739

    
740
String FileSel::GetMask()
741
{
742
        String emask = "*";
743
        if(!IsNull(type)) {
744
                if(IsString(~type))
745
                        emask = ~type;
746
                else {
747
                        int q = ~type;
748
                        if(q >= 0 && q < mask.GetCount())
749
                                emask = mask[q];
750
                }
751
        }
752
        return emask;
753
}
754

    
755
void FileSel::Load()
756
{
757
        search <<= Null;
758
        SearchLoad();
759
}
760

    
761
void FileSel::LoadNet()
762
{
763
#ifdef PLATFORM_WIN32
764
        list.Clear();
765
        for(int i = 0; i < netnode.GetCount(); i++) {
766
                Image m = CtrlImg::Group();
767
                switch(netnode[i].GetDisplayType()) {
768
                case NetNode::NETWORK:
769
                        m = CtrlImg::Network();
770
                        break;
771
                case NetNode::SHARE:
772
                        m = CtrlImg::Share();
773
                        break;
774
                case NetNode::SERVER:
775
                        m = CtrlImg::Computer();
776
                        break;
777
                }
778
                list.Add(netnode[i].GetName(), m);
779
        }
780
        places.FindSetCursor("\\");
781
#endif
782
}
783

    
784
void FileSel::SelectNet()
785
{
786
#ifdef PLATFORM_WIN32
787
        int q = list.GetCursor();
788
        if(q >= 0 && q < netnode.GetCount()) {
789
                NetNode& n = netnode[q];
790
                String p = n.GetPath();
791
                if(p.GetCount())
792
                        SetDir(p);
793
                else {
794
                        netstack.Add() = netnode[q];                
795
                        netnode = netstack.Top().Enum();
796
                        LoadNet();
797
                }
798
        }
799
#endif
800
}
801

    
802
void FileSel::SearchLoad()
803
{
804
        list.EndEdit();
805
        list.Clear();
806
        String d = GetDir();
807
#ifdef PLATFORM_WIN32
808
        if(d == "\\") {
809
                netnode = NetNode::EnumRoot();
810
                netnode.Append(NetNode::EnumRemembered());
811
                LoadNet();
812
                return;
813
        }
814
#endif
815
        String emask = GetMask();
816
        if(!UPP::Load(list, d, emask, mode == SELECTDIR, WhenIcon, *filesystem, ~search, ~hidden, ~hiddenfiles, true)) {
817
                Exclamation(t_("[A3* Unable to read the directory !]&&") + DeQtf((String)~dir) + "&&" +
818
                            GetErrorMessage(GetLastError()));
819
                if(!basedir.IsEmpty() && String(~dir).IsEmpty()) {
820
                        Break(IDCANCEL);
821
                        return;
822
                }
823
                dir <<= olddir;
824
                olddir = Null;
825
                SearchLoad();
826
        }
827

    
828
        places.KillCursor();
829
        if(d.GetCount())
830
                places.FindSetCursor(d);
831
        hiddenfiles.Enable(!hidden);
832
        if(d.IsEmpty()) {
833
                if(filesystem->IsWin32()) {
834
                        mkdir.Disable();
835
                        plus.Disable();
836
                        minus.Disable();
837
                        toggle.Disable();
838
                        list.Renaming(false);
839
                }
840
                dir <<= d;
841
                dirup.Disable();
842
        }
843
        else {
844
                dirup.Enable();
845
                mkdir.Enable();
846
                plus.Enable();
847
                minus.Enable();
848
                toggle.Enable();
849
                list.Renaming(true);
850
        }
851
        if(filesystem->IsPosix())
852
                if(d == "/" || !IsEmpty(basedir) && String(~dir).IsEmpty())
853
                        dirup.Disable();
854
        if(filesystem->IsWin32())
855
                if(!IsEmpty(basedir) && String(~dir).IsEmpty())
856
                        dirup.Disable();
857
        olddir = ~dir;
858
        if(olddir.GetCount() || basedir.GetCount())
859
                if(sortext && mode != SELECTDIR)
860
                        SortByExt(list);
861
                else
862
                        SortByName(list);
863
        Update();
864
#ifdef GUI_WIN
865
        lazyicons.Start(list, d, WhenIcon);
866
#endif
867
}
868

    
869
String TrimDot(String f) {
870
        int i = f.Find('.');
871
        if(i >= 0 && i == f.GetLength() - 1)
872
                f.Trim(i);
873
        return f;
874
}
875

    
876
void FileSel::AddName(Vector<String>& fn, String& f) {
877
        if(!f.IsEmpty()) {
878
                if(f.Find('.') < 0) {
879
                        String t = GetMask();
880
                        int q = t.Find('.');
881
                        if(q >= 0 && IsAlNum(t[q + 1])) {
882
                                int w = q + 2;
883
                                while(IsAlNum(t[w]))
884
                                        w++;
885
                                f << t.Mid(q, w - q);
886
                        }
887
                        else
888
                        if(defext.GetCount())
889
                                f << '.' << defext;
890
                }
891
                f = TrimDot(f);
892
                if(f[0] == '\"' && f.GetCount() > 2)
893
                        fn.Add(f.Mid(1, f.GetCount() - 2));
894
                else
895
                        fn.Add(f);
896
        }
897
        f.Clear();
898
}
899

    
900
void FileSel::Finish() {
901
        if(filesystem->IsWin32())
902
                if(GetDir().IsEmpty()) {
903
                        file.Clear();
904
                        return;
905
                }
906
        fn.Clear();
907
        if(mode == SELECTDIR) {
908
                String p = GetDir();
909
                if(list.IsSelection() && multi) {
910
                        for(int i = 0; i < list.GetCount(); i++)
911
                                if(list.IsSelected(i)) {
912
                                        const FileList::File& m = list[i];
913
                                        if(m.isdir)
914
                                                fn.Add(AppendFileName(p, m.name));
915
                                }
916
                }
917
                else {
918
                        String p = GetDir();
919
                        if(list.GetCursor() >= 0) {
920
                                const FileList::File& m = list[list.GetCursor()];
921
                                if(m.isdir)
922
                                        p = AppendFileName(p, m.name);
923
                        }
924
                        fn.Add(p);
925
                }
926
                Break(IDOK);
927
                return;
928
        }
929
        String f = file.GetText().ToString();
930
        if(f.IsEmpty()) return;
931
        String o;
932
        if(mode == OPEN && IsMulti()) {
933
                for(const char *s = f; *s; s++) {
934
                        if(*s == ' ')
935
                                AddName(fn, o);
936
                        else
937
                        if(*s == '\"') {
938
                                AddName(fn, o);
939
                                s++;
940
                                for(;;) {
941
                                        if(*s == '\0')
942
                                                AddName(fn, o);
943
                                        else
944
                                        if(*s == '\"') {
945
                                                AddName(fn, o);
946
                                                break;
947
                                        }
948
                                        o.Cat(*s++);
949
                                }
950
                        }
951
                        else
952
                                o.Cat(*s);
953
                }
954
                AddName(fn, o);
955
        }
956
        else {
957
                o = f;
958
                AddName(fn, o);
959
        }
960
        if(!IsMulti() && fn.GetCount())
961
                fn.SetCount(1);
962
        String d = GetDir();
963
        String nonexist;
964
        int ne = 0;
965
        for(int i = 0; i < fn.GetCount(); i++) {
966
                String p = fn[i];
967
                if(!IsFullPath(p))
968
                        p = NormalizePath(AppendFileName(d, fn[i]));
969
                Array<FileSystemInfo::FileInfo> ff = filesystem->Find(p, 1);
970
                p = DeQtf(p);
971
                if(!ff.IsEmpty() && ff[0].is_directory) {
972
                        Exclamation(p + t_(" is directory."));
973
                        return;
974
                }
975
                if(asking)
976
                        if(mode == SAVEAS) {
977
                                if(!ff.IsEmpty() && !PromptOKCancel(p + t_(" already exists.&Do you want to continue ?")))
978
                                        return;
979
                        }
980
                        else
981
                        if(ff.IsEmpty()) {
982
                                if(ne) nonexist << '&';
983
                                nonexist << p;
984
                                ne++;
985
                        }
986
        }
987
        if(ne) {
988
                nonexist << (ne == 1 ? t_(" does not exist.") : t_("&do not exist."));
989
                if(!PromptOKCancel(nonexist + t_("&Do you want to continue ?")))
990
                        return;
991
        }
992
        Break(IDOK);
993
}
994

    
995
bool FileSel::OpenItem() {
996
        if(list.IsCursor()) {
997
        #ifdef PLATFORM_WIN32
998
                if(netnode.GetCount()) {
999
                        SelectNet();
1000
                        return true;
1001
                }
1002
        #endif
1003
                const FileList::File& m = list.Get(list.GetCursor());
1004
        #ifdef PLATFORM_WIN32
1005
                if(IsNull(dir) && m.name == t_("Network")) {
1006
                        netnode = NetNode::EnumRoot();
1007
                        netnode.Append(NetNode::EnumRemembered());
1008
                        LoadNet();
1009
                        return true;
1010
                }
1011
        #endif
1012
                if(m.isdir) {
1013
                        SetDir(AppendFileName(~dir, m.name));
1014
                        return true;
1015
                }
1016
        }
1017
        if(mode != SELECTDIR)
1018
                Finish();
1019
        return false;
1020
}
1021

    
1022
void FileSel::Open() {
1023
        if(mode == SELECTDIR) {
1024
        #ifdef PLATFORM_WIN32
1025
                if(netnode.GetCount())
1026
                        return;
1027
        #endif
1028
                Finish();
1029
                return;
1030
        }
1031
        if(list.HasFocus() || type.HasFocus()) {
1032
                if(OpenItem()) list.SetCursor(0);
1033
        }
1034
        else
1035
        if(list.IsSelection())
1036
                for(int i = 0; i < list.GetCount(); i++) {
1037
                        const FileList::File& m = list[i];
1038
                        if(!m.isdir) Finish();
1039
                }
1040
        else
1041
        if(file.HasFocus()) {
1042
                String fn = file.GetText().ToString();
1043
        #ifdef PLATFORM_WIN32
1044
                if(fn[0] == '\\' && fn[1] == '\\') {
1045
                        FindFile ff(AppendFileName(fn, "*.*"));
1046
                        if(ff)
1047
                                SetDir(TrimDot(fn));
1048
                        return;
1049
                }
1050
        #endif
1051
                if(fn == "." || fn == "..") {
1052
                        DirUp();
1053
                        return;
1054
                }
1055
                if(HasWildcards(fn)) {
1056
                        file.Clear();
1057
                        int q = FindIndex(mask, fn);
1058
                        if(q >= 0)
1059
                                type.SetIndex(q);
1060
                        else {
1061
                                type.Add(fn, t_("Custom file type (") + fn + ')');
1062
                                type.SetIndex(type.GetCount() - 1);
1063
                        }
1064
                        Load();
1065
                        return;
1066
                }
1067
                if(fn.Find('\"') < 0) {
1068
                        if(filesystem->IsWin32())
1069
                        {
1070
                                if(fn.GetLength() >= 2 && fn[1] == ':' && fn.GetLength() <= 3) {
1071
                                        fn.Set(0, ToUpper(fn[0]));
1072
                                        if(fn.GetLength() == 2)
1073
                                                fn.Cat('\\');
1074
                                        SetDir(fn);
1075
                                        return;
1076
                                }
1077
                        }
1078
                        if(!IsFullPath(fn))
1079
                                fn = AppendFileName(~dir, fn);
1080
                        if(filesystem->IsWin32() && (!fn.IsEmpty() && (*fn.Last() == '\\' || *fn.Last() == '/'))
1081
                        || filesystem->IsPosix() && (fn != "/" && (*fn.Last() == '\\' || *fn.Last() == '/')))
1082
                        {
1083
                                fn.Trim(fn.GetLength() - 1);
1084
                                SetDir(TrimDot(fn));
1085
                                return;
1086
                        }
1087
                        Array<FileSystemInfo::FileInfo> ff = filesystem->Find(fn, 1);
1088
                        if(!ff.IsEmpty()) {
1089
                                if(ff[0].is_directory) {
1090
                                        SetDir(TrimDot(fn));
1091
                                        return;
1092
                                }
1093
                                else {
1094
                                        SetDir(TrimDot(GetFileFolder(fn)));
1095
                                        file.SetText(GetFileName(fn).ToWString());
1096
                                }
1097
                        }
1098
                }
1099
                if(mode != SELECTDIR) Finish();
1100
        }
1101
}
1102

    
1103
String DirectoryUp(String& dir, bool basedir)
1104
{
1105
        while(*dir.Last() == '\\' || *dir.Last() == '/')
1106
                dir.Trim(dir.GetCount() - 1);
1107
        String s = dir;
1108
        String name;
1109
#ifdef PLATFORM_WIN32
1110
        if(s.GetLength() < 3 || s.GetLength() == 3 && s[1] == ':') {
1111
                dir.Clear();
1112
                name = s;
1113
        }
1114
        else
1115
#endif
1116
#ifdef PLATFORM_POSIX
1117
        if(s != "/")
1118
#endif
1119
        {
1120
#ifdef PLATFORM_WIN32
1121
                int i = max(s.ReverseFind('/'), s.ReverseFind('\\'));
1122
#endif
1123
#ifdef PLATFORM_POSIX
1124
                int i = s.ReverseFind('/');
1125
#endif
1126
                if(basedir)
1127
                        if(i < 0)
1128
                                dir.Clear();
1129
                        else {
1130
                                dir = s.Mid(0, i);
1131
                                name = s.Mid(i + 1);
1132
                        }
1133
                else {
1134
#ifdef PLATFORM_WIN32
1135
                        if(s.GetLength() && s[1] == ':')
1136
                                if(i > 3) {
1137
                                        dir = s.Mid(0, i);
1138
                                        name = s.Mid(i + 1);
1139
                                }
1140
                                else {
1141
                                        dir = s.Mid(0, 3);
1142
                                        name = s.Mid(3);
1143
                                }
1144
                        if(s.GetLength() && s[0] == DIR_SEP && s[1] == DIR_SEP)
1145
                                if(i > 2) {
1146
                                        dir = s.Mid(0, i);
1147
                                        name = s.Mid(i + 1);
1148
                                }
1149
                                else {
1150
                                        dir.Clear();
1151
                                        name = s;
1152
                                }
1153
#endif
1154
#ifdef PLATFORM_POSIX
1155
                        if(i == 0 && s.GetLength() > 1) {
1156
                                dir = "/";
1157
                                name = s.Mid(1);
1158
                        }
1159
                        else
1160
                        if(s.GetLength() && s[0] == '/' && s[1] != '/') {
1161
                                dir = s.Mid(0, i);
1162
                                name = s.Mid(i + 1);
1163
                        }
1164
#endif
1165
                }
1166
        }
1167
        return name;
1168
}
1169

    
1170
void FileSel::DirUp() {
1171
#ifdef PLATFORM_WIN32
1172
        if(netstack.GetCount()) {
1173
                netstack.Drop();
1174
                if(netstack.GetCount()) {
1175
                        netnode = netstack.Top().Enum();
1176
                        LoadNet();
1177
                }
1178
                netnode = NetNode::EnumRoot();
1179
                return;
1180
        }
1181
        if(netnode.GetCount()) {
1182
                netnode.Clear();
1183
                SetDir("");
1184
                return;
1185
        }
1186
#endif
1187
        String s = ~dir;
1188
        String name = DirectoryUp(s, !basedir.IsEmpty());
1189
#ifdef PLATFORM_WIN32
1190
        if(s[0] == '\\' && s[1] == '\\' && s.Find('\\', 2) < 0) {
1191
                s.Clear();
1192
                name.Clear();
1193
        }
1194
#endif
1195
        SetDir(s);
1196
        if(list.HasFocus())
1197
                list.FindSetCursor(name);
1198
}
1199

    
1200
void FileSel::MkDir() {
1201
        if(String(~dir).IsEmpty() && basedir.IsEmpty()) return;
1202
        String name, error;
1203
        if(EditText(name, t_("New directory"), t_("Name")) && !name.IsEmpty())
1204
                if(filesystem->CreateFolder(FilePath(name), error))
1205
                {
1206
                        Load();
1207
                        list.FindSetCursor(name);
1208
                }
1209
                else
1210
                        Exclamation(t_("[A3* Creating directory failed !&&]") + error);
1211
}
1212

    
1213
void FileSel::PlusMinus(const char *title, bool sel) {
1214
        String pattern;
1215
        if(EditText(pattern, title, t_("Mask")) && !pattern.IsEmpty())
1216
                for(int i = 0; i < list.GetCount(); i++)
1217
                        if(!list.Get(i).isdir)
1218
                                if(PatternMatchMulti(pattern, list.Get(i).name))
1219
                                        list.SelectOne(i, sel);
1220
}
1221

    
1222
void FileSel::Plus() {
1223
        PlusMinus(t_("Add to selection"), true);
1224
}
1225

    
1226
void FileSel::Minus() {
1227
        PlusMinus(t_("Remove from selection"), false);
1228
}
1229

    
1230
void FileSel::Toggle() {
1231
        for(int i = 0; i < list.GetCount(); i++)
1232
                if(!list.Get(i).isdir)
1233
                        list.SelectOne(i, !list.IsSelected(i));
1234
}
1235

    
1236
bool FileSel::Key(dword key, int count) {
1237
        switch(key) {
1238
        case '.':
1239
        case K_CTRL_UP:
1240
                list.SetFocus();
1241
                dirup.PseudoPush();
1242
                return true;
1243
        case '+':
1244
                plus.PseudoPush();
1245
                return true;
1246
        case '-':
1247
                minus.PseudoPush();
1248
                return true;
1249
        case '*':
1250
                toggle.PseudoPush();
1251
                return true;
1252
        case K_F6:
1253
                list.StartEdit();
1254
                return true;
1255
        case K_F7:
1256
                mkdir.PseudoPush();
1257
                return true;
1258
        case K_ENTER:
1259
                if(mode == SELECTDIR && OpenItem())
1260
                        return true;
1261
                break;
1262
        case K_UP:
1263
        case K_DOWN:
1264
        case K_PAGEUP:
1265
        case K_PAGEDOWN:
1266
                list.SetFocus();
1267
                return list.Key(key, count);
1268
        }
1269
        if(CharFilterDefaultToUpperAscii(key) || key == K_BACKSPACE)
1270
                return search.Key(key, count);
1271
        return TopWindow::Key(key, count);
1272
}
1273

    
1274
void Catq(String& s, const String& fn) {
1275
        if(!s.IsEmpty())
1276
                s << ' ';
1277
        if(fn.Find(' ') >= 0)
1278
                s << '"' << fn << '"';
1279
        else
1280
                s << fn;
1281
}
1282

    
1283
String FormatFileSize(int64 n)
1284
{
1285
        if(n < 10000)
1286
                return Format("%d B  ", n);
1287
        else
1288
        if(n < 10000 * 1024)
1289
                return Format("%d.%d K  ", n >> 10, (n & 1023) / 103);
1290
        else
1291
        if(n < I64(10000000) * 1024)
1292
                return Format("%d.%d M  ", n >> 20, (n & 1023) / 103);
1293
        else
1294
                return Format("%d.%d G  ", n >> 30, (n & 1023) / 103);
1295
}
1296

    
1297
void FileSel::Update() {
1298
        String fn;
1299
        if(list.IsSelection()) {
1300
                for(int i = 0; i < list.GetCount(); i++)
1301
                        if(list.IsSelected(i))
1302
                                Catq(fn, list[i].name);
1303
        }
1304
        else
1305
        if(list.IsCursor()) {
1306
                const FileList::File& m = list[list.GetCursor()];
1307
                if(!m.isdir)
1308
                        Catq(fn, m.name);
1309
        }
1310
        if(mode == OPEN)
1311
                file <<= fn;
1312
        filename = String();
1313
        filesize = String();
1314
        filetime = String();
1315
        if(preview)
1316
                *preview <<= Null;
1317
        if(list.IsCursor()) {
1318
                fn = list[list.GetCursor()].name;
1319
                if(fn[1] == ':' && fn.GetLength() <= 3)
1320
                        filename = t_("  Drive");
1321
                else {
1322
                        String path = FilePath(fn);
1323
                        Array<FileSystemInfo::FileInfo> ff = filesystem->Find(path, 1);
1324
                        if(!ff.IsEmpty()) {
1325
                                filename = "  " + fn;
1326
                                if(ff[0].is_directory)
1327
                                        filesize = t_("Directory  ");
1328
                                else {
1329
                                        if(mode == SAVEAS)
1330
                                                file <<= fn;
1331
                                        filesize = FormatFileSize(ff[0].length);
1332
                                        if(preview)
1333
                                                *preview <<= path;
1334
                                }
1335
                                Time tm = ff[0].last_write_time;
1336
                                filetime = "     " + Format(tm);
1337
                        }
1338
                }
1339
        }
1340
        else {
1341
                int drives = 0;
1342
                int dirs = 0;
1343
                int files = 0;
1344
                int64 length = 0;
1345
                for(int i = 0; i < list.GetCount(); i++)
1346
                        if(!list.IsSelection() || list.IsSelected(i)) {
1347
                                const FileList::File& f = list[i];
1348
                                if(f.isdir)
1349
#ifdef PLATFORM_WIN32
1350
                                        (*f.name.Last() == ':' ? drives : dirs)++;
1351
#else
1352
                                        dirs++;
1353
#endif
1354
                                else {
1355
                                        files++;
1356
                                        length += f.length;
1357
                                }
1358
                        }
1359
                String s;
1360
                if(drives)
1361
                        s << drives << t_(" drive(s)");
1362
                else {
1363
                        if(dirs)
1364
                                s << dirs << t_(" folder(s)");
1365
                        if(files) {
1366
                                if(s.GetCount())
1367
                                        s << ", ";
1368
                                s << files << t_(" file(s)");
1369
                        }
1370
                }
1371
                filename = "  " + s;
1372
                if(length >= 0)
1373
                        filesize = FormatFileSize(length);
1374
        }
1375
        FileUpdate();
1376
}
1377

    
1378
void FileSel::FileUpdate() {
1379
        if(mode == SELECTDIR) {
1380
                ok.Enable(!IsNull(~dir));
1381
                return;
1382
        }
1383
        bool b = list.IsCursor() || !String(file).IsEmpty();
1384
        ok.Enable(b);
1385
        if(mode != SAVEAS || list.IsCursor() && list[list.GetCursor()].isdir)
1386
                ok.SetLabel(t_("Open"));
1387
        else
1388
                ok.SetLabel(t_("Save"));
1389
}
1390

    
1391
void FileSel::Rename(const String& on, const String& nn) {
1392
#ifdef PLATFORM_WIN32
1393
        if(FileMove(FilePath(on), FilePath(nn)))
1394
#else
1395
        if(rename(FilePath(on), FilePath(nn)) == 0)
1396
#endif
1397
        {
1398
                Load();
1399
                list.FindSetCursor(nn);
1400
        }
1401
        else
1402
                Exclamation(t_("[A3* Renaming of file failed !&&]") + GetErrorMessage(GetLastError()));
1403
}
1404

    
1405
void FileSel::Choice() {
1406
        Load();
1407
}
1408

    
1409
FileSel& FileSel::Type(const char *name, const char *ext) {
1410
        type.Add(type.GetCount(), name);
1411
        mask.Add(ext);
1412
        if(IsNull(type))
1413
                type.SetIndex(0);
1414
        return *this;
1415
}
1416

    
1417
FileSel& FileSel::Types(const char *d) {
1418
        Vector<String> s = Split(d, '\n');
1419
        for(int i = 0; i < s.GetCount(); i++) {
1420
                Vector<String> h = Split(s[i], '\t');
1421
                if(h.GetCount() == 2)
1422
                        Type(h[0], h[1]);
1423
                if(h.GetCount() == 1)
1424
                        Type(h[0], h[0]);
1425
        }
1426
        return *this;
1427
}
1428

    
1429
FileSel& FileSel::ClearTypes()
1430
{
1431
        type.Clear();
1432
        mask.Clear();
1433
        return *this;
1434
}
1435

    
1436
FileSel& FileSel::ActiveType(int i)
1437
{
1438
        activetype.Clear();
1439
        if(i >= 0 && i < type.GetCount())
1440
                activetype = type.GetValue(i);
1441
        return *this;
1442
}
1443

    
1444
FileSel& FileSel::AllFilesType() {
1445
        return Type(t_("All files"), "*.*");
1446
}
1447

    
1448
struct FolderDisplay : public Display {
1449
        virtual void Paint(Draw& w, const Rect& r, const Value& q,
1450
                           Color ink, Color paper, dword style) const;
1451
};
1452

    
1453
Image GetDirIcon(const String& s)
1454
{
1455
        Image img;
1456
#ifdef PLATFORM_X11
1457
        img = GetFileIcon(GetFileFolder(s), GetFileName(s), true, false, false);
1458
#endif
1459
#ifdef GUI_WIN
1460
        if((byte)*s.Last() == 255)
1461
                img = CtrlImg::Network();
1462
        else
1463
                img = s.GetCount() ? GetFileIcon(s, false, true, false) : CtrlImg::Computer();
1464
#endif
1465
        if(IsNull(img))
1466
                img = CtrlImg::Dir();
1467
        return img;
1468
}
1469

    
1470
void FolderDisplay::Paint(Draw& w, const Rect& r, const Value& q,
1471
                          Color ink, Color paper, dword style) const
1472
{
1473
        String s = q;
1474
        w.DrawRect(r, paper);
1475
        Image img = GetDirIcon(s);
1476
        w.DrawImage(r.left, r.top + (r.Height() - img.GetSize().cx) / 2, img);
1477
        w.DrawText(r.left + 20,
1478
                   r.top + (r.Height() - StdFont().Bold().Info().GetHeight()) / 2,
1479
                           ~s, StdFont().Bold(), ink);
1480
}
1481

    
1482
struct HomeDisplay : public Display {
1483
        virtual void Paint(Draw& w, const Rect& r, const Value& q,
1484
                           Color ink, Color paper, dword style) const {
1485
                w.DrawRect(r, paper);
1486
                w.DrawImage(r.left, r.top + (r.Height() - CtrlImg::Home().GetSize().cx) / 2,
1487
                                CtrlImg::Home());
1488
                w.DrawText(r.left + 20,
1489
                           r.top + (r.Height() - StdFont().Bold().Info().GetHeight()) / 2,
1490
                                   String(q), StdFont().Bold(), ink);
1491
        }
1492
};
1493

    
1494
void FileSel::Set(const String& s)
1495
{
1496
        fn.Clear();
1497
        if(IsFullPath(s)) {
1498
                ActiveDir(GetFileFolder(s));
1499
                fn.Add(GetFileName(s));
1500
        }
1501
        else
1502
                fn.Add(s);
1503
        bidname = true;
1504
}
1505

    
1506
void FileSel::GoToPlace()
1507
{
1508
        if(places.IsCursor()) {
1509
                dir <<= places.GetKey();
1510
                Load();
1511
        }
1512
}
1513

    
1514
bool FileSel::Execute(int _mode) {
1515
        mode = _mode;
1516

    
1517
        int system_row = -1;
1518
        for(int i = places.GetCount() - 1; i >= 0; i--) {
1519
                if(places.Get(i, 3) == "PLACES:SYSTEM") {
1520
                        system_row = i;
1521
                        places.Remove(i);
1522
                }
1523
        }
1524
        AddSystemPlaces(system_row);
1525
                
1526
        if(mode == SELECTDIR) {
1527
                if(!fn.IsEmpty())
1528
                        dir <<= NormalizePath(fn[0]);
1529
                type.Hide();
1530
                type_lbl.Hide();
1531
                file.Hide();
1532
                file_lbl.Hide();
1533
                sortext.Hide();
1534
                sort_lbl.Hide();
1535
                ok.SetLabel(t_("&Select"));
1536
                Logc p = filename.GetPos().y;
1537
                int q = ok.GetPos().y.GetA() + ok.GetPos().y.GetB() + 8;
1538
                p.SetA(q);
1539
                filename.SetPosY(p);
1540
                filesize.SetPosY(p);
1541
                filetime.SetPosY(p);
1542
                p = splitter.Ctrl::GetPos().y;
1543
                p.SetB(q + 20);
1544
                splitter.SetPosY(p);
1545
                LogPos ps = search.GetPos();
1546
                LogPos pl = sort_lbl.GetPos();
1547
                pl.x.SetB(ps.x.GetB());
1548
                pl.y.SetA(ok.GetPos().y.GetA());
1549
                pl.y.SetB(ps.y.GetB());
1550
                search.SetPos(pl);
1551
                bidname = false;
1552
        }
1553
        else {
1554
                for(Ctrl *q = GetFirstChild(); q; q = q->GetNext())
1555
                        if(q != &mkdir)
1556
                                q->Show();
1557
                Rect r = GetRect();
1558
                CtrlLayout(*this);
1559
                ArrangeOKCancel(ok, cancel);
1560
                SetRect(r);
1561
        }
1562
        readonly.Show(rdonly && mode == OPEN);
1563
        list.Multi(multi && (mode == OPEN || mode == SELECTDIR));
1564
        list.SelectDir(multi && mode == SELECTDIR);
1565
        dir.ClearList();
1566
        file <<= Null;
1567
        if(basedir.IsEmpty()) {
1568
                dir.Add(GetHomeDirectory());
1569
        #ifdef PLATFORM_POSIX
1570
                Array<FileSystemInfo::FileInfo> root = filesystem->Find("/media/*");
1571
                dir.Add(GetDesktopFolder());
1572
                dir.Add("/");
1573
                for(int i = 0; i < root.GetCount(); i++) {
1574
                        String ugly = root[i].filename;
1575
                        if(ugly[0] != '.') {
1576
                                dir.Add("/media/" + root[i].filename);
1577
                        }
1578
                }
1579
        #else
1580
                dir.Add(GetDesktopFolder());
1581
                Array<FileSystemInfo::FileInfo> root = filesystem->Find(Null);
1582
                for(int i = 0; i < root.GetCount(); i++) {
1583
                        String ugly = root[i].filename;
1584
                        if(ugly != "A:\\" && ugly != "B:\\") {
1585
                                ugly.Cat('\0');
1586
                                ugly.Cat(root[i].root_style);
1587
                                dir.Add(root[i].filename, ugly);
1588
                        }
1589
                }
1590
                if(filesystem == &StdFileSystemInfo())
1591
                        dir.Add("\\", String(t_("Network")) + String(0, 1) + "\xff");
1592
        #endif
1593
                if(filesystem->IsPosix() && String(~dir).IsEmpty())
1594
                        dir <<= GetHomeDirectory();
1595
                if(lru.GetCount())
1596
                        dir.AddSeparator();
1597
                for(int i = 0; i < lru.GetCount(); i++)
1598
                        if(IsFullPath(lru[i]) && filesystem->FolderExists(lru[i]))
1599
                                dir.Add(lru[i]);
1600
                dir.SetDisplay(Single<FolderDisplay>(), max(16, Draw::GetStdFontCy()));
1601
        }
1602
        else {
1603
                dir.SetDisplay(Single<HomeDisplay>(), max(16, Draw::GetStdFontCy()));
1604
                if(filesystem->IsPosix()) {
1605
                        if(String(~dir)[0] == '/')
1606
                                dir <<= "";
1607
                }
1608
        }
1609
        Rect lr = splitter.GetRect();
1610
        Rect dr = dir.GetRect();
1611
        int dp = max(20, dir.Ctrl::GetPos().y.GetB());
1612
        int px = GetSize().cx - lr.right;
1613
/*        if(IsMulti()) { // Cxl: Have we ever used these?!
1614
                toggle.RightPos(px, dp).TopPos(dr.top, dp);
1615
                minus.RightPos(px + 2 * dp, dp).TopPos(dr.top, dp);
1616
                plus.RightPos(px + 3 * dp, dp).TopPos(dr.top, dp);
1617
                px += 3 * dp;
1618
                toggle.Show();
1619
                minus.Show();
1620
                plus.Show();
1621
        }
1622
        else {*/
1623
                toggle.Hide();
1624
                minus.Hide();
1625
                plus.Hide();
1626
//        }
1627
        if(mkdir.IsShown()) {
1628
                mkdir.RightPos(px, dp).TopPos(dr.top, dp);
1629
                dirup.RightPos(px + dp, dp).TopPos(dr.top, dp);
1630
                px += 2 * dp;
1631
        }
1632
        else {
1633
                dirup.RightPos(px, dp).TopPos(dr.top, dp);
1634
                px += dp;
1635
        }
1636
        dir.HSizePos(dr.left, px + 4);
1637
        int q = type.FindValue(activetype);
1638
        if(q >= 0)
1639
                type <<= q;
1640
        else
1641
        if(type.GetCount())
1642
                type.SetIndex(0);
1643
        int dlc = type.GetCount();
1644
        Load();
1645
        ActiveFocus(file.IsEditable() ? (Ctrl&)file : (Ctrl&)list);
1646
        if(bidname) {
1647
                String s;
1648
                for(int i = 0; i < fn.GetCount(); i++)
1649
                        Catq(s, fn[i]);
1650
                file <<= s;
1651
                ActiveFocus(file);
1652
                bidname = false;
1653
        }
1654
        list.SetSbPos(lastsby);
1655
        if(preselect.GetCount()) {
1656
                for(int i = 0; i < list.GetCount(); i++)
1657
                    if(list[i].name == preselect) {
1658
                                list.SetCursor(i);
1659
                                ActiveFocus(list);
1660
                                break;
1661
                        }
1662
                preselect.Clear();
1663
        }
1664
        FileUpdate();
1665
        Update();
1666
        int c = TopWindow::Run(appmodal);
1667
        TopWindow::Close();
1668
        lastsby = list.GetSbPos();
1669
        if(IsNumber(~type)) {
1670
                int ti = ~type;
1671
                type.Trim(dlc);
1672
                if(ti >= 0 && ti < type.GetCount())
1673
                        activetype = type.GetValue(ti);
1674
        }
1675
        else
1676
                type.Trim(dlc);
1677
        if(c == IDOK) {
1678
                String d = ~dir;
1679
                if(filesystem->IsWin32())
1680
                        if(d.GetLength() == 3 && d[1] == ':') return true;
1681
                if(filesystem->IsPosix())
1682
                        if(d == "/") return true;
1683
                if(!IsFullPath(d)) return true;
1684
                LruAdd(lru, d, 8);
1685
                return true;
1686
        }
1687
        return false;
1688
}
1689

    
1690
bool FileSel::ExecuteOpen(const char *title) {
1691
        Title(title ? title : t_("Open"));
1692
        return Execute(OPEN);
1693
}
1694

    
1695
bool FileSel::ExecuteSaveAs(const char *title) {
1696
        Title(title ? title : t_("Save as"));
1697
        ok.SetLabel(t_("Save"));
1698
        return Execute(SAVEAS);
1699
}
1700

    
1701
bool FileSel::ExecuteSelectDir(const char *title)
1702
{
1703
        Title(title ? title : t_("Select directory"));
1704
        return Execute(SELECTDIR);
1705
}
1706

    
1707
void FileSel::Serialize(Stream& s) {
1708
#ifdef PLATFORM_WIN32
1709
        if(s.IsLoading()) {
1710
                netnode.Clear();
1711
                netstack.Clear();
1712
        }
1713
#endif
1714
        int version = 10;
1715
        s / version;
1716
        String ad = ~dir;
1717
        int dummy = 0;
1718
        if(version < 10)
1719
                s / dummy;
1720
        else
1721
                s % activetype;
1722
        s % ad;
1723
        dir <<= ad;
1724
        if(version < 1) {
1725
                String n = fn.At(0);
1726
                s % n;
1727
                fn.At(0) = n;
1728
        }
1729
        else {
1730
                if(version < 4)
1731
                        s % fn;
1732
                else {
1733
                        Vector<String> __;
1734
                        s % __;
1735
                }
1736
        }
1737
        if(version >= 2) {
1738
                SerializePlacement(s);
1739
                list.SerializeSettings(s);
1740
        }
1741
        if(version >= 3) {
1742
                s % lastsby;
1743
        }
1744
        if(version >= 4) {
1745
                s % lru;
1746
        }
1747
        if(version >= 5) {
1748
                s % sortext;
1749
        }
1750
        if(version >= 6) {
1751
                if(version >= 9)
1752
                        s % splitter;
1753
                else {
1754
                        Splitter dummy;
1755
                        s % dummy;
1756
                }
1757
        }
1758
        if(version >= 7) {
1759
                s % hidden;
1760
        }
1761
        if(version >= 8) {
1762
                s % hiddenfiles;
1763
        }
1764
}
1765

    
1766
String FileSel::GetFile(int i) const {
1767
        String p;
1768
        if(i >= 0 && i < fn.GetCount()) {
1769
                p = fn[i];
1770
                if(!IsFullPath(p))
1771
                        p = AppendFileName(dir.GetData(), p);
1772
        }
1773
        return p;
1774
}
1775

    
1776
void FileSel::SyncSplitter()
1777
{
1778
        splitter.Clear();
1779
        if(places.GetCount() && basedir.IsEmpty())
1780
                splitter.Add(places);
1781
        splitter.Add(list);
1782
        if(preview)
1783
                splitter.Add(*preview);
1784
}
1785

    
1786
FileSel& FileSel::PreSelect(const String& path)
1787
{
1788
        ActiveDir(GetFileFolder(path));
1789
        preselect = GetFileName(path);
1790
        return *this;
1791
}
1792

    
1793
void FileSel::InitSplitter()
1794
{
1795
        int n = splitter.GetCount();
1796
        int i = 0;
1797
        if(places.GetCount())
1798
                splitter.SetPos(2000, i++);
1799
        splitter.SetPos(10000 - 2000 * (n - 1), i);
1800
}
1801

    
1802
FileSel& FileSel::Preview(Ctrl& ctrl)
1803
{
1804
        if(!preview) {
1805
                Size sz = GetRect().GetSize();
1806
                sz.cx = 5 * sz.cx / 3;
1807
                SetRect(sz);
1808
        }
1809
        preview = &ctrl;
1810
        SyncSplitter();
1811
        InitSplitter();
1812
        return *this;
1813
}
1814

    
1815
FileSel& FileSel::Preview(const Display& d)
1816
{
1817
        preview_display.SetDisplay(d);
1818
        return Preview(preview_display);
1819
}
1820

    
1821
void FileSel::AddPlaceRaw(const String& path, const Image& m, const String& name, const char* group, int row)
1822
{
1823
        if(path.GetCount()) {
1824
                row = row < 0 ? places.GetCount() : row;
1825
                places.Insert(row);
1826
                places.Set(row, 0, path);
1827
                places.Set(row, 1, m);
1828
                places.Set(row, 2, name);
1829
                places.Set(row, 3, group);
1830
                places.SetLineCy(row, max(m.GetSize().cy + 4, GetStdFontCy() + 4));
1831
                SyncSplitter();
1832
                InitSplitter();
1833
        }
1834
}
1835

    
1836
FileSel& FileSel::AddPlace(const String& path, const Image& m, const String& name, const char* group, int row)
1837
{
1838
        if(path.GetCount())
1839
                AddPlaceRaw(NormalizePath(path), m, name, group, row);
1840
        return *this;
1841
}
1842

    
1843
FileSel& FileSel::AddPlace(const String& path, const String& name, const char* group, int row)
1844
{
1845
        return AddPlace(path, GetDirIcon(NormalizePath(path)), name, group, row);
1846
}
1847

    
1848
FileSel& FileSel::AddPlace(const String& path, const char* group, int row)
1849
{
1850
        return AddPlace(path, GetFileTitle(path), group, row);
1851
}
1852

    
1853
FileSel& FileSel::AddPlaceSeparator()
1854
{
1855
        places.AddSeparator();
1856
        SyncSplitter();
1857
        InitSplitter();
1858
        return *this;
1859
}
1860

    
1861
FileSel& FileSel::ClearPlaces()
1862
{
1863
        places.Clear();
1864
        SyncSplitter();
1865
        return *this;
1866
}
1867

    
1868
void FileSel::AddSystemPlaces(int row)
1869
{
1870
        row = row < 0 ? places.GetCount() : row;
1871
        Array<FileSystemInfo::FileInfo> root;
1872
#if defined(PLATFORM_WIN32) || defined(PLATFORM_WINCE)
1873
        root = filesystem->Find(Null);
1874
        for(int i = 0; i < root.GetCount(); i++) {
1875
                String desc = root[i].root_desc;
1876
                String n = root[i].filename;
1877
                if(n != "A:\\" && n != "B:\\") {
1878
                #ifdef PLATFORM_WIN32
1879
                        if(*n.Last() == '\\')
1880
                                n.Trim(n.GetCount() - 1);
1881
                #endif
1882
                        if(desc.GetCount() == 0)
1883
                            desc << " " << t_("Local Disk");
1884
                        desc << " (" << n << ")";
1885
                        AddPlace(root[i].filename, desc, "PLACES:SYSTEM", row++);
1886
                }
1887
        }
1888
#endif
1889

    
1890
#ifdef PLATFORM_WIN32
1891
        if(GetSystemMetrics(SM_REMOTESESSION))
1892
                for(int drive = 'A'; drive < 'Z'; drive++) {
1893
                        String path = Format("\\\\tsclient\\%c", drive);
1894
                        if(FindFile(path + "\\*.*"))
1895
                                AddPlace(path, Format(t_("%c on client"), drive), "PLACES:SYSTEM", row++);
1896
                }
1897
#endif
1898

    
1899
#ifdef PLATFORM_POSIX
1900
        root = filesystem->Find("/media/*");
1901
        for(int i = 0; i < root.GetCount(); i++) {
1902
                String fn = root[i].filename;
1903
                if(*fn != '.' && fn.Find("floppy") < 0)
1904
                        AddPlace("/media/" + fn, fn, "PLACES:SYSTEM", row++);
1905
        }
1906
#endif
1907
}
1908

    
1909
FileSel& FileSel::AddStandardPlaces()
1910
{
1911
        AddPlace(GetHomeDirectory(), t_("Home"), "PLACES:FOLDER");
1912
        AddPlace(GetDesktopFolder(), t_("Desktop"), "PLACES:FOLDER");
1913
        AddPlace(GetMusicFolder(), t_("Music"), "PLACES:FOLDER");
1914
        AddPlace(GetPicturesFolder(), t_("Pictures"), "PLACES:FOLDER");
1915
        AddPlace(GetVideoFolder(), t_("Videos"), "PLACES:FOLDER");
1916
        AddPlace(GetDocumentsFolder(), t_("Documents"), "PLACES:FOLDER");
1917
        AddPlace(GetDownloadFolder(), t_("Downloads"), "PLACES:FOLDER");
1918
        AddPlaceSeparator();
1919
        AddSystemPlaces();
1920
#ifdef PLATFORM_WIN32
1921
        AddPlaceSeparator();
1922
        AddPlaceRaw("\\", CtrlImg::Network(), t_("Network"), "PLACES:NETWORK");
1923
#endif
1924
        return *this;
1925
}
1926

    
1927
struct DisplayPlace : Display {
1928
        virtual void Paint(Draw& w, const Rect& r, const Value& q, Color ink, Color paper,
1929
                           dword style) const
1930
        {
1931
                w.DrawRect(r, paper);
1932
                ValueArray va = q;
1933
                Image m = va[0];
1934
                String txt = va[1];
1935
                Size isz = m.GetSize();
1936
                w.DrawImage(r.left, r.top + (r.Height() - isz.cy) / 2, m);
1937
                w.DrawText(r.left + isz.cx + 2, r.top + (r.Height() - GetStdFontCy()) / 2, txt,
1938
                           StdFont(), ink);
1939
        }
1940
        virtual Size GetStdSize(const Value& q) const {
1941
                ValueArray va = q;
1942
                Image m = va[0];
1943
                String txt = va[1];
1944
                Size isz = m.GetSize();
1945
                return Size(isz.cx + GetTextSize(txt, StdFont()).cx + 2, max(isz.cy, GetStdFontCy()));
1946
        }
1947
};
1948

    
1949
FileSel::FileSel() {
1950
        filesystem = &StdFileSystemInfo();
1951
        CtrlLayout(*this);
1952
        ArrangeOKCancel(ok, cancel);
1953
        Acceptor(ok, IDOK); ok.Ok();
1954
        Rejector(cancel, IDCANCEL); cancel.Cancel();
1955
        list.IconWidth(16).Renaming().Columns(3).ClickKill();
1956
        list.WhenLeftDouble = THISBACK(OpenItem2);
1957
        dirup <<= THISBACK(DirUp);
1958
        Add(dirup);
1959
        sortext <<= THISBACK(SearchLoad);
1960
        Add(sortext);
1961
        hidden <<= THISBACK(SearchLoad);
1962
        Add(hidden);
1963
        hiddenfiles <<= THISBACK(SearchLoad);
1964
        Add(hiddenfiles);
1965
        mkdir <<= THISBACK(MkDir);
1966
        Add(mkdir);
1967
        plus <<= THISBACK(Plus);
1968
        Add(plus);
1969
        minus <<= THISBACK(Minus);
1970
        Add(minus);
1971
        toggle <<= THISBACK(Toggle);
1972
        Add(toggle);
1973

    
1974
        ok <<= THISBACK(Open);
1975
        list <<= THISBACK(Update);
1976
        file <<= THISBACK(FileUpdate);
1977
        list.WhenRename = THISBACK(Rename);
1978
        Sizeable();
1979
        dirup.SetImage(CtrlImg::DirUp()).NoWantFocus();
1980
        dirup.Tip(t_("Dir up") + String(" (Ctrl+Up)"));
1981
        mkdir.SetImage(CtrlImg::MkDir()).NoWantFocus();
1982
        mkdir.Tip(t_("Create directory") + String(" (F7)"));
1983
        plus.SetImage(CtrlImg::Plus()).NoWantFocus();
1984
        plus.Tip(t_("Select files"));
1985
        minus.SetImage(CtrlImg::Minus()).NoWantFocus();
1986
        minus.Tip(t_("Unselect files"));
1987
        toggle.SetImage(CtrlImg::Toggle()).NoWantFocus();
1988
        toggle.Tip(t_("Toggle files"));
1989
        type <<= THISBACK(Load);
1990
        sortext <<= 0;
1991

    
1992
        search.NullText(t_("Search"), StdFont().Italic(), SColorDisabled());
1993
        search.SetFilter(CharFilterDefaultToUpperAscii);
1994
        search <<= THISBACK(SearchLoad);
1995

    
1996
        filename.SetFont(StdFont());
1997
        filename.SetFrame(ThinInsetFrame());
1998
        filesize.SetFont(StdFont()).SetAlign(ALIGN_RIGHT);
1999
        filesize.SetFrame(ThinInsetFrame());
2000
        filetime.SetFont(StdFont());
2001
        filetime.SetFrame(ThinInsetFrame());
2002

    
2003
        dir <<= THISBACK(Choice);
2004
        dir.DisplayAll();
2005
        dir.SetDropLines(24);
2006

    
2007
        readonly.Hide();
2008

    
2009
        lastsby = 0;
2010

    
2011
        asking = true;
2012
        rdonly = false;
2013
        multi = false;
2014
        bidname = false;
2015
        appmodal = true;
2016

    
2017
        AddChildBefore(GetFirstChild(), &sizegrip);
2018

    
2019
        preview = NULL;
2020
        preview_display.SetFrame(FieldFrame());
2021

    
2022
        SyncSplitter();
2023

    
2024
        BackPaintHint();
2025
        
2026
        places.AddKey();
2027
        places.AddColumn().AddIndex().SetDisplay(Single<DisplayPlace>());
2028
        places.AddIndex();
2029
        places.NoHeader().NoGrid();
2030
        places.WhenLeftClick = THISBACK(GoToPlace);
2031
        places.NoWantFocus();
2032

    
2033
#ifdef PLATFORM_WIN32
2034
        list.IconWidth(GetFileIcon(GetHomeDirectory(), true, false, false).GetSize().cx);
2035
#endif
2036

    
2037
        AddStandardPlaces();
2038
        list.AutoHideSb();
2039
        list.NoRoundSize();
2040
        places.AutoHideSb();
2041
}
2042

    
2043
FileSel::~FileSel() {}
2044

    
2045
END_UPP_NAMESPACE