Subversion Repositories Filer-Free

Rev

Rev 45 | Rev 55 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
21 gdshaw@RISCPKG.ORG 1
// This file is part of the free Filer module for RISC OS.
2
// Copyright  2007 Graham Shaw.
3
// Redistribution and modification are permitted under the terms of the
4
// GNU General Public License (version 2 or any later version).
5
 
6
#include <cstring>
35 gdshaw@RISCPKG.ORG 7
#include <cstdio>
21 gdshaw@RISCPKG.ORG 8
 
35 gdshaw@RISCPKG.ORG 9
#include "oslib/osbyte.h"
42 gdshaw@RISCPKG.ORG 10
#include "oslib/osfscontrol.h"
35 gdshaw@RISCPKG.ORG 11
#include "oslib/wimp.h"
12
 
21 gdshaw@RISCPKG.ORG 13
#include "template_loader.h"
25 gdshaw@RISCPKG.ORG 14
#include "layout_method.h"
31 gdshaw@RISCPKG.ORG 15
#include "filer_menu.h"
21 gdshaw@RISCPKG.ORG 16
#include "filer_window.h"
17
#include "filer_application.h"
18
 
35 gdshaw@RISCPKG.ORG 19
namespace {
20
 
21
/** The maximum length of a leafname. */
22
const size_t max_name_length=256;
23
 
24
/** The initial horizontal offset for opening a subdirectory. */
25
const int open_xstart=20;
26
 
27
/** The initial vertical offset for opening a subdirectory. */
28
const int open_ystart=-32;
29
 
30
/** The horizontal offset between subdirectories. */
31
const int open_xstep=20;
32
 
33
/** The vertical offset between subdirectories. */
34
const int open_ystep=0;
35
 
36
/** The number of distinct subdirectory offsets. */
37
const unsigned int open_count=8;
38
 
38 gdshaw@RISCPKG.ORG 39
/** The pathname for the template file. */
40
const char* template_pathname="Resources:$.Resources.Filer.Templates";
41
 
35 gdshaw@RISCPKG.ORG 42
}; /* anonymous namespace */
43
 
21 gdshaw@RISCPKG.ORG 44
filer_window::filer_window(filer_application* app,const char* pathname,
25 gdshaw@RISCPKG.ORG 45
        const os_box& box,const filer_options& options):
21 gdshaw@RISCPKG.ORG 46
        window(app),
47
        _pathname(new char[std::strlen(pathname)+1]),
25 gdshaw@RISCPKG.ORG 48
        _options(options),
49
        _directory(options.sort()),
50
        _xcsize(68),
51
        _ycsize(68),
52
        _xccount(1),
31 gdshaw@RISCPKG.ORG 53
        _yccount(1),
35 gdshaw@RISCPKG.ORG 54
        _temp_selection(directory::npos),
55
        _auto_pos(open_xstart,open_ystart,open_xstep,open_ystep,open_count)
21 gdshaw@RISCPKG.ORG 56
{
57
        // Copy pathname into buffer owned by this object.
58
        std::strcpy(_pathname,pathname);
59
 
60
        // Load directory listing.
61
        reload();
62
 
63
        // Create window from template.
38 gdshaw@RISCPKG.ORG 64
        template_loader loader("directory",template_pathname);
21 gdshaw@RISCPKG.ORG 65
        wimp_window& wblock=loader;
66
        wblock.title_flags|=wimp_ICON_INDIRECTED;
67
        wblock.title_data.indirected_text.text=_pathname;
68
        wblock.title_data.indirected_text.validation="";
69
        wblock.title_data.indirected_text.size=strlen(_pathname);
70
        wblock.visible=box;
71
        wblock.extent.x0=0;
72
        wblock.extent.y0=-(box.y1-box.y0);
73
        wblock.extent.x1=box.x1-box.x0;
74
        wblock.extent.y1=0;
28 gdshaw@RISCPKG.ORG 75
        wblock.flags|=wimp_WINDOW_IGNORE_XEXTENT;
21 gdshaw@RISCPKG.ORG 76
        wblock.icon_count=0;
77
        create_window(wblock);
78
 
79
        // Resize extent to match actual visible area.
80
        wimp_window_state wstate;
81
        get_window_state(wstate);
82
        os_box extent;
83
        extent.x0=0;
84
        extent.y0=-(wstate.visible.y1-wstate.visible.y0);
85
        extent.x1=wstate.visible.x1-wstate.visible.x0;
86
        extent.y1=0;
87
        window::set_extent(extent);
88
 
25 gdshaw@RISCPKG.ORG 89
        // Open window, but keep it hidden from view.
21 gdshaw@RISCPKG.ORG 90
        wimp_window_info winfo;
91
        get_window_info_header(winfo);
92
        wimp_open open;
93
        open.visible.x0=winfo.visible.x0;
94
        open.visible.y0=winfo.visible.y1-(winfo.extent.y1-winfo.extent.y0);
95
        open.visible.x1=winfo.visible.x0+(winfo.extent.x1-winfo.extent.x0);
96
        open.visible.y1=winfo.visible.y1;
97
        open.visible=winfo.visible;
98
        open.xscroll=0;
99
        open.yscroll=0;
25 gdshaw@RISCPKG.ORG 100
        open.next=wimp_HIDDEN;
101
        open_window(open);
102
 
103
        // Reformat content of window.
104
        reformat();
105
 
106
        // Reopen window, now making it visible.
107
        get_window_state(wstate);
108
        open.visible=wstate.visible;
109
        open.xscroll=wstate.xscroll;
110
        open.yscroll=wstate.yscroll;
21 gdshaw@RISCPKG.ORG 111
        open.next=wimp_TOP;
112
        open_window(open);
113
}
114
 
