~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/xpinstall/wizard/unix/src2/nsSetupTypeDlg.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 
2
/*
 
3
 * The contents of this file are subject to the Netscape Public
 
4
 * License Version 1.1 (the "License"); you may not use this file
 
5
 * except in compliance with the License. You may obtain a copy of
 
6
 * the License at http://www.mozilla.org/NPL/
 
7
 *
 
8
 * Software distributed under the License is distributed on an "AS
 
9
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 
10
 * implied. See the License for the specific language governing
 
11
 * rights and limitations under the License.
 
12
 *
 
13
 * The Original Code is Mozilla Communicator client code, 
 
14
 * released March 31, 1998. 
 
15
 *
 
16
 * The Initial Developer of the Original Code is Netscape Communications 
 
17
 * Corporation.  Portions created by Netscape are
 
18
 * Copyright (C) 1998 Netscape Communications Corporation. All
 
19
 * Rights Reserved.
 
20
 *
 
21
 * Contributor(s): 
 
22
 *     Samir Gehani <sgehani@netscape.com>
 
23
 */
 
24
 
 
25
#include "nscore.h"
 
26
#include "nsSetupTypeDlg.h"
 
27
#include "nsXInstaller.h"
 
28
 
 
29
#include <sys/types.h>
 
30
#include <dirent.h>
 
31
 
 
32
// need these for statfs 
 
33
 
 
34
#ifdef HAVE_SYS_STATVFS_H
 
35
#include <sys/statvfs.h>
 
36
#endif
 
37
 
 
38
#ifdef HAVE_SYS_STATFS_H
 
39
#include <sys/statfs.h>
 
40
#endif
 
41
 
 
42
#ifdef HAVE_STATVFS
 
43
#define STATFS statvfs
 
44
#else
 
45
#define STATFS statfs
 
46
#endif
 
47
 
 
48
 
 
49
static GtkWidget        *sBrowseBtn;
 
50
static gint             sBrowseBtnID;
 
51
static GtkWidget        *sFolder;
 
52
static GSList           *sGroup;
 
53
static GtkWidget        *sCreateDestDlg;
 
54
static GtkWidget        *sDelInstDlg;
 
55
static int              sFilePickerUp = FALSE;
 
56
static int              sConfirmCreateUp = FALSE;
 
57
static int              sDelInstUp = FALSE;
 
58
static nsLegacyCheck    *sLegacyChecks = NULL;
 
59
static nsObjectIgnore   *sObjectsToIgnore = NULL;
 
60
 
 
61
nsSetupTypeDlg::nsSetupTypeDlg() :
 
62
    mMsg0(NULL),
 
63
    mSetupTypeList(NULL)
 
64
{
 
65
}
 
66
 
 
67
nsSetupTypeDlg::~nsSetupTypeDlg()
 
68
{
 
69
    FreeSetupTypeList();
 
70
    FreeLegacyChecks();
 
71
 
 
72
    XI_IF_FREE(mMsg0)
 
73
}
 
74
 
 
75
void
 
76
nsSetupTypeDlg::Back(GtkWidget *aWidget, gpointer aData)
 
77
{
 
78
    DUMP("Back");
 
79
    if (aData != gCtx->sdlg) return;
 
80
    if (gCtx->bMoving)
 
81
    {
 
82
        gCtx->bMoving = FALSE;
 
83
        return;
 
84
    }
 
85
 
 
86
    // hide this notebook page
 
87
    gCtx->sdlg->Hide(nsXInstallerDlg::BACKWARD_MOVE);
 
88
 
 
89
    // disconnect this dlg's nav btn signal handlers
 
90
    gtk_signal_disconnect(GTK_OBJECT(gCtx->back), gCtx->backID);
 
91
    gtk_signal_disconnect(GTK_OBJECT(gCtx->next), gCtx->nextID);
 
92
    gtk_signal_disconnect(GTK_OBJECT(sBrowseBtn), sBrowseBtnID);
 
93
 
 
94
    // show the next dlg
 
95
    gCtx->ldlg->Show(nsXInstallerDlg::BACKWARD_MOVE);
 
96
    gCtx->bMoving = TRUE;
 
97
}
 
98
 
 
99
void 
 
100
nsSetupTypeDlg::Next(GtkWidget *aWidget, gpointer aData)
 
101
{
 
102
    DUMP("Next");
 
103
    if (aData != gCtx->sdlg) return;
 
104
    if (gCtx->bMoving)
 
105
    {
 
106
        gCtx->bMoving = FALSE;
 
107
        return;
 
108
    }
 
109
 
 
110
    // creation confirmation dlg still up
 
111
    if (sConfirmCreateUp || sDelInstUp)
 
112
        return;
 
113
 
 
114
    // verify selected destination directory exists
 
115
    if (OK != nsSetupTypeDlg::VerifyDestination())
 
116
        return;
 
117
 
 
118
    // old installation may exist: delete it
 
119
    if (OK != nsSetupTypeDlg::DeleteOldInst())
 
120
        return;
 
121
 
 
122
    // make sure destination directory is empty
 
123
    if (OK != nsSetupTypeDlg::CheckDestEmpty())
 
124
        return;
 
125
 
 
126
    // if not custom setup type verify disk space
 
127
    if (gCtx->opt->mSetupType != (gCtx->sdlg->GetNumSetupTypes() - 1))
 
128
    {
 
129
        if (OK != nsSetupTypeDlg::VerifyDiskSpace())
 
130
            return;
 
131
    }
 
132
 
 
133
    // hide this notebook page
 
134
    gCtx->sdlg->Hide(nsXInstallerDlg::FORWARD_MOVE);
 
135
 
 
136
    // disconnect this dlg's nav btn signal handlers
 
137
    gtk_signal_disconnect(GTK_OBJECT(gCtx->back), gCtx->backID);
 
138
    gtk_signal_disconnect(GTK_OBJECT(gCtx->next), gCtx->nextID);
 
139
    gtk_signal_disconnect(GTK_OBJECT(sBrowseBtn), sBrowseBtnID);
 
140
 
 
141
    // show the last dlg
 
142
    if (gCtx->opt->mSetupType == (gCtx->sdlg->GetNumSetupTypes() - 1))
 
143
        gCtx->cdlg->Show(nsXInstallerDlg::FORWARD_MOVE);
 
144
    else
 
145
        gCtx->idlg->Show(nsXInstallerDlg::FORWARD_MOVE);
 
146
    gCtx->bMoving = TRUE;
 
147
}
 
148
 
 
149
int
 
150
nsSetupTypeDlg::Parse(nsINIParser *aParser)
 
