ftp.nice.ch/pub/next/tools/screen/WideScreen.0.5.NIHS.bs.tar.gz#/WideScreen.0.5.NIHS.bs/Source/VdtApplication.m

This is VdtApplication.m in view mode; [Download] [Up]

/***(VdtApplication.m)*********************************************************
*H* Virtual Desk Top Application subclass implementation   	    	      *
******************************************************************************/

#import <string.h>
#import <defaults.h>

#import "VdtApplication.h"

@implementation VdtApplication

/******************************************************************************
* INSTANCE METHOD:- getDefaultBorderGray:  	    	    	    	      *
*   The BorderGray default  determines  what  gray  value is used for the Vdt *
* border color when the Vdt View is Immobilized.    	    	    	      *
******************************************************************************/
- getDefaultBorderGray

    /* Arguments */
    :(float*)grayValue	    	/*O* Returned Border Gray Value */

{   /* Local Variables */
    const char   *defStr;	/* Pointer to value string of Dock Handling default */

/* BEGIN-getDefaultBorderGray */
defStr = NXGetDefaultValue(appName, VdtKdefNamBorderGray);
sscanf(defStr, "%f", grayValue);
return(self);
}/* END-getDefaultBorderGray */



/******************************************************************************
* INSTANCE METHOD:- getDefaultDockHandling:  	    	    	    	      *
*   The DockHandling default  determines  if  the  Dock icons are always kept *
* within the View  Port, "Sticky",  or  are  treated  like  ordinary windows, *
* "Slippery".	    	    	    	    	    	    	      	      *
******************************************************************************/
- getDefaultDockHandling

    /* Arguments */
    :(int*)dockHandling	    /*O* Returned Dock Handling toggle value */

{   /* Local Variables */
    const char   *defStr;	/* Pointer to value string of Dock Handling default */

/* BEGIN- getDefaultDockHandling: */
defStr = NXGetDefaultValue(appName, VdtKdefNamDockHandling);
if ( strcmp(VdtKdefValDockHandling, defStr) == 0 )
    /* Indicate "Sticky" Dock Handling */
    *dockHandling = 0;
else
    /* Indicate "Slippery" Dock Handling */
    *dockHandling = 1;
return(self);
}/* END- getDefaultDockHandling: */



/******************************************************************************
* INSTANCE METHOD:- getDefaultIconGravity:  	    	    	    	      *
*   The IconGravity default  determines  which  corner of the screen non-Dock *
* icons will gravitate  towards  when  the  Utilities->Align Icons command is *
* selected from the application menu.	    	    	    	    	      *
******************************************************************************/
- getDefaultIconGravity

    /* Arguments */
    :(int*)gravity	    /*O* Returned Icon Gravity selection */

{   /* Local Variables */
    const char   *defStr; /* Pointer to value string of IconGravity default */

/* BEGIN- getDefaultIconGravity: */
defStr = NXGetDefaultValue(appName, VdtKdefNamIconGravity);
if ( strcmp(defStr,VdtKdefSetTopLeft) == 0 )
    /* Indicate "TopLeft" Icon Gravity */
    *gravity = 0;
else if ( strcmp(defStr,VdtKdefSetTopRight) == 0 )
    /* Indicate "TopRight" Icon Gravity */
    *gravity = 1;
else if ( strcmp(defStr,VdtKdefSetBottomLeft) == 0 )
    /* Indicate "BottomLeft" Icon Gravity */
    *gravity = 2;
else if ( strcmp(defStr,VdtKdefSetBottomRight) == 0 )
    /* Indicate "BottomRight" Icon Gravity */
    *gravity = 3;
else
    /* Indicate "BottomLeft" Dock Handling */
    *gravity = 2;

return(self);
}/* END- getDefaultIconGravity: */



/******************************************************************************
* INSTANCE METHOD:- getDefaultImmobile:  	    	    	    	      *
*   The Immobile default determines  if  the VDT window has a drag bar on it. *
* The default "No" means that it does have a drag bar.  Setting this to "Yes" *
* means the window will  be  displayed  without  a  drag bar and so cannot be *
* moved like and ordinary window.   	    	    	    	    	      *
******************************************************************************/
- getDefaultImmobile

    /* Arguments */
    :(int*)immobile	    /*O* Returned immobile switch value */

