/* OpenDoors Online Software Programming Toolkit * (C) Copyright 1991 - 1999 by Brian Pirie. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * File: ODAuto.c * * Description: Implements od_autodetect() for automatic detection of * terminal emulation supported by remote system. * * Revisions: Date Ver Who Change * --------------------------------------------------------------- * Oct 13, 1994 6.00 BP New file header format. * Oct 14, 1994 6.00 BP Standardized coding style. * Dec 31, 1994 6.00 BP Use new millisecond timer functions. * Nov 12, 1995 6.00 BP 32-bit portability. * Nov 13, 1995 6.00 BP Fixed non-functioning RIP autodetect. * Nov 16, 1995 6.00 BP Removed oddoor.h, added odcore.h. * Dec 12, 1995 6.00 BP Added entry, exit and kernel macros. * Dec 30, 1995 6.00 BP Added ODCALL for calling convention. * Feb 19, 1996 6.00 BP Changed version number to 6.00. * Mar 03, 1996 6.10 BP Begin version 6.10. * Aug 10, 2003 6.23 SH *nix support */ #define BUILDING_OPENDOORS #include #include #include "OpenDoor.h" #include "ODStr.h" #include "ODTypes.h" #include "ODGen.h" #include "ODPlat.h" #include "ODCore.h" #include "ODKrnl.h" /* Private function prototypes. */ static char ODWaitNoCase(char *pszWaitFor, tODMilliSec WaitTime); /* Number of attempts and timeout values for testing each terminal emulation */ /* protocol. */ #define ANSI_TRIES 1 #define ANSI_WAIT 660 /* Time in milliseconds. */ #define RIP_TRIES 1 #define RIP_WAIT 660 /* Time in milliseconds. */ /* Strings to use for autodetection. */ #define ANSI_QUERY "\x1b[6n\r \r" #define ANSI_RESPONSE "\x1b[" #define RIP_QUERY "\r\x1b[!\r \r" #define RIP_RESPONSE "RIP" /* Maximum number of characters to match with _waitnocase(). */ #define MATCH_LEN 3 /* ---------------------------------------------------------------------------- * od_autodetect() * * Determines the terminal emulation capabilities of the remote communications * software, when possible. Turns on ANSI and/or RIP modes if they are * supported by the remote system. * * Parameters: nFlags - Currently unused. * * Return: void */ ODAPIDEF void ODCALL od_autodetect(INT nFlags) { INT nCount; /* Log function entry if running in trace mode. */ TRACE(TRACE_API, "od_autodetect()"); /* Initialize OpenDoors if it hasn't aready been done. */ if(!bODInitialized) od_init(); OD_API_ENTRY(); /* Temporary code that will be optimized out, which prevents a compiler */ /* warning from being generated for the currently unused flags parameter. */ (void)nFlags; /* If operating in local mode, turn on ANSI mode, but not RIP. */ if(od_control.baud == 0) { od_control.user_ansi = TRUE; OD_API_EXIT(); return; } /* If user_ansi is not set, attempt to determine ANSI capabilities. */ if(!od_control.user_ansi) { /* Clear inbound keyboard buffer. */ od_clear_keybuffer(); /* Try twice to test ANSI capabilities. */ for(nCount = 0; nCount < ANSI_TRIES; ++nCount) { /* Send a string that an ANSI capable terminal will usually */ /* respond to. */ od_disp(ANSI_QUERY, strlen(ANSI_QUERY), FALSE); /* Wait for response expected from an ANSI terminal, for up to */ /* 12/18.2 second. */ if(ODWaitNoCase(ANSI_RESPONSE, ANSI_WAIT)) { /* If expected sequence was received, turn on ANSI mode and */ /* exit the loop. */ od_control.user_ansi = TRUE; break; } } od_clear_keybuffer(); } /* If user_rip is not set, attempt to determine RIP capabilities. */ if(!od_control.user_rip) { /* Clear inbound keyboard buffer. */ od_clear_keybuffer(); /* Try twice to test RIP capabilities. */ for(nCount = 0; nCount < RIP_TRIES; ++nCount) { /* Send a string that a RIP capable terminal will usually */ /* respond to. */ od_disp(RIP_QUERY, strlen(RIP_QUERY), FALSE); /* Wait for response expected from a RIP terminal. */ if(ODWaitNoCase(RIP_RESPONSE, RIP_WAIT)) { /* If expected sequence was received, turn on RIP mode and */ /* exit the loop. */ od_control.user_rip = TRUE; break; } } od_clear_keybuffer(); } OD_API_EXIT(); } /* ---------------------------------------------------------------------------- * ODWaitNoCase() *** PRIVATE FUNCTION *** * * Waits up to the specified maximum time for a specified string to be sent * from the remote system. String matching is not case sensitive. * * Parameters: pszWaitFor - String to wait for. * * WaitTime - Maximum time, in milliseconds, to wait. * * Return: TRUE on success, FALSE on failure. */ static char ODWaitNoCase(char *pszWaitFor, tODMilliSec WaitTime) { tODTimer Timer; char szReceived[MATCH_LEN + 1]; int nCount; char chReceived; int nMatchChars = MIN(MATCH_LEN, strlen(pszWaitFor)); ASSERT(pszWaitFor != NULL); ASSERT(strlen(pszWaitFor) != 0); ASSERT(WaitTime >= 0); ODTimerStart(&Timer, WaitTime); for(nCount = 0; nCount <= MATCH_LEN; ++nCount) { szReceived[nCount] = '\0'; } do { if((chReceived = od_get_key(FALSE)) != 0) { for(nCount = 0; nCount < MATCH_LEN - 1; ++ nCount) { szReceived[nCount] = szReceived[nCount + 1]; } szReceived[MATCH_LEN - 1] = chReceived; if(strnicmp(szReceived + (MATCH_LEN - nMatchChars), pszWaitFor, nMatchChars) == 0) { return(TRUE); } } } while(!ODTimerElapsed(&Timer)); return(FALSE); }