2nd step for moving option parsing from winboard to the backend
authorH.G. Muller <h.g.muller@hccnet.nl>
Thu, 19 Nov 2009 03:29:57 +0000 (19:29 -0800)
committerArun Persaud <arun@nubati.net>
Thu, 19 Nov 2009 03:29:57 +0000 (19:29 -0800)
This is the next step in option-setting refactoring: All options that are
defined in XBoard are now included in the WinBoard ArgDescriptor list.
The handling of sound option has been harmonized: the sound names
now all initially go to the appData array, (as in XB) in stead of directly to the
WB-specific variables, and LoadAllSounds now takes care of the copying.
A new routine ExportSounds copies them back before saving settings
(which, in XBoard, could be a no-op).

The definition of defaults for the XB-only options has been moved to common.h.

common.h
winboard/winboard.c
xboard.h

index 18c3b38..03f7bb0 100644 (file)
--- a/common.h
+++ b/common.h
@@ -168,10 +168,18 @@ int pclose(FILE *);
 #define JAIL_SQUARE_COLOR       "#808080"
 #define HIGHLIGHT_SQUARE_COLOR "#FFFF00"
 #define PREMOVE_HIGHLIGHT_COLOR        "#FF0000"
 #define JAIL_SQUARE_COLOR       "#808080"
 #define HIGHLIGHT_SQUARE_COLOR "#FFFF00"
 #define PREMOVE_HIGHLIGHT_COLOR        "#FF0000"
+#define LOWTIMEWARNING_COLOR    "#FF0000"
 #define BELLCHAR                '\007'
 #define NULLCHAR                '\000'
 #define FEATURE_TIMEOUT         10000 /*ms*/
 
 #define BELLCHAR                '\007'
 #define NULLCHAR                '\000'
 #define FEATURE_TIMEOUT         10000 /*ms*/
 
+/* Default to no flashing (the "usual" XBoard behavior) */
+#define FLASH_COUNT    0               /* Number of times to flash */
+#define FLASH_RATE     5               /* Flashes per second */
+
+/* Default delay per character (in msec) while sending login script */
+#define MS_LOGIN_DELAY  0
+
 /* Zippy defaults */
 #define ZIPPY_TALK FALSE
 #define ZIPPY_PLAY FALSE
 /* Zippy defaults */
 #define ZIPPY_TALK FALSE
 #define ZIPPY_PLAY FALSE
