/* * Copyright (C) 2006 Michael Brown . * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or any later version. * * This program 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 * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * You can also choose to distribute this program under the terms of * the Unmodified Binary Distribution Licence (as given in the file * COPYING.UBDL), provided that you have satisfied its requirements. */ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include /** @file * * ANSI escape sequences * */ /** * Call ANSI escape sequence handler * * @v ctx ANSI escape sequence context * @v function Control function identifier * @v count Parameter count * @v params Parameter list */ static void ansiesc_call_handler ( struct ansiesc_context *ctx, unsigned int function, int count, int params[] ) { struct ansiesc_handler *handlers = ctx->handlers; struct ansiesc_handler *handler; for ( handler = handlers ; handler->function ; handler++ ) { if ( handler->function == function ) { handler->handle ( ctx, count, params ); break; } } } /** * Process character that may be part of ANSI escape sequence * * @v ctx ANSI escape sequence context * @v c Character * @ret c Original character if not part of escape sequence * @ret <0 Character was part of escape sequence * * ANSI escape sequences will be plucked out of the character stream * and interpreted; once complete they will be passed to the * appropriate handler if one exists in this ANSI escape sequence * context. * * In the interests of code size, we are rather liberal about the * sequences we are prepared to accept as valid. */ int ansiesc_process ( struct ansiesc_context *ctx, int c ) { if ( ctx->count == 0 ) { if ( c == ESC ) { /* First byte of CSI : begin escape sequence */ ctx->count = 1; memset ( ctx->params, 0xff, sizeof ( ctx->params ) ); ctx->function = 0; return -1; } else { /* Normal character */ return c; } } else { if ( c == '[' ) { /* Second byte of CSI : do nothing */ } else if ( ( c >= '0' ) && ( c <= '9' ) ) { /* Parameter Byte : part of a parameter value */ int *param = &ctx->params[ctx->count - 1]; if ( *param < 0 ) *param = 0; *param = ( ( *param * 10 ) + ( c - '0' ) ); } else if ( c == ';' ) { /* Parameter Byte : parameter delimiter */ ctx->count++; if ( ctx->count > ( sizeof ( ctx->params ) / sizeof ( ctx->params[0] ) ) ) { /* Excessive parameters : abort sequence */ ctx->count = 0; DBG ( "Too many parameters in ANSI escape " "sequence\n" ); } } else if ( ( ( c >= 0x20 ) && ( c <= 0x2f ) ) || ( c == '?' ) ) { /* Intermediate Byte */ ctx->function <<= 8; ctx->function |= c; } else { /* Treat as Final Byte. Zero ctx->count before * calling handler to avoid potential infinite loops. */ int count = ctx->count; ctx->count = 0; ctx->function <<= 8; ctx->function |= c; ansiesc_call_handler ( ctx, ctx->function, count, ctx->params ); } return -1; } }