~profzoom/ubuntu/quantal/wmaker/bug-1079925

« back to all changes in this revision

Viewing changes to WINGs/wfilepanel.c

  • Committer: Bazaar Package Importer
  • Author(s): Marcelo E. Magallon
  • Date: 2004-11-10 14:05:30 UTC
  • Revision ID: james.westby@ubuntu.com-20041110140530-qpd66b5lm38x7apk
Tags: upstream-0.91.0
ImportĀ upstreamĀ versionĀ 0.91.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include "WINGsP.h"
 
3
#include "wconfig.h"
 
4
 
 
5
#include <sys/types.h>
 
6
#include <sys/stat.h>
 
7
#include <unistd.h>
 
8
#include <dirent.h>
 
9
#include <limits.h>
 
10
#include <errno.h>
 
11
 
 
12
#ifndef PATH_MAX
 
13
#define PATH_MAX 1024
 
14
#endif
 
15
 
 
16
 
 
17
typedef struct W_FilePanel {
 
18
    WMWindow *win;
 
19
 
 
20
    WMLabel *iconLabel;
 
21
    WMLabel *titleLabel;
 
22
 
 
23
    WMFrame *line;
 
24
 
 
25
    WMLabel *nameLabel;
 
26
    WMBrowser *browser;
 
27
 
 
28
    WMButton *okButton;
 
29
    WMButton *cancelButton;
 
30
 
 
31
    WMButton *homeButton;
 
32
    WMButton *trashcanButton;
 
33
    WMButton *createDirButton;
 
34
    WMButton *disketteButton;
 
35
    WMButton *unmountButton;
 
36
 
 
37
    WMView *accessoryView;
 
38
 
 
39
    WMTextField *fileField;
 
40
 
 
41
    char **fileTypes;
 
42
 
 
43
    struct {
 
44
        unsigned int canExit:1;
 
45
        unsigned int canceled:1;       /* clicked on cancel */
 
46
        unsigned int filtered:1;
 
47
        unsigned int canChooseFiles:1;
 
48
        unsigned int canChooseDirectories:1;
 
49
        unsigned int autoCompletion:1;
 
50
        unsigned int showAllFiles:1;
 
51
        unsigned int canFreeFileTypes:1;
 
52
        unsigned int fileMustExist:1;
 
53
        unsigned int panelType:1;
 
54
    } flags;
 
55
} W_FilePanel;
 
56
 
 
57
 
 
58
/* Type of panel */
 
59
#define WP_OPEN         0
 
60
#define WP_SAVE         1
 
61
 
 
62
#define PWIDTH          330
 
63
#define PHEIGHT         360
 
64
 
 
65
static void listDirectoryOnColumn(WMFilePanel *panel, int column, char *path);
 
66
static void browserClick();
 
67
static void browserDClick();
 
68
 
 
69
static void fillColumn(WMBrowserDelegate *self, WMBrowser *bPtr, int column,
 
70
                       WMList *list);
 
71
 
 
72
static void deleteFile();
 
73
 
 
74
static void createDir();
 
75
 
 
76
static void goHome();
 
77
 
 
78
static void goFloppy();
 
79
 
 
80
static void goUnmount();
 
81
 
 
82
static void buttonClick();
 
83
 
 
84
static char *getCurrentFileName(WMFilePanel *panel);
 
85
 
 
86
static void handleEvents(XEvent *event, void *data);
 
87
 
 
88
 
 
89
 
 
90
static WMBrowserDelegate browserDelegate = {
 
91
    NULL, /* data */
 
92
    fillColumn, /* createRowsForColumn */
 
93
    NULL, /* titleOfColumn */
 
94
    NULL, /* didScroll */
 
95
    NULL  /* willScroll */
 
96
};
 
97
 
 
98
 
 
99
static int
 
100
closestListItem(WMList *list, char *text, Bool exact)
 
101
{
 
102
    WMListItem *item;
 
103
    WMArray *items = WMGetListItems(list);
 
104
    int i, len = strlen(text);
 
105
 
 
106
    if (len==0)
 
107
        return -1;
 
108
 
 
109
    for(i=0; i<WMGetArrayItemCount(items); i++) {
 
110
        item = WMGetFromArray(items, i);
 
111
        if (strlen(item->text) >= len &&
 
112
            ((exact && strcmp(item->text, text)==0) ||
 
113
             (!exact && strncmp(item->text, text, len)==0))) {
 
114
            return i;
 
115
        }
 
116
    }
 
117
 
 
118
    return -1;
 
119
}
 
120
 
 
121
 
 
122
static void
 
123
textChangedObserver(void *observerData, WMNotification *notification)
 