{   /* Local Variables */
    const char	*defStr;    /* Pointer to value string of Immobile default */

/* BEGIN- getDefaultImmobile: */
defStr = NXGetDefaultValue(appName, VdtKdefNamImmobile);
if ( strcmp(VdtKdefSetNo, defStr) == 0 )
    /* The immobile flag is set to "No" and is disabled */
    *immobile = 0;
else
    /* Assume it is enabled */
    *immobile = 1;
return(self);
}/* END- getDefaultImmobile: */



/******************************************************************************
* INSTANCE METHOD:- getDefaultOrigin::    	    	    	    	      *
*   This function  returns  the  current values for the default VDT View Port *
* Origin.   The  VDT  Origin  default determines which section of the VDT the *
* View Port will initially be placed.  The Origin default defines the X and Y *
* position, in screen  sizes,  of  the  View  Port origin.  In a 2 x 2 VDT an *
* Origin of "0 0" puts  the View Port at the bottom left of the VDT, while an *
* Origin of "1 1" will put the View Port at the upper left of the VDT.	      *
******************************************************************************/
- getDefaultOrigin

    /* Arguments */
    :(int*)xPos	    /*O* View Port Origin X Position */
    :(int*)yPos	    /*O* View Port Origin Y Position */ 

{   /* Local Variables */
    const char	*defStr;	/* Pointer to value string of Origin default */

/* BEGIN- getDefaultOrigin:: */
defStr = NXGetDefaultValue(appName, VdtKdefNamOrigin);
sscanf(defStr, "%d %d", xPos, yPos);
return(self);
}/* END- getDefaultOrigin:: */



/******************************************************************************
* INSTANCE METHOD:- getDefaultPanDelta:  	    	    	    	      *
*   The PanDelta default  expresses   the  percentage  of the physical screen *
* that is to be shifted in one pan increment.  The default value of 100 means *
* the VDT View Port is shifted by on half the physical screen width or height *
* for the appropriate direction.	    	    	    	    	      *
******************************************************************************/
- getDefaultPanDelta

    /* Arguments */
    :(int*)panDelta	    /*O* Returned PanDelta percentage */

{   /* Local Variables */
    const char	*defStr;    /* Pointer to value string of PanDelta default */

/* BEGIN- getDefaultPanDelta: */
defStr = NXGetDefaultValue(appName, VdtKdefNamPanDelta);
sscanf(defStr, "%d", panDelta);
return(self);
}/* END- getDefaultPanDelta: */



/******************************************************************************
* INSTANCE METHOD:- getDefaultPanGrid:  	    	    	    	      *
*   The PanGrid default expresses the percentage of the physical screen to be *
* used panning grid increment.  The default value of 0 means there is no grid *
* points used in mouse based  panning.   So  the  View Port moves Continously *
* with mouse.  If  the  PanGrid  is  set between 1 and 100 then mouse panning *
* will move incrementally according  to the PanGrid physical screen width and *
* height percentage.	    	    	    	    	    	    	      *
******************************************************************************/
- getDefaultPanGrid

    /* Arguments */
    :(int*)panGrid	    /*O* Returned PanGrid percentage */

{   /* Local Variables */
    const char	*defStr;    /* Pointer to value string of PanDelta default */

/* BEGIN-getDefaultPanGrid: */
defStr = NXGetDefaultValue(appName, VdtKdefNamPanGrid);
sscanf(defStr, "%d", panGrid);
return(self);
}/* END-getDefaultPanGrid: */



/******************************************************************************
* INSTANCE METHOD:- getDefaultPanJump:  	    	    	    	      *
*   The PanJump default  determines if  the  VDT  View  is centered about the *
* pointer if a mouse click is detected in the VDT View.  The default is "No". *
******************************************************************************/
- getDefaultPanJump

    /* Arguments */
    :(int*)panJump	    /*O* Returned Pan Jump toggle value */

{   /* Local Variables */
    const char	*defStr;    /* Pointer to value string of PanJump default */

/* BEGIN- getDefaultPanJump: */
defStr = NXGetDefaultValue(appName, VdtKdefNamPanJump);
if ( strcmp(VdtKdefSetYes, defStr) == 0 )
    /* The Pan Jump is enabled */
    *panJump = 1;
else
    /* Assume it is disabled */
    *panJump = 0;
return(self);
}/* END- getDefaultPanJump: */



