// Copyright 2025 The TCell Authors//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use file except in compliance with the License.// You may obtain a copy of the license at//// http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License.package tcellimport ()type cell struct { currStr string lastStr string currStyle Style lastStyle Style width int lock bool}func ( *cell) ( bool) {if { .lastStr = "" } else {if .currStr == "" { .currStr = " " } .lastStr = .currStr .lastStyle = .currStyle }}// CellBuffer represents a two-dimensional array of character cells.// This is primarily intended for use by Screen implementors; it// contains much of the common code they need. To create one, just// declare a variable of its type; no explicit initialization is necessary.//// CellBuffer is not thread safe.typeCellBufferstruct { w int h int cells []cell}// SetContent sets the contents (primary rune, combining runes,// and style) for a cell at a given location. If the background or// foreground of the style is set to ColorNone, then the respective// color is left un changed.//// Deprecated: Use Put instead, which this is implemented in terms of.func ( *CellBuffer) ( int, int, rune, []rune, Style) { .Put(, , string(append([]rune{}, ...)), )}// Put a single styled grapheme using the given string and style// at the same location. Note that only the first grapheme in the string// will bre displayed, using only the 1 or 2 (depending on width) cells// located at x, y. It returns the rest of the string, and the width used.func ( *CellBuffer) ( int, int, string, Style) (string, int) {varint = 0if >= 0 && >= 0 && < .w && < .h {varstring := &.cells[(*.w)+] := -1for == 0 && != "" {varstring , , , = uniseg.FirstGraphemeClusterInString(, ) += if == "" {break } }// Wide characters: we want to mark the "wide" cells // dirty as well as the base cell, to make sure we consider // both cells as dirty together. We only need to do this // if we're changing contentif > 0 && != .currStr {// Prevent unnecessary boundchecks for first cell, since we already // received that one. .setDirty(true)for := 1; < ; ++ { .SetDirty(+, , true) } } .currStr = .width = if .fg == ColorNone { .fg = .currStyle.fg }if .bg == ColorNone { .bg = .currStyle.bg } .currStyle = }return , }// Get the contents of a character cell (or two adjacent cells), including the// the style and the display width in cells. (The width can be either 1, normally,// or 2 for East Asian full-width characters. If the width is 0, then the cell is// is empty.)func ( *CellBuffer) (, int) (string, Style, int) {varStylevarintvarstringif >= 0 && >= 0 && < .w && < .h { := &.cells[(*.w)+] , = .currStr, .currStyleif = .width; == 0 || == "" { = 1 = " " } }return , , }// GetContent returns the contents of a character cell, including the// primary rune, any combining character runes (which will usually be// nil), the style, and the display width in cells. (The width can be// either 1, normally, or 2 for East Asian full-width characters.)//// Deprecated: Use Get, which this implemented in terms of.func ( *CellBuffer) (, int) (rune, []rune, Style, int) {varStylevarintvarrunevar []rune , , := .Get(, )for , := range {if == 0 { = } else { = append(, ) } }return , , , }// Size returns the (width, height) in cells of the buffer.func ( *CellBuffer) () (int, int) {return .w, .h}// Invalidate marks all characters within the buffer as dirty.func ( *CellBuffer) () {for := range .cells { .cells[].lastStr = "" }}// Dirty checks if a character at the given location needs to be// refreshed on the physical display. This returns true if the cell// content is different since the last time it was marked clean.func ( *CellBuffer) (, int) bool {if >= 0 && >= 0 && < .w && < .h { := &.cells[(*.w)+]if .lock {returnfalse }if .lastStyle != .currStyle {returntrue }if .lastStr != .currStr {returntrue } }returnfalse}// SetDirty is normally used to indicate that a cell has// been displayed (in which case dirty is false), or to manually// force a cell to be marked dirty.func ( *CellBuffer) (, int, bool) {if >= 0 && >= 0 && < .w && < .h { := &.cells[(*.w)+] .setDirty() }}// LockCell locks a cell from being drawn, effectively marking it "clean" until// the lock is removed. This can be used to prevent tcell from drawing a given// cell, even if the underlying content has changed. For example, when drawing a// sixel graphic directly to a TTY screen an implementer must lock the region// underneath the graphic to prevent tcell from drawing on top of the graphic.func ( *CellBuffer) (, int) {if < 0 || < 0 {return }if >= .w || >= .h {return } := &.cells[(*.w)+] .lock = true}// UnlockCell removes a lock from the cell and marks it as dirtyfunc ( *CellBuffer) (, int) {if < 0 || < 0 {return }if >= .w || >= .h {return } := &.cells[(*.w)+] .lock = false .SetDirty(, , true)}// Resize is used to resize the cells array, with different dimensions,// while preserving the original contents. The cells will be invalidated// so that they can be redrawn.func ( *CellBuffer) (, int) {if .h == && .w == {return } := make([]cell, *)for := 0; < && < .h; ++ {for := 0; < && < .w; ++ { := &.cells[(*.w)+] := &[(*)+] .currStr = .currStr .currStyle = .currStyle .width = .width .lastStr = "" } } .cells = .h = .w = }// Fill fills the entire cell buffer array with the specified character// and style. Normally choose ' ' to clear the screen. This API doesn't// support combining characters, or characters with a width larger than one.// If either the foreground or background are ColorNone, then the respective// color is unchanged.func ( *CellBuffer) ( rune, Style) {for := range .cells { := &.cells[] .currStr = string() := if .fg == ColorNone { .fg = .currStyle.fg }if .bg == ColorNone { .bg = .currStyle.bg } .currStyle = .width = 1 }}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.