124
{
 
125
    W_FilePanel *panel = (W_FilePanel*)observerData;
 
126
    char *text;
 
127
    WMList *list;
 
128
    int col = WMGetBrowserNumberOfColumns(panel->browser) - 1;
 
129
    int i, textEvent;
 
130
 
 
131
    if (!(list = WMGetBrowserListInColumn(panel->browser, col)))
 
132
        return;
 
133
 
 
134
    text = WMGetTextFieldText(panel->fileField);
 
135
    textEvent = (int)WMGetNotificationClientData(notification);
 
136
 
 
137
    if (panel->flags.autoCompletion && textEvent!=WMDeleteTextEvent)
 
138
        i = closestListItem(list, text, False);
 
139
    else
 
140
        i = closestListItem(list, text, True);
 
141
 
 
142
    WMSelectListItem(list, i);
 
143
    if (i>=0 && panel->flags.autoCompletion) {
 
144
        WMListItem *item = WMGetListItem(list, i);
 
145
        int textLen = strlen(text), itemTextLen = strlen(item->text);
 
146
        int visibleItems = WMWidgetHeight(list)/WMGetListItemHeight(list);
 
147
 
 
148
        WMSetListPosition(list, i - visibleItems/2);
 
149
 
 
150
        if (textEvent!=WMDeleteTextEvent) {
 
151
            WMRange range;
 
152
 
 
153
            WMInsertTextFieldText(panel->fileField, &item->text[textLen],
 
154
                                  textLen);
 
155
            range.position = textLen;
 
156
            range.count = itemTextLen - textLen;
 
157
            WMSelectTextFieldRange(panel->fileField, range);
 
158
            /*WMSetTextFieldCursorPosition(panel->fileField, itemTextLen);*/
 
159
        }
 
160
    }
 
161
 
 
162
    wfree(text);
 
163
}
 
164
 
 
165
 
 
166
static void
 
167
textEditedObserver(void *observerData, WMNotification *notification)
 
168
{
 
169
    W_FilePanel *panel = (W_FilePanel*)observerData;
 
170
 
 
171
    if ((int)WMGetNotificationClientData(notification)==WMReturnTextMovement) {
 
172
        WMPerformButtonClick(panel->okButton);
 
173
    }
 
174
}
 
175
 
 
176
 
 
177
 
 
178
static WMFilePanel*
 
179
makeFilePanel(WMScreen *scrPtr, char *name, char *title)
 
