home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 March / macformat-035.iso / Shareware City / Developers / ICAppSourceKit1.2 / ICWindows.p < prev    next >
Encoding:
Text File  |  1995-11-07  |  22.9 KB  |  875 lines  |  [TEXT/CWIE]

  1. unit ICWindows;
  2.  
  3. interface
  4.  
  5.     uses
  6.         ICWindowGlobals;
  7.  
  8.     function InitICWindows: OSErr;
  9.  
  10.     function WindowsOpen (wt: WindowType): OSErr;
  11.     function WindowsClose (wp: WindowPtr): OSErr;
  12.     function WindowsFlushAll: OSErr;    (* close all information windows *)
  13.     function WindowsCloseAll: OSErr;    (* close all information windows *)
  14.  
  15.     procedure WindowsSetTitle (wt: WindowType; title: Str255);
  16.     procedure WindowsIdle;
  17.     procedure WindowActivateDeactivate (window: WindowPtr; activate: boolean);
  18.     procedure WindowItemWhere (window: WindowPtr; er: EventRecord; item: integer);
  19.     procedure WindowsDoKey (er: EventRecord);
  20.     function WindowsEarlyHandleEvent (er: EventRecord): boolean;
  21.     function WindowsEarlyHandleKey (er: EventRecord): boolean;
  22.     procedure WindowsAdjustMenus;
  23.     procedure WindowsDoEditMenu (item: integer);
  24.  
  25.     procedure WindowsRestorePositions;
  26.     procedure WindowsSavePositions;
  27.     procedure WindowsResetPositions;
  28.  
  29.     function GetWindowPtr (wt: WindowType): WindowPtr;
  30.  
  31.     function EditCurrentPreference (var key: Str255): OSErr;
  32.  
  33. implementation
  34.  
  35.     uses
  36.         Icons, Quickdraw, Resources, ToolUtils, Dialogs,
  37.  
  38.         ICMiscSubs, ICSubs, ICTypes, ICAPI, ICDialogs, ICText, ICGlobals,  ICKeys,
  39.  
  40.         ICTextWhats, ICPopupWhats, ICFontWhats, ICFSSpecWhats, ICFileMapWhat, ICHelperWhat, ICButtonWhat, 
  41.  
  42.         ICDocument {X};
  43.  
  44.     const
  45.         OurWindowPositionsKey = '49434170•WindowPositions';
  46.         
  47.     function CallWhatOpen (wt: WindowType; item: integer; open: ProcPtr): OSErr;
  48.     inline
  49.         $205F, $4E90;
  50.  
  51.     function CallWhatClose (wt: WindowType; item: integer; close: ProcPtr): OSErr;
  52.     inline
  53.         $205F, $4E90;
  54.  
  55.     function CallWhatFlush (wt: WindowType; item: integer; close: ProcPtr): OSErr;
  56.     inline
  57.         $205F, $4E90;
  58.  
  59.     function CallWhatClick (wt: WindowType; item: integer; er: eventRecord; close: ProcPtr): OSErr;
  60.     inline
  61.         $205F, $4E90;
  62.  
  63.     function CallWhatKey (wt: WindowType; item: integer; er: eventRecord; key: ProcPtr): OSErr;
  64.     inline
  65.         $205F, $4E90;
  66.  
  67.     function CallWhatActivate (wt: WindowType; item: integer; activate: boolean; actproc: ProcPtr): OSErr;
  68.     inline
  69.         $205F, $4E90;
  70.  
  71.     function CallWhatIdle (wt: WindowType; item: integer; idleproc: ProcPtr): OSErr;
  72.     inline
  73.         $205F, $4E90;
  74.  
  75.     function CallWhatCursor (wt: WindowType; item: integer; pt: Point; cursorid: integer; cursorproc: ProcPtr): OSErr;
  76.     inline
  77.         $205F, $4E90;
  78.  
  79.     function TypeToWhat (typ: OSType): integer;
  80.         var
  81.             i: integer;
  82.     begin
  83.         TypeToWhat := 1;
  84.         for i := 1 to whats_max do begin
  85.             if whatinfo[i].typ = typ then begin
  86.                 TypeToWhat := i;
  87.                 leave;
  88.             end;
  89.         end;
  90.     end;
  91.  
  92.     function GetWhatType (wt: WindowType; item: integer): OSType;
  93.         var
  94.             wrp: WhatRecordPtr;
  95.     begin
  96.         wrp := windowinfo[wt].items[item];
  97.         if wrp = nil then begin
  98.             GetWhatType := 'NULL';
  99.         end else begin
  100.             GetWhatType := wrp^.typ;
  101.         end;
  102.     end;
  103.  
  104.     function GetWindowPtr (wt: WindowType): WindowPtr;
  105.     begin
  106.         GetWindowPtr := windowinfo[wt].window;
  107.     end;
  108.  
  109.     function OurWindow (wp: WindowPtr): boolean;
  110.     begin
  111.         OurWindow := GetWindowType(wp) <> WT_None;
  112.     end;
  113.  
  114.     function WhatIdleText (wt: WindowType; item: integer; var cursor: integer): OSErr;
  115.         var
  116.             r: rect;
  117.             pt: Point;
  118.     begin
  119.         GetDItemRect(windowinfo[wt].window, item, r);
  120.         GetMouse(pt);
  121.         if PtInRect(pt, r) then begin
  122.             cursor := iBeamCursor;
  123.         end;
  124.         WhatIdleText := noErr;
  125.     end;
  126.  
  127.     procedure DoWindowIdle (window: WindowPtr);
  128.         var
  129.             selected_item, i: integer;
  130.             what: WhatRecordPtr;
  131.             wt: WindowType;
  132.             cursorid: integer;
  133.             r: rect;
  134.             pt: Point;
  135.             cursor: ProcPtr;
  136.             junk: OSErr;
  137.             cursor_set: boolean;
  138.     begin
  139.         SetPort(window);
  140.         wt := GetWindowType(window);
  141.         selected_item := GetSelectedItem(GetWindowType(window));
  142.         if selected_item > 0 then begin
  143.             TextIdle(windowinfo[GetWindowType(window)].items[selected_item]^.data);
  144.         end;
  145.         if (window = FrontWindow) & InForeground then begin
  146.             GetMouse(pt);
  147.             cursor_set := false;
  148.             for i := 1 to item_max do begin
  149.                 what := windowinfo[wt].items[i];
  150.                 if what <> nil then begin
  151.                     GetDItemRect(window, i, r);
  152.                     if PtInRect(pt, r) then begin
  153.                         cursor_set := true;
  154.                         cursorid := whatinfo[TypeToWhat(what^.typ)].cursorid;
  155.                         cursor := whatinfo[TypeToWhat(what^.typ)].cursor;
  156.                         if cursor = nil then begin
  157.                             if cursorid = 0 then begin
  158.                                 InitCursor;
  159.                             end else begin
  160.                                 SetCursor(GetCursor(cursorid)^^);
  161.                             end;
  162.                         end else begin
  163.                             junk := CallWhatCursor(wt, i, pt, cursorid, cursor);
  164.                         end; (* if *)
  165.                     end;
  166.                 end; (* if *)
  167.             end; (* for *)
  168.             if not cursor_set then begin
  169.                 InitCursor;
  170.             end; (* if *)
  171.         end;
  172.     end;
  173.  
  174.     procedure WindowDoKey (window: WindowPtr; er: EventRecord);
  175.         var
  176.             selected_item: integer;
  177.             key: ProcPtr;
  178.     begin
  179.         selected_item := windowinfo[GetWindowType(window)].selected_item;
  180.         if selected_item > 0 then begin
  181.             key := whatinfo[TypeToWhat(GetWhatType(GetWindowType(window), selected_item))].key;
  182.             if key <> nil then begin
  183.                 SetPort(window);
  184.                 DisplayError(acDoThis, CallWhatKey(GetWindowType(window), selected_item, er, key));
  185.             end; (* if *)
  186.         end;
  187.     end;
  188.  
  189.     procedure WindowActivateDeactivate (window: WindowPtr; activate: boolean);
  190.         var
  191.             wt: WindowType;
  192.             item: integer;
  193.             i: integer;
  194.             actproc: ProcPtr;
  195.             what: WhatRecordPtr;
  196.             err: OSErr;
  197.     begin
  198.         wt := GetWindowType(window);
  199.         if wt <> WT_None then begin
  200.             SetPort(window);
  201.             item := GetSelectedItem(wt);
  202.             if item > 0 then begin
  203.                 TextActivate(windowinfo[wt].items[item]^.data, activate);
  204.             end; (* if *)
  205.             for i := 1 to item_max do begin
  206.                 what := windowinfo[wt].items[i];
  207.                 if what <> nil then begin
  208.                     actproc := whatinfo[TypeToWhat(what^.typ)].activate;
  209.                     if actproc <> nil then begin
  210.                         err := CallWhatActivate(wt, i, activate, actproc);
  211.                         if (err <> noErr) and (err <> userCanceledErr) then begin
  212.                             SysBeep(10);
  213.                         end; (* if *)
  214.                     end;
  215.                 end; (* if *)
  216.             end; (* for *)
  217.         end; (* if *)
  218.     end;
  219.  
  220.     function LaunchSomeSillyURL(url: Str255): ICError;
  221.         var
  222.             start, fin: longint;
  223.     begin
  224.         start := length(url) div 2;
  225.         fin :=start;
  226.         LaunchSomeSillyURL := ICLaunchURL(GetInstance, '', @url[1], length(url), start, fin);
  227.     end;
  228.     
  229.     procedure DoAboutClick(window: WindowPtr; item: integer);
  230.         var
  231.             a:integer;
  232.             s:Str255;
  233.     begin
  234.         if TrackItems(window, item, 0, 0) then begin
  235.             if item = 6 then begin
  236.                 a := NoteAlert(167, @CancelModalFilter);
  237.                 case a of
  238.                     1: begin
  239.                         item := 7;
  240.                     end;
  241.                     2: begin
  242.                         item := 0;
  243.                     end;
  244.                     3: begin
  245.                         item := 6;
  246.                     end;
  247.                 end;
  248.             end;
  249.             if item <> 0 then begin
  250.                 GetIndString(s, 129, item);
  251.                 DisplayError(acDoThis, LaunchSomeSillyURL(s));
  252.             end;
  253.         end;
  254.     end;
  255.     
  256.     procedure WindowItemWhere (window: WindowPtr; er: EventRecord; item: integer);
  257.         var
  258.             click: ProcPtr;
  259.     begin
  260.         case GetWindowType(window) of
  261.             WT_About:  begin
  262.                 DoAboutClick(window, item);
  263.             end;
  264.             otherwise begin
  265.                 click := whatinfo[TypeToWhat(GetWhatType(GetWindowType(window), item))].click;
  266.                 if click <> nil then begin
  267.                     SetPort(window);
  268.                     DisplayError(acDoThis, CallWhatClick(GetWindowType(window), item, er, click));
  269.                 end; (* if *)
  270.             end;
  271.         end;
  272.     end;
  273.  
  274.     function WindowEarlyHandleEvent (window: WindowPtr; er: EventRecord): boolean;
  275.     begin
  276.         window := window; { Unused }
  277.         er := er; { Unused }
  278.         WindowEarlyHandleEvent := false;
  279.     end;
  280.  
  281.     procedure WindowTab (window: WindowPtr; shift: boolean);
  282.         var
  283.             orgitem, rorgitem, i: integer;
  284.             dirn: integer;
  285.             selitem: integer;
  286.             t: OSType;
  287.     begin
  288.         selitem := -1;
  289.         orgitem := GetSelectedItem(GetWindowType(window));
  290.         rorgitem := orgitem;
  291.         if orgitem <= 0 then begin
  292.             if shift then begin
  293.                 orgitem := 1;
  294.             end else begin
  295.                 orgitem := item_max;
  296.             end;
  297.         end;
  298.         dirn := item_max - 2 * ord(shift);
  299.         i := orgitem;
  300.         repeat
  301.             i := (i + dirn) mod item_max + 1;
  302.             t := GetWhatType(GetWindowType(window), i);
  303.             if t = 'TEXT' then begin
  304.                 selitem := i;
  305.                 leave;
  306.             end;
  307.         until (i = orgitem);
  308.         if selitem > 0 then begin
  309.             SelectTextItem(GetWindowType(window), selitem);
  310.         end;
  311.     end;
  312.  
  313.     function WindowEarlyHandleKey (window: WindowPtr; er: EventRecord): boolean;
  314.         var
  315.             b: boolean;
  316.             ch: integer;
  317.             wt: WindowType;
  318.     begin
  319.         b := false;
  320.         wt := GetWindowType(window);
  321.         if not windowinfo[wt].window_key_needs_tabs then begin
  322.             ch := BAND(er.message, $FF);
  323.             if ch = 9 then begin
  324.                 WindowTab(window, BAND(er.modifiers, shiftKey) <> 0);
  325.                 b := true;
  326.             end;
  327.         end;
  328.         WindowEarlyHandleKey := b;
  329.     end;
  330.  
  331.     function FlushWindowType (wp: WindowPtr; wt: WindowType): OSErr;
  332.         var
  333.             i: integer;
  334.             first_err, err: OSErr;
  335.             flush: ProcPtr;
  336.             what: WhatRecordPtr;
  337.             portrect: Rect;
  338.     begin
  339.         first_err := noErr;
  340.         SetPort(wp);
  341.         GetWindowRect(wp, portrect);
  342.         windowinfo[wt].position := portrect.topLeft;
  343.         for i := 1 to item_max do begin
  344.             what := windowinfo[wt].items[i];
  345.             if what <> nil then begin
  346.                 flush := whatinfo[TypeToWhat(what^.typ)].flush;
  347.                 if flush <> nil then begin
  348.                     err := CallWhatFlush(wt, i, flush);
  349.                     if first_err = noErr then begin
  350.                         first_err := err;
  351.                     end; (* if *)
  352.                 end;
  353.             end; (* if *)
  354.         end;
  355.         FlushWindowType := first_err;
  356.     end; (* FlushWindowType *)
  357.  
  358.     function DisposeWindowType (wp: WindowPtr; wt: WindowType): OSErr;
  359.         var
  360.             i: integer;
  361.             first_err, err: OSErr;
  362.             close: ProcPtr;
  363.             what: WhatRecordPtr;
  364.     begin
  365.         first_err := noErr;
  366.         SetPort(wp);
  367.         for i := 1 to item_max do begin
  368.             what := windowinfo[wt].items[i];
  369.             if what <> nil then begin
  370.                 close := whatinfo[TypeToWhat(what^.typ)].close;
  371.                 if close <> nil then begin
  372.                     err := CallWhatClose(wt, i, close);
  373.                     if first_err = noErr then begin
  374.                         first_err := err;
  375.                     end; (* if *)
  376.                 end;
  377.                 windowinfo[wt].items[i] := nil;
  378.                 DisposePtr(Ptr(what));
  379.             end; (* if *)
  380.         end;
  381.         windowinfo[wt].window := nil;
  382.         DisposeDialog(wp);
  383.         DisposeWindowType := first_err;
  384.     end; (* DisposeWindowType *)
  385.  
  386.     function CloseWindowType (wp: WindowPtr; wt: WindowType): OSErr;
  387.         var
  388.             err: OSErr;
  389.             err2: OSErr;
  390.             opened: boolean;
  391.     begin
  392.         opened := false;
  393.         err := ICMapErr(ICBegin(GetInstance, icReadWritePerm));
  394.         if err = noErr then begin
  395.             opened := true;
  396.             err := FlushWindowType(wp, wt);
  397.         end; (* if *)
  398.         err2 := DisposeWindowType(wp, wt);
  399.         if err = noErr then begin
  400.             err := err2;
  401.         end; (* if *)
  402.         if opened then begin
  403.             err2 := ICMapErr(ICEnd(GetInstance));
  404.             if err = noErr then begin
  405.                 err := err2;
  406.             end; (* if *)
  407.         end; (* if *)
  408.         CloseWindowType := err;
  409.     end; (* CloseWindowType *)
  410.  
  411.     function WindowsEarlyHandleEvent (er: EventRecord): boolean;
  412.     begin
  413.         WindowsEarlyHandleEvent := false;
  414.         if GetWindowType(FrontWindow) <> WT_None then begin
  415.             WindowsEarlyHandleEvent := WindowEarlyHandleEvent(FrontWindow, er);
  416.         end;
  417.     end;
  418.  
  419.     function WindowsEarlyHandleKey (er: EventRecord): boolean;
  420.     begin
  421.         WindowsEarlyHandleKey := false;
  422.         if GetWindowType(FrontWindow) <> WT_None then begin
  423.             WindowsEarlyHandleKey := WindowEarlyHandleKey(FrontWindow, er);
  424.         end;
  425.     end;
  426.  
  427.     procedure WindowsDoKey (er: EventRecord);
  428.     begin
  429.         if GetWindowType(FrontWindow) <> WT_None then begin
  430.             WindowDoKey(FrontWindow, er);
  431.         end;
  432.     end;
  433.  
  434.     procedure WindowsIdle;
  435.         var
  436.             wt: WindowType;
  437.     begin
  438.         for wt := WT_None to WT_Last do begin
  439.             if windowinfo[wt].window <> nil then begin
  440.                 DoWindowIdle(windowinfo[wt].window);
  441.             end;
  442.         end;
  443.     end;
  444.  
  445.     procedure WindowsSetTitle (wt: WindowType; title: Str255);
  446.     begin
  447.         if windowinfo[wt].window <> nil then begin
  448.             SetWTitle(windowinfo[wt].window, title);
  449.         end; (* if *)
  450.     end; (* WindowsSetTitle *)
  451.  
  452.     procedure WindowsAdjustMenus;
  453.         var
  454.             wt: WindowType;
  455.     begin
  456.         wt := GetWindowType(FrontWindow);
  457.         AdjustTextMenu(wt);
  458.     end;
  459.  
  460.     procedure WindowsDoEditMenu (item: integer);
  461.         var
  462.             wt: WindowType;
  463.     begin
  464.         wt := GetWindowType(FrontWindow);
  465.         if wt <> WT_None then begin
  466.             DoTextMenu(wt, item);
  467.         end; (* if *)
  468.     end;
  469.  
  470.     type
  471.         WhatTemplateRecord = record
  472.                 key: str31;
  473.                 typ: OSType;
  474.                 flags: longInt;
  475.             end;
  476.         WhatTemplateArray = array[1..item_max] of WhatTemplateRecord;
  477.         WhatTemplateArrayPtr = ^WhatTemplateArray;
  478.         WhatTemplateArrayHandle = ^WhatTemplateArrayPtr;
  479.  
  480.     function ParseWhat (wt: WindowType): OSErr;
  481.         var
  482.             what: WhatTemplateArrayHandle;
  483.             i: integer;
  484.             err: OSErr;
  485.     begin
  486.         err := noErr;
  487.         for i := 1 to item_max do begin
  488.             windowinfo[wt].items[i] := nil;
  489.         end;
  490.         what := WhatTemplateArrayHandle(GetResource('WHAT', windowinfo[wt].id));
  491.         if what <> nil then begin
  492.             HLock(handle(what));
  493.             for i := 1 to GetHandleSize(handle(what)) div SizeOf(WhatTemplateRecord) do begin
  494.                 if what^^[i].typ <> 'NULL' then begin
  495.                     windowinfo[wt].items[i] := WhatRecordPtr(NewPtr(SizeOf(WhatRecord)));
  496.                     err := MemError;
  497.                     if err <> noErr then begin
  498.                         leave;
  499.                     end; (* if *)
  500.                     with windowinfo[wt].items[i]^ do begin
  501.                         key := what^^[i].key;
  502.                         typ := what^^[i].typ;
  503.                         flags := what^^[i].flags;
  504.                     end; (* with *)
  505.                 end; (* if *)
  506.             end; (* for *)
  507.             HUnlock(handle(what));
  508.         end; (* if *)
  509.         ParseWhat := err;
  510.     end; (* ParseWhat *)
  511.  
  512.     function GetWindowID (wt: WindowType): integer;
  513.     begin
  514.         if wt = WT_About then begin
  515.             GetWindowID := 128;
  516.         end else begin
  517.             GetWindowID := 200 + ord(wt) - ord(WT_Main);
  518.         end;
  519.     end;
  520.  
  521.     function IsPrefix(var s:Str255; key:Str255):Boolean;
  522.     begin
  523.         IsPrefix := false;
  524.         if IUEqualString(TPCopy(s, 1, length(key)),key) = 0 then begin
  525.             s := TPCopy(s, length(key)+1, 255);
  526.             IsPrefix := true;
  527.         end;
  528.     end;
  529.     
  530.     function EditCurrentPreference (var key: Str255): OSErr;
  531.         var
  532.             wt: WindowType;
  533.             what: WhatTemplateArrayHandle;
  534.             err: OSErr;
  535.             i: integer;
  536.             id: integer;
  537.     begin
  538.         err := -1;
  539.         if IsPrefix(key, concat(kICMapping,'•')) then begin
  540.             err := WindowsOpen(WT_FileMapping);
  541.             if err = noErr then begin
  542.                 MappingSetSelection(key);
  543.             end;
  544.         end else if IsPrefix(key, kICHelper) then begin
  545.             err := WindowsOpen(WT_Helper);
  546.             if err = noErr then begin
  547.                 HelperSetSelection(key);
  548.             end;
  549.         end else begin
  550.             for wt := WT_None to WT_Last do begin
  551.                 if (WT_Personal <= wt) & (wt <= WT_Last) then begin
  552.                     id := GetWindowID(wt);
  553.                     what := WhatTemplateArrayHandle(GetResource('WHAT', id));
  554.                     if what <> nil then begin
  555.                         HLock(handle(what));
  556.                         for i := 1 to GetHandleSize(handle(what)) div SizeOf(WhatTemplateRecord) do begin
  557.                             if IUEqualString(key, what^^[i].key) = 0 then begin
  558.                                 err := WindowsOpen(wt);
  559.                                 if (what^^[i].typ = 'TEXT') then begin
  560.                                     SelectTextItem(wt, i);
  561.                                 end;
  562.                             end;
  563.                         end;
  564.                         HUnlock(handle(what));
  565.                     end;
  566.                 end;
  567.             end;
  568.         end;
  569.         EditCurrentPreference := err;
  570.     end;
  571.  
  572.     function PrepWindow (wt: WindowType; id: integer; wp: WindowPtr): OSErr;
  573.         var
  574.             what, i: integer;
  575.             err: OSErr;
  576.             first_err: OSErr;
  577.     begin
  578.         SetPort(wp);
  579.         windowinfo[wt].window := wp;
  580.         windowinfo[wt].id := id;
  581.         windowinfo[wt].selected_item := -1;
  582.         windowinfo[wt].window_key_needs_tabs := true;
  583.         first_err := ParseWhat(wt);
  584.         if first_err = noErr then begin
  585.             for i := 1 to item_max do begin
  586.                 if windowinfo[wt].items[i] <> nil then begin
  587.                     with windowinfo[wt].items[i]^ do begin
  588.                         if typ = 'TEXT' then begin
  589.                             windowinfo[wt].window_key_needs_tabs := false;
  590.                         end;
  591.                         what := TypeToWhat(typ);
  592.                         if whatinfo[what].open <> nil then begin
  593.                             err := CallWhatOpen(wt, i, whatinfo[what].open);
  594.                             if first_err = noErr then begin
  595.                                 first_err := err;
  596.                             end; (* if *)
  597.                         end;
  598.                     end; (* with *)
  599.                 end;
  600.             end; (* for *)
  601.         end; (* if *)
  602.         if first_err = noErr then begin
  603.             if windowinfo[wt].selected_item = -1 then begin
  604.                 WindowTab(windowinfo[wt].window, false);
  605.             end; (* if *)
  606.         end; (* if *)
  607.         PrepWindow := first_err;
  608.     end; (* PrepWindow *)
  609.  
  610.     function NewWindow (wt: WindowType): OSErr;
  611.         var
  612.             wp: WindowPtr;
  613.             junk: OSErr;
  614.             position: Point;
  615.             original_position: Rect;
  616.             err: OSErr;
  617.             err2: OSErr;
  618.             id, dlg_id: integer;
  619.     begin
  620.         id := GetWindowID(wt);
  621.         wp := nil;
  622.         err := ICMapErr(ICBegin(GetInstance, icReadWritePerm));
  623.         if err = noErr then begin
  624.             dlg_id := id;
  625.             if (wt = WT_Font) & not system7 then begin
  626.                 dlg_id := 290;
  627.             end;
  628.             wp := GetNewDialog(dlg_id, nil, POINTER(-1));
  629.             if wp = nil then begin
  630.                 err := memFullErr;
  631.             end; (* if *)
  632.             if err = noErr then begin
  633.                 err := PrepWindow(wt, id, wp);
  634.             end; (* if *)
  635.             if err = noErr then begin
  636.                 position := windowinfo[wt].position;
  637.                 if (position.h <> 0) or (position.v <> 0) then begin
  638.                     GetWindowRect(wp, original_position);
  639.                     MoveWindow(wp, position.h, position.v, false);
  640.                     ShowWindow(wp);            (* because TitleBarOnScreen requires window to be shown *)
  641.                     if not TitleBarOnScreen(wp) then begin
  642.                         MoveWindow(wp, original_position.left, original_position.top, false);
  643.                     end; (* if *)
  644.                 end; (* if *)
  645.                 ShowWindow(wp);
  646.             end;
  647.             err2 := ICMapErr(ICEnd(GetInstance));
  648.             if err = noErr then begin
  649.                 err := err2;
  650.             end; (* if *)
  651.         end; (* if *)
  652.         (* tidy up code *)
  653.         if err <> noErr then begin
  654.             if wp <> nil then begin
  655.                 junk := DisposeWindowType(wp, wt);
  656.             end; (* if *)
  657.         end; (* if *)
  658.         NewWindow := err;
  659.     end; (* NewWindow *)
  660.  
  661.     function WindowsOpen (wt: WindowType): OSErr;
  662.     begin
  663.         if windowinfo[wt].window <> nil then begin
  664.             ShowWindow(windowinfo[wt].window);
  665.             SelectWindow(windowinfo[wt].window);
  666.             WindowsOpen := noErr;
  667.         end else begin
  668.             WindowsOpen := NewWindow(wt);
  669.         end;
  670.     end; (* WindowsOpen *)
  671.  
  672.     function WindowsClose (wp: WindowPtr): OSErr;
  673.         var
  674.             wt: WindowType;
  675.     begin
  676.         WindowsClose := noErr;
  677.         wt := GetWindowType(wp);
  678.         if wt <> WT_None then begin
  679.             WindowsClose := CloseWindowType(wp, wt);
  680.         end; (* if *)
  681.     end; (* WindowsClose *)
  682.  
  683.     type
  684.         pointArray = array[WT_Main..WT_Last] of Point;
  685.  
  686.     procedure WindowsResetPositions;
  687.         var
  688.             wt: WindowType;
  689.             pos: Point;
  690.     begin
  691.         pos.h := 2;
  692.         pos.v := 42;
  693.         for wt := WT_Main to pred(WT_Last) do begin
  694.             windowinfo[wt].position := pos;
  695.             pos.h := pos.h + 20 * ord(qd.screenbits.bounds.right > 512);
  696.             pos.v := pos.v + 10 * ord(qd.screenbits.bounds.bottom >= 400) + 8 * ord(qd.screenbits.bounds.bottom >= 480);
  697.         end; (* for *)
  698.     end;
  699.  
  700.     procedure WindowsRestorePositions;
  701.         var
  702.             err, err2: OSErr;
  703.             attr: longint;
  704.             window_positions: pointArray;
  705.             size: longint;
  706.             wt: WindowType;
  707.     begin
  708.         err := ICMapErr(ICBegin(GetInstance, icReadOnlyPerm));
  709.         if err = noErr then begin
  710.             size := sizeof(window_positions);
  711.             err := ICGetPref(GetInstance, OurWindowPositionsKey, attr, @window_positions, size);
  712.             if (err = noErr) and (size <> sizeof(window_positions)) then begin
  713.                 err := -1;
  714.             end; (* if *)
  715.             err2 := ICMapErr(ICEnd(GetInstance));
  716.             if err = noErr then begin
  717.                 err := err2;
  718.             end; (* if *)
  719.         end; (* if *)
  720.         if err = noErr then begin
  721.             for wt := WT_Main to WT_Last do begin
  722.                 windowinfo[wt].position := window_positions[wt];
  723.             end; (* for *)
  724.         end else begin
  725.             WindowsResetPositions;
  726.         end; (* if *)
  727.     end; (* WindowsRestorePositions *)
  728.  
  729.     procedure WindowsSavePositions;
  730.         var
  731.             err, err2: OSErr;
  732.             wt: WindowType;
  733.             window_positions: pointArray;
  734.     begin
  735.         for wt := WT_Main to WT_Last do begin
  736.             window_positions[wt] := windowinfo[wt].position;
  737.         end; (* for *)
  738.         err := ICMapErr(ICBegin(GetInstance, icReadWritePerm));
  739.         if err = noErr then begin
  740.             err := ICSetPref(GetInstance, OurWindowPositionsKey, ICattr_no_change, @window_positions, sizeof(window_positions));
  741.             err2 := ICMapErr(ICEnd(GetInstance));
  742.             if err = noErr then begin
  743.                 err := err2;
  744.             end; (* if *)
  745.         end; (* if *)
  746.     end; (* WindowsSavePositions *)
  747.  
  748.     function WindowsFlushAll: OSErr;    (* flush all information windows *)
  749.         var
  750.             wt: WindowType;
  751.             first_err, err: OSErr;
  752.     begin
  753.         first_err := ICMapErr(ICBegin(GetInstance, icReadWritePerm));
  754.         if first_err = noErr then begin
  755.             for wt := WT_Main to WT_Last do begin
  756.                 if windowinfo[wt].window <> nil then begin
  757.                     SetPort(windowinfo[wt].window);
  758.                     err := FlushWindowType(windowinfo[wt].window, wt);
  759.                     if first_err = noErr then begin
  760.                         first_err := err;
  761.                     end; (* if *)
  762.                 end; (* if *)
  763.             end; (* for *)
  764.             err := ICMapErr(ICEnd(GetInstance));
  765.             if first_err = noErr then begin
  766.                 first_err := err;
  767.             end; (* if *)
  768.         end; (* if *)
  769.         WindowsFlushAll := first_err;
  770.     end; (* WindowsFlushAll *)
  771.  
  772.     function WindowsCloseAll: OSErr;    (* close all information windows *)
  773.         var
  774.             wt: WindowType;
  775.             err, first_err: OSErr;
  776.     begin
  777.         first_err := noErr;
  778.         for wt := WT_Personal to WT_Last do begin
  779.             if windowinfo[wt].window <> nil then begin
  780.                 err := CloseWindowType(windowinfo[wt].window, wt);
  781.                 if first_err = noErr then begin
  782.                     first_err := err;
  783.                 end; (* if *)
  784.             end;
  785.         end; (* for *)
  786.         WindowsCloseAll := first_err;
  787.     end; (* WindowsCloseAll *)
  788.  
  789.     procedure InitWhats;
  790.         procedure W (what: integer; xtyp: OSType; xopen, xkey, xclick, xidle, xflush, xclose, xactivate, xcursor: ProcPtr; xcursorid: integer);
  791.         begin
  792.             with whatinfo[what] do begin
  793.                 typ := xtyp;
  794.                 open := xopen;
  795.                 key := xkey;
  796.                 click := xclick;
  797.                 flush := xflush;
  798.                 close := xclose;
  799.                 activate := xactivate;
  800.                 idle := xidle;
  801.                 cursor := xcursor;
  802.                 cursorid := xcursorid;
  803.             end;
  804.         end;
  805.     begin
  806.         W(1, 'NULL', nil, nil, nil, nil, nil, nil, nil, nil, 0);
  807.         W(2, 'TEXT', @WhatOpenText, @WhatKeyText, @WhatClickText, nil, @WhatFlushText, @WhatCloseText, nil, nil, iBeamCursor);
  808.         W(3, 'SPOP', @WhatOpenPopup, nil, @WhatClickPopup, nil, @WhatFlushPopup, @WhatClosePopup, nil, nil, 0);
  809.         W(4, 'FFSP', @WhatOpenFSSpec, nil, @WhatClickFSSpec, nil, @WhatFlushFSSpec, nil, nil, nil, 0);
  810.         W(5, 'FPOP', @WhatOpenFont, nil, @WhatClickFont, nil, @WhatFlushFont, nil, nil, nil, 0);
  811.         W(6, 'FMAP', @WhatOpenFileMap, @WhatKeyFileMap, @WhatClickFileMap, nil, @WhatFlushFileMap, @WhatCloseFileMap, @WhatActivateFileMap, @WhatCursorFileMap, plusCursor);
  812.         W(7, 'FBUT', nil, nil, @WhatClickFileMap, nil, nil, nil, nil, nil, 0);
  813.         W(8, 'HMAP', @WhatOpenHelper, @WhatKeyHelper, @WhatClickHelper, nil, @WhatFlushHelper, @WhatCloseHelper, @WhatActivateHelper, @WhatCursorHelper, plusCursor);
  814.         W(9, 'HBUT', nil, nil, @WhatClickHelper, nil, nil, nil, nil, nil, 0);
  815.         W(10, 'BUTN', @WhatOpenButton, nil, @WhatClickButton, nil, nil, nil, nil, nil, 0);
  816.         W(11, 'FSIZ', nil, nil, @WhatClickFontSize, nil, nil, nil, nil, nil, 0);
  817.     end;
  818.  
  819.     procedure AboutBoxUpdate (dlg: DialogPtr; item: integer);
  820.         var
  821.             r: Rect;
  822.     begin
  823.         GetDItemRect(dlg, item, r);
  824.         if item=6 then begin
  825.             r := r;
  826.         end;
  827.         case item of
  828.             1: 
  829.                 DrawIcon(128, r, false);
  830.             3: 
  831.                 DisplayStyledString(dlg, item, concat(GetAString(129, item), app_version.shortVersion));
  832.             otherwise
  833.                 DisplayStyledString(dlg, item, GetAString(129, item));
  834.         end; (* case *)
  835.     end; (* AboutBoxUpdate *)
  836.  
  837.     function InitICWindows: OSErr;
  838.         var
  839.             wt: WindowType;
  840.             i: integer;
  841.             wp: WindowPtr;
  842.             kind: integer;
  843.             err: OSErr;
  844.     begin
  845.         InitICWindowGlobals;
  846.         InitWhats;
  847.         for wt := WT_None to WT_Last do begin
  848.             windowinfo[wt].window := nil;
  849.             windowinfo[wt].window_key_needs_tabs := false;
  850.             windowinfo[wt].position.h := 0;
  851.             windowinfo[wt].position.v := 0;
  852.         end;
  853.         WindowsResetPositions;
  854.         (* bring the about box up hidden and leave it there *)
  855.         err := noErr;
  856.         wp := GetNewDialog(128, nil, WindowPtr(-1));
  857.         windowinfo[WT_About].window := wp;
  858.         if wp = nil then begin
  859.             err := memFullErr;
  860.         end; (* if *)
  861.         if err = noErr then begin
  862.             err := PrepWindow(WT_About, 128, wp);
  863.         end; (* if *)
  864.         if err = noErr then begin
  865.             for i := 1 to CountDItems(wp) do begin
  866.                 GetDItemKind(wp, i, kind);
  867.                 if band(kind, $7f) = userItem then begin
  868.                     SetDItemHandle(wp, i, @AboutBoxUpdate);
  869.                 end; (* if *)
  870.             end; (* for *)
  871.         end; (* if *)
  872.         InitICWindows := err;
  873.     end; (* InitICWindows *)
  874.  
  875. end.