| Index: apps/moterm/moterm_model.h
|
| diff --git a/apps/moterm/moterm_model.h b/apps/moterm/moterm_model.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e222aa234fa540c2fc021433f9112c87c4fb518d
|
| --- /dev/null
|
| +++ b/apps/moterm/moterm_model.h
|
| @@ -0,0 +1,178 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +// |MotermModel| is a class providing a model for terminal emulation. The basic
|
| +// operations are providing "input" bytes (this is input from the point of view
|
| +// of the terminal; from the point of view of applications, it's output) and
|
| +// determining what character to display at any given position (with what
|
| +// attributes).
|
| +//
|
| +// Note that no termios-style processing of the "input" bytes is done. The
|
| +// "input" bytes should be as seen on the wire by a serial terminal.
|
| +//
|
| +// This class does not handle "output" from the terminal (i.e., its keyboard,
|
| +// and thus "input" to applications).
|
| +//
|
| +// The current implementation is on top of FreeBSD's libteken, though it would
|
| +// be straightforward to replace it with another terminal emulation library (or
|
| +// implement one directly).
|
| +
|
| +#ifndef APPS_MOTERM_MOTERM_MODEL_H_
|
| +#define APPS_MOTERM_MOTERM_MODEL_H_
|
| +
|
| +#include <stddef.h>
|
| +#include <stdint.h>
|
| +
|
| +#include "base/macros.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "third_party/libteken/teken/teken.h"
|
| +
|
| +class MotermModel {
|
| + public:
|
| + // Position: zero-based, starting from upper-left. (Quantities are signed to
|
| + // allow for relative and off-screen positions.)
|
| + struct Position {
|
| + Position(int row = 0, int column = 0) : row(row), column(column) {}
|
| +
|
| + int row;
|
| + int column;
|
| + };
|
| +
|
| + struct Size {
|
| + Size(unsigned rows = 0, unsigned columns = 0)
|
| + : rows(rows), columns(columns) {}
|
| +
|
| + unsigned rows;
|
| + unsigned columns;
|
| + };
|
| +
|
| + struct Rectangle {
|
| + Rectangle(int row = 0,
|
| + int column = 0,
|
| + unsigned rows = 0,
|
| + unsigned columns = 0)
|
| + : position(row, column), size(rows, columns) {}
|
| +
|
| + bool IsEmpty() const { return !size.rows || !size.columns; }
|
| +
|
| + Position position;
|
| + Size size;
|
| + };
|
| +
|
| + struct Color {
|
| + Color(uint8_t red = 0, uint8_t green = 0, uint8_t blue = 0)
|
| + : red(red), green(green), blue(blue) {}
|
| +
|
| + uint8_t red;
|
| + uint8_t green;
|
| + uint8_t blue;
|
| + };
|
| +
|
| + using Attributes = uint32_t;
|
| + static const Attributes kAttributesBold = 1;
|
| + static const Attributes kAttributesUnderline = 2;
|
| + static const Attributes kAttributesBlink = 4;
|
| +
|
| + struct CharacterInfo {
|
| + CharacterInfo(uint32_t code_point,
|
| + Attributes attributes,
|
| + const Color& foreground_color,
|
| + const Color& background_color)
|
| + : code_point(code_point),
|
| + attributes(attributes),
|
| + foreground_color(foreground_color),
|
| + background_color(background_color) {}
|
| +
|
| + uint32_t code_point; // Unicode, of course.
|
| + Attributes attributes;
|
| + Color foreground_color;
|
| + Color background_color;
|
| + };
|
| +
|
| + struct StateChanges {
|
| + StateChanges() : cursor_moved(false), bell_count(0), dirty_rect() {}
|
| +
|
| + bool IsDirty() const {
|
| + return cursor_moved || bell_count > 0 || !dirty_rect.IsEmpty();
|
| + }
|
| + void Reset() { *this = StateChanges(); }
|
| +
|
| + bool cursor_moved;
|
| + unsigned bell_count;
|
| + Rectangle dirty_rect;
|
| + };
|
| +
|
| + // Maximum number of rows/columns.
|
| + static const unsigned kMaxRows = 500; // TODO(vtl): Made up number.
|
| + static const unsigned kMaxColumns = T_NUMCOL;
|
| +
|
| + MotermModel(const Size& max_size, const Size& size);
|
| + ~MotermModel();
|
| +
|
| + // Process the given input bytes, reporting (additional) state changes to
|
| + // |*state_changes| (note: this does not "reset" |*state_changes|, so that
|
| + // state changes can be accumulated across multiple calls).
|
| + void ProcessInput(const void* input_bytes,
|
| + size_t num_input_bytes,
|
| + StateChanges* state_changes);
|
| +
|
| + Size GetSize() const;
|
| + Position GetCursorPosition() const;
|
| + CharacterInfo GetCharacterInfoAt(const Position& position) const;
|
| +
|
| + void SetSize(const Size& size, bool reset);
|
| +
|
| + private:
|
| + teken_char_t& character_at(unsigned row, unsigned column) {
|
| + return characters_[row * max_size_.columns + column];
|
| + }
|
| + teken_attr_t& attribute_at(unsigned row, unsigned column) {
|
| + return attributes_[row * max_size_.columns + column];
|
| + }
|
| +
|
| + // libteken callbacks:
|
| + void OnBell();
|
| + void OnCursor(const teken_pos_t* pos);
|
| + void OnPutchar(const teken_pos_t* pos,
|
| + teken_char_t ch,
|
| + const teken_attr_t* attr);
|
| + void OnFill(const teken_rect_t* rect,
|
| + teken_char_t ch,
|
| + const teken_attr_t* attr);
|
| + void OnCopy(const teken_rect_t* rect, const teken_pos_t* pos);
|
| + void OnParam(int cmd, unsigned val);
|
| + void OnRespond(const void* buf, size_t size);
|
| +
|
| + // Thunks for libteken callbacks:
|
| + static void OnBellThunk(void* ctx);
|
| + static void OnCursorThunk(void* ctx, const teken_pos_t* pos);
|
| + static void OnPutcharThunk(void* ctx,
|
| + const teken_pos_t* pos,
|
| + teken_char_t ch,
|
| + const teken_attr_t* attr);
|
| + static void OnFillThunk(void* ctx,
|
| + const teken_rect_t* rect,
|
| + teken_char_t ch,
|
| + const teken_attr_t* attr);
|
| + static void OnCopyThunk(void* ctx,
|
| + const teken_rect_t* rect,
|
| + const teken_pos_t* pos);
|
| + static void OnParamThunk(void* ctx, int cmd, unsigned val);
|
| + static void OnRespondThunk(void* ctx, const void* buf, size_t size);
|
| +
|
| + const Size max_size_;
|
| +
|
| + scoped_ptr<teken_char_t[]> characters_;
|
| + scoped_ptr<teken_attr_t[]> attributes_;
|
| +
|
| + teken_t terminal_;
|
| +
|
| + // Used by the callbacks. ("Usually" null, but must be non-null whenever a
|
| + // callback may be called -- it'll point to a stack variable.)
|
| + StateChanges* current_state_changes_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(MotermModel);
|
| +};
|
| +
|
| +#endif // APPS_MOTERM_MOTERM_MODEL_H_
|
|
|