180
{
 
181
    WMFilePanel *fPtr;
 
182
    WMFont *largeFont;
 
183
    WMPixmap *icon;
 
184
 
 
185
    fPtr = wmalloc(sizeof(WMFilePanel));
 
186
    memset(fPtr, 0, sizeof(WMFilePanel));
 
187
 
 
188
    fPtr->win = WMCreateWindowWithStyle(scrPtr, name, WMTitledWindowMask
 
189
                                        |WMResizableWindowMask);
 
190
    WMResizeWidget(fPtr->win, PWIDTH, PHEIGHT);
 
191
    WMSetWindowTitle(fPtr->win, "");
 
192
 
 
193
    WMCreateEventHandler(WMWidgetView(fPtr->win), StructureNotifyMask,
 
194
                         handleEvents, fPtr);
 
195
    WMSetWindowMinSize(fPtr->win, PWIDTH, PHEIGHT);
 
196
 
 
197
 
 
198
    fPtr->iconLabel = WMCreateLabel(fPtr->win);
 
199
    WMResizeWidget(fPtr->iconLabel, 64, 64);
 
200
    WMMoveWidget(fPtr->iconLabel, 0, 0);
 
201
    WMSetLabelImagePosition(fPtr->iconLabel, WIPImageOnly);
 
202
    icon = WMCreateApplicationIconBlendedPixmap(scrPtr, (RColor*)NULL);
 
203
    if (icon) {
 
204
        WMSetLabelImage(fPtr->iconLabel, icon);
 
205
        WMReleasePixmap(icon);
 
206
    } else {
 
207
        WMSetLabelImage(fPtr->iconLabel, scrPtr->applicationIconPixmap);
 
208
    }
 
209
 
 
210
    fPtr->titleLabel = WMCreateLabel(fPtr->win);
 
211
    WMResizeWidget(fPtr->titleLabel, PWIDTH-64, 64);
 
212
    WMMoveWidget(fPtr->titleLabel, 64, 0);
 
213
    largeFont = WMBoldSystemFontOfSize(scrPtr, 24);
 
214
    WMSetLabelFont(fPtr->titleLabel, largeFont);
 
215
    WMReleaseFont(largeFont);
 
216
    WMSetLabelText(fPtr->titleLabel, title);
 
217
 
 
218
    fPtr->line = WMCreateFrame(fPtr->win);
 
219
    WMMoveWidget(fPtr->line, 0, 64);
 
220
    WMResizeWidget(fPtr->line, PWIDTH, 2);
 
221
    WMSetFrameRelief(fPtr->line, WRGroove);
 
222
 
 
223
    fPtr->browser = WMCreateBrowser(fPtr->win);
 
224
    WMSetBrowserAllowEmptySelection(fPtr->browser, True);
 
225
    WMSetBrowserDelegate(fPtr->browser, &browserDelegate);
 
226
    WMSetBrowserAction(fPtr->browser, browserClick, fPtr);
 
227
    WMSetBrowserDoubleAction(fPtr->browser, browserDClick, fPtr);
 
228
    WMMoveWidget(fPtr->browser, 7, 72);
 
229
    WMResizeWidget(fPtr->browser, PWIDTH-14,200);
 
230
    WMHangData(fPtr->browser, fPtr);
 
231
 
 
232
    fPtr->nameLabel = WMCreateLabel(fPtr->win);
 
233
    WMMoveWidget(fPtr->nameLabel, 7, 282);
 
234
    WMResizeWidget(fPtr->nameLabel, 55, 14);
 
235
    WMSetLabelText(fPtr->nameLabel, _("Name:"));
 
236
 
 
237
    fPtr->fileField = WMCreateTextField(fPtr->win);
 
238
    WMMoveWidget(fPtr->fileField, 60, 278);
 
239
    WMResizeWidget(fPtr->fileField, PWIDTH-60-10, 24);
 
240
    WMAddNotificationObserver(textEditedObserver, fPtr,
 
241
                              WMTextDidEndEditingNotification,
 
242
                              fPtr->fileField);
 
243
    WMAddNotificationObserver(textChangedObserver, fPtr,
 
244
                              WMTextDidChangeNotification,
 
245
                              fPtr->fileField);
 
246
 
 
247
    fPtr->okButton = WMCreateCommandButton(fPtr->win);
 
248
    WMMoveWidget(fPtr->okButton, 245, 325);
 
249
    WMResizeWidget(fPtr->okButton, 75, 28);
 
250
    WMSetButtonText(fPtr->okButton, _("OK"));
 
251
    WMSetButtonImage(fPtr->okButton, scrPtr->buttonArrow);
 
252
    WMSetButtonAltImage(fPtr->okButton, scrPtr->pushedButtonArrow);
 
253
    WMSetButtonImagePosition(fPtr->okButton, WIPRight);
 
254
    WMSetButtonAction(fPtr->okButton, buttonClick, fPtr);
 
255
 
 
256
    fPtr->cancelButton = WMCreateCommandButton(fPtr->win);
 
257
    WMMoveWidget(fPtr->cancelButton, 165, 325);
 
258
    WMResizeWidget(fPtr->cancelButton, 75, 28);
 
259
    WMSetButtonText(fPtr->cancelButton, _("Cancel"));
 
260
    WMSetButtonAction(fPtr->cancelButton, buttonClick, fPtr);
 
261
 
 
262
    fPtr->trashcanButton = WMCreateCommandButton(fPtr->win);
 
263
    WMMoveWidget(fPtr->trashcanButton, 7, 325);
 
264
    WMResizeWidget(fPtr->trashcanButton, 28, 28);
 
265
    WMSetButtonImagePosition(fPtr->trashcanButton, WIPImageOnly);
 
266
    WMSetButtonImage(fPtr->trashcanButton, scrPtr->trashcanIcon);
 
267
    WMSetButtonAltImage(fPtr->trashcanButton, scrPtr->altTrashcanIcon);
 
268
    WMSetButtonAction(fPtr->trashcanButton, deleteFile, fPtr);
 
269
 
 
270
    fPtr->createDirButton = WMCreateCommandButton(fPtr->win);
 
271
    WMMoveWidget(fPtr->createDirButton, 37, 325);
 
272
    WMResizeWidget(fPtr->createDirButton, 28, 28);
 
273
    WMSetButtonImagePosition(fPtr->createDirButton, WIPImageOnly);
 
274
    WMSetButtonImage(fPtr->createDirButton, scrPtr->createDirIcon);
 
275
    WMSetButtonAltImage(fPtr->createDirButton, scrPtr->altCreateDirIcon);
 
276
    WMSetButtonAction(fPtr->createDirButton, createDir, fPtr);
 
277
 
 
278
    fPtr->homeButton = WMCreateCommandButton(fPtr->win);
 
279
    WMMoveWidget(fPtr->homeButton, 67, 325);
 
280
    WMResizeWidget(fPtr->homeButton, 28, 28);
 
281
    WMSetButtonImagePosition(fPtr->homeButton, WIPImageOnly);
 
282
    WMSetButtonImage(fPtr->homeButton, scrPtr->homeIcon);
 
283
    WMSetButtonAltImage(fPtr->homeButton, scrPtr->altHomeIcon);
 
284
    WMSetButtonAction(fPtr->homeButton, goHome, fPtr);
 
285
 
 
286
    fPtr->disketteButton = WMCreateCommandButton(fPtr->win);
 
287
    WMMoveWidget(fPtr->disketteButton, 97, 325);
 
288
    WMResizeWidget(fPtr->disketteButton, 28, 28);
 
289
    WMSetButtonImagePosition(fPtr->disketteButton, WIPImageOnly);
 
290
    WMSetButtonImage(fPtr->disketteButton, scrPtr->disketteIcon);
 
291
    WMSetButtonAltImage(fPtr->disketteButton, scrPtr->altDisketteIcon);
 
292
    WMSetButtonAction(fPtr->disketteButton, goFloppy, fPtr);
 
293
 
 
294
    fPtr->unmountButton = WMCreateCommandButton(fPtr->win);
 
295
    WMMoveWidget(fPtr->unmountButton, 127, 325);
 
296
    WMResizeWidget(fPtr->unmountButton, 28, 28);
 
297
    WMSetButtonImagePosition(fPtr->unmountButton, WIPImageOnly);
 
298
    WMSetButtonImage(fPtr->unmountButton, scrPtr->unmountIcon);
 
299
    WMSetButtonAltImage(fPtr->unmountButton, scrPtr->altUnmountIcon);
 
300
    WMSetButtonAction(fPtr->unmountButton, goUnmount, fPtr);
 
301
    WMSetButtonEnabled(fPtr->unmountButton, False);
 
302
 
 
303
 
 
304
    WMRealizeWidget(fPtr->win);
 
305
    WMMapSubwidgets(fPtr->win);
 
306
 
 
307
    WMSetFocusToWidget(fPtr->fileField);
 
308
    WMSetTextFieldCursorPosition(fPtr->fileField, 0);
 
309
 
 
310
    WMLoadBrowserColumnZero(fPtr->browser);
 
311
 
 
312
    WMSetWindowInitialPosition(fPtr->win,
 
313
                               (scrPtr->rootView->size.width - WMWidgetWidth(fPtr->win))/2,
 
314
                               (scrPtr->rootView->size.height - WMWidgetHeight(fPtr->win))/2);
 
315
 
 
316
    fPtr->flags.canChooseFiles = 1;
 
317
    fPtr->flags.canChooseDirectories = 1;
 
318
    fPtr->flags.autoCompletion = 1;
 
319
 
 
320
    return fPtr;
 
321
}
 
