home *** CD-ROM | disk | FTP | other *** search
/ Mac Power 1997 January / macpower199701.bin / AMUG / Programming_10 / ICPAppSource+ICprogKit / ICAppSourceKit 1.3.sit / ICAppSourceKit1.3 / ICFileMapWhat.p / ICFileMapWhat.p
Encoding:
Text File  |  1996-07-14  |  24.5 KB  |  873 lines  |  [TEXT/CWIE]

  1. unit ICFileMapWhat;
  2.  
  3. interface
  4.  
  5.     uses
  6.         ICWindowGlobals;
  7.  
  8.     function WhatOpenFileMap (wt: WindowType; item: integer): OSErr;
  9.     function WhatActivateFileMap (wt: WindowType; item: integer; activate: boolean): OSErr;
  10.     function WhatFlushFileMap (wt: WindowType; item: integer): OSErr;
  11.     function WhatCloseFileMap (wt: WindowType; item: integer): OSErr;
  12.     function WhatClickFileMap (wt: WindowType; item: integer; er: eventRecord): OSErr;
  13.     function WhatKeyFileMap (wt: WindowType; item: integer; er: EventRecord): OSErr;
  14.     function WhatCursorFileMap (wt: WindowType; item: integer; pt: Point; cursorid: integer): OSErr;
  15.  
  16.     procedure MappingSetSelection(key:Str255);
  17.     
  18. implementation
  19.  
  20.     uses
  21.         Icons, Dialogs, Lists, Fonts, ToolUtils, Resources,
  22.         ICStrH, ICTypes, 
  23.  
  24.         ICKeys, ICAPI, ICSubs, ICDialogs, ICMiscSubs, ICMiscSubs, ICDocument {X}, ICGlobals, {}
  25.         ICIConSuites, ICStandardFile, ICMovableModal, ICWindows;
  26.  
  27.     const
  28.         ditChange = 1;
  29.         ditMainUserItem = 2;
  30.         ditAdd = 3;
  31.         ditDelete = 4;
  32.         ditList = 5;
  33.         ditSortExtension = 6;
  34.         ditSortApplication = 7;
  35.         ditSortName = 8;
  36.         ditDefaults = 9;
  37.  
  38.     const
  39.         ditOK = 1;
  40.         ditCancel = 2;
  41.         ditEditorUserItem = 3;
  42.         ditEntryName = 4;
  43.         ditExtension = 5;
  44.         ditMIMEType = 6;
  45.         ditAsciiRadio = 7;
  46.         ditBinaryRadio = 8;
  47.         ditMacintoshRadio = 9;
  48.         ditType = 10;
  49.         ditCreator = 11;
  50.         ditChooseExample = 12;
  51.         ditApplicationName = 13;
  52.         ditPost = 14;
  53.         ditPostCreator = 15;
  54.         ditPostButton = 16;
  55.         ditNotForIncoming = 17;
  56.         ditNotForOutgoing = 18;
  57.         ditAddEditDefaults = 19;
  58.  
  59.     const
  60.         kCellHeight = 36;
  61.  
  62.     procedure DimButtons (wt: WindowType);
  63.         var
  64.             have_selection: boolean;
  65.             dlg: DialogPtr;
  66.             lh: ListHandle;
  67.     begin
  68.         lh := ListHandle(windowinfo[wt].items[ditList]^.spare_data);
  69.         dlg := windowinfo[wt].window;
  70.         have_selection := (SelectedLine(lh) <> -1);
  71.         SetDCtlEnable(dlg, ditAdd, not IsLocked(wt, ditList));
  72.         SetDCtlEnable(dlg, ditDelete, have_selection and not IsLocked(wt, ditList));
  73.         SetDCtlEnable(dlg, ditChange, have_selection and not IsLocked(wt, ditList));
  74.         SetDCtlEnable(dlg, ditDefaults, not IsLocked(wt, ditList));
  75.         OutlineDefault1(dlg, ditMainUserItem);
  76.     end; (* DimButtons *)
  77.  
  78.     procedure MyLDEF (message: integer; select: boolean; var r: Rect; the_cell: Cell; offset: integer; datalen: integer; lh: ListHandle);
  79.         var
  80.             entries: Handle;
  81.  
  82.         procedure LDClose;
  83.         begin
  84.             (* do nothing *)
  85.         end;
  86.  
  87.         procedure LDDraw;
  88.             const
  89.                 HiliteMode = $938;
  90.             var
  91.                 entry: ICMapEntry;
  92.                 err: OSErr;
  93.                 junkpos: longint;
  94.                 suite: Handle;
  95.                 cur_x: integer;
  96.                 junk: OSErr;
  97.                 tmprect: Rect;
  98.                 sys_font_info, appl_font_info: FontInfo;
  99.                 top: integer;
  100.                 transfer: integer;
  101.                 rgn: RgnHandle;
  102.                 rgn2: RgnHandle;
  103.         begin
  104.             if datalen = 0 then begin
  105.                 err := ICMapErr(ICGetIndMapEntry(GetInstance, entries, the_cell.v + 1, junkpos, entry));
  106.                 if err = noErr then begin
  107.                     EraseRect(r);
  108.                     cur_x := 0;
  109.                     rgn := NewRgn;
  110.                     if system7 then begin
  111.                         tmprect := r;
  112.                         tmprect.bottom := tmprect.top + 32;
  113.                         tmprect.right := tmprect.left + 32;
  114.                         OffsetRect(tmprect, (kCellHeight - 32) div 2, (kCellHeight - 32) div 2);
  115.                         junk := GetDTDBIconSuiteCached(entry.file_type, entry.file_creator, suite);
  116.                         if suite <> nil then begin
  117.                             if select then begin
  118.                                 transfer := ttSelected;
  119.                             end else begin
  120.                                 transfer := ttNone;
  121.                             end; (* if *)
  122.                             err := PlotIconSuite(tmprect, atNone, transfer, suite);
  123.                             junk := IconSuiteToRgn(rgn, tmprect, atNone, suite);
  124.                         end; (* if *)
  125.                         cur_x := cur_x + kCellHeight;
  126.                     end;
  127.                     cur_x := cur_x + 2;
  128.  
  129.                     TextFont(systemFont);
  130.                     GetFontInfo(sys_font_info);
  131.  
  132.                     TextFont(applFont);
  133.                     GetFontInfo(appl_font_info);
  134.  
  135.                     top := (kCellHeight - (sys_font_info.ascent + sys_font_info.descent + 0 + appl_font_info.ascent + appl_font_info.descent)) div 2;
  136.                     TextFont(systemFont);
  137.                     MoveTo(r.left + cur_x, r.top + top + sys_font_info.ascent);
  138.                     DrawString(concat(entry.creator_app_name, GetAString(128, 5), entry.entry_name));
  139.  
  140.                     TextFont(applFont);
  141.                     MoveTo(r.left + cur_x, r.top + top + sys_font_info.ascent + sys_font_info.descent + 0 + appl_font_info.ascent);
  142.                     DrawString(entry.extension);
  143.  
  144.                     if select then begin
  145.                         rgn2 := NewRgn;
  146.                         RectRgn(rgn2, r);
  147.                         if has_colorQD then begin
  148.                             BitClr(Ptr(HiliteMode), pHiliteBit);
  149.                         end; (* if *)
  150.                         XorRgn(rgn, rgn2, rgn2);
  151.                         InvertRgn(rgn2);
  152.                         DisposeRgn(rgn2);
  153.                     end; (* if *)
  154.                     if rgn <> nil then begin
  155.                         DisposeRgn(rgn);
  156.                     end; (* if *)
  157.                 end; (* if *)
  158.             end;
  159.         end;
  160.  
  161.     begin
  162.         offset := offset; { Unused }
  163.         SetPort(lh^^.port);
  164.         entries := Handle(windowinfo[GetWindowType(lh^^.port)].items[ditList]^.data);
  165.         case message of
  166.             lInitMsg: 
  167.                 ;
  168.             lDrawMsg: 
  169.                 LDDraw;
  170.             lHiliteMsg: 
  171.                 LDDraw;
  172.             lCloseMsg: 
  173.                 LDClose;
  174.         end;
  175.     end; (* MyLDEF *)
  176.  
  177.     procedure UserItemUpdate (dlg: DialogPtr; item: integer);
  178.         var
  179.             list_rect: Rect;
  180.     begin
  181.         GetDItemRect(dlg, item, list_rect);
  182.         PenNormal;
  183.         InsetRect(list_rect, -1, -1);
  184.         FrameRect(list_rect);
  185.         LUpdate(dlg^.visRgn, ListHandle(windowinfo[GetWindowType(dlg)].items[item]^.spare_data));
  186.     end; (* UserItemUpdate *)
  187.  
  188.     function WhatOpenFileMap (wt: WindowType; item: integer): OSErr;
  189.         var
  190.             dlg: DialogPtr;
  191.             entries: Handle;
  192.             attr: longint;
  193.             err: OSErr;
  194.             count: longint;
  195.             list_rect: Rect;
  196.             data_rect: Rect;
  197.             cell_size: Point;
  198.             lh: ListHandle;
  199.     begin
  200.         windowinfo[wt].items[item]^.spare_data := nil;
  201.         windowinfo[wt].items[item]^.data := nil;
  202.         err := noErr;
  203.         dlg := windowinfo[wt].window;
  204.         SetDItemHandle(dlg, item, @UserItemUpdate);
  205.         if ICMapErr(ICGetPrefHandle(GetInstance, windowinfo[wt].items[item]^.key, attr, entries)) <> noErr then begin
  206.             entries := NewHandle(0);
  207.             if entries = nil then begin
  208.                 err := memFullErr;
  209.             end; (* if *)
  210.         end; (* if *)
  211.         ProcessAttributes(wt, item, attr);
  212.         if err = noErr then begin
  213.             if ICCountMapEntries(GetInstance, entries, count) <> noErr then begin
  214.                 count := 0;
  215.             end; (* if *)
  216.             windowinfo[wt].items[item]^.data := Ptr(entries);
  217.             GetDItemRect(dlg, item, list_rect);
  218.             list_rect.right := list_rect.right - 15;
  219.             SetRect(data_rect, 0, 0, 1, count);
  220.             SetPt(cell_size, list_rect.right - list_rect.left, kCellHeight);
  221.             lh := LNew(list_rect, data_rect, cell_size, 128, dlg, true, false, false, true);
  222.             if lh = nil then begin
  223.                 err := memFullErr;
  224.             end; (* if *)
  225.         end; (* if *)
  226.         if err = noErr then begin
  227.             lh^^.refCon := ord(@MyLDEF);
  228.             lh^^.selFlags := lOnlyOne;
  229.             windowinfo[wt].items[item]^.spare_data := Ptr(lh);
  230.             DimButtons(wt);
  231.             SetUpDefaultOutline(dlg, ditChange, ditMainUserItem);
  232.             windowinfo[wt].selected_item := ditList;
  233.         end; (* if *)
  234.         WhatOpenFileMap := err;
  235.     end; (* WhatOpenFileMap *)
  236.  
  237.     procedure SetRadio (modal: DialogPtr; value: integer);
  238.     begin
  239.         SetDCtlBoolean(modal, ditAsciiRadio, value = ditAsciiRadio);
  240.         SetDCtlBoolean(modal, ditBinaryRadio, value = ditBinaryRadio);
  241.         SetDCtlBoolean(modal, ditMacintoshRadio, value = ditMacintoshRadio);
  242.     end; (* SetRadio *)
  243.  
  244.     function AddChangeFilter (dlg: DialogPtr; var event: EventRecord; var item: integer): boolean;
  245.         var
  246.             res: boolean;
  247.             ch: char;
  248.     begin
  249.         res := CancelModalFilter(dlg, event, item);
  250.         if not res then begin
  251.             if (event.what = keyDown) and (band(event.modifiers, cmdKey) <> 0) then begin
  252.                 ch := char(band(event.message, charCodeMask));
  253.                 if ch in ['1'..'3'] then begin
  254.                     SetRadio(dlg, ord(ch) - ord('1') + ditAsciiRadio);
  255.                 end; (* if *)
  256.             end; (* if *)
  257.         end; (* if *)
  258.         AddChangeFilter := res;
  259.     end; (* AddChangeFilter *)
  260.  
  261.     function GetMapEntriesResource(var entries:Handle):OSStatus;
  262.         var
  263.             err:OSStatus;
  264.     begin
  265.         UseResFile(app_resfile);
  266.         entries := Get1NamedResource('Pref',kICMapping);
  267.         err := ResError;
  268.         if (entries = nil) & (err = noErr) then begin
  269.             err := resNotFound;
  270.         end;
  271.         GetMapEntriesResource := err;
  272.     end;
  273.     
  274.     function DoDialog (var entry: ICMapEntry): OSErr;
  275.  
  276.         function MapOSType (ot: OSType): Str15;
  277.         begin
  278.             if ot = OSType(0) then begin
  279.                 MapOSType := '';
  280.             end else begin
  281.                 MapOSType := OSTypeToString(ot);
  282.             end; (* if *)
  283.         end; (* MapOSType *)
  284.  
  285.         function MapStr (s: Str255): OSType;
  286.         begin
  287.             s := TPCopy(concat(s, '    '), 1, 4);
  288.             MapStr := StringToOSType(s);
  289.         end; (* MapStr *)
  290.  
  291.         var
  292.             modal: DialogPtr;
  293.  
  294.         procedure DoChooseExample;
  295.             var
  296.                 info: FInfo;
  297.                 err: OSErr;
  298.                 fs, app_fss: FSSpec;
  299.         begin
  300.             err := ICStandardGetFile(OSType(0), fs, info);
  301.             DisplayError(acGetExample, err);
  302.             if err = noErr then begin
  303.                 SetItemText(modal, ditType, MapOSType(info.fdType));
  304.                 SetItemText(modal, ditCreator, MapOSType(info.fdCreator));
  305.                 err := MyGetAPPL(info.fdCreator, app_fss);
  306.                 if err = noErr then begin
  307.                     SetItemText(modal, ditApplicationName, app_fss.name);
  308.                 end else begin
  309.                     SetItemText(modal, ditApplicationName, '');
  310.                 end; (* if *)
  311.             end; (* if *)
  312.         end; (* DoChooseExample *)
  313.  
  314.         function ChoosePost: boolean;
  315.             var
  316.                 info: FInfo;
  317.                 err: OSErr;
  318.                 fs: FSSpec;
  319.         begin
  320.             err := ICStandardGetFile('APPL', fs, info);
  321.             DisplayError(acGetExample, err);
  322.             if err = noErr then begin
  323.                 entry.post_creator := info.fdCreator;
  324.                 entry.post_app_name := fs.name;
  325.             end; (* if *)
  326.             ChoosePost := err = noErr;
  327.         end;
  328.  
  329.         procedure SetPostInfo;
  330.         begin
  331.             if entry.post_creator <> OSType(0) then begin
  332.                 SetDCtlTitle(modal, ditPostButton, concat(GetIndStr(128, 24), entry.post_app_name, GetIndStr(128, 25)));
  333.                 SetItemText(modal, ditPostCreator, MapOSType(entry.post_creator));
  334.             end else begin
  335.                 SetDCtlTitle(modal, ditPostButton, GetIndStr(128, 23));
  336.                 SetItemText(modal, ditPostCreator, '');
  337.             end;
  338.             SetDCtlBoolean(modal, ditPost, TPbtst(entry.flags, ICmap_post_bit));
  339.         end;
  340.  
  341.         procedure SetAllTheStuff;
  342.         begin
  343.             SetItemText(modal, ditEntryName, entry.entry_name);
  344.             SetItemText(modal, ditExtension, entry.extension);
  345.             SetItemText(modal, ditMIMEType, entry.MIME_type);
  346.             SetDCtlBoolean(modal, ditAsciiRadio, not TPbtst(entry.flags, ICmap_binary_bit));
  347.             SetDCtlBoolean(modal, ditBinaryRadio, TPbtst(entry.flags, ICmap_binary_bit) and not (TPbtst(entry.flags, ICmap_resource_fork_bit)));
  348.             SetDCtlBoolean(modal, ditMacintoshRadio, TPbtst(entry.flags, ICmap_binary_bit) and (TPbtst(entry.flags, ICmap_resource_fork_bit)));
  349.             SetDCtlBoolean(modal, ditNotForIncoming, TPbtst(entry.flags, ICmap_not_incoming_bit));
  350.             SetDCtlBoolean(modal, ditNotForOutgoing, TPbtst(entry.flags, ICmap_not_outgoing_bit));
  351.             SetItemText(modal, ditType, MapOSType(entry.file_type));
  352.             SetItemText(modal, ditCreator, MapOSType(entry.file_creator));
  353.             SetItemText(modal, ditApplicationName, entry.creator_app_name);
  354.             SetPostInfo;
  355.             SelectDialogItemText(modal, ditEntryName, 0, 32767);
  356.         end;
  357.         
  358.         procedure SetAddEditDefaults;
  359.             var
  360.                 err:OSStatus;
  361.                 ext:Str255;
  362.                 entries:Handle;
  363.                 new_entry: ICMapEntry;
  364.                 a: integer;
  365.         begin
  366.             GetItemText(modal, ditExtension, ext);
  367.             err := GetMapEntriesResource(entries);
  368.             if err = noErr then begin
  369.                 err := ICMapEntriesFilename (GetInstance, entries, ext, new_entry);
  370.             end;
  371.             if err = noErr then begin
  372.                 entry := new_entry;
  373.                 SetAllTheStuff;
  374.             end;
  375.             if err = icPrefNotFoundErr then begin
  376.                 ParamText('', ext, '', '');
  377.                 a := StopAlert(166, @OKModalFilter);
  378.             end else begin
  379.                 DisplayError(acSetDefaults, err);
  380.             end;
  381.         end;
  382.         
  383.         var
  384.             err: OSErr;
  385.             item: integer;
  386.             flags: longint;
  387.             tmpstr: Str255;
  388.             dummy: boolean;
  389.             saved_state: Ptr;
  390.     begin
  391.         err := noErr;
  392.         modal := GetNewDialog(800, nil, WindowPtr(-1));
  393.         if modal = nil then begin
  394.             err := memFullErr;
  395.         end; (* if *)
  396.         if err = noErr then begin
  397.             SetUpDefaultOutline(modal, ditOK, ditEditorUserItem);
  398.             SetAllTheStuff;
  399.             
  400.             ShowWindow(modal);
  401.             DisableMenuBar(saved_state, -1);
  402.             InitCursor;
  403.             repeat
  404.                 MovableModalDialog(@AddChangeFilter, item);
  405.                 case item of
  406.                     ditAsciiRadio..ditMacintoshRadio:  begin
  407.                         SetRadio(modal, item);
  408.                     end;
  409.                     ditNotForIncoming..ditNotForOutgoing:  begin
  410.                         ToggleDCtlBoolean(modal, item);
  411.                     end;
  412.                     ditChooseExample:  begin
  413.                         DoChooseExample;
  414.                     end;
  415.                     ditPost:  begin
  416.                         if not TPbtst(entry.flags, ICmap_post_bit) then begin
  417.                             if (entry.post_creator = OSType(0)) then begin
  418.                                 if entry.file_creator <> OSType(0) then begin
  419.                                     entry.post_creator := entry.file_creator;
  420.                                     entry.post_app_name := entry.creator_app_name;
  421.                                 end else begin
  422.                                     dummy := ChoosePost;
  423.                                 end;
  424.                             end;
  425.                             if entry.post_creator <> OSType(0) then begin
  426.                                 bset(entry.flags, ICmap_post_bit);
  427.                             end;
  428.                         end else begin
  429.                             bclr(entry.flags, ICmap_post_bit);
  430.                         end;
  431.                         SetPostInfo;
  432.                     end;
  433.                     ditPostButton:  begin
  434.                         if ChoosePost then begin
  435.                             bset(entry.flags, ICmap_post_bit);
  436.                         end;
  437.                         SetPostInfo;
  438.                     end;
  439.                     ditAddEditDefaults: begin
  440.                         SetAddEditDefaults;
  441.                     end;
  442.                     otherwise
  443.                         ;
  444.                 end; (* case *)
  445.             until item in [ditOK, ditCancel];
  446.             if item = ditOK then begin
  447.                 GetItemText(modal, ditEntryName, entry.entry_name);
  448.                 GetItemText(modal, ditExtension, entry.extension);
  449.                 GetItemText(modal, ditMIMEType, entry.MIME_type);
  450.  
  451.                 flags := band(entry.flags, BNOT(ICmap_binary_mask + ICmap_data_fork_mask + ICmap_resource_fork_mask + ICmap_not_incoming_mask + ICmap_not_outgoing_mask));
  452.                 flags := flags + ICmap_data_fork_mask;
  453.                 if not GetDCtlBoolean(modal, ditAsciiRadio) then begin
  454.                     flags := flags + ICmap_binary_mask;
  455.                 end; (* if *)
  456.                 if GetDCtlBoolean(modal, ditMacintoshRadio) then begin
  457.                     flags := flags + ICmap_resource_fork_mask;
  458.                 end; (* if *)
  459.                 if GetDCtlBoolean(modal, ditNotForIncoming) then begin
  460.                     flags := flags + ICmap_not_incoming_mask;
  461.                 end; (* if *)
  462.                 if GetDCtlBoolean(modal, ditNotForOutgoing) then begin
  463.                     flags := flags + ICmap_not_outgoing_mask;
  464.                 end; (* if *)
  465.                 entry.flags := flags;
  466.  
  467.                 GetItemText(modal, ditType, tmpstr);
  468.                 entry.file_type := MapStr(tmpstr);
  469.                 GetItemText(modal, ditCreator, tmpstr);
  470.                 entry.file_creator := MapStr(tmpstr);
  471.                 GetItemText(modal, ditApplicationName, entry.creator_app_name);
  472.             end else begin
  473.                 err := userCanceledErr;
  474.             end; (* if *)
  475.         end; (* if *)
  476.         if modal <> nil then begin
  477.             ReEnableMenuBar(saved_state);
  478.             DisposeDialog(modal);
  479.         end; (* if *)
  480.         DoDialog := err;
  481.     end; (* DoDialog *)
  482.  
  483.     function DoAddChange (selection: integer; var entry: ICMapEntry; entries: Handle; lh: ListHandle): OSErr;
  484.         var
  485.             junkint: integer;
  486.             err: OSErr;
  487.             pos: longint;
  488.     begin
  489.         if selection = -1 then begin
  490.             with entry do begin
  491.                 version := 0;
  492.                 file_type := OSType(0);
  493.                 file_creator := OSType(0);
  494.                 post_creator := OSType(0);
  495.                 flags := 0;
  496.                 extension := '';
  497.                 creator_app_name := '';
  498.                 post_app_name := '';
  499.                 MIME_type := '';
  500.                 entry_name := '';
  501.             end; (* with *)
  502.             err := noErr;
  503.         end else begin
  504.             err := ICMapErr(ICGetIndMapEntry(GetInstance, entries, selection + 1, pos, entry));
  505.         end; (* if *)
  506.  
  507.         if err = noErr then begin
  508.             err := DoDialog(entry);
  509.         end; (* if *)
  510.  
  511.         if err = noErr then begin
  512.             if selection = -1 then begin
  513.                 err := ICMapErr(ICAddMapEntry(GetInstance, entries, entry));
  514.                 if err = noErr then begin
  515.                     junkint := LAddRow(1, 32767, lh);
  516.                 end; (* if *)
  517.             end else begin
  518.                 err := ICMapErr(ICSetMapEntry(GetInstance, entries, pos, entry));
  519.             end; (* if *)
  520.         end; (* if *)
  521.         DoAddChange := err;
  522.     end; (* DoAddChange *)
  523.  
  524.     function SetEntriesHandle(wt:WindowType; entries:Handle):OSStatus;
  525.         var
  526.             err:OSStatus;
  527.             tmph:Handle;
  528.             count:longInt;
  529.             list:ListHandle;
  530.             window:WindowPtr;
  531.             row:integer;
  532.     begin
  533.         list := ListHandle(windowinfo[wt].items[ditList]^.spare_data);
  534.         err := ICCountMapEntries(GetInstance, entries, count);
  535.         if err = noErr then begin
  536.             window := GetWindowPtr(wt);
  537.             LDelRow(list^^.dataBounds.bottom+10,0,list);
  538.             tmph := entries;
  539.             entries := Handle(windowinfo[wt].items[ditList]^.data);
  540.             windowinfo[wt].items[ditList]^.data := Ptr(tmph);
  541.             row := LAddRow(count ,0,list);
  542.         end;
  543.         DisposeHandle(entries);
  544.         SetEntriesHandle := err;
  545.     end;
  546.     
  547.     type
  548.         SmallRecord = record
  549.             position:longInt;
  550.             key:Str31;
  551.         end;
  552.         SmallArray = array[1..10000] of SmallRecord;
  553.         SmallArrayPtr = ^SmallArray;
  554.         SmallArrayHandle = ^SmallArrayPtr;
  555.     
  556.     var
  557.         SmallSort_v, SmallSort_t : SmallRecord;
  558.         (* I took these variables out of QuickSort to reduce the stack usage.  I also made them globals to make them
  559.                 go faster.
  560.         *)
  561.         SmallSort_small:SmallArrayPtr;
  562.         
  563.     function SmallSort(small:SmallArrayHandle; count:longInt) : OSErr;
  564.     
  565.     label 666;
  566.     
  567.         procedure QuickSort(l,r:longInt);
  568.             var
  569.                 i,j:longInt;
  570.         begin
  571.             if r > l then begin
  572.                 SmallSort_v := SmallSort_small^[ r ];            (* (l + r) div 2 *)
  573.                 i := l - 1;
  574.                 j := r;
  575.                 repeat
  576.                     repeat
  577.                         i := i + 1;
  578.                     until IUCompString(SmallSort_small^[i].key, SmallSort_v.key) >= 0;
  579.                     repeat
  580.                         j := j - 1;
  581.                     until  IUCompString(SmallSort_small^[j].key, SmallSort_v.key) <= 0;
  582.                     SmallSort_t := SmallSort_small^[i];
  583.                     SmallSort_small^[i] := SmallSort_small^[j];
  584.                     SmallSort_small^[j] := SmallSort_t;
  585.                 until j <= i;
  586.                 SmallSort_small^[j] := SmallSort_small^[i];
  587.                 SmallSort_small^[i] := SmallSort_small^[r];
  588.                 SmallSort_small^[r] := SmallSort_t;
  589.                 if StackSpace < 4096 then begin
  590.                     goto 666;
  591.                 end; (* if *)
  592.                 QuickSort(l, i-1);
  593.                 QuickSort(i+1, r);
  594.             end;
  595.         end;
  596.         
  597.         var
  598.             s : SInt8;
  599.     begin
  600.         s := HGetState(Handle(small));
  601.         HLock(Handle(small));
  602.         SmallSort_small := small^;
  603.         
  604.         SmallSort := memFullErr;
  605.         QuickSort(1,count);
  606.         SmallSort := noErr;
  607.     666:
  608.         HSetState(Handle(small), s);
  609.     end;
  610.     
  611.     procedure DoSort(wt: WindowType; item:integer);
  612.         var
  613.             err:OSStatus;
  614.             entries, sorted_entries:Handle;
  615.             small:SmallArrayHandle;
  616.             count:longInt;
  617.             pos:longInt;
  618.             entry: ICMapEntry;
  619.             i:longInt;
  620.     begin
  621.         SetCursor(GetCursor(watchCursor)^^);
  622.         entries := Handle(windowinfo[wt].items[ditList]^.data);
  623.         sorted_entries := NewHandle(0);
  624.         err := ICCountMapEntries(GetInstance, entries, count);
  625.         if err = noErr then begin
  626.             small := SmallArrayHandle(NewHandle(SizeOf(SmallRecord)*count));
  627.             err := MemError;
  628.             if err = noErr then begin
  629.                 pos := 0;
  630.                 for i:= 1 to count do begin
  631.                     err := ICGetMapEntry(GetInstance, entries, pos, entry);
  632.                     if err <> noErr then begin
  633.                         leave;
  634.                     end;
  635.                     small^^[i].position := i;
  636.                     case item of
  637.                         ditSortExtension:begin
  638.                             small^^[i].key := TPCopy(entry.extension, 1, 31);
  639.                         end;
  640.                         ditSortApplication:begin
  641.                             small^^[i].key := TPCopy(entry.creator_app_name, 1, 31);
  642.                         end;
  643.                         ditSortName:begin
  644.                             small^^[i].key := TPCopy(entry.entry_name, 1, 31);
  645.                         end;
  646.                     end; 
  647.                     pos := pos + entry.total_length;
  648.                 end;
  649.                 if err = noErr then begin
  650.                     err := SmallSort(small, count);
  651.                 end; (* if *)
  652.                 if err = noErr then begin
  653.                     HLock(entries);
  654.                     for i:= 1 to count do begin
  655.                         err := ICGetIndMapEntry(GetInstance, entries, small^^[i].position, pos, entry);
  656.                         if err = noErr then begin
  657.                             err := PtrAndHand(longInt(entries^) + pos, sorted_entries, entry.total_length);
  658.                         end;
  659.                         if err <> noErr then begin
  660.                             leave;
  661.                         end;
  662.                     end;
  663.                     HUnlock(entries);
  664.                 end;
  665.                 if err = noErr then begin
  666.                     err := SetEntriesHandle(wt, sorted_entries);
  667.                     sorted_entries := nil;
  668.                 end;
  669.             end;
  670.             DisposeHandle(Handle(small));
  671.         end;
  672.         DisposeHandle(sorted_entries);
  673.         InitCursor;
  674.         DisplayError(acSort, err);
  675.     end;
  676.     
  677.     procedure DoSetDefaults(wt: WindowType);
  678.         var
  679.             err:OSStatus;
  680.             entries:Handle;
  681.     begin
  682.         if CautionAlert(165, @CancelModalFilter) = 1 then begin
  683.             err := GetMapEntriesResource(entries);
  684.             if err = noErr then begin
  685.                 DetachResource(entries);
  686.                 err := SetEntriesHandle(wt, entries);
  687.             end;
  688.             DisplayError(acSetDefaults, err);
  689.             if err = noErr then begin
  690.                 DirtyDocument;
  691.             end; (* if *)
  692.         end;
  693.     end;
  694.     
  695.     function WhatClickFileMap (wt: WindowType; item: integer; er: eventRecord): OSErr;
  696.         var
  697.             lh: ListHandle;
  698.             entry: ICMapEntry;
  699.             entries: Handle;
  700.             selection: integer;
  701.             err: OSErr;
  702.             pos: longint;
  703.     begin
  704.         entries := Handle(windowinfo[wt].items[ditList]^.data);
  705.         lh := ListHandle(windowinfo[wt].items[ditList]^.spare_data);
  706.         GlobalToLocal(er.where);
  707.         selection := SelectedLine(lh);
  708.         err := 1;
  709.         case item of
  710.             ditAdd: 
  711.                 err := DoAddChange(-1, entry, entries, lh);
  712.             ditChange: 
  713.                 err := DoAddChange(selection, entry, entries, lh);
  714.             ditDelete: 
  715.                 if selection <> -1 then begin
  716.                     err := ICMapErr(ICGetIndMapEntry(GetInstance, entries, selection + 1, pos, entry));
  717.                     if err = noErr then begin
  718.                         err := ICMapErr(ICDeleteMapEntry(GetInstance, entries, pos));
  719.                     end; (* if *)
  720.                     if err = noErr then begin
  721.                         LDelRow(1, selection, lh);
  722.                     end; (* if *)
  723.                 end; (* if *)
  724.             ditList:  begin
  725.                 if LClick(er.where, 0, lh) then begin
  726.                     if IsLocked(wt, item) then begin
  727.                         LockedAlert(wt, item);
  728.                         err := userCanceledErr;
  729.                     end else begin
  730.                         FlashItem(windowinfo[wt].window, ditChange);
  731.                         err := DoAddChange(SelectedLine(lh), entry, entries, lh);            (* selection may have been changed by LClick *)
  732.                     end; (* if *)
  733.                 end; (* if *)
  734.             end;
  735.             ditSortExtension, ditSortApplication, ditSortName:begin
  736.                 DoSort(wt, item);
  737.             end;
  738.             ditDefaults:begin
  739.                 DoSetDefaults(wt);
  740.             end;
  741.         end; (* case *)
  742.         if err = noErr then begin
  743.             DirtyDocument;
  744.         end; (* if *)
  745.         if err = 1 then begin
  746.             err := noErr;
  747.         end; (* if *)
  748.         DimButtons(wt);
  749.         WhatClickFileMap := err;
  750.     end; (* WhatClickFileMap *)
  751.  
  752.     function WhatFlushFileMap (wt: WindowType; item: integer): OSErr;
  753.         var
  754.             err: OSErr;
  755.     begin
  756.         if IsLocked(wt, item) then begin
  757.             err := noErr;
  758.         end else begin
  759.             err := ICMapErr(ICSetPrefHandle(GetInstance, windowinfo[wt].items[item]^.key, ICattr_no_change, Handle(windowinfo[wt].items[item]^.data)));
  760.         end;
  761.         WhatFlushFileMap := err;
  762.     end; (* WhatFlushFileMap *)
  763.  
  764.     function WhatCloseFileMap (wt: WindowType; item: integer): OSErr;
  765.     begin
  766.         LDispose(ListHandle(windowinfo[wt].items[item]^.spare_data));
  767.         DisposeHandle(Handle(windowinfo[wt].items[item]^.data));
  768.         WhatCloseFileMap := noErr;
  769.     end; (* WhatCloseFileMap *)
  770.  
  771.     function WhatActivateFileMap (wt: WindowType; item: integer; activate: boolean): OSErr;
  772.     begin
  773.         LActivate(activate, ListHandle(windowinfo[wt].items[item]^.spare_data));
  774.         WhatActivateFileMap := noErr;
  775.     end; (* WhatActivateFileMap *)
  776.  
  777.     function GetEntryName (list: ListHandle; c: cell): str255;
  778.         var
  779.             entry: ICMapEntry;
  780.             err: OSErr;
  781.             junkpos: longint;
  782.             entries: handle;
  783.     begin
  784.         GetEntryName := '';
  785.         entries := Handle(windowinfo[GetWindowType(list^^.port)].items[ditList]^.data);
  786.         err := ICMapErr(ICGetIndMapEntry(GetInstance, entries, c.v + 1, junkpos, entry));
  787.         if err = noErr then begin
  788.             GetEntryName := entry.extension;
  789.         end;
  790.     end;
  791.  
  792.     function WhatKeyFileMap (wt: WindowType; item: integer; er: EventRecord): OSErr;
  793.         var
  794.             ch: integer;
  795.             entry: ICMapEntry;
  796.             lh: ListHandle;
  797.             err: OSErr;
  798.     begin
  799.         item := item; { Unused }
  800.         lh := ListHandle(windowinfo[wt].items[ditList]^.spare_data);
  801.         err := noErr;
  802.         if (er.what = keyDown) or (er.what = autoKey) then begin
  803.             ch := BAND(er.message, $FF);
  804.             case ch of
  805.                 crChar, enterChar:  begin
  806.                     if GetDCtlEnable(windowinfo[wt].window, ditChange) then begin
  807.                         FlashItem(windowinfo[wt].window, ditChange);
  808.                         err := DoAddChange(SelectedLine(lh), entry, Handle(windowinfo[wt].items[ditList]^.data), lh);
  809.                         if err = noErr then begin
  810.                             DirtyDocument;
  811.                         end;
  812.                     end; (* if *)
  813.                 end;
  814.                 otherwise begin
  815.                     DoListKey(lh, er, GetEntryName);
  816.                     DimButtons(wt);
  817.                 end;
  818.             end;
  819.         end;
  820.         WhatKeyFileMap := err;
  821.     end; (* WhatKeyFileMap *)
  822.  
  823.     function WhatCursorFileMap (wt: WindowType; item: integer; pt: Point; cursorid: integer): OSErr;
  824.         var
  825.             r: Rect;
  826.     begin
  827.         GetDItemRect(windowinfo[wt].window, item, r);
  828.         InsetRect(r, 15, 0);
  829.         if PtInRect(pt, r) then begin
  830.             SetCursor(GetCursor(cursorid)^^);
  831.         end else begin
  832.             InitCursor;
  833.         end; (* if *)
  834.         WhatCursorFileMap := noErr;
  835.     end; (* WhatCursorFileMap *)
  836.  
  837.     procedure MappingSetSelection(key:Str255);
  838.         var
  839.             err:OSStatus;
  840.             window:WindowPtr;
  841.             count, i, pos:longInt;
  842.             entries:Handle;
  843.             entry: ICMapEntry;
  844.             list:ListHandle;
  845.     begin
  846.         window := GetWindowPtr(WT_FileMapping);
  847.         if window <> nil then begin
  848.             entries := Handle(windowinfo[WT_FileMapping].items[ditList]^.data);
  849.             list := ListHandle(windowinfo[WT_FileMapping].items[ditList]^.spare_data);
  850.             err := ICCountMapEntries(GetInstance, entries, count);
  851.             if err = noErr then begin
  852.                 pos := 0;
  853.                 for i:= 1 to count do begin
  854.                     err := ICGetMapEntry(GetInstance, entries, pos, entry);
  855.                     if err <> noErr then begin
  856.                         leave;
  857.                     end;
  858.                     pos := pos + entry.total_length;
  859.                     if IUEqualString(entry.extension, key) = 0 then begin
  860.                         LSetSingleSelection(list, i - 1);
  861.                         DimButtons(WT_FileMapping);
  862.                         if GetDCtlEnable(window, ditChange) then begin
  863.                             err := DoAddChange(i - 1, entry, entries, list);
  864.                         end;
  865.                         leave;
  866.                     end;
  867.                 end;
  868.             end;
  869.         end;
  870.     end;
  871.     
  872. end. (* ICFileMapWhat *)
  873.