/******************************************************************************
* INSTANCE METHOD:- getDefaultResizeBar:  	    	    	    	      *
*   The ResizeBar determines if the VDT window has a resize bar at the bottom *
* of the window.  The default is "Yes".	    	    	    	    	      *
******************************************************************************/
- getDefaultResizeBar

    /* Arguments */
    :(int*)resizeBar	    /*O* Returned resize bar toggle value */

{   /* Local Variables */
    const char	*defStr;    /* Pointer to value string of ResizeBar default */

/* BEGIN- getDefaultResizeBar: */
defStr = NXGetDefaultValue(appName, VdtKdefNamResizeBar);
if ( strcmp(VdtKdefSetYes, defStr) == 0 )
    /* The resize bar is enabled */
    *resizeBar = 1;
else
    /* Assume it is disabled */
    *resizeBar = 0;
return(self);
}/* END- getDefaultResizeBar: */



/******************************************************************************
* INSTANCE METHOD:- getDefaultScale:	    	    	    	    	      *
*   The VDT Scale is the ratio  of  the  VDT  Size  to the size of the window *
* representing the VDT.   The  Scale  factor  must  be  sufficiently large to *
* allow the VDT window to fit within the physical screen limits.              *
******************************************************************************/
- getDefaultScale

    /* Arguments */
    :(float*)scale  	/*O* Scaling factor of VDT Window */

{   /* Local Variables */
    const char	*defStr;    /* Pointer to value string of Scale default */

/* BEGIN- getDefaultScale: */
defStr = NXGetDefaultValue(appName, VdtKdefNamScale);
sscanf(defStr, "%f", scale);
return(self);
}/* END- getDefaultScale: */



/******************************************************************************
* INSTANCE METHOD:- getDefaultSize::	    	    	    	    	      *
*   Get the size of the Virtual Desk Top.   The size is expressed in units of *
* physical screen size.   Two integers indicate the Size default representing *
* the desired width and height of the VDT.  The default VDT Size is 2 x 2, or *
* twice the physical screen width and twice as high. 	    	    	      *
******************************************************************************/
- getDefaultSize

    /* Arguments */
    :(int*)width    	/*O* VDT width in screen size widths */
    :(int*)height   	/*O* VDT height in screen size heights */

{   /* Local Variables */
    const char	*defStr;    /* Pointer to value string of Size default */

/* BEGIN- getDefaultSize:: */
defStr = NXGetDefaultValue(appName, VdtKdefNamSize);
sscanf(defStr, "%d %d", width, height);
return(self);
}/* END- getDefaultSize:: */



/******************************************************************************
* INSTANCE METHOD:- getDefaultWinLoc::	    	    	    	    	      *
*   The WinLocX and WinLocY defaults define where the bottom left hand corner *
* of the VDT window should be placed on start up.    	    	    	      *
******************************************************************************/
- getDefaultWinLoc

    /* Arguments */
    :(int*)locX    	/*O* VDT Window Bottom Left X location */
    :(int*)locY   	/*O* VDT Window Bottom Left Y location */

{   /* Local Variables */
    const char	*defStr;    /* Pointer to value string of WinLoc[XY] default */

/* BEGIN- getDefaultWinLoc:: */
defStr = NXGetDefaultValue(appName, VdtKdefNamWinLocX);
sscanf(defStr, "%d", locX);
defStr = NXGetDefaultValue(appName, VdtKdefNamWinLocY);
sscanf(defStr, "%d", locY);
return(self);
}/* END- getDefaultWinLoc:: */



/******************************************************************************
* INSTANCE METHOD:- getDefaultWindowLevel:    	    	    	    	      *
*   The WindowLevel  default  defines  what  the  startup window tier the VDT *
* window is  placed  in.   This  default  is  changeable  at  runtime via the *
* Preference panel.    	    	    	    	    	    	    	      *
******************************************************************************/
- getDefaultWindowLevel

    /* Arguments */
    :(int*)level    	/*O* VDT Window Tier level */

