⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ansiterm.cpp

📁 DOS下采用中断接收数据的串口通讯的例子,很难找到的好东西!
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ***************** START OF ANSITERM.CPP *****************
//
//
// This file contains all the code to support the AnsiTerm 
// class, which is a terminal emulation class that supports 
// the IBM PC ANSI.SYS control sequences.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "terminal.h"
#include "ansiterm.h"

// These two defines can be used to help debug the terminal 
// emulation class.  DEBUG is used to split the screen and 
// provide a bottom window that displays escape sequences as 
// they are parsed.  KEYBOARD_FAKE lets you input escape 
// sequences from the keyboard.

//#define KEYBOARD_FAKE
#define DEBUG

//
// The debug macro in this file is only meant to be used
// when debugging in MS-DOS. A bit of additional code would
// need to be written under Windows to create a debug window.
// So we turn off the debug macro if we are building a 
// Windows program.
//
#if defined( _WINDOWS ) && defined( DEBUG )
#undef DEBUG
#endif

#if defined( DEBUG ) 
#include "textwind.h"
BaseWindow *debug_window;
#endif

// This is a list of keyboard mappings that are defined when the
// emulator first starts.  These key mappings can be remapped
// dynamically, although this class does not support the feature.
// These values are loaded into the mapping arrays when the
// constructor executes.

struct key_strings {
    int key_value;
    char *translation;
} initial_key_translations[] = { { LEFT,        "\x1b[D"  },
                                 { RIGHT,       "\x1b[C"  },
                                 { UP,          "\x1b[A"  },
                                 { DOWN,        "\x1b[B"  },
                                 { HOME,        "\x1b[H"  },
                                 { END,         "\x1b[F"  },
                                 { PGUP,        "\x1b[I"  },
                                 { PGDN,        "\x1b[G"  },
                                 { INSERT,      "\x1b[L"  },
                                 { F1,          "\x1b[M"  },
                                 { F2,          "\x1b[N"  },
                                 { F3,          "\x1b[O"  },
                                 { F4,          "\x1b[P"  },
                                 { F5,          "\x1b[Q"  },
                                 { F6,          "\x1b[R"  },
                                 { F7,          "\x1b[S"  },
                                 { F8,          "\x1b[T"  },
                                 { F9,          "\x1b[U"  },
                                 { F10,         "\x1b[V"  },
                                 { SHIFT_F1,    "\x1b[Y"  },
                                 { SHIFT_F2,    "\x1b[Z"  },
                                 { SHIFT_F3,    "\x1b[a"  },
                                 { SHIFT_F4,    "\x1b[b"  },
                                 { SHIFT_F5,    "\x1b[c"  },
                                 { SHIFT_F6,    "\x1b[d"  },
                                 { SHIFT_F7,    "\x1b[e"  },
                                 { SHIFT_F8,    "\x1b[f"  },
                                 { SHIFT_F9,    "\x1b[g"  },
                                 { SHIFT_F10,   "\x1b[h"  },
                                 { CONTROL_F1,  "\x1b[k"  },
                                 { CONTROL_F2,  "\x1b[l"  },
                                 { CONTROL_F3,  "\x1b[m"  },
                                 { CONTROL_F4,  "\x1b[n"  },
                                 { CONTROL_F5,  "\x1b[o"  },
                                 { CONTROL_F6,  "\x1b[p"  },
                                 { CONTROL_F7,  "\x1b[q"  },
                                 { CONTROL_F8,  "\x1b[r"  },
                                 { CONTROL_F9,  "\x1b[s"  },
                                 { CONTROL_F10, "\x1b[t"  },
                                 { ALT_F1,      "\x1b[w"  },
                                 { ALT_F2,      "\x1b[x"  },
                                 { ALT_F3,      "\x1b[y"  },
                                 { ALT_F4,      "\x1b[z"  },
                                 { ALT_F5,      "\x1b[@"  },
                                 { ALT_F6,      "\x1b[["  },
                                 { ALT_F7,      "\x1b[\\" },
                                 { ALT_F8,      "\x1b[]"  },
                                 { ALT_F9,      "\x1b[^"  },
                                 { ALT_F10,     "\x1b[_"  },
                                 { 0,           0         }
                               };

//
// The constructor sets up the pointers to the port and the 
// TextWindow objects.  It puts the window in a predefined 
// state, allocates the memory for the ansi string parsing 
// storage, then initializes the key maps.  If the DEBUG macro 
// is turned on, the screen is split and a second debug text 
// window is opened.
//

