home *** CD-ROM | disk | FTP | other *** search
- /*
-
-
- DdeWin
-
- Windows Dynamic Data Exchange Client Functions
- Interface to Microsoft's DDEML.DLL
- (DDE Management Library)
-
- by Phil Ford
- ________________________________________________________________________
-
- (C) Copyright 1990-1994 by Autodesk, Inc.
-
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted.
-
- THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
- ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
- MERCHANTABILITY ARE HEREBY DISCLAIMED.
- ________________________________________________________________________
-
-
- */
-
-
- /* See DDE.DOC.
- This is the DDE Client library that interfaces to ddeml.dll.
- This module also manages DDE channels by integer handle to
- allow use by AutoLISP.
- */
-
- #include "options.h"
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <memory.h>
- #include <malloc.h>
-
- #include "winutil.h"
- #include "ddewin.h"
- #include "ddedlg.h"
- #include <shellapi.h>
- #include <stdarg.h>
-
- extern HWND adsw_hwndAcad; /* AutoCAD window handle */
-
-
- #define MSG_TITLE "AutoCAD ADS"
- #define QCONV_WORKING 1 /* Is our code to check for a valid DDE
- channel working */
-
- static DWORD idInst = 0; /* DDE id for DDEML library */
-
- #ifndef EOS
- #define EOS '\0'
- #endif
-
- static char profMain[] = "AutoCAD DDE";
- static char profDdeApp[] = "DDE App";
- static char profDdeTopic[] = "DDE Topic";
- static char profDdePath[] = "DDE Path";
- static char profAdvise[] = "DDE Advise";
- static char profFile[] = "ACAD_ADS.INI";
- static char profSpreadsheet[] = "DDE Spreadsheet";
- static char profRowSpec[] = "DDE RowSpec";
- static char profColSpec[] = "DDE ColSpec";
- static char profRangeSpec[] = "DDE RangeSeparator";
- static char profOpenCmd[] = "DDE OpenCmd";
- static char profDefaultDoc[] = "DDE DefaultDoc";
-
- typedef struct tagAPPSFLAGS {
- unsigned regDbFound : 1; /* This app was found in Windows
- registration database */
- unsigned defTopic : 1; /* default topic has been set based
- on default path--Quatro only */
- } APPSFLAGS;
-
- typedef struct tagAPPS {
- char appName[MAXNAME+1]; /* app name without ext or path */
-
- /* Windows Registration Database names. NOTE: At this time,
- only Excel has been tested. */
- char className[MAXNAME+1];
-
- char defPath[MAXPATH+120]; /* default exe path and command line */
- char defTopic[MAXPATH+1]; /* default topic (path name) */
- int apptype; /* Cell range descriptor type
- "R1C1:R3C20" or "A1..C20" */
- char openCmd[40]; /* DDE command to open a work file.
- E.g., for Excel:
- [OPEN("shaft.xls")] */
- APPSFLAGS flags;
- } APPS;
-
-
- #define NUM_APPS 3
- #define APP_EXCEL 0
- #define APP_123W 1
- #define APP_QPW 2
- APPS ddeApps[NUM_APPS] = {
- { "Excel" , "ExcelWorksheet" , "c:\\excel\\" , "Sheet1" , SSEXCEL,
- "[OPEN(\"%1\")]" },
- { "123w" , "123w" , "c:\\123w\\" , "Untitled" , SSLOTUS },
- { "QPW" , "QuattroProNotebook", "c:\\qpw\\" , "Notebk1.wb1", SSLOTUS,
- "{FileOpen \"%1\"}" },
- /* RegDB "QuattroProNotebook-shell-open-command-g:\qpw\qpw.exe" */
- };
-
-
- ddeDATA DdeData = {0}; /* DDE globals and defaults. */
-
- USHORT ChannelMap[MAPLEN] = {0}; /* bit map of channel
- numbers in use. */
-
- void AppType(int ss_type);
-
- /* Global Function Prototypes for ddewin.c */
- HDDEDATA CALLBACK DdeCB(UINT uType, UINT uFmt, HCONV hconv, HSZ hsz1, HSZ hsz2,
- HDDEDATA hdata, DWORD dwData1, DWORD dwData2);
-
- /* Static Function Prototypes for ddewin.c */
- static PDDE DdeCreateChannel(char *app, char *topic);
- static PDDE DdeCreateLink(char *AppName, char *TopicName,
- HCONV hConv, PDDE *List);
- static PDDE DdeRemoveLink(PDDE pdde, int SendTermFlag, PDDE *List);
- static int DdeAppIndex(char *AppName);
- static int DdeExpandOpenCmd(char *openCmd, char *topic, char *expCmd);
- static int findRegValue(char *key1, char *key2, char *key3, char *key4,
- char *szValue);
-
- int debugPrintf(char *format, ...);
-
-
- /* Initialize the Dde Manager. Pointer to structure
- of DDE global data is returned.
- ProgName is our name, used by other apps to get our
- attention; e.g. "AutoCAD" or "DdeApp".
- "idinst" is 0 if DdeInitialize hasn't been called elsewhere;
- otherwise, it's the value.
- Call DdeQuit() to send TERMINATE msg to apps,
- destroy DDE channel windows, and free all memory.
- */
- ddeDATA *DdeInit(char *ProgName, HANDLE hInst, DWORD idinst)
- {
- int appIdx;
-
- if (ProgName)
- strzcpy(DdeData.progname, ProgName, MAXNAME);
- else
- strcpy(DdeData.progname, profFile);
- strcpy(DdeData.ProfFile, DdeData.progname);
- strcat(DdeData.ProfFile, ".ini");
-
- DdeData.hInst = hInst;
- DdeData.flags.advise = ADVISEFLAG;
-
- /* Take these from the resource file so they can be localized
- to the commands used by the local spreadsheet */
-
- LoadString(hInst, IDS_SS_ROW, DdeData.rowspec, MAXSPEC);
- LoadString(hInst, IDS_SS_COL, DdeData.colspec, MAXSPEC);
- LoadString(hInst, IDS_SS_RANGE, DdeData.rangespec, MAXSPEC);
- LoadString(hInst, IDS_SS_OPEN, DdeData.opencmd, MAXCMD);
- LoadString(hInst, IDS_SS_DOCUMENT, DdeData.worksheet, MAXNAME);
-
- if (_stricmp (DdeData.rowspec, /*MSG0*/"R") == 0 &&
- _stricmp (DdeData.colspec, /*MSG0*/"C") == 0 &&
- _stricmp (DdeData.rangespec, /*MSG0*/":") == 0 &&
- _stricmp (DdeData.opencmd, /*MSG0*/"[OPEN(\"%1\")]") == 0 &&
- _stricmp (DdeData.worksheet, /*MSG0*/"Sheet1") == 0)
- {
- DdeData.spreadsheet = 0; /* Microsoft Excel (english) */
- } else {
- DdeData.spreadsheet = 1; /* Other spreadsheet */
- }
-
-
- /* Find paths and open commands by scanning registration database
- using the ddeApps array. */
- appIdx = DdeFindApps();
-
- /* Get user's DDE choices from INI file */
- if (DdeGetProfile(NULL))
- DdeSetApp(DdeData.app, FALSE);
- else if (appIdx >= 0) {
- strcpy(DdeData.app, ddeApps[appIdx].appName);
- strcpy(DdeData.path, ddeApps[appIdx].defPath);
- DdeSetApp(DdeData.app, TRUE);
- } else
- /* If none, set up defaults for DDE dialog to Excel. */
- DdeSetApp(ddeApps[0].appName, TRUE);
-
- if (idinst == 0) {
- /* Change APPCMD_CLIENTONLY to APPCMD_STANDARD to function as
- client and server. */
- DWORD afCmd = APPCMD_CLIENTONLY;
- if (DdeInitialize(&idInst, (PFNCALLBACK)MakeProcInstance(
- (FARPROC)DdeCB, hInst), afCmd, 0L))
- return NULL;
- DdeData.flags.init = TRUE;
- } else {
- idInst = idinst;
- DdeData.flags.init = FALSE;
- }
- return &DdeData;
- }
-
- /* Program about to quit. Unregister all services, free memory */
-
- void
- DdeQuit(void)
- {
- DdeRemoveAll(TRUE);
- if (DdeData.flags.init && idInst != 0) {
- DdeUninitialize(idInst);
- idInst = 0;
- }
- }
-
- int DdeSendAcadCmd(char *cmd)
- {
- static PDDE pAcadDde = 0;
-
- /* Interrupt AutoCAD to execute our function */
- if (!pAcadDde) {
- HCONV hConv = 0;
- static char AppName[] = "AutoCAD.r13.DDE";
- static char TopicName[] = "system";
-
- pAcadDde = DdeCreateChannel(AppName, TopicName);
- if (pAcadDde) {
- pAcadDde->hAppName =
- DdeCreateStringHandle(idInst, AppName, CP_WINANSI);
- pAcadDde->hTopicName =
- DdeCreateStringHandle(idInst, TopicName, CP_WINANSI);
- if (pAcadDde->hAppName && pAcadDde->hTopicName) {
- hConv = DdeConnect(idInst, pAcadDde->hAppName,
- pAcadDde->hTopicName, (LPVOID)NULL);
- pAcadDde->hConv = hConv;
- }
- }
- /* Msg is received by our DdeMsgInInit function before
- returning to here. */
- if (!hConv) {
- DdeTerminate(pAcadDde, FALSE);
- pAcadDde = 0;
- MessageBox(NULL, "can't talk to acad\n", "???", MB_OK);
- }
- }
- if (pAcadDde) {
- DdeExec(pAcadDde, cmd);
- }
-
- return 0;
- }
-
- #if USE_DDEDLG
-
- /* Set defaults for DDE conversation init dialog. The appexe is
- the command line used to start the app and have it load a
- work file. Set it to NULL to mean search the Windows Registration
- Database for the application path. For the default work
- file, no command line should
- follow the exe name. For work files in the current directory,
- no path is needed for the work file. Eg., the first 2 of
- the following would attempt to start Excel and use the default
- work file, "Sheet1.xls".
-
- "Excel" (Excel directory on PATH)
- "c:\\excel\\excel" (NOT on PATH)
- "c:\\excel\\excel shaft.xls" (xls file in current dir)
- "c:\\excel\\excel c:\\excel\\shaft.xls"
-
- */
-
- void DdeDefaults(char *app, char *topic, char *appexe)
- {
- int setPath = FALSE;
-
- if (appexe != NULL && appexe[0])
- strzcpy(DdeData.path, appexe, sizeof(DdeData.path)-1);
- else
- setPath = TRUE;
- DdeSetApp(app, setPath);
- if (setPath && topic != NULL && topic[0] && DdeData.path[0]) {
- if (!DdeIsDefTopic(topic)) {
- strcat(DdeData.path, " ");
- strcat(DdeData.path, topic);
- }
- }
- if (topic != NULL && topic[0])
- strzcpy(DdeData.topic, topic, sizeof(DdeData.topic)-1);
- }
-
-
-
-
-
- /* Try to link to default application and work file. If fail,
- put up a dialog asking for app and topic name, try to
- start app and link up with DDE. Set forcedlg TRUE to enter
- the dialog immediately without the attempt to find a
- channel */
-
- PDDE DdeDlgStart(HWND hwnd, int forcedlg)
- {
- PDDE pdde;
-
- /* First see if we have a channel already */
- if (!forcedlg) {
- pdde = DdeAppInit(DdeData.app, DdeData.topic, DdeData.path);
- if (pdde != NULL)
- return pdde;
- }
-
- /* Prompt user with dialog */
- for (pdde = NULL; pdde == NULL; ) {
- if (!DdeDialog(hwnd))
- return NULL;
- pdde = DdeAppInit(DdeData.app, DdeData.topic, DdeData.path);
- if (pdde == NULL) {
- char msg[80];
-
- /* App started, channel init failed */
- sprintf(msg, "Unable to open DDE channel to %s|%s",
- DdeData.app, DdeData.topic);
- MsgBox(DdeData.progname, msg);
- }
- }
- return pdde;
- }
- #endif /* USE_DDEDLG */
-
-
-
-
-
- /* Start up an application and have it load a work file. Initialize
- a DDE channel to the app and topic. Returns a pointer to the DDE
- channel object. AppPath is the application name. Set AppExe
- to NULL to search the Windows Registration Database for
- application path.
- E.g:
- pdde = DdeAppInit("Excel", "Sheet1", "c:\\excel\\excel");
- pdde = DdeAppInit("Excel", "Sheet1", NULL);
- */
- PDDE DdeAppInit(char *AppName, char *TopicName, char *AppExe)
- {
- int status, started;
- PDDE pdde = NULL;
- char *commandLine;
-
- /* See if we have a channel already. */
- pdde = DdeChannel(AppName, TopicName);
- if (pdde != NULL)
- return pdde;
-
- /* Set defaults, search Windows Registration DB */
- DdeDefaults(AppName, TopicName, AppExe);
-
- if (!DdeInitSystem(AppName, TopicName)) {
- commandLine = NULL;
- /* App not running yet--start it with the
- command line, AppExe, or default. */
- if (AppExe == NULL || AppExe[0] == EOS) {
- AppExe = DdeData.app;
- if (!DdeIsDefTopic(TopicName))
- /* Not default topic */
- commandLine = TopicName;
- }
- status = StartApp(AppExe, commandLine);
- if (status < 32)
- return NULL;
- started = TRUE;
- } else
- started = FALSE;
-
- pdde = DdeInitiate(AppName, TopicName);
- if (pdde == NULL && started) {
- /* We started app but couldn't link up to topic--give
- user a chance to open topic file. */
- DdeInitSystem(AppName, TopicName);
- return DdeInitiate(AppName, TopicName);
- } else
- return pdde;
- }
-
-
- /* See if the application is running but the work file is
- not loaded. Tell app to open work file or put up message
- box telling user to open work file. NOTE: this is application
- specific. Excel accepts "[OPEN("filename")]" as a command
- string to open a spreadsheet file.
- */
- int DdeInitSystem(char *AppName, char *TopicName)
- {
- PDDE pdde;
- char *openCmd;
- int appIdx;
-
- pdde = DdeInitiate(AppName, "System");
- if (pdde != NULL) {
- char omsg[100];
- appIdx = DdeAppIndex(AppName);
- openCmd = DdeData.opencmd;
- if (! openCmd[0])
- openCmd = ddeApps[appIdx].openCmd;
- if (openCmd[0]) {
- char estr[144];
-
- /* Open topic file with command to Excel, eg:
- [OPEN("%1")] */
- DdeExpandOpenCmd(openCmd, TopicName, estr);
- DdeExec(pdde, estr);
- DdeTerminate(pdde, TRUE);
- } else {
- DdeTerminate(pdde, TRUE);
- sprintf(omsg, "Open the file %.40s in %s\nand then click OK",
- TopicName, AppName);
- MsgBox(MSG_TITLE, omsg);
- }
- return TRUE;
- } else
- return FALSE;
- }
-
-
- /* Check if a channel to app and topic is already open. If not,
- try to start one. Copies app and topic into the defaults
- for the initiate dialog.
- */
- PDDE DdeChannel(char *app, char *topic)
- {
- PDDE pdde;
-
- if ((pdde = DdeFindChnl(app, topic)) != NULL)
- /* Have a channel open already. */
- return pdde;
- return DdeInitiate(app, topic);
- }
-
-
-
- /* Start an application */
-
- int StartApp(char *appname, char *commline)
- {
- char buf[MAXPATH+120];
-
- strcpy(buf, appname);
- if (commline != NULL && commline[0] != 0) {
- strcat(buf, " ");
- strcat(buf, commline);
- }
- return WinExec(buf, SW_SHOWNORMAL);
- }
-
-
-
- /* Initiate a DDE link on application and topic names.
- Sets channel number to be used on subsequent DDE
- functions. 0 return means not enough memory, or other
- window creation problem. When done with this channel,
- call DdeTerminate().
- */
- PDDE DdeInitiate(char *AppName, char *TopicName)
- {
- PDDE pdde;
- char MsgLine[80];
- HCONV hConv;
- HANDLE hInst = DdeData.hInst;
-
- pdde = DdeCreateChannel(AppName, TopicName);
- if (!pdde)
- return 0;
-
- if (AppName != NULL && AppName[0] != EOS) {
- /* Make sure apptype is set, but don't overwrite other
- settings with defaults (FALSE) */
- DdeSetApp(AppName, FALSE);
- pdde->apptype = DdeData.apptype;
- }
- if (!AppName[0] || !TopicName[0])
- pdde->ChannelState.wildcard = TRUE;
-
- pdde->hAppName = DdeCreateStringHandle(idInst, AppName, CP_WINANSI);
- if (pdde->hAppName == 0) {
- strhandle_msg(AppName);
- return NULL;
- }
-
- pdde->hTopicName = DdeCreateStringHandle(idInst, TopicName, CP_WINANSI);
- if (pdde->hTopicName == 0) {
- strhandle_msg(TopicName);
- return NULL;
- }
-
- hConv = DdeConnect(idInst, pdde->hAppName, pdde->hTopicName, (LPVOID)NULL);
- pdde->hConv = hConv;
-
- /* Msg is received by our DdeMsgInInit function before
- returning to here. */
- if (!hConv) {
- if (DdeData.flags.show) {
- strcpy(MsgLine, AppName);
- strcat(MsgLine, " | ");
- strcat(MsgLine, TopicName);
- strcat(MsgLine, " not responding.");
- MsgBox("DDE Initiate", MsgLine);
- }
- DdeTerminate(pdde, FALSE);
- return NULL;
- }
- return pdde;
- }
-
-
- /* Set defaults based on spreadsheet application name. Try
- to find exe path in Windows Registration Database. Returns
- TRUE if app is found in Reg DB. Set pathFlag TRUE if
- you want the default names and paths to be reset.
- */
- int DdeSetApp(char *AppName, int pathFlag)
- {
- int stat = FALSE;
- int appIdx;
- char *className;
-
- if (DdeData.app != AppName)
- strzcpy(DdeData.app, AppName, sizeof(DdeData.app)-1);
- appIdx = DdeAppIndex(AppName);
-
- DdeData.appIdx = appIdx;
- DdeData.apptype = ddeApps[appIdx].apptype;
- AppType(DdeData.apptype);
- if (pathFlag) {
- className = ddeApps[appIdx].className;
- if (!ddeApps[appIdx].flags.regDbFound) {
- if (DdeData.path[strlen(DdeData.path)-1] == '\\')
- strcat(DdeData.path, AppName);
- } else
- strcpy(DdeData.path, ddeApps[appIdx].defPath);
-
- strcpy(DdeData.topic, ddeApps[appIdx].defTopic);
- #ifdef DEBUG
- debugPrintf("DdeSetApp App: %s, Topic %s, Path: %s, Type: %d\r\n.",
- DdeData.app,
- DdeData.topic,
- DdeData.path,
- DdeData.apptype);
- #endif
- }
- return appIdx;
- }
-
- /* Return ddeApps array index of a certain app name */
-
- static int DdeAppIndex(char *AppName)
- {
- int appIdx;
-
- if (!_strnicmp(AppName, "123", 3)) {
- /* Lotus' "123w" */
- appIdx = APP_123W;
- } else if (!_strnicmp(AppName, "qua", 3)) {
- /* Borland's "Quattro Pro" */
- appIdx = APP_QPW;
- } else if (!_strnicmp(AppName, "qpw", 3)) {
- /* Borland's "Quattro Pro" */
- appIdx = APP_QPW;
- } else {
- /* Microsoft's "Excel" */
- appIdx = APP_EXCEL;
- }
- return appIdx;
- }
-
-
- /* Terminate any open DDE channels with remote processes.
- Set SendTermFlag TRUE to actually send a terminate message, FALSE
- to just remove our link in the DDE Manager list.
- */
- int DdeRemoveAll(int SendTermFlag)
- {
- PDDE NextDde;
- PDDE pdde;
- int ItemCnt = 0;
- int ChCnt = 0;
-
- for (pdde = DdeData.ChnlList; pdde != NULL; pdde = NextDde) {
- NextDde = pdde->next;
- ++ChCnt;
- DdeTerminate(pdde, SendTermFlag); /* send terminate if not
- sent already, free remote
- data */
- }
-
- DdeData.CurChnl = NULL;
-
- /*
- * RemoveText(&TopicLst, NULL);
- * RemoveText(&SysItemList, NULL);
- */
- return ChCnt;
- }
-
-
- /* Get the current channel data structure and verify conversation
- still alive */
- PDDE DdeGetCurChnl(void)
- {
- if (DdeData.CurChnl == NULL)
- return NULL;
- #if QCONV_WORKING
- if (!DdeCheckConv(DdeData.CurChnl->hConv))
- return NULL;
- #endif
- return DdeData.CurChnl;
- }
-
-
- /* Is this conversation still alive? */
- int
- DdeCheckConv(HCONV hConv)
- {
- CONVINFO ci;
- WORD wError;
-
- if (hConv == 0)
- return FALSE;
- #if QCONV_WORKING
- if (DdeQueryConvInfo(hConv, QID_SYNC, &ci) == 0) {
- wError = DdeGetLastError(idInst);
- if (wError == DMLERR_NO_CONV_ESTABLISHED) {
- #ifdef CV
- MsgBox(MSG_TITLE, "DDE Conversation closed");
- #endif
- return FALSE;
- } else
- return TRUE;
- }
- #if 0
- /* This wasn't reliable in 2/92 */
- if (ci.wStatus & ST_TERMINATED || !(ci.wStatus & ST_CONNECTED))
- return FALSE;
- #endif
- #endif /* QCONV_WORKING */
- return TRUE;
- }
-
-
- /* Build DDE text data from a linked list of text, where
- NumCol is the number of columns (can be 1). Call FreeFar
- when done with the returned pointer. E.g., in 2 Cols,
- "First Text",
- "Text 2",
- "Text 3",
- "Text 4"
-
- First Text<TAB>Text 2<CR><LF>
- Text 3<TAB>Text 4<CR><LF>
- NULL
- Globals FldSepStr and RecSepStr can be changed before calling
- this, if different separators are desired.
- */
- PHDATA DdeFormatList(PLINK TextList, int NumCol, ULONG *DataLength)
- {
- PLINK Link;
- ULONG DataLen = 0L;
- PHDATA CellDataStr;
- PHDATA ptr;
- int cCol = 1;
- int Extra = 0;
- int EndingTab = FALSE;
- int FsepLen, RsepLen;
-
- if (!TextList)
- return NULL;
- if (NumCol == 0)
- NumCol = 0xffff; /* all cols, no rows
- text<TAB>text<TAB>text<TAB>text */
- FsepLen = strlen(FldSepStr);
- RsepLen = strlen(RecSepStr);
- for (Link = TextList; Link != NULL; Link = Link->next) {
- if (cCol < NumCol) {
- Extra = FsepLen; /* add tab */
- ++cCol;
- }
- else {
- Extra = RsepLen; /* Add CrLf */
- cCol = 1;
- }
- DataLen += (strlen(Link->text) + Extra);
- }
- ++DataLen; /* terminating NULL */
- ptr = CellDataStr = AllocHuge(DataLen, FALSE);
- if (!CellDataStr)
- return NULL;
-
- cCol = 1;
- for (Link = TextList; Link != NULL; Link = Link->next) {
- strcpy(ptr, Link->text);
- ptr += strlen(Link->text);
- if (cCol < NumCol) {
- strcpy(ptr, FldSepStr);
- ptr += FsepLen;
- ++cCol;
- EndingTab = TRUE;
- }
- else {
- cCol = 1;
- strcpy(ptr, RecSepStr);
- ptr += RsepLen;
- EndingTab = FALSE;
- }
- }
- if (EndingTab) /* all cols, no rows: remove trailing TAB. */
- --ptr;
- *ptr++ = 0;
- *DataLength = ptr - CellDataStr;
- return CellDataStr;
- }
-
-
-
- /* Terminate a DDE channel. Inform the remote app, remove
- link from DdeData.ChnlList. Fix globals DdeData.CurChnl and
- DdeData.channel.
- */
- void DdeTerminate(PDDE pdde, int SendTermFlag)
- {
- PDDE Neighbor;
- int stat = 1;
- int channel = 0;
-
- if (!pdde)
- return;
-
- channel = pdde->channel;
- if (pdde->hConv && SendTermFlag) { /* Client cancel */
- if (pdde->ChannelState.advise_on)
- if (pdde->item)
- DdeUnAdvise(pdde, pdde->item, CF_TEXT);
- stat = DdeSendTerm(pdde);
- }
- if (channel > 0 && channel <= MAXCHNL)
- ClearBit(ChannelMap, channel);
-
- Neighbor = DdeRemoveLink(pdde, SendTermFlag, &DdeData.ChnlList);
- if (pdde == DdeData.CurChnl) {
- DdeData.CurChnl = Neighbor;
- if (DdeData.CurChnl)
- DdeData.ChnlNum = DdeData.CurChnl->channel;
- else
- DdeData.ChnlNum = 0;
- }
- }
-
-
- /*
- D D E Transaction Functions
- */
-
- /* Request string data on item. Returns TRUE if data is received.
- Data pointer is pdde->pData. Call DdeFreeData to free it.
- */
- DWORD DdeReqString(PDDE pdde, char *item)
- {
- DWORD stat;
-
- stat = DdeSend(pdde, item, XTYP_REQUEST, 0L, NULL, CF_TEXT, 0);
- return stat;
- }
-
-
- /* Request data on item. Returns TRUE if data is received.
- Data pointer is pdde->pData. Call DdeFreeData to free it.
- */
- DWORD DdeRequest(PDDE pdde, char *item, UINT uFmt, ULONG WaitTime)
- {
- DWORD stat;
-
- stat = DdeSend(pdde, item, XTYP_REQUEST, 0L, NULL, uFmt, WaitTime);
- return stat;
- }
-
-
-
- /* Force string data on server. Returns DDE_FACK if OK.
- */
- DWORD DdePokeString(PDDE pdde, char *item, char *pString)
- {
- return DdePoke(pdde, item, (long)strlen(pString)+1, pString, CF_TEXT);
- }
-
-
-
- /* Force data on server.
- */
- DWORD DdePoke(PDDE pdde, char *item, ULONG DataLen, char *pData, UINT uFmt)
- {
- DWORD stat;
-
- stat = DdeSend(pdde, item, XTYP_POKE, DataLen, pData, uFmt, ACKWAIT);
- return stat;
-
- }
-
-
-
- /* Execute a command in the remote program.
- */
- DWORD DdeExec(PDDE pdde, char *pString)
- {
- DWORD stat;
- ULONG DataLen;
-
- DataLen = strlen(pString) + 1;
- stat = DdeSend(pdde, NULL, XTYP_EXECUTE, DataLen, pString,
- CF_TEXT, ACKWAIT);
- return stat;
- }
-
-
- /* Send the TERMINATE message--all done with channel. hConv
- is NULL in this case only. Returns TERMOK if remote returned
- TERMINATE msg, 0 otherwise.
- */
- DWORD DdeSendTerm(PDDE pdde)
- {
- DWORD stat;
-
- if (!pdde)
- return 0;
- if (pdde->ChannelState.localterm) /* already terminated. */
- return 0;
-
- stat = DdeDisconnect(pdde->hConv);
- pdde->ChannelState.localterm = TRUE;
- pdde->hConv = 0;
- return stat; /* TERMOK = good response. */
- }
-
-
-
- /* Set advise hot link function and AutoCAD command for when hot
- link data comes in.
- DdeSetAdvise(pdde, "R3C4:R13C6", "[(moddrawing 3 20000) ] ", advfunc);
- */
- void DdeSetAdvise(PDDE pdde, char *item, char *command, ADVISEFUNC advfunc)
- {
- if (pdde == NULL)
- return;
- if (item)
- store_string(&pdde->item, item);
- if (command)
- store_string(&pdde->acadadvise, command);
- if (advfunc)
- pdde->AdviseFunc = advfunc;
- }
-
-
- /* Start or stop hot link in current channel, using info from
- DdeSetAdvise.
- */
- void DdeAdviseCur(PDDE pdde, int yes, int linktype)
- {
- if (pdde == NULL)
- if (!(pdde = DdeData.CurChnl))
- return;
- if (yes) {
- if (!pdde->ChannelState.advise_on)
- DdeAdvise(pdde, pdde->item, CF_TEXT, linktype);
- } else
- DdeUnAdvise(pdde, pdde->item, CF_TEXT);
- }
-
-
- /* Set up hot link. Set NoData TRUE if you want only notice of
- data change, not data itself. Set item to NULL to use last
- item used for a POKE message on this channel. The "advcommand"
- is the string to send to AutoCAD when new data comes in, such
- as "[import]".
- */
- DWORD DdeAdvise(PDDE pdde, char *item, UINT uFmt, int linktype)
- {
- DWORD stat;
- int Xtype = XTYP_ADVSTART;
- char *pitem;
-
- if (!DdeData.flags.advise)
- return 0;
- if (item && !item[0])
- item = NULL;
- pitem = (item == NULL ? pdde->item : item);
- if (pitem == NULL)
- return 0;
- if (pdde->AdviseFunc == NULL)
- return 0;
- if (linktype != HOTLINK)
- Xtype |= XTYPF_NODATA;
- stat = DdeSend(pdde, pitem, Xtype, 0, NULL, uFmt, ACKWAIT);
- /* ADS stores the "hot link" function handler */
- if (stat)
- pdde->ChannelState.advise_on = TRUE;
- return stat;
- }
-
-
- /* Remove hot link. Send NULL item to use the one stored in pdde->item
- */
- DWORD DdeUnAdvise(PDDE pdde, char *item, UINT uFmt)
- {
- DWORD stat;
- char *pitem;
-
- if (item && !item[0])
- item = NULL;
- if (uFmt == 0)
- uFmt = CF_TEXT;
- pitem = (item == NULL ? pdde->item : item);
- if (pitem == NULL)
- return 0;
- stat = DdeSend(pdde, pitem, XTYP_ADVSTOP, 0, NULL, uFmt, ACKWAIT);
- if (stat) {
- pdde->ChannelState.advise_on = FALSE;
- #ifdef DEBUG
- debugPrintf("Advise off for %s\r\n", pitem);
- #endif
- }
- return stat;
-
- }
-
-
-
- /*
- Send: Execute (Xtype = XTYP_EXECUTE)
- Poke (Xtype = XTYP_POKE)
- Request (Xtype = XTYP_REQUEST)
- Advise (Xtype = XTYP_ADVREQ)
- Unadvise (Xtype = XTYP_ADVSTOP)
-
- Returns zero on error.
- For "Request", the data will be in pdde->pData, the handle will
- be returned (from which pdde->pData is derived using DdeAccessData).
- */
-
- DWORD DdeSend(PDDE pdde, char *ItemName, int Xtype, ULONG DataLen,
- char *pData, UINT uFmt, ULONG WaitTime)
- {
- HSZ hszItem = (HSZ)0;
- HDDEDATA hData, hReqData;
- DWORD result;
- DWORD len;
- char *pReq;
-
- if (pdde == NULL)
- return 0;
- if (!IsValidPdde(pdde))
- return 0;
- if (uFmt == 0)
- uFmt = CF_TEXT;
- if (Xtype == XTYP_EXECUTE || ItemName == NULL)
- hszItem = (HSZ)0;
- else {
- hszItem = DdeCreateStringHandle(idInst, ItemName, CP_WINANSI);
- if (hszItem == (HSZ)0)
- return 0;
- }
- if (WaitTime == 0)
- WaitTime = DATAWAIT;
-
- #define USE_HDATA 1
- #if USE_HDATA
- if (pData != NULL) {
- hData = DdeCreateDataHandle(idInst, pData, DataLen,
- (DWORD)0, hszItem, uFmt, 0);
- if (hData == 0)
- return 0;
- DataLen = (ULONG)-1;
- } else
- hData = 0;
-
- #endif
- if (pData == NULL)
- DataLen = 0;
-
- /*
- Start transaction with DDEML here
- */
- #if USE_HDATA
- hReqData = DdeClientTransaction((LPBYTE)hData, (UINT)-1L, pdde->hConv,
- hszItem, uFmt, Xtype, WaitTime, (LPDWORD)&result);
- /* DdeFreeDataHandle(hData); done by ddeml */
- #else
- hReqData = DdeClientTransaction(pData, DataLen, pdde->hConv, hszItem,
- uFmt, Xtype, WaitTime, (LPDWORD)&result);
- #endif
- /* Old method DDE constants for low word of result field (not guaranteed
- to work in future versions). The recommended error check now
- is for a non-0 return from DdeClientTransaction.
- DDE_FACK 0x8000
- DDE_FBUSY 0x4000
- DDE_FDEFERUPD 0x4000
- DDE_FACKREQ 0x8000
- DDE_FRELEASE 0x2000
- DDE_FREQUESTED 0x1000
- DDE_FACKRESERVED 0x3ff0
- DDE_FADVRESERVED 0x3fff
- DDE_FDATRESERVED 0x4fff
- DDE_FPOKRESERVED 0xdfff
- DDE_FAPPSTATUS 0x00ff
- DDE_FNOTPROCESSED 0x0000
- */
-
- if (hszItem != (HSZ)0)
- DdeFreeStringHandle(idInst, hszItem);
-
- if (Xtype == XTYP_REQUEST) {
- pdde->DataSize = 0;
- pdde->pData = NULL;
- if (hReqData == (HDDEDATA)0)
- return 0;
- pReq = DdeAccessData(hReqData, &len);
- if (len == 0 || pReq == NULL)
- return 0;
-
- pdde->pData = pReq;
- pdde->DataSize = len;
- pdde->hReqData = hReqData;
- }
- return hReqData;
- }
-
-
-
-
- /*
- DDE Search List Functions
- */
-
- /* Is this channel number a valid DDE channel?
- */
- int IsValidChannel(int Chnl)
- {
- return CheckBit(ChannelMap, Chnl);
- }
-
- /* Is this PDDE a valid DDE channel?
- */
- int IsValidPdde(PDDE pdde)
- {
- PDDE tdde;
-
- for (tdde = DdeData.ChnlList; tdde != NULL; tdde = tdde->next)
- if (tdde == pdde)
- return TRUE;
- return FALSE;
- }
-
-
- /* Find Dde channel object by conversation handle
- */
- PDDE DdeFindConv(HCONV hConv)
- {
- PDDE pdde;
-
- if (!DdeData.ChnlList)
- return NULL;
-
- for (pdde = DdeData.ChnlList; pdde != NULL; pdde = pdde->next) {
- if (pdde->hConv == hConv)
- return pdde;
- }
- return NULL;
- }
-
-
-
-
- /* Find dde channel object by channel number.
- */
- PDDE DdeFindChnlNum(int channel)
- {
- PDDE pdde;
- if (!DdeData.ChnlList)
- return NULL;
-
- for (pdde = DdeData.ChnlList; pdde != NULL; pdde = pdde->next) {
- /* match on channel num, check if still alive */
- if (pdde->channel == channel && IsActiveChnl(pdde))
- return pdde;
- }
- return NULL;
- }
-
-
-
- /* Find Dde channel object by application name, topic name.
- */
- PDDE DdeFindChnl(char * app, char * topic)
- {
- PDDE pdde;
- if (!DdeData.ChnlList)
- return NULL;
-
- for (pdde = DdeData.ChnlList; pdde != NULL; pdde = pdde->next) {
- if (!_stricmp(pdde->app, app) && !_stricmp(pdde->topic, topic) &&
- IsActiveChnl(pdde))
- return pdde;
- }
- return NULL;
- }
-
-
-
- /* Is this DDE object a channel that hasn't been terminated
- by remote or locally
- */
- int IsActiveChnl(PDDE pdde)
- {
- if (pdde->hConv != 0 && !pdde->ChannelState.remoteterm &&
- !pdde->ChannelState.localterm) {
- #if QCONV_WORKING
- if (DdeCheckConv(pdde->hConv))
- return TRUE;
- #else
- return TRUE;
- #endif
- }
- return FALSE;
- }
-
-
-
- /*
-
- End of DDE Interface to Upper levels
-
- */
- /* This function is called by the DDE manager DLL and passes control onto
- the apropriate function pointed to by the global topic and item arrays.
- It handles all DDE interaction generated by external events. */
-
- HDDEDATA CALLBACK
- /*FCN*/DdeCB(UINT uType, UINT uFmt, HCONV hconv, HSZ hsz1, HSZ hsz2,
- HDDEDATA hdata, DWORD dwData1, DWORD dwData2)
- {
- PDDE pdde;
-
- pdde = DdeFindConv(hconv);
- if (pdde == NULL)
- return 0;
-
- switch (uType) {
- case XTYP_DISCONNECT:
- if (pdde->app == NULL)
- break;
- #ifdef SHOWMSG
- sprintf(buf, "%s cancelled DDE conversation", pdde->app);
- MsgBox("AutoCAD DDE", buf);
- #endif
- pdde->ChannelState.remoteterm = TRUE;
- DdeTerminate(pdde, FALSE);
- break;
-
- case XTYP_ADVDATA:
- if (pdde->AdviseFunc != NULL && !pdde->ChannelState.remoteterm)
- (*pdde->AdviseFunc)(pdde);
- break;
-
- default:
- break;
- }
-
- /*
- anything else fails - DDEML is designed so that a 0 return is ALWAYS ok.
- */
- return 0;
- }
-
-
- /* Create a DDE structure and a window for a channel
- (application and topic). Channel number is in pdde->channel
- on return. NULL returned on error.
- */
- static PDDE DdeCreateChannel(char *app, char *topic)
- {
- PDDE pdde;
- int channel;
- char MsgLine[80];
- char NumStr[30];
-
- channel = SetNextBit(ChannelMap, MAPLEN);
- if (channel == BITMAPFULL) {
- strcpy(MsgLine, "Only ");
- _itoa(MAXCHNL, NumStr, 10);
- strcat(MsgLine, NumStr);
- strcat(MsgLine, " DDE channels allowed.");
- MsgBox(DdeData.progname, MsgLine);
- return NULL;
- }
- pdde = DdeCreateLink(app, topic, 0, &DdeData.ChnlList);
- if (!pdde) {
- ClearBit(ChannelMap, channel);
- return NULL;
- }
-
- DdeData.ChnlNum = pdde->channel = channel;
- DdeData.CurChnl = pdde;
- return pdde;
-
- }
-
-
-
-
- /* Create a local Dde structure and add it to the chain
- of Dde structures. If it's a new channel (app and topic),
- set hConv to NULL. If it's data received on an item,
- set AppName and TopicName to NULL, and hConv = the
- HCONV.
- */
- static PDDE DdeCreateLink(char *AppName, char *TopicName,
- HCONV hConv, PDDE *List)
- {
- PDDE pdde;
-
- pdde = (PDDE)AddLink((void **)List, sizeof(DDE));
- if (!pdde)
- return NULL;
- if (AppName)
- pdde->app = _strdup(AppName);
- if (TopicName)
- pdde->topic = _strdup(TopicName);
-
- if (hConv) /* Input data from msg */
- pdde->hConv = hConv;
-
- return pdde;
- }
-
-
-
-
-
- /* Free pointers and remove DDE link from list.
- Waits for DdeSem. Set SendTermFlag
- to free remote data. Returns neighbor link.
- */
- static PDDE DdeRemoveLink(PDDE pdde, int SendTermFlag, PDDE *List)
- {
- PDDE Neighbor;
- int stat = 1;
-
- if (!pdde)
- return NULL;
-
- if (pdde->app)
- free(pdde->app);
- if (pdde->topic)
- free(pdde->topic);
- if (pdde->item)
- free(pdde->item);
- if (pdde->acadadvise)
- free(pdde->acadadvise);
- if (pdde->hAppName)
- DdeFreeStringHandle(idInst, pdde->hAppName);
- if (pdde->hTopicName)
- DdeFreeStringHandle(idInst, pdde->hTopicName);
-
- Neighbor = (PDDE)RemoveLink((void **)List, (PLINK)pdde);
- free(pdde);
-
- return Neighbor;
- }
-
- /* Free the shared data sent to us. Update DDE structure data. */
- void DdeFreeData(PDDE pdde)
- {
- if (pdde == NULL || pdde->hReqData == (HDDEDATA)0)
- return;
- DdeUnaccessData(pdde->hReqData);
- pdde->hReqData = (HDDEDATA)0;
- pdde->pData = NULL;
- pdde->DataSize = 0;
- }
-
-
- void strhandle_msg(char *name)
- {
- char buf[80];
-
- sprintf(buf, "Couldn't create a string handle for %s", name);
- MsgBox(MSG_TITLE, buf);
- }
-
-
-
- #if NEEDED
- /* Switch channels using a 0 based list index, for
- list boxes.
- */
- int SwitchChnlIndex(int ChnlIdx)
- {
- int idx = 0;
- int ChnlNum;
- PDDE pdde1;
-
- for (pdde1 = DdeData.ChnlList; pdde1 != NULL; pdde1 = pdde1->next) {
- if (ChnlIdx == idx) {
- ChnlNum = pdde1->channel;
- break;
- }
- ++idx;
- }
- return DdeSwitchChnl(ChnlNum);
- }
-
- #endif
-
-
- /* Switch DDE channel, return 0 if not valid. */
- int DdeSwitchChnl(int ChnlNum)
- {
- PDDE pdde;
-
- if (!IsValidChannel(ChnlNum))
- return 0;
- pdde = DdeFindChnlNum(ChnlNum);
- if (!pdde)
- return 0;
- DdeData.ChnlNum = ChnlNum;
- DdeData.CurChnl = pdde;
- DdeData.apptype = pdde->apptype;
- return ChnlNum;
- }
-
-
- #if USE_DDEDLG
-
- /*
-
-
- DDE Dialog
-
-
- */
-
-
-
-
- /* QuickCase:W KNB Version 1.00 */
-
- int DdeDialog(HWND hwnd)
- {
- int ok;
- FARPROC lpfnDDEDLGMsgProc;
-
- lpfnDDEDLGMsgProc = MakeProcInstance((FARPROC)DDEDLGMsgProc, DdeData.hInst);
- ok = DialogBox(DdeData.hInst, (LPSTR)"DDEINIT", hwnd, lpfnDDEDLGMsgProc);
-
- /* Set focus back to AutoCAD's graphics window */
- SetFocus(adsw_hwndAcad);
-
- FreeProcInstance(lpfnDDEDLGMsgProc);
- return ok;
- }
-
-
-
- /************************************************************************/
- /* */
- /* Dialog Window Procedure */
- /* */
- /* This procedure is associated with the dialog box that is included in */
- /* the function name of the procedure. It provides the service routines */
- /* for the events (messages) that occur because the end user operates */
- /* one of the dialog box's buttons, entry fields, or controls. */
- /* */
- /************************************************************************/
-
- BOOL FAR PASCAL DDEDLGMsgProc(HWND hWndDlg, UINT Message,
- WPARAM wParam, LPARAM lParam)
- {
- static char app[MAXNAME + 1];
- static char topic[MAXPATH + 1];
- static char path[MAXPATH + 1];
- static short advisestate;
- int chng;
- PDDE pdde;
-
- switch (Message) {
-
- case WM_INITDIALOG:
- /* initialize working variables */
- strcpy(app, DdeData.app);
- strcpy(topic, DdeData.topic);
- strcpy(path, DdeData.path);
- SetDlgItemText(hWndDlg, IDD_DDE_APP, app);
- SetDlgItemText(hWndDlg, IDD_DDE_TOPIC, topic);
- SetDlgItemText(hWndDlg, IDD_DDE_PATH, path);
- SendDlgItemMessage(hWndDlg, IDD_DDE_APP, EM_SETSEL,
- 0, MAKELONG(0, 0x7fff));
- CheckDlgButton(hWndDlg, IDD_ADVISE, DdeData.flags.advise);
- advisestate = DdeData.flags.advise;
- break; /* End of WM_INITDIALOG */
-
- case WM_CLOSE:
- /* Closing the Dialog behaves the same as Cancel */
- PostMessage(hWndDlg, WM_COMMAND, IDCANCEL, 0L);
- break; /* End of WM_CLOSE */
-
- case WM_COMMAND:
- switch (wParam) {
- case IDD_DDE_APP: /* Edit Control */
- /* Indicates changes have occured */
- /* if(HIWORD(lParam) == EN_CHANGE) */
- break;
-
- case IDD_DDE_TOPIC: /* Edit Control */
- break;
-
- case IDD_DDE_PATH: /* Edit Control */
- break;
-
- case IDD_ADVISE: /* Checkbox text: "Automatic Update (warm link)" */
- break;
-
- case IDD_DDE_PARAMS: /* Change Spreadsheet Parameters */
- if (DdeSpreadshDialog(hWndDlg)) {
- SetDlgItemText(hWndDlg, IDD_DDE_TOPIC, DdeData.worksheet);
- }
- break;
-
- case IDOK:
- chng = FALSE;
- GetDlgItemText(hWndDlg, IDD_DDE_APP, app, MAXNAME);
- GetDlgItemText(hWndDlg, IDD_DDE_TOPIC, topic, MAXPATH);
- GetDlgItemText(hWndDlg, IDD_DDE_PATH, path, MAXPATH);
-
- if (_stricmp(DdeData.app, app)) {
- chng = TRUE;
- strcpy(DdeData.app, app);
- }
- if (_stricmp(DdeData.topic, topic)) {
- chng = TRUE;
- strcpy(DdeData.topic, topic);
- }
- if (_stricmp(DdeData.path, path)) {
- chng = TRUE;
- strcpy(DdeData.path, path);
- }
- advisestate = IsDlgButtonChecked(hWndDlg, IDD_ADVISE);
- if (advisestate != (short)DdeData.flags.advise) {
- chng = TRUE;
- DdeData.flags.advise = advisestate;
- pdde = DdeFindChnl(DdeData.app, DdeData.topic);
- if (pdde != NULL)
- DdeAdviseCur(pdde, advisestate, WARMLINK);
- }
- if (chng && DdeData.ProfFile != NULL)
- DdeWriteProfile(DdeData.ProfFile);
- EndDialog(hWndDlg, TRUE);
- break;
-
- case IDCANCEL:
- /* Ignore data values entered into the controls */
- /* and dismiss the dialog window returning FALSE */
- EndDialog(hWndDlg, FALSE);
- break;
- }
- break; /* End of WM_COMMAND */
-
- default:
- return FALSE;
- }
- return TRUE;
- } /* End of DDEDLGMsgProc */
-
- int
- DdeSpreadshDialog(HWND hwnd)
- {
- int ok;
- FARPROC lpfnDDESPREADSHDLGMsgProc;
-
- lpfnDDESPREADSHDLGMsgProc = MakeProcInstance((FARPROC)
- DDESPREADSHDLGMsgProc,
- DdeData.hInst);
- ok = DialogBox(DdeData.hInst, (LPSTR) "DDESPREADSH", hwnd,
- lpfnDDESPREADSHDLGMsgProc);
- FreeProcInstance(lpfnDDESPREADSHDLGMsgProc);
- return ok;
- }
-
- BOOL FAR PASCAL
- DDESPREADSHDLGMsgProc(HWND hWndDlg, UINT Message, WPARAM wParam,
- LPARAM lParam)
- {
- static int spreadsheet;
- static char rowspec[MAXSPEC + 1];
- static char colspec[MAXSPEC + 1];
- static char rangespec[MAXSPEC + 1];
- static char opencmd[MAXCMD + 1];
- static char worksheet[MAXNAME + 1];
- int chng;
-
- switch (Message) {
- case WM_INITDIALOG:
- strcpy(rowspec, DdeData.rowspec);
- strcpy(colspec, DdeData.colspec);
- strcpy(rangespec, DdeData.rangespec);
- strcpy(opencmd, DdeData.opencmd);
- strcpy(worksheet, DdeData.worksheet);
-
- SetDlgItemText(hWndDlg, IDD_SS_ROW, rowspec);
- SetDlgItemText(hWndDlg, IDD_SS_COL, colspec);
- SetDlgItemText(hWndDlg, IDD_SS_RANGE, rangespec);
- SetDlgItemText(hWndDlg, IDD_SS_OPEN, opencmd);
- SetDlgItemText(hWndDlg, IDD_SS_DOCUMENT, worksheet);
-
- spreadsheet = DdeData.spreadsheet;
-
- CheckRadioButton(hWndDlg, IDD_SS_EXCEL, IDD_SS_OTHER,
- spreadsheet + IDD_SS_EXCEL);
- PostMessage(hWndDlg, WM_COMMAND, spreadsheet + IDD_SS_EXCEL, 0L);
-
- break; /* End of WM_INITDIALOG */
-
- case WM_CLOSE:
- /* Closing the Dialog behaves the same as Cancel */
- PostMessage(hWndDlg, WM_COMMAND, IDCANCEL, 0L);
- break; /* End of WM_CLOSE */
-
- case WM_COMMAND:
- switch (wParam) {
- case IDD_SS_EXCEL:
- spreadsheet = wParam - IDD_SS_EXCEL;
-
- SetDlgItemText(hWndDlg, IDD_SS_ROW, /*MSG0*/"R");
- SetDlgItemText(hWndDlg, IDD_SS_COL, /*MSG0*/"C");
- SetDlgItemText(hWndDlg, IDD_SS_RANGE, /*MSG0*/":");
- SetDlgItemText(hWndDlg, IDD_SS_OPEN, /*MSG0*/"[OPEN(\"%1\")]");
- SetDlgItemText(hWndDlg, IDD_SS_DOCUMENT, /*MSG0*/"Sheet1");
-
- EnableWindow(GetDlgItem(hWndDlg, IDD_SS_ROW), FALSE);
- EnableWindow(GetDlgItem(hWndDlg, IDD_SS_COL), FALSE);
- EnableWindow(GetDlgItem(hWndDlg, IDD_SS_RANGE), FALSE);
- EnableWindow(GetDlgItem(hWndDlg, IDD_SS_OPEN), FALSE);
- EnableWindow(GetDlgItem(hWndDlg, IDD_SS_DOCUMENT), FALSE);
- break;
-
- case IDD_SS_OTHER:
- spreadsheet = wParam - IDD_SS_EXCEL;
-
- EnableWindow(GetDlgItem(hWndDlg, IDD_SS_ROW), TRUE);
- EnableWindow(GetDlgItem(hWndDlg, IDD_SS_COL), TRUE);
- EnableWindow(GetDlgItem(hWndDlg, IDD_SS_RANGE), TRUE);
- EnableWindow(GetDlgItem(hWndDlg, IDD_SS_OPEN), TRUE);
- EnableWindow(GetDlgItem(hWndDlg, IDD_SS_DOCUMENT), TRUE);
- break;
-
- case IDOK:
- GetDlgItemText(hWndDlg, IDD_SS_ROW, rowspec, MAXSPEC);
- GetDlgItemText(hWndDlg, IDD_SS_COL, colspec, MAXSPEC);
- GetDlgItemText(hWndDlg, IDD_SS_RANGE, rangespec, MAXSPEC);
- GetDlgItemText(hWndDlg, IDD_SS_OPEN, opencmd, MAXCMD);
- GetDlgItemText(hWndDlg, IDD_SS_DOCUMENT, worksheet, MAXNAME);
-
- chng = FALSE;
-
- if (spreadsheet != DdeData.spreadsheet) {
- chng = TRUE;
- DdeData.spreadsheet = spreadsheet;
- }
- if (_stricmp(DdeData.rowspec, rowspec)) {
- chng = TRUE;
- strcpy(DdeData.rowspec, rowspec);
- }
- if (_stricmp(DdeData.colspec, colspec)) {
- chng = TRUE;
- strcpy(DdeData.colspec, colspec);
- }
- if (_stricmp(DdeData.rangespec, rangespec)) {
- chng = TRUE;
- strcpy(DdeData.rangespec, rangespec);
- }
- if (_stricmp(DdeData.opencmd, opencmd)) {
- chng = TRUE;
- strcpy(DdeData.opencmd, opencmd);
- }
- if (_stricmp(DdeData.worksheet, worksheet)) {
- chng = TRUE;
- strcpy(DdeData.worksheet, worksheet);
- }
- if (chng && DdeData.ProfFile != NULL) {
- DdeWriteProfile(DdeData.ProfFile);
- }
- EndDialog(hWndDlg, TRUE);
- break;
-
- case IDCANCEL:
- /* Ignore data values entered into the controls */
- /* and dismiss the dialog window returning FALSE */
- EndDialog(hWndDlg, FALSE);
- break;
- }
- break; /* End of WM_COMMAND */
-
- default:
- return FALSE;
- }
- return TRUE;
- } /* End of DDESPREADSHDLGMsgProc */
-
- #endif /* USE_DDEDLG */
-
-
-
- /* Save and restore user options from INI file */
-
- void DdeWriteProfile(char *profFile)
- {
- char *str;
-
- if (profFile == NULL)
- profFile = DdeData.ProfFile;
-
- WritePrivateProfileString(profMain,
- profDdeApp, DdeData.app, profFile);
- WritePrivateProfileString(profMain,
- profDdeTopic, DdeData.topic, profFile);
- WritePrivateProfileString(profMain,
- profDdePath, DdeData.path, profFile);
- str = (DdeData.flags.advise ? "1" : "0");
- WritePrivateProfileString(profMain,
- profAdvise, str, profFile);
- str = (DdeData.spreadsheet == 0) ? "0" : "1";
- WritePrivateProfileString(profMain,
- profSpreadsheet, str, profFile);
- WritePrivateProfileString(profMain,
- profRowSpec, DdeData.rowspec, profFile);
- WritePrivateProfileString(profMain,
- profColSpec, DdeData.colspec, profFile);
- WritePrivateProfileString(profMain,
- profRangeSpec, DdeData.rangespec, profFile);
- WritePrivateProfileString(profMain,
- profOpenCmd, DdeData.opencmd, profFile);
- WritePrivateProfileString(profMain,
- profDefaultDoc, DdeData.worksheet, profFile);
- }
-
- /* Get user options from INI file */
-
- int DdeGetProfile(char *profFile)
- {
- BOOL status;
-
- if (profFile == NULL)
- profFile = DdeData.ProfFile;
-
- status = GetPrivateProfileString(profMain, profDdeApp, DdeData.app,
- DdeData.app, MAXNAME, profFile);
- GetPrivateProfileString(profMain, profDdeTopic, DdeData.topic,
- DdeData.topic, MAXPATH, profFile);
- GetPrivateProfileString(profMain, profDdePath, DdeData.path,
- DdeData.path, MAXPATH, profFile);
- DdeData.flags.advise = GetPrivateProfileInt(
- profMain, profAdvise, 1, profFile);
- DdeData.spreadsheet = GetPrivateProfileInt(profMain,
- profSpreadsheet, DdeData.spreadsheet, profFile);
- GetPrivateProfileString(profMain, profRowSpec, DdeData.rowspec,
- DdeData.rowspec, MAXSPEC, profFile);
- GetPrivateProfileString(profMain, profColSpec, DdeData.colspec,
- DdeData.colspec, MAXSPEC, profFile);
- GetPrivateProfileString(profMain, profRangeSpec, DdeData.rangespec,
- DdeData.rangespec, MAXSPEC, profFile);
- GetPrivateProfileString(profMain, profOpenCmd, DdeData.opencmd,
- DdeData.opencmd, MAXCMD, profFile);
- GetPrivateProfileString(profMain, profDefaultDoc, DdeData.worksheet,
- DdeData.worksheet, MAXNAME, profFile);
-
- return status;
- }
-
-
- /* Search Registration Database for any of the known spreadsheet
- apps. Set in ddeApps array: defPath, openCmd, and flags.regDbFound.
- Return app index. */
- int DdeFindApps(void)
- {
- int idx, idxFound = -1;
-
- for (idx = 0; idx < NUM_APPS; ++idx) {
- if (DdeFindApp(ddeApps[idx].className, ddeApps[idx].defPath)) {
- if (idx == APP_QPW) {
- /* For Quattro Pro, change notebk1.wb1 to
- something like f:\qpw\notebk1.wb1. */
- char *saveTopic;
- char path[MAXPATH];
- char fname[13];
-
- if (!ddeApps[idx].flags.defTopic) {
- saveTopic = _strdup(ddeApps[idx].defTopic);
- getpath(ddeApps[idx].defPath, path, fname);
- strcpy(ddeApps[idx].defTopic, path);
- strcat(ddeApps[idx].defTopic, "\\");
- strcat(ddeApps[idx].defTopic, saveTopic);
- free(saveTopic);
- ddeApps[idx].flags.defTopic = TRUE;
- }
- }
- DdeFindOpenCmd(ddeApps[idx].className, ddeApps[idx].openCmd);
- ddeApps[idx].flags.regDbFound = TRUE;
- idxFound = idx;
- }
- }
- return idxFound;
- }
-
-
-
- /* Find path of app (classname) from Windows Registration
- Database. E.g., "ExcelWorksheet" might return (in exePath)
- "d:\excel\excel.exe".
- */
- int DdeFindApp(char *classname, char *exePath)
- {
- int stat;
- WORD estat = 0;
-
-
- stat = findRegValue(classname, "protocol",
- "StdFileEditing", "server", exePath);
- if (!stat) {
- /* RegDB "QuattroProNotebook-shell-open-command = g:\qpw\qpw.exe" */
- stat = findRegValue(classname, "shell",
- "open", "command", exePath);
- if (!stat)
- return FALSE;
- }
- #ifdef DEBUG
- debugPrintf("DdeFindApp: ok %s %s\r\n", exePath, openCmd);
- #endif
- return TRUE;
- }
-
-
- /* Find the open command for a classname
- */
- int DdeFindOpenCmd(char *classname, char *openCmd)
- {
- /* RegDB "QuattroProNotebook-shell-open-ddeexec = [open("%1")]" */
- return findRegValue(classname, "shell", "open", "ddeexec", openCmd);
- }
-
-
- /* Expand open command such as [open("%1")] into [open("shaft.xls")]
- */
- static int DdeExpandOpenCmd(char *openCmd, char *topic, char *expCmd)
- {
- int idx, foundIt = FALSE;
-
- for (idx = 0; openCmd[idx] != 0; ++idx) {
- if (openCmd[idx] == '%' && openCmd[idx+1] == '1') {
- foundIt = TRUE;
- break;
- } else
- expCmd[idx] = openCmd[idx];
- }
- if (!foundIt)
- return FALSE;
- strcpy(&expCmd[idx], topic);
- strcat(expCmd, &openCmd[idx+2]);
- return TRUE;
- }
-
- /* Is a topic the default topic for this application
- */
- int DdeIsDefTopic(char *topic)
- {
- return _stricmp(topic, ddeApps[DdeData.appIdx].defTopic) == 0;
- }
-
- /* Find an exe path from several levels of keys in the Windows
- Registration Database. */
-
- static int findRegValue(char *key1, char *key2, char *key3, char *key4,
- char *szValue)
- {
- HKEY hKey;
- char *lastkey;
- char szSubKey[120];
- LONG cb;
- int stat = FALSE;
-
- strcpy(szSubKey, key1);
- lastkey = key2;
- if (key2) {
- strcat(szSubKey, "\\");
- strcat(szSubKey, key2);
- lastkey = key3;
- if (key3) {
- strcat(szSubKey, "\\");
- strcat(szSubKey, key3);
- lastkey = key4;
- }
- }
-
- if (RegOpenKey(HKEY_CLASSES_ROOT, szSubKey, &hKey) == ERROR_SUCCESS) {
- cb = MAXPATH;
- if (RegQueryValue(hKey, lastkey, szValue, &cb) == ERROR_SUCCESS)
- stat = TRUE;
- RegCloseKey(hKey);
- }
- return stat;
- }
-
-
- #ifdef DEBUG
-
- #if !defined(__TURBOC__) && !defined(HCWIN)
- /* Windows version of printf for output debug terminal or window
- (see Windows SDK, DBWIN.EXE). */
- int debugPrintf(char *format, ...)
- {
- va_list va;
- int stat;
- char buf[1024];
-
- va_start(va, format);
- vsprintf(buf, format, va);
- va_end(va);
-
- /* Output to DBWIN program (from Windows SDK). */
- OutputDebugString(buf);
- return 1;
- }
- #endif
- #endif
-
- /* end of file */
-
-