151
{
 
152
    int err = OK;
 
153
    int bufsize = 0;
 
154
    char *showDlg = NULL;
 
155
    int i, j;
 
156
    char *currSec = (char *) malloc(strlen(SETUP_TYPEd) + 1); // e.g. SetupType12
 
157
    if (!currSec) return E_MEM;
 
158
    char *currKey = (char *) malloc(1 + 3); // e.g. C0, C1, C12
 
159
    if (!currKey) return E_MEM;
 
160
    char *currOIKey = (char *) malloc(strlen(OBJECT_IGNOREd) + 1);
 
161
    if (!currOIKey) return E_MEM;
 
162
    char *currLCSec = (char *) malloc(strlen(LEGACY_CHECKd) + 1);
 
163
    if (!currLCSec) return E_MEM;
 
164
    char *currVal = NULL;
 
165
    nsLegacyCheck *currLC = NULL, *lastLC = NULL, *nextLC = NULL;
 
166
    nsObjectIgnore *currOI = NULL, *lastOI = NULL, *nextOI = NULL;
 
167
    nsComponent *currComp = NULL;
 
168
    nsComponent *currCompDup = NULL;
 
169
    int currIndex;
 
170
    int currNumComps = 0;
 
171
 
 
172
    nsComponentList *compList = gCtx->cdlg->GetCompList();
 
173
    DUMP("Pre-verification of comp list")
 
174
    XI_VERIFY(compList);
 
175
    DUMP("Post-verification of comp list")
 
176
 
 
177
    nsSetupType *currST = NULL;
 
178
    char *currDescShort = NULL;
 
179
    char *currDescLong = NULL;
 
180
 
 
181
    XI_VERIFY(gCtx);
 
182
 
 
183
    /* optional keys */
 
184
    err = aParser->GetStringAlloc(DLG_SETUP_TYPE, MSG0, &mMsg0, &bufsize);
 
185
    if (err != OK && err != nsINIParser::E_NO_KEY) goto BAIL; else err = OK;
 
186
 
 
187
    bufsize = 5;
 
188
    err = aParser->GetStringAlloc(DLG_SETUP_TYPE, SHOW_DLG, &showDlg, &bufsize);
 
189
    if (err != OK && err != nsINIParser::E_NO_KEY) goto BAIL; else err = OK;
 
190
    if (bufsize != 0 && showDlg)
 
191
    {
 
192
        if (0 == strncmp(showDlg, "TRUE", 4))
 
193
            mShowDlg = nsXInstallerDlg::SHOW_DIALOG;
 
194
        else if (0 == strncmp(showDlg, "FALSE", 5))
 
195
            mShowDlg = nsXInstallerDlg::SKIP_DIALOG;
 
196
    }
 
197
 
 
198
    bufsize = 0;
 
199
    err = aParser->GetStringAlloc(DLG_SETUP_TYPE, TITLE, &mTitle, &bufsize);
 
200
    if (err != OK && err != nsINIParser::E_NO_KEY) goto BAIL; else err = OK;
 
201
    if (bufsize == 0)
 
202
            XI_IF_FREE(mTitle); 
 
203
 
 
204
    /* Objects to Ignore */
 
205
    sObjectsToIgnore = new nsObjectIgnore();
 
206
    currOI = sObjectsToIgnore;
 
207
    for (i = 0; i < MAX_LEGACY_CHECKS; i++)
 
208
    {
 
209
        // construct key name based on index
 
210
        memset(currOIKey, 0, (strlen(OBJECT_IGNOREd) + 1));
 
211
        sprintf(currOIKey, OBJECT_IGNOREd, i);
 
212
 
 
213
        // get ObjectToIgnore key
 
214
        bufsize = 0;
 
215
        err = aParser->GetStringAlloc(CLEAN_UPGRADE, currOIKey, &currVal, &bufsize);
 
216
        if (err != OK) 
 
217
        { 
 
218
            if (err != nsINIParser::E_NO_SEC &&
 
219
                err != nsINIParser::E_NO_KEY) goto BAIL; 
 
220
            else 
 
221
            {
 
222
                err = OK; 
 
223
                XI_IF_DELETE(currOI);
 
224
                if (lastOI)
 
225
                    lastOI->InitNext();
 
226
                break; 
 
227
            } 
 
228
        }
 
229
        currOI->SetFilename(currVal);
 
230
 
 
231
        nextOI = new nsObjectIgnore();
 
232
        currOI->SetNext(nextOI);
 
233
        lastOI = currOI;
 
234
        currOI = nextOI;
 
235
    }
 
236
    if (i == 0) // none found
 
237
        sObjectsToIgnore = NULL;
 
238
 
 
239
    /* legacy check */
 
240
    sLegacyChecks = new nsLegacyCheck();
 
241
    currLC = sLegacyChecks;
 
242
    for (i = 0; i < MAX_LEGACY_CHECKS; i++)
 
243
    {
 
244
        // construct section name based on index
 
245
        memset(currLCSec, 0, (strlen(LEGACY_CHECKd) + 1));
 
246
        sprintf(currLCSec, LEGACY_CHECKd, i);
 
247
 
 
248
        // get "Filename" and "Message" keys
 
249
        bufsize = 0;
 
250
        err = aParser->GetStringAlloc(currLCSec, FILENAME, &currVal, &bufsize);
 
251
        if (err != OK) 
 
252
        { 
 
253
            if (err != nsINIParser::E_NO_SEC &&
 
254
                err != nsINIParser::E_NO_KEY) goto BAIL; 
 
255
            else 
 
256
            {
 
257
                err = OK; 
 
258
                XI_IF_DELETE(currLC);
 
259
                if (lastLC)
 
260
                    lastLC->InitNext();
 
261
                break; 
 
262
            } 
 
263
        }
 
264
        currLC->SetFilename(currVal);
 
265
 
 
266
        bufsize = 0;
 
267
        err = aParser->GetStringAlloc(currLCSec, MSG, &currVal, &bufsize);
 
268
        if (err != OK)
 
269
        {
 
270
            if (err != nsINIParser::E_NO_SEC &&
 
271
                err != nsINIParser::E_NO_KEY) goto BAIL; 
 
272
            else 
 
273
            {
 
274
                err = OK; 
 
275
                XI_IF_DELETE(currLC);
 
276
                if (lastLC)
 
277
                    lastLC->InitNext();
 
278
                break; 
 
279
            } 
 
280
        }
 
281
        currLC->SetMessage(currVal);
 
282
 
 
283
        nextLC = new nsLegacyCheck();
 
284
        currLC->SetNext(nextLC);
 
285
        lastLC = currLC;
 
286
        currLC = nextLC;
 
287
    }
 
288
    if (i == 0) // none found
 
289
        sLegacyChecks = NULL;
 
290
 
 
291
    /* setup types */
 
292
    for (i=0; i<MAX_SETUP_TYPES; i++)
 
293
    {
 
294
        sprintf(currSec, SETUP_TYPEd, i);
 
295
 
 
296
        bufsize = 0;
 
297
        err = aParser->GetStringAlloc(currSec, DESC_SHORT, &currDescShort,
 
298
                                      &bufsize);
 
299
        if (err != OK && err != nsINIParser::E_NO_SEC) goto fin_iter;
 
300
        if (bufsize == 0 || err == nsINIParser::E_NO_SEC) // no more setup types
 
301
        {
 
302
            err = OK;
 
303
            break;
 
304
        }
 
305
 
 
306
        bufsize = 0;
 
307
        err = aParser->GetStringAlloc(currSec, DESC_LONG, &currDescLong,
 
308
                                      &bufsize);
 
309
        if (err != OK || bufsize == 0) goto fin_iter;
 
310
 
 
311
        currST = new nsSetupType();
 
312
        if (!currST) goto fin_iter;
 
313
 
 
314
        currST->SetDescShort(currDescShort);
 
315
        currST->SetDescLong(currDescLong);
 
316
 
 
317
        currNumComps = 0;
 
318
        for (j=0; j<MAX_COMPONENTS; j++)
 
319
        {
 
320
            sprintf(currKey, Cd, j);
 
321
            
 
322
            bufsize = 0;
 
323
            err = aParser->GetStringAlloc(currSec, currKey, &currVal, 
 
324
                                          &bufsize);
 
325
            if (err != OK && err != nsINIParser::E_NO_KEY) continue;
 
326
            if (bufsize == 0 || err == nsINIParser::E_NO_KEY) 
 
327
            {
 
328
                err = OK;
 
329
                break;
 
330
            }
 
331
        
 
332
            currComp = NULL;
 
333
            currIndex = atoi(currVal + strlen(COMPONENT));
 
334
            currComp = compList->GetCompByIndex(currIndex);
 
335
            if (currComp)
 
336
            {
 
337
                // preserve next ptr
 
338
                currCompDup = currComp->Duplicate(); 
 
339
                currST->SetComponent(currCompDup);
 
340
                currNumComps++;
 
341
            }
 
342
        }
 
343
        if (currNumComps > 0)
 
344
        {
 
345
            AddSetupType(currST);
 
346
            currST = NULL;
 
347
        }
 
348
 
 
349
fin_iter:
 
350
        XI_IF_DELETE(currST);
 
351
    }
 
352
 
 
353
    err = OK;
 
354
 
 
355
BAIL:
 
356
    XI_IF_FREE(currSec);
 
357
    XI_IF_FREE(currKey);
 
358
    XI_IF_FREE(currOIKey);
 
359
    XI_IF_FREE(currLCSec);
 
360
 
 
361
    return err;
 
362
}
 
