home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Pascal / Snippets / PNL Libraries / MyOOAbout.p < prev    next >
Encoding:
Text File  |  1997-03-25  |  10.8 KB  |  452 lines  |  [TEXT/CWIE]

  1. unit MyOOAbout;
  2.  
  3. interface
  4.  
  5.     uses
  6.         Types;
  7.  
  8.     type
  9.         GetAboutStringProc = function (index: integer): Str255;
  10.     
  11.     const
  12.         kAboutStringLongVersion = 0;
  13.         kAboutStringShortVersion = 1;
  14.         kAboutStringName = 2;
  15.         kAboutStringThanks = 3;
  16.         
  17.     procedure StartupAbout;
  18.     procedure ConfigureAbout( get_about_string_proc: GetAboutStringProc );
  19.     procedure UpdateAboutBox;
  20.     procedure OpenAboutBox;
  21.     procedure CloseAboutBox;
  22.     function DefaultGetAboutString (index: integer): Str255;
  23.  
  24. implementation
  25.  
  26.     uses
  27.         Memory, Fonts, TextEdit, Resources, Icons,Quickdraw, Windows, TextUtils, Dialogs, AppleEvents,
  28.         Events, 
  29.         MyMenus, MyDialogs, MyStrings, MyVersionResource, MySystemGlobals, MyWindows, MyAssertions,
  30.         MyFMenus, AERegistry, MyAEUtils, AEObjects, MyStrh, MyUtils, MyTypes, MyStartup, MyOOMenus, 
  31.         MyRecordedMenuCommands, MyOOMainLoop, MyLowLevel, MyResources, MySystemGlobals, MyMathUtils, 
  32.         MyRegions, MyProcesses, MyErrors, MyInternetConfig, 
  33.         BaseGlobals;
  34.  
  35.     const
  36.         agwtAbout = '•About';
  37.  
  38.     const
  39.         about_id = 928;
  40.         thanks_strh_id = 929;
  41.         about_error_strh_id = 930;
  42.         kThanksURL = 'thank:';
  43.         kRegisterURL = 'register:';
  44.         kICONStyledString = 'ICON:';
  45.  
  46.     type
  47.         AboutObject = object(DObject)
  48.                 procedure Create (id: integer);
  49.                 override;
  50.                 procedure DoItem (item: integer);
  51.                 override;
  52.                 procedure DrawUserItem( item: integer );
  53.                 override;
  54.                 procedure DrawDisplayItem( item: integer; selected: boolean );
  55.                 function TrackGroup( group:integer ):boolean;
  56.             end;
  57.             
  58.     type
  59.         AboutDataEntry = record
  60.             display: Str255;
  61.             group: integer;
  62.             url: Str255;
  63.         end;
  64.  
  65.     const
  66.         kNoGroup = 0;
  67.         
  68. {$ifc do_debug}
  69.     var
  70.         startup_check: integer;
  71. {$endc}
  72.  
  73.     var
  74.         about_data: Handle;
  75.         about_data_count: longint;
  76.         gGetAboutString: GetAboutStringProc;
  77.         thanks_click_count: longint;
  78.         about_object: AboutObject;
  79.     
  80.     procedure NextAboutDataEntry( var p: longint );
  81.     begin
  82.         Assert( about_data <> nil );
  83.         Assert( (0 <= p) & (p < GetHandleSize( about_data )) );
  84.         p := p + GetUnsignedByte( about_data^, p ) + 1; { display }
  85.         p := p + 1; { group }
  86.         p := p + GetUnsignedByte( about_data^, p ) + 1; { url }
  87.         Assert( p <= GetHandleSize( about_data ) );
  88.     end;
  89.     
  90.     procedure GetAboutDataEntry( index: integer; var entry: AboutDataEntry );
  91.         var
  92.             p: longint;
  93.             i: integer;
  94.     begin
  95.         Assert( about_data <> nil );
  96.         Assert( (1 <= index) & (index <= about_data_count) );
  97.         p := 0;
  98.         for i := 1 to index-1 do begin
  99.             NextAboutDataEntry( p );
  100.         end;
  101.         Assert( p < GetHandleSize( about_data ) );
  102.         BlockMoveData( AddPtrLong( about_data^, p ), @entry.display, GetUnsignedByte( about_data^, p ) + 1 );
  103.         p := p + GetUnsignedByte( about_data^, p ) + 1;
  104.         entry.group := GetUnsignedByte( about_data^, p );
  105.         p := p + 1;
  106.         BlockMoveData( AddPtrLong( about_data^, p ), @entry.url, GetUnsignedByte( about_data^, p ) + 1 );
  107.         p := p + GetUnsignedByte( about_data^, p ) + 1;
  108.     end;
  109.     
  110.     function MGetAboutData: OSErr;
  111.     
  112.         function CountAboutDataEntries: integer;
  113.             var
  114.                 size: longint;
  115.                 count: integer;
  116.                 p: longint;
  117.         begin
  118.             Assert( about_data <> nil );
  119.             p := 0;
  120.             count := 0;
  121.             size := GetHandleSize( about_data );
  122.             while p < size do begin
  123.                 NextAboutDataEntry( p );
  124.                 Inc(count);
  125.             end;
  126.             Assert( p = size );
  127.             CountAboutDataEntries := count;
  128.         end;
  129.     
  130.         var
  131.             err: OSErr;
  132.     begin
  133.         err := MGetResource( app_resfile, 'ABOU', about_id, about_data );
  134.         Assert( err = noErr );
  135.         if err = noErr then begin
  136.             about_data_count := CountAboutDataEntries;
  137.         end;
  138.         MGetAboutData := err;
  139.     end;
  140.  
  141.     procedure GetFirstGroupEntry( group: integer; var entry: AboutDataEntry );
  142.         var
  143.             i: integer;
  144.     begin
  145.         Assert( group <> 0 );
  146.         for i := 1 to about_data_count do begin
  147.             GetAboutDataEntry( i, entry );
  148.             if entry.group = group then begin
  149.                 Exit( GetFirstGroupEntry );
  150.             end;
  151.         end;
  152.         Assert( false );
  153.     end;
  154.     
  155. {$ifc do_debug}
  156.     procedure ValidateAboutEntryData;
  157.         var
  158.             i: integer;
  159.             kind: integer;
  160.             entry: AboutDataEntry;
  161.             frame: Rect;
  162.             first_of_group_entry: AboutDataEntry;
  163.     begin
  164.         Assert( about_object <> nil );
  165.         Assert( about_data <> nil );
  166.         for i := 1 to about_data_count do begin
  167.             GetDItemKind( about_object.window, i, kind );
  168.             GetAboutDataEntry( i, entry );
  169.             if entry.group = kNoGroup then begin
  170.                 Assert( kind = userItem+itemDisable );
  171.                 Assert( entry.url = '' );
  172.             end else begin
  173.                 Assert( kind = userItem );
  174.                 GetFirstGroupEntry( entry.group, first_of_group_entry );
  175.                 Assert( first_of_group_entry.url <> '' );
  176.                 if entry.display <> first_of_group_entry.display then begin { hack test to see if they are different entries }
  177.                     Assert( entry.url = '' );
  178.                 end;
  179.             end;
  180.             if IsPrefix( entry.display, kICONStyledString ) then begin
  181.                 GetDItemRect( about_object.window, i, frame );
  182.                 Assert( (frame.right - frame.left = 32) & (frame.bottom - frame.top = 32) );
  183.             end;
  184.         end;
  185.     end;
  186. {$endc}
  187.  
  188.     var
  189.         last_thanks_click_count: longint;
  190.         random_thanks_index: integer;
  191.         
  192.     function DefaultGetAboutString (index: integer): Str255;
  193.         var
  194.             vers: versionRecord;
  195.             newrti: integer;
  196.             s: Str255;
  197.     begin
  198.         GetVersion(app_resfile, vers);
  199.         case index of
  200.             kAboutStringLongVersion: begin
  201.                 DefaultGetAboutString := vers.longVersion;
  202.             end;
  203.             kAboutStringShortVersion: begin
  204.                 DefaultGetAboutString := vers.shortVersion;
  205.             end;
  206.             kAboutStringName: begin
  207.                 DefaultGetAboutString := vers.name;
  208.             end;
  209.             kAboutStringThanks: begin
  210.                 if last_thanks_click_count <> thanks_click_count then begin
  211.                     if CountStrs(thanks_strh_id) <= 1 then begin
  212.                         random_thanks_index := 1;
  213.                     end else begin
  214.                         newrti := BAND(Random, $7FFF) mod (CountStrs(thanks_strh_id) - 1) + 1;
  215.                         if newrti >= random_thanks_index then begin
  216.                             Inc(newrti);
  217.                         end;
  218.                         random_thanks_index := newrti;
  219.                     end;
  220.                     last_thanks_click_count := thanks_click_count;
  221.                 end;
  222.                 GetIndString(s, thanks_strh_id, random_thanks_index);
  223.                 DefaultGetAboutString := s;
  224.             end;
  225.             otherwise begin
  226. {                Assert( false );}
  227.                 DefaultGetAboutString := '???';
  228.             end;
  229.         end;
  230.     end;
  231.  
  232.     function AboutObject.TrackGroup( group:integer ):boolean;
  233.         var
  234.             click_rgn:RgnHandle;
  235.             
  236.         procedure DrawItems( selected: boolean );
  237.             var
  238.                 i: integer;
  239.                 entry: AboutDataEntry;
  240.         begin
  241.             for i := 1 to about_data_count do begin
  242.                 GetAboutDataEntry( i, entry );
  243.                 if entry.group = group then begin
  244.                     DrawDisplayItem( i, selected );
  245.                 end;
  246.             end;
  247.         end;
  248.         
  249.         var
  250.             inside,newinside:boolean;
  251.             mouse:Point;
  252.             i: integer;
  253.             entry: AboutDataEntry;
  254.             frame: Rect;
  255.     begin
  256.         SetPort( window );
  257.         click_rgn := NewRgn;
  258.         for i := 1 to about_data_count do begin
  259.             GetAboutDataEntry( i, entry );
  260.             if entry.group = group then begin
  261.                 GetDItemRect( window, i, frame );
  262.                 UnionRgnRect( click_rgn, frame );
  263.             end;
  264.         end;
  265.         DrawItems( true );
  266.         inside := true;
  267.         while StillDown do begin
  268.             GetMouse(mouse);
  269.             newinside := PtInRgn( mouse, click_rgn );
  270.             if newinside <> inside then begin
  271.                 DrawItems( newinside );
  272.                 inside := newinside;
  273.             end;
  274.         end;
  275.         if inside then begin
  276.             DrawItems( false );
  277.         end;
  278.         TrackGroup := inside;
  279.     end;
  280.  
  281.     procedure AboutObject.DoItem (item: integer);
  282.         var
  283.             frame: Rect;
  284.             entry: AboutDataEntry;
  285.             err: OSErr;
  286.     begin
  287.         GetAboutDataEntry( item, entry );
  288.         Assert( entry.group <> kNoGroup );
  289.         GetFirstGroupEntry( entry.group, entry );
  290.         Assert( entry.url <> '' );
  291.         if entry.url = kThanksURL then begin
  292.             Inc( thanks_click_count );
  293.             GetDItemRect( window, item, frame );
  294.             SetPort( window );
  295.             InvalRect( frame );
  296.         end else begin
  297.             if TrackGroup( entry.group ) then begin
  298.                 if entry.url = kRegisterURL then begin
  299.                     err := LaunchAppWithHint( app_fs.vRefNum, app_fs.parID, 'Regi','APPL',true );
  300.                 end else begin
  301.                     err := MyLaunchURL( '', entry.url );
  302.                 end;
  303.                 if err <> noErr then begin
  304.                     DisplayErrorString( GetIndStr( about_error_strh_id, 1 ), err );
  305.                 end;
  306.             end;
  307.         end;
  308.     end;
  309.  
  310.     procedure AboutObject.DrawDisplayItem( item: integer; selected: boolean );
  311.         var
  312.             s, t: Str255;
  313.             i, n: integer;
  314.             entry: AboutDataEntry;
  315.             id: longint;
  316.             frame: Rect;
  317.     begin
  318.         SetPort( window );
  319.         GetAboutDataEntry( item, entry );
  320.         Assert( entry.display <> '' );
  321.         s := entry.display;
  322.         if IsPrefix( s, kICONStyledString ) then begin
  323.             Delete( s, 1, length(kICONStyledString) );
  324.             StringToNum( s, id );
  325.             GetDItemRect( window, item, frame );
  326.             SafePlotCIcon( id, frame, selected );
  327.         end else begin
  328.             i := 1;
  329.             while (i < length(s)) do begin
  330.                 if s[i] = '^' then begin
  331.                     n := ord(s[i+1])-48;
  332.                     if n>= 10 then begin
  333.                         n := n-7;
  334.                     end;
  335.                     t := gGetAboutString(n);
  336.                     Delete(s, i, 2);
  337.                     Insert(t, s, i);
  338.                     i := i + length(t);
  339.                 end else begin
  340.                     i := i + 1;
  341.                 end;
  342.             end;
  343.             DisplayStyledString( window, item, s, selected );
  344.         end;
  345.     end;
  346.     
  347.     procedure AboutObject.DrawUserItem( item: integer );
  348.     begin
  349.         DrawDisplayItem( item, false );
  350.     end;
  351.  
  352.     procedure AboutObject.Create (id: integer);
  353.         var
  354.             s: Str255;
  355.             vers: versionRecord;
  356.     begin
  357.         UseResFile(app_resfile);
  358.         inherited Create(id);
  359.         SetPort(window);
  360.         close_hides_window := true;
  361.         AppleGuideWindowType := agwtAbout;
  362.         thanks_click_count := 0;
  363.         SetMyFont(MFT_Geneva12);
  364.         GetWTitle(window, s);
  365.         GetVersion(app_resfile, vers);
  366.         SPrintS3(s, s, vers.name, '', '');
  367.         SetWTitle(window, s);
  368.         HandleAllUserItems;
  369.     end;
  370.  
  371.     procedure DoAbout;
  372.     begin
  373.         Inc(thanks_click_count);
  374.         if GetWindowVisible(about_object.window) then begin
  375.             if FrontWindow <> about_object.window then begin
  376.                 SelectWindow(about_object.window);
  377.             end;
  378.         end else begin
  379.             SelectWindow(about_object.window);
  380.             ShowWindow(about_object.window);
  381.         end;
  382.     end;
  383.  
  384.     function AboutEnabled: boolean;
  385.     begin
  386.         AboutEnabled := not IsWObjectFront(about_object);
  387.     end;
  388.     
  389.     procedure UpdateAboutBox;
  390.     begin
  391.         AssertDidStartup( startup_check );
  392.         SetPort(about_object.window);
  393.         InvalRect(about_object.window^.portRect);
  394.     end;
  395.  
  396.     procedure CloseAboutBox;
  397.     begin
  398.         AssertDidStartup( startup_check );
  399.         about_object.DoClose;
  400.     end;
  401.  
  402.     procedure OpenAboutBox;
  403.     begin
  404.         AssertDidStartup( startup_check );
  405.         DoAbout;
  406.         SetPort(about_object.window);
  407.         DrawDialog(about_object.window);
  408.         ValidRect(about_object.window^.portRect);
  409.     end;
  410.  
  411.     function InitAbout(var msg: integer): OSStatus;
  412.         var
  413.             err: OSErr;
  414.  
  415.     begin
  416. {$unused(msg)}
  417.         AssertDidStartup( startup_check );
  418.         err := MGetAboutData;
  419.         if err = noErr then begin
  420.             SetRecordedMenuCommand( kAECoreSuite, kAEAbout, Cabout, AboutEnabled, DoAbout );
  421.             if gGetAboutString = nil then begin
  422.                 gGetAboutString := DefaultGetAboutString;
  423.             end;
  424.             new(about_object);
  425.             about_object.Create(about_id);
  426. {$ifc do_debug}
  427.             ValidateAboutEntryData;
  428. {$endc}
  429.         end;
  430.         InitAbout := err;
  431.     end;
  432.  
  433.     procedure ConfigureAbout( get_about_string_proc: GetAboutStringProc );
  434.     begin
  435.         StartupAbout;
  436.         gGetAboutString := get_about_string_proc;
  437.         DidStartup( startup_check );
  438.     end;
  439.     
  440.     procedure StartupAbout;
  441.     begin
  442.         StartupDialogs;
  443.         StartupFMenus;
  444.         StartupMainLoop;
  445.         StartupOOMenus;
  446.         StartupInternetConfig;
  447.         StartupRecordedMenuCommands;
  448.         SetStartup(InitAbout, nil, 0, nil);
  449.     end;
  450.     
  451. end.
  452.