Annotation of mstools/samples/ddeml/client/ddemlcl.c, revision 1.1

1.1     ! root        1: /***************************************************************************
        !             2:  *                                                                         *
        !             3:  *  PROGRAM     : client.c                                                 *
        !             4:  *                                                                         *
        !             5:  *  PURPOSE     : To demonstrate how to use the DDEML library from the     *
        !             6:  *                client side and for basic testing of the DDEML API.      *
        !             7:  *                                                                         *
        !             8:  ***************************************************************************/
        !             9: 
        !            10: #include "client.h"
        !            11: #include <string.h>
        !            12: #include <memory.h>
        !            13: #include "infoctrl.h"
        !            14: 
        !            15: /* global variables used in this module or among more than one module */
        !            16: CONVCONTEXT CCFilter = { sizeof(CONVCONTEXT), 0, 0, 0, 0L, 0L };
        !            17: DWORD idInst = 0;
        !            18: HANDLE hInst;                       /* Program instance handle               */
        !            19: HANDLE hAccel;                      /* Main accelerator resource             */
        !            20: HWND hwndFrame           = NULL;    /* Handle to main window                 */
        !            21: HWND hwndMDIClient       = NULL;    /* Handle to MDI client                  */
        !            22: HWND hwndActive          = NULL;    /* Handle to currently activated child   */
        !            23: LONG DefTimeout      = DEFTIMEOUT;  /* default synchronous transaction timeout */
        !            24: DWORD wDelay = 0;
        !            25: BOOL fBlockNextCB = FALSE;     /* set if next callback causes a CBR_BLOCK    */
        !            26: BOOL fTermNextCB = FALSE;      /* set to call DdeDisconnect() on next callback */
        !            27: BOOL fAutoReconnect = FALSE;   /* set if DdeReconnect() is to be called on XTYP_DISCONNECT callbacks */
        !            28: HDDEDATA hDataOwned = NULL;    /* Current owned huge data handle             */
        !            29: DWORD fmtLink = 0;                   /* link clipboard format number          */
        !            30: DWORD DefOptions = 0;                /* default transaction optons            */
        !            31: OWNED aOwned[MAX_OWNED];            /* list of all owned handles.            */
        !            32: DWORD cOwned = 0;                    /* number of existing owned handles.     */
        !            33: FARPROC lpMsgFilterProc;            /* instance proc from MSGF_DDEMGR filter */
        !            34: 
        !            35: /*
        !            36:  * This is the array of formats we support
        !            37:  */
        !            38: FORMATINFO aFormats[] = {
        !            39:     { CF_TEXT, "CF_TEXT" },       // exception!  predefined format
        !            40:     { 0, "Dummy1"  },
        !            41:     { 0, "Dummy2"  },
        !            42: };
        !            43: 
        !            44: /* Forward declarations of helper functions in this module */
        !            45: VOID NEAR PASCAL CloseAllChildren(VOID);
        !            46: VOID NEAR PASCAL InitializeMenu (HANDLE);
        !            47: VOID NEAR PASCAL CommandHandler (HWND,DWORD);
        !            48: VOID NEAR PASCAL SetWrap (HWND,BOOL);
        !            49: 
        !            50: /****************************************************************************
        !            51:  *                                                                          *
        !            52:  *  FUNCTION   : WinMain(HANDLE, HANDLE, LPSTR, int)                        *
        !            53:  *                                                                          *
        !            54:  *  PURPOSE    : Creates the "frame" window, does some initialization and   *
        !            55:  *               enters the message loop.                                   *
        !            56:  *                                                                          *
        !            57:  ****************************************************************************/
        !            58: int APIENTRY WinMain(
        !            59:     HANDLE hInstance,
        !            60:     HANDLE hPrevInstance,
        !            61:     LPSTR lpszCmdLine,
        !            62:     int nCmdShow
        !            63:     )
        !            64: {
        !            65:     MSG msg;
        !            66: 
        !            67:     hInst = hInstance;
        !            68: 
        !            69:     /* If this is the first instance of the app. register window classes */
        !            70:     if (!hPrevInstance){
        !            71:         if (!InitializeApplication ())
        !            72:             return 0;
        !            73:     }
        !            74: 
        !            75:     /* Create the frame and do other initialization */
        !            76:     if (!InitializeInstance(nCmdShow))
        !            77:         return 0;
        !            78: 
        !            79:     /* Enter main message loop */
        !            80:     while (GetMessage (&msg, NULL, 0, 0)){
        !            81:         (*lpMsgFilterProc)(MSGF_DDEMGR, 0, (LONG)(LPMSG)&msg);
        !            82:     }
        !            83: 
        !            84:     // free up any appowned handles
        !            85:     while (cOwned) {
        !            86:         DdeFreeDataHandle(aOwned[--cOwned].hData);
        !            87:     }
        !            88:     DdeUninitialize(idInst);
        !            89: 
        !            90:     UnhookWindowsHook(WH_MSGFILTER, lpMsgFilterProc);
        !            91:     FreeProcInstance(lpMsgFilterProc);
        !            92: 
        !            93:     return 0;
        !            94: }
        !            95: 
        !            96: /****************************************************************************
        !            97:  *                                                                          *
        !            98:  *  FUNCTION   : FrameWndProc (hwnd, msg, wParam, lParam )                  *
        !            99:  *                                                                          *
        !           100:  *  PURPOSE    : The window function for the "frame" window, which controls *
        !           101:  *               the menu and encompasses all the MDI child windows. Does   *
        !           102:  *               the major part of the message processing. Specifically, in *
        !           103:  *               response to:                                               *
        !           104:  *                                                                          *
        !           105:  ****************************************************************************/
        !           106: LONG  APIENTRY FrameWndProc ( hwnd, msg, wParam, lParam )
        !           107: HWND   hwnd;
        !           108: UINT   msg;
        !           109: WPARAM wParam;
        !           110: LPARAM lParam;
        !           111: 
        !           112: {
        !           113:     switch (msg){
        !           114:         case WM_CREATE:{
        !           115:             CLIENTCREATESTRUCT ccs;
        !           116: 
        !           117:             /* Find window menu where children will be listed */
        !           118:             ccs.hWindowMenu = GetSubMenu (GetMenu(hwnd),WINDOWMENU);
        !           119:             ccs.idFirstChild = IDM_WINDOWCHILD;
        !           120: 
        !           121:             /* Create the MDI client filling the client area */
        !           122:             hwndMDIClient = CreateWindow ("mdiclient",
        !           123:                                           NULL,
        !           124:                                           WS_CHILD | WS_CLIPCHILDREN |
        !           125:                                           WS_VSCROLL | WS_HSCROLL,
        !           126:                                           0,
        !           127:                                           0,
        !           128:                                           0,
        !           129:                                           0,
        !           130:                                           hwnd,
        !           131:                                           (HMENU)0xCAC,
        !           132:                                           hInst,
        !           133:                                           (LPSTR)&ccs);
        !           134: 
        !           135: 
        !           136:             ShowWindow (hwndMDIClient,SW_SHOW);
        !           137:             break;
        !           138:         }
        !           139: 
        !           140:         case WM_INITMENU:
        !           141:             InitializeMenu ((HMENU)wParam);
        !           142:             break;
        !           143: 
        !           144:         case WM_COMMAND:
        !           145:             CommandHandler (hwnd, GET_WM_COMMAND_ID(wParam, lParam));
        !           146:             break;
        !           147: 
        !           148:         case WM_CLOSE:
        !           149:             CloseAllChildren();
        !           150:             DestroyWindow(hwnd);
        !           151:             break;
        !           152: 
        !           153:         case WM_DESTROY:
        !           154:             PostQuitMessage(0);
        !           155:             break;
        !           156: 
        !           157:         default:
        !           158:             /*  use DefFrameProc() instead of DefWindowProc() since there
        !           159:              *  are things that have to be handled differently because of MDI
        !           160:              */
        !           161:             return DefFrameProc (hwnd,hwndMDIClient,msg,wParam,lParam);
        !           162:     }
        !           163:     return 0;
        !           164: }
        !           165: 
        !           166: 
        !           167: 
        !           168: 
        !           169: 
        !           170: /****************************************************************************
        !           171:  *                                                                          *
        !           172:  *  FUNCTION   : MDIChildWndProc                                            *
        !           173:  *                                                                          *
        !           174:  *  PURPOSE    : The window function for the "child" conversation and list  *
        !           175:  *               windows.                                                   *
        !           176:  *                                                                          *
        !           177:  ****************************************************************************/
        !           178: LONG  APIENTRY MDIChildWndProc( hwnd, msg, wParam, lParam )
        !           179: HWND   hwnd;
        !           180: UINT   msg;
        !           181: WPARAM wParam;
        !           182: LPARAM lParam;
        !           183: {
        !           184:     MYCONVINFO *pmci;
        !           185:     RECT rc;
        !           186: 
        !           187:     switch (msg){
        !           188:     case WM_CREATE:
        !           189:         /*
        !           190:          * Create a coresponding conversation info structure to link this
        !           191:          * window to the conversation or conversation list it represents.
        !           192:          *
        !           193:          * lParam: points to the conversation info to initialize our copy to.
        !           194:          */
        !           195:         pmci = (MYCONVINFO *)MyAlloc(sizeof(MYCONVINFO));
        !           196:         if (pmci != NULL) {
        !           197:             _fmemcpy(pmci,
        !           198:                     (LPSTR)((LPMDICREATESTRUCT)((LPCREATESTRUCT)lParam)->lpCreateParams)->lParam,
        !           199:                     sizeof(MYCONVINFO));
        !           200:             pmci->hwndXaction = 0;              /* no current transaction yet */
        !           201:             pmci->x = pmci->y = 0;              /* new transaction windows start here */
        !           202:             DdeKeepStringHandle(idInst, pmci->hszTopic);/* keep copies of the hszs for us */
        !           203:             DdeKeepStringHandle(idInst, pmci->hszApp);
        !           204: 
        !           205:              // link hConv and hwnd together
        !           206:             SetWindowLong(hwnd, 0, (DWORD)pmci);
        !           207: 
        !           208:             /*
        !           209:              * non-list windows link the conversations to the windows via the
        !           210:              * conversation user handle.
        !           211:              */
        !           212:             if (!pmci->fList)
        !           213:                 DdeSetUserHandle(pmci->hConv, QID_SYNC, (DWORD)hwnd);
        !           214:         }
        !           215:         goto CallDCP;
        !           216:         break;
        !           217: 
        !           218:     case UM_GETNEXTCHILDX:
        !           219:     case UM_GETNEXTCHILDY:
        !           220:         /*
        !           221:          * Calculate the next place to put the next transaction window.
        !           222:          */
        !           223:         {
        !           224:             pmci = (MYCONVINFO *)GetWindowLong(hwnd, 0);
        !           225:             GetClientRect(hwnd, &rc);
        !           226:             if (msg == UM_GETNEXTCHILDX) {
        !           227:                 pmci->x += 14;
        !           228:                 if (pmci->x > (rc.right - 200 - rc.left))
        !           229:                     pmci->x = 0;
        !           230:                 return(pmci->x);
        !           231:             } else {
        !           232:                 pmci->y += 12;
        !           233:                 if (pmci->y > (rc.bottom - 100 - rc.top))
        !           234:                     pmci->y = 0;
        !           235:                 return(pmci->y);
        !           236:             }
        !           237:         }
        !           238:         break;
        !           239: 
        !           240:     case UM_DISCONNECTED:
        !           241:         /*
        !           242:          * Disconnected conversations can't have any transactions so we
        !           243:          * remove all the transaction windows here to show whats up.
        !           244:          */
        !           245:         {
        !           246:             HWND hwndT;
        !           247:             while (hwndT = GetWindow(hwnd, GW_CHILD))
        !           248:                 DestroyWindow(hwndT);
        !           249:             InvalidateRect(hwnd, NULL, TRUE);
        !           250:         }
        !           251:         break;
        !           252: 
        !           253:     case WM_DESTROY:
        !           254:         /*
        !           255:          * Cleanup our conversation info structure, and disconnect all
        !           256:          * conversations associated with this window.
        !           257:          */
        !           258:         pmci = (MYCONVINFO *)GetWindowLong(hwnd, 0);
        !           259:         pmci->hwndXaction = 0;      /* clear this to avoid focus problems */
        !           260:         if (pmci->hConv) {
        !           261:             if (pmci->fList) {
        !           262:                 DdeDisconnectList((HCONVLIST)pmci->hConv);
        !           263:             } else {
        !           264:                 MyDisconnect(pmci->hConv);
        !           265:             }
        !           266:         }
        !           267:         DdeFreeStringHandle(idInst, pmci->hszTopic);
        !           268:         DdeFreeStringHandle(idInst, pmci->hszApp);
        !           269:         MyFree(pmci);
        !           270:         goto CallDCP;
        !           271:         break;
        !           272: 
        !           273:     case WM_SETFOCUS:
        !           274:         /*
        !           275:          * This catches focus changes caused by dialogs.
        !           276:          */
        !           277:         lParam = (LPARAM)hwnd;
        !           278:         // fall through
        !           279: 
        !           280:     case WM_MDIACTIVATE:
        !           281:         hwndActive = GET_WM_MDIACTIVATE_HWNDACTIVATE(wParam, lParam);
        !           282:         pmci = (MYCONVINFO *)GetWindowLong(hwnd, 0);
        !           283:         /*
        !           284:          * pass the focus onto the current transaction window.
        !           285:          */
        !           286:         if (GET_WM_MDIACTIVATE_FACTIVATE(hwnd, wParam, lParam) &&
        !           287:                 IsWindow(pmci->hwndXaction))
        !           288:             SetFocus(pmci->hwndXaction);
        !           289:         break;
        !           290: 
        !           291:     case ICN_HASFOCUS:
        !           292:         /*
        !           293:          * update which transaction window is the main one.
        !           294:          */
        !           295:         pmci = (MYCONVINFO *)GetWindowLong(hwnd, 0);
        !           296:         pmci->hwndXaction = wParam ? (HWND)lParam : NULL;
        !           297:         break;
        !           298: 
        !           299:     case ICN_BYEBYE:
        !           300:         /*
        !           301:          * Transaction window is closing...
        !           302:          *
        !           303:          * wParam = hwndXact
        !           304:          * lParam = lpxact
        !           305:          */
        !           306:         pmci = (MYCONVINFO *)GetWindowLong(hwnd, 0);
        !           307:         if (pmci != NULL) {
        !           308:             XACT *pxact;
        !           309: 
        !           310:             pxact = (XACT *)lParam;
        !           311:             if (pxact != NULL) {
        !           312:                 /*
        !           313:                  * If this transaction is active, abandon it first.
        !           314:                  */
        !           315:                 if (pxact->fsOptions & XOPT_ASYNC &&
        !           316:                         !(pxact->fsOptions & XOPT_COMPLETED)) {
        !           317:                     DdeAbandonTransaction(idInst, pmci->hConv, pxact->Result);
        !           318:                 }
        !           319:                 /*
        !           320:                  * release resources associated with transaction.
        !           321:                  */
        !           322:                 DdeFreeStringHandle(idInst, pxact->hszItem);
        !           323:                 MyFree((PSTR)pxact);
        !           324:                 /*
        !           325:                  * Locate next apropriate transaction window to get focus.
        !           326:                  */
        !           327:                 if (!pmci->hwndXaction || pmci->hwndXaction == (HWND)wParam)
        !           328:                     pmci->hwndXaction = GetWindow(hwnd, GW_CHILD);
        !           329:                 if (pmci->hwndXaction == (HWND)wParam)
        !           330:                     pmci->hwndXaction = GetWindow((HWND)wParam, GW_HWNDNEXT);
        !           331:                 if (pmci->hwndXaction == (HWND)wParam ||
        !           332:                         !IsWindow(pmci->hwndXaction) ||
        !           333:                         !IsChild(hwnd, pmci->hwndXaction))
        !           334:                     pmci->hwndXaction = NULL;
        !           335:                 else
        !           336:                     SetFocus(pmci->hwndXaction);
        !           337:             }
        !           338:         }
        !           339:         break;
        !           340: 
        !           341:     case WM_PAINT:
        !           342:         /*
        !           343:          * Paint this conversation's related information.
        !           344:          */
        !           345:         pmci = (MYCONVINFO *)GetWindowLong(hwnd, 0);
        !           346:         {
        !           347:             PAINTSTRUCT ps;
        !           348:             PSTR psz;
        !           349: 
        !           350:             BeginPaint(hwnd, &ps);
        !           351:             SetBkMode(ps.hdc, TRANSPARENT);
        !           352:             psz = pmci->fList ? GetConvListText(pmci->hConv) :
        !           353:                     GetConvInfoText(pmci->hConv, &pmci->ci);
        !           354:             if (psz) {
        !           355:                 GetClientRect(hwnd, &rc);
        !           356:                 DrawText(ps.hdc, psz, -1, &rc,
        !           357:                         DT_WORDBREAK | DT_LEFT | DT_NOPREFIX | DT_TABSTOP);
        !           358:                 MyFree(psz);
        !           359:             }
        !           360:             EndPaint(hwnd, &ps);
        !           361:         }
        !           362:         break;
        !           363: 
        !           364:     case WM_QUERYENDSESSION:
        !           365:         return TRUE;
        !           366: 
        !           367:     default:
        !           368: CallDCP:
        !           369:         /* Again, since the MDI default behaviour is a little different,
        !           370:          * call DefMDIChildProc instead of DefWindowProc()
        !           371:          */
        !           372:         return DefMDIChildProc (hwnd, msg, wParam, lParam);
        !           373:     }
        !           374:     return FALSE;
        !           375: }
        !           376: 
        !           377: 
        !           378: /****************************************************************************
        !           379:  *                                                                          *
        !           380:  *  FUNCTION   : Initializemenu ( hMenu )                                   *
        !           381:  *                                                                          *
        !           382:  *  PURPOSE    : Sets up greying, enabling and checking of main menu items  *
        !           383:  *               based on the app's state.                                  *
        !           384:  *                                                                          *
        !           385:  ****************************************************************************/
        !           386: VOID NEAR PASCAL InitializeMenu ( hmenu )
        !           387: HANDLE hmenu;
        !           388: {
        !           389:     BOOL fLink      = FALSE; // set if Link format is on the clipboard;
        !           390:     BOOL fAny       = FALSE; // set if hwndActive exists
        !           391:     BOOL fList      = FALSE; // set if hwndActive is a list window
        !           392:     BOOL fConnected = FALSE; // set if hwndActive is a connection conversation.
        !           393:     BOOL fXaction   = FALSE; // set if hwndActive has a selected transaction window
        !           394:     BOOL fXactions  = FALSE; // set if hwndActive contains transaction windows
        !           395:     BOOL fBlocked   = FALSE; // set if hwndActive conversation is blocked.
        !           396:     BOOL fBlockNext = FALSE; // set if handActive conversation is blockNext.
        !           397:     MYCONVINFO *pmci = NULL;
        !           398: 
        !           399:     if (OpenClipboard(hwndFrame)) {
        !           400:         fLink = (IsClipboardFormatAvailable(fmtLink));
        !           401:         CloseClipboard();
        !           402:     }
        !           403: 
        !           404:     if (fAny = (IsWindow(hwndActive) &&
        !           405:             (pmci = (MYCONVINFO *)GetWindowLong(hwndActive, 0)))) {
        !           406:         fXactions = (BOOL)GetWindow(hwndActive, GW_CHILD);
        !           407:         if (!(fList = pmci->fList)) {
        !           408:             CONVINFO ci;
        !           409: 
        !           410:             ci.cb = sizeof(CONVINFO);
        !           411:             DdeQueryConvInfo(pmci->hConv, QID_SYNC, &ci);
        !           412:             fConnected = ci.wStatus & ST_CONNECTED;
        !           413:             fXaction = IsWindow(pmci->hwndXaction);
        !           414:             fBlocked = ci.wStatus & ST_BLOCKED;
        !           415:             fBlockNext = ci.wStatus & ST_BLOCKNEXT;
        !           416:         }
        !           417:     }
        !           418: 
        !           419:     EnableMenuItem(hmenu,   IDM_EDITPASTE,
        !           420:             fLink           ? MF_ENABLED    : MF_GRAYED);
        !           421: 
        !           422:     // IDM_CONNECTED - always enabled.
        !           423: 
        !           424:     EnableMenuItem(hmenu,   IDM_RECONNECT,
        !           425:             fList           ? MF_ENABLED    : MF_GRAYED);
        !           426: 
        !           427:     EnableMenuItem (hmenu,  IDM_DISCONNECT,
        !           428:             fConnected      ? MF_ENABLED    : MF_GRAYED);
        !           429: 
        !           430:     EnableMenuItem (hmenu,  IDM_TRANSACT,
        !           431:             fConnected      ? MF_ENABLED    : MF_GRAYED);
        !           432: 
        !           433:     EnableMenuItem(hmenu,   IDM_ABANDON,
        !           434:             fXaction        ? MF_ENABLED    : MF_GRAYED);
        !           435: 
        !           436:     EnableMenuItem(hmenu,   IDM_ABANDONALL,
        !           437:             fXactions ? MF_ENABLED : MF_GRAYED);
        !           438: 
        !           439: 
        !           440:     EnableMenuItem (hmenu,  IDM_BLOCKCURRENT,
        !           441:             fConnected && !fBlocked ? MF_ENABLED    : MF_GRAYED);
        !           442:     CheckMenuItem(hmenu, IDM_BLOCKCURRENT,
        !           443:             fBlocked        ? MF_CHECKED    : MF_UNCHECKED);
        !           444: 
        !           445:     EnableMenuItem (hmenu,  IDM_ENABLECURRENT,
        !           446:             fConnected && (fBlocked || fBlockNext) ? MF_ENABLED : MF_GRAYED);
        !           447:     CheckMenuItem(hmenu,    IDM_ENABLECURRENT,
        !           448:             !fBlocked       ? MF_CHECKED    : MF_UNCHECKED);
        !           449: 
        !           450:     EnableMenuItem (hmenu,  IDM_ENABLEONECURRENT,
        !           451:             fConnected && (fBlocked) ? MF_ENABLED : MF_GRAYED);
        !           452:     CheckMenuItem(hmenu,    IDM_ENABLEONECURRENT,
        !           453:             fBlockNext      ? MF_CHECKED    : MF_UNCHECKED);
        !           454: 
        !           455:     EnableMenuItem (hmenu,  IDM_BLOCKALLCBS,
        !           456:             fAny            ? MF_ENABLED    : MF_GRAYED);
        !           457: 
        !           458:     EnableMenuItem (hmenu,  IDM_ENABLEALLCBS,
        !           459:             fAny            ? MF_ENABLED    : MF_GRAYED);
        !           460: 
        !           461:     EnableMenuItem (hmenu,  IDM_ENABLEONECB,
        !           462:             fAny            ? MF_ENABLED    : MF_GRAYED);
        !           463: 
        !           464:     EnableMenuItem(hmenu,   IDM_BLOCKNEXTCB,
        !           465:             fAny || fBlockNextCB ? MF_ENABLED    : MF_GRAYED);
        !           466:     CheckMenuItem(hmenu,    IDM_BLOCKNEXTCB,
        !           467:             fBlockNextCB    ? MF_CHECKED    : MF_UNCHECKED);
        !           468: 
        !           469:     EnableMenuItem(hmenu,   IDM_TERMNEXTCB,
        !           470:             fAny || fTermNextCB ? MF_ENABLED    : MF_GRAYED);
        !           471:     CheckMenuItem(hmenu,    IDM_TERMNEXTCB,
        !           472:             fTermNextCB     ? MF_CHECKED    : MF_UNCHECKED);
        !           473: 
        !           474:     // IDM_DELAY - always enabled.
        !           475: 
        !           476:     // IDM_TIMEOUT - alwasy enabled.
        !           477: 
        !           478:     EnableMenuItem (hmenu,  IDM_WINDOWTILE,
        !           479:             fAny            ? MF_ENABLED    : MF_GRAYED);
        !           480: 
        !           481:     EnableMenuItem (hmenu,  IDM_WINDOWCASCADE,
        !           482:             fAny            ? MF_ENABLED    : MF_GRAYED);
        !           483: 
        !           484:     EnableMenuItem (hmenu,  IDM_WINDOWICONS,
        !           485:             fAny            ? MF_ENABLED    : MF_GRAYED);
        !           486: 
        !           487:     EnableMenuItem (hmenu,  IDM_WINDOWCLOSEALL,
        !           488:             fAny            ? MF_ENABLED    : MF_GRAYED);
        !           489: 
        !           490:     EnableMenuItem (hmenu,  IDM_XACTTILE,
        !           491:             fXactions       ? MF_ENABLED    : MF_GRAYED);
        !           492: 
        !           493:     EnableMenuItem (hmenu,  IDM_XACTCASCADE,
        !           494:             fXactions       ? MF_ENABLED    : MF_GRAYED);
        !           495: 
        !           496:     CheckMenuItem(hmenu,   IDM_AUTORECONNECT,
        !           497:             fAutoReconnect  ? MF_CHECKED    : MF_UNCHECKED);
        !           498: 
        !           499:     // IDM_HELPABOUT - always enabled.
        !           500: }
        !           501: 
        !           502: 
        !           503: 
        !           504: /****************************************************************************
        !           505:  *                                                                          *
        !           506:  *  FUNCTION   : CloseAllChildren ()                                        *
        !           507:  *                                                                          *
        !           508:  *  PURPOSE    : Destroys all MDI child windows.                            *
        !           509:  *                                                                          *
        !           510:  ****************************************************************************/
        !           511: VOID NEAR PASCAL CloseAllChildren ()
        !           512: {
        !           513:     HWND hwndT;
        !           514: 
        !           515:     /* hide the MDI client window to avoid multiple repaints */
        !           516:     ShowWindow(hwndMDIClient,SW_HIDE);
        !           517: 
        !           518:     /* As long as the MDI client has a child, destroy it */
        !           519:     while ( hwndT = GetWindow (hwndMDIClient, GW_CHILD)){
        !           520: 
        !           521:         /* Skip the icon title windows */
        !           522:         while (hwndT && GetWindow (hwndT, GW_OWNER))
        !           523:             hwndT = GetWindow (hwndT, GW_HWNDNEXT);
        !           524: 
        !           525:         if (!hwndT)
        !           526:             break;
        !           527: 
        !           528:         SendMessage(hwndMDIClient, WM_MDIDESTROY, (DWORD)hwndT, 0L);
        !           529:     }
        !           530: 
        !           531:     ShowWindow( hwndMDIClient, SW_SHOW);
        !           532: }
        !           533: 
        !           534: /****************************************************************************
        !           535:  *                                                                          *
        !           536:  *  FUNCTION   : CommandHandler ()                                          *
        !           537:  *                                                                          *
        !           538:  *  PURPOSE    : Processes all "frame" WM_COMMAND messages.                 *
        !           539:  *                                                                          *
        !           540:  ****************************************************************************/
        !           541: VOID NEAR PASCAL CommandHandler (
        !           542: HWND hwnd,
        !           543: DWORD id)
        !           544: 
        !           545: {
        !           546:     MYCONVINFO *pmci = NULL;
        !           547: 
        !           548:     if (hwndActive)
        !           549:         pmci = (MYCONVINFO *)GetWindowLong(hwndActive, 0);
        !           550: 
        !           551:     switch (id){
        !           552:         case IDM_EDITPASTE:
        !           553:             {
        !           554:                 HANDLE hClipData;
        !           555:                 LPSTR psz;
        !           556:                 XACT xact;
        !           557: 
        !           558:                 if (OpenClipboard(hwnd)) {
        !           559:                     if (hClipData = GetClipboardData(fmtLink)) {
        !           560:                         if (psz = GlobalLock(hClipData)) {
        !           561:                             /*
        !           562:                              * Create a conversation with the link app and
        !           563:                              * begin a request and advise start transaction.
        !           564:                              */
        !           565:                             xact.hConv = CreateConv(DdeCreateStringHandle(idInst, psz, NULL),
        !           566:                                     DdeCreateStringHandle(idInst, &psz[_fstrlen(psz) + 1], NULL),
        !           567:                                     FALSE);
        !           568:                             if (xact.hConv) {
        !           569:                                 psz += _fstrlen(psz) + 1;
        !           570:                                 psz += _fstrlen(psz) + 1;
        !           571:                                 xact.ulTimeout = DefTimeout;
        !           572:                                 xact.wType = XTYP_ADVSTART;
        !           573:                                 xact.hDdeData = 0;
        !           574:                                 xact.wFmt = CF_TEXT;
        !           575:                                 xact.hszItem = DdeCreateStringHandle(idInst, psz, NULL);
        !           576:                                 xact.fsOptions = 0;
        !           577:                                 ProcessTransaction(&xact);
        !           578:                                 xact.wType = XTYP_REQUEST;
        !           579:                                 ProcessTransaction(&xact);
        !           580:                             }
        !           581:                             GlobalUnlock(hClipData);
        !           582:                         }
        !           583:                     }
        !           584:                     CloseClipboard();
        !           585:                 }
        !           586:             }
        !           587:             break;
        !           588: 
        !           589:         case IDM_CONNECT:
        !           590:         case IDM_RECONNECT:
        !           591:             DoDialog(MAKEINTRESOURCE(IDD_CONNECT), (WNDPROC)ConnectDlgProc,
        !           592:                     id == IDM_RECONNECT, FALSE);
        !           593:             break;
        !           594: 
        !           595:         case IDM_DISCONNECT:
        !           596:             if (hwndActive) {
        !           597:                 SendMessage(hwndMDIClient, WM_MDIDESTROY, (DWORD)hwndActive, 0L);
        !           598:             }
        !           599:             break;
        !           600: 
        !           601:         case IDM_TRANSACT:
        !           602:             if (DoDialog(MAKEINTRESOURCE(IDD_TRANSACT), (WNDPROC)TransactDlgProc,
        !           603:                     (DWORD)(LPSTR)pmci->hConv, FALSE))
        !           604:                 SetFocus(GetWindow(hwndActive, GW_CHILD));
        !           605:             break;
        !           606: 
        !           607:         case IDM_ABANDON:
        !           608:             if (pmci != NULL && IsWindow(pmci->hwndXaction)) {
        !           609:                 DestroyWindow(pmci->hwndXaction);
        !           610:             }
        !           611:             break;
        !           612: 
        !           613:         case IDM_ABANDONALL:
        !           614:             DdeAbandonTransaction(idInst, pmci->hConv, NULL);
        !           615:             {
        !           616:                 HWND hwndXaction;
        !           617: 
        !           618:                 hwndXaction = GetWindow(hwndActive, GW_CHILD);
        !           619:                 while (hwndXaction) {
        !           620:                     DestroyWindow(hwndXaction);
        !           621:                     hwndXaction = GetWindow(hwndActive, GW_CHILD);
        !           622:                 }
        !           623:             }
        !           624:             break;
        !           625: 
        !           626:         case IDM_BLOCKCURRENT:
        !           627:             DdeEnableCallback(idInst, pmci->hConv, EC_DISABLE);
        !           628:             InvalidateRect(hwndActive, NULL, TRUE);
        !           629:             break;
        !           630: 
        !           631:         case IDM_ENABLECURRENT:
        !           632:             DdeEnableCallback(idInst, pmci->hConv, EC_ENABLEALL);
        !           633:             InvalidateRect(hwndActive, NULL, TRUE);
        !           634:             break;
        !           635: 
        !           636:         case IDM_ENABLEONECURRENT:
        !           637:             DdeEnableCallback(idInst, pmci->hConv, EC_ENABLEONE);
        !           638:             InvalidateRect(hwndActive, NULL, TRUE);
        !           639:             break;
        !           640: 
        !           641:         case IDM_BLOCKALLCBS:
        !           642:             DdeEnableCallback(idInst, NULL, EC_DISABLE);
        !           643:             InvalidateRect(hwndMDIClient, NULL, TRUE);
        !           644:             break;
        !           645: 
        !           646:         case IDM_ENABLEALLCBS:
        !           647:             DdeEnableCallback(idInst, NULL, EC_ENABLEALL);
        !           648:             InvalidateRect(hwndMDIClient, NULL, TRUE);
        !           649:             break;
        !           650: 
        !           651:         case IDM_ENABLEONECB:
        !           652:             DdeEnableCallback(idInst, NULL, EC_ENABLEONE);
        !           653:             InvalidateRect(hwndMDIClient, NULL, TRUE);
        !           654:             break;
        !           655: 
        !           656:         case IDM_BLOCKNEXTCB:
        !           657:             fBlockNextCB = !fBlockNextCB;
        !           658:             break;
        !           659: 
        !           660:         case IDM_TERMNEXTCB:
        !           661:             fTermNextCB = !fTermNextCB;
        !           662:             break;
        !           663: 
        !           664:         case IDM_DELAY:
        !           665:             DoDialog(MAKEINTRESOURCE(IDD_VALUEENTRY), (WNDPROC)DelayDlgProc, NULL,
        !           666:                     TRUE);
        !           667:             break;
        !           668: 
        !           669:         case IDM_TIMEOUT:
        !           670:             DoDialog(MAKEINTRESOURCE(IDD_VALUEENTRY), (WNDPROC)TimeoutDlgProc, NULL,
        !           671:                     TRUE);
        !           672:             break;
        !           673: 
        !           674:         case IDM_CONTEXT:
        !           675:             DoDialog(MAKEINTRESOURCE(IDD_CONTEXT), (WNDPROC)ContextDlgProc, NULL, TRUE);
        !           676:             break;
        !           677: 
        !           678:         case IDM_AUTORECONNECT:
        !           679:             fAutoReconnect = !fAutoReconnect;
        !           680:             break;
        !           681: 
        !           682:         /* The following are window commands - these are handled by the
        !           683:          * MDI Client.
        !           684:          */
        !           685:         case IDM_WINDOWTILE:
        !           686:             /* Tile MDI windows */
        !           687:             SendMessage (hwndMDIClient, WM_MDITILE, 0, 0L);
        !           688:             break;
        !           689: 
        !           690:         case IDM_WINDOWCASCADE:
        !           691:             /* Cascade MDI windows */
        !           692:             SendMessage (hwndMDIClient, WM_MDICASCADE, 0, 0L);
        !           693:             break;
        !           694: 
        !           695:         case IDM_WINDOWICONS:
        !           696:             /* Auto - arrange MDI icons */
        !           697:             SendMessage (hwndMDIClient, WM_MDIICONARRANGE, 0, 0L);
        !           698:             break;
        !           699: 
        !           700:         case IDM_WINDOWCLOSEALL:
        !           701:             CloseAllChildren();
        !           702:             break;
        !           703: 
        !           704:         case IDM_XACTTILE:
        !           705:             TileChildWindows(hwndActive);
        !           706:             break;
        !           707: 
        !           708:         case IDM_XACTCASCADE:
        !           709:             MyCascadeChildWindows(hwndActive);
        !           710:             break;
        !           711: 
        !           712:         case IDM_HELPABOUT:{
        !           713:             DoDialog(MAKEINTRESOURCE(IDD_ABOUT), (WNDPROC)AboutDlgProc, NULL, TRUE);
        !           714:             break;
        !           715:         }
        !           716: 
        !           717:         default:
        !           718:            /*
        !           719:             * This is essential, since there are frame WM_COMMANDS generated
        !           720:             * by the MDI system for activating child windows via the
        !           721:             * window menu.
        !           722:             */
        !           723:             DefFrameProc(hwnd, hwndMDIClient, WM_COMMAND,
        !           724:                     GET_WM_COMMAND_MPS(id, 0, 0));
        !           725:     }
        !           726: }
        !           727: 
        !           728: 
        !           729: /****************************************************************************
        !           730:  *                                                                          *
        !           731:  *  FUNCTION   : MPError (flags, id, ...)                            *
        !           732:  *                                                                          *
        !           733:  *  PURPOSE    : Flashes a Message Box to the user. The format string is    *
        !           734:  *               taken from the STRINGTABLE.                                *
        !           735:  *                                                                          *
        !           736:  *  RETURNS    : Returns value returned by MessageBox() to the caller.      *
        !           737:  *                                                                          *
        !           738:  ****************************************************************************/
        !           739: INT FAR cdecl MPError(
        !           740: DWORD bFlags,
        !           741: DWORD id,
        !           742: ...)
        !           743: {
        !           744:     CHAR sz[160];
        !           745:     CHAR szFmt[128];
        !           746: 
        !           747:     LoadString (hInst, id, szFmt, sizeof (szFmt));
        !           748:     wvsprintf (sz, szFmt, (LPSTR)(&id + 1));
        !           749:     LoadString (hInst, IDS_APPNAME, szFmt, sizeof (szFmt));
        !           750:     return MessageBox (hwndFrame, sz, szFmt, bFlags);
        !           751: }
        !           752: 
        !           753: 
        !           754: 
        !           755: /****************************************************************************
        !           756:  *                                                                          *
        !           757:  *  FUNCTION   : CreateConv()                                               *
        !           758:  *                                                                          *
        !           759:  *  PURPOSE    :                                                            *
        !           760:  *                                                                          *
        !           761:  *  RETURNS    :                                                            *
        !           762:  *                                                                          *
        !           763:  ****************************************************************************/
        !           764: HCONV CreateConv(
        !           765: HSZ hszApp,
        !           766: HSZ hszTopic,
        !           767: BOOL fList)
        !           768: {
        !           769:     HCONV hConv;
        !           770:     HWND hwndConv = 0;
        !           771:     CONVINFO ci;
        !           772: 
        !           773:     if (fList) {
        !           774:         hConv = (HCONV)DdeConnectList(idInst, hszApp, hszTopic, NULL, &CCFilter);
        !           775:     } else {
        !           776:         hConv = DdeConnect(idInst, hszApp, hszTopic, &CCFilter);
        !           777:     }
        !           778:     if (hConv) {
        !           779:         if (fList) {
        !           780:             ci.hszSvcPartner = hszApp;
        !           781:             ci.hszTopic = hszTopic;
        !           782:         } else {
        !           783:             ci.cb = sizeof(CONVINFO);
        !           784:             DdeQueryConvInfo(hConv, QID_SYNC, &ci);
        !           785:         }
        !           786:         hwndConv = AddConv(ci.hszSvcPartner, ci.hszTopic, hConv, fList);
        !           787:         // HSZs get freed when window dies.
        !           788:     }
        !           789:     if (!hwndConv) {
        !           790:         DdeFreeStringHandle(idInst, hszApp);
        !           791:         DdeFreeStringHandle(idInst, hszTopic);
        !           792:     }
        !           793:     return(hConv);
        !           794: }
        !           795: 
        !           796: 
        !           797: 
        !           798: 
        !           799: 
        !           800: 
        !           801: /****************************************************************************
        !           802:  *                                                                          *
        !           803:  *  FUNCTION   : AddConv()                                                  *
        !           804:  *                                                                          *
        !           805:  *  PURPOSE    : Creates an MDI window representing a conversation          *
        !           806:  *               (fList = FALSE) or a set of MID windows for the list of    *
        !           807:  *               conversations (fList = TRUE).                              *
        !           808:  *                                                                          *
        !           809:  *  EFFECTS    : Sets the hUser for the conversation to the created MDI     *
        !           810:  *               child hwnd.  Keeps the hszs if successful.                 *
        !           811:  *                                                                          *
        !           812:  *  RETURNS    : created MDI window handle.                                 *
        !           813:  *                                                                          *
        !           814:  ****************************************************************************/
        !           815: HWND  APIENTRY AddConv(
        !           816: HSZ hszApp,
        !           817: HSZ hszTopic,
        !           818: HCONV hConv,
        !           819: BOOL fList)
        !           820: {
        !           821:     HWND hwnd;
        !           822:     MDICREATESTRUCT mcs;
        !           823:     MYCONVINFO mci;
        !           824: 
        !           825:     if (fList) {
        !           826:         /*
        !           827:          * Create all child windows FIRST so we have info for list window.
        !           828:          */
        !           829:         CONVINFO ci;
        !           830:         HCONV hConvChild = 0;
        !           831: 
        !           832:         ci.cb = sizeof(CONVINFO);
        !           833:         while (hConvChild = DdeQueryNextServer((HCONVLIST)hConv, hConvChild)) {
        !           834:             if (DdeQueryConvInfo(hConvChild, QID_SYNC, &ci)) {
        !           835:                 AddConv(ci.hszSvcPartner, ci.hszTopic, hConvChild, FALSE);
        !           836:             }
        !           837:         }
        !           838:     }
        !           839: 
        !           840:     mcs.szTitle = GetConvTitleText(hConv, hszApp, hszTopic, fList);
        !           841: 
        !           842:     mcs.szClass = fList ? szList : szChild;
        !           843:     mcs.hOwner  = hInst;
        !           844:     mcs.x = mcs.cx = CW_USEDEFAULT;
        !           845:     mcs.y = mcs.cy = CW_USEDEFAULT;
        !           846:     mcs.style = GetWindow(hwndMDIClient, GW_CHILD) ? 0L : WS_MAXIMIZE;
        !           847: 
        !           848:     // mci.hwndXaction =
        !           849:     mci.fList = fList;
        !           850:     mci.hConv = hConv;
        !           851:     mci.hszTopic = hszTopic;
        !           852:     mci.hszApp = hszApp;
        !           853:     // mci.x =
        !           854:     // mci.y =
        !           855:     // mci.ci =
        !           856:     mcs.lParam = (DWORD)(LPSTR)&mci;
        !           857: 
        !           858:     hwnd = (HWND)SendMessage (hwndMDIClient, WM_MDICREATE, 0,
        !           859:              (LONG)(LPMDICREATESTRUCT)&mcs);
        !           860: 
        !           861:     MyFree((PSTR)(DWORD)mcs.szTitle);
        !           862: 
        !           863:     return hwnd;
        !           864: }
        !           865: 
        !           866: 
        !           867: 
        !           868: 
        !           869: 
        !           870: /****************************************************************************
        !           871:  *                                                                          *
        !           872:  *  FUNCTION   : GetConvListText()                                          *
        !           873:  *                                                                          *
        !           874:  *  RETURN     : Returns a ponter to a string containing a list of          *
        !           875:  *               conversations contained in the given hConvList freeable    *
        !           876:  *               by MyFree();                                               *
        !           877:  *                                                                          *
        !           878:  ****************************************************************************/
        !           879: PSTR GetConvListText(
        !           880: HCONVLIST hConvList)
        !           881: {
        !           882:     HCONV hConv = 0;
        !           883:     DWORD cConv = 0;
        !           884:     CONVINFO ci;
        !           885:     DWORD cb = 0;
        !           886:     CHAR *psz, *pszStart;
        !           887: 
        !           888:     ci.cb = sizeof(CONVINFO);
        !           889: 
        !           890:     // find out size needed.
        !           891: 
        !           892:     while (hConv = DdeQueryNextServer(hConvList, hConv)) {
        !           893:         if (DdeQueryConvInfo(hConv, QID_SYNC, &ci)) {
        !           894:             if (!IsWindow((HWND)ci.hUser)) {
        !           895:                 if (ci.wStatus & ST_CONNECTED) {
        !           896:                     /*
        !           897:                      * This conversation doesn't have a corresponding
        !           898:                      * MDI window.  This is probably due to a reconnection.
        !           899:                      */
        !           900:                     ci.hUser = (DWORD)AddConv(ci.hszSvcPartner, ci.hszTopic, hConv, FALSE);
        !           901:                 } else {
        !           902:                     continue;   // skip this guy - he was closed locally.
        !           903:                 }
        !           904:             }
        !           905:             cb += GetWindowTextLength((HWND)ci.hUser);
        !           906:             if (cConv++)
        !           907:                 cb += 2;        // room for CRLF
        !           908:         }
        !           909:     }
        !           910:     cb++;                       // for terminator.
        !           911: 
        !           912:     // allocate and fill
        !           913: 
        !           914:     if (pszStart = psz = MyAlloc(cb)) {
        !           915:         *psz = '\0';
        !           916:         hConv = 0;
        !           917:         while (hConv = DdeQueryNextServer(hConvList, hConv)) {
        !           918:             if (DdeQueryConvInfo(hConv, QID_SYNC, &ci) &&
        !           919:                     IsWindow((HWND)ci.hUser)) {
        !           920:                 psz += GetWindowText((HWND)ci.hUser, psz, cb);
        !           921:                 if (--cConv) {
        !           922:                     *psz++ = '\r';
        !           923:                     *psz++ = '\n';
        !           924:                 }
        !           925:             }
        !           926:         }
        !           927:     }
        !           928:     return(pszStart);
        !           929: }
        !           930: 
        !           931: 
        !           932: /****************************************************************************
        !           933:  *                                                                          *
        !           934:  *  FUNCTION   : GetConvInfoText()                                          *
        !           935:  *                                                                          *
        !           936:  *  PURPOSE    : Returns a pointer to a string that reflects a              *
        !           937:  *               conversation's information.  Freeable by MyFree();         *
        !           938:  *                                                                          *
        !           939:  ****************************************************************************/
        !           940: PSTR GetConvInfoText(
        !           941: HCONV hConv,
        !           942: CONVINFO *pci)
        !           943: {
        !           944:     PSTR psz;
        !           945:     PSTR szApp;
        !           946: 
        !           947:     psz = MyAlloc(300);
        !           948:     pci->cb = sizeof(CONVINFO);
        !           949:     if (hConv) {
        !           950:         if (!DdeQueryConvInfo(hConv, QID_SYNC, (PCONVINFO)pci)) {
        !           951:             strcpy(psz, "State=Disconnected");
        !           952:             return(psz);
        !           953:         }
        !           954:         szApp = GetHSZName(pci->hszServiceReq);
        !           955:         wsprintf(psz,
        !           956:                 "hUser=0x%lx\r\nhConvPartner=0x%lx\r\nhszServiceReq=%s\r\nStatus=%s\r\nState=%s\r\nLastError=%s",
        !           957:                 pci->hUser, pci->hConvPartner, (LPSTR)szApp,
        !           958:                 (LPSTR)Status2String(pci->wStatus),
        !           959:                 (LPSTR)State2String(pci->wConvst),
        !           960:                 (LPSTR)Error2String(pci->wLastError));
        !           961:         MyFree(szApp);
        !           962:     } else {
        !           963:         strcpy(psz, Error2String(DdeGetLastError(idInst)));
        !           964:     }
        !           965:     return(psz);
        !           966: }
        !           967: 
        !           968: 
        !           969: 
        !           970: /****************************************************************************
        !           971:  *                                                                          *
        !           972:  *  FUNCTION   : GetConvTitleText()                                         *
        !           973:  *                                                                          *
        !           974:  *  PURPOSE    : Creates standard window title text based on parameters.    *
        !           975:  *                                                                          *
        !           976:  *  RETURNS    : psz freeable by MyFree()                                   *
        !           977:  *                                                                          *
        !           978:  ****************************************************************************/
        !           979: PSTR GetConvTitleText(
        !           980: HCONV hConv,
        !           981: HSZ hszApp,
        !           982: HSZ hszTopic,
        !           983: BOOL fList)
        !           984: {
        !           985:     DWORD cb;
        !           986:     PSTR psz;
        !           987: 
        !           988:     cb = (DWORD)DdeQueryString(idInst, hszApp, NULL, 0, 0) +
        !           989:             (DWORD)DdeQueryString(idInst, hszTopic, (LPSTR)NULL, 0, 0) +
        !           990:             (fList ? 30 : 20);
        !           991: 
        !           992:     if (psz = MyAlloc(cb)) {
        !           993:         DdeQueryString(idInst, hszApp, psz, cb, 0);
        !           994:         strcat(psz, "|");
        !           995:         DdeQueryString(idInst, hszTopic, &psz[strlen(psz)], cb, 0);
        !           996:         if (fList)
        !           997:             strcat(psz, " - LIST");
        !           998:         wsprintf(&psz[strlen(psz)], " - (%lx)", hConv);
        !           999:     }
        !          1000:     return(psz);
        !          1001: }
        !          1002: 
        !          1003: 
        !          1004: 
        !          1005: /****************************************************************************
        !          1006:  *                                                                          *
        !          1007:  *  FUNCTION   : Status2String()                                            *
        !          1008:  *                                                                          *
        !          1009:  *  PURPOSE    : Converts a conversation status word to a string and        *
        !          1010:  *               returns a pointer to that string.  The string is valid     *
        !          1011:  *               till the next call to this function.                       *
        !          1012:  *                                                                          *
        !          1013:  ****************************************************************************/
        !          1014: PSTR Status2String(
        !          1015: DWORD status)
        !          1016: {
        !          1017:     DWORD c, i;
        !          1018:     static CHAR szStatus[6 * 18];
        !          1019:     static struct {
        !          1020:         CHAR *szStatus;
        !          1021:         DWORD status;
        !          1022:     } s2s[] = {
        !          1023:         { "Connected"    ,   ST_CONNECTED },
        !          1024:         { "Advise"       ,   ST_ADVISE },
        !          1025:         { "IsLocal"      ,   ST_ISLOCAL },
        !          1026:         { "Blocked"      ,   ST_BLOCKED },
        !          1027:         { "Client"       ,   ST_CLIENT },
        !          1028:         { "Disconnected" ,   ST_TERMINATED },
        !          1029:         { "BlockNext"    ,   ST_BLOCKNEXT },
        !          1030:     };
        !          1031: #define CFLAGS 7
        !          1032:     szStatus[0] = '\0';
        !          1033:     c = 0;
        !          1034:     for (i = 0; i < CFLAGS; i++) {
        !          1035:         if (status & s2s[i].status) {
        !          1036:             if (c++)
        !          1037:                 strcat(szStatus, " | ");
        !          1038:             strcat(szStatus, s2s[i].szStatus);
        !          1039:         }
        !          1040:     }
        !          1041:     return szStatus;
        !          1042: #undef CFLAGS
        !          1043: }
        !          1044: 
        !          1045: 
        !          1046: 
        !          1047: 
        !          1048: /****************************************************************************
        !          1049:  *                                                                          *
        !          1050:  *  FUNCTION   : State2String()                                             *
        !          1051:  *                                                                          *
        !          1052:  *  PURPOSE    : converts a conversation state word to a string and         *
        !          1053:  *               returns a pointer to that string.  The string is valid     *
        !          1054:  *               till the next call to this routine.                        *
        !          1055:  *                                                                          *
        !          1056:  ****************************************************************************/
        !          1057: PSTR State2String(
        !          1058: DWORD state)
        !          1059: {
        !          1060:     static CHAR *s2s[] = {
        !          1061:         "NULL"             ,
        !          1062:         "Incomplete"       ,
        !          1063:         "Standby"          ,
        !          1064:         "Initiating"       ,
        !          1065:         "ReqSent"          ,
        !          1066:         "DataRcvd"         ,
        !          1067:         "PokeSent"         ,
        !          1068:         "PokeAckRcvd"      ,
        !          1069:         "ExecSent"         ,
        !          1070:         "ExecAckRcvd"      ,
        !          1071:         "AdvSent"          ,
        !          1072:         "UnadvSent"        ,
        !          1073:         "AdvAckRcvd"       ,
        !          1074:         "UnadvAckRcvd"     ,
        !          1075:         "AdvDataSent"      ,
        !          1076:         "AdvDataAckRcvd"   ,
        !          1077:         "?"                ,    // 16
        !          1078:     };
        !          1079: 
        !          1080:     if (state >= 17)
        !          1081:         return s2s[17];
        !          1082:     else
        !          1083:         return s2s[state];
        !          1084: }
        !          1085: 
        !          1086: /****************************************************************************
        !          1087:  *                                                                          *
        !          1088:  *  FUNCTION   : Error2String()                                             *
        !          1089:  *                                                                          *
        !          1090:  *  PURPOSE    : Converts an error code to a string and returns a pointer   *
        !          1091:  *               to that string.  The string is valid until the next call   *
        !          1092:  *               to this function.                                          *
        !          1093:  *                                                                          *
        !          1094:  ****************************************************************************/
        !          1095: PSTR Error2String(
        !          1096: DWORD error)
        !          1097: {
        !          1098:     static CHAR szErr[23];
        !          1099:     static CHAR *e2s[] = {
        !          1100:         "Advacktimeout"              ,
        !          1101:         "Busy"                       ,
        !          1102:         "Dataacktimeout"             ,
        !          1103:         "Dll_not_initialized"        ,
        !          1104:         "Dll_usage"                  ,
        !          1105:         "Execacktimeout"             ,
        !          1106:         "Invalidparameter"           ,
        !          1107:         "Low Memory warning"         ,
        !          1108:         "Memory_error"               ,
        !          1109:         "Notprocessed"               ,
        !          1110:         "No_conv_established"        ,
        !          1111:         "Pokeacktimeout"             ,
        !          1112:         "Postmsg_failed"             ,
        !          1113:         "Reentrancy"                 ,
        !          1114:         "Server_died"                ,
        !          1115:         "Sys_error"                  ,
        !          1116:         "Unadvacktimeout"            ,
        !          1117:         "Unfound_queue_id"           ,
        !          1118:     };
        !          1119:     if (!error) {
        !          1120:         strcpy(szErr, "0");
        !          1121:     } else if (error > DMLERR_LAST || error < DMLERR_FIRST) {
        !          1122:         strcpy(szErr, "???");
        !          1123:     } else {
        !          1124:         strcpy(szErr, e2s[error - DMLERR_FIRST]);
        !          1125:     }
        !          1126:     return(szErr);
        !          1127: }
        !          1128: 
        !          1129: 
        !          1130: 
        !          1131: 
        !          1132: 
        !          1133: /****************************************************************************
        !          1134:  *                                                                          *
        !          1135:  *  FUNCTION   : Type2String()                                              *
        !          1136:  *                                                                          *
        !          1137:  *  PURPOSE    : Converts a wType word and fsOption flags to a string and   *
        !          1138:  *               returns a pointer to that string.  the string is valid     *
        !          1139:  *               until the next call to this function.                      *
        !          1140:  *                                                                          *
        !          1141:  ****************************************************************************/
        !          1142: PSTR Type2String(
        !          1143: DWORD wType,
        !          1144: DWORD fsOptions)
        !          1145: {
        !          1146:     static CHAR sz[30];
        !          1147:     static CHAR o2s[] = "^!#$X*<?";
        !          1148:     static CHAR *t2s[] = {
        !          1149:         ""                 ,
        !          1150:         "AdvData"          ,
        !          1151:         "AdvReq"           ,
        !          1152:         "AdvStart"         ,
        !          1153:         "AdvStop"          ,
        !          1154:         "Execute"          ,
        !          1155:         "Connect"          ,
        !          1156:         "ConnectConfirm"   ,
        !          1157:         "XactComplete"    ,
        !          1158:         "Poke"             ,
        !          1159:         "Register"         ,
        !          1160:         "Request"          ,
        !          1161:         "Term"             ,
        !          1162:         "Unregister"       ,
        !          1163:         "WildConnect"      ,
        !          1164:         ""                 ,
        !          1165:     };
        !          1166:     DWORD bit, c, i;
        !          1167: 
        !          1168:     strcpy(sz, t2s[((wType & XTYP_MASK) >> XTYP_SHIFT)]);
        !          1169:     c = strlen(sz);
        !          1170:     sz[c++] = ' ';
        !          1171:     for (i = 0, bit = 1; i < 7; bit = bit << 1, i++) {
        !          1172:         if (fsOptions & bit)
        !          1173:             sz[c++] = o2s[i];
        !          1174:     }
        !          1175:     sz[c] = '\0';
        !          1176:     return(sz);
        !          1177: }
        !          1178: 
        !          1179: 
        !          1180: 
        !          1181: 
        !          1182: /****************************************************************************
        !          1183:  *                                                                          *
        !          1184:  *  FUNCTION   : GetHSZName()                                               *
        !          1185:  *                                                                          *
        !          1186:  *  PURPOSE    : Allocates local memory for and retrieves the string form   *
        !          1187:  *               of an HSZ.  Returns a pointer to the local memory or NULL  *
        !          1188:  *               if failure.  The string must be freed via MyFree().        *
        !          1189:  *                                                                          *
        !          1190:  ****************************************************************************/
        !          1191: PSTR GetHSZName(
        !          1192: HSZ hsz)
        !          1193: {
        !          1194:     PSTR psz;
        !          1195:     DWORD cb;
        !          1196: 
        !          1197:     cb = (DWORD)DdeQueryString(idInst, hsz, NULL, 0, 0) + 1;
        !          1198:     psz = MyAlloc(cb);
        !          1199:     DdeQueryString(idInst, hsz, psz, cb, 0);
        !          1200:     return(psz);
        !          1201: }
        !          1202: 
        !          1203: 
        !          1204: /****************************************************************************
        !          1205:  *
        !          1206:  *  FUNCTION   : MyMsgFilterProc
        !          1207:  *
        !          1208:  *  PURPOSE    : This filter proc gets called for each message we handle.
        !          1209:  *               This allows our application to properly dispatch messages
        !          1210:  *               that we might not otherwise see because of DDEMLs modal
        !          1211:  *               loop that is used while processing synchronous transactions.
        !          1212:  *
        !          1213:  *               Generally, applications that only do synchronous transactions
        !          1214:  *               in response to user input (as this app does) does not need
        !          1215:  *               to install such a filter proc because it would be very rare
        !          1216:  *               that a user could command the app fast enough to cause
        !          1217:  *               problems.  However, this is included as an example.
        !          1218:  *
        !          1219:  ****************************************************************************/
        !          1220: DWORD  APIENTRY MyMsgFilterProc(
        !          1221: INT nCode,
        !          1222: WPARAM wParam,
        !          1223: DWORD lParam)
        !          1224: {
        !          1225:     wParam; // not used
        !          1226: 
        !          1227: #define lpmsg ((LPMSG)lParam)
        !          1228:     if (nCode == MSGF_DDEMGR) {
        !          1229: 
        !          1230:         /* If a keyboard message is for the MDI , let the MDI client
        !          1231:          * take care of it.  Otherwise, check to see if it's a normal
        !          1232:          * accelerator key.  Otherwise, just handle the message as usual.
        !          1233:          */
        !          1234: 
        !          1235:         if ( !TranslateMDISysAccel (hwndMDIClient, lpmsg) &&
        !          1236:              !TranslateAccelerator (hwndFrame, hAccel, lpmsg)){
        !          1237:             TranslateMessage (lpmsg);
        !          1238:             DispatchMessage (lpmsg);
        !          1239:         }
        !          1240:         return(1);
        !          1241:     }
        !          1242:     return(0);
        !          1243: #undef lpmsg
        !          1244: }
        !          1245: 

unix.superglobalmegacorp.com

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