115
filer_window::~filer_window()
116
{
117
        // Delete pathname buffer.
118
        delete[] _pathname;
119
}
120
 
121
void filer_window::handle_redraw_request(wimp_draw& block)
122
{
25 gdshaw@RISCPKG.ORG 123
        // Fetch layout.
124
        layout_method& layout=_options.layout();
125
        int xgap=layout.xgap();
126
        int ygap=layout.ygap();
127
 
21 gdshaw@RISCPKG.ORG 128
        int more=0;
129
        xwimp_redraw_window(&block,&more);
130
        while (more)
131
        {
25 gdshaw@RISCPKG.ORG 132
                // Get clipping coordinates with respect to this window.
133
                int xmin=block.clip.x0-block.box.x0+block.xscroll-xgap;
134
                int ymin=block.clip.y0-block.box.y1+block.yscroll+ygap;
135
                int xmax=block.clip.x1-block.box.x0+block.xscroll-xgap;
136
                int ymax=block.clip.y1-block.box.y1+block.yscroll+ygap;
137
 
138
                // Determine which cells are within clipping box.
139
                int xcmin=(xmin)/(_xcsize+xgap);
140
                int ycmin=(-ymax)/(_ycsize+ygap);
141
                int xcmax=(xmax-1)/(_xcsize+xgap)+1;
142
                int ycmax=(-ymin-1)/(_ycsize+ygap)+1;
143
                if (xcmin<0) xcmin=0;
144
                if (ycmin<0) ycmin=0;
145
                if (xcmax>_xccount) xcmax=_xccount;
146
                if (ycmax>_yccount) ycmax=_yccount;
147
 
148
                // Iterate over cells to be redrawn.
149
                for (int yc=ycmin;yc<ycmax;++yc)
150
                {
151
                        for (int xc=xcmin;xc<xcmax;++xc)
152
                        {
153
                                // Determine whether cell is occupied.
30 gdshaw@RISCPKG.ORG 154
                                unsigned int i=xc+yc*_xccount;
155
                                if (i<_directory.size())
25 gdshaw@RISCPKG.ORG 156
                                {
157
                                        // Redraw cell.
158
                                        os_box box;
159
                                        box.x0=xc*(_xcsize+xgap)+xgap;
160
                                        box.y0=-yc*(_ycsize+ygap)-_ycsize-ygap;
161
                                        box.x1=box.x0+_xcsize;
162
                                        box.y1=box.y0+_ycsize;
163
                                        layout.plot(box,*_directory[i],
164
                                                _directory[i].selected(),_options);
165
                                }
166
                        }
167
                }
168
 
21 gdshaw@RISCPKG.ORG 169
                xwimp_get_rectangle(&block,&more);
170
        }
171
}
172
 
28 gdshaw@RISCPKG.ORG 173
void filer_window::handle_open_request(wimp_open& block)
174
{
175
        int xccount=_xccount;
176
        int yccount=_yccount;
177
        reformat(block.visible.x1-block.visible.x0);
178
        xwimp_open_window(&block);
179
        if (_xccount!=xccount||_yccount!=yccount) force_redraw();
180
}
181
 