322
 
 
323
 
 
324
WMOpenPanel*
 
325
WMGetOpenPanel(WMScreen *scrPtr)
 
326
{
 
327
    WMFilePanel *panel;
 
328
 
 
329
    if (scrPtr->sharedOpenPanel)
 
330
        return scrPtr->sharedOpenPanel;
 
331
 
 
332
    panel = makeFilePanel(scrPtr, "openFilePanel", _("Open"));
 
333
    panel->flags.fileMustExist = 1;
 
334
    panel->flags.panelType = WP_OPEN;
 
335
 
 
336
    scrPtr->sharedOpenPanel = panel;
 
337
 
 
338
    return panel;
 
339
}
 
340
 
 
341
 
 
342
WMSavePanel*
 
343
WMGetSavePanel(WMScreen *scrPtr)
 
344
{
 
345
    WMFilePanel *panel;
 
346
 
 
347
    if (scrPtr->sharedSavePanel)
 
348
        return scrPtr->sharedSavePanel;
 
349
 
 
350
    panel = makeFilePanel(scrPtr, "saveFilePanel", _("Save"));
 
351
    panel->flags.fileMustExist = 0;
 
352
    panel->flags.panelType = WP_SAVE;
 
353
 
 
354
    scrPtr->sharedSavePanel = panel;
 
355
 
 
356
    return panel;
 
357
}
 
358
 
 
359
 
 
360
void
 
361
WMFreeFilePanel(WMFilePanel *panel)
 
362
{
 
363
    if (panel == WMWidgetScreen(panel->win)->sharedSavePanel) {
 
364
        WMWidgetScreen(panel->win)->sharedSavePanel = NULL;
 
365
    }
 
366
    if (panel == WMWidgetScreen(panel->win)->sharedOpenPanel) {
 
367
        WMWidgetScreen(panel->win)->sharedOpenPanel = NULL;
 
368
    }
 
369
    WMRemoveNotificationObserver(panel);
 
370
    WMUnmapWidget(panel->win);
 
371
    WMDestroyWidget(panel->win);
 
372
    wfree(panel);
 
373
}
 
374
 
 
375
 
 
376
int
 
377
WMRunModalFilePanelForDirectory(WMFilePanel *panel, WMWindow *owner,
 
378
                                char *path, char *name, char **fileTypes)
 
379
{
 
380
    WMScreen *scr = WMWidgetScreen(panel->win);
 
381
 
 
382
    if (name && !owner) {
 
383
        WMSetWindowTitle(panel->win, name);
 
384
    }
 
385
 
 
386
    WMChangePanelOwner(panel->win, owner);
 
387
 
 
388
    WMSetFilePanelDirectory(panel, path);
 
389
 
 
390
    switch(panel->flags.panelType) {
 
391
    case WP_OPEN:
 
392
        if (fileTypes)
 
393
            panel->flags.filtered = 1;
 
394
        panel->fileTypes = fileTypes;
 
395
        if (name == NULL)
 
396
            name = _("Open");
 
397
        break;
 
398
    case WP_SAVE:
 
399
        panel->fileTypes = NULL;
 
400
        panel->flags.filtered = 0;
 
401
        if (name == NULL)
 
402
            name = _("Save");
 
403
        break;
 
404
    default:
 
405
        break;
 
406
    }
 
407
 
 
408
    WMSetLabelText(panel->titleLabel, name);
 
409
 
 
410
    WMMapWidget(panel->win);
 
411
 
 
412
    WMRunModalLoop(scr, W_VIEW(panel->win));
 
413
 
 
414
    /* Must withdraw window because the next time we map
 
415
     * it, it might have a different transient owner.
 
416
     */
 
417
    WMCloseWindow(panel->win);
 
418
 
 
419
    return (panel->flags.canceled ? False : True);
 
420
}
 
421
 
 
422
 
 
423
 
 
424
 
 
425
void
 
426
WMSetFilePanelDirectory(WMFilePanel *panel, char *path)
 
427
{
 
428
    WMList *list;
 
429
    WMListItem *item;
 
430
    int col;
 
431
    char *rest;
 
432
 
 
433
    rest = WMSetBrowserPath(panel->browser, path);
 
434
    if (strcmp(path, "/")==0)
 
435
        rest = NULL;
 
436
 
 
437
    col = WMGetBrowserSelectedColumn(panel->browser);
 
438
    list = WMGetBrowserListInColumn(panel->browser, col);
 
439
    if (list && (item = WMGetListSelectedItem(list))) {
 
440
        if (item->isBranch) {
 
441
            WMSetTextFieldText(panel->fileField, rest);
 
442
        } else {
 
443
            WMSetTextFieldText(panel->fileField, item->text);
 
444
        }
 
445
    } else {
 
446
        WMSetTextFieldText(panel->fileField, rest);
 
447
    }
 
448
}
 