363
 
 
364
int
 
365
nsSetupTypeDlg::Show(int aDirection)
 
366
{
 
367
    int err = OK;
 
368
    int numSetupTypes = 0;
 
369
    int i;
 
370
    GtkWidget *stTable = NULL;
 
371
    GtkWidget *radbtns[MAX_SETUP_TYPES];
 
372
    GtkWidget *desc[MAX_SETUP_TYPES];
 
373
    nsSetupType *currST = NULL;
 
374
    GtkWidget *destTable = NULL;
 
375
    GtkWidget *frame = NULL;
 
376
    GtkWidget *hbox = NULL;
 
377
 
 
378
    XI_VERIFY(gCtx);
 
379
    XI_VERIFY(gCtx->notebook);
 
380
 
 
381
    if (mWidgetsInit == FALSE)
 
382
    {
 
383
        // create a new table and add it as a page of the notebook
 
384
        mTable = gtk_table_new(4, 1, FALSE);
 
385
        gtk_notebook_append_page(GTK_NOTEBOOK(gCtx->notebook), mTable, NULL);
 
386
        mPageNum = gtk_notebook_get_current_page(GTK_NOTEBOOK(gCtx->notebook));
 
387
        gtk_widget_show(mTable);
 
388
 
 
389
        // insert a static text widget in the first row
 
390
        GtkWidget *msg0 = gtk_label_new(mMsg0);
 
391
        hbox = gtk_hbox_new(FALSE, 0);
 
392
        gtk_box_pack_start(GTK_BOX(hbox), msg0, FALSE, FALSE, 0);
 
393
        gtk_widget_show(hbox);
 
394
        gtk_table_attach(GTK_TABLE(mTable), hbox, 0, 1, 1, 2,
 
395
            static_cast<GtkAttachOptions>(GTK_FILL | GTK_EXPAND),
 
396
            GTK_FILL, 20, 20);
 
397
        gtk_widget_show(msg0);
 
398
 
 
399
        // insert a [n x 2] heterogeneous table in the second row
 
400
        // where n = numSetupTypes
 
401
        numSetupTypes = GetNumSetupTypes();
 
402
        stTable = gtk_table_new(numSetupTypes, 4, FALSE);
 
403
        gtk_widget_show(stTable);
 
404
        gtk_table_attach(GTK_TABLE(mTable), stTable, 0, 1, 2, 3,
 
405
            static_cast<GtkAttachOptions>(GTK_EXPAND | GTK_FILL),
 
406
            static_cast<GtkAttachOptions>(GTK_EXPAND | GTK_FILL),
 
407
            20, 0);
 
408
 
 
409
        currST = GetSetupTypeList();
 
410
        if (!currST) return E_NO_SETUPTYPES;
 
411
 
 
412
        // first radio button
 
413
        gCtx->opt->mSetupType = 0;
 
414
        radbtns[0] = gtk_radio_button_new_with_label(NULL,
 
415
                        currST->GetDescShort());
 
416
        sGroup = gtk_radio_button_group(GTK_RADIO_BUTTON(radbtns[0]));
 
417
        gtk_table_attach(GTK_TABLE(stTable), radbtns[0], 0, 1, 0, 1,
 
418
            static_cast<GtkAttachOptions>(GTK_FILL | GTK_EXPAND),
 
419
            static_cast<GtkAttachOptions>(GTK_FILL | GTK_EXPAND),
 
420
            0, 0);
 
421
        gtk_signal_connect(GTK_OBJECT(radbtns[0]), "toggled",
 
422
                           GTK_SIGNAL_FUNC(RadBtnToggled), 0);
 
423
        gtk_widget_show(radbtns[0]);
 
424
 
 
425
        desc[0] = gtk_label_new(currST->GetDescLong());
 
426
        gtk_label_set_justify(GTK_LABEL(desc[0]), GTK_JUSTIFY_LEFT);
 
427
        gtk_label_set_line_wrap(GTK_LABEL(desc[0]), TRUE);
 
428
        hbox = gtk_hbox_new(FALSE, 0);
 
429
        gtk_box_pack_start(GTK_BOX(hbox), desc[0], FALSE, FALSE, 0);
 
430
        gtk_widget_show(hbox);
 
431
        gtk_table_attach_defaults(GTK_TABLE(stTable), hbox, 1, 2, 0, 1);
 
432
        gtk_widget_show(desc[0]);
 
433
 
 
434
        // remaining radio buttons
 
435
        for (i = 1; i < numSetupTypes; i++)
 
436
        {
 
437
            currST = currST->GetNext();
 
438
            if (!currST) break;
 
439
 
 
440
            radbtns[i] = gtk_radio_button_new_with_label(sGroup,
 
441
                            currST->GetDescShort());
 
442
            sGroup = gtk_radio_button_group(GTK_RADIO_BUTTON(radbtns[i]));
 
443
            gtk_table_attach(GTK_TABLE(stTable), radbtns[i], 0, 1, i, i+1,
 
444
                static_cast<GtkAttachOptions>(GTK_FILL | GTK_EXPAND),
 
445
                static_cast<GtkAttachOptions>(GTK_FILL | GTK_EXPAND), 0, 0);
 
446
            gtk_signal_connect(GTK_OBJECT(radbtns[i]), "toggled",
 
447
                               GTK_SIGNAL_FUNC(RadBtnToggled),
 
448
                               reinterpret_cast<void *>(i));
 
449
            gtk_widget_show(radbtns[i]);
 
450
 
 
451
            desc[i] = gtk_label_new(currST->GetDescLong());
 
452
            gtk_label_set_justify(GTK_LABEL(desc[i]), GTK_JUSTIFY_LEFT);
 
453
            gtk_label_set_line_wrap(GTK_LABEL(desc[i]), TRUE);
 
454
            hbox = gtk_hbox_new(FALSE, 0);
 
455
            gtk_box_pack_start(GTK_BOX(hbox), desc[i], FALSE, FALSE, 0);
 
456
            gtk_widget_show(hbox);
 
457
            gtk_table_attach_defaults(GTK_TABLE(stTable), hbox, 1, 2, i, i+1);
 
458
            gtk_widget_show(desc[i]);
 
459
        }
 
460
 
 
461
        // insert a [1 x 2] heterogeneous table in the third row
 
462
        destTable = gtk_table_new(1, 2, FALSE);
 
463
        gtk_widget_show(destTable); 
 
464
 
 
465
        gtk_table_attach(GTK_TABLE(mTable), destTable, 0, 1, 3, 4,
 
466
            static_cast<GtkAttachOptions>(GTK_EXPAND | GTK_FILL),
 
467
            static_cast<GtkAttachOptions>(GTK_EXPAND | GTK_FILL),
 
468
            20, 5);
 
469
        frame = gtk_frame_new(gCtx->Res("DEST_DIR"));
 
470
        gtk_table_attach_defaults(GTK_TABLE(destTable), frame, 0, 2, 0, 1);
 
471
        gtk_widget_show(frame);
 
472
 
 
473
        if (!gCtx->opt->mDestination)
 
474
        {
 
475
            gCtx->opt->mDestination = (char*)malloc(MAXPATHLEN * sizeof(char));
 
476
            getcwd(gCtx->opt->mDestination, MAXPATHLEN);
 
477
        }
 
478
        sFolder = gtk_label_new(gCtx->opt->mDestination);
 
479
        gtk_label_set_line_wrap(GTK_LABEL(sFolder), TRUE);
 
480
        gtk_widget_show(sFolder);
 
481
        gtk_table_attach_defaults(GTK_TABLE(destTable), sFolder, 0, 1, 0, 1);
 
482
 
 
483
        sBrowseBtn = gtk_button_new_with_label(gCtx->Res("BROWSE"));
 
484
        gtk_widget_show(sBrowseBtn);
 
485
        gtk_table_attach(GTK_TABLE(destTable), sBrowseBtn, 1, 2, 0, 1,
 
486
            static_cast<GtkAttachOptions>(GTK_EXPAND | GTK_FILL),
 
487
            GTK_SHRINK, 10, 10);
 
488
 
 
489
        mWidgetsInit = TRUE;
 
490
    }
 
491
    else
 
492
    {
 
493
        gtk_notebook_set_page(GTK_NOTEBOOK(gCtx->notebook), mPageNum);
 
494
        gtk_widget_show(mTable);
 
495
    }
 
496
 
 
497
    // signal connect the buttons
 
498
    // NOTE: back button disfunctional in this dlg since user accepted license
 
499
    gCtx->backID = gtk_signal_connect(GTK_OBJECT(gCtx->back), "clicked",
 
500
                   GTK_SIGNAL_FUNC(nsSetupTypeDlg::Back), gCtx->sdlg);
 
501
    gCtx->nextID = gtk_signal_connect(GTK_OBJECT(gCtx->next), "clicked",
 
502
                   GTK_SIGNAL_FUNC(nsSetupTypeDlg::Next), gCtx->sdlg);
 
503
    sBrowseBtnID = gtk_signal_connect(GTK_OBJECT(sBrowseBtn), "clicked",
 
504
                   GTK_SIGNAL_FUNC(nsSetupTypeDlg::SelectFolder), NULL);  
 
505
 
 
506
    if (aDirection == nsXInstallerDlg::FORWARD_MOVE)
 
507
    {
 
508
        // change the button titles back to Back/Next
 
509
        gtk_container_remove(GTK_CONTAINER(gCtx->next), gCtx->acceptLabel);
 
510
        gtk_container_remove(GTK_CONTAINER(gCtx->back), gCtx->declineLabel);
 
511
        gCtx->nextLabel = gtk_label_new(gCtx->Res("NEXT"));
 
512
        gCtx->backLabel = gtk_label_new(gCtx->Res("BACK"));
 
513
        gtk_widget_show(gCtx->nextLabel);
 
514
        gtk_widget_show(gCtx->backLabel);
 
515
        gtk_container_add(GTK_CONTAINER(gCtx->next), gCtx->nextLabel);
 
516
        gtk_container_add(GTK_CONTAINER(gCtx->back), gCtx->backLabel);
 
517
        gtk_widget_show(gCtx->next);
 
518
        gtk_widget_show(gCtx->back);
 
519
    }
 
520
        // from install dlg
 
521
    if (aDirection == nsXInstallerDlg::BACKWARD_MOVE && 
 
522
        // not custom setup type
 
523
        gCtx->opt->mSetupType != (gCtx->sdlg->GetNumSetupTypes() - 1))
 
524
    {
 
525
        DUMP("Back from Install to Setup Type");
 
526
        gtk_container_remove(GTK_CONTAINER(gCtx->next), gCtx->installLabel);
 
527
        gCtx->nextLabel = gtk_label_new(gCtx->Res("NEXT"));
 
528
        gtk_container_add(GTK_CONTAINER(gCtx->next), gCtx->nextLabel);
 
529
        gtk_widget_show(gCtx->nextLabel);
 
530
        gtk_widget_show(gCtx->next);
 
531
    }     
 
532
 
 
533
    gtk_widget_hide(gCtx->back);
 
534
 
 
535
    return err;
 
536
}
 
