#define USECOMM #include "precomp.h" // Nota Bene: modems aren't unicode aware // so only send them ascii. #define HANGUP_CMD "ATH0\r" #define MAXDIALSIZE 80 /* max size of dial string */ #if defined(WIN32) #define GetCommError( cid, lp ) ClearCommError( cid, NULL, lp ) #endif /* * general form of modem string * * MODEM=COMn,T|P,0|1|2|3|4... * * COMn == com # (1, 2, 3, 4) * TorP == Tone or Pulse * 0|1|2|.. == speed number (0==120, 1==300, 2==1200, 3==2400... * */ #define PRE_LEN 6 TCHAR PrefixDefault[] = TEXT("9-"); TCHAR Prefix[PRE_LEN]; TCHAR ModemInitDefault[] = TEXT("COM1,T,2"); /* com1, tone dialing, 1200 baud */ TCHAR ModemInit[15]; TCHAR *pcComNum = ModemInit + 3; /* ptrs to the stuff we want */ TCHAR *pcTonePulse = ModemInit + 5; TCHAR *pcSpeedNum = ModemInit + 7; // baud rate encoded NOEXPORT void NEAR GetPhoneNumber( LPTSTR pchBuf, int cchMax); NOEXPORT BOOL NEAR ParseNumber( LPTSTR lpSrc, TCHAR *pchBuf, int cchMax); NOEXPORT void NEAR SetPortState( HFILE cid); NOEXPORT int NEAR MakeDialCmd( TCHAR *pBuf, int cchMax, LPTSTR pchNumber); BOOL fnDial( HWND hDB, UINT message, WPARAM wParam, LONG lParam) { TCHAR lpBuf[45]; TCHAR *pResultBuf; int len; TCHAR PhoneNumber[256]; TCHAR buf[40]; TCHAR cmdBuf[160]; RECT rect, rect1; static BOOL fWriteWinIni = FALSE; static BOOL fReadWinIni = TRUE; static BOOL fUsePrefix = FALSE; switch (message) { case WM_INITDIALOG: EnableWindow(GetDlgItem(hDB, ID_SETUP), TRUE); /* make sure he is on */ /* resize myself to hold just the number and buttons */ GetWindowRect(GetDlgItem(hDB, ID_BOX1), &rect); GetWindowRect(hDB, &rect1); MoveWindow(hDB, rect1.left, rect1.top, rect1.right-rect1.left, rect.bottom-rect1.top, FALSE); /* do first time initilazation? */ if (fReadWinIni) { GetProfileString(szWindows, TEXT("Modem"), ModemInitDefault, ModemInit, CharSizeOf(ModemInit)); GetProfileString(szWindows, TEXT("Prefix"), PrefixDefault, Prefix, CharSizeOf(Prefix)); fUsePrefix = GetProfileInt(szWindows, TEXT("UsePrefix"), fUsePrefix); if (*pcSpeedNum == TEXT('F')) { /* for backwards compatability */ *pcSpeedNum = TEXT('2'); fWriteWinIni = TRUE; } fReadWinIni = FALSE; } /* set phone number text and select it */ GetPhoneNumber(PhoneNumber, 256); SetDlgItemText(hDB, ID_NUM, PhoneNumber); SendMessage(GetDlgItem(hDB, ID_NUM), EM_SETSEL, 0, (long)lstrlen(PhoneNumber)); /* set the prefix text */ SetDlgItemText(hDB, ID_PREFIX, Prefix); /* check the use prefix box */ SendMessage(GetDlgItem(hDB, ID_USEPREFIX), BM_SETCHECK, fUsePrefix, 0L); /* check the rest of the buttons... */ CheckRadioButton(hDB, RB_TONE, RB_PULSE, (*pcTonePulse == TEXT('T')) ? RB_TONE : RB_PULSE); CheckRadioButton(hDB, RB_COM1, RB_COM4, RB_COM1 + (*pcComNum - TEXT('1'))); CheckRadioButton(hDB, RB_110, RB_19200, RB_110 + (*pcSpeedNum - TEXT('0'))); #ifdef JAPAN //KKBUGFIX //#4311: 2/27/93: made buttons which are disapeared disable EnableWindow(GetDlgItem(hDB, RB_TONE), FALSE); EnableWindow(GetDlgItem(hDB, RB_PULSE), FALSE); EnableWindow(GetDlgItem(hDB, RB_COM1), FALSE); EnableWindow(GetDlgItem(hDB, RB_COM2), FALSE); EnableWindow(GetDlgItem(hDB, RB_COM3), FALSE); EnableWindow(GetDlgItem(hDB, RB_COM4), FALSE); EnableWindow(GetDlgItem(hDB, RB_110), FALSE); EnableWindow(GetDlgItem(hDB, RB_300), FALSE); EnableWindow(GetDlgItem(hDB, RB_1200), FALSE); EnableWindow(GetDlgItem(hDB, RB_2400), FALSE); EnableWindow(GetDlgItem(hDB, RB_4800), FALSE); EnableWindow(GetDlgItem(hDB, RB_9600), FALSE); EnableWindow(GetDlgItem(hDB, RB_19200), FALSE); #endif return(TRUE); case WM_COMMAND: pResultBuf = NULL; switch (LOWORD(wParam)) { case IDOK: /* DIAL it! */ if (fWriteWinIni) { WriteProfileString(szWindows, TEXT("Modem"), ModemInit); WriteProfileString(szWindows, TEXT("Prefix"), Prefix); if (fUsePrefix) WriteProfileString(szWindows, TEXT("UsePrefix"), TEXT("1")); else WriteProfileString(szWindows, TEXT("UsePrefix"), TEXT("0")); fWriteWinIni = FALSE; } /* check for valid number. */ /* Get the length. If 0, do nothing.*/ len=GetDlgItemText(hDB, ID_NUM, lpBuf, 40); if (len!=0) { /* Check for a valid number, give error if not valid */ if (!ParseNumber(lpBuf, buf, 40)) { LoadString(hIndexInstance, ECANTDIAL, cmdBuf, CharSizeOf(cmdBuf)); MessageBox(hDB, cmdBuf, szCardfile, MB_OK | MB_ICONEXCLAMATION); } else { /* note: this Alloc gets freeded by the caller */ if (pResultBuf = (TCHAR *)LocalAlloc(LPTR, ByteCountOf(40))) { if (fUsePrefix) len = GetDlgItemText(hDB, ID_PREFIX, pResultBuf, PRE_LEN-1); else len = 0; GetDlgItemText(hDB, ID_NUM, pResultBuf + len, 30); } } } /* fall through... */ case IDCANCEL: EndDialog(hDB, (int)pResultBuf); break; case ID_SETUP: #ifdef JAPAN //KKBUGFIX //#4311: 2/27/93: made buttons which are disapeared disable EnableWindow(GetDlgItem(hDB, RB_TONE), TRUE); EnableWindow(GetDlgItem(hDB, RB_PULSE), TRUE); EnableWindow(GetDlgItem(hDB, RB_COM1), TRUE); EnableWindow(GetDlgItem(hDB, RB_COM2), TRUE); EnableWindow(GetDlgItem(hDB, RB_COM3), TRUE); EnableWindow(GetDlgItem(hDB, RB_COM4), TRUE); EnableWindow(GetDlgItem(hDB, RB_110), TRUE); EnableWindow(GetDlgItem(hDB, RB_300), TRUE); EnableWindow(GetDlgItem(hDB, RB_1200), TRUE); EnableWindow(GetDlgItem(hDB, RB_2400), TRUE); EnableWindow(GetDlgItem(hDB, RB_4800), TRUE); EnableWindow(GetDlgItem(hDB, RB_9600), TRUE); EnableWindow(GetDlgItem(hDB, RB_19200), TRUE); #endif /* resize myself to fit in the setup controls */ SetFocus(GetDlgItem(hDB, ((*pcTonePulse == TEXT('T')) ? RB_TONE : RB_PULSE))); EnableWindow(GetDlgItem(hDB, ID_SETUP), FALSE); GetWindowRect(GetDlgItem(hDB, ID_BOX2), &rect); GetWindowRect(hDB, &rect1); MoveWindow(hDB, rect1.left, rect1.top, rect1.right-rect1.left, rect.bottom-rect1.top, TRUE); break; case ID_PREFIX: #if defined(WIN32) if (HIWORD(lParam) == EN_CHANGE) { #else if (HIWORD(lParam) == EN_CHANGE) { #endif GetDlgItemText(hDB, ID_PREFIX, Prefix, PRE_LEN-1); fWriteWinIni = TRUE; } break; case ID_USEPREFIX: fUsePrefix = !fUsePrefix; SendMessage(GetDlgItem(hDB, ID_USEPREFIX), BM_SETCHECK, fUsePrefix, 0L); break; case RB_TONE: case RB_PULSE: CheckRadioButton(hDB, RB_TONE, RB_PULSE, LOWORD(wParam)); *pcTonePulse = ((wParam == RB_TONE) ? TEXT('T') : TEXT('P')); fWriteWinIni = TRUE; break; case RB_COM1: case RB_COM2: case RB_COM3: case RB_COM4: CheckRadioButton(hDB, RB_COM1, RB_COM4, LOWORD(wParam)); *pcComNum= (TCHAR) ((wParam - RB_COM1) + TEXT('1')); fWriteWinIni = TRUE; break; case RB_110: case RB_300: case RB_1200: case RB_2400: case RB_4800: case RB_9600: case RB_19200: CheckRadioButton(hDB, RB_110, RB_19200, LOWORD(wParam)); *pcSpeedNum= (TCHAR) ((wParam - RB_110) + TEXT('0')); fWriteWinIni = TRUE; break; default: return(FALSE); } return(TRUE); default: return(FALSE); } } /*************************************************************************** * GetPhoneNumber(pchBuf, cchMax) * * purpose: * look for phone numbers in: * 1) the header line of the card * 2) the text of the card itself, starting first with the selection * * params: * IN cchMax limit pchBuf to this # chars * OUT pchBuf gets the dialing string if * * used by: * this is called by the dailing dialog function * * uses: * ParseNumber() to find phone numbers * * returns: * nothing of interest * ***************************************************************************/ NOEXPORT void NEAR GetPhoneNumber( LPTSTR pchBuf, int cchMax) { LPCARDHEADER lpCard; int fFound = FALSE; unsigned long lSelection; lSelection = SendMessage(hEditWnd, EM_GETSEL, 0, 0L); /* first look in card header */ if (HIWORD(lSelection) == LOWORD(lSelection)) { /* no selection search card */ lpCard = (LPCARDHEADER) GlobalLock(hCards) + iFirstCard; fFound = ParseNumber(lpCard->line, pchBuf, cchMax); GlobalUnlock(hCards); } /* now look in the text of the card, first at the selection */ if (!fFound) { GetWindowText(hEditWnd, szText, CARDTEXTSIZE); if (HIWORD(lSelection) != LOWORD(lSelection)) { lstrcpy(szText, szText+LOWORD(lSelection)); *(szText + (HIWORD(lSelection) - LOWORD(lSelection))) = (TCHAR) 0; } fFound = ParseNumber(szText, pchBuf, cchMax); } if (!fFound) *pchBuf = (TCHAR) 0; } /*************************************************************************** * BOOL ParseNumber(lpSrc, pchBuf, cchMax) * * purpose: * look for phone number strings in lpSrc (return the first one found) * * params: * IN lpSrc string to search for numbers * OUT pchBuf place to put result * IN cchMax limit # chars in pchBuf * * used by: * GetPhoneNumber(), and from Autodial Dialog box. * * uses: * * returns: * BOOL TRUE if something found, FALSE otherwise * * restrictions: * as of now this is a very stupid function. a valid number has to * be 4 chars min for example. a number matching scheme should be * implemented that looks for things like ###-#### (###) ###-#### or * ####. Also this function returns the first one found. It should * probally enumerate all that are found. * ***************************************************************************/ NOEXPORT BOOL NEAR ParseNumber( LPTSTR lpSrc, TCHAR *pchBuf, int cchMax) { LPTSTR lpchTmp; LPTSTR lpchEnd; LPTSTR pchTmp; int fValid = FALSE; TCHAR ch; for (lpchTmp = lpSrc; *lpchTmp; lpchTmp++) { pchTmp = pchBuf; lpchEnd = lpchTmp; while ((pchTmp - pchBuf) < cchMax) { ch = *lpchEnd++; if (ch == TEXT('-')) { *pchTmp++ = ch; } else { FoldStringW( MAP_FOLDDIGITS, &ch, 1, &ch, 1 ); // handle odd number characters! if ((ch >= TEXT('0') && ch <= TEXT('9')) || ch == TEXT('@') || ch == TEXT(',') || ch == TEXT('(') || ch == TEXT(')') || ch == TEXT('*') || ch == TEXT('#')) { if (ch >= TEXT('0') && ch <= TEXT('9')) fValid = TRUE; *pchTmp++ = ch; } /* Allow a space after an area code in parens. */ else if (!(ch ==TEXT(' ') && *(pchTmp - 1) == TEXT(')') )) { *pchTmp = (TCHAR) 0; break; } } } if (fValid && ((pchTmp - pchBuf) > 3)) /* allow 4 digit numbers */ return(TRUE); } return(FALSE); } /* * dial the phone with the phone number in pchNumber */ void DoDial( LPTSTR pchNumber) { HFILE cid; TCHAR szComm[5]; TCHAR cmdBuf[MAXDIALSIZE*2]; char aCmdBuf[MAXDIALSIZE]; // ascii version of cmdBuf int cch; // length of unicode to write int acch; // length of ascii to write COMSTAT ComStatInfo; long oldtime; HCURSOR hPrevCursor; lstrcpy(szComm, TEXT("COMx")); szComm[3] = *pcComNum; cid = CreateFile( szComm, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ) ; if (cid != (HFILE)-1) { SetPortState(cid); GetCommError(cid, &ComStatInfo); /* Dial the number */ cch = MakeDialCmd(cmdBuf, MAXDIALSIZE, pchNumber); acch= WideCharToMultiByte( CP_ACP, // use ascii code page 0, // no flags cmdBuf, // input buffer cch, // buffer length aCmdBuf, // output buffer MAXDIALSIZE, // output buffer size NULL, // use system default char NULL); // and don't tell me if you used it while (!WriteFile(cid, aCmdBuf, acch, &acch, NULL)) { GetCommError(cid, &ComStatInfo); FlushFileBuffers(cid) ; } /* wait for dialing to complete */ /* Set the HourGlass cursor while waiting */ /* Fix for Bug #6402 --SANKAR-- 12-1-89 */ hPrevCursor = SetCursor(hWaitCurs); oldtime = GetCurrentTime(); for(;;) { GetCommError(cid, &ComStatInfo); if (GetCurrentTime() - oldtime > 3000) /* 30 seconds */ { /* Restore the original cursor shape */ SetCursor(hPrevCursor); IndexOkError(ENOMODEM); goto DoneDialing; } if (!ComStatInfo.cbOutQue) break; } /* Restore the original cursor shape */ SetCursor(hPrevCursor); FlushFileBuffers(cid) ; LoadString(hIndexInstance, IPICKUPPHONE, cmdBuf, CharSizeOf(cmdBuf)); MessageBox(hIndexWnd, cmdBuf, szCardfile, MB_OK); while(!WriteFile(cid, HANGUP_CMD, sizeof(HANGUP_CMD)-1, &cch, NULL)) { GetCommError(cid, &ComStatInfo); FlushFileBuffers(cid) ; } while(TRUE) { GetCommError(cid, &ComStatInfo); if (!ComStatInfo.cbOutQue) break; } DoneDialing: CloseHandle(cid) ; } else { LoadString(hIndexInstance, ECANTDIAL, cmdBuf, CharSizeOf(cmdBuf)); MessageBox(hIndexWnd, cmdBuf, szCardfile, MB_OK | MB_ICONEXCLAMATION); } } NOEXPORT void NEAR SetPortState( HFILE cid) { DCB dcb; TCHAR szPortInfo[30]; TCHAR *pch; TCHAR szPort[6]; if (GetCommState(cid, &dcb)!=-1) { switch (*pcSpeedNum) { case TEXT('0'): dcb.BaudRate = 110; break; case TEXT('1'): dcb.BaudRate = 300; break; case TEXT('2'): dcb.BaudRate = 1200; break; case TEXT('3'): dcb.BaudRate = 2400; break; case TEXT('4'): dcb.BaudRate = 4800; break; case TEXT('5'): dcb.BaudRate = 9600; break; case TEXT('6'): dcb.BaudRate = 19200; break; } lstrcpy(szPort, TEXT("COMx:")); #if defined(WIN32) szPort[3] = *pcComNum ; #else szPort[3] = TEXT('1') + cid; #endif GetProfileString(TEXT("Ports"), szPort, TEXT("300,n,8,1"), szPortInfo, CharSizeOf(szPortInfo)); for (pch = szPortInfo; *pch && *pch != TEXT(','); ++pch) ; while(*pch == TEXT(',') || *pch == TEXT(' ')) pch++; dcb.Parity = *pch == TEXT('n') ? NOPARITY : (*pch == TEXT('o') ? ODDPARITY : EVENPARITY); if (*pch) pch++; while(*pch == TEXT(',') || *pch == TEXT(' ')) pch++; dcb.ByteSize = *pch == TEXT('8') ? 8 : 7; if (*pch) pch++; while (*pch == TEXT(',') || *pch == TEXT(' ')) pch++; dcb.StopBits = *pch == TEXT('2') ? 2 : 0; #if !defined(WIN32) dcb.fDtrDisable = FALSE; /* use DTR for hangup */ SetCommState(&dcb); #else dcb.fDtrControl = FALSE; /* use DTR for hangup */ SetCommState(cid, &dcb); #endif } } /* * Create a string for dialing Hayes compatable modems. * * in: * cchMax - max number of chars to stuff into pBuf * pchNumber - number string to build dialing stuff out of * * out: * pBuf - output buffer * * returns: * the length of the command built */ NOEXPORT int NEAR MakeDialCmd( TCHAR *pBuf, int cchMax, LPTSTR pchNumber) { LPTSTR pch1; LPTSTR pch2; int cb; TCHAR szCmd[MAXDIALSIZE]; /* build it here */ TCHAR ch; lstrcpy(szCmd, TEXT("ATDx")); /* dialing prefix */ szCmd[3] = *pcTonePulse; /* pulse or tone dialing */ pch2 = szCmd + 4; /* use this to fill the string */ for (pch1 = pchNumber; ch = *pch1++; ) { /* copy only these characters */ if ((ch >= TEXT('0') && ch <= TEXT('9')) || (ch == TEXT(',')) || (ch == TEXT('#')) || (ch == TEXT('*'))) *pch2++ = ch; else if (ch == TEXT('@')) /* delay */ { *pch2++ = TEXT(','); *pch2++ = TEXT(','); *pch2++ = TEXT(','); } else if (ch == TEXT('P') || ch == TEXT('T')) /* manual switch to Tone or Pulse */ { *pch2++ = TEXT('D'); *pch2++ = ch; } } *pch2++ = TEXT(';'); /* terminate the string */ *pch2++ = 0x0d; *pch2 = 0; cb = lstrlen(szCmd); if (cchMax < pch2 - szCmd) { szCmd[cchMax] = (TCHAR) 0; cb = cchMax; } lstrcpy(pBuf, szCmd); return cb; }