449
 
 
450
 
 
451
void
 
452
WMSetFilePanelCanChooseDirectories(WMFilePanel *panel, Bool flag)
 
453
{
 
454
    panel->flags.canChooseDirectories = ((flag==0) ? 0 : 1);
 
455
}
 
456
 
 
457
void
 
458
WMSetFilePanelCanChooseFiles(WMFilePanel *panel, Bool flag)
 
459
{
 
460
    panel->flags.canChooseFiles = ((flag==0) ? 0 : 1);
 
461
}
 
462
 
 
463
 
 
464
void
 
465
WMSetFilePanelAutoCompletion(WMFilePanel *panel, Bool flag)
 
466
{
 
467
    panel->flags.autoCompletion = ((flag==0) ? 0 : 1);
 
468
}
 
469
 
 
470
 
 
471
char*
 
472
WMGetFilePanelFileName(WMFilePanel *panel)
 
473
{
 
474
    return getCurrentFileName(panel);
 
475
}
 
476
 
 
477
 
 
478
void
 
479
WMSetFilePanelAccessoryView(WMFilePanel *panel, WMView *view)
 
480
{
 
481
    WMView *v;
 
482
 
 
483
    panel->accessoryView = view;
 
484
 
 
485
    v = WMWidgetView(panel->win);
 
486
 
 
487
    W_ReparentView(view, v, 0, 0);
 
488
 
 
489
    W_MoveView(view, (v->size.width - v->size.width)/2, 300);
 
490
}
 
491
 
 
492
 
 
493
WMView*
 
494
WMGetFilePanelAccessoryView(WMFilePanel *panel)
 
495
{
 
496
    return panel->accessoryView;
 
497
}
 
498
 
 
499
 
 
500
static char*
 
501
get_name_from_path(char *path)
 
502
{
 
503
    int size;
 
504
 
 
505
    assert(path!=NULL);
 
506
 
 
507
    size = strlen(path);
 
508
 
 
509
    /* remove trailing / */
 
510
    while (size > 0 && path[size-1]=='/')
 
511
        size--;
 
512
    /* directory was root */
 
513
    if (size == 0)
 
514
        return wstrdup("/");
 
515
 
 
516
    while (size > 0 && path[size-1] != '/')
 
517
        size--;
 
518
 
 
519
    return wstrdup(&(path[size]));
 
520
}
 
521
 
 
522
 
 
523
static int
 
524
filterFileName(WMFilePanel *panel, char *file, Bool isDirectory)
 
525
{
 
526
    return True;
 
527
}
 
528
 
 
529
 
 
530
#define CAST(item) (*((WMListItem**)item))
 
531
static int
 
532
comparer(const void *a, const void *b)
 
533
{
 
534
    if (CAST(a)->isBranch == CAST(b)->isBranch)
 
535
        return (strcmp(CAST(a)->text, CAST(b)->text));
 
536
    if (CAST(a)->isBranch)
 
537
        return (-1);
 
538
    return (1);
 
539
}
 
540
#undef CAST
 
541
 
 
542
 
 
543
static void
 
544
listDirectoryOnColumn(WMFilePanel *panel, int column, char *path)
 
545
{
 
546
    WMBrowser *bPtr = panel->browser;
 
547
    struct dirent *dentry;
 
548
    DIR *dir;
 
549
    struct stat stat_buf;
 
550
    char pbuf[PATH_MAX+16];
 
551
    char *name;
 
552
 
 
553
    assert(column >= 0);
 
554
    assert(path != NULL);
 
555
 
 
556
    /* put directory name in the title */
 
557
    name = get_name_from_path(path);
 
558
    WMSetBrowserColumnTitle(bPtr, column, name);
 
559
    wfree(name);
 
560
 
 
561
    dir = opendir(path);
 
562
 
 
563
    if (!dir) {
 
564
#ifdef VERBOSE
 
565
        printf(_("WINGs: could not open directory %s\n"), path);
 
566
#endif
 
567
        return;
 
568
    }
 
569
 
 
570
    /* list contents in the column */
 
571
    while ((dentry = readdir(dir))) {
 
572
        if (strcmp(dentry->d_name, ".")==0 ||
 
573
            strcmp(dentry->d_name, "..")==0)
 
574
            continue;
 
575
 
 
576
        strcpy(pbuf, path);
 
577
        if (strcmp(path, "/")!=0)
 
578
            strcat(pbuf, "/");
 
579
        strcat(pbuf, dentry->d_name);
 
580
 
 
581
        if (stat(pbuf, &stat_buf)!=0) {
 
582
#ifdef VERBOSE
 
583
            printf(_("WINGs: could not stat %s\n"), pbuf);
 
584
#endif
 
585
            continue;
 
586
        } else {
 
587
            int isDirectory;
 
588
 
 
589
            isDirectory = S_ISDIR(stat_buf.st_mode);
 
590
 
 
591
            if (filterFileName(panel, dentry->d_name, isDirectory))
 
592
                WMInsertBrowserItem(bPtr, column, -1, dentry->d_name, isDirectory);
 
593
        }
 
594
    }
 
595
    WMSortBrowserColumnWithComparer(bPtr, column, comparer);
 
596
 
 
597
    closedir(dir);
 
598
}
 