29 gdshaw@RISCPKG.ORG 182
void filer_window::handle_close_request(wimp_close& block)
183
{
184
        wimp_pointer pointer;
185
        xwimp_get_pointer_info(&pointer);
186
 
187
        if (pointer.buttons&wimp_CLICK_ADJUST)
188
        {
189
                os_coord offset;
190
                offset.x=0;
191
                offset.y=0;
192
                open_parent(offset);
193
        }
194
 
195
        delete this;
196
}
197
 
30 gdshaw@RISCPKG.ORG 198
void filer_window::handle_mouse_click(wimp_pointer& block)
199
{
200
        // Fetch layout.
201
        layout_method& layout=options().layout();
202
 
35 gdshaw@RISCPKG.ORG 203
        // Read shift state.
204
        int shift_state=0;
205
        xosbyte1(osbyte_VAR_KEYBOARD_STATE,0,0xff,&shift_state);
206
        int shift=(shift_state&0x08)!=0;
207
 
30 gdshaw@RISCPKG.ORG 208
        // Find cell under pointer.
209
        unsigned int index=find_cell(block.pos);
210
 
35 gdshaw@RISCPKG.ORG 211
        bool close=false;
31 gdshaw@RISCPKG.ORG 212
        if (block.buttons==wimp_CLICK_MENU)
30 gdshaw@RISCPKG.ORG 213
        {
31 gdshaw@RISCPKG.ORG 214
                // Any existing menu will be deleted by this action.
215
                handle_menus_deleted();
216
 
217
                // Count number of cells selected.
218
                int count=0;
219
                for (unsigned int i=0,i_end=_directory.size();i!=i_end;++i)
220
                {
221
                        if (_directory[i].selected()) ++count;
222
                }
223
 
224
                // If pointer is over a cell and nothing has yet been selected
225
                // then temporarily select the cell under the pointer.
226
                if (index!=directory::npos&&!_directory[index].selected()&&!count)
227
                {
228
                        _directory[index].selected(true);
229
                        _temp_selection=index;
230
                        force_redraw_cell(index);
231
                }
232
 
233
                // Update then open the menu.
234
                shared_menu().update(this);
235
                shared_menu().show(block);
236
        }
35 gdshaw@RISCPKG.ORG 237
        else if (block.buttons&(wimp_DOUBLE_ADJUST|wimp_DOUBLE_SELECT))
238
        {
239
                // If double click within a cell then run that object.
240
                if (index!=directory::npos)
241
                {
242
                        select_all(0);
243
                        close=(block.buttons&wimp_DOUBLE_ADJUST)!=0;
244
                        if (close) close_window();
245
                        run(*_directory[index],close,shift);
246
                }
247
        }
31 gdshaw@RISCPKG.ORG 248
        else if (block.buttons&(wimp_SINGLE_SELECT|wimp_SINGLE_ADJUST))
249
        {
30 gdshaw@RISCPKG.ORG 250
                // If single select click then first de-select everything.
251
                if (block.buttons&wimp_SINGLE_SELECT) select_all(0);
252
 
253
                // If click within a cell then select that cell.
254
                if (index!=directory::npos)
255
                {
256
                        _directory[index].selected(!_directory[index].selected());
257
                        force_redraw_cell(index);
258
                }
259
        }
35 gdshaw@RISCPKG.ORG 260
 
261
        // If this window has closed as a result of the mouse event
262
        // then delete it.
263
        if (close) delete this;
30 gdshaw@RISCPKG.ORG 264
}
265
 
31 gdshaw@RISCPKG.ORG 266
void filer_window::handle_menus_deleted()
267
{
268
        if (_temp_selection!=directory::npos)
269
        {
270
                _directory[_temp_selection].selected(0);
271
                force_redraw_cell(_temp_selection);
272
                _temp_selection=directory::npos;
273
        }
274
}
275
 
36 gdshaw@RISCPKG.ORG 276
void filer_window::options(const filer_options& options)
277
{
278
        // Keep track of whether window needs to be reformatted, restored
279
        // and redrawn.
280
        int need_reformat=0;
281
        int need_resort=0;
282
        int need_redraw=0;
283
 
284
        // Check whether layout method has changed.
285
        if (&options.layout()!=&_options.layout())
286
        {
287
                need_reformat=1;
288
                need_redraw=1;
289
        }
290
 
291
        // Check whether sorting method has changed.
292
        if (&options.sort()!=&_options.sort())
293
        {
294
                need_resort=1;
295
                need_redraw=1;
296
        }
297
 
298
        // Update options.
299
        _options=options;
300
 
301
        // Reformat, resort and redraw window as required.
302
        if (need_resort) _directory.sort(_options.sort());
303
        if (need_redraw) force_redraw();
304
        if (need_reformat)
305
        {
306
                reformat();
307
                if (need_redraw) force_redraw();
308
        }
309
}
310
 