AnsiTerminal::AnsiTerminal( RS232 &p, BaseWindow &w ) 
    : Terminal( p, w )
{
    int key;
    char *translation;

    window->Clear();
    window->Goto();
    window->SetWrap( 1 );
    saved_row = 0;
    saved_col = 0;
    for ( int i = 0 ; i < 15 ; i++ )
        ansi_parms[ i ] = new char[ 81 ];
    ansi_parms[ 15 ] = 0;
    keys = new char *[ 256 ];
    extended_keys = new char *[ 256 ];
    for ( i = 0 ; i < 256 ; i++ ) {
        if ( keys )
            keys[ i ] = 0;
        if ( extended_keys )
            extended_keys[ i ] = 0;
    }
    for ( i = 0;
          initial_key_translations[ i ].translation != 0;
          i++ ) 
    {
        key = initial_key_translations[ i ].key_value;
        translation = initial_key_translations[ i ].translation;
        if ( extended_keys && key > 256 )
            extended_keys[ ( key >> 8 ) & 0xff ] = translation;
        else if ( keys )
            keys[ key ] = translation;
    }
#if defined( DEBUG ) 
    Set43LineMode( 1 );
    debug_window = new TextWindow( 25, 0, 80, 18 );
    debug_window->SetWrap( 1 );
#endif
}

//
// ReadPort filters port input for the end application.  If 
// it sees the first character of an escape sequence, it gets 
// parsed, and the application never sees it.  Normal characters 
// get passed straight back to the application.  Note that if 
// the KEYBOARD_FAKE macro is defined, input comes from the 
// keyboard instead of the port.
//
int AnsiTerminal::ReadPort( void )
{
     int c;

#ifdef KEYBOARD_FAKE
     while ( ( c = window->ReadKey() ) == 0 )
         ;
     if ( c == F10 )
         return RS232_ERROR;
#else
     c = port->Read();
#endif
     if ( c == ESC ) {
         parse();
         return RS232_TIMEOUT;
     }
     return c;
}

//
// The destructor for an AnsiTerminal objects just has to free 
// up the memory allocated for the ANSI parser.  If DEBUG is 
// turned on, the screen is restored to 25 line mode.  

AnsiTerminal::~AnsiTerminal( void )
{
    for ( int i = 0 ; i < 15 ; i++ )
        delete[] ansi_parms[ i ];
    delete[] keys;
    delete[] extended_keys;
#if defined( DEBUG ) && !defined( _WINDOWS )
    Set43LineMode( 0 );
#endif
}

// This is the actual parser that reads in ANSI strings.  It
// is just a fairly simple state machine, that sits in a loop
// reading in characters until it detects the end of an ANSI
// sequence.  When it is done, the ansi_parms[] array holds a 
// list of numeric and quoted strings, and parm_count is the 
// index to the last valid string.  Error handling is 
// non-existent, if anything odd happens the routine just returns 
// with a failure.

int AnsiTerminal::parse_ansi_string( void )
{
    int index;
    enum { READY_TO_READ,
           READING_DIGITS,
           READING_STRING,
           DONE_WITH_STRING } scan_state;
    int c;

    parm_count = 0;
    index = 0;

    for ( int i = 0 ; i < 15 ; i++ )
        if ( ansi_parms[ i ] != 0 )
            memset( ansi_parms[ i ], 0, 81 );
#ifdef KEYBOARD_FAKE
    while ( ( c = window->ReadKey() ) == 0 )
        ;
#else
    c = port->Read( 200 );
#endif
    if ( c != '[' )
        return 0;

    scan_state = READY_TO_READ;
    for ( ; ; ) {
        if ( index >= 80 || ansi_parms[ parm_count ] == 0 )
            return 0;
#ifdef KEYBOARD_FAKE
        while ( ( c = window->ReadKey() ) == 0 )
            ;
#else
        c = port->Read( 1000 );
#endif
        if ( c < 0 )
            return 0;
        switch ( scan_state ) {
          case READY_TO_READ:
            if ( parm_count == 0 && ( c == '=' || c == '?' ) )
              ansi_parms[ parm_count++ ][ 0 ] = (char) c;
            else if ( c == '"' ) {
              scan_state = READING_STRING;
              ansi_parms[ parm_count ][ index++ ] = (char) c;
            } else if ( c >= '0' && c <= '9' ) {
              ansi_parms[ parm_count ][ index++ ] = (char) c;
              scan_state = READING_DIGITS;
            } else if ( c == ';' ) {
              parm_count++;
              index = 0;
            } else {
              ansi_parms[ parm_count ][ index ] = (char) c;
              return 1;
            }
            break;
          case READING_DIGITS :
            if ( c == ';' ) {
              parm_count++;
              index = 0;
              scan_state = READY_TO_READ;
            } else if ( c >= '0' && c <='9' )
              ansi_parms[ parm_count ][ index++ ] = (char) c;
            else {
              ansi_parms[ ++parm_count ][ 0 ] = (char) c;
              return 1;
            }
            break;
          case READING_STRING :
            if ( c == '"' )
              scan_state = DONE_WITH_STRING;
            ansi_parms[ parm_count ][ index++ ] = (char) c;
            break;
          case DONE_WITH_STRING :
            if ( c == ';' ) {
              parm_count++;
              index = 0;
              scan_state = READY_TO_READ;
            } else {
              ansi_parms[ ++parm_count ][ 0 ] = (char) c;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -