/*************************************************************************** xterm256generator.cpp - description ------------------- begin : Oct 13 2006 copyright : (C) 2006 by Andre Simon email : andre.simon1@gmx.de ***************************************************************************/ /* This file is part of Highlight. Highlight 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 3 of the License, or (at your option) any later version. Highlight 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 Highlight. If not, see <http://www.gnu.org/licenses/>. */ #include <stdio.h> #include <math.h> #include <stdlib.h> #include <sstream> #include "xterm256generator.h" #include "charcodes.h" #include "version.h" using namespace std; namespace highlight { Xterm256Generator::Xterm256Generator() : CodeGenerator ( XTERM256 ) { newLineTag = "\n"; spacer = " "; } Xterm256Generator::~Xterm256Generator() {} string Xterm256Generator::getHeader() { return string(); } void Xterm256Generator::printBody() { processRootState(); } string Xterm256Generator::getFooter() { return string(); } string Xterm256Generator::maskCharacter ( unsigned char c ) { return string ( 1, c ); } void Xterm256Generator::initOutputTags ( ) { openTags.push_back ( getOpenTag ( docStyle.getDefaultStyle() ) ); openTags.push_back ( getOpenTag ( docStyle.getStringStyle() ) ); openTags.push_back ( getOpenTag ( docStyle.getNumberStyle() ) ); openTags.push_back ( getOpenTag ( docStyle.getSingleLineCommentStyle() ) ); openTags.push_back ( getOpenTag ( docStyle.getCommentStyle() ) ); openTags.push_back ( getOpenTag ( docStyle.getEscapeCharStyle() ) ); openTags.push_back ( getOpenTag ( docStyle.getDirectiveStyle() ) ); openTags.push_back ( getOpenTag ( docStyle.getDirectiveStringStyle() ) ); openTags.push_back ( getOpenTag ( docStyle.getLineStyle() ) ); openTags.push_back ( getOpenTag ( docStyle.getSymbolStyle() ) ); for ( int i=0;i<NUMBER_BUILTIN_STATES; i++ ) { closeTags.push_back ( "\033[m" ); } } string Xterm256Generator::getOpenTag ( const ElementStyle &col ) { Colour c= col.getColour(); unsigned char rgb[3]; rgb[0] = ( unsigned char ) strtoll ( c.getRed ( HTML ).c_str(), NULL, 16 ); rgb[1] = ( unsigned char ) strtoll ( c.getGreen ( HTML ).c_str(), NULL, 16 ); rgb[2] = ( unsigned char ) strtoll ( c.getBlue ( HTML ).c_str(), NULL, 16 ); ostringstream s; s << "\033[38;5;"<< ( int ) rgb2xterm ( rgb ) << "m"; return s.str(); } string Xterm256Generator::getKeywordOpenTag ( unsigned int styleID ) { return getOpenTag ( docStyle.getKeywordStyle ( langInfo.getKeywordClasses() [styleID] ) ); } string Xterm256Generator::getKeywordCloseTag ( unsigned int styleID ) { return "\033[m"; } /* the following functions are based on Wolfgang Frischs xterm256 converter utility: http://frexx.de/xterm-256-notes/ */ void Xterm256Generator::xterm2rgb ( unsigned char color, unsigned char* rgb ) { // 16 basic colors if ( color<16 ) { rgb[0] = basic16[color][0]; rgb[1] = basic16[color][1]; rgb[2] = basic16[color][2]; } // color cube color if ( color>=16 && color<=232 ) { color-=16; rgb[0] = valuerange[ ( color/36 ) %6]; rgb[1] = valuerange[ ( color/6 ) %6]; rgb[2] = valuerange[color%6]; } // gray tone if ( color>=233 && color<=253 ) { rgb[0]=rgb[1]=rgb[2] = 8+ ( color-232 ) *0x0a; } } void Xterm256Generator::maketable() { unsigned char c, rgb[3]; for ( c=0;c<=253;c++ ) { xterm2rgb ( c,rgb ); colortable[c][0] = rgb[0]; colortable[c][1] = rgb[1]; colortable[c][2] = rgb[2]; } } unsigned char Xterm256Generator::rgb2xterm ( unsigned char* rgb ) { unsigned char c, best_match=0; double d, smallest_distance; if ( !initialized ) { maketable(); initialized = true; } smallest_distance = 10000000000.0; for ( c=0;c<=253;c++ ) { d = pow ( colortable[c][0]-rgb[0],2.0 ) + pow ( colortable[c][1]-rgb[1],2.0 ) + pow ( colortable[c][2]-rgb[2],2.0 ); if ( d<smallest_distance ) { smallest_distance = d; best_match=c; } } return best_match; } bool Xterm256Generator::initialized=false; unsigned char Xterm256Generator::colortable[254][3]; const unsigned char Xterm256Generator::valuerange[] = { 0x00, 0x5F, 0x87, 0xAF, 0xD7, 0xFF }; const unsigned char Xterm256Generator::basic16[16][3] = { { 0x00, 0x00, 0x00 }, // 0 { 0xCD, 0x00, 0x00 }, // 1 { 0x00, 0xCD, 0x00 }, // 2 { 0xCD, 0xCD, 0x00 }, // 3 { 0x00, 0x00, 0xEE }, // 4 { 0xCD, 0x00, 0xCD }, // 5 { 0x00, 0xCD, 0xCD }, // 6 { 0xE5, 0xE5, 0xE5 }, // 7 { 0x7F, 0x7F, 0x7F }, // 8 { 0xFF, 0x00, 0x00 }, // 9 { 0x00, 0xFF, 0x00 }, // 10 { 0xFF, 0xFF, 0x00 }, // 11 { 0x5C, 0x5C, 0xFF }, // 12 { 0xFF, 0x00, 0xFF }, // 13 { 0x00, 0xFF, 0xFF }, // 14 { 0xFF, 0xFF, 0xFF } // 15 }; }