537
 
 
538
int
 
539
nsSetupTypeDlg::Hide(int aDirection)
 
540
{
 
541
    gtk_widget_hide(mTable);
 
542
 
 
543
    return OK;
 
544
}
 
545
 
 
546
int
 
547
nsSetupTypeDlg::SetMsg0(char *aMsg)
 
548
{
 
549
    if (!aMsg)
 
550
        return E_PARAM;
 
551
 
 
552
    mMsg0 = aMsg;
 
553
 
 
554
    return OK;
 
555
}
 
556
 
 
557
char *
 
558
nsSetupTypeDlg::GetMsg0()
 
559
{
 
560
    if (mMsg0)
 
561
        return mMsg0;
 
562
 
 
563
    return NULL;
 
564
}
 
565
 
 
566
int
 
567
nsSetupTypeDlg::AddSetupType(nsSetupType *aSetupType)
 
568
{
 
569
    if (!aSetupType)
 
570
        return E_PARAM;
 
571
 
 
572
    if (!mSetupTypeList)
 
573
    {
 
574
        mSetupTypeList = aSetupType;
 
575
        return OK;
 
576
    }
 
577
 
 
578
    nsSetupType *curr = mSetupTypeList;
 
579
    nsSetupType *next;
 
580
    while (curr)
 
581
    {
 
582
        next = NULL;
 
583
        next = curr->GetNext();
 
584
    
 
585
        if (!next)
 
586
        {
 
587
            return curr->SetNext(aSetupType);
 
588
        }
 
589
 
 
590
        curr = next;
 
591
    }
 
592
 
 
593
    return OK;
 
594
}
 