{   /* Local Variables */
    const char	*defStr;  /* Pointer to value string of Window Level default */

/* BEGIN- getDefaultWindowLevel: */
defStr = NXGetDefaultValue(appName, VdtKdefNamWindowLevel);

if ( strcmp(VdtKdefSetNormal, defStr) == 0 )
    *level = 0;
else if ( strcmp(VdtKdefSetFloating, defStr) == 0 )
    *level = 1;
else if ( strcmp(VdtKdefSetDock, defStr) == 0 )
    *level = 2;
else if ( strcmp(VdtKdefSetSubMenu, defStr) == 0)
    *level = 3;
else if ( strcmp(VdtKdefSetMainMenu, defStr) == 0 )
    *level = 4;
else
    *level = 1;

return(self);
}/* END- getDefaultWindowLevel: */



/******************************************************************************
* INSTANCE METHOD:- getDefaultWindowMotion:  	    	    	    	      *
*   The WindowMotion default determines if the action of moving a window icon *
* in the VDT window is immediately  reflected  in the windows position, or if *
* is deffered until user completes the move.  The default is "Deffered".      *
******************************************************************************/
- getDefaultWindowMotion

    /* Arguments */
    :(int*)motion	    /*O* Returned Window Motion toggle value */

{   /* Local Variables */
    const char	*defStr;  /* Pointer to value string of WindowMotion default */

/* BEGIN- getDefaultWindowMotion: */
defStr = NXGetDefaultValue(appName, VdtKdefNamWindowMotion);
if ( strcmp(VdtKdefValWindowMotion, defStr) == 0 )
    /* Indicate "Deffered" Window Motion updates */
    *motion = 0;
else
    /* Indicate "Immediate" Window Motion updates */
    *motion = 1;

return(self);
}/* END- getDefaultWindowMotion: */



/******************************************************************************
* INSTANCE METHOD:- getVdtWindow    	  	    	    	    	      *
*   This method returns the  object  ID  of the VDT Window containing the VDT *
* View.  The IVvdtWindow instance variable is set as an NIB outlet.           *
******************************************************************************/
- getVdtWindow

{/* BEGIN- getVdtWindow */
return(IVvdtWindow);
}/* END- getVdtWindow */



/******************************************************************************
* INSTANCE METHOD:- getVdtView    	  	    	    	    	      *
*   This method returns the  object  ID  of the VDT View contained in the VDT *
* Window.  The IVvdtView instance variable is set as an NIB outlet.           *
******************************************************************************/
- getVdtView

{/* BEGIN- getVdtView */
return(IVvdtView);
}/* END- getVdtView */



/******************************************************************************
* INSTANCE METHOD:- registerAppDefaults	    	    	                      *
*   This method registers the  defaults  for  the VDT applicaiton that define *
* the size, scaling  and  view  port  origin of the Virtual Desk Top which is *
* needed to create the  VdtWindow  and  initialize the VdtView.  Also defined *
* are  defaults  for   determining  the  startup  window  location,  as  well *
* preferences window level and window motion.	    	    	    	      *
******************************************************************************/
- registerAppDefaults

{   /* Local Variables */
    static NXDefaultsVector VdtDefaults =
    	{
    	    {VdtKdefNamBorderGray,   VdtKdefValBorderGray},
    	    {VdtKdefNamDockHandling, VdtKdefValDockHandling},
    	    {VdtKdefNamIconGravity,  VdtKdefValIconGravity},
    	    {VdtKdefNamImmobile,     VdtKdefValImmobile},
    	    {VdtKdefNamOrigin,       VdtKdefValOrigin},
    	    {VdtKdefNamPanDelta,     VdtKdefValPanDelta},
    	    {VdtKdefNamPanGrid,      VdtKdefValPanGrid},
    	    {VdtKdefNamPanJump,	     VdtKdefValPanJump},
    	    {VdtKdefNamResizeBar,    VdtKdefValResizeBar},
    	    {VdtKdefNamScale,        VdtKdefValScale},
    	    {VdtKdefNamSize,         VdtKdefValSize},
    	    {VdtKdefNamWinLocX,      VdtKdefValWinLocX},
    	    {VdtKdefNamWinLocY,      VdtKdefValWinLocY},
    	    {VdtKdefNamWindowLevel,  VdtKdefValWindowLevel},
    	    {VdtKdefNamWindowMotion, VdtKdefValWindowMotion},
    	    {NULL}
    	};

/* BEGIN registerAppDefaults */

/* Register the default names and values this application will respond to */
NXRegisterDefaults(appName, VdtDefaults);

/* Make sure the defaults are set legal values */
[self validateAppDefaults];

return(self);
}/* END registerAppDefaults */