@@ -443,7 +451,7 @@ typedef struct {
                          ICS logon script (xboard only) */
     Boolean colorize;  /* If True, use the following colors to color text */
     /* Strings for colors, as "fg, bg, bold" (strings used in xboard only) */
                          ICS logon script (xboard only) */
     Boolean colorize;  /* If True, use the following colors to color text */
     /* Strings for colors, as "fg, bg, bold" (strings used in xboard only) */
-    char *colorShout;
+    char *colorShout;    // [HGM] IMPORTANT: order must conform to ColorClass definition
     char *colorSShout;
     char *colorChannel1;
     char *colorChannel;
     char *colorSShout;
     char *colorChannel1;
     char *colorChannel;
@@ -454,7 +462,7 @@ typedef struct {
     char *colorSeek;
     char *colorNormal;
     char *soundProgram; /* sound-playing program */
     char *colorSeek;
     char *colorNormal;
     char *soundProgram; /* sound-playing program */
-    char *soundShout;
+    char *soundShout;     // [HGM] IMPORTANT: order must be as in ColorClass
     char *soundSShout;
     char *soundChannel1;
     char *soundChannel;
     char *soundSShout;
     char *soundChannel1;
     char *soundChannel;
@@ -463,12 +471,13 @@ typedef struct {
     char *soundChallenge;
     char *soundRequest;
     char *soundSeek;
     char *soundChallenge;
     char *soundRequest;
     char *soundSeek;
-    char *soundMove;
+    char *soundMove;     // [HGM] IMPORTANT: order must be as in SoundClass
+    char *soundBell;
+    char *soundIcsAlarm;
     char *soundIcsWin;
     char *soundIcsLoss;
     char *soundIcsDraw;
     char *soundIcsUnfinished;
     char *soundIcsWin;
     char *soundIcsLoss;
     char *soundIcsDraw;
     char *soundIcsUnfinished;
-    char *soundIcsAlarm;
     Boolean reuseFirst;
     Boolean reuseSecond;
     Boolean animateDragging; /* If True, animate mouse dragging of pieces */
     Boolean reuseFirst;
     Boolean reuseSecond;
     Boolean animateDragging; /* If True, animate mouse dragging of pieces */
@@ -611,6 +620,7 @@ typedef struct {
     char *wrapContSeq; /* continuation sequence when xboard wraps text */
     Boolean useInternalWrap; /* use internal wrapping -- noJoin usurps this if set */
     Boolean pasteSelection; /* paste X selection instead of clipboard */
     char *wrapContSeq; /* continuation sequence when xboard wraps text */
     Boolean useInternalWrap; /* use internal wrapping -- noJoin usurps this if set */
     Boolean pasteSelection; /* paste X selection instead of clipboard */
+    int nrVariations;   /* [HGM] multivar  */
 } AppData, *AppDataPtr;
 
 /* [AS] PGN tags (for showing in the game list) */
 } AppData, *AppDataPtr;
 
 /* [AS] PGN tags (for showing in the game list) */
index 6f1d434..ee5fa0c 100644 (file)
@@ -903,6 +903,8 @@ typedef struct {
 \r
 int junk;\r
 \r
 \r
 int junk;\r
 \r
+#define XBOARD FALSE\r
+\r
 ArgDescriptor argDescriptors[] = {\r
   /* positional arguments */\r
   { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE, INVALID },\r
 ArgDescriptor argDescriptors[] = {\r
   /* positional arguments */\r
   { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE, INVALID },\r
@@ -952,7 +954,30 @@ ArgDescriptor argDescriptors[] = {
   { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE, INVALID },\r
   { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE, (ArgIniType) SECOND_DIRECTORY },\r
   { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE, INVALID },\r
   { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE, INVALID },\r
   { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE, (ArgIniType) SECOND_DIRECTORY },\r
   { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE, INVALID },\r
-  /*!!bitmapDirectory?*/\r
+\r
+  /* some options only used by the XBoard front end, and ignored in WinBoard         */\r
+  /* Their saving is controlled by XBOARD, which in WinBoard is defined as FALSE */\r
+  { "internetChessServerInputBox", ArgBoolean, (LPVOID) &appData.icsInputBox, XBOARD, (ArgIniType) FALSE },\r
+  { "icsinput", ArgTrue, (LPVOID) &appData.icsInputBox, FALSE, INVALID },\r
+  { "xicsinput", ArgFalse, (LPVOID) &appData.icsInputBox, FALSE, INVALID },\r
+  { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE, (ArgIniType) "" },\r
+  { "soundProgram", ArgFilename, (LPVOID) &appData.soundProgram, XBOARD, (ArgIniType) "play" },\r
+  { "fontSizeTolerance", ArgInt, (LPVOID) &appData.fontSizeTolerance, XBOARD, (ArgIniType) 4 },\r
+  { "lowTimeWarningColor", ArgColor, (LPVOID) &appData.lowTimeWarningColor, XBOARD, \r
+       (ArgIniType) LOWTIMEWARNING_COLOR },\r
+  { "lowTimeWarning", ArgBoolean, (LPVOID) &appData.lowTimeWarning, XBOARD, (ArgIniType) FALSE },\r
+  { "titleInWindow", ArgBoolean, (LPVOID) &appData.titleInWindow, XBOARD, (ArgIniType) FALSE },\r
+  { "title", ArgTrue, (LPVOID) &appData.titleInWindow, FALSE, INVALID },\r
+  { "xtitle", ArgFalse, (LPVOID) &appData.titleInWindow, FALSE, INVALID },\r
+  { "flashCount", ArgInt, (LPVOID) &appData.flashCount, XBOARD, (ArgIniType) FLASH_COUNT },\r
+  { "flashRate", ArgInt, (LPVOID) &appData.flashRate, XBOARD, (ArgIniType) FLASH_RATE },\r
+  { "pixmapDirectory", ArgFilename, (LPVOID) &appData.pixmapDirectory, XBOARD, (ArgIniType) "" },\r
+  { "pixmap", ArgFilename, (LPVOID) &appData.pixmapDirectory, FALSE, INVALID },\r
+  { "bitmapDirectory", ArgFilename, (LPVOID) &appData.bitmapDirectory, XBOARD, (ArgIniType) "" },\r
+  { "bm", ArgFilename, (LPVOID) &appData.bitmapDirectory, FALSE, INVALID },\r
+  { "msLoginDelay", ArgInt, (LPVOID) &appData.msLoginDelay, XBOARD, (ArgIniType) MS_LOGIN_DELAY },\r
+  { "pasteSelection", ArgBoolean, (LPVOID) &appData.pasteSelection, XBOARD, (ArgIniType) FALSE },\r
+\r
   { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE, (ArgIniType) REMOTE_SHELL },\r
   { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE, INVALID },\r
   { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE, INVALID },\r
   { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE, (ArgIniType) REMOTE_SHELL },\r
   { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE, INVALID },\r
   { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE, INVALID },\r
@@ -982,6 +1007,8 @@ ArgDescriptor argDescriptors[] = {
   { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE, INVALID },\r
   { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE, INVALID },\r
   { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE, (ArgIniType) TELNET_PROGRAM },\r
   { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE, INVALID },\r
   { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE, INVALID },\r
   { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE, (ArgIniType) TELNET_PROGRAM },\r
+  { "internetChessserverHelper", ArgFilename, (LPVOID) &appData.icsHelper, \r
+       FALSE, INVALID }, // for XB\r
   { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE, (ArgIniType) "" },\r
   { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE, (ArgIniType) "" },\r
   { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE, (ArgIniType) "" },\r
   { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE, (ArgIniType) "" },\r
   { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE, (ArgIniType) "" },\r
   { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE, (ArgIniType) "" },\r
@@ -1060,6 +1087,10 @@ ArgDescriptor argDescriptors[] = {
   { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE, INVALID },\r
   { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,\r
     FALSE, (ArgIniType) TRUE }, /* historical; kept only so old winboard.ini files will parse */\r
   { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE, INVALID },\r
   { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,\r
     FALSE, (ArgIniType) TRUE }, /* historical; kept only so old winboard.ini files will parse */\r
+  { "bell", ArgTrue, (LPVOID) &appData.ringBellAfterMoves, FALSE, INVALID }, // for XB\r
+  { "xbell", ArgFalse, (LPVOID) &appData.ringBellAfterMoves, FALSE, INVALID }, // for XB\r
+  { "movesound", ArgTrue, (LPVOID) &appData.ringBellAfterMoves, FALSE, INVALID }, // for XB\r
+  { "xmovesound", ArgFalse, (LPVOID) &appData.ringBellAfterMoves, FALSE, INVALID }, // for XB\r
   { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE, INVALID },\r
   { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE, INVALID },\r
   { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE, INVALID },\r
   { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE, INVALID },\r
   { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE, INVALID },\r
   { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE, INVALID },\r
@@ -1169,35 +1200,23 @@ ArgDescriptor argDescriptors[] = {
   { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE, INVALID },\r
   { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE, INVALID },\r
   { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE, INVALID },\r
   { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE, INVALID },\r
   { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE, INVALID },\r
   { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE, INVALID },\r
-  { "soundShout", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorShout].sound.name, TRUE, INVALID },\r
-  { "soundSShout", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE, INVALID },\r
-  { "soundChannel1", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE, INVALID },\r
-  { "soundChannel", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE, INVALID },\r
-  { "soundKibitz", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE, INVALID },\r
-  { "soundTell", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorTell].sound.name, TRUE, INVALID },\r
-  { "soundChallenge", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE, INVALID },\r
-  { "soundRequest", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE, INVALID },\r
-  { "soundSeek", ArgFilename,\r
-    (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE, INVALID },\r
-  { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE, INVALID },\r
-  { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE, INVALID },\r
-  { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name, TRUE, INVALID },\r
-  { "soundIcsLoss", ArgFilename, \r
-    (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE, INVALID },\r
-  { "soundIcsDraw", ArgFilename, \r
-    (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE, INVALID },\r
-  { "soundIcsUnfinished", ArgFilename, \r
-    (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE, INVALID },\r
-  { "soundIcsAlarm", ArgFilename, \r
-    (LPVOID) &sounds[(int)SoundAlarm].name, TRUE, INVALID },\r
+  { "soundShout", ArgFilename, (LPVOID) &appData.soundShout, TRUE, (ArgIniType) "" },\r
+  { "soundSShout", ArgFilename, (LPVOID) &appData.soundSShout, TRUE, (ArgIniType) "" },\r
+  { "soundCShout", ArgFilename, (LPVOID) &appData.soundSShout, TRUE, (ArgIniType) "" }, // for XB\r
+  { "soundChannel1", ArgFilename, (LPVOID) &appData.soundChannel1, TRUE, (ArgIniType) "" },\r
+  { "soundChannel", ArgFilename, (LPVOID) &appData.soundChannel, TRUE, (ArgIniType) "" },\r
+  { "soundKibitz", ArgFilename, (LPVOID) &appData.soundKibitz, TRUE, (ArgIniType) "" },\r
+  { "soundTell", ArgFilename, (LPVOID) &appData.soundTell, TRUE, (ArgIniType) "" },\r
+  { "soundChallenge", ArgFilename, (LPVOID) &appData.soundChallenge, TRUE, (ArgIniType) "" },\r
+  { "soundRequest", ArgFilename, (LPVOID) &appData.soundRequest, TRUE, (ArgIniType) "" },\r
+  { "soundSeek", ArgFilename, (LPVOID) &appData.soundSeek, TRUE, (ArgIniType) "" },\r
+  { "soundMove", ArgFilename, (LPVOID) &appData.soundMove, TRUE, (ArgIniType) "" },\r
+  { "soundBell", ArgFilename, (LPVOID) &appData.soundBell, TRUE, (ArgIniType) SOUND_BELL },\r
+  { "soundIcsWin", ArgFilename, (LPVOID) &appData.soundIcsWin, TRUE, (ArgIniType) "" },\r
+  { "soundIcsLoss", ArgFilename, (LPVOID) &appData.soundIcsLoss, TRUE, (ArgIniType) "" },\r
+  { "soundIcsDraw", ArgFilename, (LPVOID) &appData.soundIcsDraw, TRUE, (ArgIniType) "" },\r
+  { "soundIcsUnfinished", ArgFilename, (LPVOID) &appData.soundIcsUnfinished, TRUE, (ArgIniType) "" },\r
+  { "soundIcsAlarm", ArgFilename, (LPVOID) &appData.soundIcsAlarm, TRUE, (ArgIniType) "" },\r
   { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE, (ArgIniType) TRUE },\r
   { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE, INVALID },\r
   { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE, INVALID },\r
   { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE, (ArgIniType) TRUE },\r
   { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE, INVALID },\r
   { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE, INVALID },\r
@@ -1886,29 +1905,27 @@ SetDefaultTextAttribs()
 \r
 VOID\r
 SetDefaultSounds()\r
 \r
 VOID\r
 SetDefaultSounds()\r
-{\r
+{ // [HGM] only sounds for which no option exists\r
   ColorClass cc;\r
   ColorClass cc;\r
-  SoundClass sc;\r
-  for (cc = (ColorClass)0; cc < NColorClasses; cc++) {\r
+  for (cc = ColorNormal; cc < NColorClasses; cc++) {\r
     textAttribs[cc].sound.name = strdup("");\r
     textAttribs[cc].sound.data = NULL;\r
   }\r
     textAttribs[cc].sound.name = strdup("");\r
     textAttribs[cc].sound.data = NULL;\r
   }\r
-  for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {\r
-    sounds[sc].name = strdup("");\r
-    sounds[sc].data = NULL;\r
-  }\r
-  sounds[(int)SoundBell].name = strdup(SOUND_BELL);\r
 }\r
 \r
 VOID\r
 LoadAllSounds()\r
 }\r
 \r
 VOID\r
 LoadAllSounds()\r
-{\r
+{ // [HGM] import name from appData first\r
   ColorClass cc;\r
   SoundClass sc;\r
   ColorClass cc;\r
   SoundClass sc;\r
-  for (cc = (ColorClass)0; cc < NColorClasses; cc++) {\r
+  for (cc = (ColorClass)0; cc < ColorNormal; cc++) {\r
+    textAttribs[cc].sound.name = strdup((&appData.soundShout)[cc]);\r
+    textAttribs[cc].sound.data = NULL;\r
     MyLoadSound(&textAttribs[cc].sound);\r
   }\r
   for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {\r
     MyLoadSound(&textAttribs[cc].sound);\r
   }\r
   for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {\r
+    sounds[sc].name = strdup((&appData.soundMove)[sc]);\r
+    sounds[sc].data = NULL;\r
     MyLoadSound(&sounds[sc]);\r
   }\r
 }\r
     MyLoadSound(&sounds[sc]);\r
   }\r
 }\r
@@ -2153,6 +2170,17 @@ SaveFontArg(FILE *f, ArgDescriptor *ad)
        }\r
       }\r
 \r
        }\r
       }\r
 \r
+VOID\r
+ExportSounds()\r
+{ // [HGM] copy the names from the internal WB variables to appData\r
+  ColorClass cc;\r
+  SoundClass sc;\r
+  for (cc = (ColorClass)0; cc < ColorNormal; cc++)\r
+    (&appData.soundShout)[cc] = textAttribs[cc].sound.name;\r
+  for (sc = (SoundClass)0; sc < NSoundClasses; sc++)\r
+    (&appData.soundMove)[sc] = sounds[sc].name;\r
+}\r
+\r
 void\r
 SaveAttribsArg(FILE *f, ArgDescriptor *ad)\r
 {      // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though\r
 void\r
 SaveAttribsArg(FILE *f, ArgDescriptor *ad)\r
 {      // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though\r
@@ -2223,6 +2251,9 @@ SaveSettings(char* name)
   wpEngineOutput.visible = EngineOutputIsUp();\r
   GetActualPlacement(engineOutputDialog, &wpEngineOutput);\r
 \r
   wpEngineOutput.visible = EngineOutputIsUp();\r
   GetActualPlacement(engineOutputDialog, &wpEngineOutput);\r
 \r
+  // [HGM] in WB we have to copy sound names to appData first\r
+  ExportSounds();\r
+\r
   for (ad = argDescriptors; ad->argName != NULL; ad++) {\r
     if (!ad->save) continue;\r
     switch (ad->argType) {\r
   for (ad = argDescriptors; ad->argName != NULL; ad++) {\r
     if (!ad->save) continue;\r
     switch (ad->argType) {\r
index 5806d53..9f3cdd7 100644 (file)
--- a/xboard.h
+++ b/xboard.h
@@ -107,12 +107,7 @@ typedef struct {
 #define FIRST_CHESS_PROGRAM    "fairymax"
 #define SECOND_CHESS_PROGRAM   "fairymax"
 
 #define FIRST_CHESS_PROGRAM    "fairymax"
 #define SECOND_CHESS_PROGRAM   "fairymax"
 
-/* Default to no flashing (the "usual" XBoard behavior) */
-#define FLASH_COUNT    0               /* Number of times to flash */
-#define FLASH_RATE     5               /* Flashes per second */
-
-/* Default delay per character (in msec) while sending login script */
-#define MS_LOGIN_DELAY  0
+#define XBOARD True
 
 typedef int (*FileProc) P((FILE *f, int n, char *title));
 void CatchDeleteWindow(Widget w, String procname);
 
 typedef int (*FileProc) P((FILE *f, int n, char *title));
 void CatchDeleteWindow(Widget w, String procname);