595
 
 
596
nsSetupType *
 
597
nsSetupTypeDlg::GetSetupTypeList()
 
598
{
 
599
    if (mSetupTypeList)
 
600
        return mSetupTypeList;
 
601
 
 
602
    return NULL;
 
603
}
 
604
 
 
605
int
 
606
nsSetupTypeDlg::GetNumSetupTypes()
 
607
{
 
608
    int num = 0;
 
609
    nsSetupType *curr = NULL;
 
610
 
 
611
    if (!mSetupTypeList)
 
612
        return 0;
 
613
    
 
614
    curr = mSetupTypeList;
 
615
    while(curr)
 
616
    {
 
617
        num++;
 
618
        curr = curr->GetNext();
 
619
    }
 
620
 
 
621
    return num;
 
622
}
 
623
 
 
624
nsSetupType *
 
625
nsSetupTypeDlg::GetSelectedSetupType()
 
626
{
 
627
    nsSetupType *curr = NULL;
 
628
    int numSetupTypes = GetNumSetupTypes();
 
629
    int setupTypeCount = 0;
 
630
 
 
631
    curr = GetSetupTypeList();
 
632
    while (curr && setupTypeCount < numSetupTypes)  // paranoia!
 
633
    {
 
634
        if (setupTypeCount == gCtx->opt->mSetupType)
 
635
            return curr;        
 
636
 
 
637
        setupTypeCount++;
 
638
        curr = curr->GetNext();
 
639
    }
 
640
 
 
641
    return NULL;
 
642
}
 
643
 
 
644
void
 
645
nsSetupTypeDlg::FreeSetupTypeList()
 
646
{
 
647
    nsSetupType *curr = mSetupTypeList;
 
648
    nsSetupType *prev;
 
649
    
 
650
    while (curr)
 
651
    {
 
652
        prev = curr;
 
653
        curr = curr->GetNext();
 
654
 
 
655
        XI_IF_DELETE(prev);
 
656
    }
 
657
}
 
658
 
 
659
void
 
660
nsSetupTypeDlg::FreeLegacyChecks()
 
661
{
 
662
    nsLegacyCheck *curr = NULL;
 
663
    nsLegacyCheck *last = NULL;
 
664
 
 
665
    if (sLegacyChecks)
 
666
    {
 
667
        curr = sLegacyChecks;
 
668
 
 
669
        while(curr)
 
670
        {
 
671
            last = curr;
 
672
            curr = last->GetNext();
 
673
 
 
674
            XI_IF_DELETE(last);
 
675
        }
 
676
    }
 
677
}
 
678
 
 
679
void
 
680
nsSetupTypeDlg::SelectFolder(GtkWidget *aWidget, gpointer aData)
 
681
{
 
682
    DUMP("SelectFolder");
 
683
 
 
684
    if (sFilePickerUp)
 
685
        return;
 
686
 
 
687
    GtkWidget *fileSel = NULL;
 
688
    char *selDir = gCtx->opt->mDestination;
 
689
 
 
690
    fileSel = gtk_file_selection_new(gCtx->Res("SELECT_DIR"));
 
691
    gtk_file_selection_set_filename(GTK_FILE_SELECTION(fileSel), selDir);
 
692
    gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fileSel)->ok_button),
 
693
                       "clicked", (GtkSignalFunc) SelectFolderOK, fileSel);
 
694
    gtk_signal_connect_object(GTK_OBJECT(
 
695
                                GTK_FILE_SELECTION(fileSel)->cancel_button),
 
696
                                "clicked", (GtkSignalFunc) SelectFolderCancel,
 
697
                                GTK_OBJECT(fileSel));
 
698
    gtk_widget_show(fileSel); 
 
699
    sFilePickerUp = TRUE;
 
700
}
 
701
 
 
702
void
 
703
nsSetupTypeDlg::SelectFolderOK(GtkWidget *aWidget, GtkFileSelection *aFileSel)
 
704
{
 
705
    DUMP("SelectFolderOK");
 
706
 
 
707
    struct stat destStat;
 
708
    char *selDir = gtk_file_selection_get_filename(
 
709
                    GTK_FILE_SELECTION(aFileSel));
 
710
 
 
711
    // put the candidate file name in the global variable, then verify it
 
712
 
 
713
    strcpy(gCtx->opt->mDestination, selDir);
 
714
 
 
715
    if (0 == stat(selDir, &destStat))
 
716
        if (!S_ISDIR(destStat.st_mode) || VerifyDestination() != OK ) /* not a directory, or we don't have access permissions, so don't tear down */
 
717
            return;
 
718
 
 
719
    // update folder path displayed
 
720
    gtk_label_set_text(GTK_LABEL(sFolder), gCtx->opt->mDestination);
 
721
    gtk_widget_show(sFolder);
 
722
 
 
723
    // tear down file sel dlg
 
724
    gtk_object_destroy(GTK_OBJECT(aFileSel)); 
 
725
    sFilePickerUp = FALSE;
 
726
}
 
727
 
 
728
void
 
729
nsSetupTypeDlg::SelectFolderCancel(GtkWidget *aWidget, 
 
730
                                   GtkFileSelection *aFileSel)
 
731
{
 
732
    // tear down file sel dlg
 
733
    gtk_object_destroy(GTK_OBJECT(aWidget)); 
 
734
    gtk_object_destroy(GTK_OBJECT(aFileSel)); 
 
735
    sFilePickerUp = FALSE;
 
736
}
 
737
 
 
738
void
 
739
nsSetupTypeDlg::RadBtnToggled(GtkWidget *aWidget, gpointer aData)
 
740
{
 
741
    DUMP("RadBtnToggled");
 
742
    
 
743
    gCtx->opt->mSetupType = NS_PTR_TO_INT32(aData);
 
744
}
 
745
 
 
746
int
 
747
nsSetupTypeDlg::VerifyDestination()
 