/******************************************************************************
* INSTANCE METHOD:- validateAppDefaults	        	    	              *
*   This method makes  sure  all  the  Application  dwrites  are set to legal *
* values.   Incorrect  defaults  are  corrected  in the defaults registration *
* table.    	    	    	    	    	    	    		      *
******************************************************************************/
- validateAppDefaults

{   /* Local Variables */
    float   	borderGray;    /* Validated Border Gray default value */
    const char *defStr;        /* Pointer to retreived default string */
    int	    	originX;       /* Validated Origin X default value */
    int	    	originY;       /* Validated Origin Y default value */
    int	    	panDelta;      /* Validated PanDelta default value */
    int	    	panGrid;       /* Validated PanGrid default value */
    float   	scale;	       /* Validated Scale default value */
    int	    	sizeH;         /* Validated Size height default value */
    int	    	sizeW;         /* Validated Size width default value */
    char    	validStr[64];  /* String for formating valid default setting */

/* BEGIN validateAppDefaults */

/* Make sure BorderGray default is between 0.0 and 1.0 */
defStr = NXGetDefaultValue(appName, VdtKdefNamBorderGray);
sscanf(defStr, "%f", &borderGray);
if ( borderGray < 0.0 )
    borderGray = 0.0;
if ( borderGray > 1.0 )
    borderGray = 1.0;
sprintf(validStr, "%0.3f", borderGray);
NXSetDefault(appName, VdtKdefNamBorderGray, validStr);

/* Make sure DockHandling default is "Sticky" or "Slippery */
defStr = NXGetDefaultValue(appName, VdtKdefNamDockHandling);
if ( strcmp(defStr,VdtKdefSetSticky) && strcmp(defStr,VdtKdefSetSlippery) )
    /* The default setting is invalid, set it to default value */
    NXSetDefault(appName, VdtKdefNamDockHandling, VdtKdefValDockHandling);

/* Make sure IconGravity is specified as properly */
defStr = NXGetDefaultValue(appName, VdtKdefNamIconGravity);
if ( strcmp(defStr,VdtKdefSetTopLeft) &&
     strcmp(defStr,VdtKdefSetTopRight) &&
     strcmp(defStr,VdtKdefSetBottomLeft) &&
     strcmp(defStr,VdtKdefSetBottomRight) )
    /* The default setting is invalid, set it to default value */
    NXSetDefault(appName, VdtKdefNamIconGravity, VdtKdefValIconGravity);

/* Make sure Immobile is specified as "Yes" or "No" */
defStr = NXGetDefaultValue(appName, VdtKdefNamImmobile);
if ( strcmp(defStr,VdtKdefSetYes) && strcmp(defStr,VdtKdefSetNo) )
    /* The ResizeBar default isn't set to Yes or No set it to default value */ 
    NXSetDefault(appName, VdtKdefNamImmobile, VdtKdefValImmobile);

/* Keep the PanDelta between 1 and 100 percent. */
defStr = NXGetDefaultValue(appName, VdtKdefNamPanDelta);
sscanf(defStr, "%d", &panDelta);
if ( panDelta < 1 )   panDelta = 1;
if ( panDelta > 100 ) panDelta = 100;
sprintf(validStr, "%d", panDelta);
NXSetDefault(appName, VdtKdefNamPanDelta, validStr);

/* Keep the PanGrid between 0 and 100 percent. */
defStr = NXGetDefaultValue(appName, VdtKdefNamPanGrid);
sscanf(defStr, "%d", &panGrid);
if ( panGrid < 0 )   panGrid = 0;
if ( panGrid > 100 ) panGrid = 100;
sprintf(validStr, "%d", panGrid);
NXSetDefault(appName, VdtKdefNamPanGrid, validStr);

/* Make sure PanJump is specified as "Yes" or "No" */
defStr = NXGetDefaultValue(appName, VdtKdefNamPanJump);
if ( strcmp(defStr,VdtKdefSetYes) && strcmp(defStr,VdtKdefSetNo) )
    /* The PanJump default isn't set to Yes or No set it to default value */ 
    NXSetDefault(appName, VdtKdefNamPanJump, VdtKdefValPanJump);

/* Make sure ResizeBar is specified as "Yes" or "No" */
defStr = NXGetDefaultValue(appName, VdtKdefNamResizeBar);
if ( strcmp(defStr,VdtKdefSetYes) && strcmp(defStr,VdtKdefSetNo) )
    /* The ResizeBar default isn't set to Yes or No set it to default value */ 
    NXSetDefault(appName, VdtKdefNamResizeBar, VdtKdefValResizeBar);

/*************************************************************************
* The VDT size is  restricted  to  maximum  of  8x8 to avoid hitting the *
* 16000 absolute value limit of a screen coordinate.                     *
*************************************************************************/
defStr = NXGetDefaultValue(appName, VdtKdefNamSize);
sscanf(defStr, "%d %d", &sizeW, &sizeH);
if ( sizeW < 1 )   sizeW = 1;
if ( sizeW > 8 )   sizeW = 8;
if ( sizeH < 1 )   sizeH = 1;
if ( sizeH > 8 )   sizeH = 8;
sprintf(validStr,"%d %d", sizeW, sizeH);
NXSetDefault(appName, VdtKdefNamSize, validStr);

/************************************************************************
* The VDT Scale is the ratio of  the VDT Size to the size of the window *
* representing the VDT.  The Scale factor must be sufficiently large to *
* allow the VDT window to fit within  the  physical  screen limits, and *
* small enough to  permit  a  usable  size  desk top.   To this end the *
* Scale default is  modified  so  that the VDT window is no larger than *
* 1/4 of the screen size and at least as large as 64x64.    	        *
************************************************************************/
defStr = NXGetDefaultValue(appName, VdtKdefNamScale);
sscanf(defStr, "%f", &scale);
if ( sizeW / scale > 0.5 )
    scale = sizeW * 2.0;
if ( sizeH / scale > 0.5 )
    scale = sizeH * 2.0;
if ( sizeW * screenSize.width / scale < 64.0 )
    scale = sizeW * screenSize.width / 64.0;
if ( sizeH * screenSize.height / scale < 64.0 )
    scale = sizeH * screenSize.height / 64.0;
sprintf(validStr, "%f", scale);
NXSetDefault(appName, VdtKdefNamScale, validStr);

/************************************************************************
* The VDT Origin  default  determines  which  section  of  the  VDT the *
* viewport will initially be placed.   The Origin default defines the X *
* and Y position in screen  sizes  of  the viewport origin.  In a 2 x 2 *
* VDT an Origin of 0 0 puts  the viewport at the bottom left of the VDT *
* while an Origin of 1 1 will put the viewport at the upper left of the *
* VDT.	    	    	     	    	    	    	    	    	*
************************************************************************/
defStr = NXGetDefaultValue(appName, VdtKdefNamOrigin);
sscanf(defStr, "%d %d", &originX, &originY);
if ( originX < 0 )          originX = 0;
if ( originX > sizeW - 1 )  originX = sizeW - 1;
if ( originY < 0 )          originY = 0;
if ( originY > sizeH - 1 )  originY = sizeH - 1;
sprintf(validStr, "%d %d", originX, originY);
NXSetDefault(appName, VdtKdefNamOrigin, validStr);

/* Make sure WindowLevel specified is valid */
defStr = NXGetDefaultValue(appName, VdtKdefNamWindowLevel);
if ( strcmp(defStr,VdtKdefSetNormal) &&
     strcmp(defStr,VdtKdefSetFloating) && strcmp(defStr,VdtKdefSetDock) &&
     strcmp(defStr,VdtKdefSetSubMenu)  && strcmp(defStr,VdtKdefSetMainMenu) )
    /* Then the WindowLevel is invalid, set it to default value */
    NXSetDefault(appName, VdtKdefNamWindowLevel, VdtKdefValWindowLevel);

/* Make sure WindowMotion specified is valid */
defStr = NXGetDefaultValue(appName, VdtKdefNamWindowMotion);
if ( strcmp(defStr,VdtKdefSetDeferred) && strcmp(defStr,VdtKdefSetImmediate) )
    /* The default setting is invalid, set it to default value */
    NXSetDefault(appName, VdtKdefNamWindowMotion, VdtKdefValWindowMotion);

return(self);
}/* END validateAppDefaults */

@end

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.