599
 
 
600
 
 
601
static void
 
602
fillColumn(WMBrowserDelegate *self, WMBrowser *bPtr, int column, WMList *list)
 
603
{
 
604
    char *path;
 
605
    WMFilePanel *panel;
 
606
 
 
607
    if (column > 0) {
 
608
        path = WMGetBrowserPathToColumn(bPtr, column-1);
 
609
    } else {
 
610
        path = wstrdup("/");
 
611
    }
 
612
 
 
613
    panel = WMGetHangedData(bPtr);
 
614
    listDirectoryOnColumn(panel, column, path);
 
615
    wfree(path);
 
616
}
 
617
 
 
618
 
 
619
static void
 
620
browserDClick(WMBrowser *bPtr, WMFilePanel *panel)
 
621
{
 
622
    WMPerformButtonClick(panel->okButton);
 
623
}
 
624
 
 
625
static void
 
626
browserClick(WMBrowser *bPtr, WMFilePanel *panel)
 
627
{
 
628
    int col = WMGetBrowserSelectedColumn(bPtr);
 
629
    WMListItem *item = WMGetBrowserSelectedItemInColumn(bPtr, col);
 
630
 
 
631
    if (!item || item->isBranch)
 
632
        WMSetTextFieldText(panel->fileField, NULL);
 
633
    else {
 
634
        WMSetTextFieldText(panel->fileField, item->text);
 
635
    }
 
636
}
 
637
 
 
638
 
 
639
static void
 
640
showError(WMScreen *scr, WMWindow *owner, char *s, char *file)
 
641
{
 
642
    char *errStr;
 
643
 
 
644
    if (file) {
 
645
        errStr = wmalloc(strlen(file)+strlen(s));
 
646
        sprintf(errStr, s, file);
 
647
    } else {
 
648
        errStr = wstrdup(s);
 
649
    }
 
650
    WMRunAlertPanel(scr, owner, _("Error"), errStr, _("OK"), NULL, NULL);
 
651
    wfree(errStr);
 
652
}
 
653
 
 
654
 
 
655
static void
 
656
createDir(WMButton *bPre, WMFilePanel *panel)
 
657
{
 
658
    char *dirName, *directory, *file, *s;
 
659
    WMScreen *scr = WMWidgetScreen(panel->win);
 
660
 
 
661
    dirName = WMRunInputPanel(scr, panel->win, _("Create Directory"),
 
662
                              _("Enter directory name"), "", _("OK"), _("Cancel"));
 
663
    if (!dirName)
 
664
        return;
 
665
 
 
666
    directory = getCurrentFileName(panel);
 
667
    s = strrchr(directory,'/');
 
668
    if (s) s[1] = 0;
 
669
 
 
670
    if (dirName[0] == '/') {
 
671
        directory[0] = 0;
 
672
    } else {
 
673
        while ((s = strstr(directory,"//"))) {
 
674
            int i;
 
675
            for (i = 2;s[i] == '/';i++);
 
676
            strcpy(s, &s[i-1]);
 
677
        }
 
678
        if ((s = strrchr(directory, '/')) && !s[1]) s[0] = 0;
 
679
    }
 
680
    while ((s = strstr(dirName,"//"))) {
 
681
        int i;
 
682
        for (i = 2;s[i] == '/';i++);
 
683
        strcpy(s, &s[i-1]);
 
684
    }
 
685
    if ((s = strrchr(dirName, '/')) && !s[1]) s[0] = 0;
 
686
 
 
687
    file = wmalloc(strlen(dirName)+strlen(directory)+4);
 
688
    sprintf(file, "%s/%s", directory, dirName);
 
689
    while ((s = strstr(file,"//"))) {
 
690
        int i;
 
691
        for (i = 2;s[i] == '/';i++);
 
692
        strcpy(s, &s[i-1]);
 
693
    }
 
694
 
 
695
    if (mkdir(file,0xfff) != 0) {
 
696
        switch (errno) {
 
697
        case EACCES:
 
698
            showError(scr, panel->win, _("Permission denied."), NULL);
 
699
            break;
 
700
        case EEXIST:
 
701
            showError(scr, panel->win, _("'%s' already exists."), file);
 
702
            break;
 
703
        case ENOENT:
 
704
            showError(scr, panel->win, _("Path does not exist."), NULL);
 
705
        }
 
706
    }
 
707
    else WMSetFilePanelDirectory(panel, file);
 
708
 
 
709
    wfree(dirName);
 
710
    wfree(directory);
 
711
    wfree(file);
 
712
}
 
713
 
 
714
static void
 
715
deleteFile(WMButton *bPre, WMFilePanel *panel)
 