748
{
 
749
    int err = E_NO_DEST;
 
750
    int stat_err = 0;
 
751
    struct stat stbuf; 
 
752
    GtkWidget *yesButton, *noButton, *label;
 
753
    GtkWidget *noPermsDlg, *okButton;
 
754
    char message[MAXPATHLEN];
 
755
  
 
756
    stat_err = stat(gCtx->opt->mDestination, &stbuf);
 
757
    if (stat_err == 0)
 
758
    {
 
759
      if (access(gCtx->opt->mDestination, R_OK | W_OK | X_OK ) != 0)
 
760
      {
 
761
        sprintf(message, gCtx->Res("NO_PERMS"), gCtx->opt->mDestination);
 
762
 
 
763
        noPermsDlg = gtk_dialog_new();
 
764
        label = gtk_label_new(message);
 
765
        okButton = gtk_button_new_with_label(gCtx->Res("OK_LABEL"));
 
766
 
 
767
        if (noPermsDlg && label && okButton)
 
768
        {
 
769
          gtk_window_set_title(GTK_WINDOW(noPermsDlg), gCtx->opt->mTitle);
 
770
          gtk_window_set_position(GTK_WINDOW(noPermsDlg), 
 
771
            GTK_WIN_POS_CENTER);
 
772
          gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
 
773
          gtk_box_pack_start(GTK_BOX(
 
774
            GTK_DIALOG(noPermsDlg)->action_area), okButton, FALSE, FALSE, 10);
 
775
          gtk_signal_connect(GTK_OBJECT(okButton), "clicked", 
 
776
            GTK_SIGNAL_FUNC(NoPermsOK), noPermsDlg);
 
777
          gtk_box_pack_start(GTK_BOX(
 
778
            GTK_DIALOG(noPermsDlg)->vbox), label, FALSE, FALSE, 10);
 
779
 
 
780
          gtk_widget_show_all(noPermsDlg);
 
781
        }
 
782
 
 
783
        return E_NO_PERMS;
 
784
      }
 
785
      else
 
786
      {
 
787
        // perms OK, we can proceed
 
788
        return OK;
 
789
      }
 
790
    }
 
791
 
 
792
    // destination doesn't exist so ask user if we should create it
 
793
    sprintf(message, gCtx->Res("DOESNT_EXIST"), gCtx->opt->mDestination);
 
794
 
 
795
    sCreateDestDlg = gtk_dialog_new();
 
796
    label = gtk_label_new(message);
 
797
    yesButton = gtk_button_new_with_label(gCtx->Res("YES_LABEL"));
 
798
    noButton = gtk_button_new_with_label(gCtx->Res("NO_LABEL"));
 
799
 
 
800
    gtk_window_set_title(GTK_WINDOW(sCreateDestDlg), gCtx->opt->mTitle);
 
801
    gtk_window_set_position(GTK_WINDOW(sCreateDestDlg), GTK_WIN_POS_CENTER);
 
802
    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(sCreateDestDlg)->action_area),
 
803
                      yesButton);
 
804
    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(sCreateDestDlg)->action_area),
 
805
                      noButton);
 
806
    gtk_signal_connect(GTK_OBJECT(yesButton), "clicked",
 
807
                       GTK_SIGNAL_FUNC(CreateDestYes), sCreateDestDlg);
 
808
    gtk_signal_connect(GTK_OBJECT(noButton), "clicked",
 
809
                       GTK_SIGNAL_FUNC(CreateDestNo), sCreateDestDlg);
 
810
 
 
811
    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(sCreateDestDlg)->vbox), label);
 
812
    
 
813
    gtk_widget_show_all(sCreateDestDlg);
 
814
    sConfirmCreateUp = TRUE;
 
815
 
 
816
    return err;
 
817
}
 
818
 
 
819
void
 
820
nsSetupTypeDlg::NoPermsOK(GtkWidget *aWidget, gpointer aData)
 
821
{
 
822
    GtkWidget *noPermsDlg = (GtkWidget *) aData;
 
823
 
 
824
    if (!noPermsDlg)
 
825
        return;
 
826
 
 
827
    gtk_widget_destroy(noPermsDlg);
 
828
}
 
829
 
 
830
void
 
831
nsSetupTypeDlg::CreateDestYes(GtkWidget *aWidget, gpointer aData)
 
832
{
 
833
    DUMP("CreateDestYes");
 
834
    int err = 0; 
 
835
    char path[PATH_MAX + 1];
 
836
    int  pathLen = strlen(gCtx->opt->mDestination);
 
837
 
 
838
    if (pathLen > PATH_MAX)
 
839
        pathLen = PATH_MAX;
 
840
    memcpy(path, gCtx->opt->mDestination, pathLen);
 
841
    path[pathLen] = '/';  // for uniform handling
 
842
 
 
843
    struct stat buf;
 
844
    mode_t oldPerms = umask(022);
 
845
 
 
846
    for (int i = 1; !err && i <= pathLen; i++) 
 
847
    {
 
848
        if (path[i] == '/') 
 
849
        {
 
850
            path[i] = '\0';
 
851
            if (stat(path, &buf) != 0) 
 
852
            {
 
853
                err = mkdir(path, (0777 & ~oldPerms));
 
854
            }
 
855
            path[i] = '/';
 
856
        }
 
857
    }
 
858
 
 
859
    umask(oldPerms); // restore original umask
 
860
 
 
861
    gtk_widget_destroy(sCreateDestDlg);
 
862
    sConfirmCreateUp = FALSE;
 
863
 
 
864
    if (err != 0)
 
865
    {
 
866
        ErrorHandler(E_MKDIR_FAIL);
 
867
        return;
 
868
    }
 
869
 
 
870
    // hide this notebook page
 
871
    gCtx->sdlg->Hide(nsXInstallerDlg::FORWARD_MOVE);
 
872
 
 
873
    // disconnect this dlg's nav btn signal handlers
 
874
    gtk_signal_disconnect(GTK_OBJECT(gCtx->back), gCtx->backID);
 
875
    gtk_signal_disconnect(GTK_OBJECT(gCtx->next), gCtx->nextID);
 
876
    gtk_signal_disconnect(GTK_OBJECT(sBrowseBtn), sBrowseBtnID);
 
877
 
 
878
    // show the final dlg
 
879
    if (gCtx->opt->mSetupType == (gCtx->sdlg->GetNumSetupTypes() - 1))
 
880
        gCtx->cdlg->Show(nsXInstallerDlg::FORWARD_MOVE);
 
881
    else
 
882
        gCtx->idlg->Show(nsXInstallerDlg::FORWARD_MOVE);
 
883
}
 
884
 
 
885
void
 
886
nsSetupTypeDlg::CreateDestNo(GtkWidget *aWidget, gpointer aData)
 
887
{
 
888
    DUMP("CreateDestNo");
 
889
 
 
890
    gtk_widget_destroy(sCreateDestDlg);
 
891
    sConfirmCreateUp = FALSE;
 
892
}
 
893
 
 
894
int
 
895
nsSetupTypeDlg::DeleteOldInst()
 
