From 94be8cb5150e428a328983fdb03e85c5f62f1079 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Mon, 2 Dec 2002 20:14:03 +0000 Subject: [PATCH] BTextView implementation by Marc Flerackers (with few additions of mine). Still incomplete, it works, tough. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2127 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kits/interface/BTextView/LineBuffer.cpp | 135 ++ src/kits/interface/BTextView/LineBuffer.h | 75 + src/kits/interface/BTextView/StyleBuffer.cpp | 156 ++ src/kits/interface/BTextView/StyleBuffer.h | 99 + .../interface/BTextView/TextGapBuffer.cpp | 137 ++ src/kits/interface/BTextView/TextGapBuffer.h | 77 + src/kits/interface/BTextView/TextView.cpp | 1637 +++++++++++++++++ src/kits/interface/BTextView/TextView.h | 445 +++++ .../BTextView/TextViewSupportBuffer.h | 104 ++ 9 files changed, 2865 insertions(+) create mode 100644 src/kits/interface/BTextView/LineBuffer.cpp create mode 100644 src/kits/interface/BTextView/LineBuffer.h create mode 100644 src/kits/interface/BTextView/StyleBuffer.cpp create mode 100644 src/kits/interface/BTextView/StyleBuffer.h create mode 100644 src/kits/interface/BTextView/TextGapBuffer.cpp create mode 100644 src/kits/interface/BTextView/TextGapBuffer.h create mode 100644 src/kits/interface/BTextView/TextView.cpp create mode 100644 src/kits/interface/BTextView/TextView.h create mode 100644 src/kits/interface/BTextView/TextViewSupportBuffer.h diff --git a/src/kits/interface/BTextView/LineBuffer.cpp b/src/kits/interface/BTextView/LineBuffer.cpp new file mode 100644 index 0000000000..53f5be6b9d --- /dev/null +++ b/src/kits/interface/BTextView/LineBuffer.cpp @@ -0,0 +1,135 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2001-2002, OpenBeOS +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// File Name: LineBuffer.cpp +// Author: Marc Flerackers (mflerackers@androme.be) +// Description: Line storage used by BTextView +//------------------------------------------------------------------------------ + +// Standard Includes ----------------------------------------------------------- +#include + +// System Includes ------------------------------------------------------------- +#include "LineBuffer.h" + +// Project Includes ------------------------------------------------------------ + +// Local Includes -------------------------------------------------------------- + +// Local Defines --------------------------------------------------------------- + +// Globals --------------------------------------------------------------------- + +//------------------------------------------------------------------------------ +_BLineBuffer_::_BLineBuffer_() + : fBlockSize(20), + fItemCount(2), + fPhysicalSize(22), + fObjectList(NULL) +{ + fObjectList = new STELine[fPhysicalSize]; + + memset(fObjectList, 0, fPhysicalSize * sizeof(STELine)); +} +//------------------------------------------------------------------------------ +_BLineBuffer_::~_BLineBuffer_() +{ + delete[] fObjectList; +} +//------------------------------------------------------------------------------ +void _BLineBuffer_::InsertLine(STELine *line, int32 index) +{ + if (fItemCount == fPhysicalSize - 1) + { + STELine *new_list = new STELine[fPhysicalSize + fBlockSize]; + + memcpy(new_list, fObjectList, fPhysicalSize * sizeof(STELine)); + delete fObjectList; + fObjectList = new_list; + + fPhysicalSize += fBlockSize; + } + + if (index < fItemCount) + memmove(fObjectList + index + 1, fObjectList + index, + (fItemCount - index) * sizeof(STELine)); + memcpy(fObjectList + index, line, sizeof(STELine)); + + fItemCount++; +} +//------------------------------------------------------------------------------ +void _BLineBuffer_::RemoveLines(int32 index, int32 count) +{ + memmove(fObjectList + index, fObjectList + index + count, + (fItemCount - index - count) * sizeof(STELine)); + + fItemCount -= count; +} +//------------------------------------------------------------------------------ +void _BLineBuffer_::RemoveLineRange(int32 from, int32 to) +{ + int32 linefrom = OffsetToLine(from); + int32 lineto = OffsetToLine(to); + + if (linefrom < lineto) + RemoveLines(linefrom + 1, lineto - linefrom); + + BumpOffset(linefrom + 1, from - to); +} +//------------------------------------------------------------------------------ +int32 _BLineBuffer_::OffsetToLine(int32 offset) const +{ + if (offset == 0) + return 0; + + for (int i = 0; i < fItemCount; i++) + { + if (offset < fObjectList[i].fOffset) + return i - 1; + } + + return fItemCount - 2; +} +//------------------------------------------------------------------------------ +int32 _BLineBuffer_::PixelToLine(float height) const +{ + for (int i = 0; i < fItemCount; i++) + { + if (height < fObjectList[i].fHeight) + return i - 1; + } + + return fItemCount - 2; +} +//------------------------------------------------------------------------------ +void _BLineBuffer_::BumpOffset(int32 line, int32 offset) +{ + for (int i = line; i < fItemCount; i++) + fObjectList[i].fOffset += offset; +} +//------------------------------------------------------------------------------ + +/* + * $Log $ + * + * $Id $ + * + */ diff --git a/src/kits/interface/BTextView/LineBuffer.h b/src/kits/interface/BTextView/LineBuffer.h new file mode 100644 index 0000000000..437e55c99e --- /dev/null +++ b/src/kits/interface/BTextView/LineBuffer.h @@ -0,0 +1,75 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2001-2002, OpenBeOS +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// File Name: LineBuffer.h +// Author: Marc Flerackers (mflerackers@androme.be) +// Description: Line storage used by BTextView +//------------------------------------------------------------------------------ + +// Standard Includes ----------------------------------------------------------- + +// System Includes ------------------------------------------------------------- +#include "SupportDefs.h" + +// Project Includes ------------------------------------------------------------ + +// Local Includes -------------------------------------------------------------- + +// Local Defines --------------------------------------------------------------- +struct STELine { + int32 fOffset; + float fHeight; + float fLineHeight; + float fWidth; +}; + +// Globals --------------------------------------------------------------------- + +// _BLineBuffer_ class --------------------------------------------------------- +class _BLineBuffer_ { + +public: + _BLineBuffer_(); +virtual ~_BLineBuffer_(); + + void InsertLine(STELine *line, int32); + void RemoveLines(int32 index, int32 count); + void RemoveLineRange(int32 from, int32 to); + + int32 OffsetToLine(int32 offset) const; + int32 PixelToLine(float height) const; + + void BumpOffset(int32 line, int32 offset); + void BumpOrigin(float, int32); + + int32 fBlockSize; + int32 fItemCount; + size_t fPhysicalSize; + STELine *fObjectList; +}; +//------------------------------------------------------------------------------ + +/* + * $Log $ + * + * $Id $ + * + */ diff --git a/src/kits/interface/BTextView/StyleBuffer.cpp b/src/kits/interface/BTextView/StyleBuffer.cpp new file mode 100644 index 0000000000..d4a1910947 --- /dev/null +++ b/src/kits/interface/BTextView/StyleBuffer.cpp @@ -0,0 +1,156 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2001-2002, OpenBeOS +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// File Name: StyleBuffer.cpp +// Author: Marc Flerackers (mflerackers@androme.be) +// Description: Style storage used by BTextView +//------------------------------------------------------------------------------ + +// Standard Includes ----------------------------------------------------------- + +// System Includes ------------------------------------------------------------- +#include "StyleBuffer.h" + +// Project Includes ------------------------------------------------------------ + +// Local Includes -------------------------------------------------------------- + +// Local Defines --------------------------------------------------------------- + +// Globals --------------------------------------------------------------------- + +//------------------------------------------------------------------------------ +_BStyleBuffer_::_BStyleBuffer_(const BFont *font, const rgb_color *color) + : fRuns(10, 10), + fRecords(10, 10) +{ + rgb_color black = {0, 0, 0, 255}; + + SetNullStyle(0, font ? font : be_plain_font, color ? color : &black, 0); +} +//------------------------------------------------------------------------------ +_BStyleBuffer_::~_BStyleBuffer_() +{ +} +//------------------------------------------------------------------------------ +void _BStyleBuffer_::SetNullStyle(uint32 mode, const BFont *font, + const rgb_color *color, int32) +{ + // TODO: use mode. + if (font) + fNullStyle.fFont = *font; + + if (color) + fNullStyle.fColor = *color; +} +//------------------------------------------------------------------------------ +void _BStyleBuffer_::GetNullStyle(const BFont **font, const rgb_color **color) const +{ + *font = &fNullStyle.fFont; + *color = &fNullStyle.fColor; +} +//------------------------------------------------------------------------------ +void _BStyleBuffer_::SyncNullStyle(int32) +{ +} +//------------------------------------------------------------------------------ +void _BStyleBuffer_::InvalidateNullStyle() +{ +} +//------------------------------------------------------------------------------ +bool _BStyleBuffer_::IsValidNullStyle() const +{ + // TODO: why would a style be invalid? + return true; +} +//------------------------------------------------------------------------------ +void _BStyleBuffer_::SetStyle(uint32 mode, const BFont *font, BFont *, + const rgb_color *color, rgb_color *) const +{ +} +//------------------------------------------------------------------------------ +void _BStyleBuffer_::GetStyle(uint32 mode, BFont *font, rgb_color *color) const +{ +} +//------------------------------------------------------------------------------ +void _BStyleBuffer_::SetStyleRange(int32 from, int32 to, int32, uint32 mode, + const BFont *, const rgb_color *) +{ +} +//------------------------------------------------------------------------------ +int32 _BStyleBuffer_::GetStyleRange(int32 from, int32 to) const +{ + return 0; +} +//------------------------------------------------------------------------------ +void _BStyleBuffer_::ContinuousGetStyle(BFont *, uint32 *, rgb_color *, bool *, + int32, int32) const +{ +} +//------------------------------------------------------------------------------ +void _BStyleBuffer_::RemoveStyles(int32 from, int32 to) +{ +} +//------------------------------------------------------------------------------ +void _BStyleBuffer_::RemoveStyleRange(int32 from, int32 to) +{ +} +//------------------------------------------------------------------------------ +int32 _BStyleBuffer_::OffsetToRun(int32 offset) const +{ + if (offset == 0) + return 0; + + for (int i = 0; i < fRuns.fCount; i++) + { + if (offset < fRuns.fItems[i].fOffset) + return i - 1; + } + + return fRuns.fCount - 2; +} +//------------------------------------------------------------------------------ +void _BStyleBuffer_::BumpOffset(int32 run, int32 offset) +{ + for (int i = run; i < fRuns.fCount; i++) + fRuns.fItems[i].fOffset += offset; +} +//------------------------------------------------------------------------------ +/*void _BStyleBuffer_::Iterate(int32, int32, _BInlineInput_ *, const BFont **, + const rgb_color **, float *, uint32 *) const +{ +}*/ +//------------------------------------------------------------------------------ +STEStyleRecord *_BStyleBuffer_::operator[](int32 index) +{ + if (index < fRecords.fCount) + return fRecords.fItems + index; + else + return NULL; +} +//------------------------------------------------------------------------------ + +/* + * $Log $ + * + * $Id $ + * + */ diff --git a/src/kits/interface/BTextView/StyleBuffer.h b/src/kits/interface/BTextView/StyleBuffer.h new file mode 100644 index 0000000000..0f7a0fca61 --- /dev/null +++ b/src/kits/interface/BTextView/StyleBuffer.h @@ -0,0 +1,99 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2001-2002, OpenBeOS +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// File Name: StyleBuffer.h +// Author: Marc Flerackers (mflerackers@androme.be) +// Description: Style storage used by BTextView +//------------------------------------------------------------------------------ + +// Standard Includes ----------------------------------------------------------- + +// System Includes ------------------------------------------------------------- +#include +#include +#include + +// Project Includes ------------------------------------------------------------ + +// Local Includes -------------------------------------------------------------- +#include "TextViewSupportBuffer.h" + +// Local Defines --------------------------------------------------------------- +struct STEStyleRunDesc { + int32 fOffset; + int32 fStyle; +}; + +struct STEStyleRecord { + BFont fFont; + rgb_color fColor; +}; + +// Globals --------------------------------------------------------------------- + +// _BStyleBuffer_ class -------------------------------------------------------- +class _BStyleBuffer_ { + +public: + _BStyleBuffer_(const BFont *, const rgb_color *); +virtual ~_BStyleBuffer_(); + + void SetNullStyle(uint32, const BFont *, const rgb_color *, int32); + void GetNullStyle(const BFont **, const rgb_color **) const; + void SyncNullStyle(int32); + void InvalidateNullStyle(); + bool IsValidNullStyle() const; + + void SetStyle(uint32, const BFont *, BFont *, const rgb_color *, + rgb_color *) const; + void GetStyle(uint32, BFont *, rgb_color *) const; + + void SetStyleRange(int32, int32, int32, uint32 mode, const BFont *, + const rgb_color *); + int32 GetStyleRange(int32, int32) const; + + void ContinuousGetStyle(BFont *, uint32 *, rgb_color *, bool *, + int32, int32) const; + + void RemoveStyles(int32 from, int32 to); + void RemoveStyleRange(int32 from, int32 to); + + int32 OffsetToRun(int32 offset) const; + + void BumpOffset(int32 run, int32 offset); +// void Iterate(int32, int32, _BInlineInput_ *, const BFont **, +// const rgb_color **, float *, uint32 *) const; + + STEStyleRecord *operator[](int32); + +private: + _BTextViewSupportBuffer_ fRuns; + _BTextViewSupportBuffer_ fRecords; + STEStyleRecord fNullStyle; +}; +//------------------------------------------------------------------------------ + +/* + * $Log $ + * + * $Id $ + * + */ diff --git a/src/kits/interface/BTextView/TextGapBuffer.cpp b/src/kits/interface/BTextView/TextGapBuffer.cpp new file mode 100644 index 0000000000..1a5ec05e3a --- /dev/null +++ b/src/kits/interface/BTextView/TextGapBuffer.cpp @@ -0,0 +1,137 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2001-2002, OpenBeOS +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// File Name: TextGapBuffer.cpp +// Author: Marc Flerackers (mflerackers@androme.be) +// Description: Text storage used by BTextView +//------------------------------------------------------------------------------ + +// Standard Includes ----------------------------------------------------------- + +// System Includes ------------------------------------------------------------- + +// Project Includes ------------------------------------------------------------ + +// Local Includes -------------------------------------------------------------- +#include "TextGapBuffer.h" + +// Local Defines --------------------------------------------------------------- + +// Globals --------------------------------------------------------------------- + +//------------------------------------------------------------------------------ +_BTextGapBuffer_::_BTextGapBuffer_() + : fText(NULL), + fLogicalBytes(0), + fPhysicalBytes(2048) +{ + fText = new char[fPhysicalBytes]; + *fText = '\0'; +} +//------------------------------------------------------------------------------ +_BTextGapBuffer_::~_BTextGapBuffer_() +{ + delete[] fText; +} +//------------------------------------------------------------------------------ +void _BTextGapBuffer_::InsertText(const char *text, int32 length, int32 offset) +{ + // If needed, resize buffer + if (fPhysicalBytes < fLogicalBytes + length + 1) + Resize(fLogicalBytes + length + 1); + + // Move text after insertion point + memcpy(fText + offset + length, fText + offset, + fLogicalBytes + 1 - offset); + + // Copy new text + memcpy(fText + offset, text, length); + + // Update used bytes + fLogicalBytes += length; +} +//------------------------------------------------------------------------------ +void _BTextGapBuffer_::RemoveRange(int32 from, int32 to) +{ + // Move text after deletion point + memcpy(fText + from, fText + to, fLogicalBytes + 1 - to); + + // Update used bytes + fLogicalBytes -= to - from; +} +//------------------------------------------------------------------------------ +char *_BTextGapBuffer_::Text() +{ + if (fLogicalBytes == 0 || fText[fLogicalBytes - 1] != '\0') + { + if (fPhysicalBytes < fLogicalBytes + 1) + { + char *new_text = new char[fLogicalBytes + 1]; + + if (fText) + { + memcpy(new_text, fText, fLogicalBytes ); + delete fText; + } + + fText = new_text; + } + + fText[fLogicalBytes] = '\0'; + } + + return fText; +} +//------------------------------------------------------------------------------ +char *_BTextGapBuffer_::RealText() +{ + return fText; +} +//------------------------------------------------------------------------------ +char _BTextGapBuffer_::RealCharAt(int32 offset) const +{ + return *(fText + offset); +} +//------------------------------------------------------------------------------ +void _BTextGapBuffer_::Resize(int32 size) +{ + if (fPhysicalBytes < size) + { + char *text = new char[size]; + + if (fText) + { + memcpy(text, fText, fLogicalBytes); + delete fText; + } + + fText = text; + fPhysicalBytes = size; + } +} +//------------------------------------------------------------------------------ + +/* + * $Log $ + * + * $Id $ + * + */ diff --git a/src/kits/interface/BTextView/TextGapBuffer.h b/src/kits/interface/BTextView/TextGapBuffer.h new file mode 100644 index 0000000000..c8656824fa --- /dev/null +++ b/src/kits/interface/BTextView/TextGapBuffer.h @@ -0,0 +1,77 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2001-2002, OpenBeOS +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// File Name: TextGapBuffer.h +// Author: Marc Flerackers (mflerackers@androme.be) +// Description: Text storage used by BTextView +//------------------------------------------------------------------------------ + +// Standard Includes ----------------------------------------------------------- + +// System Includes ------------------------------------------------------------- +#include "SupportDefs.h" + +// Project Includes ------------------------------------------------------------ + +// Local Includes -------------------------------------------------------------- + +// Local Defines --------------------------------------------------------------- + +// Globals --------------------------------------------------------------------- + +// _BTextGapBuffer_ class ------------------------------------------------------ +class _BTextGapBuffer_ { + +public: + _BTextGapBuffer_(); +virtual ~_BTextGapBuffer_(); + + void InsertText(const char *text, int32 length, int32 offset); + void RemoveRange(int32 from, int32 to); + + char *Text(); + char *RealText(); + void GetString(int32 offset, int32 length, char *buffer); + void GetString(int32, int32 *); + + char RealCharAt(int32 offset) const; + bool FindChar(char c, int32 inOffset, int32 *outOffset); + + void SizeGapTo(int32); + void MoveGapTo(int32); + void InsertText(BFile *, int32, int32, int32); + bool PasswordMode() const; + void SetPasswordMode(bool); + + void Resize(int32 size); + + char *fText; + int32 fLogicalBytes; + int32 fPhysicalBytes; +}; +//------------------------------------------------------------------------------ + +/* + * $Log $ + * + * $Id $ + * + */ diff --git a/src/kits/interface/BTextView/TextView.cpp b/src/kits/interface/BTextView/TextView.cpp new file mode 100644 index 0000000000..d4ea0fec59 --- /dev/null +++ b/src/kits/interface/BTextView/TextView.cpp @@ -0,0 +1,1637 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2001-2002, OpenBeOS +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// File Name: TextView.cpp +// Author: Marc Flerackers (mflerackers@androme.be) +// Description: BTextView displays and manages styled text. +//------------------------------------------------------------------------------ + +// Standard Includes ----------------------------------------------------------- +#include + +// System Includes ------------------------------------------------------------- +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Project Includes ------------------------------------------------------------ + +// Local Includes -------------------------------------------------------------- +#include "TextGapBuffer.h" +#include "LineBuffer.h" +#include "StyleBuffer.h" +#include "moreUTF8.h" +// Local Defines --------------------------------------------------------------- + +// _BTextTrackState_ class ----------------------------------------------------- +class _BTextTrackState_ { + +public: + _BTextTrackState_(bool inSelection) + : fMoved(false), + fInSelection(inSelection) + {} + + bool fMoved; + bool fInSelection; +}; +//------------------------------------------------------------------------------ + +// Globals --------------------------------------------------------------------- +static property_info prop_list[] = +{ + { + "Selection", + { B_GET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the current selection.", 0, + { B_INT32_TYPE, 0 } + }, + { + "Selection", + { B_SET_PROPERTY, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Sets the current selection.", 0, + { B_INT32_TYPE, 0 } + }, + { + "Text", + { B_COUNT_PROPERTIES, 0 }, + { B_DIRECT_SPECIFIER, 0 }, + "Returns the length of the text in bytes.", 0, + { B_INT32_TYPE, 0 } + }, + { + "Text", + { B_GET_PROPERTY, 0 }, + { B_RANGE_SPECIFIER, B_REVERSE_RANGE_SPECIFIER, 0 }, + "Returns the text in the specified range in the BTextView.", 0, + { B_STRING_TYPE, 0 } + }, + { + "Text", + { B_SET_PROPERTY, 0 }, + { B_RANGE_SPECIFIER, B_REVERSE_RANGE_SPECIFIER, 0 }, + "Removes or inserts text into the specified range in the BTextView.", 0, + { B_STRING_TYPE, 0 } + }, + { + "text_run_array", + { B_GET_PROPERTY, 0 }, + { B_RANGE_SPECIFIER, B_REVERSE_RANGE_SPECIFIER, 0 }, + "Returns the style information for the text in the specified range in the BTextView.", 0, + { B_RAW_TYPE, 0 }, + }, + { + "text_run_array", + { B_SET_PROPERTY, 0 }, + { B_RANGE_SPECIFIER, B_REVERSE_RANGE_SPECIFIER, 0 }, + "Sets the style information for the text in the specified range in the BTextView.", 0, + { B_RAW_TYPE, 0 }, + }, + { 0 } +}; + +//------------------------------------------------------------------------------ +BTextView::BTextView(BRect frame, const char *name, BRect textRect, + uint32 resizeMask, uint32 flags) + : BView(frame, name, resizeMask, flags | B_FRAME_EVENTS | B_PULSE_NEEDED), + fText(NULL), + fLines(NULL), + fStyles(NULL), + //fTextRect + fSelStart(0), + fSelEnd(0), + fCaretVisible(true), + //fCaretTime + //fClickOffset + //fClickCount + //fClickTime + //fDragOffset + //fCursor + //fActive + fStylable(false), + fTabWidth(28.0f), + fSelectable(true), + fEditable(true), + fWrap(true), + fMaxBytes(0), + fDisallowedChars(NULL), + fAlignment(B_ALIGN_LEFT), + fAutoindent(false), + fOffscreen(NULL), + fColorSpace(B_CMAP8), + fResizable(false), + fContainerView(NULL), + fUndo(NULL), + fInline(NULL), + fDragRunner(NULL), + fClickRunner(NULL), + //fWhere + fTrackingMouse(NULL), + fTextChange(NULL) +{ + InitObject(textRect, NULL, NULL); +} +//------------------------------------------------------------------------------ +BTextView::BTextView(BRect frame, const char *name, BRect textRect, + const BFont *initialFont, const rgb_color *initialColor, + uint32 resizeMask, uint32 flags) + : BView(frame, name, resizeMask, flags | B_FRAME_EVENTS), + fText(NULL), + fLines(NULL), + fStyles(NULL), + //fTextRect + fSelStart(0), + fSelEnd(0), + fCaretVisible(true), + //fCaretTime + //fClickOffset + //fClickCount + //fClickTime + //fDragOffset + //fCursor + //fActive + fStylable(false), + fTabWidth(28.0f), + fSelectable(true), + fEditable(true), + fWrap(true), + fMaxBytes(0), + fDisallowedChars(NULL), + fAlignment(B_ALIGN_LEFT), + fAutoindent(false), + fOffscreen(NULL), + fColorSpace(B_CMAP8), + fResizable(false), + fContainerView(NULL), + fUndo(NULL), + fInline(NULL), + fDragRunner(NULL), + fClickRunner(NULL), + //fWhere + fTrackingMouse(NULL), + fTextChange(NULL) +{ + InitObject(textRect, initialFont, initialColor); +} +//------------------------------------------------------------------------------ +BTextView::BTextView(BMessage *archive) + : BView(archive) +{ + archive->AddString("_text", Text()); + archive->AddInt32("_align", fAlignment); + archive->AddFloat("_tab", fTabWidth); + archive->AddInt32("_col_sp", fColorSpace); + archive->AddRect("_trect", fTextRect); + archive->AddInt32("_max", fMaxBytes); + archive->AddInt32("_sel", fSelStart); + archive->AddInt32("_sel", fSelEnd); + //"_dis_ch" (array) B_RAW_TYPE Disallowed characters. + //"_runs" B_RAW_TYPE Flattened run array. + archive->AddBool("_stylable", fStylable); + archive->AddBool("_auto_in", fAutoindent); + archive->AddBool("_wrap", fWrap); + archive->AddBool("_nsel", !fSelectable); + archive->AddBool("_nedit", !fEditable); +} +//------------------------------------------------------------------------------ +BTextView::~BTextView() +{ + delete fText; + delete fLines; +} +//------------------------------------------------------------------------------ +BArchivable *BTextView::Instantiate(BMessage *archive) +{ + if (validate_instantiation(archive, "BTextView")) + return new BTextView(archive); + else + return NULL; +} +//------------------------------------------------------------------------------ +status_t BTextView::Archive(BMessage *data, bool deep) const +{ + // TODO: write archive + return BView::Archive(data, deep); +} +//------------------------------------------------------------------------------ +void BTextView::AttachedToWindow() +{ + // TODO: set drawing mode to B_OP_COPY, adjust scrollbars, enable and set + // pulse +} +//------------------------------------------------------------------------------ +void BTextView::DetachedFromWindow() +{ + //TODO: if cursor in bounds, reset it to B_HAND_CURSOR +} +//------------------------------------------------------------------------------ +void BTextView::Draw(BRect updateRect) +{ + int32 from = 0, to = 0; + + while (fLines->fObjectList[from].fHeight + fLines->fObjectList[from].fLineHeight + < updateRect.top && from < CountLines()) + from++; + + while (to < fLines->fItemCount - 2 && + fLines->fObjectList[to].fHeight + fLines->fObjectList[to].fLineHeight + < updateRect.bottom && to < CountLines()) + to++; + + if (from > 0) + from--; + + const BFont *font; + const rgb_color *color; + + fStyles->GetNullStyle(&font, &color); + + SetFont(font); + SetHighColor(*color); + + DrawLines(from, to, 0, false); + + if (IsFocus()) + { + if (fSelStart == fSelEnd) + { + /*float caretHeight; + BPoint caret = PointAt(fSelStart, &caretHeight); + StrokeLine(BPoint(caret.x, caret.y), + BPoint(caret.x, caret.y + caretHeight));*/ + if (fCaretVisible) + DrawCaret(fSelStart); + } + else + Highlight(fSelStart, fSelEnd); + } +} +//------------------------------------------------------------------------------ +void BTextView::MouseDown(BPoint where) +{ + MakeFocus(); + SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); + + fClickOffset = OffsetAt(where); + fTrackingMouse = new _BTextTrackState_(fSelStart < fClickOffset && + fClickOffset < fSelEnd); + + if (!fTrackingMouse->fInSelection) + Select (fClickOffset, fClickOffset); + + SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY | B_SUSPEND_VIEW_FOCUS); +} +//------------------------------------------------------------------------------ +void BTextView::MouseUp(BPoint where) +{ + if (fTrackingMouse) + { + if (!fTrackingMouse->fMoved) + Select(fClickOffset, fClickOffset); + + delete fTrackingMouse; + fTrackingMouse = NULL; + } +} +//------------------------------------------------------------------------------ +void BTextView::MouseMoved(BPoint where, uint32 code, const BMessage *message) +{ + // TODO: cursor changing, and message tracking + switch (code) + { + case B_EXITED_VIEW: + SetViewCursor(B_CURSOR_SYSTEM_DEFAULT); + break; + default: + SetViewCursor(B_CURSOR_I_BEAM); + break; + } + + if (message == NULL) + { + if (fTrackingMouse) + { + if (fTrackingMouse->fInSelection) + { + BMessage msg(B_SIMPLE_DATA); + + msg.AddData("text/plain", B_MIME_TYPE, fText->Text() + fSelStart, + fSelEnd - fSelStart); + + delete fTrackingMouse; + fTrackingMouse = NULL; + + BBitmap *bitmap = NULL; + BPoint point; + BHandler *handler = this; + + GetDragParameters(&msg, &bitmap, &point, &handler); + + DragMessage(&msg, bitmap, point, handler); + } + else + { + int32 offset = OffsetAt(where); + + if (offset < fClickOffset) + Select(offset, fClickOffset); + else + Select(fClickOffset, offset); + + fTrackingMouse->fMoved = true; + } + } + } + else + { + int32 offset = OffsetAt(where); + + Select(offset, offset); + } +} +//------------------------------------------------------------------------------ +void BTextView::WindowActivated(bool state) +{ + if (!state) + fCaretVisible = false; + + Invalidate(); + // TODO: handle highlighting when state changes +} +//------------------------------------------------------------------------------ +void BTextView::KeyDown(const char *bytes, int32 numBytes) +{ + char key = bytes[0]; + + switch (key) + { + case B_BACKSPACE: + HandleBackspace(); + break; + case B_LEFT_ARROW: + case B_RIGHT_ARROW: + HandleArrowKey(key); + break; + case B_DELETE: + HandleDelete(); + break; + case B_PAGE_UP: + case B_PAGE_DOWN: + HandlePageKey(key); + break; + default: + HandleAlphaKey(bytes, numBytes); + } +} +//------------------------------------------------------------------------------ +void BTextView::Pulse() +{ + // TODO: blink caret + if (Window()->IsActive() && IsFocus()) + { + fCaretVisible = !fCaretVisible; + + if (fSelStart == fSelEnd) + InvertCaret(); + } +} +//------------------------------------------------------------------------------ +void BTextView::FrameResized(float width, float height) +{ + // TODO: update scrollbars +} +//------------------------------------------------------------------------------ +void BTextView::MakeFocus(bool focusState) +{ + // TODO: change highlight according to focusState + BView::MakeFocus(focusState); + + Invalidate(); +} +//------------------------------------------------------------------------------ +void BTextView::MessageReceived(BMessage *message) +{ + // TODO: Handle scripting + switch (message->what) + { + case B_CUT: + Cut(be_clipboard); + break; + case B_COPY: + Copy(be_clipboard); + break; + case B_PASTE: + Paste(be_clipboard); + break; + case B_SELECT_ALL: + SelectAll (); + break; + case B_MIME_DATA: + { + if (!AcceptsDrop(message)) + break; + + const char *text; + ssize_t len; + + if (message->FindData("text/plain", B_MIME_TYPE, (const void**)&text, &len) == B_OK) + { + InsertText(text, len, fSelStart, NULL); + Select(fSelStart, fSelStart + len); + } + + break; + } + default: + BView::MessageReceived(message); + } +} +//------------------------------------------------------------------------------ +BHandler *BTextView::ResolveSpecifier(BMessage *message, int32 index, + BMessage *specifier, int32 form, + const char *property) +{ + BPropertyInfo propInfo(prop_list); + BHandler *target = NULL; + + switch (propInfo.FindMatch(message, 0, specifier, form, property)) + { + case B_ERROR: + break; + + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + target = this; + break; + } + + if (!target) + target = BView::ResolveSpecifier(message, index, specifier, form, + property); + + return target; +} +//------------------------------------------------------------------------------ +status_t BTextView::GetSupportedSuites(BMessage *data) +{ + // TODO: check if the suite name is ok, according to the documentation it + // is unnamed + status_t err; + + if (data == NULL) + return B_BAD_VALUE; + + err = data->AddString("suites", ""); + + if (err != B_OK) + return err; + + BPropertyInfo prop_info(prop_list); + err = data->AddFlat("messages", &prop_info); + + if (err != B_OK) + return err; + + return BView::GetSupportedSuites(data); +} +//------------------------------------------------------------------------------ +status_t BTextView::Perform(perform_code d, void *arg) +{ + return B_ERROR; +} +//------------------------------------------------------------------------------ +void BTextView::SetText(const char *inText, const text_run_array *inRuns) +{ + DeleteText(0, fText->fLogicalBytes); + + if (inText) + InsertText(inText, strlen(inText), 0, NULL); +} +//------------------------------------------------------------------------------ +void BTextView::SetText(const char *inText, int32 inLength, + const text_run_array *inRuns) +{ + DeleteText(0, fText->fLogicalBytes); + + if (inText) + InsertText(inText, inLength, 0, NULL); +} +//------------------------------------------------------------------------------ +void BTextView::SetText (BFile *inFile, int32 startOffset, int32 inLength, + const text_run_array *inRuns) +{ + // TODO: +} +//------------------------------------------------------------------------------ +void BTextView::Insert(const char *inText, const text_run_array *inRuns) +{ + Insert(fSelStart, inText, strlen(inText), inRuns); +} +//------------------------------------------------------------------------------ +void BTextView::Insert(const char *inText, int32 inLength, + const text_run_array *inRuns) +{ + Insert(fSelStart, inText, inLength, inRuns); +} +//------------------------------------------------------------------------------ +void BTextView::Insert(int32 startOffset, const char *inText, int32 inLength, + const text_run_array *inRuns) +{ + InsertText(inText, inLength, startOffset, inRuns); +} +//------------------------------------------------------------------------------ +void BTextView::Delete() +{ + if (fSelStart != fSelEnd) + Delete(fSelStart, fSelEnd); +} +//------------------------------------------------------------------------------ +void BTextView::Delete(int32 startOffset, int32 endOffset) +{ + if (startOffset != endOffset) + DeleteText(startOffset, endOffset); +} +//------------------------------------------------------------------------------ +const char *BTextView::Text() const +{ + return fText->Text(); +} +//------------------------------------------------------------------------------ +int32 BTextView::TextLength() const +{ + return fText->fLogicalBytes; +} +//------------------------------------------------------------------------------ +void BTextView::GetText(int32 offset, int32 length, char *buffer) const +{ + memcpy(buffer, fText->RealText() + offset, length); + buffer[length] = '\0'; +} +//------------------------------------------------------------------------------ +uchar BTextView::ByteAt(int32 offset) const +{ + return fText->RealCharAt(offset); +} +//------------------------------------------------------------------------------ +int32 BTextView::CountLines() const +{ + return fLines->fItemCount - 1; +} +//------------------------------------------------------------------------------ +int32 BTextView::CurrentLine() const +{ + return LineAt(fSelStart); +} +//------------------------------------------------------------------------------ +void BTextView::GoToLine(int32 index) +{ + fSelStart = fSelEnd = OffsetAt(index); +} +//------------------------------------------------------------------------------ +void BTextView::Cut(BClipboard *clipboard) +{ + Copy(clipboard); + DeleteText(fSelStart, fSelEnd); +} +//------------------------------------------------------------------------------ +void BTextView::Copy(BClipboard *clipboard) +{ + BMessage *clip = NULL; + + if (clipboard->Lock()) + { + clipboard->Clear(); + + clip = clipboard->Data(); + + if (clip != NULL) + { + clip->AddData("text/plain", B_MIME_TYPE, Text() + fSelStart, + fSelEnd - fSelStart); + clipboard->Commit(); + } + } + + clipboard->Unlock(); +} +//------------------------------------------------------------------------------ +void BTextView::Paste(BClipboard *clipboard) +{ + BMessage *clip = NULL; + + if (clipboard->Lock()) + { + clip = clipboard->Data(); + if (clip != NULL) + { + const char *text; + ssize_t len; + + clip->FindData("text/plain", B_MIME_TYPE, (const void **)&text, &len); + + DeleteText(fSelStart, fSelEnd); + InsertText(text, len, fSelStart, NULL); + } + + clipboard->Unlock(); + } +} +//------------------------------------------------------------------------------ +void BTextView::Clear() +{ + if (fSelStart != fSelEnd) + DeleteText(fSelStart, fSelEnd); +} +//------------------------------------------------------------------------------ +bool BTextView::AcceptsPaste(BClipboard *clipboard) +{ + // TODO: check if mime on clipboard is text/plain + return (fEditable); +} +//------------------------------------------------------------------------------ +bool BTextView::AcceptsDrop(const BMessage *inMessage) +{ + const void *data; + + return (fEditable && + inMessage->FindData("text/plain", B_MIME_TYPE, &data, NULL) == B_OK); +} +//------------------------------------------------------------------------------ +void BTextView::Select(int32 startOffset, int32 endOffset) +{ + fSelStart = min(max((int32)0, startOffset), fText->fLogicalBytes); + fSelEnd = min(max(fSelStart, endOffset), fText->fLogicalBytes); + + Invalidate(); +} +//------------------------------------------------------------------------------ +void BTextView::SelectAll() +{ + Select(0, fText->fLogicalBytes); +} +//------------------------------------------------------------------------------ +void BTextView::GetSelection(int32 *outStart, int32 *outEnd) const +{ + *outStart = fSelStart; + *outEnd = fSelEnd; +} +//------------------------------------------------------------------------------ +void BTextView::SetFontAndColor(const BFont *inFont, uint32 inMode, + const rgb_color *inColor) +{ + fStyles->SetNullStyle(inMode, inFont, inColor, 0); +} +//------------------------------------------------------------------------------ +void BTextView::SetFontAndColor(int32 startOffset, int32 endOffset, + const BFont *inFont, uint32 inMode, + const rgb_color *inColor) +{ + fStyles->SetNullStyle(inMode, inFont, inColor, 0); +} +//------------------------------------------------------------------------------ +void BTextView::GetFontAndColor(int32 inOffset, BFont*outFont, + rgb_color *outColor) const +{ + const BFont *font; + const rgb_color *color; + + fStyles->GetNullStyle(&font, &color); + + if (outFont) + *outFont = *font; + + if (outColor) + *outColor = *color; +} +//------------------------------------------------------------------------------ +void BTextView::GetFontAndColor(BFont *outFont, uint32 *outMode, + rgb_color *outColor, bool *outEqColor) const +{ + const BFont *font; + const rgb_color *color; + + fStyles->GetNullStyle(&font, &color); + + if (outFont) + *outFont = *font; + + if (outColor) + *outColor = *color; +} +//------------------------------------------------------------------------------ +void BTextView::SetRunArray(int32 startOffset, int32 endOffset, + const text_run_array *inRuns) +{ +} +//------------------------------------------------------------------------------ +text_run_array *BTextView::RunArray(int32 startOffset, int32 endOffset, + int32 *outSize) const +{ +/* text_run_array *textRunArray = new text_run_array; + + textRunArray->count = 1; + textRunArray->runs[0].offset = 0; + textRunArray->runs[0].font = NULL; + //textRunArray->runs[0].color; + + return textRunArray;*/ + + return NULL; +} +//------------------------------------------------------------------------------ +int32 BTextView::LineAt(int32 offset) const +{ + return fLines->OffsetToLine(offset); +} +//------------------------------------------------------------------------------ +int32 BTextView::LineAt(BPoint point) const +{ + return fLines->PixelToLine(point.y - fTextRect.top); +} +//------------------------------------------------------------------------------ +BPoint BTextView::PointAt(int32 inOffset, float *outHeight) const +{ + int32 line = LineAt(inOffset); + + if (outHeight) + *outHeight = LineHeight(line); + + return BPoint(fTextRect.left + + StringWidth(fText->RealText() + fLines->fObjectList[line].fOffset, + inOffset - fLines->fObjectList[line].fOffset), + fTextRect.top + fLines->fObjectList[line].fHeight); +} +//------------------------------------------------------------------------------ +int32 BTextView::OffsetAt(BPoint point) const +{ + // Find the line we clicked on + int32 line = LineAt(point); + int32 offset = fLines->fObjectList[line].fOffset; + + point.x -= fTextRect.left; + + // If we clicked past the end of the line return last index + if (point.x > fLines->fObjectList[line].fWidth) + { + if (fText->RealCharAt(fLines->fObjectList[line + 1].fOffset - 1) == '\n') + return fLines->fObjectList[line + 1].fOffset - 1; + else + return fLines->fObjectList[line + 1].fOffset; + } + + // Search offset + float width = 0.0f, nextWidth; + int32 startOffset = offset, nextOffset; + + while (point.x > width && offset < fLines->fObjectList[line + 1].fOffset - 1) + { + nextOffset = next_utf8(fText->RealText() + offset) - fText->RealText(); + nextWidth = StringWidth(fText->RealText(), nextOffset - startOffset); + + if (point.x < width + (nextWidth - width) * 0.5f) + return offset; + + width = nextWidth; + offset = nextOffset; + } + + return offset; +} +//------------------------------------------------------------------------------ +int32 BTextView::OffsetAt(int32 line) const +{ + if (line > fLines->fItemCount) + return fText->fLogicalBytes; + + return fLines->fObjectList[line].fOffset; +} +//------------------------------------------------------------------------------ +void BTextView::FindWord(int32 inOffset, int32 *outFromOffset, + int32 *outToOffset) +{ +} +//------------------------------------------------------------------------------ +bool BTextView::CanEndLine(int32 offset) +{ + switch(fText->RealCharAt(offset)) + { + case B_SPACE: + case B_TAB: + case B_ENTER: + case '=': + case '+': + case '-': + case '<': + case '>': + case '^': + case '/': + case '|': + case '&': + case '*': + case '\0': + return true; + } + + return false; +} +//------------------------------------------------------------------------------ +float BTextView::LineWidth(int32 lineNum) const +{ + if (lineNum < 0) + return fLines->fObjectList[0].fWidth; + else if (lineNum > fLines->fItemCount - 2) + return fLines->fObjectList[fLines->fItemCount - 2].fWidth; + else + return fLines->fObjectList[lineNum].fWidth; +} +//------------------------------------------------------------------------------ +float BTextView::LineHeight(int32 lineNum) const +{ + if (lineNum < 0) + return fLines->fObjectList[0].fLineHeight; + else if (lineNum > fLines->fItemCount - 2) + return fLines->fObjectList[fLines->fItemCount - 2].fLineHeight; + else + return fLines->fObjectList[lineNum].fLineHeight; +} +//------------------------------------------------------------------------------ +float BTextView::TextHeight(int32 startLine, int32 endLine) const +{ + if (startLine < 0) + startLine = 0; + + if (endLine > fLines->fItemCount - 1) + endLine = fLines->fItemCount - 1; + + float height = 0.0f; + + for (int32 i = startLine; i < endLine + 1; i ++) + height += fLines->fObjectList[i].fLineHeight + 3.0f; + + return height; +} +//------------------------------------------------------------------------------ +void BTextView::GetTextRegion(int32 startOffset, int32 endOffset, + BRegion *outRegion) const +{ +} +//------------------------------------------------------------------------------ +void BTextView::ScrollToOffset(int32 inOffset) +{ + int32 line = LineAt(inOffset); + BRect rect; + + rect.left = 0; + rect.top = fLines->fObjectList[line].fHeight; + rect.right = LineWidth(line); + rect.bottom = rect.top + LineHeight(line); + + if (Bounds().Intersects(rect.InsetByCopy(0, 2))) + return; + + if (rect.top < Bounds().top ) + ScrollTo(0, rect.top); + else + ScrollTo(0, rect.bottom - Bounds().Height()); + + UpdateScrollbars(); +} +//------------------------------------------------------------------------------ +void BTextView::ScrollToSelection() +{ + ScrollToOffset(fSelStart); +} +//------------------------------------------------------------------------------ +void BTextView::Highlight(int32 startOffset, int32 endOffset) +{ + rgb_color color = HighColor(); + SetHighColor(0, 0, 0, 128); + + int32 lineStart = LineAt(startOffset); + int32 lineEnd = LineAt(endOffset); + + float selHeight; + BPoint selStart, selEnd; + + for (int32 line = lineStart; line <= lineEnd; line++) + { + if (line == lineStart) + selStart = PointAt(startOffset); + else + selStart = PointAt(OffsetAt(line)); + + if (line == lineEnd) + selEnd = PointAt(endOffset, &selHeight); + else + { + selEnd = PointAt(OffsetAt(line), &selHeight); + selEnd.x = LineWidth(line); + } + + InvertRect(BRect(selStart.x, selStart.y, selEnd.x, selEnd.y + selHeight)); + } + + SetHighColor(color); +} +//------------------------------------------------------------------------------ +void BTextView::SetTextRect(BRect rect) +{ +} +//------------------------------------------------------------------------------ +BRect BTextView::TextRect() const +{ + return BRect(); +} +//------------------------------------------------------------------------------ +void BTextView::SetStylable(bool stylable) +{ + fStylable = stylable; +} +//------------------------------------------------------------------------------ +bool BTextView::IsStylable() const +{ + return fStylable; +} +//------------------------------------------------------------------------------ +void BTextView::SetTabWidth(float width) +{ + fTabWidth = width; +} +//------------------------------------------------------------------------------ +float BTextView::TabWidth() const +{ + return fTabWidth; +} +//------------------------------------------------------------------------------ +void BTextView::MakeSelectable(bool selectable) +{ + fSelectable = selectable; +} +//------------------------------------------------------------------------------ +bool BTextView::IsSelectable() const +{ + return fSelectable; +} +//------------------------------------------------------------------------------ +void BTextView::MakeEditable(bool editable) +{ + fEditable = editable; +} +//------------------------------------------------------------------------------ +bool BTextView::IsEditable() const +{ + return fEditable; +} +//------------------------------------------------------------------------------ +void BTextView::SetWordWrap(bool wrap) +{ + fWrap = wrap; +} +//------------------------------------------------------------------------------ +bool BTextView::DoesWordWrap() const +{ + return fWrap; +} +//------------------------------------------------------------------------------ +void BTextView::SetMaxBytes(int32 max) +{ + fMaxBytes = max; +} +//------------------------------------------------------------------------------ +int32 BTextView::MaxBytes() const +{ + return fMaxBytes; +} +//------------------------------------------------------------------------------ +void BTextView::DisallowChar(uint32 aChar) +{ +} +//------------------------------------------------------------------------------ +void BTextView::AllowChar(uint32 aChar) +{ +} +//------------------------------------------------------------------------------ +void BTextView::SetAlignment(alignment flag) +{ + fAlignment = flag; +} +//------------------------------------------------------------------------------ +alignment BTextView::Alignment() const +{ + return fAlignment; +} +//------------------------------------------------------------------------------ +void BTextView::SetAutoindent(bool state) +{ + fAutoindent = state; +} +//------------------------------------------------------------------------------ +bool BTextView::DoesAutoindent() const +{ + return fAutoindent; +} +//------------------------------------------------------------------------------ +void BTextView::SetColorSpace(color_space colors) +{ + fColorSpace = colors; +} +//------------------------------------------------------------------------------ +color_space BTextView::ColorSpace() const +{ + return fColorSpace; +} +//------------------------------------------------------------------------------ +void BTextView::MakeResizable(bool resize, BView *resizeView) +{ + fResizable = resize; + fContainerView = resizeView; +} +//------------------------------------------------------------------------------ +bool BTextView::IsResizable () const +{ + return fResizable; +} +//------------------------------------------------------------------------------ +void BTextView::SetDoesUndo(bool undo) +{ + +} +//------------------------------------------------------------------------------ +bool BTextView::DoesUndo() const +{ + return false; +} +//------------------------------------------------------------------------------ +void BTextView::HideTyping(bool enabled) +{ + +} +//------------------------------------------------------------------------------ +bool BTextView::IsTypingHidden() const +{ + return false; +} +//------------------------------------------------------------------------------ +void BTextView::ResizeToPreferred() +{ + float widht, height; + GetPreferredSize(&widht, &height); + BView::ResizeTo(widht,height); +} +//------------------------------------------------------------------------------ +void BTextView::GetPreferredSize(float *width, float *height) +{ +} +//------------------------------------------------------------------------------ +void BTextView::AllAttached() +{ +} +//------------------------------------------------------------------------------ +void BTextView::AllDetached() +{ +} +//------------------------------------------------------------------------------ +void *BTextView::FlattenRunArray(const text_run_array *inArray, + int32 *outSize) +{ + // TODO: see TranslatorFormats for info + return NULL; +} +//------------------------------------------------------------------------------ +text_run_array *BTextView::UnflattenRunArray(const void *data, int32 *outSize) +{ + // TODO: see TranslatorFormats for info + return NULL; +} +//------------------------------------------------------------------------------ +void BTextView::InsertText(const char *inText, int32 inLength, int32 inOffset, + const text_run_array *inRuns) +{ + //_ASSERT ( _CrtCheckMemory () ); + + fText->InsertText(inText, inLength, inOffset); + + int32 line = fLines->OffsetToLine(inOffset); + fLines->BumpOffset(line + 1, inLength); + + // Move selection if needed + if (inOffset <= fSelStart) + { + fSelStart += inLength; + fSelEnd += inLength; + } + + //_ASSERT ( _CrtCheckMemory () ); + + // Update line buffer + Refresh(inOffset, inOffset + inLength, true, false); + + //_ASSERT ( _CrtCheckMemory () ); +} +//------------------------------------------------------------------------------ +void BTextView::DeleteText(int32 fromOffset, int32 toOffset) +{ + //_ASSERT ( _CrtCheckMemory () ); + + fText->RemoveRange(fromOffset, toOffset); + fLines->RemoveLineRange(fromOffset, toOffset); + + // Move selection if needed + if (fromOffset <= fSelStart) + { + if (toOffset <= fSelStart) + { + fSelStart -= toOffset - fromOffset; + fSelEnd -= toOffset - fromOffset; + } + else + { + fSelStart = fromOffset; + fSelEnd = fromOffset; + } + } + + //_ASSERT ( _CrtCheckMemory () ); + + // Update line buffer + Refresh(fromOffset, fromOffset, true, false); + + //_ASSERT ( _CrtCheckMemory () ); +} +//------------------------------------------------------------------------------ +void BTextView::Undo(BClipboard *clipboard) +{ +} +//------------------------------------------------------------------------------ +undo_state BTextView::UndoState(bool *isRedo) const +{ + return B_UNDO_UNAVAILABLE; +} +//------------------------------------------------------------------------------ +void BTextView::GetDragParameters(BMessage *drag, BBitmap **bitmap, + BPoint *point, BHandler **handler) +{ +} +//------------------------------------------------------------------------------ + +//Private or Reserved +//------------------------------------------------------------------------------ +void BTextView::InitObject(BRect textRect, const BFont *initialFont, + const rgb_color *initialColor) +{ + fTextRect = textRect; + + fText = new _BTextGapBuffer_; + fLines = new _BLineBuffer_; + fStyles = new _BStyleBuffer_(initialFont, initialColor); + + font_height fh; + GetFontHeight(&fh); + fLines->fObjectList[0].fLineHeight = (float)ceil(fh.ascent + fh.descent); +} +//------------------------------------------------------------------------------ +void BTextView::HandleBackspace() +{ + if (!fEditable) + return; + + if (fSelStart < fSelEnd) + { + DeleteText(fSelStart, fSelEnd); + } + else if ( fSelStart > 0 ) + { + int32 selStart = previous_utf8(fText->RealText(), + fText->RealText() + fSelStart) - fText->RealText(); + DeleteText(selStart, fSelStart); + } +} +//------------------------------------------------------------------------------ +void BTextView::HandleArrowKey(uint32 inArrowKey) +{ + switch(inArrowKey) + { + case B_LEFT_ARROW: + if (fSelStart > 0) + { + int32 sel = previous_utf8(fText->RealText(), + fText->RealText() + fSelStart) - fText->RealText(); + + if (modifiers() & B_SHIFT_KEY) + Select(sel, fSelEnd); + else + Select(sel, sel); + } + break; + case B_RIGHT_ARROW: + { + int32 sel; + + if (fSelEnd < fText->fLogicalBytes - 1) + sel= next_utf8(fText->RealText() + fSelEnd) - fText->RealText(); + else + sel = fText->fLogicalBytes; + + if (modifiers() & B_SHIFT_KEY) + Select(fSelStart, sel); + else + Select(sel, sel); + + break; + } + case B_DOWN_ARROW: + { + //TODO: Implement + break; + } + case B_UP_ARROW: + { + //TODO: Implement + break; + } + } +} +//------------------------------------------------------------------------------ +void BTextView::HandleDelete() +{ + if (!fEditable) + return; + + if (fSelStart < fSelEnd) + { + DeleteText(fSelStart, fSelEnd); + } + else if (fSelStart < fText->fLogicalBytes) + { + int32 selEnd = next_utf8(fText->RealText() + fSelStart) - + fText->RealText(); + DeleteText(fSelStart, selEnd); + } +} +//------------------------------------------------------------------------------ +void BTextView::HandlePageKey(uint32 inPageKey) +{ + if (inPageKey == B_PAGE_DOWN) + { + GoToLine(CountLines() - 1); + } + else if (inPageKey == B_PAGE_UP) + { + GoToLine(0); + } + Invalidate(); +} +//------------------------------------------------------------------------------ +void BTextView::HandleAlphaKey(const char *bytes, int32 numBytes) +{ + if (!fEditable) + return; + + if (fSelStart != fSelEnd) + DeleteText(fSelStart, fSelEnd); + + InsertText(bytes, numBytes, fSelStart, NULL); +} +//------------------------------------------------------------------------------ +void BTextView::Refresh(int32 fromOffset, int32 toOffset, bool erase, + bool scroll) +{ + float ascent, descent, width; + + // Find the first line that changed + int32 line = LineAt(fromOffset); + int32 offset = FindLineBreak(OffsetAt(line), &ascent, &descent, &width); + + // Update the lineheight and width of this line + fLines->fObjectList[line].fLineHeight = (float)ceil(ascent + descent); + fLines->fObjectList[line].fWidth = width; + line++; + + // Check if we have to insert new lines + while (offset < toOffset) + { + STELine l; + + l.fOffset = offset + 1; + l.fHeight = fLines->fObjectList[line - 1].fHeight + + fLines->fObjectList[line - 1].fLineHeight + 3; + l.fLineHeight = (float)ceil(ascent + descent); + l.fWidth = width; + + fLines->InsertLine(&l, line); + + offset++; + line++; + offset = FindLineBreak(offset, &ascent, &descent, &width); + } + + // Update the height of the remaining lines + for (int i = line; i < fLines->fItemCount; i++) + fLines->fObjectList[i].fHeight = fLines->fObjectList[i - 1].fHeight + + fLines->fObjectList[i - 1].fLineHeight + 3; + + // Update the screen + UpdateScrollbars(); + + /*Invalidate(BRect(0.0f, PointAt(fromOffset).y, Bounds().right, + PointAt(toOffset).y + LineHeight(LineAt(toOffset))));*/ + Invalidate(); +} +//------------------------------------------------------------------------------ +void BTextView::RecalLineBreaks(int32 *startLine, int32 *endLine) +{ +} +//------------------------------------------------------------------------------ +int32 BTextView::FindLineBreak(int32 fromOffset, float *outAscent, + float *outDescent, float *ioWidth) +{ + if (fromOffset >= fText->fLogicalBytes) + { + // Fill in font height if needed + if (outAscent && outDescent) + { + *outAscent = 0.0f; + *outDescent = 0.0f; + } + + return fromOffset; + } + + // Find the actual linebreak + int32 offset = fromOffset; + char *ptr = fText->RealText(); + + while(offset < fText->fLogicalBytes) + { + if (ptr[offset] == '\n' && ptr[offset + 1] != '\0') + break; + + if (ptr[offset] == '\0') + break; + + offset++; + } + + // Fill in font height if needed + if (outAscent && outDescent) + { + font_height fh; + GetFontHeight(&fh); + + *outAscent = fh.ascent; + *outDescent = fh.descent; + } + + // Calculate width if needed + if (ioWidth) + *ioWidth = StringWidth(ptr + fromOffset, offset - fromOffset); + + return offset; +} +//------------------------------------------------------------------------------ +float BTextView::StyledWidth(int32 fromOffset, int32 length, float *outAscent, + float *outDescent) const +{ + return 0.0f; +} +//------------------------------------------------------------------------------ +float BTextView::ActualTabWidth(float location) const +{ + return 0.0f; +} +//------------------------------------------------------------------------------ +void BTextView::DoInsertText(const char *inText, int32 inLength, int32 inOffset, + const text_run_array *inRuns, + _BTextChangeResult_ *outResult) +{ +} +//------------------------------------------------------------------------------ +void BTextView::DoDeleteText(int32 fromOffset, int32 toOffset, + _BTextChangeResult_ *outResult) +{ +} +//------------------------------------------------------------------------------ +void BTextView::DrawLines(int32 startLine, int32 endLine, int32 startOffset, + bool erase) +{ + char *string; + int32 length; + + font_height fh; + GetFontHeight(&fh); + + for (int32 i = startLine; i < endLine + 1; i++) + { + string = fText->RealText() + fLines->fObjectList[i].fOffset; + length = fLines->fObjectList[i + 1].fOffset - + fLines->fObjectList[i].fOffset; + + if (length > 0) + { + if (fAlignment == B_ALIGN_LEFT) + DrawString(string, length, BPoint(fTextRect.left, + fTextRect.top + fLines->fObjectList[i].fHeight + + fh.ascent)); + else if (fAlignment == B_ALIGN_CENTER) + DrawString(string, length, BPoint(fTextRect.left + + fTextRect.Width() / 2 - fLines->fObjectList[i].fWidth / 2, + fTextRect.top + fLines->fObjectList[i].fHeight + fh.ascent)); + else + DrawString(string, length, BPoint(fTextRect.right - + fLines->fObjectList[i].fWidth, fTextRect.top + + fLines->fObjectList[i].fHeight + fh.ascent)); + } + } +} +//------------------------------------------------------------------------------ +void BTextView::DrawCaret(int32 offset) +{ + Highlight(offset, offset); +} +//------------------------------------------------------------------------------ +void BTextView::InvertCaret() +{ + Highlight(fSelStart, fSelStart); +} +//------------------------------------------------------------------------------ +void BTextView::DragCaret(int32 offset) +{ +} +//------------------------------------------------------------------------------ +void BTextView::StopMouseTracking() +{ +} +//------------------------------------------------------------------------------ +bool BTextView::PerformMouseUp(BPoint where) +{ + return false; +} +//------------------------------------------------------------------------------ +bool BTextView::PerformMouseMoved(BPoint where, uint32 code) +{ + return false; +} +//------------------------------------------------------------------------------ +void BTextView::TrackMouse(BPoint where, const BMessage *message, bool force) +{ +} +//------------------------------------------------------------------------------ +void BTextView::TrackDrag(BPoint where) +{ +} +//------------------------------------------------------------------------------ +void BTextView::InitiateDrag() +{ +} +//------------------------------------------------------------------------------ +bool BTextView::MessageDropped(BMessage *inMessage, BPoint where, BPoint offset) +{ + return false; +} +//------------------------------------------------------------------------------ +void BTextView::UpdateScrollbars() +{ + BRect bounds(Bounds()); + BScrollBar *vertScroller = ScrollBar(B_VERTICAL); + + if (vertScroller) + { + float height = TextHeight(0, CountLines()); + + if (bounds.Height() > height) + vertScroller->SetRange(0.0f, 0.0f); + else + { + vertScroller->SetRange(0.0f, height - bounds.Height()); + vertScroller->SetProportion(bounds.Height() / height); + } + } +} +//------------------------------------------------------------------------------ +void BTextView::AutoResize(bool doredraw) +{ +} +//------------------------------------------------------------------------------ +void BTextView::NewOffscreen(float padding) +{ +} +//------------------------------------------------------------------------------ +void BTextView::DeleteOffscreen() +{ +} +//------------------------------------------------------------------------------ +void BTextView::Activate() +{ +} +//------------------------------------------------------------------------------ +void BTextView::Deactivate() +{ +} +//------------------------------------------------------------------------------ +void BTextView::NormalizeFont(BFont *font) +{ +} +//------------------------------------------------------------------------------ +uint32 BTextView::CharClassification(int32 offset) const +{ + return 0; +} +//------------------------------------------------------------------------------ +int32 BTextView::NextInitialByte(int32 offset) const +{ + return 0; +} +//------------------------------------------------------------------------------ +int32 BTextView::PreviousInitialByte(int32 offset) const +{ + return 0; +} +//------------------------------------------------------------------------------ +bool BTextView::GetProperty(BMessage *specifier, int32 form, + const char *property, BMessage *reply) +{ + return false; +} +//------------------------------------------------------------------------------ +bool BTextView::SetProperty(BMessage *specifier, int32 form, + const char *property, BMessage *reply) +{ + return false; +} +//------------------------------------------------------------------------------ +bool BTextView::CountProperties(BMessage *specifier, int32 form, + const char *property, BMessage *reply) +{ + return false; +} +//------------------------------------------------------------------------------ +void BTextView::HandleInputMethodChanged(BMessage *message) +{ +} +//------------------------------------------------------------------------------ +void BTextView::HandleInputMethodLocationRequest() +{ +} +//------------------------------------------------------------------------------ +void BTextView::CancelInputMethod() +{ +} +//------------------------------------------------------------------------------ +void BTextView::LockWidthBuffer() +{ +} +//------------------------------------------------------------------------------ +void BTextView::UnlockWidthBuffer() +{ +} +//------------------------------------------------------------------------------ + +//FBC +void BTextView::_ReservedTextView3() {} +void BTextView::_ReservedTextView4() {} +void BTextView::_ReservedTextView5() {} +void BTextView::_ReservedTextView6() {} +void BTextView::_ReservedTextView7() {} +void BTextView::_ReservedTextView8() {} +void BTextView::_ReservedTextView9() {} +void BTextView::_ReservedTextView10() {} +void BTextView::_ReservedTextView11() {} +void BTextView::_ReservedTextView12() {} +/* + * $Log $ + * + * $Id $ + * + */ diff --git a/src/kits/interface/BTextView/TextView.h b/src/kits/interface/BTextView/TextView.h new file mode 100644 index 0000000000..972168be45 --- /dev/null +++ b/src/kits/interface/BTextView/TextView.h @@ -0,0 +1,445 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2001-2002, OpenBeOS +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// File Name: TextView.h +// Author: Marc Flerackers (mflerackers@androme.be) +// Description: BTextView displays and manages styled text. +//------------------------------------------------------------------------------ + +#ifndef _TEXT_VIEW_H +#define _TEXT_VIEW_H + +// Standard Includes ----------------------------------------------------------- + +// System Includes ------------------------------------------------------------- +#include +#include + +// Project Includes ------------------------------------------------------------ + +// Local Includes -------------------------------------------------------------- + +// Local Defines --------------------------------------------------------------- + +// Globals --------------------------------------------------------------------- + +struct text_run { + int32 offset; /* byte offset of first character of run*/ + BFont *font; /* font of run*/ + rgb_color color; /* color of run*/ +}; + +struct text_run_array { + int32 count; /* number of text runs*/ + text_run runs[1]; /* array of count number of runs*/ +}; + +enum undo_state { + B_UNDO_UNAVAILABLE, + B_UNDO_TYPING, + B_UNDO_CUT, + B_UNDO_PASTE, + B_UNDO_CLEAR, + B_UNDO_DROP +}; + +class BBitmap; +class BClipboard; +class BFile; +class BList; +class _BTextGapBuffer_; +class _BLineBuffer_; +class _BStyleBuffer_; +class _BWidthBuffer_; +class _BUndoBuffer_; +class _BInlineInput_; +class _BTextTrackState_; +class _BTextChangeResult_; + +extern "C" status_t _init_interface_kit_(); + +// BTextView class ------------------------------------------------------------- +class BTextView : public BView { + +public: + BTextView(BRect frame, + const char *name, + BRect textRect, + uint32 resizeMask, + uint32 flags = B_WILL_DRAW | B_PULSE_NEEDED); + BTextView(BRect frame, + const char *name, + BRect textRect, + const BFont *initialFont, + const rgb_color *initialColor, + uint32 resizeMask, + uint32 flags); + BTextView(BMessage *data); +virtual ~BTextView(); + +static BArchivable* Instantiate(BMessage *data); +virtual status_t Archive(BMessage *data, bool deep = true) const; + +virtual void AttachedToWindow(); +virtual void DetachedFromWindow(); +virtual void Draw(BRect inRect); +virtual void MouseDown(BPoint where); +virtual void MouseUp(BPoint where); +virtual void MouseMoved(BPoint where, + uint32 code, + const BMessage *message); +virtual void WindowActivated(bool state); +virtual void KeyDown(const char *bytes, int32 numBytes); +virtual void Pulse(); +virtual void FrameResized(float width, float height); +virtual void MakeFocus(bool focusState = true); +virtual void MessageReceived(BMessage *message); +virtual BHandler* ResolveSpecifier(BMessage *message, + int32 index, + BMessage *specifier, + int32 form, + const char *property); +virtual status_t GetSupportedSuites(BMessage *data); +virtual status_t Perform(perform_code d, void *arg); + + void SetText(const char *inText, + const text_run_array *inRuns = NULL); + void SetText(const char *inText, + int32 inLength, + const text_run_array *inRuns = NULL); + void SetText(BFile *inFile, + int32 startOffset, + int32 inLength, + const text_run_array *inRuns = NULL); + + void Insert(const char *inText, + const text_run_array *inRuns = NULL); + void Insert(const char *inText, + int32 inLength, + const text_run_array *inRuns = NULL); + void Insert(int32 startOffset, + const char *inText, + int32 inLength, + const text_run_array *inRuns = NULL); + + void Delete(); + void Delete(int32 startOffset, int32 endOffset); + + const char* Text() const; + int32 TextLength() const; + void GetText(int32 offset, + int32 length, + char *buffer) const; + uchar ByteAt(int32 offset) const; + + int32 CountLines() const; + int32 CurrentLine() const; + void GoToLine(int32 lineNum); + +virtual void Cut(BClipboard *clipboard); +virtual void Copy(BClipboard *clipboard); +virtual void Paste(BClipboard *clipboard); + void Clear(); + +virtual bool AcceptsPaste(BClipboard *clipboard); +virtual bool AcceptsDrop(const BMessage *inMessage); + +virtual void Select(int32 startOffset, int32 endOffset); + void SelectAll(); + void GetSelection(int32 *outStart, int32 *outEnd) const; + + void SetFontAndColor(const BFont *inFont, + uint32 inMode = B_FONT_ALL, + const rgb_color *inColor = NULL); + void SetFontAndColor(int32 startOffset, + int32 endOffset, + const BFont *inFont, + uint32 inMode = B_FONT_ALL, + const rgb_color *inColor = NULL); + + void GetFontAndColor(int32 inOffset, + BFont *outFont, + rgb_color *outColor = NULL) const; + void GetFontAndColor(BFont *outFont, + uint32 *outMode, + rgb_color *outColor = NULL, + bool *outEqColor = NULL) const; + + void SetRunArray(int32 startOffset, + int32 endOffset, + const text_run_array *inRuns); + text_run_array* RunArray(int32 startOffset, + int32 endOffset, + int32 *outSize = NULL) const; + + int32 LineAt(int32 offset) const; + int32 LineAt(BPoint point) const; + BPoint PointAt(int32 inOffset, float *outHeight = NULL) const; + int32 OffsetAt(BPoint point) const; + int32 OffsetAt(int32 line) const; + +virtual void FindWord(int32 inOffset, + int32 *outFromOffset, + int32 *outToOffset); + +virtual bool CanEndLine(int32 offset); + + float LineWidth(int32 lineNum = 0) const; + float LineHeight(int32 lineNum = 0) const; + float TextHeight(int32 startLine, int32 endLine) const; + + void GetTextRegion(int32 startOffset, + int32 endOffset, + BRegion *outRegion) const; + +virtual void ScrollToOffset(int32 inOffset); + void ScrollToSelection(); + + void Highlight(int32 startOffset, int32 endOffset); + + void SetTextRect(BRect rect); + BRect TextRect() const; + void SetStylable(bool stylable); + bool IsStylable() const; + void SetTabWidth(float width); + float TabWidth() const; + void MakeSelectable(bool selectable = true); + bool IsSelectable() const; + void MakeEditable(bool editable = true); + bool IsEditable() const; + void SetWordWrap(bool wrap); + bool DoesWordWrap() const; + void SetMaxBytes(int32 max); + int32 MaxBytes() const; + void DisallowChar(uint32 aChar); + void AllowChar(uint32 aChar); + void SetAlignment(alignment flag); + alignment Alignment() const; + void SetAutoindent(bool state); + bool DoesAutoindent() const; + void SetColorSpace(color_space colors); + color_space ColorSpace() const; + void MakeResizable(bool resize, BView *resizeView = NULL); + bool IsResizable() const; + void SetDoesUndo(bool undo); + bool DoesUndo() const; + void HideTyping(bool enabled); + bool IsTypingHidden(void) const; + +virtual void ResizeToPreferred(); +virtual void GetPreferredSize(float *width, float *height); +virtual void AllAttached(); +virtual void AllDetached(); + +static void* FlattenRunArray(const text_run_array *inArray, + int32 *outSize = NULL); +static text_run_array* UnflattenRunArray(const void *data, + int32 *outSize = NULL); + +protected: +virtual void InsertText(const char *inText, + int32 inLength, + int32 inOffset, + const text_run_array *inRuns); +virtual void DeleteText(int32 fromOffset, int32 toOffset); + +public: +virtual void Undo(BClipboard *clipboard); + undo_state UndoState(bool *isRedo) const; + +protected: +virtual void GetDragParameters(BMessage *drag, + BBitmap **bitmap, + BPoint *point, + BHandler **handler); + +/*----- Private or reserved -----------------------------------------*/ +private: +friend status_t _init_interface_kit_(); +friend class _BTextTrackState_; + +#if _PR2_COMPATIBLE_ +friend void _ReservedTextView2__9BTextViewFv(BTextView *object, + BMessage *drag, + BBitmap **bitmap, + BPoint *point, + BHandler **handler); +#endif + +virtual void _ReservedTextView3(); +virtual void _ReservedTextView4(); +virtual void _ReservedTextView5(); +virtual void _ReservedTextView6(); +virtual void _ReservedTextView7(); +virtual void _ReservedTextView8(); + +#if !_PR3_COMPATIBLE_ +virtual void _ReservedTextView9(); +virtual void _ReservedTextView10(); +virtual void _ReservedTextView11(); +virtual void _ReservedTextView12(); +#endif + + void InitObject(BRect textRect, + const BFont *initialFont, + const rgb_color *initialColor); + + void HandleBackspace(); + void HandleArrowKey(uint32 inArrowKey); + void HandleDelete(); + void HandlePageKey(uint32 inPageKey); + void HandleAlphaKey(const char *bytes, int32 numBytes); + + void Refresh(int32 fromOffset, + int32 toOffset, + bool erase, + bool scroll); + void RecalLineBreaks(int32 *startLine, int32 *endLine); + int32 FindLineBreak(int32 fromOffset, + float *outAscent, + float *outDescent, + float *ioWidth); + + float StyledWidth(int32 fromOffset, + int32 length, + float *outAscent = NULL, + float *outDescent = NULL) const; + float ActualTabWidth(float location) const; + + void DoInsertText(const char *inText, + int32 inLength, + int32 inOffset, + const text_run_array *inRuns, + _BTextChangeResult_ *outResult); + void DoDeleteText(int32 fromOffset, + int32 toOffset, + _BTextChangeResult_ *outResult); + + void DrawLines(int32 startLine, + int32 endLine, + int32 startOffset = -1, + bool erase = false); + void DrawCaret(int32 offset); + void InvertCaret(); + void DragCaret(int32 offset); + + void StopMouseTracking(); + bool PerformMouseUp(BPoint where); + bool PerformMouseMoved(BPoint where, + uint32 code); + + void TrackMouse(BPoint where, const BMessage *message, + bool force = false); + + void TrackDrag(BPoint where); + void InitiateDrag(); + bool MessageDropped(BMessage *inMessage, + BPoint where, + BPoint offset); + + void UpdateScrollbars(); + void AutoResize(bool doredraw=true); + + void NewOffscreen(float padding = 0.0F); + void DeleteOffscreen(); + + void Activate(); + void Deactivate(); + + void NormalizeFont(BFont *font); + + uint32 CharClassification(int32 offset) const; + int32 NextInitialByte(int32 offset) const; + int32 PreviousInitialByte(int32 offset) const; + + bool GetProperty(BMessage *specifier, + int32 form, + const char *property, + BMessage *reply); + bool SetProperty(BMessage *specifier, + int32 form, + const char *property, + BMessage *reply); + bool CountProperties(BMessage *specifier, + int32 form, + const char *property, + BMessage *reply); + + void HandleInputMethodChanged(BMessage *message); + void HandleInputMethodLocationRequest(); + void CancelInputMethod(); + +static void LockWidthBuffer(); +static void UnlockWidthBuffer(); + + _BTextGapBuffer_* fText; + _BLineBuffer_* fLines; + _BStyleBuffer_* fStyles; + BRect fTextRect; + int32 fSelStart; + int32 fSelEnd; + bool fCaretVisible; + bigtime_t fCaretTime; + int32 fClickOffset; + int32 fClickCount; + bigtime_t fClickTime; + int32 fDragOffset; + uint8 fCursor; + bool fActive; + bool fStylable; + float fTabWidth; + bool fSelectable; + bool fEditable; + bool fWrap; + int32 fMaxBytes; + BList* fDisallowedChars; + alignment fAlignment; + bool fAutoindent; + BBitmap* fOffscreen; + color_space fColorSpace; + bool fResizable; + BView* fContainerView; + _BUndoBuffer_* fUndo; /* was _reserved[0] */ + _BInlineInput_* fInline; /* was _reserved[1] */ + BMessageRunner * fDragRunner; /* was _reserved[2] */ + BMessageRunner * fClickRunner; /* was _reserved[3] */ + BPoint fWhere; + _BTextTrackState_* fTrackingMouse; /* was _reserved[6] */ + _BTextChangeResult_* fTextChange; /* was _reserved[7] */ + uint32 _reserved[1]; /* was 8 */ +#if !_PR3_COMPATIBLE_ + uint32 _more_reserved[8]; +#endif + +static _BWidthBuffer_* sWidths; +static sem_id sWidthSem; +static int32 sWidthAtom; +}; +//------------------------------------------------------------------------------ + +#endif // _TEXT_VIEW_H + +/* + * $Log $ + * + * $Id $ + * + */ diff --git a/src/kits/interface/BTextView/TextViewSupportBuffer.h b/src/kits/interface/BTextView/TextViewSupportBuffer.h new file mode 100644 index 0000000000..43b380de43 --- /dev/null +++ b/src/kits/interface/BTextView/TextViewSupportBuffer.h @@ -0,0 +1,104 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2001-2002, OpenBeOS +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// File Name: TextViewSupportBuffer.h +// Author: Marc Flerackers (mflerackers@androme.be) +// Description: Template class used to implement the various BTextView +// buffer classes. +//------------------------------------------------------------------------------ + +// Standard Includes ----------------------------------------------------------- +#include + +// System Includes ------------------------------------------------------------- +#include "SupportDefs.h" + +// Project Includes ------------------------------------------------------------ + +// Local Includes -------------------------------------------------------------- + +// Local Defines --------------------------------------------------------------- + +// Globals --------------------------------------------------------------------- + +// _BTextViewSupportBuffer_ class ---------------------------------------------- +template +class _BTextViewSupportBuffer_ { + +public: + _BTextViewSupportBuffer_(int32 count, int32 blockSize); +virtual ~_BTextViewSupportBuffer_(); + + void InsertItemsAt(int32 offset, int32 count, const T *items); + void RemoveItemsAt(int32 offset, int32 count); + + int32 fBlockSize; + int32 fCount; + int32 fPhysicalSize; + T *fItems; + int32 fReserved; +}; +//------------------------------------------------------------------------------ +template +_BTextViewSupportBuffer_::_BTextViewSupportBuffer_(int32 count, int32 blockSize) + : + fBlockSize(blockSize), + fCount(count), + fPhysicalSize(count + blockSize), + fItems(NULL) +{ + fItems = (T*)malloc(fPhysicalSize * sizeof(T)); +} +//------------------------------------------------------------------------------ +template +_BTextViewSupportBuffer_::~_BTextViewSupportBuffer_() +{ + free(fItems); +} +//------------------------------------------------------------------------------ +template +void _BTextViewSupportBuffer_::InsertItemsAt(int32 offset, int32 count, + const T *items) +{ + if (fPhysicalSize < fCount + count) + { + int32 new_size = (((fCount + count) / fBlockSize) + 1) * fBlockSize; + + fItems = realloc(fItems, new_size); + } + + memcpy(fItems + offset, items, count); + fCount += count; +} +//------------------------------------------------------------------------------ +template +void _BTextViewSupportBuffer_::RemoveItemsAt(int32 offset, int32 count) +{ + +} +//------------------------------------------------------------------------------ + +/* + * $Log $ + * + * $Id $ + * + */