Subversion Repositories Filer-Free

Rev

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