31 gdshaw@RISCPKG.ORG 311
filer_menu& filer_window::shared_menu() const
312
{
313
        static filer_menu* _shared_menu=0;
314
        if (!_shared_menu)
315
        {
38 gdshaw@RISCPKG.ORG 316
                wimp_open_template(template_pathname);
31 gdshaw@RISCPKG.ORG 317
                _shared_menu=new filer_menu(parent_application());
38 gdshaw@RISCPKG.ORG 318
                wimp_close_template();
31 gdshaw@RISCPKG.ORG 319
        }
320
        return *_shared_menu;
321
}
322
 
21 gdshaw@RISCPKG.ORG 323
void filer_window::reload()
324
{
325
        static int buffer[256];
326
        _directory.load(_pathname,buffer,sizeof(buffer));
327
}
25 gdshaw@RISCPKG.ORG 328
 
329
void filer_window::reformat()
330
{
331
        wimp_window_state wstate;
332
        get_window_state(wstate);
333
        reformat(wstate.visible.x1-wstate.visible.x0);
334
}
335
 
336
void filer_window::reformat(int xsize)
337
{
338
        // Fetch layout.
339
        layout_method& layout=options().layout();
340
        int xgap=layout.xgap();
341
        int ygap=layout.ygap();
342
 
53 gdshaw@RISCPKG.ORG 343
        // Window will automatically resize if visible area matches extent.
344
        wimp_window_info winfo;
345
        get_window_info_header(winfo);
346
        int xauto=(winfo.xscroll==0)&&
347
                (winfo.visible.x1-winfo.visible.x0==winfo.extent.x1-winfo.extent.x0);
348
        int yauto=(winfo.yscroll==0)&&
349
                (winfo.visible.y1-winfo.visible.y0==winfo.extent.y1-winfo.extent.y0);
350
 
25 gdshaw@RISCPKG.ORG 351
        // Calculate cell size.  This must be able to accommodate
352
        // - the minimum cell size for the chosen layout, and
353
        // - the actual size occupied by each file to be listed.
354
        os_coord csize=layout.min_size(_options);
355
        for (unsigned int i=0;i!=_directory.size();++i)
356
        {
357
                os_coord size=layout.size(*_directory[i],_options);
358
                if (size.x>csize.x) csize.x=size.x;
359
                if (size.y>csize.y) csize.y=size.y;
360
        }
361
 
362
        // Apply the calculated cell size.
363
        _xcsize=csize.x;
364
        _ycsize=csize.y;
365
 
366
        // Determine number of rows and columns.
53 gdshaw@RISCPKG.ORG 367
        if (xauto&&(_yccount<2))
368
        {
369
                _xccount=(_directory.size()<4)?_directory.size():4;
370
        }
371
        else
372
        {
373
                _xccount=xsize/(_xcsize+xgap);
374
        }
25 gdshaw@RISCPKG.ORG 375
        if (_xccount<1) _xccount=1;
376
        _yccount=(_directory.size()+_xccount-1)/_xccount;
377
        if (_yccount<1) _yccount=1;
378
 
379
        // Calculate new extent.
380
        int extent_xsize=_xccount*(_xcsize+xgap)+xgap;
381
        int extent_ysize=_yccount*(_ycsize+ygap)+ygap;
382
 
28 gdshaw@RISCPKG.ORG 383
        // Do not force the window to become narrower than the width requested,
25 gdshaw@RISCPKG.ORG 384
        // unless there are too few directory entries to justify that width.
385
        if (extent_xsize<xsize)
386
        {
387
                extent_xsize=xsize;
388
                if (((extent_xsize+_xcsize-1)/(_xcsize+xgap))>
389
                        static_cast<int>(_directory.size()))
390
                {
391
                        extent_xsize=_directory.size()*(_xcsize+xgap)+xgap;
392
                }
393
        }
394
 
395
        // Apply the calculated extent.
396
        os_box extent;
397
        extent.x0=0;
398
        extent.y0=-extent_ysize;
399
        extent.x1=extent_xsize;
400
        extent.y1=0;
401
        set_extent(extent);
402
}
29 gdshaw@RISCPKG.ORG 403
 