896
{
 
897
    DUMP("DeleteOldInst");
 
898
 
 
899
    const int MAXCHARS = 64; // Maximum chars per line in Delete Dialog
 
900
    const int MAXLINES = 20; // Maximum lines in Delete Dialog
 
901
    int err = OK;
 
902
    struct stat dummy;
 
903
    char path[MAXPATHLEN];
 
904
    GtkWidget *label = NULL;
 
905
    GtkWidget *deleteBtn = NULL; /* delete button */
 
906
    GtkWidget *cancelBtn = NULL; /* cancel button */
 
907
    char *msgPtr = NULL, *msgChunkPtr = NULL, *msgEndPtr = NULL;
 
908
    char msgChunk[MAXCHARS+1];
 
909
    char msg[MAXPATHLEN+512];
 
910
    nsLegacyCheck *currLC = NULL;
 
911
 
 
912
    currLC = sLegacyChecks;
 
913
    while (currLC)
 
914
    {
 
915
      memset(path, 0, MAXPATHLEN);
 
916
      ConstructPath(path, gCtx->opt->mDestination, currLC->GetFilename());
 
917
      DUMP(path);
 
918
 
 
919
      // check if old installation exists
 
920
      if (0 == stat(path, &dummy))
 
921
      {
 
922
          // throw up delete dialog 
 
923
          sDelInstDlg = gtk_dialog_new();
 
924
          gtk_window_set_title(GTK_WINDOW(sDelInstDlg), gCtx->opt->mTitle);
 
925
          gtk_window_set_position(GTK_WINDOW(sDelInstDlg), GTK_WIN_POS_CENTER);
 
926
 
 
927
          deleteBtn = gtk_button_new_with_label(gCtx->Res("DELETE_LABEL"));
 
928
          cancelBtn = gtk_button_new_with_label(gCtx->Res("CANCEL_LABEL"));
 
929
 
 
930
          gtk_container_add(GTK_CONTAINER(GTK_DIALOG(sDelInstDlg)->action_area), 
 
931
              deleteBtn);
 
932
          gtk_container_add(GTK_CONTAINER(GTK_DIALOG(sDelInstDlg)->action_area),
 
933
              cancelBtn);
 
934
          gtk_signal_connect(GTK_OBJECT(deleteBtn), "clicked",
 
935
                         GTK_SIGNAL_FUNC(DeleteInstDelete), sDelInstDlg);
 
936
          gtk_signal_connect(GTK_OBJECT(cancelBtn), "clicked",
 
937
                         GTK_SIGNAL_FUNC(DeleteInstCancel), sDelInstDlg);
 
938
 
 
939
          snprintf(msg, sizeof(msg), currLC->GetMessage(), gCtx->opt->mDestination);
 
940
          msgPtr = msg;
 
941
          msgEndPtr = msg + strlen(msg);
 
942
          // wrap message at MAXCHARS colums (or last space inside MAXCHARS)
 
943
          // stop at MAXLINES rows or stop after last char is reached
 
944
          for (int i = 0; i < MAXLINES && msgPtr < msgEndPtr; i++)
 
945
          {
 
946
              // get the next MAXCHARS chars
 
947
              memset(msgChunk, 0, MAXCHARS+1);
 
948
              strncpy(msgChunk, msgPtr, MAXCHARS);
 
949
 
 
950
              // find last space
 
951
              msgChunkPtr = strrchr(msgChunk, ' ');
 
952
              if (msgChunkPtr)
 
953
              {
 
954
                  *msgChunkPtr = '\0';
 
955
                  msgPtr += (msgChunkPtr - msgChunk + 1);
 
956
              }
 
957
              else
 
958
              {
 
959
                  msgPtr += MAXCHARS;
 
960
              }
 
961
              label = gtk_label_new(msgChunk);
 
962
              gtk_box_pack_start(GTK_BOX(GTK_DIALOG(sDelInstDlg)->vbox), label,
 
963
                  FALSE, FALSE, 0);
 
964
          }
 
965
          gtk_widget_show_all(sDelInstDlg);
 
966
          sDelInstUp = TRUE;
 
967
      
 
968
          err = E_OLD_INST;
 
969
          break;
 
970
      }
 
971
      currLC = currLC->GetNext();    
 
972
    }
 
973
 
 
974
    return err;
 
975
}
 
976
 
 
977
void         
 
978
nsSetupTypeDlg::DeleteInstDelete(GtkWidget *aWidget, gpointer aData)
 
979
{
 
980
    DUMP("DeleteInstDelete");
 
981
 
 
982
    char cwd[MAXPATHLEN];
 
983
 
 
984
    sDelInstUp = FALSE;
 
985
 
 
986
    getcwd(cwd, MAXPATHLEN);
 
987
    chdir(gCtx->opt->mDestination);
 
988
    system("rm -rf *");
 
989
    chdir(cwd);
 
990
 
 
991
    // hide this notebook page
 
992
    gCtx->sdlg->Hide(nsXInstallerDlg::FORWARD_MOVE);
 
993
 
 
994
    // disconnect this dlg's nav btn signal handlers
 
995
    gtk_signal_disconnect(GTK_OBJECT(gCtx->back), gCtx->backID);
 
996
    gtk_signal_disconnect(GTK_OBJECT(gCtx->next), gCtx->nextID);
 
997
    gtk_signal_disconnect(GTK_OBJECT(sBrowseBtn), sBrowseBtnID);
 
998
 
 
999
    // show the final dlg
 
1000
    if (gCtx->opt->mSetupType == (gCtx->sdlg->GetNumSetupTypes() - 1))
 
1001
        gCtx->cdlg->Show(nsXInstallerDlg::FORWARD_MOVE);
 
1002
    else
 
1003
        gCtx->idlg->Show(nsXInstallerDlg::FORWARD_MOVE);
 
1004
 
 
1005
    gtk_widget_destroy(sDelInstDlg);
 
1006
}
 
1007
 
 
1008
void         
 
1009
nsSetupTypeDlg::DeleteInstCancel(GtkWidget *aWidget, gpointer aData)
 
1010
{
 
1011
    DUMP("DeleteInstCancel");
 
1012
 
 
1013
    sDelInstUp = FALSE;
 
1014
    gtk_widget_destroy(sDelInstDlg);
 
1015
}
 
1016
 
 
1017
int
 
1018
nsSetupTypeDlg::ConstructPath(char *aDest, char *aTrunk, char *aLeaf)
 
1019
{
 
1020
    int err = OK;
 
1021
    int trunkLen;
 
1022
    char *lastSlash = NULL;
 
1023
    
 
1024
    if (!aDest || !aTrunk || !aLeaf)
 
1025
        return E_PARAM;
 
1026
 
 
1027
    trunkLen = strlen(aTrunk);
 
1028
    lastSlash = strrchr(aTrunk, '/');
 
1029
    
 
1030
    strcpy(aDest, aTrunk);
 
1031
    if (lastSlash != aTrunk + (trunkLen - 1))
 
1032
    {
 
1033
        // need to tack on a slash
 
1034
        strcat(aDest, "/");
 
1035
    }
 
1036
    strcat(aDest, aLeaf);
 
1037
 
 
1038
    return err;
 
1039
}
 
1040
 
 
1041
int
 
1042
nsSetupTypeDlg::CheckDestEmpty()
 
1043
{
 
1044
    DUMP("DeleteOldInst");
 
1045
 
 
1046
    DIR *destDirD;
 
1047
    struct dirent *de;
 
1048
    nsObjectIgnore *currOI = NULL;
 
1049
 
 
1050
    /* check if the destination directory is empty */
 
1051
    destDirD = opendir(gCtx->opt->mDestination);
 
1052
    while (de = readdir(destDirD))
 
1053
    {
 
1054
        if (strcmp(de->d_name, ".") && strcmp(de->d_name, ".."))
 
1055
        {
 
1056
            currOI = sObjectsToIgnore;
 
1057
            while (currOI)
 
1058
            {
 
1059
                // check if this is an Object To Ignore
 
1060
                if (!strcmp(currOI->GetFilename(),de->d_name))
 
1061
                    break;
 
1062
 
 
1063
                currOI = currOI->GetNext();    
 
1064
            }
 
1065
            if (!currOI)
 
1066
            {
 
1067
                closedir(destDirD);
 
1068
                ErrorHandler(E_DIR_NOT_EMPTY);
 
1069
                return E_DIR_NOT_EMPTY;
 
1070
            }
 
1071
        }
 
1072
    }
 
1073
    
 
1074
    closedir(destDirD);
 
1075
    return OK;
 
1076
}
 