716
{
 
717
    char *file;
 
718
    char *buffer, *s;
 
719
    struct stat filestat;
 
720
    WMScreen *scr = WMWidgetScreen(panel->win);
 
721
 
 
722
    file = getCurrentFileName(panel);
 
723
 
 
724
    while ((s = strstr(file,"//"))) {
 
725
        int i;
 
726
        for (i = 2;s[i] == '/';i++);
 
727
        strcpy(s, &s[i-1]);
 
728
    }
 
729
    if (strlen(file) > 1 && (s = strrchr(file, '/')) && !s[1]) s[0] = 0;
 
730
 
 
731
    if (stat(file,&filestat)) {
 
732
        switch (errno) {
 
733
        case ENOENT:
 
734
            showError(scr, panel->win, _("'%s' does not exist."), file);
 
735
            break;
 
736
        case EACCES:
 
737
            showError(scr, panel->win, _("Permission denied."), NULL);
 
738
            break;
 
739
        case ENOMEM:
 
740
            showError(scr, panel->win,
 
741
                      _("Insufficient memory available."), NULL);
 
742
            break;
 
743
        case EROFS:
 
744
            showError(scr, panel->win,
 
745
                      _("'%s' is on a read-only filesystem."), file);
 
746
            break;
 
747
        default:
 
748
            showError(scr, panel->win, _("Can not delete '%s'."), file);
 
749
        }
 
750
        wfree(file);
 
751
        return;
 
752
    } else if (S_ISDIR(filestat.st_mode)) {
 
753
        int len = strlen(file)+20;
 
754
        buffer = wmalloc(len);
 
755
        snprintf(buffer,len,_("Delete directory %s ?"),file);
 
756
    } else {
 
757
        int len = strlen(file)+15;
 
758
        buffer = wmalloc(len);
 
759
        snprintf(buffer,len,_("Delete file %s ?"),file);
 
760
    }
 
761
 
 
762
    if (!WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
 
763
                         _("Warning"), buffer, _("OK"), _("Cancel"), NULL)) {
 
764
        if (S_ISDIR(filestat.st_mode)) {
 
765
            if (rmdir(file) != 0) {
 
766
                switch (errno) {
 
767
                case EACCES:
 
768
                    showError(scr, panel->win, _("Permission denied."), NULL);
 
769
                    break;
 
770
                case ENOENT:
 
771
                    showError(scr, panel->win, _("Directory '%s' does not exist."), file);
 
772
                    break;
 
773
                case ENOTEMPTY:
 
774
                    showError(scr, panel->win, _("Directory '%s' is not empty."), file);
 
775
                    break;
 
776
                case EBUSY:
 
777
                    showError(scr, panel->win, _("Directory '%s' is busy."), file);
 
778
                    break;
 
779
                default:
 
780
                    showError(scr, panel->win, _("Can not delete '%s'."), file);
 
781
                }
 
782
            } else {
 
783
                char *s = strrchr(file,'/');
 
784
                if (s) s[0] = 0;
 
785
                WMSetFilePanelDirectory(panel, file);
 
786
            }
 
787
        } else if (remove(file) != 0) {
 
788
            switch (errno) {
 
789
            case EISDIR:
 
790
                showError(scr, panel->win, _("'%s' is a directory."), file);
 
791
                break;
 
792
            case ENOENT:
 
793
                showError(scr, panel->win, _("'%s' does not exist."), file);
 
794
                break;
 
795
            case EACCES:
 
796
                showError(scr, panel->win, _("Permission denied."), NULL);
 
797
                break;
 
798
            case ENOMEM:
 
799
                showError(scr, panel->win,
 
800
                          _("Insufficient memory available."), NULL);
 
801
                break;
 
802
            case EROFS:
 
803
                showError(scr, panel->win,
 
804
                          _("'%s' is on a read-only filesystem."), file);
 
805
                break;
 
806
            default:
 
807
                showError(scr, panel->win, _("Can not delete '%s'."), file);
 
808
            }
 
809
        } else {
 
810
            char *s = strrchr(file,'/');
 
811
            if (s) s[1] = 0;
 
812
            WMSetFilePanelDirectory(panel, file);
 
813
        }
 
814
    }
 
815
    wfree(buffer);
 
816
    wfree(file);
 
817
}
 
818
 
 
819
static void
 
820
goUnmount(WMButton *bPtr, WMFilePanel *panel)
 
821
{
 
822
}
 
823
 
 
824
 
 
825
static void
 
826
goFloppy(WMButton *bPtr, WMFilePanel *panel)
 
827
{
 
828
    struct stat filestat;
 
829
    WMScreen *scr = WMWidgetScreen(panel->win);
 
830
 
 
831
    if (stat(WINGsConfiguration.floppyPath, &filestat)) {
 
832
        showError(scr, panel->win, _("An error occured browsing '%s'."),
 
833
                  WINGsConfiguration.floppyPath);
 
834
        return;
 
835
    } else if (!S_ISDIR(filestat.st_mode)) {
 
836
        showError(scr, panel->win, _("'%s' is not a directory."),
 
837
                  WINGsConfiguration.floppyPath);
 
838
        return;
 
839
    }
 
840
 
 
841
    WMSetFilePanelDirectory(panel, WINGsConfiguration.floppyPath);
 
842
}
 
843
 
 
844
 
 
845
static void
 
846
goHome(WMButton *bPtr, WMFilePanel *panel)
 
847
{
 
848
    char *home;
 
849
 
 
850
    /* home is statically allocated. Don't free it! */
 
851
    home = wgethomedir();
 
852
    if (!home)
 
853
        return;
 
854
 
 
855
    WMSetFilePanelDirectory(panel, home);
 
856
}
 
857
 
 
858
 
 
859
static void
 
860
handleEvents(XEvent *event, void *data)
 
