示例#1
0
void
H19::processCharacter(char ch)
{
    // mask off the high bit just in case, the real H19 would not have it set.
    ch &= 0x7f;

    if (mode_m == Normal)
    {
        switch (ch)
        {
            case ascii::NUL:
            case ascii::SOH:
            case ascii::STX:
            case ascii::ETX:
            case ascii::EOT:
            case ascii::ENQ:
            case ascii::ACK:
            case ascii::VT:
            case ascii::FF:
            case ascii::SO:
            case ascii::SI:
            case ascii::DLE:
            case ascii::DC1:
            case ascii::DC2:
            case ascii::DC3:
            case ascii::DC4:
            case ascii::NAK:
            case ascii::SYN:
            case ascii::ETB:
            case ascii::EM:
            case ascii::SUB:
            case ascii::FS:
            case ascii::GS:
            case ascii::RS:
            case ascii::US:
            case ascii::DEL:
                // From manual, these characters are not processed by the terminal
                break;

            case ascii::BEL: // Rings the bell.
                /// \todo - implement ringing bell.
                consoleLog("<BEL>");
                break;

            case ascii::BS: // Backspace
                consoleLog("<BS>");
                processBS();
                break;

            case ascii::HT: // Horizontal Tab
                consoleLog("<TAB>");
                processTAB();
                break;

            case ascii::LF: // Line Feed
                processLF();

                if (autoCR_m)
                {
                    processCR();
                }

                consoleLog("\n");
                break;

            case ascii::CR: // Carriage Return
                processCR();

                if (autoLF_m)
                {
                    processLF();
                }

                break;

            case ascii::CAN: // Cancel.
                break;

            case ascii::ESC: // Escape
                mode_m = Escape;
                consoleLog("<ESC>");
                break;

            default:
                // if Printable character display it.
#if CONSOLE_LOG
                fprintf(console_out, "%c", ch);
#endif
                displayCharacter(ch);
                break;
        }
    }
    else if (mode_m == Escape)
    {
        // Assume we go back to Normal, so only the few that don't need to set the mode.
        mode_m = Normal;

        switch (ch)
        {
            case ascii::CAN: // CAN - Cancel
                // return to Normal mode, already set.
                break;

            case ascii::ESC: // Escape
                // From the ROM listing, stay in this mode.
                mode_m = Escape;
                break;

            // Cursor Functions

            case 'H': // Cursor Home
                posX_m    = posY_m = 0;
                updated_m = true;
                break;

            case 'C': // Cursor Forward
                cursorForward();
                break;

            case 'D':        // Cursor Backward
                processBS(); // same processing as cursor backward
                break;

            case 'B': // Cursor Down
                cursorDown();
                break;

            case 'A': // Cursor Up
                cursorUp();
                break;

            case 'I': // Reverse Index
                reverseIndex();
                break;

            case 'n': // Cursor Position Report
                cursorPositionReport();
                break;

            case 'j': // Save cursor position
                saveCursorPosition();
                break;

            case 'k': // Restore cursor position
                restoreCursorPosition();
                break;

            case 'Y': // Direct Cursor Addressing
                mode_m = DCA_1;
                break;

            // Erase and Editing

            case 'E': // Clear Display
                clearDisplay();
                break;

            case 'b': // Erase Beginning of Display
                eraseBOD();
                break;

            case 'J': // Erase to End of Page
                eraseEOP();
                break;

            case 'l': // Erase entire Line
                eraseEL();
                break;

            case 'o': // Erase Beginning Of Line
                eraseBOL();
                break;

            case 'K': // Erase To End Of Line
                eraseEOL();
                break;

            case 'L': // Insert Line
                insertLine();
                break;

            case 'M': // Delete Line
                deleteLine();
                break;

            case 'N': // Delete Character
                deleteChar();
                break;

            case '@': // Enter Insert Character Mode
                insertMode_m = true;
                break;

            case 'O': // Exit Insert Character Mode
                insertMode_m = false;
                break;

            // Configuration

            case 'z': // Reset To Power-Up Configuration
                reset();
                break;

            case 'r': // Modify the Baud Rate
                /// \todo - determine if we should support this.
                debugss(ssH19, ERROR, "Error Unimplemented Modify Baud\n");
                break;

            case 'x': // Set Mode
                mode_m = SetMode;
                break;

            case 'y': // Reset Mode
                mode_m = ResetMode;
                break;

            case '<': // Enter ANSI Mode
                /// \todo - implement ANSI mode.
                // ROM - just sets the mode
                debugss(ssH19, ERROR, "Error Entering ANSI mode - unsupported\n");
                break;

            // Modes of operation

            case '[': // Enter Hold Screen Mode
                holdScreen_m = true;
                break;

            case '\\': // Exit Hold Screen Mode
                holdScreen_m = false;
                break;

            case 'p': // Enter Reverse Video Mode
                reverseVideo_m = true;
                break;

            case 'q': // Exit Reverse Video Mode
                reverseVideo_m = false;
                break;

            case 'F': // Enter Graphics Mode
                graphicMode_m = true;
                break;

            case 'G': // Exit Graphics Mode
                graphicMode_m = false;
                break;

            case 't': // Enter Keypad Shifted Mode
                keypadShifted_m = true;
                break;

            case 'u': // Exit Keypad Shifted Mode
                // ROM - just sets the mode
                keypadShifted_m = false;
                break;

            case '=': // Enter Alternate Keypad Mode
                // ROM - just sets the mode
                keypadShifted_m = true;
                break;

            case '>': // Exit Alternate Keypad Mode
                // ROM - just sets the mode
                keypadShifted_m = false;
                break;

            // Additional Functions

            case '}': // Keyboard Disable
                /// \todo - determine whether to do this.
                keyboardEnabled_m = false;
                break;

            case '{': // Keyboard Enable
                keyboardEnabled_m = true;
                break;

            case 'v': // Wrap Around at End Of Line
                wrapEOL_m = true;
                break;

            case 'w': // Discard At End Of Line
                wrapEOL_m = false;
                break;

            case 'Z': // Identify as VT52 (Data: ESC / K)
                debugss(ssH19, ERROR, "Identify request\n");
                sendData(ascii::ESC);
                sendData('/');
                sendData('K');
                break;

            case ']': // Transmit 25th Line
                transmitLine25();
                break;

            case '#': // Transmit Page
                transmitPage();
                break;

            default:
                debugss(ssH19, WARNING, "Unhandled ESC: %d\n", ch);
                /// \todo - verify this is how the H19 ROM does it.
                break;
        }
    }
    else if (mode_m == SetMode)
    {
        mode_m = Normal;

        switch (ch)
        {
            case '1': // Enable 25th line
                // From the ROM, it erases line 25 on the enable, but here we erase on the disable.
                line25_m = true;
                break;

            case '2': // No key click
                keyClick_m = true;
                break;

            case '3': // Hold screen mode
                holdScreen_m = true;
                break;

            case '4': // Block Cursor
                cursorBlock_m = true;
                updated_m     = true;
                break;

            case '5': // Cursor Off
                cursorOff_m = true;
                updated_m   = true;
                break;

            case '6': // Keypad Shifted
                keypadShifted_m = true;
                break;

            case '7': // Alternate Keypad mode
                altKeypadMode_m = true;
                break;

            case '8': // Auto LF
                autoLF_m = true;
                break;

            case '9': // Auto CR
                autoCR_m = true;
                break;

            default:
                /// \todo Need to process ch as if none of this happened...
                debugss(ssH19, WARNING, "Invalid set Mode: %c\n", ch);
                break;
        }
    }
    else if (mode_m == ResetMode)
    {
        mode_m = Normal;

        switch (ch)
        {
            case '1': // Disable 25th line
                eraseLine(rowsMain_c);
                line25_m  = false;
                updated_m = true;
                break;

            case '2': // key click
                keyClick_m = false;
                break;

            case '3': // Hold screen mode
                holdScreen_m = false;
                break;

            case '4': // Block Cursor
                cursorBlock_m = false;
                updated_m     = true;
                break;

            case '5': // Cursor On
                cursorOff_m = false;
                updated_m   = true;
                break;

            case '6': // Keypad Unshifted
                keypadShifted_m = false;
                break;

            case '7': // Exit Alternate Keypad mode
                altKeypadMode_m = false;
                break;

            case '8': // No Auto LF
                autoLF_m = false;
                break;

            case '9': // No Auto CR
                autoCR_m = false;
                break;

            default:
                /// \todo Need to process ch as if none of this happened...
                debugss(ssH19, WARNING, "Invalid reset Mode: %c\n", ch);
                break;
        }
    }
    else if (mode_m == DCA_1)
    {
        // From actual H19, once the line is specified, the cursor
        // immediately moves to that line, so no need to save the
        // position and wait for the entire command.
        /// \todo verify that this is the same on newer H19s.
        if (ch == ascii::CAN)
        {
            // cancel
            mode_m = Normal;
        }
        else
        {
            // \todo handle error conditions

            int pos = ch - 31;

            // verify valid Position
            if (((pos > 0) && (pos < (signed) rows_c)) || ((pos == (signed) rows_c) && (line25_m)))
            {
                posY_m = pos - 1;
            }
            else
            {
                /// \todo check to see how a real h19 handles this.
                debugss(ssH19, INFO, "DCA invalid Y: %d\n", pos);
            }

            mode_m = DCA_2;
        }
    }
    else if (mode_m == DCA_2)
    {
        if (ch == ascii::CAN)
        {
            // cancel
            mode_m = Normal;
        }
        else
        {
            int pos = ch - 31;

            if ((pos > 0) && (pos < 81))
            {
                posX_m = pos - 1;
            }
            else
            {
                posX_m = (cols_c - 1);
            }

            updated_m = true;
            mode_m    = Normal;
        }
    }
}
示例#2
0
// dest: MUST already contain a string, even if empty.
// maxLineLength: Must include room for terminating NUL.
// Returns TRUE if the user pressed Enter, FALSE if Break.
//
byte getLineFromUser(char *dest, word maxLineLength, word initIndex)
{
    saveCursorPosition();

    word index = initIndex;  // offset of cursor in 'dest'

    // Print the existing string, if any.
    //
    word curLen = strlen(dest);
    putstr(dest, curLen);

    // Put the cursor at 'initIndex'.
    //
    restoreCursorPosition();
    advanceCursor(initIndex);

    char key;

    for (;;)
    {
        animateCursor();

        key = (char) tolower(inkey());
        if (!key)
            continue;

        if (key == '\r' || key == '\n' || key == BREAK_CHAR)  // if Enter (CoCo or PC) or Break
        {
            dest[curLen] = 0;
            break;
        }

        removeCursor();

        if (key == CLEAR_CHAR)  // if backspace
        {
            if (index > 0)
            {
                word numCharsToMove = curLen - index;
                moveBackwardOneByte(dest + index, numCharsToMove);
                --index;
                --curLen;
                putchar('\b');
                byte finalX = textPosX, finalY = textPosY;
                putstr(dest + index, numCharsToMove);
                putchar(' ');  // erase last char from screen
                moveCursor(finalX, finalY);  // place cursor at erased char
            }
            continue;
        }

        if (key == SHIFT_CLEAR_CHAR)  // if delete
        {
            if (index < curLen)
            {
                word numCharsToMove = curLen - index - 1;
                moveBackwardOneByte(dest + index + 1, numCharsToMove);
                --curLen;
                byte finalX = textPosX, finalY = textPosY;
                putstr(dest + index, numCharsToMove);
                putchar(' ');  // erase last char from screen
                moveCursor(finalX, finalY);  // place cursor at erased char
            }
            continue;
        }

        if (key == LEFT_CHAR)  // if move cursor left
        {
            if (index > 0)
            {
                --index;
                putchar('\b');
            }
            continue;
        }

        if (key == RIGHT_CHAR)  // if move cursor right
        {
            if (index < curLen)
            {
                ++index;
                advanceCursor(1);
            }
            continue;
        }

        if (key == KILL_LINE_CHAR)  // if shift-backspace
        {
            for (word i = 0; i < index; ++i)  // back up cursor to beginning
                putchar('\b');
            byte finalX = textPosX, finalY = textPosY;
            for (word i = 0; i < curLen; ++i)  // erase entire line
                putchar(' ');
            moveCursor(finalX, finalY);  // put cursor at beginning
            index = 0;
            curLen = 0;
            continue;
        }

        if (key < ' ' || key >= 127)
            continue;  // ignore invalid characters

        if (curLen < maxLineLength - 1)  // if still room
        {
            moveForwardOneByte(dest + index, curLen + 1 - index);  // include terminating NUL
            dest[index] = key;
            ++curLen;
            saveCursorPosition();
            putstr(dest + index, curLen - index);
            restoreCursorPosition();
            advanceCursor(1);
            ++index;
        }
    }

    removeCursor();

    return key != BREAK_CHAR;
}