home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 April: Mac OS SDK / Dev.CD Apr 99 SDK1.toast / Development Kits / ColorSync 2.5.1 SDK / Sample Code / CSDemo 2.5 / CSDemoSources / winProfile.c < prev    next >
Encoding:
Text File  |  1998-09-09  |  33.6 KB  |  1,167 lines  |  [TEXT/CWIE]

  1. // A profile window
  2. //
  3. // David Hayward 
  4. // Developer Technical Support
  5. // AppleLink: DEVSUPPORT
  6. //
  7. // Copyrite 1995, Apple Computer,Inc
  8. //
  9. // This file contains the menus routines for a profile window.
  10. // 
  11. // 12/13/94    david    first cut
  12.  
  13.  
  14. #include <QuickDraw.h>
  15. #include <Icons.h>
  16. #include <Fonts.h>
  17. #include <LowMem.h>
  18. #include <Files.h>
  19. #include <TextUtils.h>
  20. #include <QDOffScreen.h>
  21. #include <Resources.h>
  22. #include <StandardFile.h>
  23.  
  24. #include "appGlobals.h"
  25. #include "appMain.h"
  26. #include "appMenus.h"
  27. #include "appErrors.h"
  28. #include "appAEvts.h"
  29.  
  30. #include "win.h"
  31. #include "winTables.h"
  32. #include "winProfile.h"
  33. #include "winProfileGetSet.h"
  34. #include "winProfID.h"
  35. #include "winProfIDGetSet.h"
  36. #include "winProfList.h"
  37. #include "winProfListGetSet.h"
  38.  
  39. #include "stringUtils.h"
  40. #include "colorsyncUtils.h"
  41. #include "resourceUtils.h"
  42.  
  43.  
  44. /**\
  45. |**| ==============================================================================
  46. |**| PRIVATE TYPEDEFS
  47. |**| ==============================================================================
  48. \**/
  49. typedef struct FlagList
  50. {
  51.     short    count ;            // 1-based count of structs to follow 
  52.     struct
  53.     {
  54.         short    shift ;            // bits to shift over
  55.         short    mask ;            // bits to then mask over
  56.         short    value ;            // resulting value
  57.         Str27    string ;
  58.     } entry[];
  59. } FlagList, *FlagListPtr, **FlagListHdl ;
  60.  
  61.  
  62. /**\
  63. |**| ==============================================================================
  64. |**| PRIVATE DEFINES
  65. |**| ==============================================================================
  66. \**/
  67. #define rProfileWindID                1000            // 'WIND' resource id
  68. #define rProfileLabelsStringID        1000            // 'STR ' resource id
  69. #define rProfileVarsStringID        1001            // 'STR ' resource id
  70. #define rProfileWhereVarStringID    1002            // 'STR ' resource id
  71. #define rProfileIconID                1003            // icon family resource id
  72.  
  73.  
  74. /**\
  75. |**| ==============================================================================
  76. |**| PRIVATE FUNCTION PROTOTYPES
  77. |**| ==============================================================================
  78. \**/
  79. void        DoDrawProfData            ( winHandle win ) ;
  80. void        MungeProfileHeader1        ( CMProfileRef prof, Handle text ) ;
  81. void        MungeProfileHeader2        ( CMProfileRef prof, Handle text ) ;
  82. OSErr        RendIntent2String        ( unsigned long intent, StringPtr dest ) ;
  83. OSErr        ColorSpace2String        ( OSType spaceType, StringPtr dest ) ;
  84. OSErr        ProfileClass2String        ( OSType classType, StringPtr dest ) ;
  85. OSErr        DoCreateProfWindow        ( winHandle win ) ;
  86. void        ProfMakeSysProfileCmnd    ( winHandle win ) ;
  87. void        ProfCreateProfIDCmnd    ( winHandle win ) ;
  88. void        SaveCmndProfile            ( winHandle win ) ;
  89. void        SaveAsCmndProfile        ( winHandle win ) ;
  90. void        RevertCmndProfile        ( winHandle win ) ;
  91. long        PopUpMenuSelectFont        ( MenuHandle theMenu, short top, short left,
  92.                                           short popUpItem, short font, short size) ;
  93. OSErr        GetFlagListStringPtr    ( short id, unsigned long flags, StringPtr dest ) ;
  94. OSErr        BuildFlagListMenu        ( short id, unsigned long flags, MenuHandle menu ) ;
  95. OSErr        SetFlagFromMenuItem        ( short id, unsigned long *flags, short mitem ) ;
  96.  
  97.  
  98. /**\
  99. |**| ==============================================================================
  100. |**| PUBLIC FUNCTIONS
  101. |**| ==============================================================================
  102. \**/
  103.  
  104.  
  105. /*------------------------------------------------------------------------------*\
  106.     winUpdateProfile
  107.  *------------------------------------------------------------------------------*
  108.         This is a UpdateProcPtr for Profile windows.  
  109.         It handles all drawing into the window.
  110.         For ProfList windows, this means that this routine is responible for
  111.         drawing the the basic CS1 and CS2 profile info into the window.
  112.         This ProcPtr is envoked by CallWinUpdateProc() which is called by:
  113.             DoUpdateEvent() which dispaches update events.
  114. \*------------------------------------------------------------------------------*/
  115. void    winUpdateProfile ( winHandle win, EventRecord *e )
  116. {
  117.     WindowRef        window = (WindowRef)e->message;
  118.     GrafPtr            savedPort ;
  119.     
  120.     GetPort(&savedPort ) ;    
  121.     SetPort( (GrafPtr)window ) ;
  122.  
  123.     BeginUpdate( window ) ;
  124.  
  125.     DoDrawProfData( win ) ;
  126.     
  127.     // signal that we finished drawing
  128.     EndUpdate( window ) ;
  129.     SetPort( savedPort ) ;
  130. }
  131.  
  132.  
  133. /*------------------------------------------------------------------------------*\
  134.     winClickProfile
  135.  *------------------------------------------------------------------------------*
  136.         This is a ClickProcPtr for Profile windows.
  137.         So far, all this contains is a crude handling of the popup menus
  138.         Other things, such as initiating a drag-and-drop should also go here
  139.         This ProcPtr is envoked by CallWinClickProc() which is called by:
  140.             DoMouseDownEvent() which dispaches mouse down events 
  141. \*------------------------------------------------------------------------------*/
  142. void winClickProfile ( winHandle win, EventRecord *e ) 
  143. {
  144.     CMError                    cmerr ;
  145.     CMProfileRef            prof;
  146.     CMAppleProfileHeader    head ;
  147.     unsigned long            vers ;
  148.     unsigned long            *flagPtr ;
  149.     Point                    where ;
  150.     Rect                    varsRect ;
  151.     
  152.     varsRect = GetRect ( rProfileVarsStringID ) ;
  153.  
  154.     // if in correct region
  155.     where = e->where;
  156.     GlobalToLocal(&where);
  157.     
  158.     if ( (where.h >= varsRect.left) && (where.h <= varsRect.left+8) )
  159.     {
  160.         short        row, resID, mitem;
  161.         long        mresult;
  162.         MenuHandle    menu;
  163.         Point        mOrigin ;
  164.         
  165.         row = (where.v - varsRect.top) /12;
  166.         
  167.         if ( row>=14 && row<=17 )
  168.         {
  169.             prof = GetProfileRef( win );
  170.         
  171.             cmerr = CMGetProfileHeader(prof, &head) ;
  172.             if (cmerr) return ;
  173.         
  174.             vers = head.cm2.profileVersion ;
  175.     
  176.             menu = NewMenu(5000,"\ppopup");
  177.             InsertMenu(menu,-1);
  178.             
  179.             mOrigin.h = varsRect.left;
  180.             mOrigin.v = varsRect.top + 12*row;            
  181.             LocalToGlobal(&mOrigin);
  182.  
  183.             flagPtr = nil;
  184.             
  185.             if (row==15 && vers>=cmCS2ProfileVersion)        // CS2 Atrb1
  186.             {    flagPtr = &(head.cm2.deviceAttributes[1]) ;
  187.                 resID = 1001;
  188.             }                
  189.             if (row==16 && vers>=cmCS2ProfileVersion)        // CS2 Flags
  190.             {    flagPtr = &(head.cm2.flags) ;
  191.                 resID = 1002;
  192.             }                
  193.             if (row==16 && vers<cmCS2ProfileVersion)        // CS1 Flags
  194.             {    flagPtr = (unsigned long *)&(head.cm1.flags) ;
  195.                 resID = 1003;
  196.             }                
  197.             if (row==17)                                    // CS Intent
  198.             {    flagPtr = &(head.cm2.renderingIntent) ;
  199.                 resID = 1000;
  200.             }                
  201.             
  202.             if (flagPtr) cmerr = BuildFlagListMenu( resID, *flagPtr, menu ) ;
  203.             
  204.             if (flagPtr && !cmerr)
  205.             {
  206.                 mresult = PopUpMenuSelectFont(menu,mOrigin.v,mOrigin.h,0, 3, 9);
  207.                 DeleteMenu((**menu).menuID);
  208.                 mitem = LoWord(mresult);
  209.  
  210.                 cmerr = SetFlagFromMenuItem( resID, flagPtr, mitem ) ;
  211.                 
  212.                 if (!cmerr)
  213.                 {
  214.                     cmerr = CMSetProfileHeader(prof, &head) ;
  215.                     SetWinDirty( win, true ) ;
  216.                     InvalRect( &varsRect ) ;
  217.                     DoAppAdjustMenus() ;        // undim app items
  218.                 }
  219.             }
  220.             DisposeMenu(menu);
  221.         }
  222.     }
  223. }
  224.  
  225.  
  226. /*------------------------------------------------------------------------------*\
  227.     winCloseProfile
  228.  *------------------------------------------------------------------------------*
  229.         This is a CloseProcPtr for Profile windows.
  230.         So far, all this does is call DisposeWinHandle()
  231.         This win type doesn't need to be saved so ther is no reason to prompt the
  232.         user to save the file here.
  233.         This ProcPtr is envoked by CallWinCloseProc() which is called by:
  234.             DoMouseDownEvent() which dispached click events (e.g. close box), and
  235.             MenuProcPtrs which are called whenever menu events occur.
  236. \*------------------------------------------------------------------------------*/
  237. void    winCloseProfile ( winHandle win ) 
  238. {
  239.     DisposeWinHandle( win ) ;
  240. }
  241.  
  242.  
  243. /*------------------------------------------------------------------------------*\
  244.     winMenuProfile
  245.  *------------------------------------------------------------------------------*
  246.         This is a MenuProcPtr for Profile windows.
  247.         This routine dispatches any menu commands that the window can handle
  248.         to the appropriate function.
  249.         This ProcPtr is envoked by CallWinMenuProc() which is called by:
  250.             HandleMenuCommand() which dispatches all menu events.
  251. \*------------------------------------------------------------------------------*/
  252. void winMenuProfile ( winHandle win, long menuResult, Boolean *didit )
  253. {
  254.     short            menuID;
  255.     short            menuItem;
  256.     
  257.     *didit = true ;
  258.     menuID   = HiWrd(menuResult) ;
  259.     menuItem = LoWrd(menuResult) ;
  260.     switch ( menuID )
  261.     {
  262.         case mFile:
  263.             switch ( menuItem )
  264.             {
  265.                 case iSave:                // save this document under the name it was opened
  266.                     SaveCmndProfile( win ) ;
  267.                     break ;
  268.                 case iSaveAs:            // save this document under a new name
  269.                     SaveAsCmndProfile( win ) ;
  270.                     break ;
  271.                 case iRevert:            // discard all changes made to the document since it was last saved
  272.                     RevertCmndProfile( win ) ;
  273.                     break ;
  274.                 default :
  275.                     *didit = false ;
  276.                     break ;
  277.             }
  278.             break ;
  279.  
  280.         case mProfiles:
  281.             switch ( menuItem )
  282.             {
  283.                 case iSetDefaultProf:
  284.                     ProfMakeSysProfileCmnd( win ) ;
  285.                     break ;
  286.                 case iCreateProfID:
  287.                     ProfCreateProfIDCmnd( win ) ;
  288.                     break ;
  289.                 default :
  290.                     *didit = false ;
  291.                     break ;
  292.             }
  293.             break ;
  294.  
  295.         default :
  296.             *didit = false ;
  297.             break ;
  298.     }
  299.     HiliteMenu(0) ;        // Unhighlight whatever MenuSelect or MenuKey hilited
  300. }
  301.  
  302.     
  303. /*------------------------------------------------------------------------------*\
  304.     winUpdateMenusProfile
  305.  *------------------------------------------------------------------------------*
  306.         This is a UpdateMenuProcPtr for Profile windows.
  307.         This routine enables any menu commands that the window can handle.
  308.         This ProcPtr is envoked by CallWinUpdateMenusProc() which is called by:
  309.             DoAppAdjustMenus() which dispatches all menu events.
  310. \*------------------------------------------------------------------------------*/
  311. void winUpdateMenusProfile ( winHandle win ) 
  312. {
  313.     MenuHandle        theMenu ;
  314.     FSSpec            spec ;
  315.     Boolean            dirty ;
  316.     Boolean            hasFile ;
  317.     OSType            subtype ;
  318.     winHandle        frontWin;
  319.     
  320.     frontWin = GetFrontWindowWinHandle() ;
  321.     
  322.     if ( win == frontWin )
  323.     {
  324.         spec = GetWinFSSpec( win ) ;
  325.         dirty = GetWinDirty( win ) ;
  326.         hasFile = ( spec.name[0] > 0 ) ;
  327.         subtype = GetWinSubtype( win ) ;
  328.  
  329.         // do the file menu
  330.         theMenu = GetMenuHandle ( mFile ) ;
  331.     
  332.             EnableItem ( theMenu, kWholeMenu ) ;
  333.             EnableItem ( theMenu, iClose ) ;
  334.             EnableItem ( theMenu, iSaveAs ) ;
  335.         
  336.             // for the next 2, check to see if the document has been changed
  337.             if ( dirty && subtype==kFileSubType)
  338.                 EnableItem ( theMenu, iSave ) ;
  339.             if ( dirty && subtype==kFileSubType && hasFile )
  340.                 EnableItem ( theMenu, iRevert ) ;
  341.  
  342.         // do the profiles menu
  343.         theMenu = GetMenuHandle ( mProfiles ) ;
  344.         
  345.             EnableItem ( theMenu, kWholeMenu ) ;
  346.             EnableItem ( theMenu, iCreateProfID ) ;
  347.             if ( subtype==kFileSubType )
  348.                 EnableItem ( theMenu, iSetDefaultProf ) ;
  349.     }
  350. }
  351.  
  352.  
  353. /*------------------------------------------------------------------------------*\
  354.     winAllocProfile
  355.  *------------------------------------------------------------------------------*
  356.         This is a AllocProcPtr for Profile windows.
  357.         This routine is responsible for filling in all the needed fields of the
  358.         winHandle structure.  This routine shouldn't be called directly.
  359.         Instead, the code which needs to create a document of this type should
  360.         call NewWinHandle(win,winAllocProfile) to envoke this function.
  361.         This ProcPtr is envoked by NewWinHandle() which is called by:
  362.             app_aeODOC_handler() which handles ODOC AppleEvents, and
  363.             app_aePDOC_handler() which handles PDOC AppleEvents.
  364. \*------------------------------------------------------------------------------*/
  365. OSErr winAllocProfile ( winHandle win )
  366. {
  367.     OSErr            err = noErr ;
  368.     ProfileDataHdl    data ;
  369.         
  370.     // we need ColorSync 2.
  371.     if (!CS2_available())
  372.         return eWarnCantOpenFileNoColorSync2 ;
  373.  
  374.     // set the window type
  375.     SetWinType( win, kProfileType ) ;
  376.     
  377.     // stuff winHandle fields
  378.     SetWinUpdateProc        ( win,      (UpdateProcPtr) winUpdateProfile ) ;
  379.     SetWinClickProc            ( win,       (ClickProcPtr) winClickProfile ) ;
  380.     SetWinMenuProc            ( win,        (MenuProcPtr) winMenuProfile ) ;
  381.     SetWinUpdateMenusProc    ( win, (UpdateMenusProcPtr) winUpdateMenusProfile ) ;
  382.     SetWinOpenProc            ( win,        (OpenProcPtr) winOpenProfile ) ;
  383.     SetWinCloseProc            ( win,       (CloseProcPtr) winCloseProfile ) ;
  384.     SetWinDisposeProc        ( win,     (DisposeProcPtr) winDisposeProfile ) ;
  385.  
  386.     // allocate data handle
  387.     data = (ProfileDataHdl)NewHandleClear( sizeof(ProfileDataRec) ) ;    
  388.     if( data == nil ) return MemError() ;
  389.     SetWinData( win, (Handle)data ) ;
  390.     
  391.     return err ;    
  392. }
  393.  
  394.  
  395. /*------------------------------------------------------------------------------*\
  396.     winOpenProfile
  397.  *------------------------------------------------------------------------------*
  398.         This is a OpenProcPtr for Profile windows.
  399.         This routine is responsible for opening a Profile window after all the
  400.         needed fields of the winHandle structure have been filled in by winAllocProfile.
  401.         On entry the DocumentRecord must contain a valid FSSpec.
  402.         If a Profile window for the FSSpec is already onen, then this routine 
  403.         will bring it to the front instead of opening a second window.
  404.         This routine shouldn't be called directly.  Instead, the code which needs
  405.         to create a document of this type should call NewWinHandle(win,winAllocProfile),
  406.         SetWinFSSpec (win,spec), and then CallWinOpenProc(win) to envoke this function.
  407.         This ProcPtr is envoked by CallWinOpenProc() which is called by:
  408.             app_aeODOC_handler() which handles ODOC AppleEvents, and
  409.             app_aePDOC_handler() which handles PDOC AppleEvents.
  410. \*------------------------------------------------------------------------------*/
  411. OSErr winOpenProfile ( winHandle win )
  412. {
  413.     OSErr                err = noErr ;
  414.     winHandle            existingWin ;
  415.     FSSpec                spec ;
  416.     CMProfileRef         prof ;
  417.     CMProfileLocation    profLoc ;
  418.     OSType                subtype ;    // this is the subtype of window ('file' 'embd' or 'sysp')
  419.     unsigned long        index ;        // if embeded subtype then this tells us which one
  420.     Boolean                alreadyOpen = false;
  421.     short                count, i ;
  422.     
  423.     spec = GetWinFSSpec( win ) ;
  424.     subtype = GetWinSubtype( win ) ;
  425.     index = GetProfileIndex( win ) ;
  426.  
  427.     // see if already open
  428.     switch (subtype)
  429.     {
  430.         case kFileSubType :
  431.              if ( FindWinHandle( &spec, kProfileType, subtype, 1, 1, &existingWin ) == 1 )
  432.                  alreadyOpen = true ;
  433.              break ;
  434.              
  435.         case kEmbededSubType :
  436.             count = FindWinHandle( &spec, kProfileType, subtype, 0, 0, nil ) ;
  437.             for (i=1; i<=count && !alreadyOpen; i++)
  438.             {
  439.                 if ( FindWinHandle( &spec, kProfileType, subtype, i, 1, &existingWin ) == 1 )
  440.                     if ( GetProfileIndex(existingWin) == index )
  441.                         alreadyOpen = true ;
  442.             }
  443.              break ;
  444.              
  445.         case kSysProfSubType :
  446.              if ( FindWinHandle( nil, kProfileType, subtype, 1, 1, &existingWin ) == 1 )
  447.                  alreadyOpen = true ;
  448.              break ;
  449.     }
  450.      
  451.      if (alreadyOpen)
  452.     {
  453.         // bring it to the front
  454.         SelectWindow( GetWinWindow(existingWin) ) ;        
  455.         return kWasAlreadyOpen ;
  456.     }
  457.  
  458.     switch (subtype)
  459.     {
  460.         case kFileSubType :
  461.             err = OpenProfileFSSpec( spec, &prof ) ;
  462.             if ( err ) return err;
  463.             SetProfileRef( win, prof ) ;            // set the window's data's profile ref
  464.             break ;
  465.             
  466.         case kEmbededSubType :
  467.             //? the prof is valid
  468.             //? the spec is the spec of the pict file
  469.             break ;
  470.             
  471.         case kSysProfSubType :
  472.             err = CMGetSystemProfile( &prof ) ;
  473.             err = CMGetProfileLocation( prof, &profLoc) ;
  474.             if ( err ) return err ;
  475.             if ( profLoc.locType != cmFileBasedProfile )
  476.                 return fnfErr ;                        //? should also close prof
  477.             spec = profLoc.u.fileLoc.spec ;
  478.             SetWinFSSpec( win, &spec ) ;
  479.             SetProfileRef( win, prof ) ;            // this should be nil already
  480.             break ;
  481.     }
  482.     
  483.     err = DoCreateProfWindow( win ) ;
  484.     return err ;    
  485. }
  486.  
  487.  
  488. /*------------------------------------------------------------------------------*\
  489.     winDisposeProfile
  490.  *------------------------------------------------------------------------------*
  491.         This is a DisposeProcPtr for Profile windows.
  492.         This routine is responsible for disposing of any data that was allocated
  493.         by the document and stored in the its data handle.
  494.         This ProcPtr is envoked by CallWinDisposeProc() which is called by:
  495.             DisposeWinHandle() which disposes of the entire winHandle.
  496. \*------------------------------------------------------------------------------*/
  497. void winDisposeProfile ( winHandle win )
  498. {
  499.     ProfileDataHdl    data ;
  500.     CMProfileRef    prof ;
  501.  
  502.     data = (ProfileDataHdl) GetWinData ( win ) ;
  503.     if ( data==nil ) return;
  504.  
  505.     prof = GetProfileRef( win ) ;
  506.     if ( prof != nil )
  507.         CMCloseProfile( prof ) ;
  508.  
  509. #if TryGettingAnEditableProfileName    
  510.     TEHandle teh = GetProfileNameTEH( win ) ;
  511.     if ( teh != nil )
  512.         TEDispose( teh ) ;
  513. #endif
  514.  
  515.     // lastly, dispose of the data handle
  516.     DisposeHandle( (Handle)data ) ;
  517. }
  518.  
  519.  
  520. /**\
  521. |**| ==============================================================================
  522. |**| PRIVATE FUNCTIONS
  523. |**| ==============================================================================
  524. \**/
  525.  
  526.  
  527. static void DoDrawProfData ( winHandle win ) 
  528. {    
  529.     long                length ;
  530.     Rect                labelRect, varsRect, whereRect, iconRect ; // = {7,53,39,85} ;
  531.     Handle                labelText, varText,  whereText ;
  532.     CMProfileRef        prof ;    
  533.     CMError                cmerr ;
  534.     OSType                subtype ;
  535.     unsigned long        vers ;
  536.     Str255                name, path ;
  537.     FSSpec                spec ;
  538.  
  539. // get rects from resources
  540.     labelRect = GetRect ( rProfileLabelsStringID ) ;
  541.     varsRect = GetRect ( rProfileVarsStringID ) ;
  542.     whereRect = GetRect ( rProfileWhereVarStringID ) ;
  543.     iconRect = GetRect ( rProfileIconID ) ;
  544.  
  545. // draw icon
  546.     PlotIconID( &iconRect, atNone, ttNone, rProfileIconID ) ;
  547.  
  548. // draw labels
  549.     TextSize(9) ;
  550.     TextFace(bold) ;
  551.     TextFont(applFont) ;
  552.  
  553.     labelText = GetResource( 'TEXT', rProfileLabelsStringID ) ;
  554.     
  555.     HLock( labelText ) ;
  556.     length = GetHandleSize( labelText ) ;
  557.     TETextBox( *labelText, length, &labelRect, teFlushRight) ;
  558.     HUnlock( labelText ) ;
  559.     ReleaseResource( labelText ) ;
  560.  
  561.     TextSize(9) ;
  562.     TextFace(0) ;
  563.     TextFont(applFont) ;
  564.  
  565. // get the profile's vital stats
  566.     subtype = GetWinSubtype( win ) ;
  567.     prof = GetProfileRef( win ) ;
  568.     spec = GetWinFSSpec( win ) ;
  569.     
  570. // get the profile's name element
  571.     cmerr = GetProfName ( prof, (StringPtr)&name ) ;
  572.     if (cmerr) return ;
  573.  
  574. // draw the profile's name
  575.     MoveTo (varsRect.left,varsRect.top-19) ;
  576.     if ( IsPseudoProfile(prof) )
  577.         TextFace(italic) ;
  578.     DrawString( name ) ;
  579.     TextFace(0) ;
  580.  
  581. #if TryGettingAnEditableProfileName    
  582.     {
  583.         TEHandle    hTE;
  584.         Rect        rUpdate;
  585.         hTE = GetProfileNameTEH( win );
  586.         rUpdate = (**hTE).destRect;
  587.         TEUpdate(&rUpdate,hTE);
  588.     }
  589. #endif    
  590.     
  591. // get profile version
  592.     cmerr = GetProfVersion ( prof, &vers) ;
  593.     if (cmerr) return ;
  594.  
  595. // set up the profile info text
  596.     varText = GetResource( 'TEXT', rProfileVarsStringID ) ;
  597.     if (vers == cmCS1ProfileVersion)
  598.         MungeProfileHeader1( prof, varText ) ;
  599.     else if (vers >= cmCS2ProfileVersion)
  600.         MungeProfileHeader2( prof, varText ) ;
  601.     else return ;                            // need a better error code here
  602.  
  603. // set up the "where" info text
  604.     whereText = GetResource( 'TEXT', rProfileWhereVarStringID ) ;
  605.     FSSpecToString( GetWinFSSpec(win), path, (subtype==kEmbededSubType) ) ;
  606.     MyReplaceText ( whereText, path, "\p«Where»" ) ;
  607.     MyReplaceText ( whereText, "\p:\0", "\p:" ) ;
  608.  
  609. // draw the profile info
  610.     HLock( varText ) ;
  611.     length = GetHandleSize( varText ) ;
  612.     TETextBox( *varText, length, &varsRect, teFlushLeft) ;
  613.     HUnlock( varText ) ;
  614.     ReleaseResource( varText ) ;    
  615.  
  616. // draw the "where" information
  617.     HLock( whereText ) ;
  618.     length = GetHandleSize( whereText ) ;
  619.     TETextBox( *whereText, length, &whereRect, teFlushLeft) ;
  620.     HUnlock( whereText ) ;
  621.     ReleaseResource( whereText ) ;
  622. }
  623.  
  624.  
  625. /*------------------------------------------------------------------------------*\
  626. \*------------------------------------------------------------------------------*/
  627. static void MungeProfileHeader1 ( CMProfileRef prof, Handle text )
  628. {
  629.     CMAppleProfileHeader    head ;
  630.     CMHeader                cm1 ;
  631.     Str255                    myStr ;
  632.     CMError                    cmerr ;
  633.     
  634. // get the profile's header
  635.     cmerr = CMGetProfileHeader(prof, &head) ;
  636.     if (cmerr) return ;
  637.     cm1 = head.cm1 ;
  638.     
  639. // Vers
  640.     MyReplaceText( text, "\p1.0", "\p«Vers»" ) ;
  641. // Embed
  642. // Size
  643.     FormatLong( cm1.size, rBytesFMAT, myStr) ;
  644.     MyReplaceText( text, myStr, "\p«Size»" ) ;
  645. // ColorSpace
  646.     ColorSpace2String ( cm1.dataType, myStr ) ;
  647.     MyReplaceText( text, myStr, "\p«ColorSpace»" ) ;
  648. // InterchangeSpace
  649.     ColorSpace2String ( 'XYZ ', myStr ) ;
  650.     MyReplaceText( text, myStr, "\p«XchngSpace»" ) ;
  651. // CMM
  652.     OSTypeToString( cm1.CMMType, myStr) ;
  653.     MyReplaceText( text, myStr, "\p«CMM»" ) ;
  654. // Class
  655.     ProfileClass2String ( cm1.deviceType, myStr ) ;
  656.     MyReplaceText( text, myStr, "\p«Class»" ) ;
  657. // Manufacturer
  658.     OSTypeToString( cm1.deviceManufacturer, myStr) ;
  659.     MyReplaceText( text, myStr, "\p«Manufacturer»" ) ;
  660. // DeviceModel
  661.     LongHexToString ( cm1.deviceModel, myStr) ;
  662.     MyReplaceText( text, myStr, "\p«DeviceModel»" ) ;
  663. // Attributes
  664.     LongHexToString ( cm1.deviceAttributes[0], myStr) ;
  665.     MyReplaceText( text, myStr, "\p«Attributes0»" ) ;
  666.     LongHexToString ( cm1.deviceAttributes[1], myStr) ;
  667.     MyReplaceText( text, myStr, "\p«Attributes1»" ) ;
  668. // Flags
  669.     LongHexToString ( cm1.flags, myStr) ;
  670.     MyReplaceText( text, myStr, "\p«Flags»" ) ;
  671. // Intent
  672.     RendIntent2String ( cm1.options, myStr ) ;
  673.     MyReplaceText( text, myStr, "\p«Intent»" ) ;
  674. // White
  675.     MyReplaceText( text, "\p«X», «Y», «Z»", "\p«White»" ) ;
  676.     FormatSmallFract( cm1.white.X, rDotThreeFMAT, myStr ) ;
  677.     MyReplaceText( text, myStr, "\p«X»" ) ;
  678.     FormatSmallFract( cm1.white.Y, rDotThreeFMAT, myStr ) ;
  679.     MyReplaceText( text, myStr, "\p«Y»" ) ;
  680.     FormatSmallFract( cm1.white.Z, rDotThreeFMAT, myStr ) ;
  681.     MyReplaceText( text, myStr, "\p«Z»" ) ;
  682. // Created
  683.     MyReplaceText( text, "\p--", "\p«Created»" ) ;
  684. }
  685.  
  686.  
  687. /*------------------------------------------------------------------------------*\
  688. \*------------------------------------------------------------------------------*/
  689. static void MungeProfileHeader2 ( CMProfileRef prof, Handle text )
  690. {
  691.     CMAppleProfileHeader    head ;
  692.     CM2Header                cm2 ;
  693.     Str255                    myStr ;
  694.     CMError                    cmerr ;
  695.     unsigned long            rawSecs ;
  696.  
  697. // get the profile's header
  698.     cmerr = CMGetProfileHeader(prof, &head) ;
  699.     if (cmerr) return ;
  700.     cm2 = head.cm2 ;
  701.     
  702. // Vers
  703.     VersionToString( cm2.profileVersion, myStr) ;
  704.     MyReplaceText( text, myStr, "\p«Vers»" ) ;
  705. // Embed
  706. // Size
  707.     FormatLong( cm2.size, rBytesFMAT, myStr) ;
  708.     MyReplaceText( text, myStr, "\p«Size»" ) ;
  709. // ColorSpace
  710.     ColorSpace2String ( cm2.dataColorSpace, myStr ) ;
  711.     MyReplaceText( text, myStr, "\p«ColorSpace»" ) ;
  712. // InterchangeSpace
  713.     ColorSpace2String ( cm2.profileConnectionSpace, myStr ) ;
  714.     MyReplaceText( text, myStr, "\p«XchngSpace»" ) ;
  715. // CMM
  716.     OSTypeToString( cm2.CMMType, myStr) ;
  717.     MyReplaceText( text, myStr, "\p«CMM»" ) ;
  718. // Class
  719.     OSTypeToString( cm2.profileClass, myStr) ;
  720.     ProfileClass2String ( cm2.profileClass, myStr ) ;
  721.     MyReplaceText( text, myStr, "\p«Class»" ) ;
  722. // Manufacturer
  723.     OSTypeToString( cm2.deviceManufacturer, myStr) ;
  724.     MyReplaceText( text, myStr, "\p«Manufacturer»" ) ;
  725. // DeviceModel
  726.     LongHexToString ( cm2.deviceModel, myStr) ;
  727.     MyReplaceText( text, myStr, "\p«DeviceModel»" ) ;
  728. // Attributes
  729.     LongHexToString ( cm2.deviceAttributes[0], myStr) ;
  730.     MyReplaceText( text, myStr, "\p«Attributes0»" ) ;
  731.     LongHexToString ( cm2.deviceAttributes[1], myStr) ;
  732.     MyReplaceText( text, myStr, "\p«Attributes1»" ) ;
  733. // Flags
  734.     LongHexToString ( cm2.flags, myStr) ;
  735.     MyReplaceText( text, myStr, "\p«Flags»" ) ;
  736. // Intent
  737.     RendIntent2String ( cm2.renderingIntent, myStr ) ;
  738.     MyReplaceText( text, myStr, "\p«Intent»" ) ;
  739. // White
  740.     MyReplaceText( text, "\p«X», «Y», «Z»", "\p«White»" ) ;
  741.     FormatFixed( cm2.white.X, rDotThreeFMAT, myStr) ;
  742.     MyReplaceText( text, myStr, "\p«X»" ) ;
  743.     FormatFixed( cm2.white.Y, rDotThreeFMAT, myStr) ;
  744.     MyReplaceText( text, myStr, "\p«Y»" ) ;
  745.     FormatFixed( cm2.white.Z, rDotThreeFMAT, myStr) ;
  746.     MyReplaceText( text, myStr, "\p«Z»" ) ;
  747. // Created
  748.     MyReplaceText( text, "\p«Date», «Time»", "\p«Created»" ) ;
  749.     DateToSeconds( (DateTimeRec*)&(cm2.dateTime), &rawSecs) ;
  750.     IUDateString( rawSecs, abbrevDate, myStr) ;
  751.     MyReplaceText( text, myStr, "\p«Date»" ) ;
  752.     IUTimeString( rawSecs, false, myStr) ;
  753.     MyReplaceText( text, myStr, "\p«Time»" ) ;
  754. }
  755.  
  756.  
  757. static OSErr RendIntent2String ( unsigned long intent, StringPtr dest )
  758. {
  759.     return GetFlagListStringPtr( 1000, intent, dest ) ;
  760. }
  761.  
  762. static OSErr ColorSpace2String ( OSType spaceType, StringPtr dest )
  763. {
  764.     return GetOSTypeListStringPtr( 129, spaceType, dest ) ;
  765. }
  766.  
  767. static OSErr ProfileClass2String ( OSType classType, StringPtr dest )
  768. {
  769.     return GetOSTypeListStringPtr( 128, classType, dest ) ;
  770. }
  771.  
  772.  
  773.  
  774.  
  775.  
  776. /*------------------------------------------------------------------------------*\
  777.     DoCreateProfWindow
  778.  *------------------------------------------------------------------------------*
  779.         This routine actually creates the WindowRef for a winHandle.
  780.         After creating the window, it:
  781.             reference the window and the DocumentRecord to each other,
  782.             makes the window the current port,
  783.             resizes the window according to the WIND resource,
  784.             titles it according the the FSSpec, and
  785.             makes it visible .
  786.         This routine is called by:
  787.             winOpenProfList() which fills in the winHandle structure
  788. \*------------------------------------------------------------------------------*/
  789. static OSErr DoCreateProfWindow ( winHandle win )
  790. {
  791.     OSErr            err = noErr ;
  792.     WindowRef        window ;
  793.     FSSpec            spec ;
  794.     CMProfileRef     prof ;
  795.     OSType            subtype ;
  796.     Str255            winTitle="\p" ;
  797.         
  798.     // create the window
  799.     window = GetNewCWindow(rProfileWindID, nil, (WindowRef)-1 ) ;
  800.             
  801.     SetWinWindow( win, window ) ;            // save a reference to the window in the winRecord
  802.     SetWindowWinHandle ( window, win ) ;        // save a reference to the winRecord in the window
  803.  
  804.     SetGWorld( (CGrafPtr)GetWinWindow(win), nil ) ;    // set the window to be the current port
  805.  
  806.     SetWinRect( win, ((CGrafPtr)window)->portRect ) ;
  807.  
  808.     spec = GetWinFSSpec( win ) ;
  809.     prof = GetProfileRef( win ) ;
  810.     subtype = GetWinSubtype( win ) ;
  811.  
  812.     // set the name of this document window
  813.     switch (subtype)
  814.     {
  815.         case kFileSubType :
  816.             SetWTitle( window, spec.name ) ;
  817.             break ;
  818.             
  819.         case kEmbededSubType :
  820.             NumToString( GetProfileIndex(win), winTitle ) ;
  821.             pStrIns( winTitle, "\p:", 255 ) ;
  822.             pStrIns( winTitle, spec.name, 255 ) ;
  823.             SetWTitle( window, winTitle ) ;
  824.             break ;
  825.             
  826.         case kSysProfSubType :
  827.             err = GetProfName( nil, winTitle ) ;
  828.             SetWTitle( window, winTitle ) ;
  829.             break ;
  830.     }
  831.  
  832. #if TryGettingAnEditableProfileName    
  833.     {
  834.         Rect        varsRect;
  835.         Rect        destRect;
  836.         Rect        viewRect;
  837.         TEHandle    hTE;
  838.         
  839.         varsRect = GetRect ( rProfileVarsStringID ) ;
  840.         varsRect.top -= 19;
  841.         varsRect.bottom = varsRect.top + 16*2;
  842.         
  843.         destRect = viewRect = varsRect;
  844.         
  845.         hTE = TENew(&destRect,&viewRect);
  846.         (**hTE).txSize = 9;
  847.         (**hTE).lineHeight = 16;
  848.         (**hTE).fontAscent = 9;
  849.         TESetText(" ",1,hTE);
  850.     //    TESetText("this is a test",14,hTE);
  851.         TEActivate(hTE);
  852.                 
  853.         SetProfileNameTEH( win, hTE );
  854.     }
  855. #endif
  856.  
  857.     // make sure it is visible
  858.     ShowWindow( window ) ;
  859.     
  860.     return err ;
  861. }
  862.  
  863.  
  864. static void ProfMakeSysProfileCmnd ( winHandle win ) 
  865. {
  866.     OSType            subtype ;
  867.     OSErr            err ;
  868.     FSSpec            spec ;
  869.     
  870.     subtype = GetWinSubtype( win ) ;
  871.     if ( subtype==kFileSubType )
  872.     {
  873.         spec = GetWinFSSpec( win ) ;
  874.         err = CMSetSystemProfile( &spec ) ;
  875.     }
  876. }
  877.  
  878. static void ProfCreateProfIDCmnd ( winHandle win ) 
  879. {
  880.     OSErr                    err ;
  881.     CMProfileRef            prof ;
  882.     unsigned long            size ;
  883.     CMProfileIdentifierHdl    ident ;
  884.     winHandle                newwin ;
  885.     
  886.     prof = GetProfileRef( win ) ;
  887.     
  888.     err = CMCreateProfileIdentifierCompat( prof, nil, &size) ;
  889.     if (err) return ;
  890.     ident = (CMProfileIdentifierHdl) NewHandle( size );
  891.     if (!ident) return ;
  892.     HLock( (Handle)ident );
  893.     err = CMCreateProfileIdentifierCompat( prof, *ident, &size) ;
  894.     HUnlock( (Handle)ident );
  895.     
  896.     
  897.     // create a new winHandle of the proper type
  898.     err = NewWinHandle( &newwin, winAllocProfID ) ;
  899.     WarnIfErr( err ) ;
  900.     if (err) return ;
  901.  
  902.     // set the subtype of the winHandle so that the correct search is done
  903.     SetProfIDIDHdl( newwin, ident ) ;
  904.     SetWinSubtype( newwin, kHandleSubType ) ;    // set subtype
  905.     
  906.     err = CallWinOpenProc( newwin ) ;
  907.     if ( err != noErr )
  908.         DisposeWinHandle( newwin ) ;
  909.  
  910.     if ( err == kWasAlreadyOpen )
  911.         err = noErr;
  912. }
  913.  
  914.  
  915. /*------------------------------------------------------------------------------*\
  916.     SaveCmndProfile
  917.  *------------------------------------------------------------------------------*
  918. \*------------------------------------------------------------------------------*/
  919. static void SaveCmndProfile ( winHandle win ) 
  920. {
  921.     FSSpec                spec ;
  922.     Boolean                dirty ;
  923.     Boolean                hasFile ;
  924.     OSErr                err ;
  925.     OSType                subtype ;
  926.     
  927.     spec = GetWinFSSpec( win ) ;
  928.     dirty = GetWinDirty( win ) ;
  929.     hasFile = ( spec.name[0] > 0 ) ;
  930.     subtype = GetWinSubtype( win ) ;
  931.     GetProfileRef( win ) ;
  932.  
  933.     if ( !dirty ) return;                // no need to save
  934.     if ( subtype!=kFileSubType) return;    // can't save
  935.     
  936.     if ( !hasFile )
  937.         SaveAsCmndProfile( win ) ;
  938.     else
  939.     {
  940.         err = CMUpdateProfile(GetProfileRef(win));
  941.         if (err) return ;                // if err, should do something
  942.         SetWinDirty( win, false ) ;
  943.         DoAppAdjustMenus() ;            // undim app items
  944.     }
  945. }
  946.  
  947.  
  948. /*------------------------------------------------------------------------------*\
  949.     SaveAsCmndProfile
  950.  *------------------------------------------------------------------------------*
  951. \*------------------------------------------------------------------------------*/
  952. static void SaveAsCmndProfile ( winHandle win ) 
  953. {
  954.     FSSpec                spec ;
  955.     Boolean                dirty ;
  956.     Boolean                hasFile ;
  957.     StandardFileReply    reply ;
  958.     OSErr                err ;
  959.     WindowRef            window ;
  960.     Str255                title ;
  961.     OSType                subtype ;
  962.     
  963.     spec = GetWinFSSpec( win ) ;
  964.     dirty = GetWinDirty( win ) ;
  965.     hasFile = ( spec.name[0] > 0 ) ;
  966.     subtype = GetWinSubtype( win ) ;
  967.     window = GetWinWindow( win ) ;
  968.     
  969.     if ( hasFile )
  970.         StringToString( spec.name, title ) ;
  971.     else
  972.         GetWTitle( window, title ) ;
  973.     
  974.     StandardPutFile( "\pSave profile as:", title, &reply) ;
  975.     if ( reply.sfGood )
  976.     {
  977.         CMProfileRef        newProf, prof;
  978.         CMProfileLocation    profLoc ;
  979.         
  980.         profLoc.locType = cmFileBasedProfile;
  981.         profLoc.u.fileLoc.spec = reply.sfFile;
  982.         
  983.         prof = GetProfileRef(win);
  984.         err = CMCopyProfile( &newProf, &profLoc, prof) ;
  985.         WarnIfErr( err ) ;
  986.         if ( err ) return ;                    // if err, should do something 
  987.         SetWinFSSpec( win, &spec ) ;        // win's spec = new spec
  988.         SetWTitle( window, spec.name ) ;    // win title = new title
  989.         SetProfileRef(win, newProf);
  990.         SetWinDirty( win, false ) ;
  991.         DoAppAdjustMenus() ;                // undim app items
  992.     }
  993. }
  994.  
  995.  
  996. /*------------------------------------------------------------------------------*\
  997.     RevertCmndProfile
  998.  *------------------------------------------------------------------------------*
  999. \*------------------------------------------------------------------------------*/
  1000. static void RevertCmndProfile ( winHandle win ) 
  1001. {    
  1002.     FSSpec                spec ;
  1003.     Boolean                dirty ;
  1004.     Boolean                hasFile ;
  1005.     OSType                subtype ;
  1006.  
  1007.     spec = GetWinFSSpec( win ) ;
  1008.     dirty = GetWinDirty( win ) ;
  1009.     hasFile = ( spec.name[0] > 0 ) ;
  1010.     subtype = GetWinSubtype( win ) ;
  1011.     
  1012.     if ( !dirty || !hasFile ) return ;
  1013.     if ( subtype!=kFileSubType) return;    // can't revert
  1014.         
  1015.                                     // ask user if it's ok
  1016.     
  1017.     SetWinDirty( win, false ) ;        // clear dirty so we don't get another dialog
  1018.     CallWinCloseProc( win ) ;        // close the document
  1019.     SendODOC( &spec ) ;                // reopen: send ODOC event to ourselves:
  1020. //    DoAppAdjustMenus() ;            // undim app items
  1021. }
  1022.  
  1023.  
  1024. #define LMGetWMgrCPort() (* (GrafPtr *) 0x0D2C)
  1025.  
  1026. static long PopUpMenuSelectFont (MenuHandle theMenu,
  1027.                             short top, short left,
  1028.                               short popUpItem,
  1029.                               short font, short size)
  1030. {
  1031.     long    result;
  1032.     /*
  1033.     short    SaveSysFontFam;
  1034.     GrafPtr    wmPtr,wmCPtr;
  1035.     short    SaveWPortFont;
  1036.     short    SaveWPortSize;
  1037.     
  1038.     wmPtr  = LMGetWMgrPort();
  1039.     wmCPtr = LMGetWMgrCPort();
  1040.     SaveWPortFont  = wmPtr->txFont;
  1041.     SaveWPortSize  = wmPtr->txSize;
  1042.     
  1043.     SaveSysFontFam = LMGetSysFontFam();
  1044.     LMSetSysFontFam(font);
  1045.     wmCPtr->txFont = font;
  1046.     wmCPtr->txSize = size;
  1047.     wmPtr->txFont  = font;
  1048.     wmPtr->txSize  = size;
  1049.     */
  1050.     result = PopUpMenuSelect(theMenu,top,left,popUpItem);
  1051.     /*
  1052.     LMSetSysFontFam(SaveSysFontFam);
  1053.     wmCPtr->txFont = SaveWPortFont;
  1054.     wmCPtr->txSize = SaveWPortSize;
  1055.     wmPtr->txFont  = SaveWPortFont;
  1056.     wmPtr->txSize  = SaveWPortSize;
  1057.     */
  1058.     return result;
  1059. }
  1060.  
  1061.  
  1062. /*------------------------------------------------------------------------------*\
  1063.     GetFlagListStringPtr
  1064.  *------------------------------------------------------------------------------*
  1065.         This routine loads a 'BTS#' resource and loops through it looking
  1066.         for the string that coresponds to the type parameter.
  1067. \*------------------------------------------------------------------------------*/
  1068.  
  1069. static OSErr GetFlagListStringPtr( short id, unsigned long flags, StringPtr dest )
  1070. {
  1071.     short            i, count;
  1072.     short            shift ;
  1073.     long            maskShift, valueShift ;
  1074.     FlagListHdl        list ;
  1075.     
  1076.     list = (FlagListHdl) GetResource('BTS#', id) ;
  1077.     if (list==nil) return ResError() ;
  1078.     
  1079.     count = (**list).count ;
  1080.     dest[0] = 0 ;
  1081.     
  1082.     for (i=0; i<count; i++ )
  1083.     {
  1084.         shift = (**list).entry[i].shift ;
  1085.         maskShift  = ((unsigned long)((**list).entry[i].mask))  << shift ;
  1086.         valueShift = ((unsigned long)((**list).entry[i].value)) << shift ;
  1087.  
  1088.         if ( (flags & maskShift) == valueShift )
  1089.         {
  1090.             if (dest[0]) pStrCat( dest, "\p, ", 255 );
  1091.             pStrCat( dest, (StringPtr)&((**list).entry[i].string), 255 );
  1092.         }
  1093.     }
  1094.     ReleaseResource( (Handle)list ) ;
  1095.     return noErr ;
  1096. }
  1097.  
  1098. static OSErr BuildFlagListMenu ( short id, unsigned long flags, MenuHandle menu )
  1099. {
  1100.     short            j, i, count;
  1101.     short            shift, lastshift ;
  1102.     long            maskShift, valueShift ;
  1103.     FlagListHdl        list ;
  1104.     
  1105.     list = (FlagListHdl) GetResource('BTS#', id) ;
  1106.     if (list==nil) return ResError() ;
  1107.     
  1108.     count = (**list).count ;
  1109.     
  1110.     for (j=i=0; i<count; i++, j++ )
  1111.     {
  1112.         shift = (**list).entry[i].shift ;
  1113.         maskShift  = ((unsigned long)((**list).entry[i].mask))  << shift ;
  1114.         valueShift = ((unsigned long)((**list).entry[i].value)) << shift ;
  1115.  
  1116.         if ( (i!=0) && (lastshift!=shift) )
  1117.         {
  1118.             AppendMenu( menu, "\p-" );
  1119.             j++;
  1120.         }
  1121.             
  1122.         AppendMenu(menu, (StringPtr)&((**list).entry[i].string) );
  1123.         if ( (flags & maskShift) == valueShift )
  1124.             SetItemMark(menu,j+1,0xC3);
  1125.         
  1126.         lastshift = shift ;
  1127.     }
  1128.     ReleaseResource( (Handle)list ) ;
  1129.     return noErr ;
  1130. }
  1131.  
  1132. static OSErr SetFlagFromMenuItem ( short id, unsigned long *flags, short mitem )
  1133. {
  1134.     short            j, i, count;
  1135.     short            shift, lastshift ;
  1136.     long            maskShift, valueShift ;
  1137.     FlagListHdl        list ;
  1138.     unsigned long    flagsBefore ;
  1139.     
  1140.     flagsBefore = *flags ;
  1141.  
  1142.     list = (FlagListHdl) GetResource('BTS#', id) ;
  1143.     if (list==nil) return ResError() ;
  1144.     
  1145.     count = (**list).count ;
  1146.     
  1147.     for (j=i=0; i<count; i++, j++ )
  1148.     {
  1149.         shift = (**list).entry[i].shift ;
  1150.         maskShift  = ((unsigned long)((**list).entry[i].mask))  << shift ;
  1151.         valueShift = ((unsigned long)((**list).entry[i].value)) << shift ;
  1152.  
  1153.         if ( (i!=0) && (lastshift!=shift) )
  1154.             j++;
  1155.         
  1156.         if (mitem == j+1)
  1157.             *flags = ((*flags) & (~maskShift)) | (valueShift);
  1158.  
  1159.         lastshift = shift ;
  1160.     }
  1161.     ReleaseResource( (Handle)list ) ;
  1162.     
  1163.     return (flagsBefore == *flags) ;        // return something if there was no change
  1164. }
  1165.  
  1166.  
  1167.