From f68f4fd627dbca6ffa88c15189cf12327485eba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Czerpak?= Date: Thu, 16 Jul 2015 17:10:34 +0200 Subject: [PATCH] 2015-07-16 17:10 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * src/rtl/gttrm/gttrm.c * gives the highest priority to terminal type specified by in //gttrm: switch + added support for extended XTERM colors. It can be enabled by EXCLR GTTRM parameter. So far GTTRM used only standard 8 ANSI colors combined with BOLD and BLINK attributes to highlight text and/or background. Such functionality is supported by nearly all color terminals so is well portable but in some cases BOLD and BLINK attributes where interpreted differently. Now for XTERM compatible terminals GTTRM can use also other methods of color settings. They can be enabled by //gttrm:exclr application command line switch, i.e.: //GTTRM:EXCLR=0 - use 8 ANSI colors with BLINK and BOLD attributes (current default behavior) //GTTRM:EXCLR=1 - use XTERM 16 extended colors //GTTRM:EXCLR=2 - use XTERM 256 extended colors //GTTRM:EXCLR=3 - use XTERM RGB colors (//GTTRM:EXCLR without number is the same as //GTTRM:EXCLR=1) If terminal supports XTERM extended color escape sequences then it's possible to enable 16 colors even if BLINK and BOLD does not do that and if terminal support XTERM RGB color escape sequences then also colors set by HB_GTI_PALETTE will be shown (so far HB_GTI_PALETTE in GTTRM was working only for Linux and PuTTY which support: ESC ] P escape sequence). Warning: I added above modes to test different terminals. It's possible that I'll change it after tests. --- ChangeLog.txt | 29 +++++ src/rtl/gttrm/gttrm.c | 259 +++++++++++++++++++++++++++++++++++------- 2 files changed, 249 insertions(+), 39 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index e03168a261..99b37ab8bd 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,35 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2015-07-16 17:10 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * src/rtl/gttrm/gttrm.c + * gives the highest priority to terminal type specified by + in //gttrm: switch + + added support for extended XTERM colors. + It can be enabled by EXCLR GTTRM parameter. + So far GTTRM used only standard 8 ANSI colors combined with BOLD + and BLINK attributes to highlight text and/or background. + Such functionality is supported by nearly all color terminals + so is well portable but in some cases BOLD and BLINK attributes + where interpreted differently. + Now for XTERM compatible terminals GTTRM can use also other + methods of color settings. They can be enabled by //gttrm:exclr + application command line switch, i.e.: + //GTTRM:EXCLR=0 - use 8 ANSI colors with BLINK and BOLD + attributes (current default behavior) + //GTTRM:EXCLR=1 - use XTERM 16 extended colors + //GTTRM:EXCLR=2 - use XTERM 256 extended colors + //GTTRM:EXCLR=3 - use XTERM RGB colors + (//GTTRM:EXCLR without number is the same as //GTTRM:EXCLR=1) + If terminal supports XTERM extended color escape sequences then + it's possible to enable 16 colors even if BLINK and BOLD does + not do that and if terminal support XTERM RGB color escape + sequences then also colors set by HB_GTI_PALETTE will be shown + (so far HB_GTI_PALETTE in GTTRM was working only for Linux and + PuTTY which support: ESC ] P escape sequence). + Warning: I added above modes to test different terminals. + It's possible that I'll change it after tests. + 2015-07-14 17:51 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * src/rtl/gtxwc/gtxwc.c ! fixed SetMode() when HB_GTI_RESIZABLE is set to .F. diff --git a/src/rtl/gttrm/gttrm.c b/src/rtl/gttrm/gttrm.c index 35948dee75..7ae74bfc2f 100644 --- a/src/rtl/gttrm/gttrm.c +++ b/src/rtl/gttrm/gttrm.c @@ -129,6 +129,11 @@ static HB_GT_FUNCS SuperTable; #define TERM_PUTTY 4 #define TERM_CONS 8 +#define HB_GTTRM_CLRSTD 0 +#define HB_GTTRM_CLRX16 1 +#define HB_GTTRM_CLR256 2 +#define HB_GTTRM_CLRRGB 3 + #define NO_STDKEYS 96 #define NO_EXTDKEYS 30 @@ -310,7 +315,7 @@ typedef struct _HB_GTTRM int iHeight; HB_SIZE nLineBufSize; char * pLineBuf; - int iCurrentSGR, iFgColor, iBgColor, iBold, iBlink, iACSC, iAM; + int iCurrentSGR, iFgColor, iBgColor, iBold, iBlink, iACSC, iExtColor, iAM; int iAttrMask; int iCursorStyle; HB_BOOL fAM; @@ -412,7 +417,7 @@ static const char * s_szMouseOff = "\033[?1002l\033[?1001r"; static const char s_szBell[] = { HB_CHAR_BEL, 0 }; /* conversion table for ANSI color indexes */ -static const int s_AnsiColors[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; +static const int s_AnsiColors[] = { 0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15 }; static int getClipKey( int nKey ) { @@ -1528,7 +1533,7 @@ static void hb_gt_trm_LinuxSetPalette( PHB_GTTRM pTerm, int iIndexFrom, int iInd do { char szColor[ 11 ]; - int iAnsiIndex = s_AnsiColors[ iIndexFrom & 0x07 ] | ( iIndexFrom & 0x08 ); + int iAnsiIndex = s_AnsiColors[ iIndexFrom & 0x0F ]; hb_snprintf( szColor, sizeof( szColor ), "\033]P%X%02X%02X%02X", iAnsiIndex, @@ -1592,18 +1597,27 @@ static void hb_gt_trm_XtermSetAttributes( PHB_GTTRM pTerm, int iAttr ) if( pTerm->iCurrentSGR != iAttr ) { - int i, acsc, bg, fg, bold, blink; - char buff[ 32 ]; + int i, acsc, bg, fg, bold, blink, rgb; + char buff[ 64 ]; i = 2; buff[ 0 ] = 0x1b; buff[ 1 ] = '['; acsc = ( iAttr & HB_GTTRM_ATTR_ACSC ) && ! pTerm->fUTF8 ? 1 : 0; - bg = s_AnsiColors[ ( iAttr >> 4 ) & 0x07 ]; - fg = s_AnsiColors[ iAttr & 0x07 ]; - bold = iAttr & 0x08 ? 1 : 0; - blink = iAttr & 0x80 ? 1 : 0; + if( pTerm->iExtColor == HB_GTTRM_CLRSTD ) + { + bg = s_AnsiColors[ ( iAttr >> 4 ) & 0x07 ]; + fg = s_AnsiColors[ iAttr & 0x07 ]; + bold = iAttr & 0x08 ? 1 : 0; + blink = iAttr & 0x80 ? 1 : 0; + } + else + { + bg = s_AnsiColors[ ( iAttr >> 4 ) & 0x0F ]; + fg = s_AnsiColors[ iAttr & 0x0F ]; + bold = blink = 0; + } if( pTerm->iCurrentSGR == -1 ) { @@ -1615,21 +1629,72 @@ static void hb_gt_trm_XtermSetAttributes( PHB_GTTRM pTerm, int iAttr ) buff[ i++ ] = 0x1b; buff[ i++ ] = '['; - if( bold ) + if( pTerm->iExtColor == HB_GTTRM_CLRSTD ) { - buff[ i++ ] = '1'; + if( bold ) + { + buff[ i++ ] = '1'; + buff[ i++ ] = ';'; + } + if( blink ) + { + buff[ i++ ] = '5'; + buff[ i++ ] = ';'; + } + buff[ i++ ] = '3'; + buff[ i++ ] = '0' + fg; buff[ i++ ] = ';'; + buff[ i++ ] = '4'; + buff[ i++ ] = '0' + bg; } - if( blink ) + else if( pTerm->iExtColor == HB_GTTRM_CLRX16 ) { + // ESC [ 38 ; 5 ; m + buff[ i++ ] = '3'; + buff[ i++ ] = '8'; + buff[ i++ ] = ';'; buff[ i++ ] = '5'; buff[ i++ ] = ';'; + if( fg >= 10 ) + buff[ i++ ] = '1'; + buff[ i++ ] = '0' + fg % 10; + buff[ i++ ] = ';'; + // ESC [ 48 ; 5 ; m + buff[ i++ ] = '4'; + buff[ i++ ] = '8'; + buff[ i++ ] = ';'; + buff[ i++ ] = '5'; + buff[ i++ ] = ';'; + if( bg >= 10 ) + buff[ i++ ] = '1'; + buff[ i++ ] = '0' + bg % 10; + } + else if( pTerm->iExtColor == HB_GTTRM_CLR256 ) + { + // ESC [ 38 ; 5 ; <16 + 36 * r + 6 * g + b> m // 0 <= r,g,b <= 5 + rgb = pTerm->colors[ iAttr & 0x0F ]; + rgb = 16 + 36 * ( ( rgb & 0xFF ) / 43 ) + + 6 * ( ( ( rgb >> 8 ) & 0xFF ) / 43 ) + + ( ( ( rgb >> 16 ) & 0xFF ) / 43 ); + i += hb_snprintf( buff + i, sizeof( buff ) - i, "38;5;%d", rgb ); + // ESC [ 48 ; 5 ; <16 + 36 * r + 6 * g + b> m // 0 <= r,g,b <= 5 + rgb = pTerm->colors[ ( iAttr >> 4 ) & 0x0F ]; + rgb = 16 + 36 * ( ( rgb & 0xFF ) / 43 ) + + 6 * ( ( ( rgb >> 8 ) & 0xFF ) / 43 ) + + ( ( ( rgb >> 16 ) & 0xFF ) / 43 ); + i += hb_snprintf( buff + i, sizeof( buff ) - i, ";48;5;%d", rgb ); + } + else if( pTerm->iExtColor == HB_GTTRM_CLRRGB ) + { + // ESC [ 38 ; 2 ; ; ; m + rgb = pTerm->colors[ iAttr & 0x0F ]; + i += hb_snprintf( buff + i, sizeof( buff ) - i, "38;2;%d;%d;%d", + rgb & 0xFF, ( rgb >> 8 ) & 0xFF, ( rgb >> 16 ) & 0xFF ); + // ESC [ 48 ; 2 ; ; ; m + rgb = pTerm->colors[ ( iAttr >> 4 ) & 0x0F ]; + i += hb_snprintf( buff + i, sizeof( buff ) - i, ";48;2;%d;%d;%d", + rgb & 0xFF, ( rgb >> 8 ) & 0xFF, ( rgb >> 16 ) & 0xFF ); } - buff[ i++ ] = '3'; - buff[ i++ ] = '0' + fg; - buff[ i++ ] = ';'; - buff[ i++ ] = '4'; - buff[ i++ ] = '0' + bg; buff[ i++ ] = 'm'; pTerm->iACSC = acsc; pTerm->iBold = bold; @@ -1661,15 +1726,77 @@ static void hb_gt_trm_XtermSetAttributes( PHB_GTTRM pTerm, int iAttr ) } if( pTerm->iFgColor != fg ) { - buff[ i++ ] = '3'; - buff[ i++ ] = '0' + fg; + if( pTerm->iExtColor == HB_GTTRM_CLRSTD ) + { + buff[ i++ ] = '3'; + buff[ i++ ] = '0' + fg; + } + else if( pTerm->iExtColor == HB_GTTRM_CLRX16 ) + { + // ESC [ 38 ; 5 ; m + buff[ i++ ] = '3'; + buff[ i++ ] = '8'; + buff[ i++ ] = ';'; + buff[ i++ ] = '5'; + buff[ i++ ] = ';'; + if( fg >= 10 ) + buff[ i++ ] = '1'; + buff[ i++ ] = '0' + fg % 10; + } + else if( pTerm->iExtColor == HB_GTTRM_CLR256 ) + { + // ESC [ 38 ; 5 ; <16 + 36 * r + 6 * g + b> m // 0 <= r,g,b <= 5 + rgb = pTerm->colors[ iAttr & 0x0F ]; + rgb = 16 + 36 * ( ( rgb & 0xFF ) / 43 ) + + 6 * ( ( ( rgb >> 8 ) & 0xFF ) / 43 ) + + ( ( ( rgb >> 16 ) & 0xFF ) / 43 ); + i += hb_snprintf( buff + i, sizeof( buff ) - i, "38;5;%d", rgb ); + } + else if( pTerm->iExtColor == HB_GTTRM_CLRRGB ) + { + // ESC [ 38 ; 2 ; ; ; m + rgb = pTerm->colors[ iAttr & 0x0F ]; + i += hb_snprintf( buff + i, sizeof( buff ) - i, "38;2;%d;%d;%d", + rgb & 0xFF, ( rgb >> 8 ) & 0xFF, ( rgb >> 16 ) & 0xFF ); + } buff[ i++ ] = ';'; pTerm->iFgColor = fg; } if( pTerm->iBgColor != bg ) { - buff[ i++ ] = '4'; - buff[ i++ ] = '0' + bg; + if( pTerm->iExtColor == HB_GTTRM_CLRSTD ) + { + buff[ i++ ] = '4'; + buff[ i++ ] = '0' + bg; + } + else if( pTerm->iExtColor == HB_GTTRM_CLRX16 ) + { + // ESC [ 48 ; 5 ; m + buff[ i++ ] = '4'; + buff[ i++ ] = '8'; + buff[ i++ ] = ';'; + buff[ i++ ] = '5'; + buff[ i++ ] = ';'; + if( bg >= 10 ) + buff[ i++ ] = '1'; + buff[ i++ ] = '0' + bg % 10; + } + else if( pTerm->iExtColor == HB_GTTRM_CLR256 ) + { + // ESC [ 48 ; 5 ; <16 + 36 * r + 6 * g + b> m // 0 <= r,g,b <= 5 + rgb = pTerm->colors[ ( iAttr >> 4 ) & 0x0F ]; + rgb = 16 + 36 * ( ( rgb & 0xFF ) / 43 ) + + 6 * ( ( ( rgb >> 8 ) & 0xFF ) / 43 ) + + ( ( ( rgb >> 16 ) & 0xFF ) / 43 ); + i += hb_snprintf( buff + i, sizeof( buff ) - i, "48;5;%d", rgb ); + } + else if( pTerm->iExtColor == HB_GTTRM_CLRRGB ) + { + // ESC [ 48 ; 2 ; ; ; m + rgb = pTerm->colors[ ( iAttr >> 4 ) & 0x0F ]; + i += hb_snprintf( buff + i, sizeof( buff ) - i, "48;2;%d;%d;%d", + rgb & 0xFF, ( rgb >> 8 ) & 0xFF, ( rgb >> 16 ) & 0xFF ); + } buff[ i++ ] = ';'; pTerm->iBgColor = bg; } @@ -2136,14 +2263,28 @@ static void hb_gt_trm_AnsiExit( PHB_GTTRM pTerm ) /* * common functions */ -static HB_BOOL hb_trm_Param( const char * pszParam ) +static HB_BOOL hb_trm_Param( const char * pszParam, int * piValue ) { HB_BOOL fResult = HB_FALSE; char * pszGtTrmParams = hb_cmdargString( "GTTRM" ); if( pszGtTrmParams ) { - fResult = strstr( hb_strupr( pszGtTrmParams ), pszParam ) != NULL; + const char * pszAt = strstr( hb_strupr( pszGtTrmParams ), pszParam ); + + if( pszAt != NULL ) + { + fResult = HB_TRUE; + if( piValue ) + { + int iOverflow; + + pszAt += strlen( pszParam ); + if( *pszAt == '=' || *pszAt == ':' ) + ++pszAt; + * piValue = HB_ISDIGIT( *pszAt ) ? hb_strValInt( pszAt, &iOverflow ) : 1; + } + } hb_xfree( pszGtTrmParams ); } @@ -2165,9 +2306,9 @@ static HB_BOOL hb_trm_isUTF8( PHB_GTTRM pTerm ) } } - if( hb_trm_Param( "UTF8" ) || hb_trm_Param( "UTF-8" ) ) + if( hb_trm_Param( "UTF8", NULL ) || hb_trm_Param( "UTF-8", NULL ) ) return HB_TRUE; - else if( hb_trm_Param( "ISO" ) ) + else if( hb_trm_Param( "ISO", NULL ) ) return HB_FALSE; else if( pTerm->fPosAnswer ) return fUTF8; @@ -2947,6 +3088,7 @@ static void hb_gt_trm_SetTerm( PHB_GTTRM pTerm ) static const char * szAcsc = "``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~"; static const char * szExtAcsc = "+\020,\021-\030.\0310\333`\004a\261f\370g\361h\260i\316j\331k\277l\332m\300n\305o~p\304q\304r\304s_t\303u\264v\301w\302x\263y\363z\362{\343|\330}\234~\376"; const char * szTerm; + int iValue; HB_TRACE( HB_TR_DEBUG, ( "hb_gt_trm_SetTerm(%p)", pTerm ) ); @@ -2959,26 +3101,67 @@ static void hb_gt_trm_SetTerm( PHB_GTTRM pTerm ) pTerm->mouse_type = MOUSE_NONE; pTerm->esc_delay = ESC_DELAY; pTerm->iAttrMask = ~HB_GTTRM_ATTR_BOX; + pTerm->iExtColor = HB_GTTRM_CLRSTD; pTerm->terminal_ext = 0; pTerm->fAM = HB_FALSE; - if( hb_trm_Param( "PUTTY" ) ) - pTerm->terminal_ext |= TERM_PUTTY; - szTerm = getenv( "HB_TERM" ); - if( szTerm == NULL || *szTerm == '\0' ) + /* standard VGA colors */ + pTerm->colors[ 0x00 ] = 0x000000; + pTerm->colors[ 0x01 ] = 0xAA0000; + pTerm->colors[ 0x02 ] = 0x00AA00; + pTerm->colors[ 0x03 ] = 0xAAAA00; + pTerm->colors[ 0x04 ] = 0x0000AA; + pTerm->colors[ 0x05 ] = 0xAA00AA; + pTerm->colors[ 0x06 ] = 0x0055AA; + pTerm->colors[ 0x07 ] = 0xAAAAAA; + pTerm->colors[ 0x08 ] = 0x555555; + pTerm->colors[ 0x09 ] = 0xFF5555; + pTerm->colors[ 0x0A ] = 0x55FF55; + pTerm->colors[ 0x0B ] = 0xFFFF55; + pTerm->colors[ 0x0C ] = 0x5555FF; + pTerm->colors[ 0x0D ] = 0xFF55FF; + pTerm->colors[ 0x0E ] = 0x55FFFF; + pTerm->colors[ 0x0F ] = 0xFFFFFF; + + if( hb_trm_Param( "PUTTY", NULL ) ) + pTerm->terminal_ext |= TERM_PUTTY; + if( hb_trm_Param( "EXCLR", &iValue ) ) { - szTerm = getenv( "TERM" ); - if( szTerm == NULL || *szTerm == '\0' ) - szTerm = "ansi"; + switch( iValue ) + { + case HB_GTTRM_CLRSTD: + case HB_GTTRM_CLRX16: + case HB_GTTRM_CLR256: + case HB_GTTRM_CLRRGB: + pTerm->iExtColor = iValue; + break; + } } + if( hb_trm_Param( "XTERM", NULL ) ) + szTerm = "xterm"; + else if( hb_trm_Param( "LINUX", NULL ) ) + szTerm = "linux"; + else if( hb_trm_Param( "CONS", NULL ) ) + szTerm = "cons"; + else if( hb_trm_Param( "ANSI", NULL ) ) + szTerm = "ansi"; + else + { + szTerm = getenv( "HB_TERM" ); + if( szTerm == NULL || *szTerm == '\0' ) + { + szTerm = getenv( "TERM" ); + if( szTerm == NULL || *szTerm == '\0' ) + szTerm = "ansi"; + } + } if( ( pTerm->terminal_ext & TERM_PUTTY ) || strstr( szTerm, "xterm" ) != NULL || strncmp( szTerm, "rxvt", 4 ) == 0 || strcmp( szTerm, "putty" ) == 0 || - strncmp( szTerm, "screen", 6 ) == 0 || - hb_trm_Param( "XTERM" ) ) + strncmp( szTerm, "screen", 6 ) == 0 ) { pTerm->Init = hb_gt_trm_AnsiInit; pTerm->Exit = hb_gt_trm_AnsiExit; @@ -2996,8 +3179,7 @@ static void hb_gt_trm_SetTerm( PHB_GTTRM pTerm ) } else if( strncmp( szTerm, "linux", 5 ) == 0 || strcmp( szTerm, "tterm" ) == 0 || - strcmp( szTerm, "teraterm" ) == 0 || - hb_trm_Param( "LINUX" ) ) + strcmp( szTerm, "teraterm" ) == 0 ) { pTerm->Init = hb_gt_trm_AnsiInit; pTerm->Exit = hb_gt_trm_AnsiExit; @@ -3013,8 +3195,7 @@ static void hb_gt_trm_SetTerm( PHB_GTTRM pTerm ) pTerm->szAcsc = szExtAcsc; pTerm->terminal_type = TERM_LINUX; } - else if( strncmp( szTerm, "cons", 4 ) == 0 || - hb_trm_Param( "CONS" ) ) + else if( strncmp( szTerm, "cons", 4 ) == 0 ) { pTerm->Init = hb_gt_trm_AnsiInit; pTerm->Exit = hb_gt_trm_AnsiExit; @@ -3058,7 +3239,7 @@ static void hb_gt_trm_SetTerm( PHB_GTTRM pTerm ) pTerm->hFileno = pTerm->hFilenoStdin; pTerm->fOutTTY = HB_TRUE; } - pTerm->fPosAnswer = pTerm->fOutTTY && ! hb_trm_Param( "NOPOS" ); + pTerm->fPosAnswer = pTerm->fOutTTY && ! hb_trm_Param( "NOPOS", NULL ); pTerm->fUTF8 = HB_FALSE; hb_fsSetDevMode( pTerm->hFileno, FD_BINARY );