home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / Utilities / Fiend-1.4.1-src / Dock.m < prev    next >
Encoding:
Text File  |  1995-12-01  |  27.7 KB  |  1,124 lines

  1. #import "Fiend.h"
  2. #import "IconDragView.h"
  3. #import "DockMgrView.h"
  4. #import "Dock.h"
  5. #import "Controller.h"
  6. #import "FiendWraps.h"
  7.  
  8. @implementation Dock
  9.  
  10. - initMgrView:theDockMgrView
  11. {
  12.     dockMgrView = theDockMgrView;
  13.     [[dockMgrView window] getFrame:&frame];
  14.  
  15.     name[0] = '\0';
  16.     sticky = NO;
  17.     fiendSound = destroySound = nil;
  18.     dockWindowList = [[List allocFromZone:[self zone]] init];
  19.     fileNameStore = [[Storage allocFromZone:[self zone]] initCount:0 elementSize:sizeof(NXAtom) description:"%"];
  20.     appIconStore = [[Storage allocFromZone:[self zone]] initCount:0 elementSize:sizeof(int) description:"i"];
  21.     launchFlagStore = [[Storage allocFromZone:[self zone]] initCount:0 elementSize:sizeof(int) description:"i"];
  22.     filePositionStore = [[Storage allocFromZone:[self zone]] initCount:0
  23.                          elementSize:sizeof(NXPoint) description:"{ff}"];
  24.     nameWinHash = [[HashTable allocFromZone:[self zone]] initKeyDesc:"%" valueDesc:"@"];
  25.  
  26.     return self;
  27. }
  28.  
  29. - free
  30. {
  31.     BOOL    hideIcons = !strcmp(NXGetDefaultValue([NXApp appName], HIDE_ICONS), "YES");
  32.  
  33.     if (hideIcons)
  34.         [self vanishIcons:NO];
  35.  
  36.     [self empty];
  37.  
  38.     [nameWinHash free];
  39.     [appIconStore free];
  40.     [fileNameStore free];
  41.     [dockWindowList free];
  42.     [launchFlagStore free];
  43.     [filePositionStore free];
  44.  
  45.     return [super free];
  46. }
  47.  
  48.  
  49. - empty
  50. {
  51.     id        win;
  52.     int        i;
  53.     int        count = [dockWindowList count];
  54.  
  55.     if (!sticky)    {
  56.         for(i = 0; i < count; i++)    {
  57.             win = [dockWindowList objectAt:i];
  58.             if (![win isMemberOf:[Dock class]])    {
  59.                 if ([[win contentView] isSticky])
  60.                     [dockMgrView add:[win contentView] toStickyDock:NO owner:self];
  61.                 [win free];
  62.             }
  63.         }
  64.     }
  65.     [nameWinHash empty];
  66.     [appIconStore empty];
  67.     [fileNameStore empty];
  68.     [dockWindowList empty];
  69.     [filePositionStore empty];
  70.     return self;
  71. }
  72.  
  73. - setFiendSound:fSound destroySound:dSound
  74. {
  75.     fiendSound = fSound;
  76.     destroySound = dSound;
  77.  
  78.     return self;
  79. }
  80.  
  81. - getOffset:(NXPoint *)theOffset fromFrame:(NXRect *)theFrame
  82. {
  83.     NXRect    mainFrame = frame;
  84.  
  85.     theOffset->x = (NX_X(theFrame) - NX_X(&mainFrame))/NX_WIDTH(&frame);
  86.     theOffset->y = (NX_Y(theFrame) - NX_Y(&mainFrame))/NX_HEIGHT(&frame);
  87.  
  88.     return self;
  89. }
  90.  
  91. - createWindowWithFrame:(NXRect *)theFrame
  92. {
  93.     id        newWin;
  94.     int        lowerLevel = atoi(NXGetDefaultValue([NXApp appName], DCKLWR_LEVEL));
  95.     int        upperLevel = atoi(NXGetDefaultValue([NXApp appName], DCKUPR_LEVEL));
  96.     BOOL    sinkDock = !strcmp(NXGetDefaultValue([NXApp appName], SINK_DOCK), "YES");
  97.  
  98.     newWin = [[Window allocFromZone:[self zone]]
  99.               initContent:theFrame
  100.               style:NX_TOKENSTYLE
  101.               backing:NX_BUFFERED buttonMask:0 defer:NO];
  102.     PSsetwindowlevel(((sinkDock) ? lowerLevel : upperLevel), [newWin windowNum]);
  103.  
  104.     return newWin;
  105. }
  106.  
  107. - select:(BOOL)flag iconWithPath:(char *)aPath
  108. {
  109.     id        *win;
  110.     id        view;
  111.     int        i;
  112.     int        count = [fileNameStore count];
  113.     id        *dockWinListPtr = (count > 0) ? NX_ADDRESS(dockWindowList) : (id *)NULL;
  114.  
  115.     for(i = 0, win = dockWinListPtr; i < count; i++, win++)    {
  116.         if (strstr(*(NXAtom *)[fileNameStore elementAt:i], aPath))    {
  117.             view = [*win contentView];
  118.             if ([view state] != flag)
  119.                 [view setState:flag];
  120.             return self;
  121.         }
  122.     }
  123.     return self;
  124. }
  125.  
  126. - redisplayIcons
  127. {
  128.     id        *win;
  129.     int        i;
  130.     int        count = [fileNameStore count];
  131.     id        *dockWinListPtr = (count > 0) ? NX_ADDRESS(dockWindowList) : (id *)NULL;
  132.  
  133.     for(i = 0, win = dockWinListPtr; i < count; i++, win++)
  134.         [[*win contentView] display];
  135.  
  136.     return self;
  137. }
  138.  
  139. - (int)iconCount
  140. {
  141.     return [dockWindowList count];
  142. }
  143.  
  144. - (int)indexOfPath:(char *)aPath exact:(BOOL)flag
  145. {
  146.     int        i;
  147.     NXAtom    atom;
  148.     int        count = [fileNameStore count];
  149.  
  150.     for(i = 0; i < count; i++)    {
  151.         atom = *(NXAtom *)[fileNameStore elementAt:i];
  152.         if (!flag && strstr(atom, aPath))
  153.             return i;
  154.         else if (flag && !strcmp(atom, aPath))
  155.             return i;
  156.     }
  157.     return -1;
  158. }
  159.  
  160. - createIconViewForPath:(const char *)path withFrame:(NXRect *)iconFrame
  161. {
  162.     id        iconView;
  163.     id           newImage;
  164.     BOOL    drawThumbnail = !strcmp(NXGetDefaultValue([NXApp appName], DRAW_TNAIL), "YES");
  165.  
  166.     newImage = [IconView getImageForPath:path fileIcon:!drawThumbnail zone:[self zone]];
  167.     iconView = [[IconDragView allocFromZone:[self zone]]
  168.                     initFrame:iconFrame
  169.                         image:newImage
  170.                          data:path andLength:strlen(path)
  171.                       useSize:YES onDock:YES];
  172.     if (dockMgrView != nil)
  173.         [iconView setDockMgrView:dockMgrView];
  174.     [[iconView setAutodisplay:NO] display];
  175.  
  176.     return iconView;
  177. }
  178.  
  179. - setIsLoaded:(BOOL)flag
  180. {
  181.     isLoaded = flag;
  182.     return self;
  183. }
  184.  
  185. - (BOOL)isLoaded
  186. {
  187.     return isLoaded;
  188. }
  189.  
  190. - createWindowsFromStores:(BOOL)doRegs stickyWindows:(BOOL)doStickers
  191. {
  192.     id        oldWin;
  193.     id        newWin;
  194.     id           iconView;
  195.     int        i;
  196.     int        count;
  197.     int        autoLaunchFlag;
  198.     BOOL    isSticky;
  199.     NXAtom    path;
  200.     NXPoint    *theOffset;
  201.     NXCoord    width = NX_WIDTH(&frame);
  202.     NXCoord    height = NX_HEIGHT(&frame);
  203.  
  204.     if (!isLoaded && doRegs)
  205.         isLoaded = YES;
  206.  
  207.     count = [filePositionStore count];
  208.     if (count && ![dockWindowList count]) for(i=0;i<count;i++) [dockWindowList addObject:self];
  209.     for(i = 0; i < count; i++)    {
  210.         path = *(NXAtom *)[fileNameStore elementAt:i];
  211.         autoLaunchFlag = *(int *)[launchFlagStore elementAt:i];
  212.  
  213.         isSticky = (autoLaunchFlag & DOCK_STICKY) ? YES : NO;
  214.         if (isSticky)    {
  215.             if (!doStickers)
  216.                 continue;
  217.         }
  218.         else if (!doRegs)    {
  219.             [nameWinHash insertKey:path value:self];
  220.             continue;
  221.         }
  222.  
  223.         theOffset = (NXPoint *)[filePositionStore elementAt:i];
  224.         newWin = [self createWindowWithFrame:&frame];
  225.         [newWin setAvoidsActivation:YES];
  226.         [newWin moveTo:(theOffset->x * width - 1000.0) :(theOffset->y * height - 1000.0)];
  227.         [nameWinHash insertKey:path value:newWin];
  228.         oldWin = [dockWindowList replaceObjectAt:i with:newWin];
  229.         if (![oldWin isMemberOf:[Dock class]]) [oldWin free];
  230.  
  231.         iconView = [self createIconViewForPath:path withFrame:&frame];
  232.         [[newWin setContentView:iconView] free];
  233.  
  234.         [iconView setAutoScan:(BOOL)(autoLaunchFlag & DOCK_ASCAN)];
  235.         if (autoLaunchFlag & DOCK_ALNCH)  {
  236.             [iconView setAutoLaunch:YES];
  237.             if ([iconView isApp] && ![iconView isLaunched])
  238.                 [iconView setGhost:YES];
  239.         }
  240.         if (autoLaunchFlag & DOCK_STICKY)    {
  241.             [iconView setSticky:YES];
  242.             [dockMgrView add:iconView toStickyDock:YES owner:self];
  243.         }
  244.  
  245.         [newWin display];
  246.         [newWin orderFront:self];
  247.     }
  248.     return self;
  249. }
  250.  
  251. - performAutolaunches
  252. {
  253.     int        i;
  254.     int        autoLaunchFlag;
  255.     BOOL    isApp;
  256.     NXAtom    path;
  257.     char    workString[200];
  258.     char    shortName[MAXPATHLEN+1];
  259.     int        count = [launchFlagStore count];
  260.  
  261.     for(i = 0; i < count; i++)    {
  262.         autoLaunchFlag = *(int *)[launchFlagStore elementAt:i];
  263.         path = *(NXAtom *)[fileNameStore elementAt:i];
  264.         isApp = IS_APP_PATH(path);
  265.         if (autoLaunchFlag & DOCK_ALNCH)    {
  266.             if (isApp && strcmp(path, WKSPC_FILE))    {
  267.                 [IconView getShortName:shortName from:(const char *)path];
  268.                 if ([IconView getLastPidFor:shortName] == -1)    {
  269.                     sprintf(workString, "Launching %s...", shortName);
  270.                     [[NXApp delegate] setProgressFieldString:workString];
  271.                     [dockMgrView launch:path autolaunch:YES];
  272.                 }
  273.             }
  274.             else
  275.                 [[Application workspace] openFile:path];
  276.         }
  277.     }
  278.     return self;
  279. }
  280.  
  281. - vanish:(BOOL)vanish icon:(int)appIcon for:(NXAtom)path
  282. {
  283.     NXSize        screenSize;
  284.  
  285.     [NXApp getScreenSize:&screenSize];    
  286.     if (appIcon > 0 && !onNeXTDock(path, (int)screenSize.height))    {
  287.         if (vanish)
  288.             PSWMove(-1000.0, -1000.0, appIcon);
  289.         else
  290.             PSWReplaceIcon(appIcon, (int)(screenSize.width)-64);
  291.     }
  292.     return self;
  293. }        
  294.  
  295. - checkLaunchStatus
  296. {
  297.     id        *win;
  298.     id        iconView;
  299.     int        i;
  300.     int     appPid;
  301.     int        appCtxt;
  302.     int     appIcon;
  303.     NXAtom  path;
  304.     int        count = [dockWindowList count];
  305.     id        *winListPtr = (count > 0) ? NX_ADDRESS(dockWindowList) : (id *)NULL;
  306.     BOOL    hideIcons = !strcmp(NXGetDefaultValue([NXApp appName], HIDE_ICONS), "YES");
  307.  
  308.     for(i = 0, win = winListPtr; i < count; i++, win++)    {
  309.         path = *(NXAtom *)[fileNameStore elementAt:i];
  310.         if (IS_APP_PATH(path))    {
  311.             [IconView getCtxt:&appCtxt pid:&appPid andIcon:&appIcon forPath:(char *)path];
  312.             [appIconStore replaceElementAt:i with:(void *)&appIcon];
  313.         }
  314.         else
  315.             appIcon = appPid = appCtxt = -1;
  316.         if (hideIcons && appIcon != -1)
  317.             [self vanish:YES icon:appIcon for:path];
  318.         if (*win == self) continue;
  319.         iconView = [*win contentView];
  320.         [iconView setCtxt:appCtxt pid:appPid andIcon:appIcon];
  321.     }
  322.     return self;
  323. }
  324.  
  325.  
  326. - (BOOL)isShowing
  327. {
  328.     return (NX_X(&frame) > -1000.0 && NX_Y(&frame) > -1000.0);
  329. }
  330.  
  331.  
  332. - updateWindows:(NXPoint *)p usePlace:(BOOL)usePlace followLevels:(BOOL)follow
  333. {
  334.     id        *win;
  335.     id        iconView;
  336.     int        i;
  337.     BOOL    exceptionRaised;
  338.     BOOL    isLaunched;
  339.     NXPoint    *offset;
  340.     NXRect    winRect;
  341.     int        width = NX_WIDTH(&frame);
  342.     int        height = NX_HEIGHT(&frame);
  343.     int        count = [filePositionStore count];
  344.     id        *winListPtr = (count > 0) ? NX_ADDRESS(dockWindowList) : (id *)NULL;
  345.  
  346.     frame.origin = *p;
  347.     for(i = 0, win = winListPtr; i < count; i++, win++)    {
  348.         exceptionRaised = NO;
  349.         if (*win == self) continue;
  350.         iconView = [*win contentView];
  351.         isLaunched = [iconView isLaunched];
  352.         if (!sticky && follow)    {
  353.             if (p->x == p->y && p->x == -1000.0)    {
  354.                 if ([iconView isLaunched])    {
  355.                     [iconView getScreenStatus];
  356.                     if ([iconView appWasVisible] && ![iconView isSticky])
  357.                         fiendUnhideContext([iconView appCtxt], 0, 0, 0);
  358.                 }
  359.             }
  360.             else    {
  361.                 if ([iconView isLaunched] && [iconView appWasVisible])    {
  362.                     if (![iconView isSticky])    {
  363.                         fiendUnhideContext([iconView appCtxt], (int)[iconView appWasVisible],
  364.                                       (int)[iconView appWasActive], 0);
  365.                     }
  366.                 }
  367.             }
  368.         }
  369.         if (!sticky && [iconView isSticky])
  370.             continue;
  371.         offset = (NXPoint *)[filePositionStore elementAt:i];
  372.         if (offset->x == offset->y && offset->x == 0.0)    {
  373.             [*win getFrame:&winRect];
  374.             [self getOffset:offset fromFrame:&winRect];
  375.             [filePositionStore replaceElementAt:i with:(void *)offset];
  376.         }
  377.         if (usePlace)    {
  378.             NXSetRect(&winRect, p->x + offset->x * width, p->y + offset->y * height,
  379.                       NX_WIDTH(&frame), NX_HEIGHT(&frame));
  380.             [*win placeWindowAndDisplay:&winRect];
  381.         }
  382.         else
  383.             [*win moveTo:p->x + offset->x * width :p->y + offset->y * height];
  384.         if ([iconView isSticky])
  385.             [*win orderFront:self];
  386.         [filePositionStore replaceElementAt:i with:(void *)offset];
  387.     }
  388.     return self;
  389. }
  390.  
  391. - setSticky
  392. {
  393.     sticky = YES;
  394.     return self;
  395. }
  396.  
  397. - setDockMgrView:theMgrView
  398. {
  399.     id        *win;
  400.     int        i;
  401.     int        count = [dockWindowList count];
  402.     id        *dockWinListPtr = (count > 0) ? NX_ADDRESS(dockWindowList) : (id *)NULL;
  403.  
  404.     dockMgrView = theMgrView;
  405.  
  406.     for(i = 0, win = dockWinListPtr; i < count; i++, win++)
  407.         [[*win contentView] setDockMgrView:dockMgrView];
  408.     return self;
  409. }
  410.  
  411. - viewAtPosition:(NXRect *)checkRect besides:testView
  412. {
  413.     id        *win;
  414.     int        i;
  415.     NXRect    winFrame;
  416.     NXRect    myWinFrame = frame;
  417.     int        count = [dockWindowList count];
  418.     id        *winListPtr = (count > 0) ? NX_ADDRESS(dockWindowList) : (id *)NULL;
  419.  
  420.     [[dockMgrView window] getFrame:&myWinFrame];
  421.     if (NX_X(checkRect) == NX_X(&myWinFrame) && NX_Y(checkRect) == NX_Y(&myWinFrame))
  422.         return self;
  423.     for(i = 0, win = winListPtr; i < count; i++, win++)    {
  424.         if (*win == self) continue;
  425.         if (testView && testView == [*win contentView])
  426.             continue;
  427.         [*win getFrame:&winFrame];
  428.         if (NX_X(checkRect) == NX_X(&winFrame) && NX_Y(checkRect) == NX_Y(&winFrame))
  429.             return [*win contentView];
  430.     }
  431.     return nil;
  432. }
  433.  
  434. - deleteSelectedCells
  435. {
  436.     id        *win;
  437.     id        iconView;
  438.     int        i;
  439.     id        *cutListPtr = (id *)NULL;
  440.     int        count = [dockWindowList count];
  441.     id        cutList = [[List allocFromZone:[self zone]] init];
  442.     id        *dockWinListPtr = (count > 0) ? NX_ADDRESS(dockWindowList) : (id *)NULL;
  443.  
  444.     for(i = 0, win = dockWinListPtr; i < count; i++, win++)    {
  445.         iconView = [*win contentView];
  446.         if ([iconView state] && ![iconView isSticky])
  447.             [cutList addObject:iconView];
  448.     }
  449.     count = [cutList count];
  450.     if (count > 0)
  451.         cutListPtr = NX_ADDRESS(cutList);
  452.     for(i = 0, win = cutListPtr; i < count; i++, win++)
  453.         [self deleteView:*win unvanish:YES];
  454.  
  455.     [cutList free];
  456.     return self;
  457. }
  458.  
  459. - (int)hasSelectedCells
  460. {
  461.     id        *win;
  462.     int        i;
  463.     int        selCnt = 0;
  464.     int        count = [dockWindowList count];
  465.     id        *dockWinListPtr = (count > 0) ? NX_ADDRESS(dockWindowList) : (id *)NULL;
  466.  
  467.     for(i = 0, win = dockWinListPtr; i < count; i++, win++)    {
  468.         if ([[*win contentView] state])
  469.             selCnt++;
  470.     }
  471.     return selCnt;
  472. }
  473.  
  474. - (const char *)selectedCellPath
  475. {
  476.     id        *win;
  477.     id        iconView;
  478.     int        i;
  479.     int        len;
  480.     char    *path = "";
  481.     int        count = [dockWindowList count];
  482.     id        *dockWinListPtr = (count > 0) ? NX_ADDRESS(dockWindowList) : (id *)NULL;
  483.  
  484.     for(i = 0, win = dockWinListPtr; i < count; i++, win++)    {
  485.         if ([(iconView = [*win contentView]) state])    {
  486.             [iconView getData:(void *)&path andLength:&len];
  487.             break;
  488.         }
  489.     }
  490.     return (const char *)path;
  491. }
  492.  
  493. - selectedCell
  494. {
  495.     id        *win;
  496.     id        iconView;
  497.     int        i;
  498.     int        count = [dockWindowList count];
  499.     id        *dockWinListPtr = (count > 0) ? NX_ADDRESS(dockWindowList) : (id *)NULL;
  500.  
  501.     iconView = nil;
  502.     for(i = 0, win = dockWinListPtr; i < count; i++, win++)    {
  503.         if ([(iconView = [*win contentView]) state])
  504.             return iconView;
  505.     }
  506.     return nil;
  507. }
  508.  
  509. - select:(BOOL)flag all:sender
  510. {
  511.     id        *win;
  512.     id        view;
  513.     int        i;
  514.     int        count = [dockWindowList count];
  515.     id        *dockWinListPtr = (count > 0) ? NX_ADDRESS(dockWindowList) : (id *)NULL;
  516.  
  517.     for(i = 0, win = dockWinListPtr; i < count; i++, win++)    {
  518.         view = [*win contentView];
  519.         if ([view state] != flag)
  520.             [[view setState:flag] display];
  521.     }
  522.     return self;
  523. }
  524.  
  525. - getNextFrame:(NXRect *)theFrame
  526. {
  527.     int            maxTries;
  528.     BOOL        goingDown = TRUE;
  529.     float        limit = 4.0;
  530.     NXSize        size = {0.0, 0.0};
  531.  
  532.     [NXApp getScreenSize:&size];
  533.     maxTries = size.width * size.height/(NX_WIDTH(&frame) * NX_WIDTH(&frame));
  534.  
  535.     *theFrame = frame;
  536.  
  537.     while (maxTries)    {
  538.         /* scan left */
  539.         do    {
  540.             maxTries--;
  541.             NX_X(theFrame) -= NX_WIDTH(theFrame);
  542.         } while ((NX_X(theFrame) > 0.0) && ((NX_X(&frame) - NX_X(theFrame))/NX_WIDTH(theFrame) <= limit) &&
  543.                  ([self viewAtPosition:theFrame besides:nil] != nil ||
  544.                  [[dockMgrView stickyDock] viewAtPosition:theFrame besides:nil] != nil));
  545.  
  546.         /* if we're within bounds, we're done */
  547.         if (NX_X(theFrame) > 0.0  && ((NX_X(&frame) - NX_X(theFrame))/NX_WIDTH(theFrame) <= limit))
  548.             return self;
  549.         else    {
  550.             /* scan right */
  551.             NX_X(theFrame) = NX_X(&frame);
  552.             do    {
  553.                 maxTries--;
  554.                 NX_X(theFrame) += NX_WIDTH(theFrame);
  555.             }    while ((NX_MAXX(theFrame) < size.width) &&
  556.                        ((NX_MAXX(theFrame) - NX_MAXX(&frame))/NX_WIDTH(theFrame) <= limit) &&
  557.                        ([self viewAtPosition:theFrame besides:nil] != nil ||
  558.                        [[dockMgrView stickyDock] viewAtPosition:theFrame besides:nil] != nil));
  559.  
  560.             /* if we're within bounds, we're done */
  561.             if (NX_MAXX(theFrame) < size.width && ((NX_MAXX(theFrame) - NX_MAXX(&frame))/NX_WIDTH(theFrame) <= limit))
  562.                 return self;
  563.             else    {
  564.                 /* move down a row */
  565.                 if (goingDown)    {
  566.                     if (NX_Y(theFrame) >= NX_HEIGHT(theFrame))
  567.                         NX_Y(theFrame) -= NX_HEIGHT(theFrame);
  568.                     else    {
  569.                         goingDown = NO;
  570.                         NX_Y(theFrame) = NX_MAXY(&frame);
  571.                     }
  572.                 }
  573.                 else    {
  574.                     if (NX_MAXY(theFrame) <= size.height)
  575.                         NX_Y(theFrame) += NX_HEIGHT(theFrame);
  576.                     else    {
  577.                         limit = 100.0;
  578.                         goingDown = YES;
  579.                         NX_Y(theFrame) = NX_Y(&frame);
  580.                     }
  581.                 }
  582.                 NX_X(theFrame) = NX_MAXX(&frame);
  583.             }
  584.         }
  585.     }
  586.     return self;
  587. }
  588.  
  589. - addStickyWindow:aWindow atOffset:(NXPoint *)offset
  590. {
  591.     int        junk;
  592.     char    *viewPath;
  593.     id        aView = [aWindow contentView];
  594.  
  595.     [aView getData:(void **)&viewPath andLength:&junk];
  596.     [dockWindowList addObject:aWindow];
  597.     [filePositionStore addElement:(void *)offset];
  598.     return self;
  599. }
  600.  
  601. - getOffset:(NXPoint *)offset forWindow:aWindow
  602. {
  603.     int        index = [dockWindowList indexOf:aWindow];
  604.  
  605.     if (index == NX_NOT_IN_LIST)
  606.         return nil;
  607.  
  608.     *offset = *(NXPoint *)[filePositionStore elementAt:index];
  609.     return self;
  610. }
  611.         
  612.  
  613. - removeStickyWindow:aWindow
  614. {
  615.     int        index = [dockWindowList indexOf:aWindow];
  616.  
  617.     if (index != NX_NOT_IN_LIST)    {
  618.         [dockWindowList removeObject:aWindow];
  619.         [filePositionStore removeElementAt:index];
  620.     }
  621.  
  622.     return self;
  623. }
  624.  
  625. - createWindowForPath:(const char *)thePath newFrame:(NXRect *)newFrame
  626. {
  627.     id            newWin;
  628.     id            iconView;
  629.  
  630.     if (!thePath)
  631.         return nil;
  632.  
  633.     if (NX_MAXX(newFrame) <= NX_WIDTH(newFrame) || NX_MAXY(newFrame) <= NX_HEIGHT(newFrame) ||
  634.         [self viewAtPosition:newFrame besides:nil] ||
  635.         [[dockMgrView stickyDock] viewAtPosition:newFrame besides:nil])
  636.         [self getNextFrame:newFrame];
  637.  
  638.     newWin = [self createWindowWithFrame:newFrame];
  639.     iconView = [self createIconViewForPath:thePath withFrame:newFrame];
  640.     [nameWinHash insertKey:NXUniqueString(thePath) value:newWin];
  641.     [[newWin setContentView:iconView] free];
  642.  
  643.     [newWin setAvoidsActivation:YES];
  644.     [dockWindowList addObject:newWin];
  645.  
  646.     [newWin display];
  647.     [newWin orderFront:self];
  648.  
  649.     return newWin;
  650. }
  651.  
  652. - vanishIcons:(BOOL)flag
  653. {
  654.     int        i;
  655.     int        appIcon;
  656.     NXAtom    path;
  657.     int        count = [appIconStore count];
  658.  
  659.     for(i = 0; i < count; i++)    {
  660.         path = *(NXAtom *)[fileNameStore elementAt:i];
  661.         appIcon = *(int *)[appIconStore elementAt:i];
  662.         [self vanish:flag icon:appIcon for:path];
  663.     }
  664.     return self;
  665. }
  666.  
  667. - rotateOffsets
  668. {
  669.     id        *win;
  670.     int        i;
  671.     NXRect    windowRect;
  672.     NXPoint    p;
  673.     NXPoint    *oldOffset;
  674.     NXPoint    newOffset;
  675.     int        width = NX_WIDTH(&frame);
  676.     int        height = NX_HEIGHT(&frame);
  677.     int        count = [dockWindowList count];
  678.     id        *winListPtr = (count > 0) ? NX_ADDRESS(dockWindowList) : (id *)NULL;
  679.  
  680.     [[dockMgrView window] getFrame:&windowRect];
  681.     p = windowRect.origin;
  682.     for(i = 0, win = winListPtr; i < count; i++, win++)    {
  683.         if (*win == self) continue;
  684.         if ([[*win contentView] isSticky])
  685.             continue;
  686.         oldOffset = (NXPoint *)[filePositionStore elementAt:i];
  687.         newOffset.x = oldOffset->y;
  688.         newOffset.y = -oldOffset->x;
  689.         [*win moveTo:p.x+newOffset.x*width :p.y+newOffset.y*height];
  690.         [filePositionStore replaceElementAt:i with:(void *)&newOffset];
  691.     }
  692.     return self;
  693. }
  694.  
  695.  
  696. - scanIcons
  697. {
  698.     int        i;
  699.     id        *win;
  700.     id        view;
  701.     int        count = [dockWindowList count];
  702.     id        *winListPtr = (count > 0) ? NX_ADDRESS(dockWindowList) : (id *)NULL;
  703.  
  704.     for(i = 0, win = winListPtr; i < count; i++, win++)    {
  705.         if (*win == self) continue;
  706.         view = [*win contentView];
  707.         if (!sticky && [view isSticky])
  708.             continue;
  709.         if ([view autoScan])
  710.             [view refreshIcon];
  711.     }
  712.  
  713.     return self;
  714. }
  715.  
  716. - restoreIcons
  717. {
  718.     int        i;
  719.     id        *win;
  720.     id        view;
  721.     int        count = [dockWindowList count];
  722.     id        *winListPtr = (count > 0) ? NX_ADDRESS(dockWindowList) : (id *)NULL;
  723.  
  724.     for(i = 0, win = winListPtr; i < count; i++, win++)    {
  725.         if (*win == self) continue;
  726.         view = [*win contentView];
  727.         if (!sticky && [view isSticky])
  728.             continue;
  729.         if ([view autoScan])
  730.             [view restoreIconImage];
  731.     }
  732.  
  733.     return self;
  734. }
  735.  
  736. - addWindowForPath:(NXAtom)pathAtom at:(NXRect *)testFrame
  737. {
  738.     id        newWin;
  739.     NXPoint    newOffset;
  740.     int        autoLaunch = NO;
  741.     NXRect    aFrame = {{NX_X(&frame)-NX_WIDTH(&frame), NX_Y(&frame)}, {NX_WIDTH(&frame), NX_HEIGHT(&frame)}};
  742.     NXRect    *newFrame = (testFrame == (NXRect *)NULL) ? &aFrame : testFrame;
  743.  
  744.     [launchFlagStore addElement:(void *)&autoLaunch];
  745.     newWin = [self createWindowForPath:pathAtom newFrame:newFrame];
  746.     [fileNameStore addElement:(void *)&pathAtom];
  747.     [self getOffset:&newOffset fromFrame:newFrame];
  748.     [filePositionStore addElement:(void *)&newOffset];
  749.  
  750.     return newWin;
  751. }
  752.  
  753. - removeWindow:aWin
  754. {
  755.     NXAtom    pathAtom;
  756.     int        index = [dockWindowList indexOf:aWin];
  757.  
  758.     if (index != NX_NOT_IN_LIST)    {
  759.         pathAtom = *(NXAtom *)[fileNameStore elementAt:index];
  760.         [nameWinHash removeKey:pathAtom];
  761.         [appIconStore removeElementAt:index];
  762.         [fileNameStore removeElementAt:index];
  763.         [launchFlagStore removeElementAt:index];
  764.         [filePositionStore removeElementAt:index];
  765.         [dockWindowList removeObjectAt:index];
  766.     }
  767.  
  768.     return self;
  769. }
  770.  
  771. - addWindow:aWin withPath:(char *)aPath
  772. {
  773.     int            autoLaunch = NO;
  774.     int            junk = -1;
  775.     NXRect        aFrame;
  776.     NXPoint        newOffset;
  777.     NXRect        *newFrame = &aFrame;
  778.     NXAtom        pathAtom = NXUniqueString(aPath);
  779.  
  780.     [aWin getFrame:newFrame];
  781.     if (NX_MAXX(newFrame) <= NX_WIDTH(newFrame) || NX_MAXY(newFrame) <= NX_HEIGHT(newFrame) ||
  782.         [self viewAtPosition:newFrame besides:nil])
  783.         [self getNextFrame:newFrame];
  784.     
  785.     [dockWindowList addObject:aWin];
  786.     [appIconStore addElement:(void *)&junk];
  787.     [fileNameStore addElement:(void *)&pathAtom];
  788.     [launchFlagStore addElement:(void *)&autoLaunch];
  789.     [self setLaunchFlagsFor:[aWin contentView]];
  790.     
  791.     [self getOffset:&newOffset fromFrame:newFrame];
  792.     [filePositionStore addElement:(void *)&newOffset];
  793.     return self;
  794. }
  795.  
  796.  
  797. - deleteView:aView quickly:(BOOL)flag unvanish:(BOOL)unvanishFlag
  798. {
  799.     NXAtom    pathAtom;
  800.     id        win = [aView window];
  801.     int        index = [dockWindowList indexOf:win];
  802.     BOOL    hideIcons = !strcmp(NXGetDefaultValue([NXApp appName], HIDE_ICONS), "YES");
  803.  
  804.     [win moveTo:-1000.0 :-1000.0];
  805.     if (index != NX_NOT_IN_LIST)    {
  806.         if (unvanishFlag && hideIcons)
  807.             [aView unvanishIcon];
  808.         pathAtom = *(NXAtom *)[fileNameStore elementAt:index];
  809.         [nameWinHash removeKey:pathAtom];
  810.         [appIconStore removeElementAt:index];
  811.         [fileNameStore removeElementAt:index];
  812.         [filePositionStore removeElementAt:index];
  813.         [launchFlagStore removeElementAt:index];
  814.         [dockWindowList removeObjectAt:index];
  815.         [NXApp delayedFree:win];
  816.     }
  817.     return self;
  818. }
  819.  
  820. - deleteView:aView unvanish:(BOOL)unvanishFlag
  821. {
  822.     return [self deleteView:aView quickly:YES unvanish:unvanishFlag];
  823. }
  824.  
  825. - dockWindowList
  826. {
  827.     return dockWindowList;
  828. }
  829.  
  830. - setLaunchFlagsFor:iconView
  831. {
  832.     int        index = [dockWindowList indexOf:[iconView window]];
  833.     int        flag = ([iconView autoLaunch]) ? DOCK_ALNCH : DOCK_NONE;
  834.  
  835.     if ([iconView autoScan]) flag |= DOCK_ASCAN;
  836.     if ([iconView isSticky]) flag |= DOCK_STICKY;
  837.     [launchFlagStore replaceElementAt:index with:(void *)&flag];
  838.     return self;
  839. }
  840.  
  841. - (int)copy:sender toPasteboard:pb andCut:(BOOL)cutFlag sndEnable:(BOOL)flag
  842. {
  843.     id        *win;
  844.     id        view;
  845.     int        i;
  846.     int        junk;
  847.     int        length;
  848.     int        maxLength;
  849.     int        *launchFlags;
  850.     NXPoint    *theOffset;
  851.     char    *viewPath;
  852.     char    *cutString;
  853.     NXPoint    maxOffset = {-100.0, -100.0};
  854.     int        count = [dockWindowList count];
  855.     id        cutList = [[List allocFromZone:[self zone]] init];
  856.     id        *cutListPtr = (id *)NULL;
  857.     id        *dockWinListPtr = (count > 0) ? NX_ADDRESS(dockWindowList) : (id *)NULL;
  858.     BOOL    useSound = (flag && !strcmp(NXGetDefaultValue([NXApp appName], USE_SOUND), "YES"));
  859.     NXStream    *theStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
  860.     const char     *types[] = {FIEND_PBTYPE, NXFilenamePboardType, NXAsciiPboardType};
  861.  
  862.     [pb declareTypes:types num:3 owner:nil];
  863.  
  864.     for(i = 0, win = dockWinListPtr; i < count; i++, win++)    {
  865.         if ([[*win contentView] state])    {
  866.             theOffset = (NXPoint *)[filePositionStore elementAt:i];
  867.             maxOffset.x = (maxOffset.x > theOffset->x) ? maxOffset.x : theOffset->x;
  868.             maxOffset.y = (maxOffset.y > theOffset->y) ? maxOffset.y : theOffset->y;
  869.         }
  870.     }
  871.     NXPrintf(theStream, "DOCK\t%.0f %.0f\t", maxOffset.x, maxOffset.y);
  872.     for(i = 0, win = dockWinListPtr; i < count; i++, win++)    {
  873.         theOffset = (NXPoint *)[filePositionStore elementAt:i];
  874.         launchFlags = (int *)[launchFlagStore elementAt:i];
  875.         view = [*win contentView];
  876.         if ([view state])    {
  877.             [view getData:(void **)&viewPath andLength:&junk];
  878.             NXPrintf(theStream, "%6d%7.0f%7.0f  %s\t",
  879.                      *launchFlags, theOffset->x, theOffset->y, viewPath);
  880.             [cutList addObject:view];
  881.         }
  882.     }
  883.     NXGetMemoryBuffer(theStream, &cutString, &length, &maxLength);
  884.     [pb writeType:FIEND_PBTYPE data:cutString length:length];
  885.     NXClose(theStream);
  886.  
  887.     length = 0;
  888.     count = [cutList count];
  889.     if (count > 0)
  890.         cutListPtr = NX_ADDRESS(cutList);
  891.     theStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
  892.     for(i = 0, win = cutListPtr; i < count; i++, win++)    {
  893.         [*win getData:(void **)&viewPath andLength:&junk];
  894.         NXPrintf(theStream, "%s\t", viewPath);
  895.     }
  896.     NXGetMemoryBuffer(theStream, &cutString, &length, &maxLength);
  897.     cutString[strlen(cutString)-1] = '\0';
  898.     [pb writeType:NXFilenamePboardType data:cutString length:length];
  899.  
  900.     for(i = 0; i < strlen(cutString); i++)    {
  901.         if (cutString[i] == '\t')
  902.             cutString[i] = '\n';
  903.     }
  904.     if (cutString[strlen(cutString)-1] != '\n') strcat(cutString, "\n");
  905.     [pb writeType:NXAsciiPboardType data:cutString length:length];
  906.     NXClose(theStream);
  907.  
  908.     if (cutFlag)    {
  909.         if (count && useSound)
  910.             [destroySound play:self];
  911.         for(i = 0, win = cutListPtr; i < count; i++, win++)    {
  912.             if (![*win isSticky])
  913.                 [self deleteView:*win unvanish:(sender != dockMgrView)];
  914.         }
  915.     }
  916.  
  917.     [cutList free];
  918.  
  919.     return count;
  920. }
  921.  
  922. - paste:sender toPasteboard:pb sndEnable:(BOOL)flag
  923. {
  924.     id        iconView;
  925.     int        len;
  926.     int        level;
  927.     int        launchFlag;
  928.     char    *path;
  929.     char    *dragString;
  930.     char    tokenString[MAXPATHLEN+1];
  931.     BOOL    didPaste;
  932.     BOOL    fromDock;
  933.     BOOL    fromShelf;
  934.     NXRect    winRect;
  935.     NXAtom    pathAtom;
  936.     NXCoord    x;
  937.     NXCoord    y;
  938.     const    char *type;
  939.     char    *sep = "\t";
  940.     const    char *types[] = {FIEND_PBTYPE, NXFilenamePboardType};
  941.     BOOL    hideIcons = !strcmp(NXGetDefaultValue([NXApp appName], HIDE_ICONS), "YES");
  942.     BOOL    useSound = (flag && !strcmp(NXGetDefaultValue([NXApp appName], USE_SOUND), "YES"));
  943.  
  944.     type = [pb findAvailableTypeFrom:types num:2];
  945.     if (type && !strcmp(type, FIEND_PBTYPE))    {
  946.         if (![pb readType:FIEND_PBTYPE data:&dragString length:&len])
  947.             return self;
  948.         sep = "\t";
  949.     }        
  950.     else if (type && !strcmp(type, NXFilenamePboard))    {
  951.         if (![pb readType:NXFilenamePboardType data:&dragString length:&len])
  952.             return self;
  953.         sep = "\t";
  954.     }
  955.     else    {
  956.         NXBeep();
  957.         return self;
  958.     }
  959.  
  960.     if (len == 0)    {
  961.         NXBeep();
  962.         return self;
  963.     }
  964.  
  965.     [self select:NO all:self];
  966.  
  967.     didPaste = NO;
  968.     path = strtok(dragString, sep);
  969.     fromDock = (!strcmp(path, "DOCK")) ? YES : NO;
  970.     fromShelf = (!strcmp(path, "SHELF")) ? YES : NO;
  971.     if (fromShelf || fromDock)
  972.         path = strtok(NULL, sep);
  973.     if (fromDock) path = strtok(NULL, sep);
  974.     while(path && strlen(path))    {
  975.         if (strcmp(type, FIEND_PBTYPE))    {
  976.             winRect = frame;
  977.             pathAtom = NXUniqueString(path);
  978.         }
  979.         else    {
  980.             sscanf(path, "%d %f %f %[^\n\t]", &launchFlag, &x, &y, tokenString);
  981.             pathAtom = NXUniqueString(tokenString);
  982.             if (fromShelf)    {
  983.                 x = rint(x); y = rint(y);
  984.                 launchFlag = DOCK_NONE;
  985.                 x -= 1.0;
  986.             }
  987.             NXSetRect(&winRect,
  988.                       NX_X(&frame) + x * NX_WIDTH(&frame),
  989.                       NX_Y(&frame) + y * NX_HEIGHT(&frame),
  990.                       NX_WIDTH(&frame), NX_HEIGHT(&frame));
  991.         }
  992.         if ((level = [dockMgrView findLevelContaining:pathAtom switch:NO]) < 0)    {
  993.             didPaste = YES;
  994.             iconView = [[self addWindowForPath:pathAtom at:&winRect] contentView];
  995.             [iconView setAutoScan:((launchFlag & DOCK_ASCAN)?YES:NO)];
  996.             [iconView setAutoLaunch:((launchFlag & DOCK_ALNCH)?YES:NO)];
  997.             [self setLaunchFlagsFor:iconView];
  998.             [iconView refreshIcon];
  999.             if (sender != self && hideIcons)
  1000.                 [iconView vanishIcon];
  1001.         }
  1002.         else    {
  1003.             NXBeep();
  1004.             NXRunAlertPanel([NXApp appName],
  1005.                             "Fiend Dock already contains %s on level %d...",
  1006.                             NULL, NULL, NULL, pathAtom, level+1);
  1007.         }
  1008.         path = strtok(NULL, sep);
  1009.     }
  1010.     [pb deallocatePasteboardData:dragString length:len];
  1011.  
  1012.     if (didPaste && useSound)
  1013.         [fiendSound play:self];
  1014.  
  1015.     return self;
  1016. }
  1017.  
  1018. - setWindowTier:(int)aLevel
  1019. {
  1020.     int        i;
  1021.     id        *win;
  1022.     int        count = [dockWindowList count];
  1023.     id        *winListPtr = (count > 0) ? NX_ADDRESS(dockWindowList) : (id *)NULL;
  1024.  
  1025.     for(i = 0, win = winListPtr; i < count; i++, win++)   {
  1026.         if (*win == self) continue;
  1027.         PSsetwindowlevel(aLevel, [*win windowNum]);
  1028.     }
  1029.     return self;
  1030. }
  1031.  
  1032. - paste:sender sndEnable:(BOOL)flag
  1033. {
  1034.     return [self paste:sender toPasteboard:[Pasteboard new] sndEnable:flag];
  1035. }
  1036.  
  1037. - (int)addToWinRecArray:(struct winRec **)winRecs presentCount:(int *)presentCount
  1038. {
  1039.     id        *win;
  1040.     int        i;
  1041.     int        localNum;
  1042.     int        globalNum;
  1043.     NXPoint    *offset;
  1044.     int        actualCount = 0;
  1045.     int        winCount = [dockWindowList count];
  1046.     id        *winListPtr = (winCount > 0) ? NX_ADDRESS(dockWindowList) : (id *)NULL;
  1047.  
  1048.     if (winCount > 0)    {
  1049.         actualCount = 0;
  1050.         *winRecs = (struct winRec *)realloc(*winRecs,
  1051.                                             sizeof(struct winRec) * (*presentCount + winCount));
  1052.         for(i = 0, win = winListPtr; i < winCount; i++, win++)    {
  1053.             if (*win == self) continue;
  1054.             if (sticky || ![[*win contentView] isSticky])    {
  1055.                 localNum = [*win windowNum];
  1056.                 NXConvertWinNumToGlobal(localNum, &globalNum);
  1057.                 offset = (NXPoint *)[filePositionStore elementAt:i];
  1058.                 (*winRecs)[*presentCount + actualCount].winNum = globalNum;
  1059.                 (*winRecs)[*presentCount + actualCount].xOffset = offset->x;
  1060.                 (*winRecs)[*presentCount + actualCount].yOffset = offset->y;
  1061.                 actualCount++;
  1062.             }
  1063.         }
  1064.         winCount = actualCount;
  1065.     }
  1066.     return (*presentCount + winCount);
  1067. }
  1068.  
  1069. - findWindowForName:(const char *)aName
  1070. {
  1071.     return (id)[nameWinHash valueForKey:NXUniqueString(aName)];
  1072. }
  1073.  
  1074. - filePositionStore
  1075. {
  1076.     return filePositionStore;
  1077. }
  1078.  
  1079. - fileNameStore
  1080. {
  1081.     return fileNameStore;
  1082. }
  1083.  
  1084. - appIconStore
  1085. {
  1086.     return appIconStore;
  1087. }
  1088.  
  1089. - launchFlagStore
  1090. {
  1091.     return launchFlagStore;
  1092. }
  1093.  
  1094. - nameWinHash
  1095. {
  1096.     return nameWinHash;
  1097. }
  1098.  
  1099. - getFrame:(NXRect *)aFrame
  1100. {
  1101.     *aFrame = frame;
  1102.     return self;
  1103. }
  1104.  
  1105. - setFrame:(const NXRect *)aFrame
  1106. {
  1107.     frame = *aFrame;
  1108.     return self;
  1109. }
  1110.  
  1111. - setName:(char *)aName
  1112. {
  1113.     strncpy(name, aName, DOCKNAMELEN);
  1114.     name[DOCKNAMELEN] = '\0';
  1115.     return self;
  1116. }
  1117.  
  1118. - (const char *)name
  1119. {
  1120.     return (const char *)name;
  1121. }
  1122.  
  1123. @end
  1124.