Back to index

lightning-sunbird  0.9+nobinonly
MacInstallWizard.c
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code, released
00016  * March 31, 1998.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1999
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Samir Gehani <sgehani@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "MacInstallWizard.h"
00041 
00042 
00043 /*-----------------------------------------------------------*
00044  *   globals
00045  *-----------------------------------------------------------*/
00046 
00047 Boolean       gDone = false;
00048 WindowPtr     gWPtr = NULL;
00049 short         gCurrWin = 0;
00050 InstWiz              *gControls = NULL;
00051 InstINIRes  *gStrings = NULL;
00052 Boolean     gInstallStarted = false;
00053 ErrTableEnt *gErrTable = NULL;
00054 short gErrTableSize = 0;
00055 
00056 
00057 
00058 /*-----------------------------------------------------------*
00059  *   Application Setup
00060  *-----------------------------------------------------------*/
00061 
00062 int gState;
00063 
00064 void main(void)
00065 {      
00066        OSErr err = noErr;
00067        
00068        Init();
00069        if (VerifyEnv() && !gDone)  
00070        {
00071               err = NavLoad();
00072               if (err!=noErr)
00073                      SysBeep(10);  // XXX better error handling
00074                      
00075               ShowWindow(gWPtr);
00076               MainEventLoop();
00077        }
00078 }
00079 
00080 Boolean
00081 VerifyEnv(void)
00082 {
00083        long   response;
00084        OSErr  err = noErr;
00085        Boolean bEnvOK = true;
00086        
00087        // gestalt to check we are running 8.5 or later
00088        err = Gestalt('sysv', &response);
00089        if (err != noErr)
00090        {
00091               // errors already!  we are bailing
00092         ErrorHandler(err, nil);
00093               bEnvOK = false;
00094        }
00095        
00096        if (response < 0x00000850)
00097        {
00098               // we are bailing
00099               StopAlert(160, nil);
00100               bEnvOK = false;
00101        }
00102        
00103        // it's all good
00104        return bEnvOK;
00105 }
00106 
00107 void Init(void)
00108 {
00109        Str255               winTitle;
00110        OSErr                err = noErr;
00111     Str255                  instMode;
00112     Ptr                            pinstMode;
00113        
00114        gDone = false;
00115        InitManagers();
00116        InitControlsObject();       
00117        CleanTemp();
00118 
00119        ParseInstall();
00120 
00121        gWPtr = GetNewCWindow(rRootWin, NULL, (WindowPtr) -1);  
00122     GetIndString( instMode, rTitleStrList, sNSInstTitle);
00123     pinstMode = PascalToC(instMode);
00124 #if MOZILLA == 0
00125     GetResourcedString(winTitle, rInstList, sNsTitle);
00126 #else
00127     GetResourcedString(winTitle, rInstList, sMoTitle);
00128 #endif
00129        SetWTitle( gWPtr, winTitle );      
00130        SetWRefCon(gWPtr, kMIWMagic);
00131        MakeMenus();
00132 
00133        ParseConfig(); 
00134        InitOptObject();
00135        
00136        ShowWelcomeWin();    
00137        SetThemeWindowBackground(gWPtr, kThemeBrushDialogBackgroundActive, true); 
00138        
00139        /* Set menu */
00140        InitNewMenu();
00141 }
00142 
00143 OSErr
00144 GetCWD(long *outDirID, short *outVRefNum)
00145 {
00146        OSErr                       err = noErr;
00147        ProcessSerialNumber  psn;
00148        ProcessInfoRec              pInfo;
00149        FSSpec                      tmp;
00150        
00151        /* get cwd based on curr ps info */
00152        if (!(err = GetCurrentProcess(&psn))) 
00153        {
00154               pInfo.processName = nil;
00155               pInfo.processAppSpec = &tmp;
00156               pInfo.processInfoLength = (sizeof(ProcessInfoRec));
00157               
00158               if(!(err = GetProcessInformation(&psn, &pInfo)))
00159               {
00160                      *outDirID = pInfo.processAppSpec->parID;
00161                      *outVRefNum = pInfo.processAppSpec->vRefNum;
00162               }
00163        }
00164        
00165        return err;
00166 }
00167 
00168 void
00169 InitOptObject(void)
00170 {
00171        FSSpec        tmp;
00172        OSErr  err=noErr;
00173        Boolean isDir;
00174        
00175        gControls->opt = (Options*)NewPtrClear(sizeof(Options));
00176 
00177        if (!gControls->opt)
00178        {
00179         ErrorHandler(eMem, nil);
00180               return;
00181        }
00182        
00183        /* SetupTypeWin options */
00184        gControls->opt->instChoice = 1;           
00185        gControls->opt->folder = (unsigned char *)NewPtrClear(64*sizeof(unsigned char));
00186        if (!gControls->opt->folder)
00187        {
00188         ErrorHandler(eMem, nil);
00189               return;
00190        }
00191        
00192        /* TerminalWIn options */
00193        gControls->opt->siteChoice = 1;
00194        gControls->opt->saveBits = false;
00195        
00196        gControls->opt->vRefNum = -1;
00197        err = FSMakeFSSpec(gControls->opt->vRefNum, 0, "\p", &tmp);
00198        pstrcpy( gControls->opt->folder, tmp.name );
00199        err = FSpGetDirectoryID( &tmp, &gControls->opt->dirID, &isDir );
00200 
00201 }
00202 
00203 void
00204 InitControlsObject(void)
00205 {      
00206        gControls            = (InstWiz *)               NewPtrClear(sizeof(InstWiz));
00207        if (!gControls)
00208        {
00209         ErrorHandler(eMem, nil);
00210               return;
00211        }
00212        
00213        gControls->lw        = (LicWin *)         NewPtrClear(sizeof(LicWin));
00214        gControls->ww        = (WelcWin *)               NewPtrClear(sizeof(WelcWin));
00215        gControls->stw       = (SetupTypeWin *)   NewPtrClear(sizeof(SetupTypeWin)); 
00216        gControls->cw        = (CompWin *)               NewPtrClear(sizeof(CompWin));
00217        gControls->aw        = (CompWin *)               NewPtrClear(sizeof(CompWin));
00218        gControls->tw        = (TermWin*)         NewPtrClear(sizeof(TermWin));
00219 
00220        if (!gControls->lw || !gControls->ww || !gControls->stw || 
00221               !gControls->cw || !gControls->tw)
00222        {
00223         ErrorHandler(eMem, nil);
00224        }
00225        
00226        gControls->state = eInstallNotStarted;
00227        
00228        return;
00229 }
00230 
00231 void InitManagers(void)
00232 {
00233        MaxApplZone();       
00234        MoreMasters(); MoreMasters(); MoreMasters();
00235        
00236        InitGraf(&qd.thePort);  
00237        InitFonts();                
00238        InitWindows();
00239        InitMenus();
00240        TEInit();                          
00241        InitDialogs(NULL);
00242        
00243        InitCursor();        
00244        FlushEvents(everyEvent, 0); 
00245 }
00246 
00247 void CleanTemp(void)
00248 {
00249     OSErr   err = noErr;
00250     short   vRefNum;
00251     long    dirID;
00252     FSSpec  viewerFSp;
00253     XPISpec *xpiList, *currXPI = 0, *nextXPI = 0;
00254 #ifdef MIW_DEBUG
00255     Boolean isDir = false;
00256 #endif
00257     
00258 #ifndef MIW_DEBUG
00259     /* get "viewer" in "Temporary Items" folder */
00260     ERR_CHECK(FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder, &vRefNum, &dirID));
00261     err = FSMakeFSSpec(vRefNum, dirID, kViewerFolder, &viewerFSp);
00262 #else
00263     /* for DEBUG builds temp is "<currProcessVolume>:Temp NSInstall:" */
00264     ERR_CHECK(GetCWD(&dirID, &vRefNum));
00265        err = FSMakeFSSpec(vRefNum, 0, kTempFolder, &viewerFSp);
00266        if (err == fnfErr)
00267            return; /* no debug temp exists */
00268        err = FSpGetDirectoryID(&viewerFSp, &dirID, &isDir);
00269        if (err != noErr || !isDir)
00270            return;
00271     err = FSMakeFSSpec(vRefNum, dirID, kViewerFolder, &viewerFSp);
00272 #endif
00273     
00274     /* whack the viewer folder if it exists */
00275     if (err == noErr)
00276     {
00277         ERR_CHECK(DeleteDirectory(viewerFSp.vRefNum, viewerFSp.parID, viewerFSp.name));
00278     }
00279     
00280     /* clean out the zippies (.xpi's) */
00281     xpiList = (XPISpec *) NewPtrClear(sizeof(XPISpec));
00282     if (!xpiList)
00283         return;
00284     IterateDirectory(vRefNum, dirID, "\p", 1, CheckIfXPI, (void*)&xpiList);
00285     
00286     if (xpiList)
00287     {
00288         currXPI = xpiList;
00289         while(currXPI)
00290         {
00291             nextXPI = currXPI->next; /* save nextXPI before we blow away currXPI */
00292             if (currXPI->FSp)
00293             {
00294                 FSpDelete(currXPI->FSp);
00295                 DisposePtr((Ptr)currXPI->FSp);
00296             }
00297             DisposePtr((Ptr)currXPI);
00298             currXPI = nextXPI;
00299         }
00300     }
00301 }
00302 
00303 pascal void CheckIfXPI(const CInfoPBRec * const cpbPtr, Boolean *quitFlag, void *dataPtr)
00304 {
00305     OSErr err = noErr;
00306     char cFilename[256];    /* for convenience: copy the name in cpbPtr->hFileInfo */
00307     int len = 0;            /* for convenience: length of name string */
00308     FSSpecPtr currFSp;
00309     XPISpec *currXPI = 0, *newXPI = 0, **xpiList = 0;
00310     
00311     /* param check */
00312     if (!cpbPtr || !dataPtr)
00313         return;    
00314      xpiList = (XPISpec **)dataPtr;
00315      
00316     /* file detected */
00317     if ((cpbPtr->hFileInfo.ioFlAttrib & ioDirMask) == 0)
00318     {
00319         if (!cpbPtr->hFileInfo.ioNamePtr)
00320             return;
00321         len = *(cpbPtr->hFileInfo.ioNamePtr);            
00322         strncpy(cFilename, (char*)(cpbPtr->hFileInfo.ioNamePtr + 1), len);
00323         
00324         /* check suffix for ".xpi" */   
00325         if (0 == strncmp(".xpi", cFilename+len-4, 4))
00326         {
00327             currFSp = (FSSpecPtr) NewPtrClear(sizeof(FSSpec));
00328             if (!currFSp)
00329                 return;
00330             err = FSMakeFSSpec(cpbPtr->hFileInfo.ioVRefNum, cpbPtr->hFileInfo.ioFlParID,
00331                                cpbPtr->hFileInfo.ioNamePtr, currFSp);
00332                                
00333             /* if file exists add it to deletion list */
00334             if (err == noErr)
00335             {
00336                 currXPI = *xpiList;
00337                 while (currXPI)
00338                 { 
00339                     /* list head special case */
00340                     if (!currXPI->FSp)
00341                     {
00342                         newXPI = currXPI;  
00343                         break;
00344                     }
00345                     
00346                     /* more in list */
00347                     if (currXPI->next)
00348                     {
00349                         currXPI = currXPI->next;
00350                         continue;
00351                     }
00352                     /* list end so allocate new node */ 
00353                     else
00354                     {
00355                         newXPI = (XPISpec *) NewPtrClear(sizeof(XPISpec));
00356                         if (!newXPI)
00357                             return;  
00358                         currXPI->next = newXPI;
00359                         break;
00360                     }
00361                 }
00362                 newXPI->FSp = currFSp;
00363             }
00364             else
00365                 DisposePtr((Ptr) currFSp);
00366         }
00367     }
00368     
00369     /* paranoia: make sure we continue iterating */
00370     *quitFlag = false;
00371 }
00372 
00373 void MakeMenus(void)
00374 {
00375     Handle           mbarHdl;
00376        MenuHandle    menuHdl;
00377        OSErr         err;
00378        
00379        if ( !(mbarHdl = GetNewMBar( rMBar)) )
00380        {
00381         ErrorHandler(eMem, nil);
00382               return;
00383        }
00384        
00385        SetMenuBar(mbarHdl);
00386        
00387        if ( (menuHdl = GetMenuHandle(mApple)) != nil) 
00388        {
00389               AppendResMenu(menuHdl, 'DRVR');
00390        }
00391        else
00392         ErrorHandler(eMenuHdl, nil); 
00393 
00394        ERR_CHECK(HMGetHelpMenuHandle(&menuHdl));
00395        DisableItem(menuHdl, 1);
00396 
00397        DrawMenuBar();
00398 }
00399 
00400 static        RgnHandle gMouseRgn;
00401 
00402 void MainEventLoop(void)
00403 {
00404        gMouseRgn = NewRgn();
00405        
00406        while (!gDone) 
00407        {      
00408         YieldToAnyThread();  /* download thread */
00409            MainEventLoopPass();    
00410        }
00411        
00412        if (gMouseRgn)
00413               DisposeRgn(gMouseRgn);
00414        gMouseRgn = (RgnHandle) 0;
00415        Shutdown();
00416 }
00417  
00418 // following needs to return int so it can be used as a libXPnet callback
00419 
00420 int BreathFunc()
00421 {
00422     static int ticks = 0;
00423     
00424     ticks++;
00425     if ( ( ticks % 4 ) == 0 ) {
00426         ticks = 0;
00427         MainEventLoopPass();
00428         if ( gDone == true ) {     // this is likely because user selected Quit from the file menu
00429             if (gMouseRgn)
00430                       DisposeRgn(gMouseRgn);
00431                gMouseRgn = (RgnHandle) 0;
00432                Shutdown();
00433            } 
00434     }
00435     return 1;
00436 }
00437 
00438 void  MainEventLoopPass()
00439 {
00440     EventRecord evt;
00441        Boolean              notHandled = true;
00442 
00443     if (!gDone)       /* after cx switch back ensure not done */
00444     {
00445               if(WaitNextEvent(everyEvent, &evt, 1, gMouseRgn))
00446               {
00447                      if (gMouseRgn)
00448                             SetRectRgn(gMouseRgn, evt.where.h, evt.where.v, evt.where.h + 1, evt.where.v + 1);
00449                                    
00450                      HandleNextEvent(&evt);
00451               }
00452        }
00453 }
00454  
00455 void ErrorHandler(short errCode, Str255 msg)
00456 {
00457 // TO DO
00458 //            * handle a "fatality" parameter for recovery
00459 
00460     Str255      pErrorStr;
00461     Str255      pMessage, errMsg;
00462     char        *cErrNo = 0;
00463     StringPtr   pErrNo = 0;
00464     AlertStdAlertParamRec *alertdlg;
00465 
00466     // only throw up the error dialog once (since we have no fatality param)
00467     static Boolean bErrHandled = false;
00468     if (bErrHandled)
00469         return;
00470     else
00471         bErrHandled = true;
00472         
00473     // if install.ini read failed
00474     if( errCode == eInstRead )
00475     {
00476         GetIndString(pErrorStr, rStringList, errCode);
00477         ParamText(pErrorStr, "\p", "\p", "\p");
00478         StopAlert(rAlrtError, nil);
00479         SysBeep(10);
00480         gDone = true;
00481         return;
00482     }
00483        
00484     GetResourcedString(pMessage, rErrorList, eErr1);
00485     GetResourcedString(pErrorStr, rErrorList, eErr2);
00486     
00487     cErrNo = ltoa(errCode);
00488     pErrNo = CToPascal(cErrNo);
00489     
00490     if (errCode > 0)    // negative errors are definitely from the system so we don't interpret
00491     {
00492         GetResourcedString(pErrorStr, rErrorList, errCode);
00493         pstrcat(pMessage, pErrNo);
00494         pstrcat(pMessage, "\p: ");
00495         pstrcat(pMessage, pErrorStr);
00496     }
00497     else
00498     {
00499         GetResourcedString(pMessage, rErrorList, eErr3);
00500         if ( LookupErrorMsg( errCode, errMsg ) == true )
00501           pstrcat(pMessage, errMsg);
00502         else 
00503           pstrcat(pMessage, pErrNo);
00504         if ( msg[0] != 0 ) {
00505           pstrcat(pMessage, "\p : ");
00506           pstrcat(pMessage, msg);
00507         }
00508     }  
00509         
00510     alertdlg = (AlertStdAlertParamRec *)NewPtrClear(sizeof(AlertStdAlertParamRec));
00511     alertdlg->defaultButton = kAlertStdAlertOKButton;
00512     alertdlg->defaultText = (ConstStringPtr)NewPtrClear(kKeyMaxLen);
00513     GetResourcedString((unsigned char *)alertdlg->defaultText, rInstList, sOKBtn);
00514     StandardAlert(kAlertStopAlert, pMessage, nil, alertdlg, 0);
00515          SysBeep(10);
00516        
00517     if (cErrNo)
00518         free(cErrNo);
00519     if (pErrNo)
00520         DisposePtr((Ptr) pErrNo); 
00521         
00522        gDone = true;
00523 }
00524 
00525 Boolean
00526 LookupErrorMsg( short code, Str255 msg )
00527 {
00528     int i;
00529     Boolean retval = false;
00530     msg[0] = 1; msg[1] = ' ';
00531     
00532     for ( i = 0; i < gErrTableSize; i++ ) {
00533       if ( gErrTable[i].num == code ) {
00534           pstrcat( msg, gErrTable[i].msg );
00535           retval = true;
00536           break;
00537         }   
00538     }
00539     return( retval );
00540 }
00541 
00542 void Shutdown(void)
00543 {
00544        WindowPtr     frontWin;
00545        long          MIWMagic = 0;
00546 
00547        NavUnload();
00548        
00549 #if 0
00550 
00551 /* deallocate config object */
00552     if (gControls->cfg)
00553     {
00554         /* General */
00555         if (gControls->cfg->targetSubfolder)
00556             DisposePtr((Ptr) gControls->cfg->targetSubfolder);
00557         if (gControls->cfg->globalURL)
00558             DisposePtr((Ptr) gControls->cfg->globalURL);
00559             
00560         /* LicenseWin */
00561         if (gControls->cfg->licFileName)
00562             DisposePtr((Ptr) gControls->cfg->licFileName);        
00563             
00564         /* WelcomeWin */
00565         for (i = 0; i < kNumWelcMsgs; i++)
00566         {
00567             if (gControls->cfg->welcMsg[i])
00568                 DisposePtr((Ptr) gControls->cfg->welcMsg[i]);  
00569         }      
00570         if (gControls->cfg->readmeFile)
00571             DisposePtr((Ptr) gControls->cfg->readmeFile);    
00572         if (gControls->cfg->readmeApp)
00573             DisposePtr((Ptr) gControls->cfg->readmeApp);
00574             
00575         /* ComponentsWin and AdditionsWin */
00576         if (gControls->cfg->selCompMsg)
00577             DisposePtr((Ptr) gControls->cfg->selCompMsg);
00578         if (gControls->cfg->selAddMsg)
00579             DisposePtr((Ptr) gControls->cfg->selAddMsg);
00580 
00581         /* TerminalWin */            
00582         if (gControls->cfg->startMsg)
00583             DisposePtr((Ptr) gControls->cfg->startMsg);
00584         if (gControls->cfg->saveBitsMsg)
00585             DisposePtr((Ptr) gControls->cfg->saveBitsMsg);
00586                         
00587         /* "Tunneled" IDI keys */
00588         if (gControls->cfg->coreFile)
00589             DisposePtr((Ptr) gControls->cfg->coreFile);  
00590         if (gControls->cfg->coreDir)
00591             DisposePtr((Ptr) gControls->cfg->coreDir);  
00592         if (gControls->cfg->noAds)
00593             DisposePtr((Ptr) gControls->cfg->noAds);  
00594         if (gControls->cfg->silent)
00595             DisposePtr((Ptr) gControls->cfg->silent);  
00596         if (gControls->cfg->execution)
00597             DisposePtr((Ptr) gControls->cfg->execution);  
00598         if (gControls->cfg->confirmInstall)
00599             DisposePtr((Ptr) gControls->cfg->confirmInstall);
00600             
00601         DisposePtr((Ptr)gControls->cfg);
00602     }
00603        
00604 /* deallocate options object */
00605        if (gControls->opt && gControls->opt->folder)
00606        {
00607               DisposePtr((Ptr) gControls->opt->folder);
00608               DisposePtr((Ptr) gControls->opt);
00609        }
00610               
00611 /* deallocate all controls */      
00612 
00613        if (gControls->nextB)
00614               DisposeControl(gControls->nextB);  
00615        if (gControls->backB)
00616               DisposeControl(gControls->backB);
00617        
00618        if (gControls->lw)
00619               DisposePtr( (char*) gControls->lw);
00620        if (gControls->ww)
00621               DisposePtr( (char*) gControls->ww);
00622        if (gControls->stw)
00623               DisposePtr( (char*) gControls->stw);
00624        if (gControls->cw)
00625               DisposePtr( (char*) gControls->cw);
00626        if (gControls->tw)
00627               DisposePtr( (char*) gControls->tw);
00628        
00629        if (gControls)
00630               DisposePtr( (char*) gControls);
00631               
00632 #endif /* 0 */
00633                      
00634        frontWin = FrontWindow();
00635        MIWMagic = GetWRefCon(frontWin);
00636        if (MIWMagic != kMIWMagic)
00637               if (gWPtr)
00638                      BringToFront(gWPtr);
00639 
00640        if (gWPtr)
00641        {
00642               HideWindow(gWPtr);
00643               DisposeWindow(gWPtr);
00644        }
00645        ExitToShell();
00646 }
00647 
00648 //set new menu groups and items from install.ini
00649 void InitNewMenu()
00650 {
00651     MenuHandle              instMenu=0;
00652     MenuRef                 fileMenu, editMenu;
00653     Str255                  menuText;
00654 
00655     instMenu = GetMenuHandle(mApple);
00656 #if MOZILLA == 0
00657        GetResourcedString(menuText, rInstMenuList, sMenuAboutNs);
00658 #else
00659        GetResourcedString(menuText, rInstMenuList, sMenuAboutMo);
00660 #endif
00661     SetMenuItemText(instMenu, iAbout, menuText);
00662     
00663     GetResourcedString(menuText, rInstMenuList, sMenuFile);
00664     fileMenu = NewMenu(mFile, menuText);
00665     InsertMenu(fileMenu, mFile);
00666     GetResourcedString(menuText, rInstMenuList, sMenuEdit);
00667     editMenu = NewMenu(mEdit, menuText);
00668     InsertMenu(editMenu, mEdit);
00669     DrawMenuBar();
00670 
00671     GetResourcedString(menuText, rInstMenuList, sMenuQuit);
00672     AppendMenu(fileMenu, menuText);
00673     GetResourcedString(menuText, rInstMenuList, sMenuQuitHot);
00674     SetItemCmd(fileMenu, iQuit, menuText[1]);
00675     
00676     GetResourcedString(menuText, rInstMenuList, sMenuUndo);
00677     AppendMenu(editMenu, menuText);
00678     GetResourcedString(menuText, rInstMenuList, sMenuUndoHot);
00679     SetItemCmd(editMenu, iUndo, menuText[1]);
00680     pstrcpy(menuText, CToPascal("-"));
00681     AppendMenu(editMenu, menuText);
00682     GetResourcedString(menuText, rInstMenuList, sMenuCut);
00683     AppendMenu(editMenu, menuText);
00684     GetResourcedString(menuText, rInstMenuList, sMenuCutHot);
00685     SetItemCmd(editMenu, iCut, menuText[1]);
00686     GetResourcedString(menuText, rInstMenuList, sMenuCopy);
00687     AppendMenu(editMenu, menuText);
00688     GetResourcedString(menuText, rInstMenuList, sMenuCopyHot);
00689     SetItemCmd(editMenu, iCopy, menuText[1]);
00690     GetResourcedString(menuText, rInstMenuList, sMenuPaste);
00691     AppendMenu(editMenu, menuText);
00692     GetResourcedString(menuText, rInstMenuList, sMenuPasteHot);
00693     SetItemCmd(editMenu, iPaste, menuText[1]);
00694     GetResourcedString(menuText, rInstMenuList, sMenuClear);
00695     AppendMenu(editMenu, menuText);
00696     GetResourcedString(menuText, rInstMenuList, sMenuClearHot);
00697     SetItemCmd(editMenu, iClear, menuText[1]);
00698 }