ansiterm.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:32k
- /*
- * ansiterm.cxx
- *
- * ANSI terminal emulation class.
- *
- * Portable Windows Library
- *
- * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.0 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Original Code is Portable Windows Library.
- *
- * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
- *
- * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
- * All Rights Reserved.
- *
- * Contributor(s): ______________________________________.
- *
- * $Log: ansiterm.cxx,v $
- * Revision 1.40 1998/12/20 09:14:37 robertj
- * Added pragma implementation for GNU compiler.
- *
- * Revision 1.39 1998/12/12 00:44:13 robertj
- * Added capability to get text lines out of scroll back buffer.
- *
- * Revision 1.38 1998/11/30 04:52:12 robertj
- * New directory structure
- *
- * Revision 1.37 1998/10/16 11:08:14 robertj
- * GNU compatibility.
- *
- * Revision 1.36 1998/09/23 06:29:33 robertj
- * Added open source copyright license.
- *
- * Revision 1.35 1998/09/18 13:09:33 robertj
- * Fixed clearing of very bottom of window.
- *
- * Revision 1.34 1998/09/17 04:24:45 robertj
- * Fixed update problems requiring screen refresh to see output text.
- *
- * Revision 1.33 1998/09/04 06:57:02 robertj
- * Fixed crash if window was realy, really wide.
- *
- * Revision 1.32 1997/04/27 05:50:20 robertj
- * DLL support.
- *
- * Revision 1.31 1996/12/21 07:01:35 robertj
- * Fixed flush on close problem in ANSI terminal stream.
- *
- * Revision 1.30 1996/06/03 10:07:31 robertj
- * Fixed bug in auto scroll to cursor position on output.
- * Fixed bug in DEL character processing (no screen update).
- *
- * Revision 1.29 1996/05/15 10:14:40 robertj
- * Rewrite of terminal to make descendant only require single character output function.
- *
- * Revision 1.28 1996/04/30 12:33:45 robertj
- * Changed "inPixels" boolean to enum for three coordinate systems.
- *
- * Revision 1.27 1996/04/29 12:18:24 robertj
- * Added local echo capability to terminal.
- *
- * Revision 1.26 1995/12/10 11:36:16 robertj
- * Fixed bug in display of window bigger than virtual screen.
- * Fixed warning in GNU compiler.
- *
- * Revision 1.25 1995/11/20 11:04:09 robertj
- * Fixed bugs in non-adjustable rows and columns mode.
- * Implemented horizontal scrolling.
- *
- * Revision 1.24 1995/11/09 12:19:50 robertj
- * Removed GNU warning.
- *
- * Revision 1.23 1995/08/24 12:35:51 robertj
- * Implemented copy/paste.
- *
- * Revision 1.22 1995/07/31 12:15:47 robertj
- * Removed PContainer from PChannel ancestor.
- *
- * Revision 1.21 1995/07/02 01:20:58 robertj
- * Removed OnDoubleClick() and added BOOL to OnMouseDown() for double click.
- *
- * Revision 1.20 1995/06/17 11:11:09 robertj
- * Changed OnKeyDown to return BOOL indicating OnKeyInput is to be used.
- *
- * Revision 1.19 1995/06/04 08:41:42 robertj
- * Some minor speedups.
- *
- * Revision 1.18 1995/04/25 11:28:06 robertj
- * Fixed Borland compiler warnings.
- *
- * Revision 1.17 1995/04/01 08:30:08 robertj
- * Changed default end of line wrap option.
- * Fixed loss of focus problem.
- *
- * Revision 1.16 1995/01/07 04:39:44 robertj
- * Redesigned font enumeration code and changed font styles.
- *
- * Revision 1.15 1995/01/06 10:43:53 robertj
- * Changed PRealFont usage from pointer to reference.
- *
- * Revision 1.14 1994/12/05 11:20:22 robertj
- * Removed Normalise() function from PRect as all rectangles should be inherently normal.
- *
- * Revision 1.13 1994/11/28 12:35:42 robertj
- * Fixed closure of channel not clearing the keyboard stream.
- * Moved saved cursor position variables to PAnsiTerminal.
- *
- * Revision 1.12 1994/10/30 11:52:02 robertj
- * Fixed bug in auto scrolling vertical scroll bar position.
- *
- * Revision 1.11 1994/10/23 03:40:23 robertj
- * Fixed scrolling wrong direction.
- * Added ReturnOnLineFeed option.
- * Added capability of setting cursor type.
- * Improved the channel.
- *
- * Revision 1.10 1994/09/25 10:48:32 robertj
- * Added boundary condition tests.
- *
- * Revision 1.9 1994/08/21 23:43:02 robertj
- * Bug fixes.
- *
- * Revision 1.8 1994/08/01 03:41:24 robertj
- * Use of PNEW instead of new for heap debugging. Need undef for Unix end.
- *
- * Revision 1.7 1994/07/27 05:58:07 robertj
- * Synchronisation.
- *
- * Revision 1.6 1994/07/25 03:38:07 robertj
- * Changed variables to int for better portability.
- *
- * Revision 1.5 1994/07/21 12:33:49 robertj
- * Moved cooperative threads to common.
- *
- * Revision 1.4 1994/07/17 10:46:06 robertj
- * Major redesign to get list instead of array for line data.
- *
- * Revision 1.3 1994/06/25 11:55:15 robertj
- * Unix version synchronisation.
- *
- * Revision 1.2 1994/04/20 12:17:44 robertj
- * some implementation
- *
- * Revision 1.1 1994/04/01 14:27:01 robertj
- * Initial revision
- */
- #ifdef __GNUC__
- #pragma implementation "ansiterm.h"
- #endif
- #include <pwlib.h>
- #include <pwclib/ansiterm.h>
- #include <limits.h>
- #define new PNEW
- PTerminal::PTerminal(PScroller * parent, ostream * kbd)
- : PScrollable(parent)
- {
- keyboard = kbd;
- PScrollable::SetFont(PFont("Courier", 10));
- SetCursor(PCursor(PSTD_ID_CURSOR_IBEAM));
- variableRowColumns = TRUE;
- blockCursor = TRUE;
- lineFeedOnReturn = FALSE;
- returnOnLineFeed = FALSE;
- localEcho = FALSE;
- wrapEOL = FALSE;
- columns = 80;
- rows = 25;
- maxSavedRows = 0;
- columnModeSelection = FALSE;
- updateColumn = 0;
- Reset();
- GrabFocus();
- ShowCaret();
- }
- PTerminal::Row::Row(Attribute attribute)
- {
- for (PINDEX i = 0; i < MaxColumns; i++)
- attrib[i] = attribute;
- memset(ascii, ' ', sizeof(ascii));
- }
- void PTerminal::Reset()
- {
- cellWidth = font.GetAvgWidth(TRUE);
- cellHeight = font.GetHeight(TRUE);
- SetScaleFactor(cellWidth, cellHeight);
- cursorRow = cursorColumn = 0;
- caret.SetDimensions(blockCursor ? cellWidth : 1, cellHeight);
- SetCaretPos(0, 0, PixelCoords);
- PDim dim = GetDimensions(PixelCoords);
- columnsVisible = dim.Width()/cellWidth;
- if (columnsVisible > Row::MaxColumns)
- columnsVisible = Row::MaxColumns;
- rowsVisible = dim.Height()/cellHeight;
- if (variableRowColumns) {
- columns = columnsVisible > 1 ? columnsVisible : 2;
- rows = rowsVisible > 1 ? rowsVisible : 2;
- }
- scrollTop = 0;
- scrollBottom = rows;
- attribute.bold = FALSE;
- attribute.underline = FALSE;
- attribute.blink = FALSE;
- attribute.inverse = FALSE;
- attribute.selected = FALSE;
- attribute.fgColor = 8; // Window fg colour
- attribute.bkColor = 9; // Window bk colour
- rowData.RemoveAll();
- for (PINDEX i = 0; i < rows; i++)
- rowData.Append(new Row(attribute));
- SetScrollRange(PRect(0, 0, columns, rows));
- anchor = selection = 0;
- Invalidate();
- }
- void PTerminal::SetFont(const PFont & newFont, BOOL toChildren)
- {
- PScrollable::SetFont(newFont, toChildren);
- cellWidth = font.GetAvgWidth(TRUE);
- cellHeight = font.GetHeight(TRUE);
- SetScaleFactor(cellWidth, cellHeight);
- caret.SetDimensions(blockCursor ? cellWidth : 1, cellHeight);
- SetDimensions(GetDimensions(PixelCoords), PixelCoords);
- Invalidate();
- }
- void PTerminal::_SetDimensions(PDIMENSION width, PDIMENSION height,
- CoordinateSystem coords)
- {
- PScrollable::_SetDimensions(width, height, coords);
- PDim dim = GetDimensions(PixelCoords);
- columnsVisible = dim.Width()/cellWidth;
- if (columnsVisible > Row::MaxColumns)
- columnsVisible = Row::MaxColumns;
- rowsVisible = dim.Height()/cellHeight;
- if (variableRowColumns) {
- variableRowColumns = FALSE;
- SetColumns(columnsVisible);
- SetRows(rowsVisible);
- variableRowColumns = TRUE;
- }
- else
- SetScrollRange(PRect(0, 0, columns, rowData.GetSize()));
- }
- void PTerminal::Row::AdjustSelection(PINDEX start, PINDEX finish, BOOL select)
- {
- for (PINDEX col = start; col < finish; col++)
- attrib[col].selected = select;
- }
- void PTerminal::AdjustSelection(PCanvas & canvas,
- PINDEX start, PINDEX finish, BOOL select)
- {
- if (start == finish)
- return;
- if (start > finish) {
- PINDEX tmp = start;
- start = finish;
- finish = tmp;
- }
- PINDEX firstRow = start/Row::MaxColumns;
- PINDEX lastRow = finish/Row::MaxColumns;
- PINDEX firstCol = start%Row::MaxColumns;
- PINDEX lastCol = finish%Row::MaxColumns;
- if (columnModeSelection) {
- if (firstCol > lastCol) {
- PINDEX tmp = lastCol;
- lastCol = firstCol;
- firstCol = tmp;
- }
- for (PINDEX row = firstRow; row <= lastRow; row++) {
- rowData[row].AdjustSelection(0, Row::MaxColumns, FALSE);
- if (select)
- rowData[row].AdjustSelection(firstCol, lastCol, select);
- rowData[row].Draw(this, canvas, row - origin.Y(), 0);
- }
- }
- else {
- for (PINDEX row = firstRow; row <= lastRow; row++) {
- rowData[row].AdjustSelection(firstCol,
- row < lastRow ? (int)Row::MaxColumns : lastCol, select);
- rowData[row].Draw(this, canvas, row - origin.Y(), 0);
- firstCol = 0;
- }
- }
- }
- void PTerminal::OnMouseTrack(PCanvas * canvas,
- const PPoint & where, BOOL lastTrack)
- {
- PINDEX pos = origin.Y()*Row::MaxColumns + origin.X();
- if (where.Y() > 0)
- pos += (where.Y()/cellHeight)*Row::MaxColumns;
- if (where.X() > 0)
- pos += (where.X() + cellWidth/2)/cellWidth;
- if (pos >= rowData.GetSize()*Row::MaxColumns)
- pos = rowData.GetSize()*Row::MaxColumns - 1;
- if (pos == selection)
- return;
- if ((pos >= anchor && selection < anchor) ||
- (pos <= anchor && selection > anchor)) {
- AdjustSelection(*canvas, anchor, selection, FALSE);
- selection = anchor;
- }
- if (columnModeSelection) {
- if ((pos > anchor && pos < selection) ||
- (pos < anchor && pos > selection))
- AdjustSelection(*canvas, selection, pos, FALSE);
- AdjustSelection(*canvas, anchor, pos, TRUE);
- }
- else
- AdjustSelection(*canvas, pos, selection,
- (pos > anchor && pos > selection) || (pos < anchor && pos < selection));
- selection = pos;
- if (lastTrack)
- UpdateCommandSources();
- }
- void PTerminal::OnMouseDown(PKeyCode button, const PPoint & where, BOOL)
- {
- GrabFocus();
- PCanvas * canvas = StartMouseTrack(TRUE);
- PINDEX pos = (origin.Y() + where.Y()/cellHeight)*Row::MaxColumns +
- origin.X() + (where.X()+cellWidth/2)/cellWidth;
- if (pos >= rowData.GetSize()*Row::MaxColumns)
- pos = rowData.GetSize()*Row::MaxColumns - 1;
- if (HasSelection() && button.IsModifier(PKeyCode::Shift)) {
- if ((anchor > selection && pos > anchor) ||
- (anchor < selection && pos < anchor)) {
- PINDEX tmp = anchor;
- anchor = selection;
- selection = tmp;
- }
- OnMouseTrack(canvas, where, FALSE);
- }
- else {
- AdjustSelection(*canvas, anchor, selection, FALSE);
- anchor = selection = pos;
- columnModeSelection = button.IsModifier(PKeyCode::Control);
- }
- }
- void PTerminal::OnKeyInput(const PString & str)
- {
- if (keyboard != NULL) {
- *keyboard << str;
- keyboard->flush();
- if (localEcho)
- Write(str);
- }
- }
- void PTerminal::Row::Draw(PTerminal * term,
- PCanvas & canvas, PINDEX line, PINDEX lastCol)
- {
- static PColour colour[10] = {
- PColour::Black,
- PColour::Red,
- PColour::Yellow,
- PColour::Green,
- PColour::Blue,
- PColour::Magenta,
- PColour::Cyan,
- PColour::White,
- PApplication::Current().GetWindowFgColour(),
- PApplication::Current().GetWindowBkColour()
- };
- PDIMENSION origins[MaxColumns];
- for (int i = 0; i < MaxColumns; i++)
- origins[i] = term->cellWidth;
- WORD lastAttr = *(WORD *)&attrib[0];
- PINDEX col = lastCol;
- while (lastCol < term->columnsVisible) {
- col++;
- if (lastAttr != *(WORD *)&attrib[col] || col >= term->columnsVisible) {
- if (col > lastCol) {
- Attribute attr = attrib[lastCol];
- if (attr.inverse ^ attr.selected) {
- canvas.SetTextFgColour(colour[attr.bkColor]);
- canvas.SetTextBkColour(colour[attr.fgColor]);
- }
- else {
- canvas.SetTextFgColour(colour[attr.fgColor]);
- canvas.SetTextBkColour(colour[attr.bkColor]);
- }
- WORD styles = PFont::Regular;
- if (attr.bold)
- styles |= PFont::Bold;
- if (attr.underline)
- styles |= PFont::Underline;
- PFont newFont(term->font.GetFacename(), term->font.GetSize(), styles);
- canvas.SetFont(newFont);
- canvas.DrawTextLine(lastCol*term->cellWidth,
- line*term->cellHeight, &ascii[lastCol], origins, col - lastCol);
- }
- lastAttr = *(WORD *)&attrib[col];
- lastCol = col;
- }
- }
- }
- void PTerminal::OnRedraw(PCanvas & canvas)
- {
- HideCaret();
- canvas.SetMappingRect(canvas.GetViewportRect());
- canvas.SetOrigin(PPoint(origin.X()*scaleFactor.X(), 0));
- PINDEX lastRow = PMIN(rowData.GetSize(), rowsVisible);
- PINDEX bottom = origin.Y() + lastRow;
- canvas.SetPenFgColour(GetBackgroundColour());
- canvas.DrawRect(0, lastRow*cellHeight, 30000, 30000);
- for (PINDEX line = 1; line <= lastRow; line++)
- rowData[bottom - line].Draw(this, canvas, lastRow - line, 0);
- ShowCaret();
- }
- PString PTerminal::GetRow(PINDEX idx) const
- {
- if (idx >= GetTotalRows())
- return PString();
- return rowData[idx].GetText();
- }
- BOOL PTerminal::HasSelection() const
- {
- return anchor != selection;
- }
- PString PTerminal::Row::GetText() const
- {
- PINDEX len = sizeof(ascii)-1;
- while (len > 0 && ascii[len] == ' ')
- len--;
- return PString(ascii, len);
- }
- PString PTerminal::Row::GetSelection() const
- {
- PINDEX firstCol = 0;
- while (firstCol < MaxColumns && !attrib[firstCol].selected)
- firstCol++;
- PINDEX lastCol = MaxColumns - 1;
- while (lastCol > firstCol && (!attrib[lastCol].selected || ascii[lastCol] == ' '))
- lastCol--;
- if (lastCol >= firstCol)
- return PString(&ascii[firstCol], lastCol - firstCol + 1);
- else
- return PString();
- }
- PString PTerminal::GetSelection() const
- {
- PString str;
- if (HasSelection()) {
- PINDEX row = PMIN(anchor, selection)/Row::MaxColumns;
- PINDEX finish = PMAX(anchor, selection)/Row::MaxColumns;
- while (row <= finish)
- str += rowData[row++].GetSelection() + "rn";
- }
- return str;
- }
- void PTerminal::SetSelection(PINDEX startRow, PINDEX startColumn,
- PINDEX finishRow, PINDEX finishColumn)
- {
- anchor = startRow*Row::MaxColumns + startColumn;
- selection = finishRow*Row::MaxColumns + finishColumn;
- Invalidate();
- }
- void PTerminal::SetKeyboardStream(ostream * kbd)
- {
- keyboard = kbd;
- }
- void PTerminal::SetMaxSavedRows(PINDEX newRows)
- {
- maxSavedRows = newRows;
- if (maxSavedRows != 0 && rowData.GetSize() > maxSavedRows+rows)
- rowData.SetSize(maxSavedRows+rows);
- }
- void PTerminal::SetVariableRowColumns(BOOL b)
- {
- variableRowColumns = b;
- if (variableRowColumns)
- SetDimensions(GetDimensions(PixelCoords), PixelCoords);
- else {
- SetRows(rowsVisible > 0 ? rowsVisible : 25);
- SetColumns(columnsVisible > 1 ? columnsVisible : (int)Row::MaxColumns);
- }
- }
- void PTerminal::SetRows(PINDEX newRows)
- {
- if (variableRowColumns) {
- SetDimensions(GetDimensions(PixelCoords), PixelCoords);
- return;
- }
- if (newRows < 2)
- newRows = 2;
- if (scrollTop >= newRows)
- scrollTop = newRows - 1;
- if (scrollBottom == rows || scrollBottom > newRows)
- scrollBottom = newRows;
- if (newRows <= rows)
- AdjustCaretPosition((int)newRows - (int)rows, 0);
- else {
- for (PINDEX i = rows; i < newRows; i++)
- rowData.Append(new Row(attribute));
- SetScrollRange(PRect(0, 0, columns, rowData.GetSize()));
- }
- rows = newRows;
- }
- void PTerminal::SetColumns(PINDEX newColumns)
- {
- if (variableRowColumns) {
- SetDimensions(GetDimensions(PixelCoords), PixelCoords);
- return;
- }
- if (newColumns < 2)
- newColumns = 2;
- else if (newColumns > Row::MaxColumns)
- newColumns = Row::MaxColumns;
- if (columns != newColumns)
- SetScrollRange(PRect(0, 0, columns, rowData.GetSize()));
- columns = newColumns;
- }
- void PTerminal::AdjustCaretPosition(int dLine, int dCol)
- {
- cursorColumn += dCol;
- if ((int)cursorColumn < 0)
- cursorColumn = 0;
- else if (cursorColumn >= columns)
- cursorColumn = columns-1;
- cursorRow += dLine;
- if ((int)cursorRow < (int)scrollTop) // Need signed compare here
- cursorRow = scrollTop;
- else if (cursorRow >= scrollBottom)
- cursorRow = scrollBottom-1;
- SetCaretPos(cursorColumn*cellWidth,
- blockCursor ? cursorRow*cellHeight : (cursorRow+1)*cellHeight-1,
- PixelCoords);
- }
- void PTerminal::MoveCaretPosition(PDrawCanvas & canvas, int dLine, int dCol)
- {
- PINDEX absRow = rowData.GetSize() - rows + cursorRow;
- rowData[absRow].Draw(this, canvas, absRow - origin.Y(), updateColumn);
- AdjustCaretPosition(dLine, dCol);
- updateColumn = cursorColumn;
- if (absRow < (PINDEX)origin.Y() ||
- absRow >= (PINDEX)origin.Y()+rowsVisible ||
- cursorColumn < (PINDEX)origin.X() ||
- cursorColumn >= (PINDEX)origin.X()+columnsVisible)
- ScrollTo(cursorColumn-columnsVisible, cursorRow);
- }
- void PTerminal::SetBlockCursor(BOOL b)
- {
- blockCursor = b;
- caret.SetDimensions(blockCursor ? cellWidth : 1, cellHeight);
- }
- PTerminal::Row & PTerminal::GetCursorRow()
- {
- return rowData[rowData.GetSize() - rows + cursorRow];
- }
- void PTerminal::ScrollLines(PDrawCanvas & canvas,
- PINDEX top, PINDEX bottom, int lines)
- {
- PAssert(lines != 0 && bottom > top, PInvalidParameter);
- HideCaret();
- Update(); // Make sure interactor is up to date (fully redrawn)
- MoveCaretPosition(canvas, 0, 0);
- PINDEX totalRows = rowData.GetSize();
- int topRow = totalRows - rows + top;
- int bottomRow = totalRows - rows + bottom;
- int absLines = PABS(lines);
- if (absLines > (int)(bottom - top))
- absLines = bottom - top;
- if (lines > 0 && top == 0) {
- while (absLines-- > 0)
- rowData.InsertAt(bottomRow, new Row(attribute));
- if (maxSavedRows != 0 && rowData.GetSize() > maxSavedRows+rows)
- rowData.SetSize(maxSavedRows+rows);
- if (rowData.GetSize() != totalRows) {
- SetScrollRange(PRect(0, 0, columns, rowData.GetSize()));
- ScrollTo(0, rowData.GetSize());
- }
- }
- else {
- PRect scrollRect(0, top*cellHeight, 30000, (bottom - top)*cellHeight);
- PDIMENSION scrollAmount = absLines*cellHeight;
- BOOL doScroll = scrollAmount < scrollRect.Height();
- if (lines > 0) {
- while (absLines-- > 0) {
- rowData.InsertAt(bottomRow, new Row(attribute));
- rowData.RemoveAt(topRow);
- }
- if (doScroll) {
- PDrawCanvas canvas(this, TRUE);
- canvas.Scroll(0, -(PORDINATE)scrollAmount, scrollRect);
- scrollRect.SetTop(scrollRect.Bottom() - scrollAmount);
- }
- }
- else {
- while (absLines-- > 0) {
- rowData.RemoveAt(bottomRow-1);
- rowData.InsertAt(topRow, new Row(attribute));
- }
- if (doScroll) {
- PDrawCanvas canvas(this, TRUE);
- canvas.Scroll(0, scrollAmount, scrollRect);
- scrollRect.SetHeight(scrollAmount);
- }
- }
- Invalidate(scrollRect, PixelCoords);
- }
- ShowCaret();
- }
- void PTerminal::Row::Scroll(PTerminal * term, PCanvas & canvas,
- PINDEX line, PINDEX left, PINDEX right, int columns)
- {
- PAssert(columns != 0 && right > left, PInvalidParameter);
- if (right >= MaxColumns)
- right = MaxColumns-1;
- PINDEX absCols = PABS(columns);
- if (absCols > right - left)
- absCols = right - left;
- if (columns < 0) {
- memmove(&attrib[left+absCols], &attrib[left], (right-left-absCols)*sizeof(attrib[0]));
- for (PINDEX i = 0; i < absCols; i++)
- attrib[left+i] = term->attribute;
- memmove(&ascii[left+absCols], &ascii[left], (right-left-absCols)*sizeof(ascii[0]));
- memset(&ascii[left], ' ', absCols*sizeof(ascii[0]));
- }
- else {
- memmove(&attrib[left], &attrib[left+absCols], (right-left-absCols)*sizeof(attrib[0]));
- for (PINDEX i = 0; i < absCols; i++)
- attrib[right-absCols+i] = term->attribute;
- memmove(&ascii[left], &ascii[left+absCols], (right-left-absCols)*sizeof(ascii[0]));
- memset(&ascii[right-absCols], ' ', absCols*sizeof(ascii[0]));
- }
- Draw(term, canvas, line, left);
- }
- void PTerminal::Write(const char * buf, PINDEX len)
- {
- if (len <= 0 || (len == 1 && *buf == ' '))
- return;
- PDrawCanvas updateCanvas(this, TRUE);
- updateCanvas.SetOrigin(PPoint(origin.X()*scaleFactor.X(), 0));
- HideCaret();
- MoveCaretPosition(updateCanvas, 0, 0);
- for (PINDEX i = 0; i < len; i++)
- ProcessCharacter(updateCanvas, *buf++);
- MoveCaretPosition(updateCanvas, 0, 0);
- ShowCaret();
- }
- void PTerminal::ProcessCharacter(PDrawCanvas & canvas, char ch)
- {
- switch (ch) {
- case 'a' :
- PSound::Beep();
- break;
- case 'b' :
- MoveCaretPosition(canvas, 0, -1);
- break;
- case ' 13' : // ^K
- MoveCaretPosition(canvas, -1, 0);
- break;
- case ' 14' : // ^L
- MoveCaretPosition(canvas, 0, 1);
- break;
- case 't' :
- MoveCaretPosition(canvas, 0, 8 - cursorColumn%8);
- break;
- case 'r' :
- MoveCaretPosition(canvas, 0, -(int)cursorColumn);
- if (!lineFeedOnReturn)
- break;
- // Else do line feed case
- case 'n' :
- if (cursorRow < scrollBottom-1)
- MoveCaretPosition(canvas, 1, 0);
- else
- ScrollLines(canvas, scrollTop, scrollBottom, 1);
- if (returnOnLineFeed)
- MoveCaretPosition(canvas, 0, -(int)cursorColumn);
- break;
- case 'x7f' : // DEL
- if (cursorColumn > 0) {
- MoveCaretPosition(canvas, 0, -1);
- GetCursorRow().SetCell(cursorColumn, ' ', attribute);
- }
- break;
- default :
- GetCursorRow().SetCell(cursorColumn, ch, attribute);
- if (cursorColumn < columns-1)
- AdjustCaretPosition(0, 1);
- else if (wrapEOL) {
- ProcessCharacter(canvas, 'r');
- ProcessCharacter(canvas, 'n');
- }
- }
- }
- ///////////////////////////////////////////////////////////////////////////////
- PAnsiTerminal::PAnsiTerminal(PScroller * parent, ostream * kbd)
- : PTerminal(parent, kbd)
- {
- Reset();
- }
- void PAnsiTerminal::Reset()
- {
- PTerminal::Reset();
- inEscapeSequence = FALSE;
- savedCursorRow = savedCursorColumn = 0;
- }
- BOOL PAnsiTerminal::OnKeyDown(PKeyCode key, unsigned repeat)
- {
- static const struct {
- PKeyCode::Value value;
- const char * sequence;
- } ansikeys[] = {
- { PKeyCode::F1, "