home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
tcltk805.zip
/
tcl805s.zip
/
tk8.0.5
/
os2
/
tkOS2Dialog.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-09-08
|
44KB
|
1,393 lines
/*
* tkOS2Dialog.c --
*
* Contains the OS/2 implementation of the common dialog boxes.
*
* Copyright (c) 1996 Sun Microsystems, Inc.
* Copyright (c) 1999-2000 Illya Vaes
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* SCCS: @(#) tkOS2Dialog.c 1.5 96/09/11 19:24:28
*
*/
#include "tkOS2Int.h"
#include "TkResIds.h"
#include "tkFileFilter.h"
/*
* Global variables
*/
static PFN colorSelectWndProcPtr = NULL;
static PFNWP oldDlgProc = NULL;
static ULONG chosenColor = 0;
#if ((TK_MAJOR_VERSION == 4) && (TK_MINOR_VERSION <= 2))
/*
* The following function is implemented on tk4.3 and after only
*/
#define Tk_GetHWND TkOS2GetHWND
#endif
#define SAVE_FILE 0
#define OPEN_FILE 1
/*----------------------------------------------------------------------
* MsgTypeInfo --
*
* This structure stores the type of available message box in an
* easy-to-process format. Used by the Tk_MessageBox() function
*----------------------------------------------------------------------
*/
typedef struct MsgTypeInfo {
char * name;
int type;
int numButtons;
char * btnNames[3];
} MsgTypeInfo;
#define NUM_TYPES 6
static MsgTypeInfo
msgTypeInfo[NUM_TYPES] = {
{"abortretryignore", MB_ABORTRETRYIGNORE, 3, {"abort", "retry", "ignore"}},
{"ok", MB_OK, 1, {"ok" }},
{"okcancel", MB_OKCANCEL, 2, {"ok", "cancel" }},
{"retrycancel", MB_RETRYCANCEL, 2, {"retry", "cancel" }},
{"yesno", MB_YESNO, 2, {"yes", "no" }},
{"yesnocancel", MB_YESNOCANCEL, 3, {"yes", "no", "cancel"}}
};
static MRESULT EXPENTRY ColorDlgProc _ANSI_ARGS_((HWND hwnd, ULONG message,
MPARAM param1, MPARAM param2));
static int GetFileName _ANSI_ARGS_((ClientData clientData,
Tcl_Interp *interp, int argc, char **argv,
int isOpen));
static int MakeFilter _ANSI_ARGS_((Tcl_Interp *interp,
FILEDLG *fdlgPtr, char * string,
FileFilterList *flistPtr));
static int ParseFileDlgArgs _ANSI_ARGS_((Tcl_Interp * interp,
FILEDLG *fdlgPtr, int argc, char ** argv,
int isOpen, HWND *hwndParent,
FileFilterList *flistPtr));
static int ProcessError _ANSI_ARGS_((Tcl_Interp * interp,
ERRORID lastError, HWND hWnd));
/*
*----------------------------------------------------------------------
*
* EvalArgv --
*
* Invokes the Tcl procedure with the arguments. argv[0] is set by
* the caller of this function. It may be different than cmdName.
* The TCL command will see argv[0], not cmdName, as its name if it
* invokes [lindex [info level 0] 0]
*
* Results:
* TCL_ERROR if the command does not exist and cannot be autoloaded.
* Otherwise, return the result of the evaluation of the command.
*
* Side effects:
* The command may be autoloaded.
*
*----------------------------------------------------------------------
*/
static int
EvalArgv(interp, cmdName, argc, argv)
Tcl_Interp *interp; /* Current interpreter. */
char * cmdName; /* Name of the TCL command to call */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
Tcl_CmdInfo cmdInfo;
if (!Tcl_GetCommandInfo(interp, cmdName, &cmdInfo)) {
char * cmdArgv[2];
/*
* This comand is not in the interpreter yet -- looks like we
* have to auto-load it
*/
if (!Tcl_GetCommandInfo(interp, "auto_load", &cmdInfo)) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "cannot execute command \"auto_load\"",
NULL);
return TCL_ERROR;
}
cmdArgv[0] = "auto_load";
cmdArgv[1] = cmdName;
if ((*cmdInfo.proc)(cmdInfo.clientData, interp, 2, cmdArgv)!= TCL_OK){
return TCL_ERROR;
}
if (!Tcl_GetCommandInfo(interp, cmdName, &cmdInfo)) {
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "cannot auto-load command \"",
cmdName, "\"",NULL);
return TCL_ERROR;
}
}
return (*cmdInfo.proc)(cmdInfo.clientData, interp, argc, argv);
}
/*
*----------------------------------------------------------------------
*
* Tk_ChooseColorCmd --
*
* This procedure implements the color dialog box for the OS/2
* platform. See the user documentation for details on what it
* does.
*
* Results:
* See user documentation.
*
* Side effects:
* A dialog window is created the first time this procedure is called.
* This window is not destroyed and will be reused the next time the
* application invokes the "tk_chooseColor" command.
*
*----------------------------------------------------------------------
*/
int
Tk_ChooseColorCmd(clientData, interp, argc, argv)
ClientData clientData; /* Main window associated with interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
/*
* From Rick Papo's "Undocumented Features of OS/2" (INF file):
* The color wheel control used by the Solid and Mixed Color Palette
* object is a publicly registered window class within OS/2, but is
* undocumented. The following notes are all that is necessary to
* use this control class:
* (1) You must load the module WPCONFIG.DLL so that the publicly
* registered window message processor (colorSelectWndProc) can
* be used without an addressing violation.
* (2) Create your control window with WinCreateWindow or through a
* dialog template, using the window class name "ColorSelectClass".
* (3) If you used WinCreateWindow you will need to reposition the
* control window each time the parent window is resized, as
* otherwise the control will reposition itself out of view.
* Dialogs seem to handle this automatically.
* (4) The only control message defined -to- the control is 0x0602
* under OS/2 Warp 4 or later, or (by some reports) 0x1384 on
* older versiosn of OS/2. Message parameter one must contain the
* RGB value to which the color wheel will be set.
* (5) The only control message defined -from- the control is 0x0601
* under OS/2 Warp 4 or later, or (by some reports) 0x130C on
* older version of OS/2. Message parameter one will contain the
* RGB value to which the color wheel will be set.
* (6) The control can only be sized at creation, and should be sized
* so that its height is approximately 60% of its width.
*/
HMODULE wpConfigHandle;
UCHAR loadError[256]; /* Area for name of DLL that we failed on */
Tk_Window parent = Tk_MainWindow(interp);
int oldMode;
char * colorStr = NULL;
char * title = NULL;
int i;
int tclCode;
ULONG ulReply;
ULONG startColor = 0L;
XColor * colorPtr = NULL;
static BOOL inited = FALSE;
static BOOL useOS2Dlg = FALSE;
static HWND hwndDlg = NULLHANDLE, hwndWheel = NULLHANDLE;
HWND hwndOwner;
static ULONG info[QSV_MAX]= {0}; /* System Information Data Buffer */
#ifdef VERBOSE
printf("Tk_ChooseColorCmd\n");
fflush(stdout);
#endif
/*
* 1. Parse the arguments
* We need to do this before creating the dialog, because we don't want
* a dialog thrown up and immediately removed again (or worse: staying)
* because of an error in the arguments.
*/
for (i=1; i<argc; i+=2) {
int v = i+1;
int len = strlen(argv[i]);
#ifdef VERBOSE
printf(" argv[%d] [%s], argv[%d] [%s]\n", i, argv[i], i+1, argv[i+1]);
#endif
if (strncmp(argv[i], "-initialcolor", len)==0) {
if (v==argc) {goto arg_missing;}
colorStr = argv[v];
}
else if (strncmp(argv[i], "-parent", len)==0) {
if (v==argc) {goto arg_missing;}
parent=Tk_NameToWindow(interp, argv[v], Tk_MainWindow(interp));
if (parent == NULL) {
return TCL_ERROR;
}
}
else if (strncmp(argv[i], "-title", len)==0) {
if (v==argc) {goto arg_missing;}
title = argv[v];
}
else {
#ifdef VERBOSE
printf(" unknown option \"%s\", must be -initialcolor, -parent or -title", argv[i]);
#endif
Tcl_AppendResult(interp, "unknown option \"",
argv[i], "\", must be -initialcolor, -parent or -title",
NULL);
return TCL_ERROR;
}
}
if (Tk_WindowId(parent) == None) {
Tk_MakeWindowExist(parent);
}
hwndOwner = Tk_GetHWND(Tk_WindowId(parent));
#ifdef VERBOSE
printf(" hwndOwner now %x\n", hwndOwner);
fflush(stdout);
#endif
if (!inited) {
inited = TRUE;
/* Load DLL to get access to it */
if (DosLoadModule((PSZ)loadError, sizeof(loadError), "WPCONFIG.DLL",
&wpConfigHandle) != NO_ERROR) {
#ifdef VERBOSE
printf("DosLoadModule WPCONFIG.DLL ERROR on %s\n", loadError);
fflush(stdout);
#endif
goto fallback;
}
#ifdef VERBOSE
printf("DosLoadModule WPCONFIG.DLL returned %x\n", wpConfigHandle);
fflush(stdout);
#endif
/* Get address of color selection window procedure */
rc = DosQueryProcAddr(wpConfigHandle, 0, "ColorSelectWndProc",
&colorSelectWndProcPtr);
if (rc != NO_ERROR) {
#ifdef VERBOSE
printf("DosQueryProcAddr %x ERROR %d\n", wpConfigHandle, rc);
fflush(stdout);
#endif
goto fallback;
}
#ifdef VERBOSE
printf("DosQueryProcAddr %x returned %x\n", wpConfigHandle,
colorSelectWndProcPtr);
printf("calling WinLoadDlg(H_D %x hOwn %x CDP %x hMod %x ID %x\n",
HWND_DESKTOP, hwndOwner, ColorDlgProc, Tk_GetHMODULE(),
ID_COLORDLGTEMPLATE);
fflush(stdout);
#endif
/* Load the dialog around the color wheel from our Tk DLL */
hwndDlg = WinLoadDlg(HWND_DESKTOP, hwndOwner, WinDefDlgProc,
Tk_GetHMODULE(), ID_COLORDLGTEMPLATE, NULL);
if (hwndDlg == NULLHANDLE) {
goto fallback;
}
#ifdef VERBOSE
printf("WinLoadDlg hOwn %x hMod %x returned %x\n", hwndOwner,
Tk_GetHMODULE(), hwndDlg);
fflush(stdout);
#endif
/* Subclass to get our own procedure in */
hwndWheel = WinWindowFromID(hwndDlg, ID_COLORWHEEL);
if (hwndWheel == NULLHANDLE) {
goto fallback;
#ifdef VERBOSE
printf("WinWindowFromID ID_COLORWHEEL (%x) ERROR %x\n",
ID_COLORWHEEL, WinGetLastError(TclOS2GetHAB()));
fflush(stdout);
} else {
printf("WinWindowFromID ID_COLORWHEEL (%x) OK: %x\n", ID_COLORWHEEL,
hwndWheel);
fflush(stdout);
#endif
}
oldDlgProc = WinSubclassWindow(hwndDlg, ColorDlgProc);
if (oldDlgProc == NULL) {
goto fallback;
#ifdef VERBOSE
printf("WinSubclassWindow %x ERROR %x\n", hwndDlg,
WinGetLastError(TclOS2GetHAB()));
fflush(stdout);
} else {
printf("WinSubclassWindow %x OK\n", hwndDlg);
fflush(stdout);
#endif
}
useOS2Dlg = TRUE;
rc= DosQuerySysInfo (1L, QSV_MAX, (PVOID)info, sizeof(info));
} else {
/*
* If we use the native color dialog and don't have to initialise,
* we have to reset the 'dismissed' dialog flag FF_DLGDISMISSED
*/
if (useOS2Dlg) {
USHORT flags = WinQueryWindowUShort(hwndDlg, QWS_FLAGS);
rc = WinSetWindowUShort(hwndDlg, QWS_FLAGS,
flags & ~FF_DLGDISMISSED);
#ifdef VERBOSE
if (rc != TRUE) {
printf("WinSetWindowUShort FF_DLGDISMISSED ERROR %x\n",
WinGetLastError(TclOS2GetHAB()));
} else {
printf("WinSetWindowUShort FF_DLGDISMISSED OK\n");
}
fflush(stdout);
#endif
}
}
/* If no init necessary, go to Tcl code if we don't use the Dlg code */
if (!useOS2Dlg) goto fallback;
if (title != NULL) {
/* Set title of dialog */
rc = WinSetWindowText(hwndDlg, title);
#ifdef VERBOSE
if (rc != TRUE) {
printf("WinSetWindowText [%s] ERROR %x\n", title,
WinGetLastError(TclOS2GetHAB()));
} else {
printf("WinSetWindowText [%s] OK\n", title);
}
fflush(stdout);
#endif
}
if (colorStr != NULL) {
colorPtr = Tk_GetColor(interp, Tk_MainWindow(interp), colorStr);
if (!colorPtr) {
return TCL_ERROR;
}
startColor = RGB((colorPtr->red/0x100), (colorPtr->green/0x100),
(colorPtr->blue/0x100));
/* pre-"choose" the color */
chosenColor = startColor;
} else {
/* undo any previously chosen color */
chosenColor = 0L;
}
/*
* Set to previously chosen color.
* Hack for LX-versions above 2.11
* OS/2 version MAJOR MINOR
* 2.0 20 0
* 2.1 20 10
* 2.11 20 11
* 3.0 20 30
* 4.0 20 40
*/
if (info[QSV_VERSION_MAJOR - 1] == 20 &&
info[QSV_VERSION_MINOR - 1] >= 40) {
/* Warp 4 or higher */
#ifdef VERBOSE
printf("Warp 4 or higher => msg 0x602, startColor 0x%x\n", startColor);
fflush(stdout);
#endif
WinSendMsg(hwndWheel, 0x0602, MPFROMLONG(0x8fff), MPVOID);
WinSendMsg(hwndWheel, 0x0602, MPFROMLONG(startColor), MPVOID);
} else {
/* 2.0 - 3.0 */
#ifdef VERBOSE
printf("OS/2 2.0 - 3.0 => msg 0x1384, startColor 0x%x\n", startColor);
fflush(stdout);
#endif
WinSendMsg(hwndWheel, 0x1384, MPFROMLONG(startColor), MPVOID);
}
/*
* 2. Popup the dialog
*/
oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
ulReply = WinProcessDlg(hwndDlg);
#ifdef VERBOSE
printf("WinProcessDlg hwndDlg %x returned 0x%x (%d)\n", hwndDlg, ulReply,
ulReply);
fflush(stdout);
#endif
(void) Tcl_SetServiceMode(oldMode);
/*
* Clear the interp result since anything may have happened during the
* modal loop.
*/
Tcl_ResetResult(interp);
if (colorPtr) {
Tk_FreeColor(colorPtr);
}
/*
* 3. Process the result of the dialog
*/
switch (ulReply) {
case DID_OK:
case ID_OK: {
/*
* User has selected a color
*/
char result[100];
sprintf(result, "#%02x%02x%02x", GetRValue(chosenColor),
GetGValue(chosenColor), GetBValue(chosenColor));
#ifdef VERBOSE
printf("ulReply ID_OK, returning color %x (%s)\n", chosenColor, result);
fflush(stdout);
#endif
Tcl_AppendResult(interp, result, NULL);
tclCode = TCL_OK;
break;
}
case ID_TKVERSION:
#ifdef VERBOSE
printf("ulReply ID_TKVERSION\n");
fflush(stdout);
#endif
goto fallback;
break;
case DID_CANCEL:
case ID_CANCEL:
#ifdef VERBOSE
printf("ulReply (D)ID_CANCEL\n");
fflush(stdout);
#endif
tclCode = TCL_RETURN;
break;
default:
/*
* User probably pressed Cancel, or an error occurred
*/
#ifdef VERBOSE
printf("ulReply default for 0x%x\n", ulReply);
fflush(stdout);
#endif
tclCode = ProcessError(interp, WinGetLastError(TclOS2GetHAB()),
hwndOwner);
} /* of switch */
return tclCode;
arg_missing:
Tcl_AppendResult(interp, "value for \"", argv[argc-1], "\" missing",
NULL);
return TCL_ERROR;
/* Have a Tcl-code fallback in place: */
fallback:
return EvalArgv(interp, "tkColorDialog", argc, argv);
}
/*
*----------------------------------------------------------------------
*
* ColorDlgProc --
*
* This function is called by OS/2 PM whenever an event occurs on
* a color dialog control created by Tk.
*
* Results:
* Standard OS/2 PM return value.
*
* Side effects:
* May generate events.
*
*----------------------------------------------------------------------
*/
static MRESULT EXPENTRY
ColorDlgProc(hwnd, message, param1, param2)
HWND hwnd;
ULONG message;
MPARAM param1;
MPARAM param2;
{
MRESULT ret;
#ifdef VERBOSE
printf("ColorDlgProc hwnd %x msg %x mp1 %x mp2 %x\n", hwnd, message, param1,
param2);
fflush(stdout);
#endif
if (message == 0x0601 /* Warp 4 */ || message == 0x130C /* older */) {
chosenColor = LONGFROMMP(param1);
#ifdef VERBOSE
printf("Message %x from color dialog, color %x\n", message,chosenColor);
fflush(stdout);
#endif
}
ret = (MRESULT) oldDlgProc(hwnd, message, param1, param2);
#ifdef VERBOSE
printf("oldDlgProc returned 0x%x (%d)\n", ret, ret);
fflush(stdout);
#endif
return ret;
}
/*
*----------------------------------------------------------------------
*
* Tk_GetOpenFileCmd --
*
* This procedure implements the "open file" dialog box for the
* OS/2 platform. See the user documentation for details on what
* it does.
*
* Results:
* See user documentation.
*
* Side effects:
* A dialog window is created the first this procedure is called.
* This window is not destroyed and will be reused the next time
* the application invokes the "tk_getOpenFile" or
* "tk_getSaveFile" command.
*
*----------------------------------------------------------------------
*/
int
Tk_GetOpenFileCmd(clientData, interp, argc, argv)
ClientData clientData; /* Main window associated with interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
/* "Unix look-and-feel"
return EvalArgv(interp, "tkFDialog", argc, argv);
*/
/* OS/2 look-and-feel */
return GetFileName(clientData, interp, argc, argv, OPEN_FILE);
}
/*
*----------------------------------------------------------------------
*
* Tk_GetSaveFileCmd --
*
* Same as Tk_GetOpenFileCmd but opens a "save file" dialog box
* instead
*
* Results:
* Same as Tk_GetOpenFileCmd.
*
* Side effects:
* Same as Tk_GetOpenFileCmd.
*
*----------------------------------------------------------------------
*/
int
Tk_GetSaveFileCmd(clientData, interp, argc, argv)
ClientData clientData; /* Main window associated with interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
/* "Unix look-and-feel"
return EvalArgv(interp, "tkFDialog", argc, argv);
*/
/* OS/2 look-and-feel */
return GetFileName(clientData, interp, argc, argv, SAVE_FILE);
}
/*
*----------------------------------------------------------------------
*
* GetFileName --
*
* Create File Open or File Save Dialog.
*
* Results:
* See user documentation.
*
* Side effects:
* See user documentation.
*
*----------------------------------------------------------------------
*/
static int
GetFileName(clientData, interp, argc, argv, isOpen)
ClientData clientData; /* Main window associated with interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
int isOpen; /* true if we should open a file,
* false if we should save a file */
{
FILEDLG fileDlg;
int tclCode, oldMode;
ULONG length = MAX_PATH+1;
ULONG curDrive, logical;
char buffer[MAX_PATH+1];
HWND hwndParent, hwndDlg;
ERRORID errorId = NO_ERROR;
FileFilterList flist;
#ifdef VERBOSE
printf("GetFileName\n");
fflush(stdout);
#endif
TkInitFileFilters(&flist);
/*
* 1. Parse the arguments.
*/
if (ParseFileDlgArgs(interp, &fileDlg, argc, argv, isOpen, &hwndParent,
&flist) != TCL_OK) {
TkFreeFileFilters(&flist);
return TCL_ERROR;
}
#ifdef VERBOSE
for (tclCode = 0; tclCode < flist.numFilters; tclCode++) {
printf("Type %d [%s]\n", tclCode, *(fileDlg.papszITypeList)[tclCode]);
fflush(stdout);
}
#endif
/*
* 2. Call the common dialog function.
*/
rc = DosQueryCurrentDisk(&curDrive, &logical);
#ifdef VERBOSE
if (rc != NO_ERROR) {
printf("DosQueryCurrentDisk ERROR %d\n", rc);
fflush(stdout);
} else {
printf("DosQueryCurrentDisk OK\n");
fflush(stdout);
}
#endif
rc = DosQueryCurrentDir(0, (PBYTE)&buffer, &length);
#ifdef VERBOSE
if (rc != NO_ERROR) {
printf("DosQueryCurrentDir ERROR %d\n", rc);
fflush(stdout);
} else {
printf("DosQueryCurrentDir OK\n");
fflush(stdout);
}
#endif
oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
hwndDlg = WinFileDlg(HWND_DESKTOP, hwndParent, &fileDlg);
(void) Tcl_SetServiceMode(oldMode);
#ifdef VERBOSE
printf("fileDlg.lReturn %x\n", fileDlg.lReturn);
#endif
if (fileDlg.lReturn == 0) {
errorId = WinGetLastError(TclOS2GetHAB());
}
TkFreeFileFilters(&flist);
rc = DosSetDefaultDisk(curDrive);
rc = DosSetCurrentDir(buffer);
/*
* Clear the interp result since anything may have happened during the
* modal loop.
*/
Tcl_ResetResult(interp);
if (fileDlg.papszITypeList) {
ckfree((char*)fileDlg.papszITypeList);
}
if (fileDlg.papszIDriveList) {
ckfree((char*)fileDlg.papszIDriveList);
}
/*
* 3. Process the results.
*/
if (hwndDlg && (fileDlg.lReturn == DID_OK)) {
char *p;
Tcl_ResetResult(interp);
for (p = fileDlg.szFullFile; p && *p; p++) {
/*
* Change the pathname to the Tcl "normalized" pathname, where
* back slashes are used instead of forward slashes
*/
if (*p == '\\') {
*p = '/';
}
}
Tcl_AppendResult(interp, fileDlg.szFullFile, NULL);
tclCode = TCL_OK;
} else {
if (fileDlg.lReturn == DID_CANCEL) {
/* User hit Cancel */
tclCode = TCL_OK;
} else {
tclCode = ProcessError(interp, errorId, hwndParent);
}
}
return tclCode;
}
/*
*----------------------------------------------------------------------
*
* ParseFileDlgArgs --
*
* Parses the arguments passed to tk_getOpenFile and tk_getSaveFile.
*
* Results:
* A standard TCL return value.
*
* Side effects:
* The FILEDLG structure is initialized and modified according
* to the arguments.
*
*----------------------------------------------------------------------
*/
static int
ParseFileDlgArgs(interp, fdlgPtr, argc, argv, isOpen, hwndParent, flistPtr)
Tcl_Interp * interp; /* Current interpreter. */
FILEDLG *fdlgPtr; /* Info about the file dialog */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
int isOpen; /* true if we should call GetOpenFileName(),
* false if we should call GetSaveFileName() */
HWND *hwndParent; /* Parent for dialog (output) */
FileFilterList *flistPtr; /* Filters to be used */
{
int i;
Tk_Window parent = Tk_MainWindow(interp);
int doneFilter = 0;
BOOL hadInitialFile = FALSE;
Tcl_DString buffer;
#ifdef VERBOSE
printf("ParseFileDlgArgs\n");
fflush(stdout);
#endif
/* Fill in the FILEDLG structure */
memset(fdlgPtr, 0, sizeof(FILEDLG));
fdlgPtr->cbSize = sizeof(FILEDLG);
if (isOpen) {
fdlgPtr->fl = FDS_OPEN_DIALOG | FDS_CENTER | FDS_ENABLEFILELB |
FDS_FILTERUNION | FDS_PRELOAD_VOLINFO;
} else {
fdlgPtr->fl = FDS_SAVEAS_DIALOG | FDS_CENTER | FDS_ENABLEFILELB |
FDS_FILTERUNION | FDS_PRELOAD_VOLINFO;
}
#ifdef 0
fdlgPtr->pszTitle = (PSZ)NULL; /* filled in below */
fdlgPtr->pszOKButton = (PSZ)NULL; /* use default text */
fdlgPtr->pfnDlgProc = (PFNWP)NULL; /* No subclassing */
fdlgPtr->pszIType = (PSZ)NULL; /* no EA filter */
fdlgPtr->papszITypeList = (PAPSZ)NULL; /* no EA filter table */
fdlgPtr->pszIDrive = (PSZ)NULL; /* no initial drive */
fdlgPtr->papszIDriveList = (PAPSZ)NULL; /* no drive table */
fdlgPtr->hMod = NULLHANDLE; /* no custom dlg module */
fdlgPtr->szFullFile[0] = '\0';
fdlgPtr->papszFQFilename = (PAPSZ)NULL; /* No multiple selection */
fdlgPtr->ulFQFCount = 1; /* Single file selection */
/* PM Guide and Reference says 'usDlgID', but EMX defines 'usDlgId' */
fdlgPtr->usDlgId = 0; /* No custom Dialog ID */
fdlgPtr->x = 0; /* Initial X (overridden) */
fdlgPtr->y = 0; /* Initial Y (overridden) */
fdlgPtr->sEAType = 0; /* no selected EA */
#endif
/* We have to check these ourselves in OS/2 */
/*
if (isOpen) {
fdlgPtr->Flags |= OFN_FILEMUSTEXIST;
} else {
fdlgPtr->Flags |= OFN_OVERWRITEPROMPT;
}
*/
for (i=1; i<argc; i+=2) {
int v = i+1;
int len = strlen(argv[i]);
char *defExt = "";
#ifdef VERBOSE
printf("Arg %d [%s] %d [%s]\n", i, argv[i], v, argv[v]);
fflush(stdout);
#endif
if (strncmp(argv[i], "-defaultextension", len)==0) {
if (v==argc) {goto arg_missing;}
/*
fdlgPtr->lpstrDefExt = argv[v];
strcpy(fdlgPtr->szFullFile, argv[v]);
sprintf(fdlgPtr->szFullFile, "*%s", argv[v]);
*/
#ifdef VERBOSE
printf("defaultextension %s\n", argv[v]);
fflush(stdout);
#endif
if (hadInitialFile) {
/* Add default extension if necessary */
if (strchr(fdlgPtr->szFullFile, '.') == NULL) {
/* No extension given */
#ifdef VERBOSE
printf("initialfile %s, strcat %s\n", fdlgPtr->szFullFile,
argv[v]);
fflush(stdout);
#endif
strcat(fdlgPtr->szFullFile, argv[v]);
}
} else {
/* Remember for if we get an initialfile argument */
defExt = argv[v];
}
}
else if (strncmp(argv[i], "-filetypes", len)==0) {
if (v==argc) {goto arg_missing;}
if (MakeFilter(interp, fdlgPtr, argv[v], flistPtr) != TCL_OK) {
return TCL_ERROR;
}
doneFilter = 1;
}
else if (strncmp(argv[i], "-initialdir", len)==0) {
ULONG diskNum;
if (v==argc) {goto arg_missing;}
if (Tcl_TranslateFileName(interp, argv[v], &buffer) == NULL) {
return TCL_ERROR;
}
/*
fdlgPtr->lpstrInitialDir = argv[v];
*/
diskNum = (ULONG) Tcl_DStringValue(&buffer)[0] - 'A' + 1;
if (argv[v][0] >= 'a') {
diskNum -= ('a' - 'A');
}
rc = DosSetDefaultDisk(diskNum);
#ifdef VERBOSE
if (rc != NO_ERROR) {
printf("DosSetDefaultDisk %c (%d) ERROR %d\n", argv[v][0],
diskNum, rc);
fflush(stdout);
} else {
printf("DosSetDefaultDisk %c (%d) OK\n", argv[v][0], diskNum);
fflush(stdout);
}
#endif
rc = DosSetCurrentDir(Tcl_DStringValue(&buffer) + 2);
#ifdef VERBOSE
if (rc != NO_ERROR) {
printf("DosSetCurrentDir %s ERROR %d\n",
Tcl_DStringValue(&buffer)+2, rc);
fflush(stdout);
} else {
printf("DosSetCurrentDir %s OK\n", Tcl_DStringValue(&buffer)+2);
fflush(stdout);
}
#endif
Tcl_DStringFree(&buffer);
}
else if (strncmp(argv[i], "-initialfile", len)==0) {
if (v==argc) {goto arg_missing;}
if (Tcl_TranslateFileName(interp, argv[v], &buffer) == NULL) {
return TCL_ERROR;
}
hadInitialFile = TRUE;
strcpy(fdlgPtr->szFullFile, Tcl_DStringValue(&buffer));
Tcl_DStringFree(&buffer);
if (strchr(fdlgPtr->szFullFile, '.') == NULL) {
/* No extension given */
#ifdef VERBOSE
printf("initialfile %s, strcat %s\n", argv[v], defExt);
fflush(stdout);
#endif
strcat(fdlgPtr->szFullFile, defExt);
}
}
else if (strncmp(argv[i], "-parent", len)==0) {
if (v==argc) {goto arg_missing;}
parent = Tk_NameToWindow(interp, argv[v], Tk_MainWindow(interp));
if (parent == NULL) {
return TCL_ERROR;
}
}
else if (strncmp(argv[i], "-title", len)==0) {
if (v==argc) {goto arg_missing;}
fdlgPtr->pszTitle = argv[v];
}
else {
Tcl_AppendResult(interp, "unknown option \"",
argv[i], "\", must be -defaultextension, ",
"-filetypes, -initialdir, -initialfile, -parent or -title",
NULL);
return TCL_ERROR;
}
}
if (!doneFilter) {
if (MakeFilter(interp, fdlgPtr, "", flistPtr) != TCL_OK) {
return TCL_ERROR;
}
}
if (Tk_WindowId(parent) == None) {
Tk_MakeWindowExist(parent);
}
*hwndParent = Tk_GetHWND(Tk_WindowId(parent));
return TCL_OK;
arg_missing:
Tcl_AppendResult(interp, "value for \"", argv[argc-1], "\" missing",
NULL);
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
* MakeFilter --
*
* Allocate a buffer to store the filters and types in a format
* understood by OS/2
*
* Results:
* A standard TCL return value.
*
* Side effects:
* fdlgPtr->pszIType, papszITypeList, szFullFile are modified.
*
*----------------------------------------------------------------------
*/
static int MakeFilter(interp, fdlgPtr, string, flistPtr)
Tcl_Interp *interp; /* Current interpreter. */
FILEDLG *fdlgPtr; /* Info about the file dialog */
char *string; /* String value of the -filetypes option */
FileFilterList *flistPtr; /* Filters to be used */
{
CHAR *filterStr;
char *p;
FileFilter *filterPtr;
if (TkGetFileFilters(interp, flistPtr, string, 1) != TCL_OK) {
#ifdef VERBOSE
printf("MakeFilter, TkGetFileFilters failed\n");
fflush(stdout);
#endif
return TCL_ERROR;
}
#ifdef VERBOSE
printf("MakeFilter, %d filter(s): %s\n", flistPtr->numFilters, string);
fflush(stdout);
#endif
/*
* Since the full file name only contains CCHMAXPATH characters, we
* don't need (cannot) to allocate more space.
*/
filterStr = (CHAR *) ckalloc(CCHMAXPATH);
if (filterStr == (CHAR *)NULL) {
return TCL_ERROR;
}
if (flistPtr->filters == NULL) {
/*
* Use "All Files" (*.*) as the default filter is none is specified
*/
char *defaultFilter = "*.*";
strcpy(filterStr, defaultFilter);
#ifdef VERBOSE
printf(" default filter %s\n", defaultFilter);
fflush(stdout);
#endif
} else {
/*
* We put the filter types in a table, and format the extension
* into the full filename field.
* BEWARE! Specifying the same extension twice gets you a crash
* in PMCTLS.DLL, so make sure that doesn't happen.
*/
char *sep;
int typeCounter;
filterStr[0] = '\0';
/* Table of extended-attribute types, *END WITH NULL!* */
fdlgPtr->papszITypeList = (PAPSZ) ckalloc(flistPtr->numFilters *
sizeof(PSZ) + 1);
if (fdlgPtr->papszITypeList == (PAPSZ)NULL) {
ckfree((char *)filterStr);
return TCL_ERROR;
}
sep = "";
for (filterPtr = flistPtr->filters, typeCounter=0, p = filterStr;
filterPtr; filterPtr = filterPtr->next, typeCounter++) {
FileFilterClause *clausePtr;
/*
* First, put in the name of the file type
*/
*(fdlgPtr->papszITypeList)[typeCounter] = (PSZ)filterPtr->name;
#ifdef VERBOSE
printf(" adding type %s\n", filterPtr->name);
fflush(stdout);
#endif
/* We format the extensions in the filter pattern field */
for (clausePtr=filterPtr->clauses;clausePtr;
clausePtr=clausePtr->next) {
GlobPattern *globPtr;
for (globPtr=clausePtr->patterns; globPtr;
globPtr=globPtr->next) {
char *sub = strstr(filterStr, globPtr->pattern);
/*
* See if pattern is already in filterStr. Watch out for
* it being there as a substring of another pattern!
* eg. *.c is part of *.cpp
*/
if (sub == NULL ||
(*(sub+strlen(globPtr->pattern)) != ';' &&
*(sub+strlen(globPtr->pattern)) != '\0')) {
/*
if (strncmp(globPtr->pattern, "*.*", 3) !=0 ) {
*/
strcpy(p, sep);
p+= strlen(sep);
strcpy(p, globPtr->pattern);
#ifdef VERBOSE
printf(" adding pattern %s, filterStr %s\n",
globPtr->pattern, filterStr);
fflush(stdout);
#endif
p+= strlen(globPtr->pattern);
sep = ";";
/*
}
*/
}
#ifdef VERBOSE
else {
printf("not re-adding pattern %s\n", globPtr->pattern);
}
#endif
}
}
}
/* End table with NULL! */
*(fdlgPtr->papszITypeList)[typeCounter] = (PSZ)NULL;
/* Don't specify initial type, so extensions can play too */
}
if (strlen(fdlgPtr->szFullFile) == 0) {
strcpy(fdlgPtr->szFullFile, filterStr);
}
ckfree((char *)filterStr);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* Tk_MessageBoxCmd --
*
* This procedure implements the MessageBox window for the
* OS/2 platform. See the user documentation for details on what
* it does.
*
* Results:
* See user documentation.
*
* Side effects:
* None. The MessageBox window will be destroy before this procedure
* returns.
*
*----------------------------------------------------------------------
*/
int
Tk_MessageBoxCmd(clientData, interp, argc, argv)
ClientData clientData; /* Main window associated with interpreter. */
Tcl_Interp *interp; /* Current interpreter. */
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
int flags;
Tk_Window parent = Tk_MainWindow(interp);
HWND hWnd;
char *message = "";
char *title = "";
int icon = MB_INFORMATION;
int type = MB_OK;
int i, j;
char *result;
int code, oldMode;
char *defaultBtn = NULL;
int defaultBtnIdx = -1;
#ifdef VERBOSE
printf("Tk_MessageBoxCmd\n");
#endif
for (i=1; i<argc; i+=2) {
int v = i+1;
int len = strlen(argv[i]);
if (strncmp(argv[i], "-default", len)==0) {
if (v==argc) {goto arg_missing;}
defaultBtn = argv[v];
}
else if (strncmp(argv[i], "-icon", len)==0) {
if (v==argc) {goto arg_missing;}
if (strcmp(argv[v], "error") == 0) {
icon = MB_ERROR;
}
else if (strcmp(argv[v], "info") == 0) {
icon = MB_INFORMATION;
}
else if (strcmp(argv[v], "question") == 0) {
icon = MB_ICONQUESTION;
}
else if (strcmp(argv[v], "warning") == 0) {
icon = MB_WARNING;
}
else {
Tcl_AppendResult(interp, "invalid icon \"", argv[v],
"\", must be error, info, question or warning", NULL);
return TCL_ERROR;
}
}
else if (strncmp(argv[i], "-message", len)==0) {
if (v==argc) {goto arg_missing;}
message = argv[v];
}
else if (strncmp(argv[i], "-parent", len)==0) {
if (v==argc) {goto arg_missing;}
parent=Tk_NameToWindow(interp, argv[v], Tk_MainWindow(interp));
if (parent == NULL) {
return TCL_ERROR;
}
}
else if (strncmp(argv[i], "-title", len)==0) {
if (v==argc) {goto arg_missing;}
title = argv[v];
}
else if (strncmp(argv[i], "-type", len)==0) {
int found = 0;
if (v==argc) {goto arg_missing;}
for (j=0; j<NUM_TYPES; j++) {
if (strcmp(argv[v], msgTypeInfo[j].name) == 0) {
type = msgTypeInfo[j].type;
found = 1;
break;
}
}
if (!found) {
Tcl_AppendResult(interp, "invalid message box type \"",
argv[v], "\", must be abortretryignore, ok, ",
"okcancel, retrycancel, yesno or yesnocancel", NULL);
return TCL_ERROR;
}
}
else {
Tcl_AppendResult(interp, "unknown option \"",
argv[i], "\", must be -default, -icon, ",
"-message, -parent, -title or -type", NULL);
return TCL_ERROR;
}
}
/* Make sure we have a valid hWnd to act as the parent of this message box
*/
if (Tk_WindowId(parent) == None) {
Tk_MakeWindowExist(parent);
}
hWnd = Tk_GetHWND(Tk_WindowId(parent));
if (defaultBtn != NULL) {
for (i=0; i<NUM_TYPES; i++) {
if (type == msgTypeInfo[i].type) {
for (j=0; j<msgTypeInfo[i].numButtons; j++) {
if (strcmp(defaultBtn, msgTypeInfo[i].btnNames[j])==0) {
defaultBtnIdx = j;
break;
}
}
if (defaultBtnIdx < 0) {
Tcl_AppendResult(interp, "invalid default button \"",
defaultBtn, "\"", NULL);
return TCL_ERROR;
}
break;
}
}
switch (defaultBtnIdx) {
case 0: flags = MB_DEFBUTTON1; break;
case 1: flags = MB_DEFBUTTON2; break;
case 2: flags = MB_DEFBUTTON3; break;
/*
case 3: flags = MB_DEFBUTTON4; break;
*/
default: flags = MB_DEFBUTTON1; break;
}
} else {
flags = 0;
}
flags |= icon | type;
oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
#ifdef VERBOSE
printf("WinMessageBox [%s] title [%s], flags %x\n", message, title, flags);
#endif
/* Windows Port uses SYSTEM modal dialog, I use application modal */
code = WinMessageBox(HWND_DESKTOP, hWnd, message, title, 0,
flags|MB_APPLMODAL);
(void) Tcl_SetServiceMode(oldMode);
switch (code) {
case MBID_ABORT: result = "abort"; break;
case MBID_CANCEL: result = "cancel"; break;
case MBID_IGNORE: result = "ignore"; break;
case MBID_NO: result = "no"; break;
case MBID_OK: result = "ok"; break;
case MBID_RETRY: result = "retry"; break;
case MBID_YES: result = "yes"; break;
default: result = "";
}
/*
* When we come to here interp->result may have been changed by some
* background scripts. Call Tcl_SetResult() to make sure that any stuff
* lingering in interp->result will not appear in the result of
* this command.
*/
Tcl_SetResult(interp, result, TCL_STATIC);
return TCL_OK;
arg_missing:
Tcl_AppendResult(interp, "value for \"", argv[argc-1], "\" missing",
NULL);
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
* ProcessError --
*
* This procedure gets called if a OS/2-specific error message
* has occurred during the execution of a common dialog or the
* user has pressed the CANCEL button.
*
* Results:
* If an error has indeed happened, returns a standard TCL result
* that reports the error code in string format. If the user has
* pressed the CANCEL button (lastError == 0), resets
* interp->result to the empty string.
*
* Side effects:
* interp->result is changed.
*
*----------------------------------------------------------------------
*/
static int ProcessError(interp, lastError, hWnd)
Tcl_Interp * interp; /* Current interpreter. */
ERRORID lastError; /* The OS/2 PM-specific error code */
HWND hWnd; /* window in which the error happened*/
{
/*
char *string;
*/
char string[257];
#ifdef VERBOSE
printf("ProcessError\n");
fflush(stdout);
#endif
Tcl_ResetResult(interp);
switch(lastError) {
case 0:
return TCL_OK;
/*
case CDERR_DIALOGFAILURE: string="CDERR_DIALOGFAILURE"; break;
case CDERR_STRUCTSIZE: string="CDERR_STRUCTSIZE"; break;
case CDERR_INITIALIZATION: string="CDERR_INITIALIZATION"; break;
case CDERR_NOTEMPLATE: string="CDERR_NOTEMPLATE"; break;
case CDERR_NOHINSTANCE: string="CDERR_NOHINSTANCE"; break;
case CDERR_LOADSTRFAILURE: string="CDERR_LOADSTRFAILURE"; break;
case CDERR_FINDRESFAILURE: string="CDERR_FINDRESFAILURE"; break;
case CDERR_LOADRESFAILURE: string="CDERR_LOADRESFAILURE"; break;
case CDERR_LOCKRESFAILURE: string="CDERR_LOCKRESFAILURE"; break;
case CDERR_MEMALLOCFAILURE: string="CDERR_MEMALLOCFAILURE"; break;
case CDERR_MEMLOCKFAILURE: string="CDERR_MEMLOCKFAILURE"; break;
case CDERR_NOHOOK: string="CDERR_NOHOOK"; break;
case PDERR_SETUPFAILURE: string="PDERR_SETUPFAILURE"; break;
case PDERR_PARSEFAILURE: string="PDERR_PARSEFAILURE"; break;
case PDERR_RETDEFFAILURE: string="PDERR_RETDEFFAILURE"; break;
case PDERR_LOADDRVFAILURE: string="PDERR_LOADDRVFAILURE"; break;
case PDERR_GETDEVMODEFAIL: string="PDERR_GETDEVMODEFAIL"; break;
case PDERR_INITFAILURE: string="PDERR_INITFAILURE"; break;
case PDERR_NODEVICES: string="PDERR_NODEVICES"; break;
case PDERR_NODEFAULTPRN: string="PDERR_NODEFAULTPRN"; break;
case PDERR_DNDMMISMATCH: string="PDERR_DNDMMISMATCH"; break;
case PDERR_CREATEICFAILURE: string="PDERR_CREATEICFAILURE"; break;
case PDERR_PRINTERNOTFOUND: string="PDERR_PRINTERNOTFOUND"; break;
case CFERR_NOFONTS: string="CFERR_NOFONTS"; break;
case FNERR_SUBCLASSFAILURE: string="FNERR_SUBCLASSFAILURE"; break;
case FNERR_INVALIDFILENAME: string="FNERR_INVALIDFILENAME"; break;
case FNERR_BUFFERTOOSMALL: string="FNERR_BUFFERTOOSMALL"; break;
case PMERR_INVALID_HWND: string="PMERR_INVALID_HWND"; break;
*/
default:
sprintf(string, "unknown error, %lx", (ULONG) lastError);
}
Tcl_AppendResult(interp, "OS/2 internal error: ", string, NULL);
return TCL_ERROR;
}