1077
 
 
1078
int
 
1079
nsSetupTypeDlg::VerifyDiskSpace(void)
 
1080
{
 
1081
    int err = OK;
 
1082
    int dsAvail, dsReqd;
 
1083
    char dsAvailStr[128], dsReqdStr[128];
 
1084
    char message[512];
 
1085
    GtkWidget *noDSDlg, *label, *okButton, *packer;
 
1086
 
 
1087
    // find disk space available at destination
 
1088
    dsAvail = DSAvailable();
 
1089
    if (dsAvail < 0)
 
1090
        return OK; // optimistic when statfs failed
 
1091
                   // or we don't have statfs
 
1092
 
 
1093
    // get disk space required
 
1094
    dsReqd = DSRequired();
 
1095
 
 
1096
    if (dsReqd > dsAvail)
 
1097
    {
 
1098
        // throw up not enough ds dlg
 
1099
        sprintf(dsAvailStr, gCtx->Res("DS_AVAIL"), dsAvail);
 
1100
        sprintf(dsReqdStr, gCtx->Res("DS_REQD"), dsReqd);
 
1101
        sprintf(message, "%s\n%s\n\n%s", dsAvailStr, dsReqdStr, 
 
1102
                gCtx->Res("NO_DISK_SPACE"));
 
1103
 
 
1104
        noDSDlg = gtk_dialog_new();
 
1105
        label = gtk_label_new(message);
 
1106
        okButton = gtk_button_new_with_label(gCtx->Res("OK_LABEL"));
 
1107
        packer = gtk_packer_new(); 
 
1108
 
 
1109
        if (noDSDlg && label && okButton && packer)
 
1110
        {
 
1111
            gtk_window_set_title(GTK_WINDOW(noDSDlg), gCtx->opt->mTitle);
 
1112
            gtk_window_set_position(GTK_WINDOW(noDSDlg), 
 
1113
                                    GTK_WIN_POS_CENTER);
 
1114
            gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
 
1115
            gtk_packer_set_default_border_width(GTK_PACKER(packer), 20);
 
1116
            gtk_packer_add_defaults(GTK_PACKER(packer), label, GTK_SIDE_BOTTOM,
 
1117
                                    GTK_ANCHOR_CENTER, GTK_FILL_X);
 
1118
            gtk_box_pack_start(GTK_BOX(
 
1119
                GTK_DIALOG(noDSDlg)->action_area), okButton,
 
1120
                FALSE, FALSE, 10);
 
1121
            gtk_signal_connect(GTK_OBJECT(okButton), "clicked", 
 
1122
                GTK_SIGNAL_FUNC(NoDiskSpaceOK), noDSDlg);
 
1123
            gtk_box_pack_start(GTK_BOX(
 
1124
                GTK_DIALOG(noDSDlg)->vbox), packer, FALSE, FALSE, 10);
 
1125
 
 
1126
            gtk_widget_show_all(noDSDlg);
 
1127
        }
 
1128
 
 
1129
        err = E_NO_DISK_SPACE;
 
1130
    }
 
1131
 
 
1132
    return err;
 
1133
}
 
1134
 
 
1135
int
 
1136
nsSetupTypeDlg::DSAvailable(void)
 
1137
{
 
1138
    // returns disk space available in kilobytes
 
1139
 
 
1140
    int dsAvail = -1;
 
1141
 
 
1142
#if defined(HAVE_SYS_STATVFS_H) || defined(HAVE_SYS_STATFS_H)
 
1143
    struct STATFS buf;
 
1144
    int rv;
 
1145
 
 
1146
    if (gCtx->opt->mDestination)
 
1147
    {
 
1148
        rv = STATFS(gCtx->opt->mDestination, &buf);
 
1149
        if (rv == 0)
 
1150
        {
 
1151
            if (buf.f_bsize > 1024 && (buf.f_bsize%1024 == 0))
 
1152
            {
 
1153
                // normally the block size is >= 1024 and a multiple
 
1154
                // so we can shave off the last three digits before 
 
1155
                // finding the product of the block size and num blocks
 
1156
                // which is important for large disks
 
1157
 
 
1158
                dsAvail = (buf.f_bsize/1024) * (buf.f_bavail);
 
1159
            }
 
1160
            else
 
1161
            {
 
1162
                // attempt to stuff into a 32 bit int even though
 
1163
                // we convert from bytes -> kilobytes later
 
1164
                // (may fail to compute on very large disks whose
 
1165
                // block size is not a multiple of 1024 -- highly 
 
1166
                // improbable)
 
1167
 
 
1168
                dsAvail = (buf.f_bsize * buf.f_bavail)/1024;
 
1169
            }
 
1170
        }
 
1171
    }
 
1172
#endif // HAVE_SYS_STATVFS_H -or- HAVE_SYS_STATFS_H 
 
1173
 
 
1174
    return dsAvail;
 
1175
}
 
1176
 
 
1177
int 
 
1178
nsSetupTypeDlg::DSRequired(void)
 
1179
{
 
1180
    // returns disk space required in kilobytes 
 
1181
 
 
1182
    int dsReqd = 0;
 
1183
    nsComponentList *comps;
 
1184
    int bCus;
 
1185
 
 
1186
    // find setup type's component list
 
1187
    bCus = (gCtx->opt->mSetupType == (gCtx->sdlg->GetNumSetupTypes() - 1));
 
1188
    comps = gCtx->sdlg->GetSelectedSetupType()->GetComponents();
 
1189
 
 
1190
    // loop through all components
 
1191
    nsComponent *currComp = comps->GetHead();
 
1192
    while (currComp)
 
1193
    {
 
1194
        if ( (bCus == TRUE && currComp->IsSelected()) || (bCus == FALSE) )
 
1195
        {
 
1196
            // add to disk space required 
 
1197
            dsReqd += currComp->GetInstallSize();
 
1198
            dsReqd += currComp->GetArchiveSize();
 
1199
        }
 
1200
 
 
1201
        currComp = currComp->GetNext();
 
1202
    }
 
1203
 
 
1204
    return dsReqd;
 
1205
}
 
1206
 
 
1207
void
 
1208
nsSetupTypeDlg::NoDiskSpaceOK(GtkWidget *aWidget, gpointer aData)
 
1209
{
 
1210
    GtkWidget *noDSDlg = (GtkWidget *) aData;
 
1211
 
 
1212
    if (!noDSDlg)
 
1213
        return;
 
1214
 
 
1215
    gtk_widget_destroy(noDSDlg);
 
1216
}
 
1217