53 gdshaw@RISCPKG.ORG 404
void filer_window::set_extent(const os_box& extent)
405
{
406
        // Window will automatically resize if visible area matches extent.
407
        wimp_window_info winfo;
408
        get_window_info_header(winfo);
409
        int xauto=(winfo.xscroll==0)&&
410
                (winfo.visible.x1-winfo.visible.x0==winfo.extent.x1-winfo.extent.x0);
411
        int yauto=(winfo.yscroll==0)&&
412
                (winfo.visible.y1-winfo.visible.y0==winfo.extent.y1-winfo.extent.y0);
413
 
414
        // Set the new extent.
415
        window::set_extent(extent);
416
 
417
        // Open the window.
418
        wimp_open open;
419
        open.visible=winfo.visible;
420
        open.xscroll=winfo.xscroll;
421
        open.yscroll=winfo.yscroll;
422
        open.next=winfo.next;
423
 
424
        // If automatically resizing then adjust visible area to match extent.
425
        int reopen=0;
426
        if (xauto&&(winfo.visible.x1-winfo.visible.x0!=extent.x1-extent.x0))
427
        {
428
                open.visible.x1=open.visible.x0+(extent.x1-extent.x0);
429
                reopen=1;
430
        }
431
        if (yauto&&(open.visible.y1-open.visible.y0!=extent.y1-extent.y0))
432
        {
433
                open.visible.y0=open.visible.y1-(extent.y1-extent.y0);
434
                reopen=1;
435
        }
436
        if (reopen) open_window(open);
437
}
438
 
30 gdshaw@RISCPKG.ORG 439
unsigned int filer_window::find_cell(const os_coord& p)
440
{
441
        layout_method& layout=options().layout();
442
        int xgap=layout.xgap();
443
        int ygap=layout.ygap();
444
 
445
        wimp_window_state state;
446
        get_window_state(state);
447
        int x=p.x-state.visible.x0+state.xscroll-xgap;
448
        int y=p.y-state.visible.y1+state.yscroll+ygap;
449
 
450
        int xc=x/(_xcsize+xgap);
451
        int yc=(-y)/(_ycsize+ygap);
452
        unsigned int index=xc+yc*_xccount;
453
 
454
        x-=xc*(_xcsize+xgap);
455
        y+=yc*(_ycsize+ygap);
456
 
457
        int found=(x>=0)&&(y>=-_ycsize)&&(x<_xcsize)&&(y<0)&&
458
                (xc>=0)&&(yc>=0)&&(xc<_xccount)&&(yc<_yccount)&&
459
                (index<_directory.size());
460
 
461
        return (found)?index:directory::npos;
462
}
463
 
464
void filer_window::force_redraw_cell(unsigned int index)
465
{
466
        layout_method& layout=options().layout();
467
        int xgap=layout.xgap();
468
        int ygap=layout.ygap();
469
 
470
        int xc=index%_xccount;
471
        int yc=index/_xccount;
472
 
473
        os_box box;
474
        box.x0=xgap+xc*(_xcsize+xgap);
475
        box.y0=-(yc+1)*(_ycsize+ygap);
476
        box.x1=box.x0+_xcsize;
477
        box.y1=box.y0+_ycsize;
478
        force_redraw(box);
479
}
480
 
34 gdshaw@RISCPKG.ORG 481
void filer_window::refresh()
482
{
483
        reload();
484
        reformat();
485
        force_redraw();
486
}
487
 
