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