Back to index

lightning-sunbird  0.9+nobinonly
mac_xpidl_panel.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is mozilla.org code.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1998
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 /*
00038        mac_xpidl_panel.cpp
00039  */
00040 
00041 #define CW_STRICT_DIALOGS 1
00042 
00043 /* standard headers */
00044 #include <stdarg.h>
00045 #include <stdio.h>
00046 #include <string.h>
00047 
00048 /* system headers */
00049 #include <AERegistry.h>
00050 #include <Drag.h>
00051 #include <Palettes.h>
00052 #include <Resources.h>
00053 #include <Scrap.h>
00054 #include <TextUtils.h>
00055 #include <Sound.h>
00056 
00057 /* compiler headers */
00058 #include <DropInPanel.h>
00059 
00060 /* project headers */
00061 #include "mac_xpidl_panel.h"
00062 
00063 enum {
00064        kFactoryPrefsID = 128,
00065        kCW7ItemListID = 128,
00066        kCW8ItemListID = 129,
00067 
00068        kXPIDLModeItem = 1,
00069        kXPIDLWarningsItem,
00070        kXPIDLVerboseItem,
00071 
00072        kXPTLinkerOutputItem = 4
00073 };
00074 
00075 
00076 /* local variables */
00077 static RgnHandle     sDragRgn;
00078 static Boolean              sHighlightOn;
00079 
00080 
00081 /* prototypes of local functions */
00082 static short  InitDialog(PanelParameterBlock *pb);
00083 static void          TermDialog(PanelParameterBlock *pb);
00084 static void          PutData(PanelParameterBlock *pb, Handle options);
00085 static short  GetData(PanelParameterBlock *pb, Handle options, Boolean noisy);
00086 static void          ByteSwapData(XPIDLSettingsHandle options);
00087 static short  Filter(PanelParameterBlock *pb, EventRecord *event, short *itemHit);
00088 static void          ItemHit(PanelParameterBlock *pb);
00089 static void          Validate(Handle original, Handle current, Boolean *recompile, Boolean *relink, Boolean *reset);
00090 static short  GetPref(AEKeyword keyword, AEDesc *prefsDesc, Handle settings);
00091 static short  SetPref(AEKeyword keyword, const AEDesc *prefsDesc, Handle settings);
00092 static short  GetFactory(Handle settings);
00093 static short  UpdatePref(Handle settings);
00094 static Boolean       ComparePrefs(Handle prefsHand1, Handle prefsHand2);
00095 static Boolean       ComparePrefs(XPIDLSettings& prefs1, XPIDLSettings& prefs2);
00096 static void          OutlineRect(const Rect* focusRect, Boolean outlineOn);
00097 static OSErr  DragEnter(PanelParameterBlock *pb);
00098 static void          DragWithin(PanelParameterBlock *pb);
00099 static void          DragExit(PanelParameterBlock *pb);
00100 static void          DragDrop(PanelParameterBlock *pb);
00101 
00102 extern "C" {
00103 
00104 pascal short  xpidl_panel(PanelParameterBlock *pb);
00105 
00106 }
00107 
00108 /*
00109  *     main   -      entry-point for Drop-In Preferences Panel
00110  *
00111  */
00112  
00113 pascal short xpidl_panel(PanelParameterBlock *pb)
00114 {
00115        short  result;
00116               
00117        result = noErr;
00118                      
00119        switch (pb->request)
00120        {
00121        case reqInitPanel:
00122               /* panel has just been loaded into memory */
00123               break;
00124 
00125        case reqTermPanel:
00126               /* panel is about to be unloaded from memory */
00127               break;
00128 
00129        case reqFirstLoad:
00130               /* first time panel was loaded. */
00131               break;
00132 
00133        case reqInitDialog:
00134               /* hook our dialog item list into the preferences dialog */
00135               result = InitDialog(pb);
00136               break;
00137        
00138        case reqTermDialog:
00139               /* unhook our dialog item list from the preferences dialog */
00140               TermDialog(pb);
00141               break;
00142        
00143        case reqPutData:
00144               /* put the data in the given handle into our dialog items */
00145               PutData(pb, pb->currentPrefs);
00146               break;
00147 
00148        case reqGetData:
00149               /* fill in the given handle with our dialog items */
00150               result = GetData(pb, pb->currentPrefs, true);
00151               break;
00152 
00153        case reqByteSwapData:
00154               /* byte swap the data in the handle */
00155               ByteSwapData((XPIDLSettingsHandle)pb->currentPrefs);
00156               break;
00157               
00158        case reqFilter:
00159               /* filter an event in the dialog */
00160               result = Filter(pb, pb->event, &pb->itemHit);
00161               break;
00162               
00163        case reqItemHit:
00164               /* handle a hit on one of our dialog items */
00165               ItemHit(pb);
00166               break;
00167               
00168        case reqDrawCustomItem:
00169               /* handle a request to draw one of our user items (CW/8 and later) */
00170               break;
00171               
00172        case reqActivateItem:
00173               break;
00174               
00175        case reqDeactivateItem:
00176               break;
00177               
00178        case reqHandleKey:
00179               break;
00180               
00181        case reqHandleClick:
00182               break;
00183               
00184        case reqFindStatus:
00185               break;
00186               
00187        case reqObeyCommand:
00188               break;
00189               
00190        case reqAEGetPref:
00191               /* return one item in the given handle as an Apple Event descriptor */
00192               result = GetPref(pb->prefsKeyword, &pb->prefsDesc, pb->currentPrefs);
00193               break;
00194 
00195        case reqAESetPref:
00196               /* change one item in the given handle according to the given Apple Event descriptor */
00197               result = SetPref(pb->prefsKeyword, &pb->prefsDesc, pb->currentPrefs);
00198               break;
00199 
00200        case reqValidate:
00201               /* determine if we need to reset paths, recompile, or relink */
00202               Validate(pb->originalPrefs, pb->currentPrefs, &pb->recompile, &pb->relink, &pb->reset);
00203               break;
00204 
00205        case reqGetFactory:
00206               /* return our factory settings */
00207               result = GetFactory(pb->factoryPrefs);
00208               break;
00209 
00210        case reqUpdatePref:
00211               /* update the given handle to use the current format for our prefs data */
00212               result = UpdatePref(pb->currentPrefs);
00213               break;
00214               
00215        case reqDragEnter:
00216               /* determine if we can accept the drag and, if so, start tracking */
00217               result = DragEnter(pb);
00218               break;
00219        
00220        case reqDragWithin:
00221               /* continue tracking */
00222               DragWithin(pb);
00223               break;
00224        
00225        case reqDragExit:
00226               /* stop tracking */
00227               DragExit(pb);
00228               break;
00229        
00230        case reqDragDrop:
00231               /* the user has dropped in our panel */
00232               DragDrop(pb);
00233               break;
00234        
00235        default:
00236               result = paramErr;
00237               break;
00238        }
00239               
00240        return (result);
00241 }
00242 
00243 /*
00244  *     InitDialog  - initialize Dialog Box items for this panel
00245  *
00246  */
00247 
00248 static short InitDialog(PanelParameterBlock *pb)
00249 {
00250        OSErr  err;
00251        
00252        // The library function will call the IDE to append the dialog items 
00253        // if possible;  else it will call AppendDITL itself.  This way, you 
00254        // don't have to worry about it.
00255        
00256        err = CWPanlAppendItems(pb, kCW8ItemListID);
00257        if (err != noErr)
00258               return (err);
00259        
00260        sDragRgn = NewRgn();
00261        
00262        return (err);
00263 }
00264 
00265 /*
00266  *     TermDialog    -      destroy Dialog Box items for this panel
00267  *
00268  */
00269 
00270 static void TermDialog(PanelParameterBlock *pb)
00271 {
00272        DisposeRgn(sDragRgn);
00273 }
00274 
00275 inline Boolean hasLinkerOutput(short mode)
00276 {
00277        return (mode == kXPIDLModeHeader || mode == kXPIDLModeTypelib);
00278 }
00279 
00280 /*
00281  *     PutData              -      copy the options data from the handle to the screen
00282  *
00283  */
00284 
00285 static void PutData(PanelParameterBlock *pb, Handle options)
00286 {
00287        // make sure the options are the right size.
00288        UpdatePref(options);
00289        
00290        XPIDLSettings prefsData = **(XPIDLSettingsHandle) options;
00291 
00292        CWPanlSetItemValue(pb, kXPIDLModeItem, prefsData.mode);
00293        CWPanlSetItemValue(pb, kXPIDLWarningsItem, prefsData.warnings);
00294        CWPanlSetItemValue(pb, kXPIDLVerboseItem, prefsData.verbose);
00295 
00296        CWPanlEnableItem(pb, kXPTLinkerOutputItem, hasLinkerOutput(prefsData.mode));
00297        CWPanlSetItemText(pb, kXPTLinkerOutputItem, prefsData.output);
00298 }
00299 
00300 /*
00301  *     GetData              -      copy the options data from screen to the handle
00302  *
00303  */
00304 
00305 static short GetData(PanelParameterBlock *pb, Handle options, Boolean noisy)
00306 {
00307        XPIDLSettings prefsData     = **(XPIDLSettingsHandle) options;
00308        long mode, warnings, verbose;
00309        
00310        CWPanlGetItemValue(pb, kXPIDLModeItem, &mode);
00311        CWPanlGetItemValue(pb, kXPIDLWarningsItem, &warnings);
00312        CWPanlGetItemValue(pb, kXPIDLVerboseItem, &verbose);
00313        
00314        prefsData.mode = (short) mode;
00315        prefsData.warnings = (Boolean) warnings;
00316        prefsData.verbose = (Boolean) verbose;
00317        
00318        CWPanlGetItemText(pb, kXPTLinkerOutputItem, prefsData.output, sizeof(Str32));
00319        
00320        ** (XPIDLSettingsHandle) options = prefsData;
00321        
00322        return (noErr);
00323 }
00324 
00325 static void ByteSwapShort(short* x)
00326 {
00327        union {
00328               short  s;
00329               char   c[2];
00330        }      from,to;
00331 
00332        from.s=*x;
00333        to.c[0]=from.c[1];
00334        to.c[1]=from.c[0];
00335        *x = to.s;
00336 }
00337 
00338 /*
00339  *     ByteSwapData         -      byte-swap the options data
00340  *
00341  */
00342 
00343 static void ByteSwapData(XPIDLSettingsHandle options)
00344 {
00345        ByteSwapShort(&(**options).version);
00346        ByteSwapShort(&(**options).mode);
00347 }
00348 
00349 /*
00350  *     Filter        -      filter an event for the Preferences panel
00351  *
00352  */
00353 static short Filter(PanelParameterBlock *pb, EventRecord *event, short *itemHit)
00354 {
00355 #pragma unused(pb, event, itemHit)
00356        
00357        return (noErr);
00358 }
00359 
00360 /*
00361  *     ItemHit              -      handle an itemHit in a Preferences panel
00362  *
00363  */
00364 
00365 static void ItemHit(PanelParameterBlock *pb)
00366 {
00367        short  theItem       = pb->itemHit - pb->baseItems;
00368        long   oldValue;
00369        
00370        switch (theItem) {
00371        case kXPIDLModeItem:
00372               CWPanlGetItemValue(pb, theItem, &oldValue);
00373               CWPanlEnableItem(pb, kXPTLinkerOutputItem, hasLinkerOutput(oldValue));
00374               break;
00375               
00376        case kXPIDLWarningsItem:
00377        case kXPIDLVerboseItem:
00378               CWPanlGetItemValue(pb, theItem, &oldValue);
00379               break;
00380        }
00381        
00382        GetData(pb, pb->currentPrefs, false);
00383 
00384        pb->canRevert = !ComparePrefs(pb->originalPrefs, pb->currentPrefs);
00385        pb->canFactory       = !ComparePrefs(pb->factoryPrefs,  pb->currentPrefs);
00386 }
00387 
00388 /*
00389  *     Validate      -      check if panel's changes require a recompile or relink
00390  *
00391  */
00392 
00393 static void Validate(Handle original, Handle current, Boolean *recompile, Boolean *relink, Boolean *reset)
00394 {
00395 #pragma unused(original, current)
00396        XPIDLSettings& origSettings = **(XPIDLSettingsHandle) original;
00397        XPIDLSettings& currentSettings = **(XPIDLSettingsHandle) current;
00398        
00399        *recompile    = currentSettings.mode != origSettings.mode;
00400        *relink              = *recompile && hasLinkerOutput(currentSettings.mode);
00401        *reset        = false;
00402 }
00403 
00404 /*
00405  *     GetPref              -      get a specified Preference setting for an AppleEvent request
00406  *
00407  */
00408 static short GetPref(AEKeyword keyword, AEDesc *prefsDesc, Handle settings)
00409 {
00410 #if 0  
00411        XPIDLSettings prefsData     = ** (XPIDLSettingsHandle) settings;
00412        DescType      anEnum;
00413        OSErr         err;
00414 
00415        switch (keyword)  {
00416        case prefsLN_GenerateSymFile:
00417               err = AECreateDesc(typeBoolean, &prefsData.linksym, sizeof(Boolean), prefsDesc);
00418               break;
00419               
00420        case prefsPR_ProjectType:
00421               switch (prefsData.projtype)
00422               {
00423               case kProjTypeApplication:  anEnum = enum_Project_Application;        break;
00424               case kProjTypeLibrary:             anEnum = enum_Project_Library;                   break;
00425               case kProjTypeSharedLib:    anEnum = enum_Project_SharedLibrary;      break;
00426               case kProjTypeCodeResource: anEnum = enum_Project_CodeResource;              break;
00427               case kProjTypeMPWTool:             anEnum = enum_Project_MPWTool;                   break;
00428               default:                                  return (paramErr);
00429               }
00430               err = AECreateDesc(typeEnumeration, &anEnum, sizeof(anEnum), prefsDesc);
00431               break;
00432               
00433        case prefsPR_FileName:
00434               err = AECreateDesc(typeChar, prefsData.outfile+1, StrLength(prefsData.outfile), prefsDesc);
00435               break;
00436 
00437        default:
00438               err = errAECantHandleClass;
00439               break;
00440        }
00441        
00442        return (err);
00443 #else
00444        return (errAECantHandleClass);
00445 #endif
00446 }
00447 
00448 /*
00449  *     SetPref              -      set a specified Preference setting from an AppleEvent request
00450  *
00451  */
00452 
00453 static short SetPref(AEKeyword keyword, const AEDesc *prefsDesc, Handle settings)
00454 {
00455 #if 0
00456        XPIDLSettings prefsData     = ** (XPIDLSettingsHandle) settings;
00457        AEDesc               toDesc = { typeNull, NULL };
00458        OSErr                err           = noErr;
00459        Handle               dataHand;
00460        Size                 textLength;
00461        DescType             anEnum;
00462        
00463        switch (keyword)
00464        {
00465        case prefsLN_GenerateSymFile:
00466               if (prefsDesc->descriptorType == typeBoolean)
00467               {
00468                      dataHand = prefsDesc->dataHandle;
00469               }
00470               else
00471               {
00472                      err = AECoerceDesc(prefsDesc, typeBoolean, &toDesc);
00473                      if (err == noErr)
00474                             dataHand = toDesc.dataHandle;
00475               }
00476               if (err == noErr)
00477               {
00478                      prefsData.linksym = ** (Boolean **) dataHand;
00479               }
00480               break;
00481               
00482        case prefsPR_ProjectType:
00483               if (prefsDesc->descriptorType != typeEnumeration)
00484               {
00485                      err = errAETypeError;
00486                      break;
00487               }
00488 
00489               anEnum = ** (DescType **) prefsDesc->dataHandle;
00490               
00491               switch (anEnum)
00492               {
00493               case enum_Project_Application:            prefsData.projtype = kProjTypeApplication;       break;
00494               case enum_Project_Library:                prefsData.projtype = kProjTypeLibrary;           break;
00495               case enum_Project_SharedLibrary:   prefsData.projtype = kProjTypeSharedLib;  break;
00496               case enum_Project_CodeResource:           prefsData.projtype = kProjTypeCodeResource;      break;
00497               case enum_Project_MPWTool:                prefsData.projtype = kProjTypeMPWTool;           break;
00498               default:                                                return (errAECoercionFail);
00499               }
00500               break;
00501               
00502        case prefsPR_FileName:
00503               if (prefsDesc->descriptorType == typeChar)
00504               {
00505                      dataHand = prefsDesc->dataHandle;
00506               }
00507               else
00508               {
00509                      err = AECoerceDesc(prefsDesc, typeChar, &toDesc);
00510                      if (err == noErr)
00511                             dataHand = toDesc.dataHandle;
00512               }
00513               if (err == noErr)
00514               {
00515                      textLength = GetHandleSize(dataHand);
00516                      if (textLength > sizeof(prefsData.outfile) - 1)
00517                             textLength = sizeof(prefsData.outfile) - 1;
00518                      BlockMoveData(*dataHand, prefsData.outfile+1, textLength);
00519                      prefsData.outfile[0] = textLength;
00520               }
00521               break;
00522 
00523        default:
00524               err = errAECantHandleClass;
00525               break;
00526        }
00527        
00528        if (err == noErr)
00529        {
00530               ** (XPIDLSettingsHandle) settings = prefsData;
00531        }
00532        
00533        AEDisposeDesc(&toDesc);
00534        
00535        return (err);
00536 #else
00537        return (errAECantHandleClass);
00538 #endif
00539 }
00540 
00541 /*
00542  *     GetFactory    -      retrieve factory settings
00543  *
00544  */
00545 
00546 static short GetFactory(Handle settings)
00547 {
00548        Handle factory;
00549        Size   size;
00550        OSErr  err;
00551        
00552        factory = Get1Resource('pref', kFactoryPrefsID);
00553        if (factory == NULL) {
00554               err = ResError();
00555               if (err == noErr)
00556                      err = resNotFound;
00557               return (err);
00558        }
00559        
00560        size = GetHandleSize(factory);
00561        SetHandleSize(settings, size);
00562        err = MemError();
00563        
00564        if (err == noErr) {
00565               BlockMoveData(*factory, *settings, size);
00566        }
00567        
00568        return (err);
00569 }
00570 
00571 /*
00572  *     UpdatePref    -      "upgrade" a pref to the current version
00573  */
00574 static short UpdatePref(Handle settings)
00575 {
00576        if (GetHandleSize(settings) != sizeof(XPIDLSettings))
00577               GetFactory(settings);
00578 
00579        return (noErr);
00580 }
00581 
00582 /*
00583  *     ComparePrefs
00584  *
00585  */
00586 static Boolean ComparePrefs(Handle prefsHand1, Handle prefsHand2)
00587 {
00588        XPIDLSettings& prefs1       = **(XPIDLSettingsHandle) prefsHand1;
00589        XPIDLSettings& prefs2       = **(XPIDLSettingsHandle) prefsHand2;
00590        
00591        return ((prefs1.mode  == prefs2.mode) && 
00592                      (prefs1.warnings == prefs2.warnings) && 
00593                      (prefs1.verbose == prefs2.verbose) &&
00594                      (EqualString(prefs1.output, prefs2.output, true, true)));
00595 }
00596 
00597 static Boolean ComparePrefs(XPIDLSettings& prefs1, XPIDLSettings& prefs2)
00598 {
00599        return ((prefs1.mode  == prefs2.mode) && 
00600                      (prefs1.warnings == prefs2.warnings) && 
00601                      (prefs1.verbose == prefs2.verbose) &&
00602                      (EqualString(prefs1.output, prefs2.output, true, true)));
00603 }
00604 
00605 /*
00606  *     OutlineRect
00607  *
00608  */
00609 static void   OutlineRect(const Rect* focusRect, Boolean outlineOn)
00610 {
00611        ColorSpec     savedForeColor, backColor;
00612        PenState      savedPen;
00613        
00614        GetPenState(&savedPen);
00615        PenNormal();
00616        
00617        if (!outlineOn)
00618        {
00619               SaveFore(&savedForeColor);
00620               SaveBack(&backColor);
00621               RestoreFore(&backColor);
00622        }
00623        
00624        PenSize(2, 2);
00625        FrameRect(focusRect);
00626        
00627        SetPenState(&savedPen);
00628        
00629        if (!outlineOn)
00630        {
00631               RestoreFore(&savedForeColor);
00632        }
00633 }
00634 
00635 /*
00636  *     DragEnter
00637  *
00638  */
00639 static OSErr  DragEnter(PanelParameterBlock *pb)
00640 {
00641 #if 0
00642        short                theItem       = pb->itemHit - pb->baseItems;
00643        unsigned short       itemCount;
00644        Rect                 itemRect;
00645        OSErr                err;
00646 #endif
00647        
00648        /* Return paramErr if the user is on a item that can't be dropped on */
00649        return (paramErr);
00650 }
00651 
00652 /*
00653  *     DragWithin
00654  *
00655  */
00656 static void   DragWithin(PanelParameterBlock *pb)
00657 {
00658 #pragma unused(pb)
00659 
00660        /* there's nothing to do */
00661        
00663 }
00664 
00665 /*
00666  *     DragExit
00667  *
00668  */
00669 static void   DragExit(PanelParameterBlock *pb)
00670 {
00671        OSErr  err;
00672        
00674        
00675        if (sHighlightOn) {
00676               err = HideDragHilite(pb->dragref);
00677               if (err == noErr)
00678                      sHighlightOn = false;
00679        }
00680 }
00681 
00682 /*
00683  *     DragDrop
00684  *
00685  */
00686 static void   DragDrop(PanelParameterBlock *pb)
00687 {
00688 #if 0
00689        Rect   itemRect;
00690 #endif
00691        
00693        
00694        DragExit(pb);
00695 }