Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
229 lines (193 sloc) 8.85 KB
// -*- mode:objc -*-
** ScreenChar.h
** Copyright (c) 2011
** Author: George Nachman
** Project: iTerm2
** Description: Code related to screen_char_t. Most of this has to do with
** storing multiple code points together in one cell by using a "color
** palette" approach where the code point can be used as an index into a
** string table, and the strings can have surrogate pairs and combining
** marks.
** 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
** (at your option) 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
** 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., 675 Mass Ave, Cambridge, MA 02139, USA.
#import <Cocoa/Cocoa.h>
// This is used in the rightmost column when a double-width character would
// have been split in half and was wrapped to the next line. It is nonprintable
// and not selectable. It is not copied into the clipboard. A line ending in this
// character should always have EOL_DWC. These are stripped when adding a line
// to the scrollback buffer.
#define DWC_SKIP 0xf000
// When a tab is received, we insert some number of TAB_FILLER characters
// preceded by a \t character. This allows us to reconstruct the tab for
// copy-pasting.
#define TAB_FILLER 0xf001
// If a private-use character is received as input, we convert it to this
// meaningless character.
#define BOGUS_CHAR 0xf002
// Double-width characters have their "real" code in one cell and this code in
// the right-hand cell.
#define DWC_RIGHT 0xf003
// These codes go in the continuation character to the right of the
// rightmost column.
#define EOL_HARD 0 // Hard line break (explicit newline)
#define EOL_SOFT 1 // Soft line break (a long line was wrapped)
#define EOL_DWC 2 // Double-width character wrapped to next line
// The range of private codes we use, with specific instances defined right
// above here.
#define ITERM2_PRIVATE_BEGIN 0xf000
#define ITERM2_PRIVATE_END 0xf8fe
// This is the standard unicode replacement character for when input couldn't
// be parsed properly but we need to render something there.
#define UNKNOWN 0xfffd
#define ONECHAR_UNKNOWN ('#') // Used for encodings other than utf-8.
// Alternate semantics definitions
// Default background color
// Default foreground color
// Selected color
// Cursor color
// Max unichars in a glyph.
static const int kMaxParts = 20;
typedef struct screen_char_t
// Normally, 'code' gives a utf-16 code point. If 'complexChar' is set then
// it is a key into a string table of multiple utf-16 code points (for
// example, a surrogate pair or base char+combining mark). These must render
// to a single glyph. 'code' can take some special values which are valid
// regardless of the setting of 'complexChar':
// 0: Signifies no character was ever set at this location. Not selectable.
// DWC_SKIP, TAB_FILLER, BOGUS_CHAR, or DWC_RIGHT: See comments above.
// In the WIDTH+1 position on a line, this takes the value of EOL_HARD,
// EOL_SOFT, or EOL_DWC. See the comments for those constants.
unichar code;
// With normal background semantics:
// The lower 9 bits have the same semantics for foreground and background
// color:
// Low three bits give color. 0-7 are black, red, green, yellow, blue,
// purple, cyan, and white.
// Values between 8 and 15 are bright versions of 0-7.
// Values between 16 and 255 are used for 256 color mode:
// 16-232: rgb value given by 16 + r*36 + g*6 + b, with each color in
// the range [0,6].
// 233-255: Grayscale values from dimmest gray 233 (which is not black)
// to brightest 255 (not white).
// With alternate background semantics:
// ALTSEM_xxx (see comments above)
unsigned int backgroundColor : 8;
unsigned int foregroundColor : 8;
// This flag determines the interpretation of backgroundColor.
unsigned int alternateBackgroundSemantics : 1;
// If set, the 'code' field does not give a utf-16 value but is intead a
// key into a string table of more complex chars (combined, surrogate pairs,
// etc.). Valid 'code' values for a complex char are in [1, 0xefff] and will
// be recycled as needed.
unsigned int complexChar : 1;
// Foreground color has the same definition as background color.
unsigned int alternateForegroundSemantics : 1;
// Various bits affecting text appearance. The bold flag here is semantic
// and may be rendered as some combination of font choice and color
// intensity.
unsigned int bold : 1;
unsigned int blink : 1;
unsigned int underline : 1;
// These bits aren't used by are defined here so that the entire memory
// region can be initialized.
unsigned int unused : 26;
} screen_char_t;
// Standard unicode replacement string. Is a double-width character.
static inline NSString* ReplacementString()
const unichar kReplacementCharacter = 0xfffd;
return [NSString stringWithCharacters:&kReplacementCharacter length:1];
// Copy foreground color from one char to another.
static inline void CopyForegroundColor(screen_char_t* to, const screen_char_t from)
to->foregroundColor = from.foregroundColor;
to->alternateForegroundSemantics = from.alternateForegroundSemantics;
to->bold = from.bold;
to->blink = from.blink;
to->underline = from.underline;
// COpy background color from one char to another.
static inline void CopyBackgroundColor(screen_char_t* to, const screen_char_t from)
to->backgroundColor = from.backgroundColor;
to->alternateBackgroundSemantics = from.alternateBackgroundSemantics;
// Returns true iff two background colors are equal.
static inline BOOL BackgroundColorsEqual(const screen_char_t a,
const screen_char_t b)
return a.backgroundColor == b.backgroundColor &&
a.alternateBackgroundSemantics == b.alternateBackgroundSemantics;
// Returns true iff two foreground colors are equal.
static inline BOOL ForegroundColorsEqual(const screen_char_t a,
const screen_char_t b)
return a.foregroundColor == b.foregroundColor &&
a.alternateForegroundSemantics == b.alternateForegroundSemantics &&
a.bold == b.bold &&
a.blink == b.blink &&
a.underline == b.underline;
// Look up the string associated with a complex char's key.
NSString* ComplexCharToStr(int key);
// Return a string with the contents of a screen char, which may or may not
// be complex.
NSString* ScreenCharToStr(screen_char_t* sct);
NSString* CharToStr(unichar code, BOOL isComplex);
// This is a faster version of ScreenCharToStr if what you want is an array of
// unichars. Returns the number of code points appended to dest.
int ExpandScreenChar(screen_char_t* sct, unichar* dest);
// Convert a code into a utf-32 char.
UTF32Char CharToLongChar(unichar code, BOOL isComplex);
// Add a code point to the end of an existing complex char. A replacement key is
// returned.
int AppendToComplexChar(int key, unichar codePoint);
// Create a new complex char from two code points. A key is returned.
int BeginComplexChar(unichar initialCodePoint, unichar combiningChar);
// Returns true if the given character is a combining mark, per chapter 3 of
// the Unicode 6.0 spec, D52.
BOOL IsCombiningMark(UTF32Char c);
// Translate a surrogate pair into a single utf-32 char.
UTF32Char DecodeSurrogatePair(unichar high, unichar low);
// Test for low surrogacy.
BOOL IsLowSurrogate(unichar c);
// Test for high surrogacy.
BOOL IsHighSurrogate(unichar c);
// Convert an array of screen_char_t into a string.
// After this call free(*backingStorePtr), free(*deltasPtr)
// *deltasPtr will be filled in with values that let you convert indices in
// the result string to indices in the original array.
// In other words:
// part or all of [result characterAtIndex:i] refers to all or part of screenChars[i - (*deltasPtr)[i]].
NSString* ScreenCharArrayToString(screen_char_t* screenChars,
int start,
int end,
unichar** backingStorePtr,
int** deltasPtr);
// Number of chars before a sequence of nuls at the end of the line.
int EffectiveLineLength(screen_char_t* theLine, int totalLength);