home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 May: Tool Chest / Dev.CD May 98 TC.toast / Tool Chest / QuickTime / QuickTime Tools / DrawTextCodec Example / Sample code / CodecTestMain.c next >
Encoding:
C/C++ Source or Header  |  1992-06-12  |  24.8 KB  |  1,150 lines  |  [TEXT/KAHL]

  1. /*
  2.  
  3.     Written by:    Mark Krueger
  4.  
  5.     Copyright:    © 1992 by Apple Computer, Inc., all rights reserved.
  6.  
  7. */
  8.  
  9.  
  10. #ifdef    THINK_C
  11. //#define    OpenStdCompression    OPENSTDCOMPRESSION
  12. #endif
  13.  
  14.  
  15. #include    "StdCompression.h"
  16. #include    "ImageCompression.h"
  17. #include    "DrawTextCodec.h"
  18.  
  19. #define    dangerousPattern
  20.  
  21. //#define    DONT_SHOW_PICTURE
  22. //#define    DONT_DO_PREVIEW
  23.  
  24. #include    <Types.h>
  25. #include    <Files.h>
  26. #include    <Quickdraw.h>
  27. #include    <Packages.h>
  28. #include    <Memory.h>
  29. #include    <Fonts.h>
  30. #include    <Events.h>
  31. #include    <OSUtils.h>
  32. #include    <ToolUtils.h>
  33. #include    <Menus.h>
  34. #include    <Dialogs.h>
  35. #include    <stdio.h>
  36. #include    <Errors.h>
  37. #include    <Scrap.h>
  38. #include    <Desk.h>
  39. #include    <string.h>
  40. #include    <GestaltEqu.h>
  41. #include    <Resources.h>
  42. #include    <Finder.h>
  43. #include    <PictUtil.h>
  44. #include    <palettes.h>
  45. #include    <PictUtil.h>
  46. #include    <QDOffscreen.h>
  47. #include    <Windows.h>
  48.  
  49. #ifndef    THINK_C
  50. #include    <Strings.h>
  51. #endif
  52.  
  53.  
  54. #include    "ImageCompression.h"
  55.  
  56. #include    "StdCompression.h"
  57.  
  58.  
  59.  
  60. #define        appleMenuID        128
  61. #define        fileMenuID        129
  62. #define        editMenuID        130
  63.  
  64.  
  65. #define        M_OPEN            1
  66. #define        M_CLOSE            3
  67. #define        M_SAVE            4
  68. #define        M_COMP            6
  69. #define        M_QUIT            8
  70.  
  71. #define        M_COPY            4
  72. #define        M_PASTE            5
  73. #define        M_FIT            10
  74.  
  75.  
  76. Boolean        gDitherFlag  = false;
  77. StandardFileReply    gOriginalSFR;    
  78. short            gOriginalFile;
  79. Cursor            **gWatch;
  80. short            gCompressedFile;
  81. Boolean            gExitFlag = false;
  82. MenuHandle        gMenus[3];            // our menus
  83. CWindowPtr        gActiveWindow = nil;
  84. CWindowPtr        gOrigWindow = nil;
  85. CWindowPtr        gCompWindow = nil;
  86. Rect            gOriginalPicFrame;
  87. Rect            gZoomedPictureFrame;
  88. Boolean            gZoomed = false;
  89. Boolean            gFitToWindow = true;
  90. Boolean            gHasNewStdFile = false;
  91. PicHandle        gOriginalPicture = nil;
  92. Boolean            gCompressed = false;
  93. Boolean            gSevenOh = false;
  94. short            gDepth = 1;
  95.  
  96.  
  97. ComponentInstance    gSCComponent;
  98. SCParams            gSCParams;
  99.  
  100. Boolean            gDidError = false;
  101.  
  102. GWorldPtr    gworld,compgworld;
  103.  
  104. /************************************************
  105.  *
  106.  *    Set up application environment.
  107.  *
  108.  ************************************************/
  109.  
  110.  
  111. Initialize()
  112. {
  113.     Ptr    size;
  114.     
  115.     size = GetApplLimit();
  116.     SetApplLimit(size - 32*1024);        /* make room on stack so Quickdraw can do big pictures */
  117.     MaxApplZone();
  118.  
  119.     /*    initialize managers */
  120.  
  121.     InitGraf(&qd.thePort);
  122.     InitFonts();
  123.     InitWindows();
  124.     InitMenus();
  125.     InitDialogs(nil);
  126.     InitCursor();
  127.     ErrorSound(nil);
  128.     
  129.     /*    install menus */
  130.     
  131.     if ( (gMenus[0] = GetMenu(appleMenuID)) == nil )
  132.         return(-1);
  133.     AddResMenu(gMenus[0], (ResType) 'DRVR');
  134.     InsertMenu(gMenus[0], 0);
  135.     if ( (gMenus[1] = GetMenu(fileMenuID)) == nil )
  136.         return(-1);
  137.     InsertMenu(gMenus[1], 0);
  138.     if ( (gMenus[2] = GetMenu(editMenuID)) == nil )
  139.         return(-1);
  140.     InsertMenu(gMenus[2], 0);
  141.     DrawMenuBar();
  142.     if ( (gWatch =  GetCursor(watchCursor)) == nil )
  143.         return(-1);
  144.     HNoPurge((Handle)gWatch);
  145.     return(0);
  146. }
  147.  
  148.  
  149. /************************************************
  150.  *
  151.  *    Report errors as needed.
  152.  *
  153.  ************************************************/
  154.  
  155. Error(char *msg)
  156. {
  157.     SysBeep(1);
  158.     ParamText("\pError:",c2pstr(msg),nil,nil);    /* oops da baby */
  159.     Alert(128,nil);
  160. }
  161.  
  162.  
  163. /************************************************
  164.  *
  165.  *    Progress proc called from the Image Compression manager.
  166.  *
  167.  ************************************************/
  168.  
  169.  
  170. pascal OSErr
  171. Progress(short progressMsg,Fixed progressPercent,long refcon)
  172. {
  173.     OSErr  result = noErr;
  174.     short kind;
  175.     Handle h;
  176.     Rect r;
  177.     CGrafPtr savePort,wmgPort;
  178.     GDHandle saveGD;
  179.     static DialogPtr progressDialog = 0;
  180.     KeyMap    keys;
  181.  
  182.     switch (progressMsg) {
  183.     
  184.     case codecProgressOpen:
  185.     
  186.         progressDialog = 0;
  187.         GetGWorld(&savePort,&saveGD);
  188.         GetCWMgrPort(&wmgPort);
  189.         SetGWorld(wmgPort,nil);
  190.         if ( refcon != -1 && (progressDialog = GetNewDialog(5002, 0, (WindowPtr)-1)) != nil ) { 
  191.             ShowWindow((WindowPtr)progressDialog);
  192.             SetGWorld((CGrafPtr)progressDialog,nil);
  193.             DrawDialog(progressDialog);
  194.             GetDItem(progressDialog, 1, &kind, &h, &r);
  195.             InsetRect(&r, -1, -1);
  196.             FrameRect(&r);
  197.             InsetRect(&r, 1, 1);
  198.         }
  199.         SetGWorld(savePort,saveGD);
  200.         break;
  201.  
  202.     case codecProgressUpdatePercent:
  203.     
  204.         if ( progressDialog ) {
  205.             GetGWorld(&savePort,&saveGD);
  206.             SetGWorld((CGrafPtr)progressDialog,nil);
  207.             GetDItem(progressDialog, 1, &kind, &h, &r);
  208.             
  209.             FillRect(&r,qd.gray);
  210.             r.right = r.left + FixRound( FixMul(progressPercent, FixRatio(r.right-r.left,1)));
  211.             PaintRect(&r);
  212.             SetGWorld(savePort,saveGD);
  213.         }    
  214.  
  215.         /* check for command period - not the best way, but it works */
  216.  
  217.         GetKeys(keys);
  218.         if ( (keys[1] & 0x8000) && ((0x800000 & keys[1]) || (0x2000000 & keys[1])  ) )
  219.             result = codecAbortErr;
  220.         break;
  221.     
  222.     case codecProgressClose:
  223.     
  224.         if ( progressDialog )
  225.             DisposDialog(progressDialog);
  226.         progressDialog = 0;
  227.         break;
  228.     }
  229.     return(result);
  230. }
  231.  
  232.     
  233. /************************************************
  234.  *
  235.  *    Allow the user to specify compression and an output file, and then
  236.  *  compress the picture and save the result in that file.
  237.  *
  238.  ************************************************/
  239.  
  240.  
  241. DoCompression(CWindowPtr    window)
  242. {
  243.     Str32        newName;
  244.  
  245.     /* StdFile stuff */
  246.     
  247.     CGrafPtr    savePort;
  248.     GDHandle    saveGD;
  249.  
  250.     /* for sepecifying compression */
  251.     
  252.     Rect        pictureFrame;
  253.     OSErr        result;
  254.     Boolean        inPlace;
  255.     Point        where;
  256.     ImageDescriptionHandle desc = nil;
  257.     Ptr    data = nil;
  258.     long    cdsize;
  259.     ProgressProcRecord    *progP,progressRec;
  260.     Str255        buf;
  261.         
  262.     progressRec.progressProc = Progress;
  263.     progressRec.progressRefCon = 0;
  264.     progP = &progressRec;
  265.         
  266.  
  267.     if ( window == nil )
  268.         return;
  269.     pictureFrame = ((CGrafPtr)window)->portRect;
  270.  
  271.     /************************************************
  272.      *
  273.      *        Ask how the user wants to compress it.
  274.      *
  275.      ************************************************/
  276.  
  277.     SetCursor(&qd.arrow);
  278.     if (SCSetTestImagePixMap(gSCComponent,gworld->portPixMap,&gworld->portRect,0))
  279.         goto done;
  280.     where.h = where.v = -2;        // position dialog on the best device
  281.     if (SCGetCompression(gSCComponent,&gSCParams,where))
  282.         goto done;
  283.     
  284.     /************************************************
  285.      *
  286.      *        Ask her for the name of the new file.
  287.      *
  288.      ************************************************/
  289.     
  290.  
  291.     SetCursor(*gWatch);
  292.  
  293.  
  294.     if ( (result=GetMaxCompressionSize(gworld->portPixMap,&gworld->portRect,
  295.             gSCParams.depth,gSCParams.spatialQuality,gSCParams.theCodecType,
  296.             gSCParams.theCodec,&cdsize)) != noErr ) {
  297.         Error("getting max comp size");
  298.         goto done;
  299.     }        
  300.     if ( (data=NewPtr(cdsize)) == nil ) {
  301.         Error("no mem for picture");
  302.         goto done;
  303.     }        
  304.     desc = (ImageDescriptionHandle)NewHandle(sizeof(ImageDescription));
  305.     if ( desc == nil ) {
  306.         DisposPtr(data);
  307.         Error("no mem for picture");
  308.         goto done;
  309.     }        
  310.         
  311.     if ( (result=FCompressImage(gworld->portPixMap,&gworld->portRect,
  312.                 gSCParams.depth,gSCParams.spatialQuality,gSCParams.theCodecType,
  313.                 gSCParams.theCodec,nil,0,0,nil,progP,
  314.                  desc,data)) != noErr   ) {
  315.          DisposPtr(data);
  316.          DisposHandle((Handle)desc);
  317.          if ( result != codecAbortErr ) 
  318.             Error("compressing picture");
  319.         goto done;
  320.     }    
  321.     
  322.     
  323.     NumToString((*desc)->dataSize,buf);
  324.     ParamText("\pCompressed to ",buf,"\pBytes",nil);
  325.     Alert(128,nil);
  326.     GetGWorld(&savePort,&saveGD);
  327.     SetGWorld(compgworld,nil);
  328.     
  329.     if ( (result=DecompressImage(data,desc,compgworld->portPixMap,
  330.                     &gworld->portRect,&compgworld->portRect,ditherCopy,nil)) != noErr ) {
  331.          DisposPtr(data);
  332.          DisposHandle((Handle)desc);
  333.         Error("compressing picture");
  334.         goto done;
  335.     }    
  336.      DisposPtr(data);
  337.      DisposHandle((Handle)desc);
  338.      SetGWorld(gCompWindow,nil);
  339.      InvalRect(&gCompWindow->portRect);
  340.     SetGWorld(savePort,saveGD);
  341. done:
  342.     gDidError = false;
  343.     SetCursor(&qd.arrow);
  344.     
  345.     return(result);
  346. }
  347.  
  348.     
  349.     
  350.     
  351.  
  352.  
  353. DoError()
  354. {
  355.     CGrafPtr    savePort;
  356.     GDHandle    saveGD;
  357.     short        i;
  358.     RGBColor    opColor;
  359.     
  360.     
  361.     GetGWorld(&savePort,&saveGD);
  362.     SetGWorld(compgworld,nil);
  363.     if ( !gDidError ) {
  364.         gDidError = true;
  365.         opColor.red = opColor.green = opColor.blue = 0;
  366.         OpColor(&opColor);
  367.         CopyBits((BitMap *)*gworld->portPixMap,(BitMap *)*((CGrafPtr)compgworld)->portPixMap,
  368.             &gworld->portRect,&compgworld->portRect,subPin,nil);
  369.     }
  370.     opColor.red = opColor.green = opColor.blue = 0xffff;
  371.     OpColor(&opColor);
  372.     CopyBits((BitMap *)*compgworld->portPixMap,(BitMap *)*((CGrafPtr)compgworld)->portPixMap,
  373.         &compgworld->portRect,&compgworld->portRect,addPin,nil);
  374.      SetGWorld(gCompWindow,nil);
  375.      InvalRect(&gCompWindow->portRect);
  376.     SetGWorld(savePort,saveGD);
  377. }
  378.  
  379.  
  380.     
  381. /************************************************
  382.  *
  383.  *    Massage a rectangle to fit on a device's screen.
  384.  *
  385.  ************************************************/
  386.  
  387.  
  388. FitRect(Rect *rect,short w,short h)
  389. {
  390.     short     n;
  391.     Rect    dRect;
  392.     GDHandle    gd;
  393.     
  394. //    dRect = *rect;
  395.     gd = GetGDevice();
  396.     dRect =(*gd)->gdRect;
  397.     dRect.top += 40;                                /* make way for title bar */
  398.     InsetRect(&dRect,16,16);
  399.  
  400.     if ( w < (dRect.right-dRect.left) &&  h < (dRect.bottom-dRect.top) ) {
  401.          dRect.right = dRect.left + w;
  402.          dRect.bottom = dRect.top + h;
  403.     } else if ( gFitToWindow ) {
  404.         n = dRect.top + ((dRect.right -dRect.left) * h)/w;
  405.         if ( n > dRect.bottom )
  406.             dRect.right = dRect.left +((dRect.bottom -dRect.top) * w)/h;
  407.         else 
  408.             dRect.bottom = n;
  409.     }
  410.     *rect = dRect;
  411.  
  412. }
  413.  
  414.  
  415.     
  416. /************************************************
  417.  *
  418.  *    Ask the user for a pict file to open and open it.
  419.  *
  420.  ************************************************/
  421.  
  422.  
  423. DoOpen(FSSpec *fsp)
  424. {
  425.     OpenCPicParams    originalPicHeader;
  426.     SFTypeList     types = { 'PICT',0 };
  427.     OSErr        result = noErr;
  428.     CTabHandle    clut;
  429.     long        size;
  430.     CGrafPtr    savePort;
  431.     GDHandle    saveGD;
  432.     Rect        rect;
  433.     
  434.     
  435.     if ( fsp == nil ) {
  436.         if ( gHasNewStdFile )
  437.             StandardGetFile(nil,1,types,&gOriginalSFR);
  438.         else {
  439.             SFReply        osfr;
  440.             Point    pt = {100,100};
  441.             
  442.             SFGetFile(pt,(ConstStr255Param)"",nil,1,types,nil,&osfr);
  443.             gOriginalSFR.sfGood = osfr.good;
  444.             gOriginalSFR.sfReplacing = osfr.copy;
  445.             gOriginalSFR.sfType = osfr.fType;
  446.             if ( osfr.good ) 
  447.                 FSMakeFSSpec(osfr.vRefNum,0L,osfr.fName,&gOriginalSFR.sfFile);
  448.         }
  449.         if ( !gOriginalSFR.sfGood  ) {
  450.             return(0);
  451.         }
  452.     } else {
  453.         gOriginalSFR.sfFile = *fsp;
  454.     }
  455.         
  456.     SetCursor(*gWatch);
  457.     if ((result=FSpOpenDF(&gOriginalSFR.sfFile,fsRdPerm,&gOriginalFile)) != noErr ) {
  458.         goto done;
  459.     }
  460.  
  461.     
  462.     
  463.     /************************************************
  464.      *
  465.      *    Get the picture frame, to see how big of a window to make.
  466.      *
  467.      ************************************************/
  468.  
  469.     if ( (result=GetPictureFileHeader(gOriginalFile,&gOriginalPicFrame,&originalPicHeader)) != noErr ) {
  470.         FSClose(gOriginalFile);
  471.         goto done;
  472.     }
  473.  
  474.  
  475.     /************************************************
  476.      *
  477.      *    Figure out the best screen to show the picture on, and if
  478.      *    it doesn't fit, then scale it to fit while maintaining aspect ratio.
  479.      *
  480.      ************************************************/
  481.     
  482.     
  483.     SetRect(&gZoomedPictureFrame,-32767,-32767,32767,32767);
  484.     FitRect(&gZoomedPictureFrame,gOriginalPicFrame.right-gOriginalPicFrame.left,
  485.         gOriginalPicFrame.bottom-gOriginalPicFrame.top);
  486.     gZoomed = false;
  487.  
  488.     /************************************************
  489.      *
  490.      *    Create a window for the picture, and set our port to it.
  491.      *
  492.      ************************************************/
  493.  
  494.     if ( (gOrigWindow = (CWindowPtr)NewCWindow(nil,&gZoomedPictureFrame,gOriginalSFR.sfFile.name,true,
  495.                 zoomDocProc,(WindowPtr)-1,true,0)) == nil ) {
  496.         FSClose(gOriginalFile);
  497.         result = -1;
  498.         goto done;
  499.     }
  500.     rect = gZoomedPictureFrame;
  501. //    OffsetRect(&rect,(rect.right-rect.left)+10,0);
  502.     OffsetRect(&rect,50,50);
  503.     if ( (gCompWindow = (CWindowPtr)NewCWindow(nil,&rect,"\pCompressed",true,
  504.                 zoomDocProc,(WindowPtr)-1,true,0)) == nil ) {
  505.         FSClose(gOriginalFile);
  506.         result = -1;
  507.         goto done;
  508.     }
  509.     SetPort((GrafPtr)gActiveWindow);
  510.     if ( GetEOF(gOriginalFile,&size) == noErr ) {
  511.         size -= 512;
  512.         if ( gOriginalPicture = (PicHandle)NewHandle(size) ) {
  513.             HLock((Handle)gOriginalPicture);
  514.             SetFPos(gOriginalFile,fsFromStart,512);
  515.             FSRead(gOriginalFile,&size,*(Handle)gOriginalPicture);
  516.             HUnlock((Handle)gOriginalPicture);
  517.             HPurge((Handle)gOriginalPicture);
  518.         }
  519.     }    
  520.     rect = gZoomedPictureFrame;    
  521.     OffsetRect(&rect,-rect.left,-rect.top);
  522.     
  523.     if ( (result=NewGWorld(&gworld,gDepth,&rect,nil,nil,0)) != 0 ) {
  524.         if ( (result=NewGWorld(&gworld,gDepth,&rect,nil,nil,8)) != 0 ) {
  525.             Error("No mem for gworld");
  526.             goto done;
  527.         }
  528.     }
  529.     if ( (result=NewGWorld(&compgworld,gDepth,&rect,nil,nil,0)) != 0 ) {
  530.         if ( (result=NewGWorld(&compgworld,gDepth,&rect,nil,nil,8)) != 0 ) {
  531.             Error("No mem for gworld");
  532.             DisposeGWorld(gworld);
  533.             gworld = nil;
  534.             goto done;
  535.         }
  536.     }
  537.     GetGWorld(&savePort,&saveGD);
  538.     SetGWorld(gworld,nil);
  539.     if ( gOriginalPicture && *gOriginalPicture) {
  540.         HNoPurge((Handle)gOriginalPicture);
  541.         if ( (result=DrawTrimmedPicture(gOriginalPicture,&rect,nil,gDitherFlag,nil)) != noErr  && result != codecAbortErr) {
  542.             SysBeep(1);
  543.         }
  544.         HPurge((Handle)gOriginalPicture);
  545.     }else {
  546.         if ( (result=DrawTrimmedPictureFile(gOriginalFile,&rect,nil,gDitherFlag,nil)) != noErr  && result != codecAbortErr) {
  547.             SysBeep(1);
  548.         }
  549.     }
  550.     
  551.     SetGWorld(compgworld,nil);
  552.     EraseRect(&compgworld->portRect);
  553.     SetGWorld(savePort,saveGD);
  554.     SetWRefCon((WindowPtr)gCompWindow,(long)compgworld);
  555.     SetWRefCon((WindowPtr)gOrigWindow,(long)gworld);
  556.     FSClose(gOriginalFile);
  557.     if ( gOriginalPicture ) {
  558.         DisposHandle((Handle)gOriginalPicture);
  559.         gOriginalPicture = nil;
  560.     }
  561. done:
  562.     SetCursor(&qd.arrow);
  563.     if ( result ) {
  564.         SysBeep(1);
  565.     }
  566.  
  567. }
  568.  
  569.     
  570. /************************************************
  571.  *
  572.  *    Close the window and the file and get rid of any temporary file we may have.
  573.  *
  574.  ************************************************/
  575.  
  576.  
  577. DoClose(CWindowPtr w)
  578. {
  579.     GWorldPtr    gw;
  580.     
  581.     if ( w == nil )
  582.         return;
  583.         
  584.     gw = (GWorldPtr)GetWRefCon((WindowPtr)w);
  585.     if ( gw ) {
  586.         DisposeGWorld(gw);
  587.     }
  588.     CloseWindow((WindowPtr)w);
  589.     if  ( w == gActiveWindow ) {
  590.         gActiveWindow = nil;
  591.     }
  592.     if ( w == gOrigWindow )    
  593.         gOrigWindow = nil;
  594.     if ( w == gCompWindow )    
  595.         gCompWindow = nil;
  596.     return(0);
  597. }
  598.  
  599. DoSave(CWindowPtr w) 
  600. {
  601.  
  602.     long    l,k;
  603.     OSErr    e = 0;
  604.     PicHandle    pict = nil;
  605.     long    i;
  606.     short    f = 0;
  607.     static Str255    name = "\pPICT";
  608.     StandardFileReply     sfr;
  609.     CGrafPtr    savePort;
  610.     GDHandle    saveGD;
  611.     GWorldPtr    gw;
  612.     long zero = 0;
  613.     
  614.         
  615.     gw = (GWorldPtr)GetWRefCon((WindowPtr)w);
  616.     if ( gw == nil )
  617.         return;
  618.     StandardPutFile((ConstStr255Param)"",name,&sfr);
  619.     if ( sfr.sfGood ) { 
  620.         GetGWorld(&savePort,&saveGD);
  621.         SetGWorld(gw,nil);
  622.         pict = OpenPicture(&gw->portRect);
  623.         ClipRect(&gw->portRect);
  624.         CopyBits((BitMap *)*gw->portPixMap,(BitMap *)*((CGrafPtr)gw)->portPixMap,
  625.             &gw->portRect,&gw->portRect,ditherCopy,nil);
  626.         ClosePicture();
  627.         SetGWorld(savePort,saveGD);
  628.         if ( (l=GetHandleSize((Handle)pict)) <= 10 ) {
  629.             DisposHandle((Handle)pict);
  630.             Error("Making Pict");
  631.             return;
  632.         }
  633.         FSpDelete(&sfr.sfFile);
  634.         if ( (e=FSpCreate(&sfr.sfFile,'ppxi','PICT',0)) != noErr  ) {
  635.             Error("Creating file");
  636.             return;
  637.         }
  638.         if ( (e=FSpOpenDF(&sfr.sfFile,fsRdWrPerm,&f)) != noErr ) {
  639.             Error("Opening file");
  640.             goto bail;
  641.         }
  642.         SetFPos(f,fsFromStart,0);
  643.         k = 4;
  644.         for ( i=0; i < 512/4; i++ ) {
  645.             if ( (e=FSWrite(f,&k,(char *)&zero)) != noErr ) {
  646.                 Error("Writing file");
  647.                 goto bail;
  648.             }
  649.         }
  650.         HLock((Handle)pict);
  651.         if ( (e=FSWrite(f,&l,(Ptr)*pict)) != noErr)  {
  652.             Error("Writing file");
  653.             goto bail;
  654.         }
  655.         SetEOF(f,l+512);
  656.  
  657. bail:    
  658.         if ( pict )    
  659.             DisposHandle((Handle)pict);
  660.         if ( f ) 
  661.             FSClose(f);
  662.         if ( e )
  663.             FSpDelete(&sfr.sfFile);
  664.         FlushVol(nil,sfr.sfFile.vRefNum);
  665.     }
  666. }
  667.  
  668.  
  669.  
  670.     
  671. /************************************************
  672.  *
  673.  *    Fix the menu hiliting based on conditions.
  674.  *
  675.  ************************************************/
  676.  
  677.  
  678. FixMenus()
  679. {
  680.     long    offset;
  681.     
  682.     if ( gActiveWindow == nil ) {
  683.         EnableItem(gMenus[1],M_OPEN);
  684.         DisableItem(gMenus[1],M_CLOSE);
  685.         DisableItem(gMenus[1],M_SAVE);
  686.         DisableItem(gMenus[2],M_COPY);
  687.     } else  { 
  688.         DisableItem(gMenus[1],M_OPEN);
  689.         EnableItem(gMenus[1],M_CLOSE);
  690.         EnableItem(gMenus[1],M_SAVE);
  691. //        EnableItem(gMenus[2],M_COPY);
  692.     }
  693.     
  694.     if ( gOrigWindow != nil && gCompWindow != nil ) 
  695.         EnableItem(gMenus[1],M_COMP);
  696.     else
  697.         DisableItem(gMenus[1],M_COMP);
  698.     EnableItem(gMenus[2],M_FIT);
  699. //    if ( GetScrap(nil,'PICT',&offset) > 0  ) 
  700. //        EnableItem(gMenus[2],M_PASTE);
  701. //    else
  702.         DisableItem(gMenus[2],M_PASTE);
  703. }
  704.  
  705.     
  706. /************************************************
  707.  *
  708.  *    Paste the PICT from the clip board into a new window, making a temporary
  709.  *  file for it.
  710.  *
  711.  ************************************************/
  712.  
  713.  
  714. DoPaste()
  715. {
  716. }
  717.  
  718.     
  719. /************************************************
  720.  *
  721.  *    Copy the open PICT onto the clip board.
  722.  *
  723.  ************************************************/
  724.  
  725.  
  726. DoCopy(CWindowPtr w)
  727. {
  728.  
  729. }
  730.     
  731.  
  732. /************************************************
  733.  *
  734.  *    Update the window from the PICT file.
  735.  *
  736.  ************************************************/
  737.  
  738. DoUpdate(CWindowPtr w)
  739. {
  740.     CGrafPtr        savePort;
  741.     GDHandle        saveGD;
  742.     Rect        srcRect;
  743.     OSErr        result;
  744.     GWorldPtr    gw;
  745.  
  746.  
  747.     if ( w == nil ) 
  748.         return;
  749.     SetCursor(*gWatch);
  750.     GetGWorld(&savePort,&saveGD);
  751.     SetGWorld((CGrafPtr)w,nil);
  752.     
  753.     gw = (GWorldPtr)GetWRefCon((WindowPtr)w);
  754.     if ( gw  ) { 
  755.         srcRect = gw->portRect;
  756.         BeginUpdate((WindowPtr)w);
  757.         CopyBits((BitMap *)*gw->portPixMap,(BitMap *)*((CGrafPtr)w)->portPixMap,
  758.             &srcRect,&((CGrafPtr)w)->portRect,ditherCopy,nil);
  759.     
  760.         EndUpdate((WindowPtr)w);
  761.     }
  762.     SetGWorld(savePort,saveGD);
  763.     SetCursor(&qd.arrow);
  764.  
  765. }
  766.  
  767.     
  768. /************************************************
  769.  *
  770.  *    Resize the window and remember the old size, and force it to update.
  771.  *
  772.  ************************************************/
  773.  
  774.  
  775. DoSizeWindow(CWindowPtr wind,short h,short v,Boolean fup)
  776. {
  777.     GrafPtr    savePort;
  778.  
  779.     gZoomed = false;
  780.     GetPort(&savePort);
  781.     SetPort((GrafPtr)wind);
  782.     SizeWindow((WindowPtr)wind,h,v,false);
  783.     gZoomedPictureFrame = ((CGrafPtr)wind)->portRect;
  784.     LocalToGlobal((Point *)&gZoomedPictureFrame.top);
  785.     LocalToGlobal((Point *)&gZoomedPictureFrame.bottom);
  786.     if ( fup )
  787.         InvalRect(&((CWindowPtr)wind)->portRect);
  788.     SetPort(savePort);
  789. }
  790.  
  791.     
  792. /************************************************
  793.  *
  794.  *    Handle clicks in the window zoom box.
  795.  *
  796.  ************************************************/
  797.  
  798. DoZoom(WindowPtr wind)
  799. {
  800.     Rect         rect;
  801.     Rect         saveRect;
  802.     GrafPtr        savePort;
  803.     KeyMap        keys;
  804.     Boolean        doOriginal;
  805.     
  806.     GetPort(&savePort);
  807.     SetPort((GrafPtr)wind);
  808.  
  809.     GetKeys(keys);
  810.     doOriginal = (( keys[1] & 4 ) != 0);        /* option key */
  811.  
  812.     if ( doOriginal ) {
  813.         gZoomed = false;
  814.         FitRect(&gZoomedPictureFrame,gOriginalPicFrame.right-gOriginalPicFrame.left,
  815.             gOriginalPicFrame.bottom-gOriginalPicFrame.top);
  816.     } else {
  817.         if ( gZoomed ) {
  818.             gZoomed = false;
  819.         } else {
  820.             rect = gZoomedPictureFrame;
  821.             rect.top += 16;                        /* make way for title bar */
  822.             InsetRect(&rect,16,16);
  823.             ShowHide(wind,0);
  824.             MoveWindow(wind,rect.left,rect.top,true);
  825.             saveRect = gZoomedPictureFrame;
  826.             DoSizeWindow((CWindowPtr)wind,rect.right-rect.left,rect.bottom-rect.top,true);
  827.             gZoomedPictureFrame = saveRect;
  828.             gZoomed = true;
  829.             goto done;
  830.         }
  831.     }
  832.     ShowHide(wind,0);
  833.     MoveWindow(wind,gZoomedPictureFrame.left,gZoomedPictureFrame.top,true);
  834.     DoSizeWindow((CWindowPtr)wind,gZoomedPictureFrame.right-gZoomedPictureFrame.left,
  835.         gZoomedPictureFrame.bottom-gZoomedPictureFrame.top,true);
  836. done:
  837.     ShowHide(wind,1);
  838.     SetPort(savePort);
  839. }
  840.  
  841.  
  842.  
  843. /************************************************
  844.  *
  845.  *    Grow the window (constrain aspect ratio if option key pressed.
  846.  *
  847.  ************************************************/
  848.  
  849.  
  850. DoGrow(wind,where)
  851. WindowPtr wind;
  852. Point *where;
  853. {
  854.     unsigned long     size;
  855.     Rect            sizeRect;
  856.     GrafPtr            savePort;
  857.     short            h,v;
  858.     short            height = gOriginalPicFrame.bottom - gOriginalPicFrame.top;
  859.     short            width = gOriginalPicFrame.right - gOriginalPicFrame.left;
  860.     KeyMap            keys;
  861.     short            minH = 128,minV = 128,maxH = 4096,maxV = 4096;
  862.     Boolean            maintainAspect;
  863.     Rect            rect;
  864.     
  865.     
  866.     GetPort(&savePort);
  867.     SetPort((GrafPtr)wind);
  868.     GetKeys(keys);
  869.     maintainAspect = (( keys[1] & 4 ) != 0);
  870.     if ( maintainAspect ) {
  871.         Rect    oRect;
  872.         
  873.         rect = ((CGrafPtr)wind)->portRect;
  874.         LocalToGlobal((Point *)&rect.top);
  875.         LocalToGlobal((Point *)&rect.bottom);
  876.         oRect = rect;
  877.         if ( width > 2048 || height > 2048 )
  878.             FitRect(&rect,width,height);
  879.         else if ( width < 1024 && height < 1024 )
  880.             FitRect(&rect,width<<4,height<<4);
  881.         else
  882.             FitRect(&rect,width<<2,height<<2);
  883.         maxH = (rect.right - rect.left);
  884.         maxV = (rect.bottom - rect.top);
  885.         if ( maxV < minV || maxH < minH ) {
  886.             minV = maxV;
  887.             minH = maxH;
  888.         }
  889.         maxV = (maxH * height)/width;
  890.         minV = (minH * height)/width;
  891.     }
  892.     SetRect(&sizeRect,minH,minV,maxH,maxV);
  893.     if ( (size = GrowWindow(wind,*where,&sizeRect))  != 0 ) {
  894.         h = size & 0xffff;
  895.         v = size >> 16;
  896.         if ( maintainAspect )
  897.             v = (h * height)/width;
  898.         DoSizeWindow((CWindowPtr)wind,h,v,true);
  899.     }
  900.     SetPort(savePort);
  901.     FixMenus();
  902. }
  903.  
  904. /************************************************
  905.  *
  906.  *    Handle menu commands.
  907.  *
  908.  ************************************************/
  909.  
  910. DoCommand(long    mResult)
  911. {
  912.     short         theMenu, theItem;
  913.     GrafPtr    savePort;
  914.     Str255        daName;
  915.  
  916.     theItem = ((mResult) & 0xFFFF);
  917.     theMenu = (((mResult) >> 16) & 0xFFFF);        /* This is the resource ID */
  918.  
  919.     switch (theMenu) {
  920.     case appleMenuID:
  921.         if ( theItem != 1 ) {
  922.             GetItem(gMenus[0], theItem, daName);
  923.             GetPort(&savePort);
  924.             (void) OpenDeskAcc(daName);
  925.             SetPort(savePort);
  926.         }
  927.         break;
  928.  
  929.     case fileMenuID:
  930.         {
  931.             switch (theItem) {
  932.             case M_OPEN:
  933.                 DoOpen(nil);
  934.                 break;
  935.             case M_CLOSE:
  936.                 DoClose(gActiveWindow);
  937.                 break;
  938.             case M_COMP:
  939.                 DoCompression(gActiveWindow);
  940.                 break;
  941.             case M_SAVE:
  942.                 DoSave(gActiveWindow);
  943.                 break;
  944.             case M_QUIT:
  945.                 gExitFlag = true;            /* Request exit */
  946.                 break;
  947.             }
  948.             FixMenus();
  949.         }
  950.         break;
  951.     case editMenuID:
  952.         if ( !SystemEdit(theItem-1) ) {
  953.             switch ( theItem ) {
  954.             case M_COPY:
  955.                 DoCopy(gActiveWindow);
  956.                 break;
  957.             case M_PASTE:
  958.                 DoPaste();
  959.                 break;
  960.             case M_FIT:
  961.                 DoError();
  962.                 break;
  963.             default:
  964.                 break;
  965.             }
  966.         }
  967.         FixMenus();
  968.         break;
  969.     default:
  970.         break;
  971.     }
  972.     HiliteMenu(0);
  973. }
  974.  
  975. extern pascal ComponentResult DRAWTEXTCODEC(ComponentParameters *params,Handle storage);
  976.  
  977. /************************************************
  978.  *
  979.  *    Our program.
  980.  *
  981.  ************************************************/
  982.  
  983. main()
  984. {
  985.     GrafPtr    savePort;
  986.     EventRecord myEvent;
  987.     Rect        dragRect;
  988.     WindowPtr    whichWindow;
  989.     long        resp;
  990.  
  991.  
  992.     if ( Initialize() ) {
  993.         SysBeep(1);
  994.         ExitToShell();
  995.     }
  996.     
  997.     if ( Gestalt(gestaltSystemVersion, &resp) != noErr || resp < 0x700 ) {
  998.         gSevenOh = false;
  999.     } else {
  1000.         gSevenOh = true;
  1001.     }
  1002.     
  1003.     /*    Check to make sure the image compression manager is installed. */
  1004.  
  1005.     if ( Gestalt(gestaltCompressionMgr, &resp) != noErr || resp < 15 ) {
  1006.         SysBeep(1);
  1007.         ExitToShell();
  1008.     }
  1009.  
  1010.     /*    Check to see if new style standard file is around. */
  1011.  
  1012.     gHasNewStdFile = ( Gestalt(gestaltStandardFileAttr,&resp) == 0 );
  1013.  
  1014.     /*    Install and open the standard compression component. */
  1015.  
  1016.     gSCComponent = OpenStdCompression();
  1017.     if (!gSCComponent) {
  1018.         SysBeep(1);
  1019.         ExitToShell();
  1020.     }
  1021.     
  1022.     /*    Set up the first defaults for compression dialog. */
  1023.     
  1024.     gSCParams.flags = scListEveryCodec;
  1025.     gSCParams.theCodecType = 'dtxt';
  1026.     gSCParams.theCodec = anyCodec;
  1027.     gSCParams.spatialQuality = codecNormalQuality;
  1028.     gSCParams.temporalQuality = 0;
  1029.     gSCParams.depth = 32;
  1030.  
  1031.  
  1032.  
  1033.     /* install CoDec to test */
  1034.  
  1035.     {
  1036.         ComponentDescription td;
  1037.     
  1038.         Handle    cname = NewHandle(11);
  1039.         Handle    dname = NewHandle(11);
  1040.     
  1041.         td.componentType = 'imco';
  1042.         td.componentSubType = 'dtxt';
  1043.         td.componentManufacturer = 'mark';
  1044.         td.componentFlags = codecInfoDoes1;
  1045.         td.componentFlagsMask = 0;
  1046.         
  1047.         
  1048.         BlockMove(CODEC_NAME,*cname,sizeof(CODEC_NAME));
  1049.         RegisterComponent(&td,DRAWTEXTCODEC, 0,cname,nil, nil);
  1050.             
  1051.         td.componentType = 'imdc';
  1052.         td.componentFlags = codecInfoDoes1;
  1053.         BlockMove(CODEC_NAME,*dname,sizeof(CODEC_NAME));
  1054.         RegisterComponent(&td,DRAWTEXTCODEC, 0,dname,nil, nil);
  1055.     }
  1056.  
  1057.  
  1058.     FixMenus();
  1059.     DoOpen(nil);
  1060.     
  1061.     while (!gExitFlag ) {
  1062.         
  1063.         if ( WaitNextEvent( everyEvent, &myEvent, 1, nil) == 0 )
  1064.             continue;
  1065.         
  1066.         switch (myEvent.what) {
  1067.         case mouseDown:
  1068.             switch ((short)FindWindow(myEvent.where, &whichWindow)) {
  1069.             case inSysWindow:
  1070.                 SystemClick(&myEvent, whichWindow);
  1071.                 FixMenus();
  1072.                 break;
  1073.  
  1074.             case inMenuBar:
  1075.                 DoCommand(MenuSelect(myEvent.where));
  1076.                 break;
  1077.  
  1078.             case inDrag:
  1079.                 GetPort(&savePort);
  1080.                 SetPort((GrafPtr)whichWindow);
  1081.                 SetRect(&dragRect, 4, 20 + 4, qd.screenBits.bounds.right-4, qd.screenBits.bounds.bottom-4);
  1082.                 DragWindow(whichWindow, myEvent.where, &dragRect);
  1083.                 gZoomedPictureFrame = ((CGrafPtr)whichWindow)->portRect;
  1084.                 LocalToGlobal((Point *)&gZoomedPictureFrame.top);
  1085.                 LocalToGlobal((Point *)&gZoomedPictureFrame.bottom);
  1086.                 SetPort(savePort);
  1087.                 break;
  1088.  
  1089.             case inGrow:
  1090.                 DoGrow(whichWindow,&myEvent.where);
  1091.                 break;
  1092.  
  1093.             case inGoAway:
  1094.                 if ( TrackGoAway(whichWindow,myEvent.where)  ) 
  1095.                     DoClose((CWindowPtr)whichWindow);
  1096.                 FixMenus();
  1097.                 break;
  1098.  
  1099.             case inZoomIn:
  1100.                 if ( TrackBox(whichWindow,myEvent.where,inZoomIn)  ) 
  1101.                     DoZoom(whichWindow);
  1102.                 break;
  1103.  
  1104.             case inZoomOut:
  1105.                 if ( TrackBox(whichWindow,myEvent.where,inZoomOut)  ) 
  1106.                     DoZoom(whichWindow);
  1107.                 break;
  1108.  
  1109.             case inContent:
  1110.                 if (whichWindow != FrontWindow()) 
  1111.                     SelectWindow(whichWindow);
  1112.                 break;
  1113.             
  1114.             default:
  1115.                 break;
  1116.             }
  1117.             break;
  1118.  
  1119.         case keyDown:
  1120.             if ( ((myEvent.modifiers & cmdKey) != 0) ) {
  1121.                 char key = myEvent.message & charCodeMask;
  1122.                 DoCommand(MenuKey(key));
  1123.             }
  1124.             break;
  1125.         
  1126.         case updateEvt :
  1127.  
  1128.             DoUpdate((CWindowPtr)myEvent.message);
  1129.             break;
  1130.         
  1131.         case activateEvt:
  1132.                 
  1133.             whichWindow=(WindowPtr)myEvent.message;
  1134.             if ( (myEvent.modifiers & activeFlag) == 0 ) 
  1135.                 gActiveWindow = nil;
  1136.              else 
  1137.                 gActiveWindow = (CWindowPtr)whichWindow;
  1138.             FixMenus();
  1139.             break;
  1140.     
  1141.         default:
  1142.             break;
  1143.             
  1144.         }
  1145.     }
  1146.     DoClose(gActiveWindow);
  1147.     CloseComponent(gSCComponent);
  1148.     ExitToShell();
  1149. }
  1150.