861
{
 
862
    W_FilePanel *pPtr = (W_FilePanel*)data;
 
863
    W_View *view = WMWidgetView(pPtr->win);
 
864
 
 
865
    if (event->type == ConfigureNotify) {
 
866
        if (event->xconfigure.width != view->size.width
 
867
            || event->xconfigure.height != view->size.height) {
 
868
            unsigned int newWidth = event->xconfigure.width;
 
869
            unsigned int newHeight = event->xconfigure.height;
 
870
            int newColumnCount;
 
871
 
 
872
            W_ResizeView(view, newWidth, newHeight);
 
873
            WMResizeWidget(pPtr->line, newWidth, 2);
 
874
            WMResizeWidget(pPtr->browser, newWidth-14,
 
875
                           newHeight-(PHEIGHT-200));
 
876
            WMResizeWidget(pPtr->fileField, newWidth-60-10, 24);
 
877
            WMMoveWidget(pPtr->nameLabel, 7, newHeight-(PHEIGHT-282));
 
878
            WMMoveWidget(pPtr->fileField, 60, newHeight-(PHEIGHT-278));
 
879
            WMMoveWidget(pPtr->okButton, newWidth-(PWIDTH-245),
 
880
                         newHeight-(PHEIGHT-325));
 
881
            WMMoveWidget(pPtr->cancelButton, newWidth-(PWIDTH-165),
 
882
                         newHeight-(PHEIGHT-325));
 
883
 
 
884
            WMMoveWidget(pPtr->trashcanButton, 7, newHeight-(PHEIGHT-325));
 
885
            WMMoveWidget(pPtr->createDirButton, 37, newHeight-(PHEIGHT-325));
 
886
            WMMoveWidget(pPtr->homeButton, 67, newHeight-(PHEIGHT-325));
 
887
            WMMoveWidget(pPtr->disketteButton, 97, newHeight-(PHEIGHT-325));
 
888
            WMMoveWidget(pPtr->unmountButton, 127, newHeight-(PHEIGHT-325));
 
889
 
 
890
            newColumnCount = (newWidth - 14) / 140;
 
891
            WMSetBrowserMaxVisibleColumns(pPtr->browser, newColumnCount);
 
892
        }
 
893
    }
 
894
}
 
895
 
 
896
 
 
897
static char*
 
898
getCurrentFileName(WMFilePanel *panel)
 
899
{
 
900
    char *path;
 
901
    char *file;
 
902
    char *tmp;
 
903
    int len;
 
904
 
 
905
    path = WMGetBrowserPath(panel->browser);
 
906
 
 
907
    len = strlen(path);
 
908
    if (path[len-1]=='/') {
 
909
        file = WMGetTextFieldText(panel->fileField);
 
910
        tmp = wmalloc(strlen(path)+strlen(file)+8);
 
911
        if (file[0]!='/') {
 
912
            strcpy(tmp, path);
 
913
            strcat(tmp, file);
 
914
        } else
 
915
            strcpy(tmp, file);
 
916
 
 
917
        wfree(file);
 
918
        wfree(path);
 
919
        return tmp;
 
920
    } else {
 
921
        return path;
 
922
    }
 
923
}
 
924
 
 
925
 
 
926
 
 
927
static Bool
 
928
validOpenFile(WMFilePanel *panel)
 
929
{
 
930
    WMListItem *item;
 
931
    int col, haveFile = 0;
 
932
    char *file = WMGetTextFieldText(panel->fileField);
 
933
 
 
934
    if (file[0] != '\0')
 
935
        haveFile = 1;
 
936
    wfree(file);
 
937
 
 
938
    col = WMGetBrowserSelectedColumn(panel->browser);
 
939
    item = WMGetBrowserSelectedItemInColumn(panel->browser, col);
 
940
    if (item) {
 
941
        if (item->isBranch && !panel->flags.canChooseDirectories && !haveFile)
 
942
            return False;
 
943
        else if (!item->isBranch && !panel->flags.canChooseFiles)
 
944
            return False;
 
945
        else
 
946
            return True;
 
947
    } else {
 
948
        /* we compute for / here */
 
949
        if (!panel->flags.canChooseDirectories && !haveFile)
 
950
            return False;
 
951
        else
 
952
            return True;
 
953
    }
 
954
    return True;
 
955
}
 
956
 
 
957
 
 
958
 
 
959
static void
 
960
buttonClick(WMButton *bPtr, WMFilePanel *panel)
 
961
{
 
962
    WMRange range;
 
963
 
 
964
    if (bPtr == panel->okButton) {
 
965
        if (!validOpenFile(panel))
 
966
            return;
 
967
        if (panel->flags.fileMustExist) {
 
968
            char *file;
 
969
 
 
970
            file = getCurrentFileName(panel);
 
971
            if (access(file, F_OK)!=0) {
 
972
                WMRunAlertPanel(WMWidgetScreen(panel->win), panel->win,
 
973
                                _("Error"), _("File does not exist."),
 
974
                                _("OK"), NULL, NULL);
 
975
                wfree(file);
 
976
                return;
 
977
            }
 
978
            wfree(file);
 
979
        }
 
980
        panel->flags.canceled = 0;
 
981
    } else
 
982
        panel->flags.canceled = 1;
 
983
 
 
984
    range.count = range.position = 0;
 
985
    WMSelectTextFieldRange(panel->fileField, range);
 
986
    WMBreakModalLoop(WMWidgetScreen(bPtr));
 
987
}
 
988
 
 
989