Annotation of mstools/mfc/doc/tn013.txt, revision 1.1.1.1

1.1       root        1: 
                      2: Microsoft Foundation Classes                           Microsoft Corporation
                      3: Technical Notes
                      4: 
                      5: #13 : Using the standard dialog classes
                      6: 
                      7: 
                      8: This note describes the use of the standard dialog classes provided
                      9: with MFC.  The classes are CFileDialog, CFontDialog, CColorDialog, 
                     10: CPrintDialog, and CFindReplaceDialog.  They provide standard user interface
                     11: objects for your application.  The class declarations for these
                     12: classes can be found in the source file \C700\MFC\INCLUDE\AFXDLGS.H.
                     13: =============================================================================
                     14: 
                     15: 
                     16: Requirements
                     17: ============
                     18: You may use these classes for any MFC application.  Although these
                     19: classes use the Windows 3.1 COMMDLG functions, they do not require
                     20: Windows 3.1 to run.  You must redistribute COMMDLG.DLL with your 
                     21: application and install the DLL in the user's Windows 3.0 system directory.
                     22: When building an application that uses these classes, you must 
                     23: link with the library COMMDLG.LIB, which is part of the Windows SDK
                     24: installation.
                     25: 
                     26: 
                     27: General Use
                     28: ===========
                     29: These dialogs classes may be used in one of two ways.  You can use them
                     30: "as is" and supply the necessary arguments to the constructor to
                     31: customize the dialogs to suit your needs.  You might also
                     32: consider deriving from these classes and providing a specific constructor
                     33: tailored to your needs.  In either case, these dialogs act
                     34: like standard MFC dialogs, since they derive from CDialog (either
                     35: directly or indirectly.)  You can use message maps and customize
                     36: these dialogs even more.
                     37: 
                     38: COMMDLG dialog APIs interface with the application code via
                     39: a parameter block structure.  The MFC dialog classes provide
                     40: public access to this structure, which may be accessed at any
                     41: time to permit maximum customization.  On the other hand, MFC
                     42: provides sensible defaults for most of the fields in the parameter
                     43: block so that you do not need to worry about them.  These structures
                     44: are described in the online Windows 3.1 API reference.
                     45: 
                     46: 
                     47: Examples
                     48: ========
                     49: The MULTIPAD sample application uses the CFileDialog, CFontDialog,
                     50: and CPrintDialog.  The CHART application uses CFileDialog
                     51: and CPrintDialog.  The MDI application uses the CColorDialog.  In
                     52: addition, the OLE classes use the standard CFileDialog for
                     53: implementing standard OLE user interface objects.
                     54: 
                     55: 
                     56: CFileDialog
                     57: ===========
                     58: The CFileDialog class encapsulates the OPENFILENAME structure
                     59: and the two Windows APIs GetOpenFileName and GetSaveFileName.  This
                     60: dialog box is used to obtain from a user either a new file name 
                     61: or the name of an existing file to open.  CFileDialog is a modal
                     62: dialog and derives from the class CModalDialog.
                     63: 
                     64: To use a CFileDialog class object, create an object using the CFileDialog
                     65: constructor.  The arguments to the constructor are below, note
                     66: that several have default values:
                     67: 
                     68:         bOpenFileDialog     set to TRUE for file open dialog, FALSE for
                     69:                                 a file save dialog
                     70:         lpszDefExt          is the default extension, if a user does not
                     71:                                 include a file extension, this is 
                     72:                                 automatically appended.
                     73:         lpszFileName        is the initial file name (defaults to NULL)
                     74:         dwFlags             is a set of flags that you can supply 
                     75:                                 that allow you to customize the dialog box.  
                     76:                                 See the online Windows API reference 
                     77:                                 (OPENFILESTRUCT) for more information 
                     78:                                 (defaults to OFN_HIDEREADONLY | 
                     79:                                 OFN_OVERWRITEPROMPT)
                     80:         lpszFilter          is a series of pairs of strings that specify
                     81:                                 filters the user may apply to the files. 
                     82:                                 See below (defaults to NULL)
                     83:         pParentWnd          is a pointer to a parent Window.  This is 
                     84:                                 used only when routing customized help 
                     85:                                 messages (defaults to NULL.)
                     86:                                         
                     87: The lpszFilter is used to display a possible list of suffixes.  For
                     88: example Microsoft Excel permits users to open *.XLC and *.XLS
                     89: (and many others).  The filter for Excel would look something
                     90: like the following:
                     91: 
                     92: char BASED_CODE szFilter[] = 
                     93: "Chart Files (*.xlc)|*.xlc|Worksheet Files (*.xlm)|*.xlm|All Files (*.*)|*.*||"
                     94: 
                     95: Note the use of '|' to separate the components of the filter.  Also
                     96: note that the entire filter ends with two '|'.  This is the
                     97: standard MFC syntax for specifying filters.  Also, note that the
                     98: entire string is a standard NULL terminated C string, though you
                     99: can always use an MFC CString object.
                    100: 
                    101: Once the dialog has been constructed, you are free to modify the
                    102: public member variable m_ofn, which is an OPENFILENAME structure.  
                    103: You may manually set any flags or fields that you need.  When you
                    104: are ready to prompt the user call the DoModal function (this is
                    105: a virtual function derived from CModalDialog.)  The user is then
                    106: prompted for a file name (either an existing file or new file,
                    107: depending on the bOpenFileDialog constructor parameter.)  When
                    108: the user clicks OK, CANCEL, or selected the CLOSE option from the
                    109: dialogs System Menu, control is returned to your application.  The
                    110: return value from DoModal indicates success (IDOK) or
                    111: failure (IDCANCEL.)  If the return value is IDCANCEL, either the
                    112: user closed the dialog or clicked CANCEL, or there was an error
                    113: in the parameter block.  If you suspect an error, you can call
                    114: the CommDlgExtendedError API to learn more about the problem.  
                    115: CommDlgExtendedError function returns 0 if there was no error.
                    116: This function differs from the standard OnOK and OnCancel functions
                    117: in that it is possible to force the user to change actions, whereas
                    118: OnOK and OnCancel are notifications that you must accept.
                    119: 
                    120: If the user chose a file name, then you can continue processing.
                    121: The CFileDialog class provides a number of helper functions to 
                    122: retrieve information regarding the users choice:
                    123: 
                    124:         GetPathName     retrieves the fully qualified path name of the
                    125:                         selected file (suitable to use with CFile)
                    126:         GetFileName     retrieves just the file name without an extension
                    127:         GetFileExt      retrieves only the file extension (without a '.')
                    128:         GetFileTitle    retrieves the preferred title of the file, which
                    129:                         should be used as the title text of the frame window
                    130:         GetReadOnlyPref returns TRUE if the user checked the read-only
                    131:                         option.  If this is TRUE, you should open the file
                    132:                         with read-only permissions.
                    133: 
                    134: There are also several "callback" functions that you may respond
                    135: to in your derived CFileDialog class.  You do not need message map
                    136: entries for these, since they are standard virtual functions.
                    137: 
                    138:         OnShareViolation    this function is called when a network
                    139:                                 sharing violation occurs while processing
                    140:                                 the dialog.  See OPENFILENAME in the Windows
                    141:                                 API for more information.
                    142:         OnLBSelChangeNotify this function is called whenever the
                    143:                                 user changes the selection(s) in the file
                    144:                                 list.  You can use this message if you
                    145:                                 need to do extra work when a file is
                    146:                                 a potential selection, such as calculating
                    147:                                 disk space required, or displaying
                    148:                                 file access rights.
                    149:         OnFileNameOK        this function is called when the user 
                    150:                                 selects OK.  You can validate the file name
                    151:                                 and determine if the user can continue.  If
                    152:                                 you return TRUE, be sure to indicate to the
                    153:                                 user the problem with the selected file(s.)
                    154:         
                    155: One other technique available to customize the CFileDialog is to
                    156: introduce a message map in a derived class and to handle messages
                    157: just as you would for any other dialog.  For example, you can modify
                    158: the dialog background color or handle the command messages for
                    159: a new control (the .RC file for the dialog is included.)
                    160: 
                    161: 
                    162: CFontDialog
                    163: ===========
                    164: The CFontDialog class provides support for a standard dialog
                    165: that permits a user to choose a font.  The dialog makes use
                    166: of the COMMDLG structure CHOOSEFONT and the API ChooseFont.  
                    167: CFontDialog is a modal dialog derived from the CModalDialog class.
                    168: 
                    169: To use a CFontDialog class object, create an object using the CFontDialog
                    170: constructor.  The arguments to the constructor are below, note
                    171: that several have default values:
                    172: 
                    173:         lplfInitial the initial settings of the dialog box (defaults
                    174:                         to NULL)
                    175:         dwFlags     is a set of flags that you can use to customize
                    176:                         the function and appearance of the dialog.  See
                    177:                         the CHOOSEFONT structure reference for more
                    178:                         information on possible values. (defaults to 
                    179:                         CF_EFFECTS | CF_SCREENFONTS)
                    180:         hdcPrinter  if supplied is a CDC for the printer for which fonts
                    181:                         are to be selected (defaults to NULL)
                    182:         pParentWnd  is a pointer to a parent Window.  This is 
                    183:                         used only when routing customized help 
                    184:                         messages (defaults to NULL)
                    185: 
                    186: As with the CFileDialog class, once the object has been constructed
                    187: you are free to modify the CHOOSEFONT structure, m_cf, in order
                    188: to customize the dialog box fully.  After any further customization,
                    189: you call the member function DoModal, which will return either
                    190: IDOK or IDCANCEL.  If the return value is IDCANCEL, the user clicked
                    191: on CANCEL or there was an initialization error in the dialog.  You
                    192: may use the CommDlgExtendedError function to determine if there
                    193: was an initialization error.  If the user selected OK the IDOK value
                    194: is returned.  The CFontDialog class provides a number of helper functions
                    195: for extracting information out of the dialog:
                    196: 
                    197:         GetFaceName     returns the face name of the font
                    198:         GetStyleName    returns the style name of the font
                    199:         GetSize         returns the point size in 1/10ths of a point
                    200:         GetColor        returns the color of the selected font
                    201:         GetWeight       returns the weight of the font
                    202:         IsStrikeout     returns TRUE if the strikeout effect was selected
                    203:         IsUnderline     returns TRUE if the underline effect was selected
                    204:         IsBold          returns TRUE if the weight is equal to FW_BOLD
                    205:         IsItalic        returns TRUE if the font is italic
                    206: 
                    207: In addition, the member variable m_lf is the LOGFONT descriptor
                    208: of the font, which can be used in a CreateFontIndirect call,
                    209: or accessed directly.
                    210: 
                    211: You may customize the dialog by deriving your own class from CFontDialog
                    212: and using a message map to handle any messages.  You can also use
                    213: the CFontDialog::GetCurrentFont member function to determine the
                    214: currently selected font while in a message handler.  
                    215: 
                    216: 
                    217: CColorDialog
                    218: ============
                    219: The CColorDialog class provides support for a standard dialog
                    220: that permits a user to choose/create a color.  The dialog makes use
                    221: of the COMMDLG structure CHOOSECOLOR and the API ChooseColor.  
                    222: CColorDialog is a modal dialog derived from the CModalDialog class.
                    223: 
                    224: CColorDialog is used just like CFontDialog.  The COMMDLG structure
                    225: that is used for customizing the dialog is CHOOSECOLOR, and it
                    226: can be modified after construction of the object and before
                    227: DoModal is called.  The arguments to the constructor are as
                    228: follows:
                    229: 
                    230:         clrInit     is a COLORREF that is the initial color selection
                    231:                         (defaults to RGB(0,0,0))
                    232:         dwFlags     is a set of flags that you can use to customize
                    233:                         the function and appearance of the dialog.  See
                    234:                         the CHOOSECOLOR structure reference for more
                    235:                         information on possible values. (defaults to 0)
                    236:         pParentWnd  is a pointer to a parent Window.  This is 
                    237:                         used only when routing customized help 
                    238:                         messages (defaults to NULL.)
                    239: 
                    240: In addition, the CColorDialog permits the user to define up to 16 
                    241: custom colors.  The CColorDialog saves these custom colors between
                    242: invocations of the dialog in the static member variable clrSavedCustom.
                    243: If you wish to save these colors between executions of the application,
                    244: then you must do this yourself.  After the dialog has been constructed
                    245: you call DoModal.  If the return value is IDOK, then you can use
                    246: the GetColor member function to retrieve the color the user
                    247: selected.  
                    248: 
                    249: As with all of the standard dialog classes, you are permitted
                    250: to define a message map in your derived CColorDialog class 
                    251: customize the dialog to suite your needs.  The member function
                    252: SetCurrentColor is provided for forcing the currently selected
                    253: color to a certain value.  As with CFileDialog, a validation
                    254: callback is provided that gives you a chance to override the OK
                    255: selection.  This validation is handled in the OnColorOK virtual
                    256: function.
                    257: 
                    258: 
                    259: CPrintDialog
                    260: ============
                    261: The CPrintDialog class provides support for a standard dialog
                    262: that permits a user to print a document or setup the printer.  
                    263: The dialog makes use of the COMMDLG structure PRINTDLG and the 
                    264: API PrintDlg.  CPrintDialog is a modal dialog derived from 
                    265: the CModalDialog class.  
                    266: 
                    267: As with CFileDialog, CPrintDialog is really two different dialogs,
                    268: distinguished by a constructor argument.  The CPrintDialog class
                    269: can be used to respond to the Print command and/or the Print Setup
                    270: command (both usually in the File menu.)  The arguments to the
                    271: constructor for CPrintDialog include:
                    272: 
                    273:         bPrintSetupOnly TRUE if you want only a Print Setup
                    274:                             dialog, FALSE for the Print dialog
                    275:         dwFlags         is a set of flags that you can use to customize
                    276:                             the function and appearance of the dialog.  See
                    277:                             the PRINTDLG structure reference for more
                    278:                             information on possible values. (defaults to
                    279:                             PD_ALLPAGES | PD_USEDEVMODECOPIES | PD_NOPAGENUMS
                    280:                             | PD_HIDEPRINTTOFILE | PD_NOSELECTION)
                    281:         pParentWnd      is a pointer to a parent Window.  This is 
                    282:                             used only when routing customized help 
                    283:                             messages (defaults to NULL.)
                    284: 
                    285: You may use the GetDefaults member function to retrieve the
                    286: current printer defaults.  All of the helper functions described
                    287: below will be valid after a successful return.  Note that
                    288: this member function requires no user interaction.
                    289: 
                    290: As with other standard dialogs, you can customize the appearance
                    291: and functionality by directly modifying the PRINTDLG structure,
                    292: which is the m_pd member variable.  After any customization
                    293: you call DoModal, which will return IDOK or IDCANCEL as expected.
                    294: Remember to check for extended errors if IDCANCEL is the return
                    295: value, since there might have been a setup error.  If IDOK
                    296: is returned there are a number of functions that can be used
                    297: to retrieve information about the selected printer.  Some of
                    298: these functions might not be valid, depending on the settings
                    299: of dwFlags and m_pd.Flags.
                    300: 
                    301:         GetCopies       returns the number of copies the user chose
                    302:         GetFromPage     returns the starting page of the print job
                    303:         GetToPage       returns the ending page of the print jon
                    304:         GetDevMode      returns a pointer to the device mode
                    305:         GetDriverName   returns a string that is the driver name
                    306:         GetDeviceName   returns a string that is the device name
                    307:         GetPortName     returns a string that is the port name
                    308:         PrintCollate    returns TRUE if the job is to be collated
                    309:         PrintAll        returns TRUE if All pages selected
                    310:         PrintRange      returns TRUE if the user entered a print range
                    311:                         (GetFromPage and GetToPage are then valid)
                    312:         PrintSelection  returns TRUE if the user wishes to print
                    313:                         the current selection
                    314:         GetPrinterDC    returns an HDC for the selected printer
                    315: 
                    316: The GetPrinterDC function returns an HDC only if the bPrintSetupOnly
                    317: constructor parameter was FALSE (i.e. the Print dialog is displayed.)
                    318: You are responsible for calling DeleteDC.  If you wish to
                    319: use this DC as an MFC CDC object, then you can attach it to
                    320: an object as follows:
                    321:         {
                    322:                 CDC printerDC;
                    323:                 CPrintDialog pd(FALSE);
                    324:                 if (pd.DoModal() == IDCANCEL)
                    325:                         return FALSE;
                    326:                 printerDC.Attach(pd.GetPrinterDC());
                    327:                 // print using printerDC
                    328:         } // falling out of scope will implicitly call CDC::DeleteDC
                    329: 
                    330: While the Print dialog is active, it is possible for the user to
                    331: obtain a Print Setup dialog and further customize the print job.  
                    332: MFC handles this automatically for you.  
                    333: 
                    334: You may customize the CPrintDialog object by deriving your
                    335: own class from it and using a message map to handle messages and
                    336: commands of your choosing.  If you wish to handle the same message
                    337: differently depending on if the Print dialog or Print Setup dialog
                    338: is active you will need to derive an additional class, one 
                    339: for the Print dialog and one for your custom Print Setup dialog.  In
                    340: your print dialog class you will also need to override the 
                    341: AttachOnSetup member function.  This function handles the creation
                    342: of a new dialog for when the Print Setup button is clicked.  The
                    343: source code in \C700\MFC\SRC\WINDLGS.CPP provides more documentation
                    344: on how to implement this feature.
                    345: 
                    346: 
                    347: CFindReplaceDialog
                    348: ==================
                    349: The CFindReplaceDialog class is a standard modeless dialog for implementing
                    350: a dialog that queries the user for a find/replace string pair.  The
                    351: dialog is dual purpose in that it can display either a Find dialog
                    352: or a Find Replace dialog.  This is a modeless dialog and is 
                    353: derived from the CDialog class.  You are responsible for implementing
                    354: code that does the actual search and replace, as this dialog only
                    355: receives input from the user.  The relevant parameter block
                    356: structure is FINDREPLACE and the APIs used are FindText and
                    357: ReplaceText.
                    358: 
                    359: Since this dialog is modeless, it should be dynamically allocated
                    360: using operator new.  If you wish to allocate a CFindReplace dialog
                    361: on the stack frame, you will need to derive your own CFindReplaceDialog
                    362: and override the default behavior of the PostNcDestroy function.
                    363: The constructor for this class takes no arguments.  When your application
                    364: needs to query the user for find/replace information the Create
                    365: member function is called.  This will create and show the modeless
                    366: dialog.  The parameters to Create are as follows:
                    367: 
                    368:         bFindDialogOnly TRUE for Find, FALSE for Find and Replace
                    369:         lpszFindWhat    the default search string, such as the
                    370:                             current selection
                    371:         lpszReplaceWith the default replacement string
                    372:                             (defaults to NULL)
                    373:         dwFlags         is a set of flags that you can use to customize
                    374:                             the function and appearance of the dialog.  See
                    375:                             the FINDREPLACE structure reference for more
                    376:                             information on possible values. (defaults to
                    377:                             FR_DOWN)
                    378:         pParentWnd      the parent of the dialog, this is the dialog
                    379:                             that receives the special message indicating
                    380:                             that a find/replace action is requested (defaults
                    381:                             to the current frame window, CWinApp::m_pMainWnd)
                    382: 
                    383: In order for the pParentWnd to be notified of find/replace requests
                    384: you must use the Windows API ::RegisterMessage(FINDMSGSTRING).  The
                    385: return value of this function is a message number that is unique to this
                    386: application instance.  Your frame window should have a message map
                    387: entry that handles this registered message.  The following code
                    388: fragments show how to do this for a frame window class CMyFrameWnd.
                    389: 
                    390:         class CMyFrameWnd : public CFrameWnd
                    391:         {
                    392:                 // normal members
                    393: 
                    394:         protected:
                    395:                 // CFindReplaceDialog helpers   
                    396:                 static CFindReplace* pFindReplace;
                    397:                 static UINT nMsgFind;
                    398:                 afx_msg LONG CmdFindHelper(UINT wParam, LONG lParam);
                    399:                 
                    400:                 DECLARE_MESSAGE_MAP()
                    401:         };
                    402: 
                    403:         BEGIN_MESSAGE_MAP(CMyFrameWnd, CFrameWnd)
                    404:                 // normal message map entries
                    405:                 ON_REGISTERED_MESSAGE(nMsgFind, CmdFindHelper) 
                    406:         END_MESSAGE_MAP
                    407: 
                    408:         UINT CMyFrameWnd::nMsgFind = ::RegisterMessage(FINDMSGSTRING);
                    409:         CFindReplace* CMyFrameWnd::pFindReplace = NULL;
                    410: 
                    411: Note the use of a static member that is the current CFindReplaceDialog
                    412: object.  When the user first executes the Find command, a dialog will
                    413: be created and that object will be used until the Close command on
                    414: the system menu is executed or the user clicks CANCEL.
                    415: 
                    416: Within the CmdFindHelper you will interpret the intentions of the
                    417: user and do the work for find/replace.  In order to assist you, there
                    418: are a number of helper functions available:
                    419:         
                    420:         GetFindString       returns the current find string
                    421:         SearchDown          TRUE of the user wishes to search down
                    422:                                 the document
                    423:         FindNext            TRUE if the user clicked the Find Next
                    424:                                 button
                    425:         MatchCase           TRUE if the user wishes to match case
                    426:                                 of text exactly
                    427:         MatchWholeWord      TRUE if the user wishes to match entire
                    428:                                 words only
                    429:         GetReplaceString    returns the current replace string for
                    430:                                 a replace dialog
                    431:         ReplaceCurrent      TRUE is the user requested that the current
                    432:                                 word be replaced in a replace dialog
                    433:         ReplaceAll          TRUE if the user wishes all occurrences
                    434:                                 to be replaced
                    435:         IsTerminating       TRUE is the dialog is terminating (the
                    436:                                 current m_hWnd is no longer valid when this
                    437:                                 function returns TRUE)
                    438:         GetNotifier         return the CFindReplaceDialog structure
                    439:                                 (valid only in the CmdFindHandler callback
                    440:                                 function)
                    441: 
                    442: The CmdFindHandler upon being called will first use the static
                    443: member function of CFindReplaceDialog, GetNotifier, to convert
                    444: the lParam into a CFindReplaceDialog object pointer, which will
                    445: then be used to call member functions and extract dialog information.
                    446: If you derived your own CFindReplaceDialog, you will need to
                    447: provide a typesafe castdown static member function to safely convert
                    448: the lParam to your own derived CFileDialog.
                    449: 
                    450: Normally the CmdFindHandler will then do a check to see if the
                    451: dialog is being terminated (using IsTerminating) and if this is
                    452: TRUE you will cleanup (delete the current pFindReplace dialog and
                    453: set the member variable to NULL) and possibly store away the
                    454: final find/replace text to be used in the initialization of the
                    455: next dialog.  
                    456: 
                    457: Although this dialog is a modeless dialog, as with other 
                    458: CDialog derived modeless dialogs MFC automatically
                    459: handles the translation dialog messages and routes them to
                    460: your dialog's message map.  Thus you are free to customize your
                    461: CFindReplaceDialog by deriving and supplying a message map with
                    462: the necessary handlers.
                    463: 
                    464: 
                    465: Advanced Usage Notes
                    466: ====================
                    467: Many of these dialogs permit the use of strings to customize
                    468: the appearance or functionality of the dialog.  Whenever a 
                    469: string is used, it is best to use a STRINGTABLE resource 
                    470: rather than embedding the string in your code.  The CString::LoadString
                    471: API can assist you in loading a string from a resource file.
                    472: Similarly, if the string is read-only, you could place it in
                    473: a code segment (use the MFC helper macro BASED_CODE.)
                    474: 
                    475: The standard COMMDLG functions all permit the user to add special
                    476: "hook" functions in order to customize the dialog box appearance and
                    477: functionality.  With MFC you should not use these special
                    478: hook procedures, but you should use a derived class and a message
                    479: just as you would for any other standard Windows dialog.  If you
                    480: require the use of the hook function, be sure to save the MFC
                    481: hook function and call it if you do not handle a message, just
                    482: as when dynamically subclassing a Windows window.
                    483: 
                    484: As with other short-lived objects, dialogs that derive from
                    485: the CModalDialog class are best allocated on the stack frame.
                    486: The CFindReplaceDialog class is designed to be heap allocated
                    487: (via operator new) since it is a long-lived object.  
                    488: 
                    489: All of these dialog classes have a parent window pointer as
                    490: a constructor parameter.  The classes will all use the current
                    491: frame window (CWinApp::m_pMainWnd) as the parent if you
                    492: specify NULL as the pParentWnd parameter (the default.)  If
                    493: you are spawning a standard dialog from another dialog, it
                    494: you must pass the current dialog as the the parent pointer 
                    495: (the 'this' pointer in the command handler that spawns the
                    496: dialog.  If you do not, the two dialogs will have sibling
                    497: relationship rather than a parent/child relationship.
                    498: 
                    499: COMMDLG functions require significant stack space, so be
                    500: sure to have at least 16K of stack space available (use the
                    501: .DEF file to change the default.)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.