home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / YellowBox / Kits / MiscTableScroll-138.1 / Examples / LazyScrollDir / DirWindow.m < prev    next >
Encoding:
Text File  |  1998-03-31  |  40.2 KB  |  1,294 lines

  1. //=============================================================================
  2. //
  3. //  Copyright (C) 1995,1996,1997,1998 by Paul S. McCarthy and Eric Sunshine.
  4. //        Written by Paul S. McCarthy and Eric Sunshine.
  5. //                All Rights Reserved.
  6. //
  7. //    This notice may not be removed from this source code.
  8. //
  9. //    This object is included in the MiscKit by permission from the authors
  10. //    and its use is governed by the MiscKit license, found in the file
  11. //    "License.rtf" in the MiscKit distribution.  Please refer to that file
  12. //    for a list of all applicable permissions and restrictions.
  13. //
  14. //=============================================================================
  15. //-----------------------------------------------------------------------------
  16. // DirWindow.m
  17. //
  18. //    Manages window which displays directory listing.
  19. //
  20. //-----------------------------------------------------------------------------
  21. //-----------------------------------------------------------------------------
  22. // $Id: DirWindow.m,v 1.7 98/03/30 00:19:19 sunshine Exp $
  23. // $Log:    DirWindow.m,v $
  24. // Revision 1.7  98/03/30  00:19:19  sunshine
  25. // v18.1: Wasn't respecting selected-text color.  Problem was cell's "owner"
  26. // was never getting set.
  27. // Now uses NSColor's "system" color by default for window rather than
  28. // hard-wired light-gray.
  29. // Added -tableScrollIgnoreModifierKeysWhileDragging: returning NO.
  30. // Had to implement -tableScroll:draggingSourceOperationMaskForLocal: since
  31. // in MiscTableScroll v126.1 the default changed from "copy" to "generic".
  32. // 
  33. // Revision 1.6  97/11/24  19:50:47  sunshine
  34. // v17.1: Fixed bug: Menu was sending -print: to first-responder even though
  35. // any control can be first-responder, rather than just MiscTableScroll.
  36. // Added row-numbers switch.  Adjusted initial cascade position for NT.
  37. // 
  38. // Revision 1.5  97/07/08  12:46:32  sunshine
  39. // v16.1: Synchronized with NEXTSTEP 3.3 LazyScrollDir v16.
  40. //-----------------------------------------------------------------------------
  41. #import "DirWindow.h"
  42. #import "Defaults.h"
  43. #import "DirArray.h"
  44. #import <MiscTableScroll/MiscExporter.h>
  45. #import <MiscTableScroll/MiscTableScroll.h>
  46. #import <MiscTableScroll/MiscTableCell.h>
  47. #import <AppKit/NSButton.h>
  48. #import <AppKit/NSFont.h>
  49. #import <AppKit/NSImage.h>
  50. #import <AppKit/NSNibLoading.h>
  51. #import <AppKit/NSPanel.h>
  52. #import <AppKit/NSPasteboard.h>
  53. #import <AppKit/NSTextField.h>
  54. #import <AppKit/NSWorkspace.h>
  55. #import <Foundation/NSFileManager.h>
  56. #import <sys/stat.h>
  57.  
  58. // MS-Windows doesn't define these:
  59. #ifndef S_ISUID
  60. # define S_ISUID 0004000 /* Set user id on execution */
  61. #endif
  62. #ifndef  S_ISGID
  63. # define S_ISGID 0002000 /* Set group id on execution */
  64. #endif
  65. #ifndef  S_ISVTX
  66. # define S_ISVTX 0001000 /* Save swapped text even after use */
  67. #endif 
  68.  
  69. enum
  70.     {
  71.     ICON_SLOT,
  72.     NAME_SLOT,
  73.     LOCK_SLOT,
  74.     SIZE_SLOT,
  75.     MODIFIED_SLOT,
  76.     PERMS_SLOT,
  77.     OWNER_SLOT,
  78.     GROUP_SLOT,
  79.     HARDLINKS_SLOT,
  80.     SOFTLINK_SLOT,
  81.  
  82.     MAX_SLOT
  83.     };
  84.  
  85. static int const CASCADE_MAX = 10;
  86. static int CASCADE_COUNTER = 0;
  87. static float CASCADE_ORIGIN_X;
  88. static float CASCADE_ORIGIN_Y;
  89. static float CASCADE_DELTA_X;
  90. static float CASCADE_DELTA_Y;
  91.  
  92. static BOOL DEFAULT_AUTO_SORT;
  93. static BOOL DEFAULT_ROW_NUMBERS;
  94. static BOOL DEFAULT_SHOW_HIDDEN;
  95. static BOOL DEFAULT_HIGHLIGHT_DIRS;
  96. static BOOL DEFAULT_DRAG_UNSCALED;
  97. static NSColor* DEFAULT_COLOR;
  98. static NSSize DEFAULT_WIN_SIZE;
  99. static NSFont* DEFAULT_FONT;
  100. static NSMutableArray* OPEN_DIRS = 0;
  101. static NSImage* LOCKED_IMAGE = 0;
  102. static NSImage* UNLOCKED_IMAGE = 0;
  103.  
  104. static NSString* const COLOR_DEF = @"DirColor";
  105. static NSString* const SIZE_DEF = @"DirSize";
  106. static NSString* const FONT_DEF = @"DirFont";
  107. static NSString* const SORT_DEF = @"AutoSort";
  108. static NSString* const HIDDEN_DEF = @"ShowHidden";
  109. static NSString* const HLIGHT_DEF = @"HighlightDirs";
  110. static NSString* const UNSCALED_DEF = @"DragUnscaled";
  111. static NSString* const COL_SIZES_DEF = @"ColSizes";
  112. static NSString* const COL_ORDER_DEF = @"ColOrder";
  113. static NSString* const ROW_NUMBERS_DEF = @"RowNumbers";
  114.  
  115. static NSString* const LOCKED_IMAGE_S = @"Lock.secure";
  116. static NSString* const UNLOCKED_IMAGE_S = @"Lock.insecure";
  117.  
  118.  
  119. //-----------------------------------------------------------------------------
  120. // NOTE: USE_PRIVATE_ZONE
  121. //    When set to '1', this program will place each window in a separate
  122. //    NSZone and destroy the zone when the window is closed.  When set to
  123. //    '0' windows are placed in the NSDefaultMallocZone().
  124. //-----------------------------------------------------------------------------
  125. #define    USE_PRIVATE_ZONE 1
  126.  
  127. #if USE_PRIVATE_ZONE
  128. # define EMPLOY_ZONE()    NSCreateZone( NSPageSize(), NSPageSize(), YES )
  129. # define RETIRE_ZONE(Z)    NSRecycleZone(Z)
  130. #else
  131. # define EMPLOY_ZONE()    NSDefaultMallocZone()
  132. # define RETIRE_ZONE(Z)    (void)(Z)
  133. #endif
  134.  
  135.  
  136. //-----------------------------------------------------------------------------
  137. // normalize_path
  138. //-----------------------------------------------------------------------------
  139. static inline NSString* normalize_path( NSString* buff )
  140.     {
  141.     return [buff stringByStandardizingPath];
  142.     }
  143.  
  144.  
  145. //-----------------------------------------------------------------------------
  146. // str_date
  147. //-----------------------------------------------------------------------------
  148. static NSString* str_date( NSDate* d )
  149.     {
  150.     return [d descriptionWithCalendarFormat:@"%m/%d/%y %H:%M"
  151.         timeZone:0 locale:0];
  152.     }
  153.  
  154.  
  155. //-----------------------------------------------------------------------------
  156. // str_perms
  157. //-----------------------------------------------------------------------------
  158. static NSString* str_perms( unsigned long mode, NSString* file_type )
  159.     {
  160.     char c;
  161.     NSMutableString* s = [NSMutableString string];
  162.     if  ([file_type isEqualToString:NSFileTypeDirectory])
  163.     c = 'd';
  164.     else if ([file_type isEqualToString:NSFileTypeCharacterSpecial])
  165.     c = 'c';
  166.     else if ([file_type isEqualToString:NSFileTypeBlockSpecial])
  167.     c = 'b';
  168.     else if ([file_type isEqualToString:NSFileTypeRegular])
  169.     c = '-';
  170.     else if ([file_type isEqualToString:NSFileTypeSymbolicLink])
  171.     c = 'l';
  172.     else if ([file_type isEqualToString:NSFileTypeSocket])
  173.     c = 's';
  174.     else
  175.     c = '?';
  176.     [s appendFormat:@"%c", c];
  177.     [s appendFormat:@"%c", (mode & 0400) ? 'r' : '-'];
  178.     [s appendFormat:@"%c", (mode & 0200) ? 'w' : '-'];
  179.     [s appendFormat:@"%c", (mode & S_ISUID) ? 's' : (mode & 0100) ? 'x' : '-'];
  180.     [s appendFormat:@"%c", (mode & 0040) ? 'r' : '-'];
  181.     [s appendFormat:@"%c", (mode & 0020) ? 'w' : '-'];
  182.     [s appendFormat:@"%c", (mode & S_ISGID) ? 's' : (mode & 0010) ? 'x' : '-'];
  183.     [s appendFormat:@"%c", (mode & 0004) ? 'r' : '-'];
  184.     [s appendFormat:@"%c", (mode & 0002) ? 'w' : '-'];
  185.     [s appendFormat:@"%c", (mode & S_ISVTX) ? 't' : (mode & 0001) ? 'x' : '-'];
  186.  
  187.     return s;
  188.     }
  189.  
  190.  
  191. //-----------------------------------------------------------------------------
  192. // fmt_icon
  193. //-----------------------------------------------------------------------------
  194. static void fmt_icon( MiscTableScroll* ts, NSDictionary* dict, id cell )
  195.     {
  196.     float h,w,s;
  197.     NSImage* i = [dict scaledImage];
  198.  
  199.     w = [ts columnSize:ICON_SLOT];    if (w == 0) w = 18;
  200.     h = [ts uniformSizeRows];        if (h == 0) h = 18;
  201.     s = (w < h ? w : h) - 1.0;
  202.  
  203.     [i setSize:NSMakeSize( s, s )];
  204.     [cell setImage:i];
  205.     }
  206.  
  207.  
  208. //-----------------------------------------------------------------------------
  209. // fmt_lock
  210. //-----------------------------------------------------------------------------
  211. static void fmt_lock( MiscTableScroll* ts, NSDictionary* dict, id cell )
  212.     {
  213.     [cell setState:![[dict objectForKey:DA_IS_LOCKED] boolValue]];
  214.     [cell setEnabled:[[dict objectForKey:DA_CAN_TOGGLE_LOCK] boolValue]];
  215.     }
  216.  
  217.  
  218. //-----------------------------------------------------------------------------
  219. // fmt_name
  220. //-----------------------------------------------------------------------------
  221. static void fmt_name( MiscTableScroll* ts, NSDictionary* dict, id cell )
  222.     {
  223.     [cell setStringValue:[dict objectForKey:DA_SHORT_NAME]];
  224.     }
  225.  
  226.  
  227. //-----------------------------------------------------------------------------
  228. // fmt_size
  229. //-----------------------------------------------------------------------------
  230. static void fmt_size( MiscTableScroll* ts, NSDictionary* dict, id cell )
  231.     {
  232.     [cell setIntValue:[dict fileSize]];
  233.     }
  234.  
  235.  
  236. //-----------------------------------------------------------------------------
  237. // fmt_modified
  238. //-----------------------------------------------------------------------------
  239. static void fmt_modified( MiscTableScroll* ts, NSDictionary* dict, id cell )
  240.     {
  241.     [cell setStringValue:str_date( [dict fileModificationDate] )];
  242.     }
  243.  
  244.  
  245. //-----------------------------------------------------------------------------
  246. // fmt_perms
  247. //-----------------------------------------------------------------------------
  248. static void fmt_perms( MiscTableScroll* ts, NSDictionary* dict, id cell )
  249.     {
  250.     [cell setStringValue:
  251.     str_perms( [dict filePosixPermissions], [dict fileType])];
  252.     }
  253.  
  254.  
  255. //-----------------------------------------------------------------------------
  256. // fmt_owner
  257. //-----------------------------------------------------------------------------
  258. static void fmt_owner( MiscTableScroll* ts, NSDictionary* dict, id cell )
  259.     {
  260.     NSString* s = [dict fileOwnerAccountName];
  261.     [cell setStringValue:(s != 0 ? s : @"")];
  262.     }
  263.  
  264.  
  265. //-----------------------------------------------------------------------------
  266. // fmt_group
  267. //-----------------------------------------------------------------------------
  268. static void fmt_group( MiscTableScroll* ts, NSDictionary* dict, id cell )
  269.     {
  270.     NSString* s = [dict fileGroupOwnerAccountName];
  271.     [cell setStringValue:(s != 0 ? s : @"")];
  272.     }
  273.  
  274.  
  275. //-----------------------------------------------------------------------------
  276. // fmt_hardlinks
  277. //-----------------------------------------------------------------------------
  278. static void fmt_hardlinks( MiscTableScroll* ts, NSDictionary* dict, id cell )
  279.     {
  280.     [cell setIntValue:
  281.     [[dict objectForKey:NSFileReferenceCount] unsignedLongValue]];
  282.     }
  283.  
  284.  
  285. //-----------------------------------------------------------------------------
  286. // fmt_softlink
  287. //-----------------------------------------------------------------------------
  288. static void fmt_softlink( MiscTableScroll* ts, NSDictionary* dict, id cell )
  289.     {
  290.     [cell setStringValue:[dict objectForKey:DA_SOFT_LINK]];
  291.     }
  292.  
  293.  
  294. //-----------------------------------------------------------------------------
  295. // FORMAT_FUNC
  296. //-----------------------------------------------------------------------------
  297.  
  298. typedef void (*FormatFunc)( MiscTableScroll*, NSDictionary*, id );
  299.  
  300. static FormatFunc FORMAT_FUNC[ MAX_SLOT ] =
  301.     {
  302.     fmt_icon,        // ICON_SLOT,
  303.     fmt_name,        // NAME_SLOT,
  304.     fmt_lock,        // LOCK_SLOT,
  305.     fmt_size,        // SIZE_SLOT,
  306.     fmt_modified,        // MODIFIED_SLOT,
  307.     fmt_perms,        // PERMS_SLOT,
  308.     fmt_owner,        // OWNER_SLOT,
  309.     fmt_group,        // GROUP_SLOT,
  310.     fmt_hardlinks,        // HARDLINKS_SLOT,
  311.     fmt_softlink,        // SOFTLINK_SLOT,
  312.     };
  313.  
  314.  
  315. //-----------------------------------------------------------------------------
  316. // format_cell
  317. //-----------------------------------------------------------------------------
  318. static inline void format_cell(
  319.     MiscTableScroll* ts,
  320.     NSDictionary* dict,
  321.     id cell,
  322.     unsigned int col )
  323.     {
  324.     FORMAT_FUNC[ col ]( ts, dict, cell );
  325.     }
  326.  
  327.  
  328. //=============================================================================
  329. // IMPLEMENTATION
  330. //=============================================================================
  331. @implementation DirWindow
  332.  
  333. //-----------------------------------------------------------------------------
  334. // + initCascader
  335. //-----------------------------------------------------------------------------
  336. + (void)initCascader
  337.     {
  338.     NSSize const s = [[NSScreen mainScreen] frame].size;
  339.     CASCADE_ORIGIN_X = s.width / 4;
  340.     CASCADE_ORIGIN_Y = s.height - 60;
  341.     CASCADE_DELTA_X = 20;
  342.     CASCADE_DELTA_Y = 20;
  343.     }
  344.  
  345.  
  346. //-----------------------------------------------------------------------------
  347. // + initialize
  348. //-----------------------------------------------------------------------------
  349. + (void)initialize
  350.     {
  351.     if (self == [DirWindow class])
  352.     {
  353.     [self initCascader];
  354.     OPEN_DIRS = [[NSMutableArray alloc] init];
  355.     LOCKED_IMAGE   = [[NSImage imageNamed:LOCKED_IMAGE_S] retain];
  356.     UNLOCKED_IMAGE = [[NSImage imageNamed:UNLOCKED_IMAGE_S] retain];
  357.     DEFAULT_COLOR = [[Defaults getColor:COLOR_DEF
  358.             fallback:[NSColor controlColor]] retain];
  359.     DEFAULT_AUTO_SORT = [Defaults getBool:SORT_DEF fallback:NO];
  360.     DEFAULT_SHOW_HIDDEN = [Defaults getBool:HIDDEN_DEF fallback:NO];
  361.     DEFAULT_ROW_NUMBERS = [Defaults getBool:ROW_NUMBERS_DEF fallback:NO];
  362.     DEFAULT_HIGHLIGHT_DIRS = [Defaults getBool:HLIGHT_DEF fallback:NO];
  363.     DEFAULT_DRAG_UNSCALED = [Defaults getBool:UNSCALED_DEF fallback:YES];
  364.     }
  365.     }
  366.  
  367.  
  368. //-----------------------------------------------------------------------------
  369. // - cascade
  370. //-----------------------------------------------------------------------------
  371. - (void)cascade
  372.     {
  373.     float top,left;
  374.     left = CASCADE_ORIGIN_X + (CASCADE_DELTA_X * CASCADE_COUNTER);
  375.     top  = CASCADE_ORIGIN_Y - (CASCADE_DELTA_Y * CASCADE_COUNTER);
  376.     [window setFrameTopLeftPoint:NSMakePoint( left, top )];
  377.     if (++CASCADE_COUNTER >= CASCADE_MAX)
  378.     CASCADE_COUNTER = 0;
  379.     }
  380.  
  381.  
  382. //-----------------------------------------------------------------------------
  383. // - isDir:
  384. //-----------------------------------------------------------------------------
  385. - (BOOL)isDir:(int)r
  386.     {
  387.     return [[[dirArray objectAtIndex:r]
  388.     objectForKey:DA_IS_DIRECTORY] boolValue];
  389.     }
  390.  
  391.  
  392. //-----------------------------------------------------------------------------
  393. // - updateButtons
  394. //-----------------------------------------------------------------------------
  395. - (void)updateButtons
  396.     {
  397.     BOOL const enable = [scroll numberOfSelectedRows] == 1 &&
  398.             [self isDir:[scroll selectedRow]];
  399.     if (enable != [cdButton isEnabled])
  400.     [cdButton setEnabled:enable];
  401.     }
  402.  
  403.  
  404. //-----------------------------------------------------------------------------
  405. // - scrollColor
  406. //-----------------------------------------------------------------------------
  407. - (NSColor*)scrollColor
  408.     {
  409.     if ([DEFAULT_COLOR isEqual:[NSColor controlColor]])
  410.         return [MiscTableScroll defaultBackgroundColor];
  411.     else
  412.         return DEFAULT_COLOR;
  413.     }
  414.  
  415.  
  416. //-----------------------------------------------------------------------------
  417. // - tableScroll:cellAtRow:column:
  418. //-----------------------------------------------------------------------------
  419. - (id)tableScroll:(MiscTableScroll*)ts cellAtRow:(int)row column:(int)col
  420.     {
  421.     id cell = [lazyRow objectAtIndex:col];
  422.     NSDictionary* dict = [dirArray objectAtIndex:row];
  423.     format_cell( ts, dict, cell, col );
  424.     if ([cell respondsToSelector:@selector(setBackgroundColor:)])
  425.     {
  426.     if (highlightDirs && [self isDir:row])
  427.         [cell setBackgroundColor:[NSColor cyanColor]];
  428.     else
  429.         [cell setBackgroundColor:[ts backgroundColor]];
  430.     }
  431.     return cell;
  432.     }
  433.  
  434.  
  435. //-----------------------------------------------------------------------------
  436. // - tableScroll:stringValueAtRow:column:
  437. //-----------------------------------------------------------------------------
  438. - (NSString*)tableScroll:(MiscTableScroll*)ts
  439.     stringValueAtRow:(int)r column:(int)c
  440.     {
  441.     NSString* rc = 0;
  442.     if (r < [dirArray count])
  443.     {
  444.     NSDictionary* dict = [dirArray objectAtIndex:r];
  445.     switch (c)
  446.         {
  447.         case SIZE_SLOT:
  448.         rc = [[dict objectForKey:NSFileSize] stringValue];
  449.         break;
  450.         case MODIFIED_SLOT:
  451.         rc = str_date( [dict fileModificationDate] );
  452.         break;
  453.         case PERMS_SLOT:
  454.         rc = str_perms( [dict filePosixPermissions], [dict fileType] );
  455.         break;
  456.         case OWNER_SLOT:
  457.         rc = [dict fileOwnerAccountName];
  458.         break;
  459.         case GROUP_SLOT:
  460.         rc = [dict fileGroupOwnerAccountName];
  461.         break;
  462.         case HARDLINKS_SLOT:
  463.         rc = [[dict objectForKey:NSFileReferenceCount] stringValue];
  464.         break;
  465.         case NAME_SLOT:
  466.         rc = [dict objectForKey:DA_SHORT_NAME];
  467.         break;
  468.         case SOFTLINK_SLOT:
  469.         rc = [dict objectForKey:DA_SOFT_LINK];
  470.         break;
  471.         case ICON_SLOT:
  472.         case LOCK_SLOT:
  473.         default:
  474.         rc = @"";
  475.         break;
  476.         }
  477.     }
  478.     return (rc != 0 ? rc : @""); // Owner or group may have returned nil.
  479.     }
  480.  
  481.  
  482. //-----------------------------------------------------------------------------
  483. // -intValueAtRow:column:
  484. //-----------------------------------------------------------------------------
  485. - (int)intValueAtRow:(int)r column:(int)c
  486.     {
  487.     int rc = 0;
  488.     if (r < [dirArray count])
  489.     {
  490.     NSDictionary* dict = [dirArray objectAtIndex:r];
  491.     switch (c)
  492.         {
  493.         case LOCK_SLOT:
  494.         rc = [[dict objectForKey:DA_IS_LOCKED] intValue];
  495.         break;
  496.         case SIZE_SLOT:
  497.         rc = [dict fileSize];
  498.         break;
  499.         case MODIFIED_SLOT:
  500.         rc = [[dict fileModificationDate]
  501.             timeIntervalSinceReferenceDate];
  502.         break;
  503.         case PERMS_SLOT:
  504.         rc = [dict filePosixPermissions];
  505.         break;
  506.         case HARDLINKS_SLOT:
  507.         rc = [[dict objectForKey:NSFileReferenceCount] intValue];
  508.         break;
  509.         case OWNER_SLOT:
  510.         case GROUP_SLOT:
  511.         case ICON_SLOT:
  512.         case NAME_SLOT:
  513.         case SOFTLINK_SLOT:
  514.         default:
  515.         break;
  516.         }
  517.     }
  518.     return rc;
  519.     }
  520.  
  521.  
  522. //-----------------------------------------------------------------------------
  523. // - tableScroll:intValueAtRow:column:
  524. //-----------------------------------------------------------------------------
  525. - (int)tableScroll:(MiscTableScroll*)ts intValueAtRow:(int)r column:(int)c
  526.     {
  527.     return [self intValueAtRow:r column:c];
  528.     }
  529.  
  530.  
  531. //-----------------------------------------------------------------------------
  532. // - tableScroll:tagAtRow:column:
  533. //-----------------------------------------------------------------------------
  534. - (int)tableScroll:(MiscTableScroll*)ts tagAtRow:(int)r column:(int)c
  535.     {
  536.     return [self intValueAtRow:r column:c];
  537.     }
  538.  
  539.  
  540. //-----------------------------------------------------------------------------
  541. // - tableScroll:stateAtRow:column:
  542. //-----------------------------------------------------------------------------
  543. - (int)tableScroll:(MiscTableScroll*)ts stateAtRow:(int)r column:(int)c
  544.     {
  545.     return [self intValueAtRow:r column:c];
  546.     }
  547.  
  548.  
  549. //-----------------------------------------------------------------------------
  550. // - tableScroll:fontChangedFrom:to:
  551. //-----------------------------------------------------------------------------
  552. - (void)tableScroll:(MiscTableScroll*)ts
  553.     fontChangedFrom:(NSFont*)oldFont
  554.     to:(NSFont*)newFont
  555.     {
  556.     int col;
  557.     for (col = 0; col < MAX_SLOT; col++)
  558.     [[lazyRow objectAtIndex:col] setFont:newFont];
  559.  
  560.     [DEFAULT_FONT autorelease];
  561.     DEFAULT_FONT = [newFont retain];
  562.     [Defaults set:FONT_DEF font:DEFAULT_FONT];
  563.     }
  564.  
  565.  
  566. //-----------------------------------------------------------------------------
  567. // - tableScroll:border:slotResized:
  568. //-----------------------------------------------------------------------------
  569. - (void)tableScroll:(MiscTableScroll*)ts
  570.     border:(MiscBorderType)b
  571.     slotResized:(int)n
  572.     {
  573.     [Defaults set:COL_SIZES_DEF str:[ts columnSizesAsString]];
  574.     }
  575.  
  576.  
  577. //-----------------------------------------------------------------------------
  578. // saveSlotOrder:border:
  579. //-----------------------------------------------------------------------------
  580. - (void)saveSlotOrder:(MiscTableScroll*)ts
  581.     border:(MiscBorderType)b
  582.     {
  583.     if (b == MISC_COL_BORDER)
  584.     [Defaults set:COL_ORDER_DEF str:[ts columnOrderAsString]];
  585.     }
  586.  
  587.  
  588. //-----------------------------------------------------------------------------
  589. // - tableScroll:border:slotDraggedFrom:to:
  590. //-----------------------------------------------------------------------------
  591. - (void)tableScroll:(MiscTableScroll*)ts
  592.     border:(MiscBorderType)b
  593.     slotDraggedFrom:(int)fromPos
  594.     to:(int)toPos
  595.     {
  596.     [self saveSlotOrder:ts border:b];
  597.     }
  598.  
  599.  
  600. //-----------------------------------------------------------------------------
  601. // - tableScroll:border:slotSortReversed:
  602. //-----------------------------------------------------------------------------
  603. - (void)tableScroll:(MiscTableScroll*)ts
  604.     border:(MiscBorderType)b
  605.     slotSortReversed:(int)n
  606.     {
  607.     [self saveSlotOrder:ts border:b];
  608.     }
  609.  
  610.  
  611. //-----------------------------------------------------------------------------
  612. // - tableScroll:canEdit:atRow:column:
  613. //-----------------------------------------------------------------------------
  614. - (BOOL)tableScroll:(MiscTableScroll*)ts
  615.     canEdit:(NSEvent*)ev
  616.     atRow:(int)row column:(int)col
  617.     {
  618.     return ((ev == 0 || [ev clickCount] == 2) && col == NAME_SLOT &&
  619.     ![[[dirArray objectAtIndex:row] objectForKey:DA_IS_LOCKED] boolValue]);
  620.     }
  621.  
  622.  
  623. //-----------------------------------------------------------------------------
  624. // - tableScroll:setStringValue:atRow:column:
  625. //-----------------------------------------------------------------------------
  626. - (BOOL)tableScroll:(MiscTableScroll*)ts
  627.     setStringValue:(NSString*)s
  628.     atRow:(int)row column:(int)col
  629.     {
  630.     NSMutableDictionary* dict = [dirArray objectAtIndex:row];
  631.     [dict setObject:s forKey:DA_SHORT_NAME];
  632.     [dict setObject:[path stringByAppendingPathComponent:s]
  633.     forKey:DA_LONG_NAME];
  634.     return YES;
  635.     }
  636.  
  637.  
  638. //-----------------------------------------------------------------------------
  639. // -tableScroll:draggingSourceOperationMaskForLocal:
  640. //-----------------------------------------------------------------------------
  641. - (unsigned int)tableScroll:(MiscTableScroll*)s
  642.     draggingSourceOperationMaskForLocal:(BOOL)isLocal
  643.     {
  644.     return NSDragOperationAll;
  645.     }
  646.  
  647.  
  648. //-----------------------------------------------------------------------------
  649. // tableScrollIgnoreModifierKeysWhileDragging:
  650. //-----------------------------------------------------------------------------
  651. - (BOOL)tableScrollIgnoreModifierKeysWhileDragging:(MiscTableScroll*)s
  652.     {
  653.     return NO;
  654.     }
  655.  
  656.  
  657. //-----------------------------------------------------------------------------
  658. // - tableScroll:preparePasteboard:forDragOperationAtRow:column:
  659. //-----------------------------------------------------------------------------
  660. - (void)tableScroll:(MiscTableScroll*)s
  661.     preparePasteboard:(NSPasteboard*)pb 
  662.     forDragOperationAtRow:(int)r column:(int)c
  663.     {
  664.     NSString* file = [[dirArray objectAtIndex:r] objectForKey:DA_LONG_NAME];
  665.     [pb declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType] owner:0];
  666.     [pb setPropertyList:[NSArray arrayWithObject:file]
  667.         forType:NSFilenamesPboardType];
  668.     }
  669.  
  670.  
  671. //-----------------------------------------------------------------------------
  672. // - tableScroll:allowDragOperationAtRow:column:
  673. //-----------------------------------------------------------------------------
  674. - (BOOL)tableScroll:(MiscTableScroll*)s
  675.     allowDragOperationAtRow:(int)r column:(int)c
  676.     {
  677.     return (c == ICON_SLOT);
  678.     }
  679.  
  680.  
  681. //-----------------------------------------------------------------------------
  682. // - tableScroll:imageForDragOperationAtRow:column:
  683. //-----------------------------------------------------------------------------
  684. - (NSImage*)tableScroll:(MiscTableScroll*)s
  685.     imageForDragOperationAtRow:(int)r column:(int)c
  686.     {
  687.     NSDictionary* dict = [dirArray objectAtIndex:r];
  688.     return (dragUnscaled ? [dict unscaledImage] : [dict scaledImage]);
  689.     }
  690.  
  691.  
  692. //-----------------------------------------------------------------------------
  693. // - fillScroll
  694. //-----------------------------------------------------------------------------
  695. - (void)fillScroll
  696.     {
  697.     [scroll renewRows:[dirArray count]];
  698.     if ([scroll autoSortRows])
  699.     [scroll sortRows];
  700.  
  701.     [countField setStringValue:
  702.         [NSString stringWithFormat:@"%d files   %lu bytes",
  703.         [dirArray count], [dirArray totalBytes]]];
  704.  
  705.     [self updateButtons];
  706.     }
  707.  
  708.  
  709. //-----------------------------------------------------------------------------
  710. // - setPath:
  711. //-----------------------------------------------------------------------------
  712. - (void)setPath:(NSString*)dirname
  713.     {
  714.     [path autorelease];
  715.     if (dirname == 0) dirname = NSHomeDirectory();
  716.     if ([dirname length] == 0) dirname = @"/";
  717.     path = [dirname retain];
  718.     [window setTitleWithRepresentedFilename:path];
  719.     }
  720.  
  721.  
  722. //-----------------------------------------------------------------------------
  723. // - loadDirectory:
  724. //-----------------------------------------------------------------------------
  725. - (void)loadDirectory:(NSString*)dirname
  726.     {
  727.     if (![dirArray loadPath:dirname showHidden:showHidden])
  728.     NSRunAlertPanel( @"Can't Read", @"Cannot read directory, %@",
  729.              @"OK", 0, 0, path );
  730.     }
  731.  
  732.  
  733. //-----------------------------------------------------------------------------
  734. // - reload
  735. //-----------------------------------------------------------------------------
  736. - (void)reload
  737.     {
  738.     [scroll abortEditing];
  739.     [self loadDirectory:path];
  740.     [self fillScroll];
  741.     }
  742.  
  743.  
  744. //-----------------------------------------------------------------------------
  745. // - load:
  746. //-----------------------------------------------------------------------------
  747. - (void)load:(NSString*)dirname
  748.     {
  749.     [self setPath:dirname];
  750.     [self reload];
  751.     }
  752.  
  753.  
  754. //-----------------------------------------------------------------------------
  755. // - save:
  756. //-----------------------------------------------------------------------------
  757. - (void)save:(id)sender
  758.     {
  759.     [[MiscExporter commonInstance] exportTableScroll:scroll];
  760.     }
  761.  
  762.  
  763. //-----------------------------------------------------------------------------
  764. // - printDirectory:
  765. //-----------------------------------------------------------------------------
  766. - (void)printDirectory:(id)sender
  767.     {
  768.     [scroll print:self];
  769.     }
  770.  
  771.  
  772. //-----------------------------------------------------------------------------
  773. // - open:
  774. //-----------------------------------------------------------------------------
  775. - (void)open:(id)sender
  776.     {
  777.     if ([scroll hasRowSelection])
  778.     {
  779.     int i;
  780.     NSArray* list = [scroll selectedRows];
  781.     for (i = [list count]; i-- > 0; )
  782.         {
  783.         int const r = [[list objectAtIndex:i] intValue];
  784.         NSString* s = [[dirArray objectAtIndex:r]
  785.                 objectForKey:DA_LONG_NAME];
  786.         if ([self isDir:r])
  787.         [[self class] launchDir:s];
  788.         else
  789.         [[NSWorkspace sharedWorkspace] openFile:s];
  790.         }
  791.     }
  792.     }
  793.  
  794.  
  795. //-----------------------------------------------------------------------------
  796. // - destroy:
  797. //-----------------------------------------------------------------------------
  798. - (void)destroy:(id)sender
  799.     {
  800.     if ([dirArray writable] && [scroll hasRowSelection])
  801.     {
  802.     int i;
  803.     NSArray* list = [scroll selectedRows];
  804.     NSFileManager* manager = [NSFileManager defaultManager];
  805.     for (i = [list count]; i-- > 0; )
  806.         [manager removeFileAtPath:[[dirArray objectAtIndex:i]
  807.             objectForKey:DA_LONG_NAME] handler:0];
  808.     [self reload];
  809.     }
  810.     }
  811.  
  812.  
  813. //-----------------------------------------------------------------------------
  814. // - fileManager:shouldProceedAfterError:
  815. //-----------------------------------------------------------------------------
  816. - (BOOL)fileManager:(NSFileManager*)manager 
  817.     shouldProceedAfterError:(NSDictionary*)errorInfo
  818.     {
  819.     NSRunAlertPanel( @"Error", @"Rename failed: %@.", @"OK", 0, 0, 
  820.             [errorInfo objectForKey:@"Error"]);
  821.     return NO;
  822.     }
  823.  
  824.  
  825. //-----------------------------------------------------------------------------
  826. // - rename:to:
  827. //-----------------------------------------------------------------------------
  828. - (BOOL)rename:(NSString*)oldName to:(NSString*)newName
  829.     {
  830.     return [[NSFileManager defaultManager]
  831.     movePath:[path stringByAppendingPathComponent:oldName]
  832.     toPath:[path stringByAppendingPathComponent:newName]
  833.     handler:self];
  834.     }
  835.  
  836.  
  837. //-----------------------------------------------------------------------------
  838. // - control:textShouldEndEditing:
  839. //-----------------------------------------------------------------------------
  840. - (BOOL)control:(NSControl*)control textShouldEndEditing:(NSText*)fieldEditor
  841.     {
  842.     BOOL accept = YES;
  843.     NSString* oldName;
  844.     NSString* newName;
  845.  
  846.     int const r = [scroll clickedRow];
  847.     int const c = [scroll clickedColumn];
  848.     NSParameterAssert( c == NAME_SLOT );
  849.  
  850.     oldName = [[dirArray objectAtIndex:r] objectForKey:DA_SHORT_NAME];
  851.     newName = [fieldEditor string];
  852.  
  853.     if (![newName isEqualToString:oldName])
  854.     accept = [self rename:oldName to:newName];
  855.  
  856.     if (!accept)
  857.     [fieldEditor setString:oldName];
  858.  
  859.     return accept;
  860.     }
  861.  
  862.  
  863. //-----------------------------------------------------------------------------
  864. // - refreshPressed:
  865. //-----------------------------------------------------------------------------
  866. - (void)refreshPressed:(id)sender
  867.     {
  868.     [self reload];
  869.     }
  870.  
  871.  
  872. //-----------------------------------------------------------------------------
  873. // - cdPressed:
  874. //-----------------------------------------------------------------------------
  875. - (void)cdPressed:(id)sender
  876.     {
  877.     [scroll abortEditing];
  878.     if ([scroll numberOfSelectedRows] == 1)
  879.     {
  880.     MiscCoord_P const row = [scroll selectedRow];
  881.     if ([self isDir:row])
  882.         [self load:normalize_path( [path stringByAppendingPathComponent:
  883.         [[dirArray objectAtIndex:row] objectForKey:DA_SHORT_NAME]] )];
  884.     }
  885.     }
  886.  
  887.  
  888. //-----------------------------------------------------------------------------
  889. // - rowNumbersClick:
  890. //-----------------------------------------------------------------------------
  891. - (void)rowNumbersClick:(id)sender
  892.     {
  893.     BOOL const newVal = ([rowNumbersSwitch state] != 0);
  894.     BOOL const oldVal = [scroll rowTitlesOn];
  895.     if (newVal != oldVal)
  896.     {
  897.     DEFAULT_ROW_NUMBERS = newVal;
  898.     [scroll setRowTitlesOn:DEFAULT_ROW_NUMBERS];
  899.     [Defaults set:ROW_NUMBERS_DEF bool:DEFAULT_ROW_NUMBERS];
  900.     }
  901.     }
  902.  
  903.  
  904. //-----------------------------------------------------------------------------
  905. // - autoSortClick:
  906. //-----------------------------------------------------------------------------
  907. - (void)autoSortClick:(id)sender
  908.     {
  909.     BOOL const switchState = [autoSortSwitch state];
  910.     [scroll abortEditing];
  911.     if (autoSort != switchState)
  912.     {
  913.     DEFAULT_AUTO_SORT = autoSort = switchState;
  914.     [Defaults set:SORT_DEF bool:DEFAULT_AUTO_SORT];
  915.     [scroll setAutoSortRows:switchState];
  916.     if (switchState)
  917.         [scroll sortRows];
  918.     }
  919.     }
  920.  
  921.  
  922. //-----------------------------------------------------------------------------
  923. // - hiddenFilesClick:
  924. //-----------------------------------------------------------------------------
  925. - (void)hiddenFilesClick:(id)sender
  926.     {
  927.     BOOL const switchState = [hiddenFilesSwitch state];
  928.     [scroll abortEditing];
  929.     if (showHidden != switchState)
  930.     {
  931.     DEFAULT_SHOW_HIDDEN = showHidden = switchState;
  932.     [Defaults set:HIDDEN_DEF bool:DEFAULT_SHOW_HIDDEN];
  933.     [self reload];
  934.     }
  935.     }
  936.  
  937.  
  938. //-----------------------------------------------------------------------------
  939. // - highlightClick:
  940. //-----------------------------------------------------------------------------
  941. - (void)highlightClick:(id)sender
  942.     {
  943.     BOOL const switchState = [highlightSwitch state];
  944.     [scroll abortEditing];
  945.     if (highlightDirs != switchState)
  946.     {
  947.     DEFAULT_HIGHLIGHT_DIRS = highlightDirs = switchState;
  948.     [Defaults set:HLIGHT_DEF bool:DEFAULT_HIGHLIGHT_DIRS];
  949.     [scroll setNeedsDisplay:YES];
  950.     }
  951.     }
  952.  
  953.  
  954. //-----------------------------------------------------------------------------
  955. // - dragUnscaledClick:
  956. //-----------------------------------------------------------------------------
  957. - (void)dragUnscaledClick:(id)sender
  958.     {
  959.     BOOL const switchState = [dragUnscaledSwitch state];
  960.     if (dragUnscaled != switchState)
  961.     {
  962.     DEFAULT_DRAG_UNSCALED = dragUnscaled = switchState;
  963.     [Defaults set:UNSCALED_DEF bool:DEFAULT_DRAG_UNSCALED];
  964.     }
  965.     }
  966.  
  967.  
  968. //-----------------------------------------------------------------------------
  969. // - lockClick:
  970. //-----------------------------------------------------------------------------
  971. - (void)lockClick:(id)sender
  972.     {
  973.     int const row = [sender clickedRow];
  974.     NSMutableDictionary* dict = [dirArray objectAtIndex:row];
  975.     if ([[dict objectForKey:DA_CAN_TOGGLE_LOCK] boolValue])
  976.     {
  977.     BOOL const wasLocked = [[dict objectForKey:DA_IS_LOCKED] boolValue];
  978.     [dict setObject:[NSNumber numberWithBool:!wasLocked]
  979.         forKey:DA_IS_LOCKED];
  980.     if ([sender autoSortRows])
  981.         [sender sortRow:row];
  982.     }
  983.     }
  984.  
  985.  
  986. //-----------------------------------------------------------------------------
  987. // - didClick:
  988. //-----------------------------------------------------------------------------
  989. - (void)didClick:(id)sender
  990.     {
  991.     [self updateButtons];
  992.     }
  993.  
  994.  
  995. //-----------------------------------------------------------------------------
  996. // - didDoubleClick:
  997. //-----------------------------------------------------------------------------
  998. - (void)didDoubleClick:(id)sender
  999.     {
  1000.     [self open:sender];
  1001.     }
  1002.  
  1003.  
  1004. //-----------------------------------------------------------------------------
  1005. // - makeKeyAndOrderFront:
  1006. //-----------------------------------------------------------------------------
  1007. - (void)makeKeyAndOrderFront:(id)sender
  1008.     {
  1009.     [window makeKeyAndOrderFront:sender];
  1010.     }
  1011.  
  1012.  
  1013. //-----------------------------------------------------------------------------
  1014. // - windowShouldClose:
  1015. //-----------------------------------------------------------------------------
  1016. - (BOOL)windowShouldClose:(id)sender
  1017.     {
  1018.     [scroll abortEditing];
  1019.     [OPEN_DIRS removeObject:self];
  1020.     [self autorelease];
  1021.     return YES;
  1022.     }
  1023.  
  1024.  
  1025. //-----------------------------------------------------------------------------
  1026. // - windowDidResize:
  1027. //-----------------------------------------------------------------------------
  1028. - (void)windowDidResize:(NSNotification*)notification
  1029.     {
  1030.     NSRect r = [[notification object] frame];
  1031.     if (NSWidth (r) != DEFAULT_WIN_SIZE.width ||
  1032.     NSHeight(r) != DEFAULT_WIN_SIZE.height)
  1033.     {
  1034.     DEFAULT_WIN_SIZE = r.size;
  1035.     [Defaults set:SIZE_DEF size:DEFAULT_WIN_SIZE];
  1036.     }
  1037.     }
  1038.  
  1039.  
  1040. //-----------------------------------------------------------------------------
  1041. // - setDefaultColor:
  1042. //-----------------------------------------------------------------------------
  1043. - (void)setDefaultColor:(NSColor*)c
  1044.     {
  1045.     [DEFAULT_COLOR autorelease];
  1046.     DEFAULT_COLOR = [c retain];
  1047.     [Defaults set:COLOR_DEF color:c];
  1048.     }
  1049.  
  1050.  
  1051. //-----------------------------------------------------------------------------
  1052. // - setColors:
  1053. //-----------------------------------------------------------------------------
  1054. - (void)setColors:(NSColor*)c
  1055.     {
  1056.     [window setBackgroundColor:c];
  1057.     [scroll setBackgroundColor:[self scrollColor]];
  1058.     [window display];
  1059.     }
  1060.  
  1061.  
  1062. //-----------------------------------------------------------------------------
  1063. // - draggingEntered:
  1064. //-----------------------------------------------------------------------------
  1065. - (unsigned int)draggingEntered:(id<NSDraggingInfo>)sender
  1066.     {
  1067.     return ([sender draggingSourceOperationMask] & NSDragOperationGeneric);
  1068.     }
  1069.  
  1070.  
  1071. //-----------------------------------------------------------------------------
  1072. // - performDragOperation:
  1073. //-----------------------------------------------------------------------------
  1074. - (BOOL)performDragOperation:(id<NSDraggingInfo>)sender
  1075.     {
  1076.     [self setDefaultColor:
  1077.         [NSColor colorFromPasteboard:[sender draggingPasteboard]]];
  1078.     [self setColors:DEFAULT_COLOR];
  1079.     return YES;
  1080.     }
  1081.  
  1082.  
  1083. //-----------------------------------------------------------------------------
  1084. // - initLazyRow
  1085. //    NOTE *1*: NeXT docs say immutable arrays are accessed more efficiently.
  1086. //-----------------------------------------------------------------------------
  1087. - (NSArray*)initLazyRow
  1088.     {
  1089.     NSMutableArray* array = [NSMutableArray array];
  1090.     NSFont* font = [scroll font];
  1091.     NSZone* const z = [self zone];
  1092.     int i;
  1093.     for (i = 0; i < MAX_SLOT; i++)
  1094.     {
  1095.     id c = [[[scroll columnCellPrototype:i] copyWithZone:z] autorelease];
  1096.     if ([c respondsToSelector:@selector(setOwner:)])
  1097.         [c setOwner:scroll];
  1098.     else if ([c respondsToSelector:@selector(setFont:)])
  1099.         [c setFont:font];
  1100.     [array addObject:c];
  1101.     }
  1102.     return [[array copy] autorelease];    // NOTE *1*
  1103.     }
  1104.  
  1105.  
  1106. //-----------------------------------------------------------------------------
  1107. // - initDefaults
  1108. //-----------------------------------------------------------------------------
  1109. - (void)initDefaults
  1110.     {
  1111.     static BOOL initialized = NO;
  1112.     if (!initialized)
  1113.     {
  1114.     NSRect r = [window frame];
  1115.     DEFAULT_WIN_SIZE = r.size;
  1116.     DEFAULT_FONT = 
  1117.         [[Defaults getFont:FONT_DEF fallback:[scroll font]] retain];
  1118.     initialized = YES;
  1119.     }
  1120.     }
  1121.  
  1122.  
  1123. //-----------------------------------------------------------------------------
  1124. // - loadDefaults
  1125. //-----------------------------------------------------------------------------
  1126. - (void)loadDefaults
  1127.     {
  1128.     NSString* s;
  1129.  
  1130.     NSRect r = [window frame];
  1131.     r.size = [Defaults getSize:SIZE_DEF fallback:DEFAULT_WIN_SIZE];
  1132.     [window setFrame:r display:NO];
  1133.  
  1134.     autoSort = DEFAULT_AUTO_SORT;
  1135.     showHidden = DEFAULT_SHOW_HIDDEN;
  1136.     highlightDirs = DEFAULT_HIGHLIGHT_DIRS;
  1137.     dragUnscaled = DEFAULT_DRAG_UNSCALED;
  1138.  
  1139.     [autoSortSwitch setState:autoSort];
  1140.     [hiddenFilesSwitch setState:showHidden];
  1141.     [highlightSwitch setState:highlightDirs];
  1142.     [dragUnscaledSwitch setState:dragUnscaled];
  1143.     [rowNumbersSwitch setState:DEFAULT_ROW_NUMBERS];
  1144.  
  1145.     [scroll setRowTitlesOn:DEFAULT_ROW_NUMBERS];
  1146.     [scroll setAutoSortRows:autoSort];
  1147.     [scroll setFont:DEFAULT_FONT];
  1148.     [self setColors:DEFAULT_COLOR];
  1149.  
  1150.     s = [Defaults getStr:COL_SIZES_DEF fallback:0];
  1151.     if (s)
  1152.     [scroll setColumnSizesFromString:s];
  1153.  
  1154.     s = [Defaults getStr:COL_ORDER_DEF fallback:0];
  1155.     if (s)
  1156.     [scroll setColumnOrderFromString:s];
  1157.     }
  1158.  
  1159.  
  1160. //-----------------------------------------------------------------------------
  1161. // - initLockSlot
  1162. //-----------------------------------------------------------------------------
  1163. - (void)initLockSlot
  1164.     {
  1165.     id proto = [scroll columnCellPrototype:LOCK_SLOT];
  1166.     [proto setButtonType:NSSwitchButton];
  1167.     [proto setImagePosition:NSImageOnly];
  1168.     [proto setTarget:self];
  1169.     [proto setAction:@selector(lockClick:)];
  1170.     [proto setImage:LOCKED_IMAGE];
  1171.     [proto setAlternateImage:UNLOCKED_IMAGE];
  1172.     }
  1173.  
  1174.  
  1175. //-----------------------------------------------------------------------------
  1176. // - initNameSlot
  1177. //-----------------------------------------------------------------------------
  1178. - (void)initNameSlot
  1179.     {
  1180.     id proto = [scroll columnCellPrototype:NAME_SLOT];
  1181.     [proto setEditable:YES];
  1182.     [proto setScrollable:YES];
  1183.     }
  1184.  
  1185.  
  1186. //-----------------------------------------------------------------------------
  1187. // - initSlots
  1188. //-----------------------------------------------------------------------------
  1189. - (void)initSlots
  1190.     {
  1191.     [self initLockSlot];
  1192.     [self initNameSlot];
  1193.     [[scroll columnCellPrototype:SIZE_SLOT] setAlignment:NSRightTextAlignment];
  1194.     [[scroll columnCellPrototype:HARDLINKS_SLOT]
  1195.         setAlignment:NSRightTextAlignment];
  1196.     }
  1197.  
  1198.  
  1199. //-----------------------------------------------------------------------------
  1200. // - initWithDir:
  1201. //-----------------------------------------------------------------------------
  1202. - (id)initWithDir:(NSString*)dirname
  1203.     {
  1204.     [super init];
  1205.     path = [[NSString alloc] init];
  1206.     [NSBundle loadNibNamed:@"DirWindow" owner:self];
  1207.     [window registerForDraggedTypes:
  1208.         [NSArray arrayWithObject:NSColorPboardType]];
  1209.     dirArray = [[DirArray allocWithZone:[self zone]] init];
  1210.     [self initSlots];
  1211.     [self initDefaults];
  1212.     [self loadDefaults];
  1213.     lazyRow = [[self initLazyRow] retain];
  1214.     [self load:dirname];
  1215.     [OPEN_DIRS addObject:self];
  1216.     [self cascade];
  1217.     [window makeKeyAndOrderFront:self];
  1218.     return self;
  1219.     }
  1220.  
  1221.  
  1222. //-----------------------------------------------------------------------------
  1223. // - init
  1224. //-----------------------------------------------------------------------------
  1225. - (id)init
  1226.     {
  1227.     return [self initWithDir:NSHomeDirectory()];
  1228.     }
  1229.  
  1230.  
  1231. //-----------------------------------------------------------------------------
  1232. // - dealloc
  1233. //-----------------------------------------------------------------------------
  1234. - (void)dealloc
  1235.     {
  1236.     NSZone* const z = [self zone];
  1237.     [window setDelegate:0];
  1238.     [window close];
  1239.     [window release];
  1240.     [path release];
  1241.     [dirArray release];
  1242.     [lazyRow release];
  1243.     [super dealloc];
  1244.     RETIRE_ZONE(z);
  1245.     }
  1246.  
  1247.  
  1248. //-----------------------------------------------------------------------------
  1249. // - path
  1250. //-----------------------------------------------------------------------------
  1251. - (NSString*)path
  1252.     {
  1253.     return path;
  1254.     }
  1255.  
  1256.  
  1257. //-----------------------------------------------------------------------------
  1258. // + findDir:
  1259. //-----------------------------------------------------------------------------
  1260. + (DirWindow*)findDir:(NSString*)normalizedPath
  1261.     {
  1262.     if (normalizedPath != 0)
  1263.     {
  1264.     unsigned int i;
  1265.     unsigned int const lim = [OPEN_DIRS count];
  1266.     for (i = 0;  i < lim;  i++)
  1267.         {
  1268.         DirWindow* p = (DirWindow*)[OPEN_DIRS objectAtIndex:i];
  1269.         NSString* s = [p path];
  1270.         if (s != 0 && [s isEqualToString:normalizedPath])
  1271.         return p;
  1272.         }
  1273.     }
  1274.     return 0;
  1275.     }
  1276.  
  1277.  
  1278. //-----------------------------------------------------------------------------
  1279. // + launchDir:
  1280. //-----------------------------------------------------------------------------
  1281. + (void)launchDir:(NSString*)dirname
  1282.     {
  1283.     DirWindow* p = 0;
  1284.     if (dirname == 0) dirname = NSHomeDirectory();
  1285.     if (dirname == 0) dirname = @"/";
  1286.     dirname = normalize_path( dirname );
  1287.     if ((p = [self findDir:dirname]) != 0)
  1288.     [p makeKeyAndOrderFront:self];
  1289.     else
  1290.     p = [[self allocWithZone:EMPLOY_ZONE()] initWithDir:dirname];
  1291.     }
  1292.  
  1293. @end
  1294.