30 gdshaw@RISCPKG.ORG 488
void filer_window::select_all(int selected)
489
{
490
        layout_method& layout=options().layout();
491
        int xgap=layout.xgap();
492
        int ygap=layout.ygap();
493
 
494
        int xc_min=_xccount;
495
        int yc_min=_yccount;
496
        int xc_max=0;
497
        int yc_max=0;
498
 
499
        for (unsigned int i=0;i!=_directory.size();++i)
500
        {
501
                if (_directory[i].selected()!=selected)
502
                {
503
                        _directory[i].selected(selected);
504
 
505
                        int xc=i%_xccount;
506
                        int yc=i/_xccount;
507
                        if (xc<xc_min) xc_min=xc;
508
                        if (yc<yc_min) yc_min=yc;
509
                        if (xc+1>xc_max) xc_max=xc+1;
510
                        if (yc+1>yc_max) yc_max=yc+1;
511
                }
512
        }
513
 
514
        if ((xc_max>xc_min)&&(yc_max>yc_min))
515
        {
516
                os_box box;
517
                box.x0=xgap+xc_min*(_xcsize+xgap);
518
                box.y0=-yc_max*(_ycsize+ygap);
519
                box.x1=xc_max*(_xcsize+xgap);
520
                box.y1=-ygap-yc_min*(_ycsize+ygap);
521
                force_redraw(box);
522
        }
31 gdshaw@RISCPKG.ORG 523
 
524
        _temp_selection=directory::npos;
30 gdshaw@RISCPKG.ORG 525
}
526
 
29 gdshaw@RISCPKG.ORG 527
void filer_window::open_parent(const os_coord& offset) const
528
{
529
        // Determine whether there is a parent directory.
530
        char* lastdot=strrchr(_pathname,'.');
531
        if (lastdot&&strcmp(lastdot+1,"$"))
532
        {
533
                // Find top-left corner of this window.
534
                wimp_window_state state;
535
                get_window_state(state);
536
 
537
                // Add offset to give top-left corner of new window.
538
                os_box box;
539
                box.x0=state.visible.x0+offset.x;
540
                box.y1=state.visible.y1+offset.y;
541
                box.x1=box.x0;
542
                box.y0=box.y1;
543
 
544
                // Open new window.
545
                *lastdot=0;
546
                new filer_window((filer_application*)parent_application(),
547
                        _pathname,box,_options);
548
                *lastdot='.';
549
        }
550
}
35 gdshaw@RISCPKG.ORG 551
 
42 gdshaw@RISCPKG.ORG 552
void filer_window::set_work_directory() const
553
{
554
        osfscontrol_dir(_pathname);
555
}
556
 
45 gdshaw@RISCPKG.ORG 557
wimp_t filer_window::begin_filer_action()
558
{
559
        // Start a FilerAction task.
560
        wimp_t handle=wimp_start_task("Filer_Action");
561
 
562
        // Send it the pathname of the directory on which it is to act.
563
        fileraction_send_selected_directory(handle,pathname());
564
 
565
        // Send it the list of leafnames on which it is to act.
566
        for (unsigned int i=0,i_end=_directory.size();i!=i_end;++i)
567
        {
568
                if (_directory[i].selected())
569
                {
570
                        const char* leafname=_directory[i]->name;
571
                        fileraction_send_selected_file(handle,leafname);
572
                }
573
        }
574
 
575
        // Return the task handle of the FilerAction task.
576
        return handle;
577
}
578
 
35 gdshaw@RISCPKG.ORG 579
void filer_window::run(osgbpb_info& info,int close,int shift)
580
{
581
        // Need to at least partially handle shift key here, because
582
        // Filer_Run does not allow coordinates to be specified when
583
        // shift-clicking an application directory.
584
        // (... unless there is an alternative way to invoke Filer_Run?)
585
 
586
        static char buffer[12+max_name_length];
587
        if ((info.obj_type&fileswitch_IS_DIR)&&((info.name[0]!='!')||shift))
588
        {
589
                // Get dimensions of this window.
590
                wimp_window_state state;
591
                get_window_state(state);
592
 
593
                // Choose coordinates for new window.
594
                // If closing this window then open in same position,
595
                // otherwise open below and to the right.
596
                os_coord offset=_auto_pos();
597
                os_box box;
598
                box.x0=state.visible.x0+((close)?0:offset.x);
599
                box.y1=state.visible.y1+((close)?0:offset.y);
600
                box.x1=box.x0;
601
                box.y0=box.y1;
602
 
603
                // Open new window.
604
                if (std::strlen(_pathname)+std::strlen(info.name)+1<max_name_length)
605
                {
606
                        std::sprintf(buffer,"%s.%s",_pathname,info.name);
607
                        window* w=new filer_window(
608
                                (filer_application*)parent_application(),
609
                                buffer,box,_options);
610
                }
611
        }
612
        else
613
        {
614
                // Run object.
615
                if (std::strlen(_pathname)+std::strlen(info.name)+1<max_name_length)
616
                {
617
                        std::sprintf(buffer,"Run %s.%s",_pathname,info.name);
618
                        wimp_start_task(buffer);
619
                }
620
        }
621
}